pEp_utitlity.cpp
author Volker Birk <vb@pep-project.org>
Sun, 31 May 2015 19:31:19 +0200
changeset 39 6fc5cc7a167c
parent 38 d314ed57180c
child 40 dfb59114debe
permissions -rw-r--r--
safer
     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).Detach();
    67             _ident->comm_type = this->comm_type;
    68             _ident->fpr = utf16_bstr(this->fpr).Detach();
    69             _ident->lang = utf16_bstr(this->lang).Detach();
    70             _ident->username = utf16_bstr(this->username).Detach();
    71             _ident->user_id = utf16_bstr(this->user_id).Detach();
    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).Detach();
    84                 if (ident->fpr)
    85                     ident_s->fpr = utf16_bstr(ident->fpr).Detach();
    86                 if (ident->user_id)
    87                     ident_s->user_id = utf16_bstr(ident->user_id).Detach();
    88                 if (ident->username)
    89                     ident_s->username = utf16_bstr(ident->username).Detach();
    90                 ident_s->comm_type = (pEp_comm_type) ident->comm_type;
    91                 if (ident->lang)
    92                     ident_s->lang = utf16_bstr(ident->lang).Detach();
    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         template<> BSTR from_C< BSTR, char >(char *s)
   158         {
   159             if (s)
   160                 return utf16_bstr(s).Detach();
   161             else
   162                 return _bstr_t(L"").Detach();
   163         }
   164 
   165         inline BSTR bstr(char *s)
   166         {
   167             return from_C< BSTR, char >(s);
   168         }
   169 
   170         template<> blob *from_C< blob *, bloblist_t >(bloblist_t *tl)
   171         {
   172             assert(tl && tl->value);
   173 
   174             CComSafeArray<BYTE> sa;
   175             sa.Create(tl->size);
   176 
   177             memcpy(sa.m_psa->pvData, tl->value, tl->size);
   178 
   179             blob *_blob = new blob();
   180 
   181             _blob->value = sa.Detach();
   182             _blob->mime_type = bstr(tl->mime_type);
   183             _blob->filename = bstr(tl->filename);
   184 
   185             return _blob;
   186         }
   187 
   188         template< class T > int length(T *);
   189 
   190         template< class T2, class T > SAFEARRAY * array_from_C(T *tl)
   191         {
   192             if (tl == NULL)
   193                 return newSafeArray<T2>(0);
   194 
   195             int len = length<T>(tl);
   196 
   197             LPSAFEARRAY sa = newSafeArray<T2>(len);
   198             LONG lbound, ubound;
   199             SafeArrayGetLBound(sa, 1, &lbound);
   200             SafeArrayGetUBound(sa, 1, &ubound);
   201 
   202             T *_tl = tl;
   203             for (LONG i = lbound; i <= ubound; _tl = _tl->next, i++)
   204                 SafeArrayPutElement(sa, &i, from_C<T2 *, T>(_tl));
   205 
   206             return sa;
   207         }
   208 
   209         template<> pEp_identity_s from_C< pEp_identity_s, pEp_identity >(pEp_identity *tl)
   210         {
   211             pEp_identity_s _ident;
   212             if (tl)
   213                 copy_identity(&_ident, tl);
   214             return _ident;
   215         }
   216 
   217         pEp_identity_s identity_s(pEp_identity *ident)
   218         {
   219             return from_C< pEp_identity_s, pEp_identity >(ident);
   220         }
   221 
   222         template<> pEp_identity_s *from_C< pEp_identity_s *, identity_list >(identity_list *il)
   223         {
   224             pEp_identity_s *ident = new pEp_identity_s();
   225             if (il)
   226                 copy_identity(ident, il->ident);
   227             return ident;
   228         }
   229 
   230         template<> opt_field *from_C< opt_field *, stringpair_list_t >(stringpair_list_t * sp)
   231         {
   232             opt_field *fld = new opt_field();
   233             if (sp) {
   234                 fld->name = bstr(sp->value->key);
   235                 fld->value = bstr(sp->value->value);
   236             }
   237             return fld;
   238         }
   239 
   240         template<> int length<identity_list>(identity_list *tl)
   241         {
   242             return identity_list_length(tl);
   243         }
   244 
   245         template<> int length<bloblist_t>(bloblist_t *tl)
   246         {
   247             return bloblist_length(tl);
   248         }
   249 
   250         template<> int length<stringpair_list_t>(stringpair_list_t *tl)
   251         {
   252             return stringpair_list_length(tl);
   253         }
   254 
   255         void text_message_from_C(text_message *msg2, ::message *msg)
   256         {
   257             assert(msg2);
   258             assert(msg);
   259 
   260             msg2->dir = (pEp_msg_direction) msg->dir;
   261             msg2->id = bstr(msg->id);
   262             msg2->shortmsg = bstr(msg->shortmsg);
   263             msg2->longmsg = bstr(msg->longmsg);
   264             msg2->longmsg_formatted = bstr(msg->longmsg_formatted);
   265             msg2->attachments = array_from_C<blob, bloblist_t>(msg->attachments);
   266             if (msg->sent)
   267                 msg2->sent = mktime(msg->sent);
   268             if (msg->recv)
   269                 msg2->recv = mktime(msg->recv);
   270             msg2->from = identity_s(msg->from);
   271             msg2->to = array_from_C<pEp_identity_s, identity_list>(msg->to);
   272             msg2->recv_by = identity_s(msg->recv_by);
   273             msg2->cc = array_from_C<pEp_identity_s, identity_list>(msg->cc);
   274             msg2->bcc = array_from_C<pEp_identity_s, identity_list>(msg->bcc);
   275             msg2->reply_to = array_from_C<pEp_identity_s, identity_list>(msg->reply_to);
   276             msg2->references = string_array(msg->references).Detach();
   277             msg2->keywords = string_array(msg->keywords).Detach();
   278             msg2->comments = bstr(msg->comments);
   279             msg2->opt_fields = array_from_C<opt_field, stringpair_list_t>(msg->opt_fields);
   280         }
   281 
   282         char * str(BSTR s)
   283         {
   284             string str = utf8_string(s);
   285             char *_s = _strdup(str.c_str());
   286             if (_s == NULL)
   287                 throw bad_alloc();
   288 
   289             return _s;
   290         }
   291 
   292         bloblist_t *bloblist(SAFEARRAY *sa)
   293         {
   294             if (sa == NULL)
   295                 return NULL;
   296 
   297             LONG lbound, ubound;
   298             SafeArrayGetLBound(sa, 1, &lbound);
   299             SafeArrayGetUBound(sa, 1, &ubound);
   300 
   301             size_t size = ubound - lbound + 1;
   302             if (size <= 0)
   303                 return NULL;
   304 
   305             bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL);
   306             if (bl == NULL)
   307                 throw bad_alloc();
   308 
   309             bloblist_t *_bl = bl;
   310             for (LONG i = lbound; i <= ubound; i++) {
   311                 blob b;
   312                 memset(&b, 0, sizeof(blob));
   313                 SafeArrayGetElement(sa, &i, &b);
   314 
   315                 LONG _lbound, _ubound;
   316                 SafeArrayGetLBound(b.value, 1, &_lbound);
   317                 SafeArrayGetUBound(b.value, 1, &_ubound);
   318                 size_t size = _ubound - _lbound + 1;
   319 
   320                 char *buffer = (char *) malloc(size);
   321                 if (buffer == NULL)
   322                     throw bad_alloc();
   323 
   324                 char *data;
   325 
   326                 SafeArrayAccessData(b.value, (void **) &data);
   327                 memcpy(buffer, data, size);
   328                 SafeArrayUnaccessData(sa);
   329 
   330                 _bl = bloblist_add(_bl, buffer, size, str(b.mime_type), str(b.filename));
   331                 if (_bl == NULL) {
   332                     IRecordInfo *ri = getRecordInfo<blob>();
   333                     ri->RecordClear(&b);
   334 
   335                     free_bloblist(bl);
   336                     free(buffer);
   337                     throw bad_alloc();
   338                 }
   339 
   340                 IRecordInfo *ri = getRecordInfo<blob>();
   341                 ri->RecordClear(&b);
   342             }
   343 
   344             return bl;
   345         }
   346 
   347         identity_list *identities(SAFEARRAY * sa)
   348         {
   349             if (sa == NULL)
   350                 return NULL;
   351 
   352             LONG lbound, ubound;
   353             SafeArrayGetLBound(sa, 1, &lbound);
   354             SafeArrayGetUBound(sa, 1, &ubound);
   355 
   356             size_t size = ubound - lbound + 1;
   357             if (size <= 0)
   358                 return NULL;
   359 
   360             identity_list *il = new_identity_list(NULL);
   361 
   362             identity_list *_il = il;
   363             for (LONG i = lbound; i <= ubound; i++) {
   364                 pEp_identity_s s;
   365                 memset(&s, 0, sizeof(s));
   366                 SafeArrayGetElement(sa, &i, &s);
   367 
   368                 pEp_identity *ident;
   369                 try {
   370                     ident = new_identity(&s);
   371                 }
   372                 catch (bad_alloc&) {
   373                     IRecordInfo *ri = getRecordInfo<pEp_identity_s>();
   374                     ri->RecordClear(&s);
   375 
   376                     throw bad_alloc();
   377                 }
   378 
   379                 IRecordInfo *ri = getRecordInfo<pEp_identity_s>();
   380                 ri->RecordClear(&s);
   381 
   382                 _il = identity_list_add(_il, ident);
   383                 if (_il == NULL) {
   384                     free_identity_list(il);
   385                     throw bad_alloc();
   386                 }
   387             }
   388 
   389             return il;
   390         }
   391 
   392         stringpair_t *new_stringpair(opt_field *fld)
   393         {
   394             stringpair_t *pair = ::new_stringpair(str(fld->name), str(fld->value));
   395             if (pair == NULL)
   396                 throw bad_alloc();
   397 
   398             return pair;
   399         }
   400 
   401         stringpair_list_t *stringpair_list(SAFEARRAY * sa)
   402         {
   403             if (sa == NULL)
   404                 return NULL;
   405 
   406             LONG lbound, ubound;
   407             SafeArrayGetLBound(sa, 1, &lbound);
   408             SafeArrayGetUBound(sa, 1, &ubound);
   409 
   410             size_t size = ubound - lbound + 1;
   411             if (size <= 0)
   412                 return NULL;
   413 
   414             stringpair_list_t *il = new_stringpair_list(NULL);
   415 
   416             stringpair_list_t *_il = il;
   417             for (LONG i = lbound; i <= ubound; i++) {
   418                 opt_field s;
   419                 memset(&s, 0, sizeof(opt_field));
   420                 SafeArrayGetElement(sa, &i, &s);
   421 
   422                 stringpair_t *pair;
   423                 try {
   424                     pair = new_stringpair(&s);
   425                 }
   426                 catch (bad_alloc&) {
   427                     IRecordInfo *ri = getRecordInfo<opt_field>();
   428                     ri->RecordClear(&s);
   429 
   430                     throw bad_alloc();
   431                 }
   432 
   433                 IRecordInfo *ri = getRecordInfo<opt_field>();
   434                 ri->RecordClear(&s);
   435 
   436                 _il = stringpair_list_add(_il, pair);
   437                 if (_il == NULL) {
   438                     free_stringpair_list(il);
   439                     throw bad_alloc();
   440                 }
   441             }
   442 
   443             return il;
   444         }
   445         
   446         ::message * text_message_to_C(text_message *msg)
   447         {
   448             assert(msg);
   449 
   450             ::message * msg2 = new_message((PEP_msg_direction) msg->dir);
   451             if (msg2 == NULL)
   452                 throw bad_alloc();
   453 
   454             msg2->id = str(msg->id);
   455             msg2->shortmsg = str(msg->shortmsg);
   456             msg2->longmsg = str(msg->longmsg);
   457             msg2->longmsg_formatted = str(msg->longmsg_formatted);
   458             msg2->attachments = bloblist(msg->attachments);
   459             msg2->sent = new_timestamp(msg->sent);
   460             msg2->recv = new_timestamp(msg->recv);
   461             msg2->from = new_identity(&msg->from);
   462             msg2->to = identities(msg->to);
   463             msg2->recv_by = new_identity(&msg->recv_by);
   464             msg2->cc = identities(msg->cc);
   465             msg2->bcc = identities(msg->bcc);
   466             msg2->reply_to = identities(msg->reply_to);
   467             msg2->references = new_stringlist(msg->references);
   468             msg2->keywords = new_stringlist(msg->keywords);
   469             msg2->comments = str(msg->comments);
   470             msg2->opt_fields = stringpair_list(msg->opt_fields);
   471 
   472             return msg2;
   473         }
   474     }
   475 }