pEp_utility.cpp
author Volker Birk <vb@pep-project.org>
Thu, 01 Dec 2016 16:44:03 +0100
changeset 223 490e6399476b
parent 219 03531c4d3fda
child 224 b0290a75f7a5
permissions -rw-r--r--
FIX: 0 termination missing
     1 #include "stdafx.h"
     2 #include "pEp_utility.h"
     3 
     4 using namespace ATL;
     5 
     6 namespace pEp {
     7     namespace utility {
     8         pEp_identity_cpp::pEp_identity_cpp(const ::pEp_identity *_ident)
     9             : me(false)
    10         {
    11 			if (!_ident)
    12 				return;
    13 
    14             if (_ident->address)
    15                 address = _ident->address;
    16             if (_ident->fpr)
    17                 fpr = _ident->fpr;
    18             if (_ident->user_id)
    19                 user_id = _ident->user_id;
    20             if (_ident->username)
    21                 username = _ident->username;
    22             comm_type = (pEpComType) _ident->comm_type;
    23             lang = _ident->lang;
    24 			flags = (int) _ident->flags;
    25         }
    26 
    27         pEp_identity_cpp::pEp_identity_cpp(const pEpIdentity *_ident)
    28             : me(false)
    29         {
    30 			if (!_ident)
    31 				return;
    32 
    33 			if (_ident->Address)
    34                 address = utf8_string(_ident->Address);
    35             if (_ident->Fpr)
    36                 fpr = utf8_string(_ident->Fpr);
    37             if (_ident->UserId)
    38                 user_id = utf8_string(_ident->UserId);
    39             if (_ident->UserName)
    40                 username = utf8_string(_ident->UserName);
    41             comm_type = _ident->CommType;
    42             if (_ident->Lang)
    43                 lang = utf8_string(_ident->Lang);
    44 			flags = (int)_ident->Flags;
    45         }
    46 
    47         pEp_identity * pEp_identity_cpp::to_pEp_identity()
    48         {
    49             ::pEp_identity *_ident = ::new_identity(this->address.c_str(), this->fpr.c_str(), this->user_id.c_str(), this->username.c_str());
    50             assert(_ident);
    51             if (_ident == NULL)
    52                 throw bad_alloc();
    53 
    54             _ident->comm_type = (::PEP_comm_type) this->comm_type;
    55             _ident->me = this->me;
    56 
    57             assert(this->lang.size() == 0 || this->lang.size() == 2);
    58 
    59             if (this->lang.size()) {
    60                 _ident->lang[0] = this->lang[0];
    61                 _ident->lang[1] = this->lang[1];
    62             }
    63 
    64 			_ident->flags = (identity_flags) this->flags;
    65 
    66             return _ident;
    67         }
    68 
    69         pEpIdentity * pEp_identity_cpp::to_pEp_identity_s()
    70         {
    71             pEpIdentity *_ident = (pEpIdentity *) calloc(1, sizeof(pEpIdentity));
    72             assert(_ident);
    73             if (_ident == NULL)
    74                 throw bad_alloc();
    75 
    76             _ident->Address = utf16_bstr(this->address);
    77             _ident->CommType = this->comm_type;
    78             _ident->Fpr = utf16_bstr(this->fpr);
    79             _ident->Lang = utf16_bstr(this->lang);
    80             _ident->UserName = utf16_bstr(this->username);
    81             _ident->UserId = utf16_bstr(this->user_id);
    82 			_ident->Flags = (pEpIdentityFlags) this->flags;
    83 
    84             return _ident;
    85         }
    86 
    87         void copy_identity(pEpIdentity * ident_s, const pEp_identity * ident)
    88         {
    89             assert(ident_s);
    90 			if (!ident_s)
    91 				throw invalid_argument("ident_s");
    92 
    93             ::memset(ident_s, 0, sizeof(pEpIdentity));
    94             if (ident) {
    95                 if (ident->address)
    96                     ident_s->Address = utf16_bstr(ident->address);
    97                 if (ident->fpr)
    98                     ident_s->Fpr = utf16_bstr(ident->fpr);
    99                 if (ident->user_id)
   100                     ident_s->UserId = utf16_bstr(ident->user_id);
   101                 if (ident->username)
   102                     ident_s->UserName = utf16_bstr(ident->username);
   103                 ident_s->CommType = (pEpComType) ident->comm_type;
   104                 if (ident->lang)
   105                     ident_s->Lang = utf16_bstr(ident->lang);
   106 				ident_s->Flags = (pEpIdentityFlags) ident->flags;
   107             }
   108         }
   109 
   110         ::pEp_identity *new_identity(const pEpIdentity * ident)
   111         {
   112             if (ident == NULL)
   113                 return NULL;
   114 
   115             ::pEp_identity *_ident;
   116 
   117             string _address;
   118             string _fpr;
   119             string _user_id;
   120             string _username;
   121 
   122             if (ident->Address)
   123                 _address = utf8_string(ident->Address);
   124             if (ident->Fpr) {
   125                 _fpr = utf8_string(ident->Fpr);
   126                 for (auto p = _fpr.begin(); p != _fpr.end(); ++p) {
   127                     if (*p >= 'A' && *p <= 'Z')
   128                         continue;
   129                     if (*p >= '0' && *p <= '9')
   130                         continue;
   131                     throw invalid_argument("invalid hex digits in fingerprint");
   132                 }
   133             }
   134             if (ident->UserId)
   135                 _user_id = utf8_string(ident->UserId);
   136             if (ident->UserName)
   137                 _username = utf8_string(ident->UserName);
   138 
   139             _ident = ::new_identity(_address.c_str(), _fpr.c_str(), _user_id.c_str(), _username.c_str());
   140             assert(_ident);
   141             if (_ident == NULL)
   142                 throw bad_alloc();
   143 
   144             _ident->comm_type = (PEP_comm_type) ident->CommType;
   145 
   146             if (ident->Lang) {
   147                 string _lang = utf8_string(ident->Lang);
   148                 if (_lang.length() != 0) {
   149                     if (_lang.length() != 2) {
   150                         ::free_identity(_ident);
   151                         throw invalid_argument("invalid language code");
   152                     }
   153                     if (_lang[0] < 'a' || _lang[0] > 'z') {
   154                         ::free_identity(_ident);
   155                         throw invalid_argument("invalid language code");
   156                     }
   157                     if (_lang[1] < 'a' || _lang[1] > 'z') {
   158                         ::free_identity(_ident);
   159                         throw invalid_argument("invalid language code");
   160                     }
   161                     _ident->lang[0] = _lang[0];
   162                     _ident->lang[1] = _lang[1];
   163                 }
   164             }
   165 
   166 			_ident->flags = (identity_flags_t)ident->Flags;
   167 
   168             return _ident;
   169         }
   170 
   171         template< class T2, class T > T2 from_C(T *tl);
   172 
   173         BSTR bstr(char *s)
   174         {
   175             if (s == NULL)
   176                 return _bstr_t(L"").Detach();
   177 
   178             return utf16_bstr(s);
   179         }
   180 
   181         template<> Blob *from_C< Blob *, bloblist_t >(bloblist_t *tl)
   182         {
   183 			assert(tl);
   184 
   185             CComSafeArray<BYTE> sa;
   186 			if (tl) {
   187 				sa.Create(tl->size);
   188 				if (tl->size) {
   189 					char *data;
   190 					SafeArrayAccessData(sa, (void **)&data);
   191 					memcpy(data, tl->value, tl->size);
   192 					SafeArrayUnaccessData(sa);
   193 				}
   194 			}
   195 			else {
   196 				sa.Create((ULONG)0);
   197 			}
   198 
   199             Blob *_blob = new Blob();
   200 
   201             _blob->value = sa.Detach();
   202             _blob->MimeType = bstr(tl->mime_type);
   203             _blob->Filename = bstr(tl->filename);
   204 
   205             return _blob;
   206         }
   207 
   208         template< class T > int length(T *);
   209 
   210         template< class T2, class T > SAFEARRAY * array_from_C(T *tl)
   211         {
   212             if (tl == NULL)
   213                 return newSafeArray<T2>(0);
   214 
   215             int len = length<T>(tl);
   216 
   217             LPSAFEARRAY sa = newSafeArray<T2>(len);
   218             LONG lbound, ubound;
   219             SafeArrayGetLBound(sa, 1, &lbound);
   220             SafeArrayGetUBound(sa, 1, &ubound);
   221 
   222             T *_tl = tl;
   223             for (LONG i = lbound; i <= ubound; _tl = _tl->next, i++)
   224                 SafeArrayPutElement(sa, &i, from_C<T2 *, T>(_tl));
   225 
   226             return sa;
   227         }
   228 
   229         void clear_identity_s(pEpIdentity& ident)
   230         {
   231             SysFreeString(ident.Address);
   232             SysFreeString(ident.Fpr);
   233             SysFreeString(ident.Lang);
   234             SysFreeString(ident.UserName);
   235             SysFreeString(ident.UserId);
   236 
   237             memset(&ident, 0, sizeof(pEpIdentity));
   238         }
   239 
   240         template<> pEpIdentity from_C< pEpIdentity, pEp_identity >(pEp_identity *tl)
   241         {
   242             pEpIdentity _ident;
   243             memset(&_ident, 0, sizeof(_ident));
   244 
   245             if (tl)
   246                 copy_identity(&_ident, tl);
   247             return _ident;
   248         }
   249 
   250         pEpIdentity identity_s(pEp_identity *ident)
   251         {
   252             return from_C< pEpIdentity, pEp_identity >(ident);
   253         }
   254 
   255         template<> pEpIdentity *from_C< pEpIdentity *, identity_list >(identity_list *il)
   256         {
   257             pEpIdentity *ident = new pEpIdentity();
   258             memset(ident, 0, sizeof(pEpIdentity));
   259 
   260             if (il)
   261                 copy_identity(ident, il->ident);
   262             return ident;
   263         }
   264 
   265         template<> StringPair *from_C< StringPair *, stringpair_list_t >(stringpair_list_t * sp)
   266         {
   267             StringPair *fld = new StringPair();
   268             if (sp) {
   269                 fld->Name = bstr(sp->value->key);
   270                 fld->Value = bstr(sp->value->value);
   271             }
   272             return fld;
   273         }
   274 
   275         template<> int length<identity_list>(identity_list *tl)
   276         {
   277             return identity_list_length(tl);
   278         }
   279 
   280         template<> int length<bloblist_t>(bloblist_t *tl)
   281         {
   282             return bloblist_length(tl);
   283         }
   284 
   285         template<> int length<stringpair_list_t>(stringpair_list_t *tl)
   286         {
   287             return stringpair_list_length(tl);
   288         }
   289 
   290         void clear_text_message(TextMessage *msg)
   291         {
   292 			assert(msg);
   293 			if (!msg)
   294 				return;
   295 
   296             SysFreeString(msg->Id);
   297             SysFreeString(msg->ShortMsg);
   298             SysFreeString(msg->LongMsg);
   299             SysFreeString(msg->LongMsgFormatted);
   300             SafeArrayDestroy(msg->Attachments);
   301             clear_identity_s(msg->From);
   302             SafeArrayDestroy(msg->To);
   303             clear_identity_s(msg->RecvBy);
   304             SafeArrayDestroy(msg->Cc);
   305             SafeArrayDestroy(msg->Bcc);
   306             SafeArrayDestroy(msg->ReplyTo);
   307             SafeArrayDestroy(msg->References);
   308             SafeArrayDestroy(msg->Keywords);
   309             SysFreeString(msg->Comments);
   310             SafeArrayDestroy(msg->OptFields);
   311 
   312             memset(msg, 0, sizeof(TextMessage));
   313         }
   314 
   315         void text_message_from_C(TextMessage *msg2, const ::message *msg)
   316         {
   317             assert(msg2);
   318             assert(msg);
   319 
   320 			if (!msg2) {
   321 				msg2 = (TextMessage *)calloc(1, sizeof(TextMessage));
   322 				assert(msg2);
   323 				if (!msg2)
   324 					throw bad_alloc();
   325 			}
   326 			else {
   327 				clear_text_message(msg2);
   328 			}
   329 
   330 			if (!msg)
   331 				return;
   332 
   333             msg2->Dir = (pEpMsgDirection) msg->dir;
   334             msg2->Id = bstr(msg->id);
   335             msg2->ShortMsg = bstr(msg->shortmsg);
   336             msg2->LongMsg = bstr(msg->longmsg);
   337             msg2->LongMsgFormatted = bstr(msg->longmsg_formatted);
   338             msg2->Attachments = array_from_C<Blob, bloblist_t>(msg->attachments);
   339             if (msg->sent)
   340                 msg2->Sent = mktime(msg->sent);
   341             if (msg->recv)
   342                 msg2->Recv = mktime(msg->recv);
   343             msg2->From = identity_s(msg->from);
   344             msg2->To = array_from_C<pEpIdentity, identity_list>(msg->to);
   345             msg2->RecvBy = identity_s(msg->recv_by);
   346             msg2->Cc = array_from_C<pEpIdentity, identity_list>(msg->cc);
   347             msg2->Bcc = array_from_C<pEpIdentity, identity_list>(msg->bcc);
   348             msg2->ReplyTo = array_from_C<pEpIdentity, identity_list>(msg->reply_to);
   349             msg2->References = string_array(msg->references);
   350             msg2->Keywords = string_array(msg->keywords);
   351             msg2->Comments = bstr(msg->comments);
   352             msg2->OptFields = array_from_C<StringPair, stringpair_list_t>(msg->opt_fields);
   353         }
   354 
   355         char * str(BSTR s)
   356         {
   357             string str = utf8_string(s);
   358             char *_s = _strdup(str.c_str());
   359             if (_s == NULL)
   360                 throw bad_alloc();
   361 
   362             return _s;
   363         }
   364 
   365         void clear_blob(Blob& b)
   366         {
   367             SysFreeString(b.Filename);
   368             SysFreeString(b.MimeType);
   369             SafeArrayDestroy(b.value);
   370             memset(&b, 0, sizeof(Blob));
   371         }
   372 
   373         bloblist_t *bloblist(SAFEARRAY *sa)
   374         {
   375             if (sa == NULL)
   376                 return NULL;
   377 
   378             LONG lbound, ubound;
   379             SafeArrayGetLBound(sa, 1, &lbound);
   380             SafeArrayGetUBound(sa, 1, &ubound);
   381 
   382             size_t size = ubound - lbound + 1;
   383             if (size <= 0)
   384                 return NULL;
   385 
   386             bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL);
   387             if (bl == NULL)
   388                 throw bad_alloc();
   389 
   390             bloblist_t *_bl = bl;
   391             for (LONG i = lbound; i <= ubound; i++) {
   392                 Blob b;
   393                 memset(&b, 0, sizeof(Blob));
   394                 SafeArrayGetElement(sa, &i, &b);
   395 
   396                 LONG _lbound, _ubound;
   397                 SafeArrayGetLBound(b.value, 1, &_lbound);
   398                 SafeArrayGetUBound(b.value, 1, &_ubound);
   399                 size_t size = _ubound - _lbound + 1;
   400 
   401                 char *buffer;
   402                 if (size) {
   403                     buffer = (char *) calloc(1, size);
   404                     if (buffer == NULL)
   405                         throw bad_alloc();
   406 
   407                     char *data;
   408 
   409                     SafeArrayAccessData(b.value, (void **) &data);
   410                     memcpy(buffer, data, size);
   411                     SafeArrayUnaccessData(sa);
   412                 }
   413                 else {
   414                     buffer = _strdup("");
   415                     if (buffer == NULL)
   416                         throw bad_alloc();
   417 
   418                 }
   419                 _bl = bloblist_add(_bl, buffer, size, str(b.MimeType), str(b.Filename));
   420                 if (_bl == NULL) {
   421                     free(buffer);
   422                     clear_blob(b);
   423                     free_bloblist(bl);
   424                     throw bad_alloc();
   425                 }
   426 
   427                 clear_blob(b);
   428             }
   429 
   430             return bl;
   431         }
   432 
   433         identity_list *identities(SAFEARRAY * sa)
   434         {
   435             if (sa == NULL)
   436                 return NULL;
   437 
   438             LONG lbound, ubound;
   439             SafeArrayGetLBound(sa, 1, &lbound);
   440             SafeArrayGetUBound(sa, 1, &ubound);
   441 
   442             size_t size = ubound - lbound + 1;
   443             if (size <= 0)
   444                 return NULL;
   445 
   446             identity_list *il = new_identity_list(NULL);
   447 
   448             identity_list *_il = il;
   449             for (LONG i = lbound; i <= ubound; i++) {
   450                 pEpIdentity s;
   451                 memset(&s, 0, sizeof(pEpIdentity));
   452                 SafeArrayGetElement(sa, &i, &s);
   453 
   454                 pEp_identity *ident;
   455                 try {
   456                     ident = new_identity(&s);
   457                 }
   458                 catch (bad_alloc&) {
   459                     clear_identity_s(s);
   460                     throw bad_alloc();
   461                 }
   462 
   463                 clear_identity_s(s);
   464 
   465                 _il = identity_list_add(_il, ident);
   466                 if (_il == NULL) {
   467                     free_identity_list(il);
   468                     throw bad_alloc();
   469                 }
   470             }
   471 
   472             return il;
   473         }
   474 
   475         stringpair_t *new_stringpair(StringPair *fld)
   476         {
   477 			stringpair_t *pair;
   478 
   479 			if (!fld) {
   480 				pair = ::new_stringpair(NULL, NULL);
   481 			}
   482 			else {
   483 				pair = ::new_stringpair(str(fld->Name), str(fld->Value));
   484 			}
   485             if (pair == NULL)
   486                 throw bad_alloc();
   487 
   488             return pair;
   489         }
   490 
   491         void clear_opt_field(StringPair& f)
   492         {
   493             SysFreeString(f.Name);
   494             SysFreeString(f.Value);
   495             memset(&f, 0, sizeof(StringPair));
   496         }
   497 
   498         stringpair_list_t *stringpair_list(SAFEARRAY * sa)
   499         {
   500             if (sa == NULL)
   501                 return NULL;
   502 
   503             LONG lbound, ubound;
   504             SafeArrayGetLBound(sa, 1, &lbound);
   505             SafeArrayGetUBound(sa, 1, &ubound);
   506 
   507             size_t size = ubound - lbound + 1;
   508             if (size <= 0)
   509                 return NULL;
   510 
   511             stringpair_list_t *il = new_stringpair_list(NULL);
   512 
   513             stringpair_list_t *_il = il;
   514             for (LONG i = lbound; i <= ubound; i++) {
   515                 StringPair s;
   516                 memset(&s, 0, sizeof(StringPair));
   517                 SafeArrayGetElement(sa, &i, &s);
   518 
   519                 stringpair_t *pair;
   520                 try {
   521                     pair = new_stringpair(&s);
   522                 }
   523                 catch (bad_alloc&) {
   524                     clear_opt_field(s);
   525                     throw bad_alloc();
   526                 }
   527 
   528                 clear_opt_field(s);
   529 
   530                 _il = stringpair_list_add(_il, pair);
   531                 if (_il == NULL) {
   532                     free_stringpair_list(il);
   533                     throw bad_alloc();
   534                 }
   535             }
   536 
   537             return il;
   538         }
   539         
   540         ::message * text_message_to_C(TextMessage *msg)
   541         {
   542             assert(msg);
   543 			if (!msg)
   544 				throw invalid_argument("msg");
   545 
   546             ::message * msg2 = new_message((PEP_msg_direction) msg->Dir);
   547             if (msg2 == NULL)
   548                 throw bad_alloc();
   549 
   550             msg2->id = str(msg->Id);
   551             msg2->shortmsg = str(msg->ShortMsg);
   552             msg2->longmsg = str(msg->LongMsg);
   553             msg2->longmsg_formatted = str(msg->LongMsgFormatted);
   554             msg2->attachments = bloblist(msg->Attachments);
   555             msg2->sent = new_timestamp(msg->Sent);
   556             msg2->recv = new_timestamp(msg->Recv);
   557             msg2->from = new_identity(&msg->From);
   558             msg2->to = identities(msg->To);
   559             msg2->recv_by = new_identity(&msg->RecvBy);
   560             msg2->cc = identities(msg->Cc);
   561             msg2->bcc = identities(msg->Bcc);
   562             msg2->reply_to = identities(msg->ReplyTo);
   563             msg2->references = new_stringlist(msg->References);
   564             msg2->keywords = new_stringlist(msg->Keywords);
   565             msg2->comments = str(msg->Comments);
   566             msg2->opt_fields = stringpair_list(msg->OptFields);
   567 
   568             return msg2;
   569         }
   570 
   571 		void opt_field_array_from_C(stringpair_list_t* spair_list, LPSAFEARRAY* pair_list_out) {
   572 			assert(spair_list);
   573 			assert(pair_list_out);
   574 			
   575 			if (!spair_list)
   576 				return;
   577 
   578 			*pair_list_out = array_from_C<StringPair, stringpair_list_t>(spair_list);
   579 		}
   580 
   581 		void clear_opt_field_array(LPSAFEARRAY* opt_field_array) {
   582 			if (opt_field_array){
   583 				SafeArrayDestroy(*opt_field_array);
   584 				*opt_field_array = NULL;
   585 			}
   586 		}
   587     }
   588 }