pEp_utility.cpp
author Volker Birk <vb@pep.foundation>
Mon, 22 Oct 2018 10:14:50 +0200
branchsync
changeset 304 00916b0afaac
parent 302 b3444780fa9f
child 326 83b46d64c11d
permissions -rw-r--r--
start COM on sync thread
     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         {
    10             if (!_ident)
    11                 return;
    12 
    13             if (_ident->address)
    14                 address = _ident->address;
    15             if (_ident->fpr)
    16                 fpr = _ident->fpr;
    17             if (_ident->user_id)
    18                 user_id = _ident->user_id;
    19             if (_ident->username)
    20                 username = _ident->username;
    21             comm_type = (pEpComType)_ident->comm_type;
    22             lang = _ident->lang;
    23             flags = (int)_ident->flags;
    24         }
    25 
    26         pEp_identity_cpp::pEp_identity_cpp(const pEpIdentity *_ident)
    27         {
    28             if (!_ident)
    29                 return;
    30 
    31             if (_ident->Address)
    32                 address = utf8_string(_ident->Address);
    33             if (_ident->Fpr)
    34                 fpr = utf8_string(_ident->Fpr);
    35             if (_ident->UserId)
    36                 user_id = utf8_string(_ident->UserId);
    37             if (_ident->UserName)
    38                 username = utf8_string(_ident->UserName);
    39             comm_type = _ident->CommType;
    40             if (_ident->Lang)
    41                 lang = utf8_string(_ident->Lang);
    42             flags = (int)_ident->Flags;
    43         }
    44 
    45         pEp_identity * pEp_identity_cpp::to_pEp_identity()
    46         {
    47             ::pEp_identity *_ident = ::new_identity(this->address.c_str(), this->fpr.c_str(), this->user_id.c_str(), this->username.c_str());
    48             assert(_ident);
    49             if (_ident == NULL)
    50                 throw bad_alloc();
    51 
    52             _ident->comm_type = (::PEP_comm_type) this->comm_type;
    53 
    54             assert(this->lang.size() == 0 || this->lang.size() == 2);
    55 
    56             if (this->lang.size()) {
    57                 _ident->lang[0] = this->lang[0];
    58                 _ident->lang[1] = this->lang[1];
    59             }
    60 
    61             _ident->flags = (identity_flags) this->flags;
    62 
    63             return _ident;
    64         }
    65 
    66         pEpIdentity * pEp_identity_cpp::to_pEp_identity_s()
    67         {
    68             pEpIdentity *_ident = (pEpIdentity *)calloc(1, sizeof(pEpIdentity));
    69             assert(_ident);
    70             if (_ident == NULL)
    71                 throw bad_alloc();
    72 
    73             _ident->Address = utf16_bstr(this->address);
    74             _ident->CommType = this->comm_type;
    75             _ident->Fpr = utf16_bstr(this->fpr);
    76             _ident->Lang = utf16_bstr(this->lang);
    77             _ident->UserName = utf16_bstr(this->username);
    78             _ident->UserId = utf16_bstr(this->user_id);
    79             _ident->Flags = (pEpIdentityFlags) this->flags;
    80 
    81             return _ident;
    82         }
    83 
    84         void copy_identity(pEpIdentity * ident_s, const pEp_identity * ident)
    85         {
    86             assert(ident_s);
    87             if (!ident_s)
    88                 throw invalid_argument("ident_s");
    89 
    90             ::memset(ident_s, 0, sizeof(pEpIdentity));
    91             if (ident) {
    92                 if (ident->address)
    93                     ident_s->Address = utf16_bstr(ident->address);
    94                 if (ident->fpr)
    95                     ident_s->Fpr = utf16_bstr(ident->fpr);
    96                 if (ident->user_id)
    97                     ident_s->UserId = utf16_bstr(ident->user_id);
    98                 if (ident->username)
    99                     ident_s->UserName = utf16_bstr(ident->username);
   100                 ident_s->CommType = (pEpComType)ident->comm_type;
   101                 if (ident->lang)
   102                     ident_s->Lang = utf16_bstr(ident->lang);
   103                 ident_s->Flags = (pEpIdentityFlags)ident->flags;
   104             }
   105         }
   106 
   107         ::pEp_identity *new_identity(const pEpIdentity * ident)
   108         {
   109             if (ident == NULL)
   110                 return NULL;
   111 
   112             ::pEp_identity *_ident;
   113 
   114             string _address;
   115             string _fpr;
   116             string _user_id;
   117             string _username;
   118 
   119             if (ident->Address)
   120                 _address = utf8_string(ident->Address);
   121             if (ident->Fpr) {
   122                 _fpr = utf8_string(ident->Fpr);
   123                 for (auto p = _fpr.begin(); p != _fpr.end(); ++p) {
   124                     if (*p >= 'A' && *p <= 'Z')
   125                         continue;
   126                     if (*p >= '0' && *p <= '9')
   127                         continue;
   128                     throw invalid_argument("invalid hex digits in fingerprint");
   129                 }
   130             }
   131             if (ident->UserId)
   132                 _user_id = utf8_string(ident->UserId);
   133             if (ident->UserName)
   134                 _username = utf8_string(ident->UserName);
   135 
   136             _ident = ::new_identity(_address.c_str(), _fpr.c_str(), _user_id.c_str(), _username.c_str());
   137             assert(_ident);
   138             if (_ident == NULL)
   139                 throw bad_alloc();
   140 
   141             _ident->comm_type = (PEP_comm_type)ident->CommType;
   142 
   143             if (ident->Lang) {
   144                 string _lang = utf8_string(ident->Lang);
   145                 if (_lang.length() != 0) {
   146                     if (_lang.length() != 2) {
   147                         ::free_identity(_ident);
   148                         throw invalid_argument("invalid language code");
   149                     }
   150                     if (_lang[0] < 'a' || _lang[0] > 'z') {
   151                         ::free_identity(_ident);
   152                         throw invalid_argument("invalid language code");
   153                     }
   154                     if (_lang[1] < 'a' || _lang[1] > 'z') {
   155                         ::free_identity(_ident);
   156                         throw invalid_argument("invalid language code");
   157                     }
   158                     _ident->lang[0] = _lang[0];
   159                     _ident->lang[1] = _lang[1];
   160                 }
   161             }
   162 
   163             _ident->flags = (identity_flags_t)ident->Flags;
   164 
   165             return _ident;
   166         }
   167 
   168         template< class T2, class T > T2 from_C(T *tl);
   169 
   170         BSTR bstr(char *s)
   171         {
   172             if (s == NULL)
   173                 return _bstr_t(L"").Detach();
   174 
   175             return utf16_bstr(s);
   176         }
   177 
   178         template<> Blob *from_C< Blob *, bloblist_t >(bloblist_t *tl)
   179         {
   180             assert(tl);
   181 
   182             CComSafeArray<BYTE> sa;
   183             if (tl) {
   184                 sa.Create(tl->size);
   185                 if (tl->size) {
   186                     char *data;
   187                     SafeArrayAccessData(sa, (void **)&data);
   188                     memcpy(data, tl->value, tl->size);
   189                     SafeArrayUnaccessData(sa);
   190                 }
   191             }
   192             else {
   193                 sa.Create((ULONG)0);
   194             }
   195 
   196             Blob *_blob = new Blob();
   197 
   198             _blob->value = sa.Detach();
   199             _blob->MimeType = bstr(tl->mime_type);
   200             _blob->Filename = bstr(tl->filename);
   201 
   202             return _blob;
   203         }
   204 
   205         template< class T > int length(T *);
   206 
   207         template< class T2, class T > SAFEARRAY * array_from_C(T *tl)
   208         {
   209             if (tl == NULL)
   210                 return newSafeArray<T2>(0);
   211 
   212             int len = length<T>(tl);
   213 
   214             LPSAFEARRAY sa = newSafeArray<T2>(len);
   215             LONG lbound, ubound;
   216             SafeArrayGetLBound(sa, 1, &lbound);
   217             SafeArrayGetUBound(sa, 1, &ubound);
   218 
   219             T *_tl = tl;
   220             for (LONG i = lbound; i <= ubound; _tl = _tl->next, i++) {
   221                 HRESULT result = SafeArrayPutElement(sa, &i, from_C<T2 *, T>(_tl));
   222                 if (!SUCCEEDED(result))
   223                     throw bad_alloc();
   224             }
   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 }