pEp_utility.cpp
author Thomas
Wed, 02 May 2018 09:46:48 +0200
branchCOM-87
changeset 287 99abd7d70c1e
parent 269 26c8597fe860
child 302 b3444780fa9f
child 324 ef317c83c07a
permissions -rw-r--r--
Rename flags
     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                 SafeArrayPutElement(sa, &i, from_C<T2 *, T>(_tl));
   222 
   223             return sa;
   224         }
   225 
   226         void clear_identity_s(pEpIdentity& ident)
   227         {
   228             SysFreeString(ident.Address);
   229             SysFreeString(ident.Fpr);
   230             SysFreeString(ident.Lang);
   231             SysFreeString(ident.UserName);
   232             SysFreeString(ident.UserId);
   233 
   234             memset(&ident, 0, sizeof(pEpIdentity));
   235         }
   236 
   237         template<> pEpIdentity from_C< pEpIdentity, pEp_identity >(pEp_identity *tl)
   238         {
   239             pEpIdentity _ident;
   240             memset(&_ident, 0, sizeof(_ident));
   241 
   242             if (tl)
   243                 copy_identity(&_ident, tl);
   244             return _ident;
   245         }
   246 
   247         pEpIdentity identity_s(pEp_identity *ident)
   248         {
   249             return from_C< pEpIdentity, pEp_identity >(ident);
   250         }
   251 
   252         template<> pEpIdentity *from_C< pEpIdentity *, identity_list >(identity_list *il)
   253         {
   254             pEpIdentity *ident = new pEpIdentity();
   255             memset(ident, 0, sizeof(pEpIdentity));
   256 
   257             if (il)
   258                 copy_identity(ident, il->ident);
   259             return ident;
   260         }
   261 
   262         template<> StringPair *from_C< StringPair *, stringpair_list_t >(stringpair_list_t * sp)
   263         {
   264             StringPair *fld = new StringPair();
   265             if (sp) {
   266                 fld->Name = bstr(sp->value->key);
   267                 fld->Value = bstr(sp->value->value);
   268             }
   269             return fld;
   270         }
   271 
   272         template<> int length<identity_list>(identity_list *tl)
   273         {
   274             return identity_list_length(tl);
   275         }
   276 
   277         template<> int length<bloblist_t>(bloblist_t *tl)
   278         {
   279             return bloblist_length(tl);
   280         }
   281 
   282         template<> int length<stringpair_list_t>(stringpair_list_t *tl)
   283         {
   284             return stringpair_list_length(tl);
   285         }
   286 
   287         void clear_text_message(TextMessage *msg)
   288         {
   289             assert(msg);
   290             if (!msg)
   291                 return;
   292 
   293             SysFreeString(msg->Id);
   294             SysFreeString(msg->ShortMsg);
   295             SysFreeString(msg->LongMsg);
   296             SysFreeString(msg->LongMsgFormatted);
   297             SafeArrayDestroy(msg->Attachments);
   298             clear_identity_s(msg->From);
   299             SafeArrayDestroy(msg->To);
   300             clear_identity_s(msg->RecvBy);
   301             SafeArrayDestroy(msg->Cc);
   302             SafeArrayDestroy(msg->Bcc);
   303             SafeArrayDestroy(msg->ReplyTo);
   304             SafeArrayDestroy(msg->References);
   305             SafeArrayDestroy(msg->Keywords);
   306             SysFreeString(msg->Comments);
   307             SafeArrayDestroy(msg->OptFields);
   308 
   309             memset(msg, 0, sizeof(TextMessage));
   310         }
   311 
   312         void text_message_from_C(TextMessage *msg2, const ::message *msg)
   313         {
   314             assert(msg2);
   315             assert(msg);
   316 
   317             if (!msg2) {
   318                 msg2 = (TextMessage *)calloc(1, sizeof(TextMessage));
   319                 assert(msg2);
   320                 if (!msg2)
   321                     throw bad_alloc();
   322             }
   323             else {
   324                 clear_text_message(msg2);
   325             }
   326 
   327             if (!msg)
   328                 return;
   329 
   330             msg2->Dir = (pEpMsgDirection)msg->dir;
   331             msg2->Id = bstr(msg->id);
   332             msg2->ShortMsg = bstr(msg->shortmsg);
   333             msg2->LongMsg = bstr(msg->longmsg);
   334             msg2->LongMsgFormatted = bstr(msg->longmsg_formatted);
   335             msg2->Attachments = array_from_C<Blob, bloblist_t>(msg->attachments);
   336             if (msg->sent)
   337                 msg2->Sent = mktime(msg->sent);
   338             if (msg->recv)
   339                 msg2->Recv = mktime(msg->recv);
   340             msg2->From = identity_s(msg->from);
   341             msg2->To = array_from_C<pEpIdentity, identity_list>(msg->to);
   342             msg2->RecvBy = identity_s(msg->recv_by);
   343             msg2->Cc = array_from_C<pEpIdentity, identity_list>(msg->cc);
   344             msg2->Bcc = array_from_C<pEpIdentity, identity_list>(msg->bcc);
   345             msg2->ReplyTo = array_from_C<pEpIdentity, identity_list>(msg->reply_to);
   346             msg2->References = string_array(msg->references);
   347             msg2->Keywords = string_array(msg->keywords);
   348             msg2->Comments = bstr(msg->comments);
   349             msg2->OptFields = array_from_C<StringPair, stringpair_list_t>(msg->opt_fields);
   350         }
   351 
   352         char * str(BSTR s)
   353         {
   354             string str = utf8_string(s);
   355             char *_s = _strdup(str.c_str());
   356             if (_s == NULL)
   357                 throw bad_alloc();
   358 
   359             return _s;
   360         }
   361 
   362         void clear_blob(Blob& b)
   363         {
   364             SysFreeString(b.Filename);
   365             SysFreeString(b.MimeType);
   366             SafeArrayDestroy(b.value);
   367             memset(&b, 0, sizeof(Blob));
   368         }
   369 
   370         bloblist_t *bloblist(SAFEARRAY *sa)
   371         {
   372             if (sa == NULL)
   373                 return NULL;
   374 
   375             LONG lbound, ubound;
   376             SafeArrayGetLBound(sa, 1, &lbound);
   377             SafeArrayGetUBound(sa, 1, &ubound);
   378 
   379             size_t size = ubound - lbound + 1;
   380             if (size <= 0)
   381                 return NULL;
   382 
   383             bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL);
   384             if (bl == NULL)
   385                 throw bad_alloc();
   386 
   387             bloblist_t *_bl = bl;
   388             for (LONG i = lbound; i <= ubound; i++) {
   389                 Blob b;
   390                 memset(&b, 0, sizeof(Blob));
   391                 SafeArrayGetElement(sa, &i, &b);
   392 
   393                 LONG _lbound, _ubound;
   394                 SafeArrayGetLBound(b.value, 1, &_lbound);
   395                 SafeArrayGetUBound(b.value, 1, &_ubound);
   396                 size_t size = _ubound - _lbound + 1;
   397 
   398                 char *buffer;
   399                 if (size) {
   400                     buffer = (char *)malloc(size + 1);
   401                     if (buffer == NULL)
   402                         throw bad_alloc();
   403 
   404                     char *data;
   405 
   406                     SafeArrayAccessData(b.value, (void **)&data);
   407                     memcpy(buffer, data, size);
   408                     buffer[size] = 0; // safeguard
   409                     SafeArrayUnaccessData(sa);
   410                 }
   411                 else {
   412                     buffer = _strdup("");
   413                     if (buffer == NULL)
   414                         throw bad_alloc();
   415 
   416                 }
   417                 _bl = bloblist_add(_bl, buffer, size, str(b.MimeType), str(b.Filename));
   418                 if (_bl == NULL) {
   419                     free(buffer);
   420                     clear_blob(b);
   421                     free_bloblist(bl);
   422                     throw bad_alloc();
   423                 }
   424 
   425                 clear_blob(b);
   426             }
   427 
   428             return bl;
   429         }
   430 
   431         identity_list *identities(SAFEARRAY * sa)
   432         {
   433             if (sa == NULL)
   434                 return NULL;
   435 
   436             LONG lbound, ubound;
   437             SafeArrayGetLBound(sa, 1, &lbound);
   438             SafeArrayGetUBound(sa, 1, &ubound);
   439 
   440             size_t size = ubound - lbound + 1;
   441             if (size <= 0)
   442                 return NULL;
   443 
   444             identity_list *il = new_identity_list(NULL);
   445 
   446             identity_list *_il = il;
   447             for (LONG i = lbound; i <= ubound; i++) {
   448                 pEpIdentity s;
   449                 memset(&s, 0, sizeof(pEpIdentity));
   450                 SafeArrayGetElement(sa, &i, &s);
   451 
   452                 pEp_identity *ident;
   453                 try {
   454                     ident = new_identity(&s);
   455                 }
   456                 catch (bad_alloc&) {
   457                     clear_identity_s(s);
   458                     throw bad_alloc();
   459                 }
   460 
   461                 clear_identity_s(s);
   462 
   463                 _il = identity_list_add(_il, ident);
   464                 if (_il == NULL) {
   465                     free_identity_list(il);
   466                     throw bad_alloc();
   467                 }
   468             }
   469 
   470             return il;
   471         }
   472 
   473         stringpair_t *new_stringpair(StringPair *fld)
   474         {
   475             stringpair_t *pair;
   476 
   477             if (!fld) {
   478                 pair = ::new_stringpair(NULL, NULL);
   479             }
   480             else {
   481                 pair = ::new_stringpair(str(fld->Name), str(fld->Value));
   482             }
   483             if (pair == NULL)
   484                 throw bad_alloc();
   485 
   486             return pair;
   487         }
   488 
   489         void clear_opt_field(StringPair& f)
   490         {
   491             SysFreeString(f.Name);
   492             SysFreeString(f.Value);
   493             memset(&f, 0, sizeof(StringPair));
   494         }
   495 
   496         stringpair_list_t *stringpair_list(SAFEARRAY * sa)
   497         {
   498             if (sa == NULL)
   499                 return NULL;
   500 
   501             LONG lbound, ubound;
   502             SafeArrayGetLBound(sa, 1, &lbound);
   503             SafeArrayGetUBound(sa, 1, &ubound);
   504 
   505             size_t size = ubound - lbound + 1;
   506             if (size <= 0)
   507                 return NULL;
   508 
   509             stringpair_list_t *il = new_stringpair_list(NULL);
   510 
   511             stringpair_list_t *_il = il;
   512             for (LONG i = lbound; i <= ubound; i++) {
   513                 StringPair s;
   514                 memset(&s, 0, sizeof(StringPair));
   515                 SafeArrayGetElement(sa, &i, &s);
   516 
   517                 stringpair_t *pair;
   518                 try {
   519                     pair = new_stringpair(&s);
   520                 }
   521                 catch (bad_alloc&) {
   522                     clear_opt_field(s);
   523                     throw bad_alloc();
   524                 }
   525 
   526                 clear_opt_field(s);
   527 
   528                 _il = stringpair_list_add(_il, pair);
   529                 if (_il == NULL) {
   530                     free_stringpair_list(il);
   531                     throw bad_alloc();
   532                 }
   533             }
   534 
   535             return il;
   536         }
   537 
   538         ::message * text_message_to_C(TextMessage *msg)
   539         {
   540             assert(msg);
   541             if (!msg)
   542                 throw invalid_argument("msg");
   543 
   544             ::message * msg2 = new_message((PEP_msg_direction)msg->Dir);
   545             if (msg2 == NULL)
   546                 throw bad_alloc();
   547 
   548             msg2->id = str(msg->Id);
   549             msg2->shortmsg = str(msg->ShortMsg);
   550             msg2->longmsg = str(msg->LongMsg);
   551             msg2->longmsg_formatted = str(msg->LongMsgFormatted);
   552             msg2->attachments = bloblist(msg->Attachments);
   553             msg2->sent = new_timestamp(msg->Sent);
   554             msg2->recv = new_timestamp(msg->Recv);
   555             msg2->from = new_identity(&msg->From);
   556             msg2->to = identities(msg->To);
   557             msg2->recv_by = new_identity(&msg->RecvBy);
   558             msg2->cc = identities(msg->Cc);
   559             msg2->bcc = identities(msg->Bcc);
   560             msg2->reply_to = identities(msg->ReplyTo);
   561             msg2->references = new_stringlist(msg->References);
   562             msg2->keywords = new_stringlist(msg->Keywords);
   563             msg2->comments = str(msg->Comments);
   564             msg2->opt_fields = stringpair_list(msg->OptFields);
   565 
   566             return msg2;
   567         }
   568 
   569         void opt_field_array_from_C(stringpair_list_t* spair_list, LPSAFEARRAY* pair_list_out) {
   570             assert(spair_list);
   571             assert(pair_list_out);
   572 
   573             if (!spair_list)
   574                 return;
   575 
   576             *pair_list_out = array_from_C<StringPair, stringpair_list_t>(spair_list);
   577         }
   578 
   579         void clear_opt_field_array(LPSAFEARRAY* opt_field_array) {
   580             if (opt_field_array) {
   581                 SafeArrayDestroy(*opt_field_array);
   582                 *opt_field_array = NULL;
   583             }
   584         }
   585     }
   586 }