pEp_utility.cpp
author Edouard Tisserant <edouard@pep-project.org>
Tue, 21 Feb 2017 12:43:43 +0100
changeset 237 589b9cb32b07
parent 224 b0290a75f7a5
child 251 ded328cde93f
child 258 794f2468ccec
permissions -rw-r--r--
Updated SyncHandshakeSignal enum
     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 *) malloc(size + 1);
   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 					buffer[size] = 0; // safeguard
   412                     SafeArrayUnaccessData(sa);
   413                 }
   414                 else {
   415                     buffer = _strdup("");
   416                     if (buffer == NULL)
   417                         throw bad_alloc();
   418 
   419                 }
   420                 _bl = bloblist_add(_bl, buffer, size, str(b.MimeType), str(b.Filename));
   421                 if (_bl == NULL) {
   422                     free(buffer);
   423                     clear_blob(b);
   424                     free_bloblist(bl);
   425                     throw bad_alloc();
   426                 }
   427 
   428                 clear_blob(b);
   429             }
   430 
   431             return bl;
   432         }
   433 
   434         identity_list *identities(SAFEARRAY * sa)
   435         {
   436             if (sa == NULL)
   437                 return NULL;
   438 
   439             LONG lbound, ubound;
   440             SafeArrayGetLBound(sa, 1, &lbound);
   441             SafeArrayGetUBound(sa, 1, &ubound);
   442 
   443             size_t size = ubound - lbound + 1;
   444             if (size <= 0)
   445                 return NULL;
   446 
   447             identity_list *il = new_identity_list(NULL);
   448 
   449             identity_list *_il = il;
   450             for (LONG i = lbound; i <= ubound; i++) {
   451                 pEpIdentity s;
   452                 memset(&s, 0, sizeof(pEpIdentity));
   453                 SafeArrayGetElement(sa, &i, &s);
   454 
   455                 pEp_identity *ident;
   456                 try {
   457                     ident = new_identity(&s);
   458                 }
   459                 catch (bad_alloc&) {
   460                     clear_identity_s(s);
   461                     throw bad_alloc();
   462                 }
   463 
   464                 clear_identity_s(s);
   465 
   466                 _il = identity_list_add(_il, ident);
   467                 if (_il == NULL) {
   468                     free_identity_list(il);
   469                     throw bad_alloc();
   470                 }
   471             }
   472 
   473             return il;
   474         }
   475 
   476         stringpair_t *new_stringpair(StringPair *fld)
   477         {
   478 			stringpair_t *pair;
   479 
   480 			if (!fld) {
   481 				pair = ::new_stringpair(NULL, NULL);
   482 			}
   483 			else {
   484 				pair = ::new_stringpair(str(fld->Name), str(fld->Value));
   485 			}
   486             if (pair == NULL)
   487                 throw bad_alloc();
   488 
   489             return pair;
   490         }
   491 
   492         void clear_opt_field(StringPair& f)
   493         {
   494             SysFreeString(f.Name);
   495             SysFreeString(f.Value);
   496             memset(&f, 0, sizeof(StringPair));
   497         }
   498 
   499         stringpair_list_t *stringpair_list(SAFEARRAY * sa)
   500         {
   501             if (sa == NULL)
   502                 return NULL;
   503 
   504             LONG lbound, ubound;
   505             SafeArrayGetLBound(sa, 1, &lbound);
   506             SafeArrayGetUBound(sa, 1, &ubound);
   507 
   508             size_t size = ubound - lbound + 1;
   509             if (size <= 0)
   510                 return NULL;
   511 
   512             stringpair_list_t *il = new_stringpair_list(NULL);
   513 
   514             stringpair_list_t *_il = il;
   515             for (LONG i = lbound; i <= ubound; i++) {
   516                 StringPair s;
   517                 memset(&s, 0, sizeof(StringPair));
   518                 SafeArrayGetElement(sa, &i, &s);
   519 
   520                 stringpair_t *pair;
   521                 try {
   522                     pair = new_stringpair(&s);
   523                 }
   524                 catch (bad_alloc&) {
   525                     clear_opt_field(s);
   526                     throw bad_alloc();
   527                 }
   528 
   529                 clear_opt_field(s);
   530 
   531                 _il = stringpair_list_add(_il, pair);
   532                 if (_il == NULL) {
   533                     free_stringpair_list(il);
   534                     throw bad_alloc();
   535                 }
   536             }
   537 
   538             return il;
   539         }
   540         
   541         ::message * text_message_to_C(TextMessage *msg)
   542         {
   543             assert(msg);
   544 			if (!msg)
   545 				throw invalid_argument("msg");
   546 
   547             ::message * msg2 = new_message((PEP_msg_direction) msg->Dir);
   548             if (msg2 == NULL)
   549                 throw bad_alloc();
   550 
   551             msg2->id = str(msg->Id);
   552             msg2->shortmsg = str(msg->ShortMsg);
   553             msg2->longmsg = str(msg->LongMsg);
   554             msg2->longmsg_formatted = str(msg->LongMsgFormatted);
   555             msg2->attachments = bloblist(msg->Attachments);
   556             msg2->sent = new_timestamp(msg->Sent);
   557             msg2->recv = new_timestamp(msg->Recv);
   558             msg2->from = new_identity(&msg->From);
   559             msg2->to = identities(msg->To);
   560             msg2->recv_by = new_identity(&msg->RecvBy);
   561             msg2->cc = identities(msg->Cc);
   562             msg2->bcc = identities(msg->Bcc);
   563             msg2->reply_to = identities(msg->ReplyTo);
   564             msg2->references = new_stringlist(msg->References);
   565             msg2->keywords = new_stringlist(msg->Keywords);
   566             msg2->comments = str(msg->Comments);
   567             msg2->opt_fields = stringpair_list(msg->OptFields);
   568 
   569             return msg2;
   570         }
   571 
   572 		void opt_field_array_from_C(stringpair_list_t* spair_list, LPSAFEARRAY* pair_list_out) {
   573 			assert(spair_list);
   574 			assert(pair_list_out);
   575 			
   576 			if (!spair_list)
   577 				return;
   578 
   579 			*pair_list_out = array_from_C<StringPair, stringpair_list_t>(spair_list);
   580 		}
   581 
   582 		void clear_opt_field_array(LPSAFEARRAY* opt_field_array) {
   583 			if (opt_field_array){
   584 				SafeArrayDestroy(*opt_field_array);
   585 				*opt_field_array = NULL;
   586 			}
   587 		}
   588     }
   589 }