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