pEp_utility.cpp
author Dean Looyengoed
Fri, 29 Apr 2016 15:30:10 +0200
changeset 69 8e47cec9271b
parent 43 pEp_utitlity.cpp@3d403e61e33a
child 74 f2531096699e
permissions -rw-r--r--
Rename 'utitlity' to 'utility'.
     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 = (pEp_comm_type) _ident->comm_type;
    20             lang = _ident->lang;
    21         }
    22 
    23         pEp_identity_cpp::pEp_identity_cpp(const pEp_identity_s *_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->user_id)
    31                 user_id = utf8_string(_ident->user_id);
    32             if (_ident->username)
    33                 username = utf8_string(_ident->username);
    34             comm_type = _ident->comm_type;
    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         pEp_identity_s * pEp_identity_cpp::to_pEp_identity_s()
    60         {
    61             pEp_identity_s *_ident = (pEp_identity_s *) calloc(1, sizeof(pEp_identity_s));
    62             assert(_ident);
    63             if (_ident == NULL)
    64                 throw bad_alloc();
    65 
    66             _ident->address = utf16_bstr(this->address);
    67             _ident->comm_type = 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->user_id = utf16_bstr(this->user_id);
    72 
    73             return _ident;
    74         }
    75 
    76         void copy_identity(pEp_identity_s * ident_s, const pEp_identity * ident)
    77         {
    78             assert(ident_s);
    79 
    80             ::memset(ident_s, 0, sizeof(pEp_identity_s));
    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->user_id = utf16_bstr(ident->user_id);
    88                 if (ident->username)
    89                     ident_s->username = utf16_bstr(ident->username);
    90                 ident_s->comm_type = (pEp_comm_type) ident->comm_type;
    91                 if (ident->lang)
    92                     ident_s->lang = utf16_bstr(ident->lang);
    93             }
    94         }
    95 
    96         ::pEp_identity *new_identity(const pEp_identity_s * 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->user_id)
   121                 _user_id = utf8_string(ident->user_id);
   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->comm_type;
   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             char *data;
   171             SafeArrayAccessData(sa, (void **) &data);
   172             memcpy(data, tl->value, tl->size);
   173             SafeArrayUnaccessData(sa);
   174 
   175             blob *_blob = new blob();
   176 
   177             _blob->value = sa.Detach();
   178             _blob->mime_type = bstr(tl->mime_type);
   179             _blob->filename = bstr(tl->filename);
   180 
   181             return _blob;
   182         }
   183 
   184         template< class T > int length(T *);
   185 
   186         template< class T2, class T > SAFEARRAY * array_from_C(T *tl)
   187         {
   188             if (tl == NULL)
   189                 return newSafeArray<T2>(0);
   190 
   191             int len = length<T>(tl);
   192 
   193             LPSAFEARRAY sa = newSafeArray<T2>(len);
   194             LONG lbound, ubound;
   195             SafeArrayGetLBound(sa, 1, &lbound);
   196             SafeArrayGetUBound(sa, 1, &ubound);
   197 
   198             T *_tl = tl;
   199             for (LONG i = lbound; i <= ubound; _tl = _tl->next, i++)
   200                 SafeArrayPutElement(sa, &i, from_C<T2 *, T>(_tl));
   201 
   202             return sa;
   203         }
   204 
   205         void clear_identity_s(pEp_identity_s& ident)
   206         {
   207             SysFreeString(ident.address);
   208             SysFreeString(ident.fpr);
   209             SysFreeString(ident.lang);
   210             SysFreeString(ident.username);
   211             SysFreeString(ident.user_id);
   212 
   213             memset(&ident, 0, sizeof(pEp_identity_s));
   214         }
   215 
   216         template<> pEp_identity_s from_C< pEp_identity_s, pEp_identity >(pEp_identity *tl)
   217         {
   218             pEp_identity_s _ident;
   219             memset(&_ident, 0, sizeof(_ident));
   220 
   221             if (tl)
   222                 copy_identity(&_ident, tl);
   223             return _ident;
   224         }
   225 
   226         pEp_identity_s identity_s(pEp_identity *ident)
   227         {
   228             return from_C< pEp_identity_s, pEp_identity >(ident);
   229         }
   230 
   231         template<> pEp_identity_s *from_C< pEp_identity_s *, identity_list >(identity_list *il)
   232         {
   233             pEp_identity_s *ident = new pEp_identity_s();
   234             memset(ident, 0, sizeof(pEp_identity_s));
   235 
   236             if (il)
   237                 copy_identity(ident, il->ident);
   238             return ident;
   239         }
   240 
   241         template<> opt_field *from_C< opt_field *, stringpair_list_t >(stringpair_list_t * sp)
   242         {
   243             opt_field *fld = new opt_field();
   244             if (sp) {
   245                 fld->name = bstr(sp->value->key);
   246                 fld->value = bstr(sp->value->value);
   247             }
   248             return fld;
   249         }
   250 
   251         template<> int length<identity_list>(identity_list *tl)
   252         {
   253             return identity_list_length(tl);
   254         }
   255 
   256         template<> int length<bloblist_t>(bloblist_t *tl)
   257         {
   258             return bloblist_length(tl);
   259         }
   260 
   261         template<> int length<stringpair_list_t>(stringpair_list_t *tl)
   262         {
   263             return stringpair_list_length(tl);
   264         }
   265 
   266         void clear_text_message(text_message *msg)
   267         {
   268             SysFreeString(msg->id);
   269             SysFreeString(msg->shortmsg);
   270             SysFreeString(msg->longmsg);
   271             SysFreeString(msg->longmsg_formatted);
   272             SafeArrayDestroy(msg->attachments);
   273             clear_identity_s(msg->from);
   274             SafeArrayDestroy(msg->to);
   275             clear_identity_s(msg->recv_by);
   276             SafeArrayDestroy(msg->cc);
   277             SafeArrayDestroy(msg->bcc);
   278             SafeArrayDestroy(msg->reply_to);
   279             SafeArrayDestroy(msg->references);
   280             SafeArrayDestroy(msg->keywords);
   281             SysFreeString(msg->comments);
   282             SafeArrayDestroy(msg->opt_fields);
   283 
   284             memset(msg, 0, sizeof(text_message));
   285         }
   286 
   287         void text_message_from_C(text_message *msg2, ::message *msg)
   288         {
   289             assert(msg2);
   290             assert(msg);
   291 
   292             clear_text_message(msg2);
   293 
   294             msg2->dir = (pEp_msg_direction) msg->dir;
   295             msg2->id = bstr(msg->id);
   296             msg2->shortmsg = bstr(msg->shortmsg);
   297             msg2->longmsg = bstr(msg->longmsg);
   298             msg2->longmsg_formatted = bstr(msg->longmsg_formatted);
   299             msg2->attachments = array_from_C<blob, bloblist_t>(msg->attachments);
   300             if (msg->sent)
   301                 msg2->sent = mktime(msg->sent);
   302             if (msg->recv)
   303                 msg2->recv = mktime(msg->recv);
   304             msg2->from = identity_s(msg->from);
   305             msg2->to = array_from_C<pEp_identity_s, identity_list>(msg->to);
   306             msg2->recv_by = identity_s(msg->recv_by);
   307             msg2->cc = array_from_C<pEp_identity_s, identity_list>(msg->cc);
   308             msg2->bcc = array_from_C<pEp_identity_s, identity_list>(msg->bcc);
   309             msg2->reply_to = array_from_C<pEp_identity_s, identity_list>(msg->reply_to);
   310             msg2->references = string_array(msg->references);
   311             msg2->keywords = string_array(msg->keywords);
   312             msg2->comments = bstr(msg->comments);
   313             msg2->opt_fields = array_from_C<opt_field, stringpair_list_t>(msg->opt_fields);
   314         }
   315 
   316         char * str(BSTR s)
   317         {
   318             string str = utf8_string(s);
   319             char *_s = _strdup(str.c_str());
   320             if (_s == NULL)
   321                 throw bad_alloc();
   322 
   323             return _s;
   324         }
   325 
   326         void clear_blob(blob& b)
   327         {
   328             SysFreeString(b.filename);
   329             SysFreeString(b.mime_type);
   330             SafeArrayDestroy(b.value);
   331             memset(&b, 0, sizeof(blob));
   332         }
   333 
   334         bloblist_t *bloblist(SAFEARRAY *sa)
   335         {
   336             if (sa == NULL)
   337                 return NULL;
   338 
   339             LONG lbound, ubound;
   340             SafeArrayGetLBound(sa, 1, &lbound);
   341             SafeArrayGetUBound(sa, 1, &ubound);
   342 
   343             size_t size = ubound - lbound + 1;
   344             if (size <= 0)
   345                 return NULL;
   346 
   347             bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL);
   348             if (bl == NULL)
   349                 throw bad_alloc();
   350 
   351             bloblist_t *_bl = bl;
   352             for (LONG i = lbound; i <= ubound; i++) {
   353                 blob b;
   354                 memset(&b, 0, sizeof(blob));
   355                 SafeArrayGetElement(sa, &i, &b);
   356 
   357                 LONG _lbound, _ubound;
   358                 SafeArrayGetLBound(b.value, 1, &_lbound);
   359                 SafeArrayGetUBound(b.value, 1, &_ubound);
   360                 size_t size = _ubound - _lbound + 1;
   361 
   362                 char *buffer = (char *) malloc(size);
   363                 if (buffer == NULL)
   364                     throw bad_alloc();
   365 
   366                 char *data;
   367 
   368                 SafeArrayAccessData(b.value, (void **) &data);
   369                 memcpy(buffer, data, size);
   370                 SafeArrayUnaccessData(sa);
   371 
   372                 _bl = bloblist_add(_bl, buffer, size, str(b.mime_type), str(b.filename));
   373                 if (_bl == NULL) {
   374                     free(buffer);
   375                     clear_blob(b);
   376                     free_bloblist(bl);
   377                     throw bad_alloc();
   378                 }
   379 
   380                 clear_blob(b);
   381             }
   382 
   383             return bl;
   384         }
   385 
   386         identity_list *identities(SAFEARRAY * sa)
   387         {
   388             if (sa == NULL)
   389                 return NULL;
   390 
   391             LONG lbound, ubound;
   392             SafeArrayGetLBound(sa, 1, &lbound);
   393             SafeArrayGetUBound(sa, 1, &ubound);
   394 
   395             size_t size = ubound - lbound + 1;
   396             if (size <= 0)
   397                 return NULL;
   398 
   399             identity_list *il = new_identity_list(NULL);
   400 
   401             identity_list *_il = il;
   402             for (LONG i = lbound; i <= ubound; i++) {
   403                 pEp_identity_s s;
   404                 memset(&s, 0, sizeof(pEp_identity_s));
   405                 SafeArrayGetElement(sa, &i, &s);
   406 
   407                 pEp_identity *ident;
   408                 try {
   409                     ident = new_identity(&s);
   410                 }
   411                 catch (bad_alloc&) {
   412                     clear_identity_s(s);
   413                     throw bad_alloc();
   414                 }
   415 
   416                 clear_identity_s(s);
   417 
   418                 _il = identity_list_add(_il, ident);
   419                 if (_il == NULL) {
   420                     free_identity_list(il);
   421                     throw bad_alloc();
   422                 }
   423             }
   424 
   425             return il;
   426         }
   427 
   428         stringpair_t *new_stringpair(opt_field *fld)
   429         {
   430             stringpair_t *pair = ::new_stringpair(str(fld->name), str(fld->value));
   431             if (pair == NULL)
   432                 throw bad_alloc();
   433 
   434             return pair;
   435         }
   436 
   437         void clear_opt_field(opt_field& f)
   438         {
   439             SysFreeString(f.name);
   440             SysFreeString(f.value);
   441             memset(&f, 0, sizeof(opt_field));
   442         }
   443 
   444         stringpair_list_t *stringpair_list(SAFEARRAY * sa)
   445         {
   446             if (sa == NULL)
   447                 return NULL;
   448 
   449             LONG lbound, ubound;
   450             SafeArrayGetLBound(sa, 1, &lbound);
   451             SafeArrayGetUBound(sa, 1, &ubound);
   452 
   453             size_t size = ubound - lbound + 1;
   454             if (size <= 0)
   455                 return NULL;
   456 
   457             stringpair_list_t *il = new_stringpair_list(NULL);
   458 
   459             stringpair_list_t *_il = il;
   460             for (LONG i = lbound; i <= ubound; i++) {
   461                 opt_field s;
   462                 memset(&s, 0, sizeof(opt_field));
   463                 SafeArrayGetElement(sa, &i, &s);
   464 
   465                 stringpair_t *pair;
   466                 try {
   467                     pair = new_stringpair(&s);
   468                 }
   469                 catch (bad_alloc&) {
   470                     clear_opt_field(s);
   471                     throw bad_alloc();
   472                 }
   473 
   474                 clear_opt_field(s);
   475 
   476                 _il = stringpair_list_add(_il, pair);
   477                 if (_il == NULL) {
   478                     free_stringpair_list(il);
   479                     throw bad_alloc();
   480                 }
   481             }
   482 
   483             return il;
   484         }
   485         
   486         ::message * text_message_to_C(text_message *msg)
   487         {
   488             assert(msg);
   489 
   490             ::message * msg2 = new_message((PEP_msg_direction) msg->dir);
   491             if (msg2 == NULL)
   492                 throw bad_alloc();
   493 
   494             msg2->id = str(msg->id);
   495             msg2->shortmsg = str(msg->shortmsg);
   496             msg2->longmsg = str(msg->longmsg);
   497             msg2->longmsg_formatted = str(msg->longmsg_formatted);
   498             msg2->attachments = bloblist(msg->attachments);
   499             msg2->sent = new_timestamp(msg->sent);
   500             msg2->recv = new_timestamp(msg->recv);
   501             msg2->from = new_identity(&msg->from);
   502             msg2->to = identities(msg->to);
   503             msg2->recv_by = new_identity(&msg->recv_by);
   504             msg2->cc = identities(msg->cc);
   505             msg2->bcc = identities(msg->bcc);
   506             msg2->reply_to = identities(msg->reply_to);
   507             msg2->references = new_stringlist(msg->references);
   508             msg2->keywords = new_stringlist(msg->keywords);
   509             msg2->comments = str(msg->comments);
   510             msg2->opt_fields = stringpair_list(msg->opt_fields);
   511 
   512             return msg2;
   513         }
   514     }
   515 }