pEp_utility.cpp
author Volker Birk <vb@pep-project.org>
Sun, 13 Nov 2016 16:28:45 +0100
changeset 211 3e6efc641a02
parent 210 05ce89e74ac6
child 212 33bddd7ba879
permissions -rw-r--r--
fixing COM-15
     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 			if (!msg2) {
   299 				msg2 = (TextMessage *)calloc(1, sizeof(TextMessage));
   300 				assert(msg2);
   301 				if (!msg2)
   302 					throw bad_alloc();
   303 			}
   304 			else {
   305 				clear_text_message(msg2);
   306 			}
   307 
   308 			if (!msg)
   309 				return;
   310 
   311             msg2->Dir = (pEpMsgDirection) msg->dir;
   312             msg2->Id = bstr(msg->id);
   313             msg2->ShortMsg = bstr(msg->shortmsg);
   314             msg2->LongMsg = bstr(msg->longmsg);
   315             msg2->LongMsgFormatted = bstr(msg->longmsg_formatted);
   316             msg2->Attachments = array_from_C<Blob, bloblist_t>(msg->attachments);
   317             if (msg->sent)
   318                 msg2->Sent = mktime(msg->sent);
   319             if (msg->recv)
   320                 msg2->Recv = mktime(msg->recv);
   321             msg2->From = identity_s(msg->from);
   322             msg2->To = array_from_C<pEpIdentity, identity_list>(msg->to);
   323             msg2->RecvBy = identity_s(msg->recv_by);
   324             msg2->Cc = array_from_C<pEpIdentity, identity_list>(msg->cc);
   325             msg2->Bcc = array_from_C<pEpIdentity, identity_list>(msg->bcc);
   326             msg2->ReplyTo = array_from_C<pEpIdentity, identity_list>(msg->reply_to);
   327             msg2->References = string_array(msg->references);
   328             msg2->Keywords = string_array(msg->keywords);
   329             msg2->Comments = bstr(msg->comments);
   330             msg2->OptFields = array_from_C<StringPair, stringpair_list_t>(msg->opt_fields);
   331         }
   332 
   333         char * str(BSTR s)
   334         {
   335             string str = utf8_string(s);
   336             char *_s = _strdup(str.c_str());
   337             if (_s == NULL)
   338                 throw bad_alloc();
   339 
   340             return _s;
   341         }
   342 
   343         void clear_blob(Blob& b)
   344         {
   345             SysFreeString(b.Filename);
   346             SysFreeString(b.MimeType);
   347             SafeArrayDestroy(b.value);
   348             memset(&b, 0, sizeof(Blob));
   349         }
   350 
   351         bloblist_t *bloblist(SAFEARRAY *sa)
   352         {
   353             if (sa == NULL)
   354                 return NULL;
   355 
   356             LONG lbound, ubound;
   357             SafeArrayGetLBound(sa, 1, &lbound);
   358             SafeArrayGetUBound(sa, 1, &ubound);
   359 
   360             size_t size = ubound - lbound + 1;
   361             if (size <= 0)
   362                 return NULL;
   363 
   364             bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL);
   365             if (bl == NULL)
   366                 throw bad_alloc();
   367 
   368             bloblist_t *_bl = bl;
   369             for (LONG i = lbound; i <= ubound; i++) {
   370                 Blob b;
   371                 memset(&b, 0, sizeof(Blob));
   372                 SafeArrayGetElement(sa, &i, &b);
   373 
   374                 LONG _lbound, _ubound;
   375                 SafeArrayGetLBound(b.value, 1, &_lbound);
   376                 SafeArrayGetUBound(b.value, 1, &_ubound);
   377                 size_t size = _ubound - _lbound + 1;
   378 
   379                 char *buffer;
   380                 if (size) {
   381                     buffer = (char *) malloc(size);
   382                     if (buffer == NULL)
   383                         throw bad_alloc();
   384 
   385                     char *data;
   386 
   387                     SafeArrayAccessData(b.value, (void **) &data);
   388                     memcpy(buffer, data, size);
   389                     SafeArrayUnaccessData(sa);
   390                 }
   391                 else {
   392                     buffer = _strdup("");
   393                     if (buffer == NULL)
   394                         throw bad_alloc();
   395 
   396                 }
   397                 _bl = bloblist_add(_bl, buffer, size, str(b.MimeType), str(b.Filename));
   398                 if (_bl == NULL) {
   399                     free(buffer);
   400                     clear_blob(b);
   401                     free_bloblist(bl);
   402                     throw bad_alloc();
   403                 }
   404 
   405                 clear_blob(b);
   406             }
   407 
   408             return bl;
   409         }
   410 
   411         identity_list *identities(SAFEARRAY * sa)
   412         {
   413             if (sa == NULL)
   414                 return NULL;
   415 
   416             LONG lbound, ubound;
   417             SafeArrayGetLBound(sa, 1, &lbound);
   418             SafeArrayGetUBound(sa, 1, &ubound);
   419 
   420             size_t size = ubound - lbound + 1;
   421             if (size <= 0)
   422                 return NULL;
   423 
   424             identity_list *il = new_identity_list(NULL);
   425 
   426             identity_list *_il = il;
   427             for (LONG i = lbound; i <= ubound; i++) {
   428                 pEpIdentity s;
   429                 memset(&s, 0, sizeof(pEpIdentity));
   430                 SafeArrayGetElement(sa, &i, &s);
   431 
   432                 pEp_identity *ident;
   433                 try {
   434                     ident = new_identity(&s);
   435                 }
   436                 catch (bad_alloc&) {
   437                     clear_identity_s(s);
   438                     throw bad_alloc();
   439                 }
   440 
   441                 clear_identity_s(s);
   442 
   443                 _il = identity_list_add(_il, ident);
   444                 if (_il == NULL) {
   445                     free_identity_list(il);
   446                     throw bad_alloc();
   447                 }
   448             }
   449 
   450             return il;
   451         }
   452 
   453         stringpair_t *new_stringpair(StringPair *fld)
   454         {
   455             stringpair_t *pair = ::new_stringpair(str(fld->Name), str(fld->Value));
   456             if (pair == NULL)
   457                 throw bad_alloc();
   458 
   459             return pair;
   460         }
   461 
   462         void clear_opt_field(StringPair& f)
   463         {
   464             SysFreeString(f.Name);
   465             SysFreeString(f.Value);
   466             memset(&f, 0, sizeof(StringPair));
   467         }
   468 
   469         stringpair_list_t *stringpair_list(SAFEARRAY * sa)
   470         {
   471             if (sa == NULL)
   472                 return NULL;
   473 
   474             LONG lbound, ubound;
   475             SafeArrayGetLBound(sa, 1, &lbound);
   476             SafeArrayGetUBound(sa, 1, &ubound);
   477 
   478             size_t size = ubound - lbound + 1;
   479             if (size <= 0)
   480                 return NULL;
   481 
   482             stringpair_list_t *il = new_stringpair_list(NULL);
   483 
   484             stringpair_list_t *_il = il;
   485             for (LONG i = lbound; i <= ubound; i++) {
   486                 StringPair s;
   487                 memset(&s, 0, sizeof(StringPair));
   488                 SafeArrayGetElement(sa, &i, &s);
   489 
   490                 stringpair_t *pair;
   491                 try {
   492                     pair = new_stringpair(&s);
   493                 }
   494                 catch (bad_alloc&) {
   495                     clear_opt_field(s);
   496                     throw bad_alloc();
   497                 }
   498 
   499                 clear_opt_field(s);
   500 
   501                 _il = stringpair_list_add(_il, pair);
   502                 if (_il == NULL) {
   503                     free_stringpair_list(il);
   504                     throw bad_alloc();
   505                 }
   506             }
   507 
   508             return il;
   509         }
   510         
   511         ::message * text_message_to_C(TextMessage *msg)
   512         {
   513             assert(msg);
   514 
   515             ::message * msg2 = new_message((PEP_msg_direction) msg->Dir);
   516             if (msg2 == NULL)
   517                 throw bad_alloc();
   518 
   519             msg2->id = str(msg->Id);
   520             msg2->shortmsg = str(msg->ShortMsg);
   521             msg2->longmsg = str(msg->LongMsg);
   522             msg2->longmsg_formatted = str(msg->LongMsgFormatted);
   523             msg2->attachments = bloblist(msg->Attachments);
   524             msg2->sent = new_timestamp(msg->Sent);
   525             msg2->recv = new_timestamp(msg->Recv);
   526             msg2->from = new_identity(&msg->From);
   527             msg2->to = identities(msg->To);
   528             msg2->recv_by = new_identity(&msg->RecvBy);
   529             msg2->cc = identities(msg->Cc);
   530             msg2->bcc = identities(msg->Bcc);
   531             msg2->reply_to = identities(msg->ReplyTo);
   532             msg2->references = new_stringlist(msg->References);
   533             msg2->keywords = new_stringlist(msg->Keywords);
   534             msg2->comments = str(msg->Comments);
   535             msg2->opt_fields = stringpair_list(msg->OptFields);
   536 
   537             return msg2;
   538         }
   539 
   540 		void opt_field_array_from_C(stringpair_list_t* spair_list, LPSAFEARRAY* pair_list_out) {
   541 			assert(spair_list);
   542 			assert(pair_list_out);
   543 			
   544 			if (!spair_list)
   545 				return;
   546 
   547 			*pair_list_out = array_from_C<StringPair, stringpair_list_t>(spair_list);
   548 		}
   549 
   550 		void clear_opt_field_array(LPSAFEARRAY* opt_field_array) {
   551 			SafeArrayDestroy(*opt_field_array);
   552 			//memset(*opt_field_array, 0, sizeof(SAFEARRAY*));
   553 			*opt_field_array = NULL;
   554 		}
   555     }
   556 }