pEp_utility.cpp
author Markus Schaber <markus@pep-security.net>
Wed, 14 Jun 2017 23:46:37 +0200
branchCOM-54-ENGINE-9
changeset 251 ded328cde93f
parent 224 b0290a75f7a5
permissions -rw-r--r--
COM-54: Attachment Blob CID Support
     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)
    12 				return;
    13 
    14             if (_ident->address)
    15                 address = _ident->address;
    16             if (_ident->fpr)
    17                 fpr = _ident->fpr;
    18             if (_ident->user_id)
    19                 user_id = _ident->user_id;
    20             if (_ident->username)
    21                 username = _ident->username;
    22             comm_type = (pEpComType) _ident->comm_type;
    23             lang = _ident->lang;
    24 			flags = (int) _ident->flags;
    25         }
    26 
    27         pEp_identity_cpp::pEp_identity_cpp(const pEpIdentity *_ident)
    28             : me(false)
    29         {
    30 			if (!_ident)
    31 				return;
    32 
    33 			if (_ident->Address)
    34                 address = utf8_string(_ident->Address);
    35             if (_ident->Fpr)
    36                 fpr = utf8_string(_ident->Fpr);
    37             if (_ident->UserId)
    38                 user_id = utf8_string(_ident->UserId);
    39             if (_ident->UserName)
    40                 username = utf8_string(_ident->UserName);
    41             comm_type = _ident->CommType;
    42             if (_ident->Lang)
    43                 lang = utf8_string(_ident->Lang);
    44 			flags = (int)_ident->Flags;
    45         }
    46 
    47         pEp_identity * pEp_identity_cpp::to_pEp_identity()
    48         {
    49             ::pEp_identity *_ident = ::new_identity(this->address.c_str(), this->fpr.c_str(), this->user_id.c_str(), this->username.c_str());
    50             assert(_ident);
    51             if (_ident == NULL)
    52                 throw bad_alloc();
    53 
    54             _ident->comm_type = (::PEP_comm_type) this->comm_type;
    55             _ident->me = this->me;
    56 
    57             assert(this->lang.size() == 0 || this->lang.size() == 2);
    58 
    59             if (this->lang.size()) {
    60                 _ident->lang[0] = this->lang[0];
    61                 _ident->lang[1] = this->lang[1];
    62             }
    63 
    64 			_ident->flags = (identity_flags) this->flags;
    65 
    66             return _ident;
    67         }
    68 
    69         pEpIdentity * pEp_identity_cpp::to_pEp_identity_s()
    70         {
    71             pEpIdentity *_ident = (pEpIdentity *) calloc(1, sizeof(pEpIdentity));
    72             assert(_ident);
    73             if (_ident == NULL)
    74                 throw bad_alloc();
    75 
    76             _ident->Address = utf16_bstr(this->address);
    77             _ident->CommType = this->comm_type;
    78             _ident->Fpr = utf16_bstr(this->fpr);
    79             _ident->Lang = utf16_bstr(this->lang);
    80             _ident->UserName = utf16_bstr(this->username);
    81             _ident->UserId = utf16_bstr(this->user_id);
    82 			_ident->Flags = (pEpIdentityFlags) this->flags;
    83 
    84             return _ident;
    85         }
    86 
    87         void copy_identity(pEpIdentity * ident_s, const pEp_identity * ident)
    88         {
    89             assert(ident_s);
    90 			if (!ident_s)
    91 				throw invalid_argument("ident_s");
    92 
    93             ::memset(ident_s, 0, sizeof(pEpIdentity));
    94             if (ident) {
    95                 if (ident->address)
    96                     ident_s->Address = utf16_bstr(ident->address);
    97                 if (ident->fpr)
    98                     ident_s->Fpr = utf16_bstr(ident->fpr);
    99                 if (ident->user_id)
   100                     ident_s->UserId = utf16_bstr(ident->user_id);
   101                 if (ident->username)
   102                     ident_s->UserName = utf16_bstr(ident->username);
   103                 ident_s->CommType = (pEpComType) ident->comm_type;
   104                 if (ident->lang)
   105                     ident_s->Lang = utf16_bstr(ident->lang);
   106 				ident_s->Flags = (pEpIdentityFlags) ident->flags;
   107             }
   108         }
   109 
   110         ::pEp_identity *new_identity(const pEpIdentity * ident)
   111         {
   112             if (ident == NULL)
   113                 return NULL;
   114 
   115             ::pEp_identity *_ident;
   116 
   117             string _address;
   118             string _fpr;
   119             string _user_id;
   120             string _username;
   121 
   122             if (ident->Address)
   123                 _address = utf8_string(ident->Address);
   124             if (ident->Fpr) {
   125                 _fpr = utf8_string(ident->Fpr);
   126                 for (auto p = _fpr.begin(); p != _fpr.end(); ++p) {
   127                     if (*p >= 'A' && *p <= 'Z')
   128                         continue;
   129                     if (*p >= '0' && *p <= '9')
   130                         continue;
   131                     throw invalid_argument("invalid hex digits in fingerprint");
   132                 }
   133             }
   134             if (ident->UserId)
   135                 _user_id = utf8_string(ident->UserId);
   136             if (ident->UserName)
   137                 _username = utf8_string(ident->UserName);
   138 
   139             _ident = ::new_identity(_address.c_str(), _fpr.c_str(), _user_id.c_str(), _username.c_str());
   140             assert(_ident);
   141             if (_ident == NULL)
   142                 throw bad_alloc();
   143 
   144             _ident->comm_type = (PEP_comm_type) ident->CommType;
   145 
   146             if (ident->Lang) {
   147                 string _lang = utf8_string(ident->Lang);
   148                 if (_lang.length() != 0) {
   149                     if (_lang.length() != 2) {
   150                         ::free_identity(_ident);
   151                         throw invalid_argument("invalid language code");
   152                     }
   153                     if (_lang[0] < 'a' || _lang[0] > 'z') {
   154                         ::free_identity(_ident);
   155                         throw invalid_argument("invalid language code");
   156                     }
   157                     if (_lang[1] < 'a' || _lang[1] > 'z') {
   158                         ::free_identity(_ident);
   159                         throw invalid_argument("invalid language code");
   160                     }
   161                     _ident->lang[0] = _lang[0];
   162                     _ident->lang[1] = _lang[1];
   163                 }
   164             }
   165 
   166 			_ident->flags = (identity_flags_t)ident->Flags;
   167 
   168             return _ident;
   169         }
   170 
   171         template< class T2, class T > T2 from_C(T *tl);
   172 
   173         BSTR bstr(char *s)
   174         {
   175             if (s == NULL)
   176                 return _bstr_t(L"").Detach();
   177 
   178             return utf16_bstr(s);
   179         }
   180 
   181         template<> Blob *from_C< Blob *, bloblist_t >(bloblist_t *tl)
   182         {
   183 			assert(tl);
   184 
   185             CComSafeArray<BYTE> sa;
   186 			if (tl) {
   187 				sa.Create(tl->size);
   188 				if (tl->size) {
   189 					char *data;
   190 					SafeArrayAccessData(sa, (void **)&data);
   191 					memcpy(data, tl->value, tl->size);
   192 					SafeArrayUnaccessData(sa);
   193 				}
   194 			}
   195 			else {
   196 				sa.Create((ULONG)0);
   197 			}
   198 
   199             Blob *_blob = new Blob();
   200 
   201             _blob->value = sa.Detach();
   202             _blob->MimeType = bstr(tl->mime_type);
   203             _blob->Filename = bstr(tl->filename);
   204 
   205             return _blob;
   206         }
   207 
   208         template<> BlobEx *from_C< BlobEx *, bloblist_t >(bloblist_t *tl)
   209         {
   210             assert(tl);
   211 
   212             CComSafeArray<BYTE> sa;
   213             if (tl) {
   214                 sa.Create(tl->size);
   215                 if (tl->size) {
   216                     char *data;
   217                     SafeArrayAccessData(sa, (void **)&data);
   218                     memcpy(data, tl->value, tl->size);
   219                     SafeArrayUnaccessData(sa);
   220                 }
   221             }
   222             else {
   223                 sa.Create((ULONG)0);
   224             }
   225 
   226             BlobEx *_blob = new BlobEx();
   227 
   228             _blob->value = sa.Detach();
   229             _blob->MimeType = bstr(tl->mime_type);
   230             _blob->Filename = bstr(tl->filename);
   231             _blob->ContentId = bstr(tl->content_id);
   232 
   233             return _blob;
   234         }
   235 
   236         template< class T > int length(T *);
   237 
   238         template< class T2, class T > SAFEARRAY * array_from_C(T *tl)
   239         {
   240             if (tl == NULL)
   241                 return newSafeArray<T2>(0);
   242 
   243             int len = length<T>(tl);
   244 
   245             LPSAFEARRAY sa = newSafeArray<T2>(len);
   246             LONG lbound, ubound;
   247             SafeArrayGetLBound(sa, 1, &lbound);
   248             SafeArrayGetUBound(sa, 1, &ubound);
   249 
   250             T *_tl = tl;
   251             for (LONG i = lbound; i <= ubound; _tl = _tl->next, i++)
   252                 SafeArrayPutElement(sa, &i, from_C<T2 *, T>(_tl));
   253 
   254             return sa;
   255         }
   256 
   257         void clear_identity_s(pEpIdentity& ident)
   258         {
   259             SysFreeString(ident.Address);
   260             SysFreeString(ident.Fpr);
   261             SysFreeString(ident.Lang);
   262             SysFreeString(ident.UserName);
   263             SysFreeString(ident.UserId);
   264 
   265             memset(&ident, 0, sizeof(pEpIdentity));
   266         }
   267 
   268         template<> pEpIdentity from_C< pEpIdentity, pEp_identity >(pEp_identity *tl)
   269         {
   270             pEpIdentity _ident;
   271             memset(&_ident, 0, sizeof(_ident));
   272 
   273             if (tl)
   274                 copy_identity(&_ident, tl);
   275             return _ident;
   276         }
   277 
   278         pEpIdentity identity_s(pEp_identity *ident)
   279         {
   280             return from_C< pEpIdentity, pEp_identity >(ident);
   281         }
   282 
   283         template<> pEpIdentity *from_C< pEpIdentity *, identity_list >(identity_list *il)
   284         {
   285             pEpIdentity *ident = new pEpIdentity();
   286             memset(ident, 0, sizeof(pEpIdentity));
   287 
   288             if (il)
   289                 copy_identity(ident, il->ident);
   290             return ident;
   291         }
   292 
   293         template<> StringPair *from_C< StringPair *, stringpair_list_t >(stringpair_list_t * sp)
   294         {
   295             StringPair *fld = new StringPair();
   296             if (sp) {
   297                 fld->Name = bstr(sp->value->key);
   298                 fld->Value = bstr(sp->value->value);
   299             }
   300             return fld;
   301         }
   302 
   303         template<> int length<identity_list>(identity_list *tl)
   304         {
   305             return identity_list_length(tl);
   306         }
   307 
   308         template<> int length<bloblist_t>(bloblist_t *tl)
   309         {
   310             return bloblist_length(tl);
   311         }
   312 
   313         template<> int length<stringpair_list_t>(stringpair_list_t *tl)
   314         {
   315             return stringpair_list_length(tl);
   316         }
   317 
   318         void clear_text_message(TextMessage *msg)
   319         {
   320 			assert(msg);
   321 			if (!msg)
   322 				return;
   323 
   324             SysFreeString(msg->Id);
   325             SysFreeString(msg->ShortMsg);
   326             SysFreeString(msg->LongMsg);
   327             SysFreeString(msg->LongMsgFormatted);
   328             SafeArrayDestroy(msg->Attachments);
   329             clear_identity_s(msg->From);
   330             SafeArrayDestroy(msg->To);
   331             clear_identity_s(msg->RecvBy);
   332             SafeArrayDestroy(msg->Cc);
   333             SafeArrayDestroy(msg->Bcc);
   334             SafeArrayDestroy(msg->ReplyTo);
   335             SafeArrayDestroy(msg->References);
   336             SafeArrayDestroy(msg->Keywords);
   337             SysFreeString(msg->Comments);
   338             SafeArrayDestroy(msg->OptFields);
   339 
   340             memset(msg, 0, sizeof(TextMessage));
   341         }
   342 
   343         void clear_text_message(TextMessageEx *msg)
   344         {
   345             assert(msg);
   346             if (!msg)
   347                 return;
   348 
   349             SysFreeString(msg->Id);
   350             SysFreeString(msg->ShortMsg);
   351             SysFreeString(msg->LongMsg);
   352             SysFreeString(msg->LongMsgFormatted);
   353             SafeArrayDestroy(msg->Attachments);
   354             clear_identity_s(msg->From);
   355             SafeArrayDestroy(msg->To);
   356             clear_identity_s(msg->RecvBy);
   357             SafeArrayDestroy(msg->Cc);
   358             SafeArrayDestroy(msg->Bcc);
   359             SafeArrayDestroy(msg->ReplyTo);
   360             SafeArrayDestroy(msg->References);
   361             SafeArrayDestroy(msg->Keywords);
   362             SysFreeString(msg->Comments);
   363             SafeArrayDestroy(msg->OptFields);
   364 
   365             memset(msg, 0, sizeof(TextMessage));
   366         }
   367 
   368         void text_message_from_C(TextMessage *msg2, const ::message *msg)
   369         {
   370             assert(msg2);
   371             assert(msg);
   372 
   373 			if (!msg2) {
   374 				msg2 = (TextMessage *)calloc(1, sizeof(TextMessage));
   375 				assert(msg2);
   376 				if (!msg2)
   377 					throw bad_alloc();
   378 			}
   379 			else {
   380 				clear_text_message(msg2);
   381 			}
   382 
   383 			if (!msg)
   384 				return;
   385 
   386             msg2->Dir = (pEpMsgDirection) msg->dir;
   387             msg2->Id = bstr(msg->id);
   388             msg2->ShortMsg = bstr(msg->shortmsg);
   389             msg2->LongMsg = bstr(msg->longmsg);
   390             msg2->LongMsgFormatted = bstr(msg->longmsg_formatted);
   391             msg2->Attachments = array_from_C<Blob, bloblist_t>(msg->attachments);
   392             if (msg->sent)
   393                 msg2->Sent = mktime(msg->sent);
   394             if (msg->recv)
   395                 msg2->Recv = mktime(msg->recv);
   396             msg2->From = identity_s(msg->from);
   397             msg2->To = array_from_C<pEpIdentity, identity_list>(msg->to);
   398             msg2->RecvBy = identity_s(msg->recv_by);
   399             msg2->Cc = array_from_C<pEpIdentity, identity_list>(msg->cc);
   400             msg2->Bcc = array_from_C<pEpIdentity, identity_list>(msg->bcc);
   401             msg2->ReplyTo = array_from_C<pEpIdentity, identity_list>(msg->reply_to);
   402             msg2->References = string_array(msg->references);
   403             msg2->Keywords = string_array(msg->keywords);
   404             msg2->Comments = bstr(msg->comments);
   405             msg2->OptFields = array_from_C<StringPair, stringpair_list_t>(msg->opt_fields);
   406         }
   407 
   408         void text_message_from_C(TextMessageEx *msg2, const ::message *msg)
   409         {
   410             assert(msg2);
   411             assert(msg);
   412 
   413             if (!msg2) {
   414                 msg2 = (TextMessageEx *)calloc(1, sizeof(TextMessageEx));
   415                 assert(msg2);
   416                 if (!msg2)
   417                     throw bad_alloc();
   418             }
   419             else {
   420                 clear_text_message(msg2);
   421             }
   422 
   423             if (!msg)
   424                 return;
   425 
   426             msg2->Dir = (pEpMsgDirection)msg->dir;
   427             msg2->Id = bstr(msg->id);
   428             msg2->ShortMsg = bstr(msg->shortmsg);
   429             msg2->LongMsg = bstr(msg->longmsg);
   430             msg2->LongMsgFormatted = bstr(msg->longmsg_formatted);
   431             msg2->Attachments = array_from_C<BlobEx, bloblist_t>(msg->attachments);
   432             if (msg->sent)
   433                 msg2->Sent = mktime(msg->sent);
   434             if (msg->recv)
   435                 msg2->Recv = mktime(msg->recv);
   436             msg2->From = identity_s(msg->from);
   437             msg2->To = array_from_C<pEpIdentity, identity_list>(msg->to);
   438             msg2->RecvBy = identity_s(msg->recv_by);
   439             msg2->Cc = array_from_C<pEpIdentity, identity_list>(msg->cc);
   440             msg2->Bcc = array_from_C<pEpIdentity, identity_list>(msg->bcc);
   441             msg2->ReplyTo = array_from_C<pEpIdentity, identity_list>(msg->reply_to);
   442             msg2->References = string_array(msg->references);
   443             msg2->Keywords = string_array(msg->keywords);
   444             msg2->Comments = bstr(msg->comments);
   445             msg2->OptFields = array_from_C<StringPair, stringpair_list_t>(msg->opt_fields);
   446         }
   447 
   448         char * str(BSTR s)
   449         {
   450             string str = utf8_string(s);
   451             char *_s = _strdup(str.c_str());
   452             if (_s == NULL)
   453                 throw bad_alloc();
   454 
   455             return _s;
   456         }
   457 
   458         void clear_blob(Blob& b)
   459         {
   460             SysFreeString(b.Filename);
   461             SysFreeString(b.MimeType);
   462             SafeArrayDestroy(b.value);
   463             memset(&b, 0, sizeof(Blob));
   464         }
   465 
   466         void clear_blob(BlobEx& b)
   467         {
   468             SysFreeString(b.Filename);
   469             SysFreeString(b.MimeType);
   470             SysFreeString(b.ContentId);
   471             SafeArrayDestroy(b.value);
   472             memset(&b, 0, sizeof(Blob));
   473         }
   474 
   475         bloblist_t *bloblist(SAFEARRAY *sa)
   476         {
   477             if (sa == NULL)
   478                 return NULL;
   479 
   480             LONG lbound, ubound;
   481             SafeArrayGetLBound(sa, 1, &lbound);
   482             SafeArrayGetUBound(sa, 1, &ubound);
   483 
   484             size_t size = ubound - lbound + 1;
   485             if (size <= 0)
   486                 return NULL;
   487 
   488             bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL, NULL);
   489             if (bl == NULL)
   490                 throw bad_alloc();
   491 
   492             bloblist_t *_bl = bl;
   493             for (LONG i = lbound; i <= ubound; i++) {
   494                 Blob b;
   495                 memset(&b, 0, sizeof(Blob));
   496                 SafeArrayGetElement(sa, &i, &b);
   497 
   498                 LONG _lbound, _ubound;
   499                 SafeArrayGetLBound(b.value, 1, &_lbound);
   500                 SafeArrayGetUBound(b.value, 1, &_ubound);
   501                 size_t size = _ubound - _lbound + 1;
   502 
   503                 char *buffer;
   504                 if (size) {
   505                     buffer = (char *) malloc(size + 1);
   506                     if (buffer == NULL)
   507                         throw bad_alloc();
   508 
   509                     char *data;
   510 
   511                     SafeArrayAccessData(b.value, (void **) &data);
   512                     memcpy(buffer, data, size);
   513 					buffer[size] = 0; // safeguard
   514                     SafeArrayUnaccessData(sa);
   515                 }
   516                 else {
   517                     buffer = _strdup("");
   518                     if (buffer == NULL)
   519                         throw bad_alloc();
   520 
   521                 }
   522                 _bl = bloblist_add(_bl, buffer, size, str(b.MimeType), str(b.Filename), "");
   523                 if (_bl == NULL) {
   524                     free(buffer);
   525                     clear_blob(b);
   526                     free_bloblist(bl);
   527                     throw bad_alloc();
   528                 }
   529 
   530                 clear_blob(b);
   531             }
   532 
   533             return bl;
   534         }
   535 
   536         bloblist_t *bloblistEx(SAFEARRAY *sa)
   537         {
   538             if (sa == NULL)
   539                 return NULL;
   540 
   541             LONG lbound, ubound;
   542             SafeArrayGetLBound(sa, 1, &lbound);
   543             SafeArrayGetUBound(sa, 1, &ubound);
   544 
   545             size_t size = ubound - lbound + 1;
   546             if (size <= 0)
   547                 return NULL;
   548 
   549             bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL, NULL);
   550             if (bl == NULL)
   551                 throw bad_alloc();
   552 
   553             bloblist_t *_bl = bl;
   554             for (LONG i = lbound; i <= ubound; i++) {
   555                 BlobEx b;
   556                 memset(&b, 0, sizeof(BlobEx));
   557                 SafeArrayGetElement(sa, &i, &b);
   558 
   559                 LONG _lbound, _ubound;
   560                 SafeArrayGetLBound(b.value, 1, &_lbound);
   561                 SafeArrayGetUBound(b.value, 1, &_ubound);
   562                 size_t size = _ubound - _lbound + 1;
   563 
   564                 char *buffer;
   565                 if (size) {
   566                     buffer = (char *)malloc(size + 1);
   567                     if (buffer == NULL)
   568                         throw bad_alloc();
   569 
   570                     char *data;
   571 
   572                     SafeArrayAccessData(b.value, (void **)&data);
   573                     memcpy(buffer, data, size);
   574                     buffer[size] = 0; // safeguard
   575                     SafeArrayUnaccessData(sa);
   576                 }
   577                 else {
   578                     buffer = _strdup("");
   579                     if (buffer == NULL)
   580                         throw bad_alloc();
   581 
   582                 }
   583                 _bl = bloblist_add(_bl, buffer, size, str(b.MimeType), str(b.Filename), str(b.ContentId));
   584                 if (_bl == NULL) {
   585                     free(buffer);
   586                     clear_blob(b);
   587                     free_bloblist(bl);
   588                     throw bad_alloc();
   589                 }
   590 
   591                 clear_blob(b);
   592             }
   593 
   594             return bl;
   595         }
   596 
   597         identity_list *identities(SAFEARRAY * sa)
   598         {
   599             if (sa == NULL)
   600                 return NULL;
   601 
   602             LONG lbound, ubound;
   603             SafeArrayGetLBound(sa, 1, &lbound);
   604             SafeArrayGetUBound(sa, 1, &ubound);
   605 
   606             size_t size = ubound - lbound + 1;
   607             if (size <= 0)
   608                 return NULL;
   609 
   610             identity_list *il = new_identity_list(NULL);
   611 
   612             identity_list *_il = il;
   613             for (LONG i = lbound; i <= ubound; i++) {
   614                 pEpIdentity s;
   615                 memset(&s, 0, sizeof(pEpIdentity));
   616                 SafeArrayGetElement(sa, &i, &s);
   617 
   618                 pEp_identity *ident;
   619                 try {
   620                     ident = new_identity(&s);
   621                 }
   622                 catch (bad_alloc&) {
   623                     clear_identity_s(s);
   624                     throw bad_alloc();
   625                 }
   626 
   627                 clear_identity_s(s);
   628 
   629                 _il = identity_list_add(_il, ident);
   630                 if (_il == NULL) {
   631                     free_identity_list(il);
   632                     throw bad_alloc();
   633                 }
   634             }
   635 
   636             return il;
   637         }
   638 
   639         stringpair_t *new_stringpair(StringPair *fld)
   640         {
   641 			stringpair_t *pair;
   642 
   643 			if (!fld) {
   644 				pair = ::new_stringpair(NULL, NULL);
   645 			}
   646 			else {
   647 				pair = ::new_stringpair(str(fld->Name), str(fld->Value));
   648 			}
   649             if (pair == NULL)
   650                 throw bad_alloc();
   651 
   652             return pair;
   653         }
   654 
   655         void clear_opt_field(StringPair& f)
   656         {
   657             SysFreeString(f.Name);
   658             SysFreeString(f.Value);
   659             memset(&f, 0, sizeof(StringPair));
   660         }
   661 
   662         stringpair_list_t *stringpair_list(SAFEARRAY * sa)
   663         {
   664             if (sa == NULL)
   665                 return NULL;
   666 
   667             LONG lbound, ubound;
   668             SafeArrayGetLBound(sa, 1, &lbound);
   669             SafeArrayGetUBound(sa, 1, &ubound);
   670 
   671             size_t size = ubound - lbound + 1;
   672             if (size <= 0)
   673                 return NULL;
   674 
   675             stringpair_list_t *il = new_stringpair_list(NULL);
   676 
   677             stringpair_list_t *_il = il;
   678             for (LONG i = lbound; i <= ubound; i++) {
   679                 StringPair s;
   680                 memset(&s, 0, sizeof(StringPair));
   681                 SafeArrayGetElement(sa, &i, &s);
   682 
   683                 stringpair_t *pair;
   684                 try {
   685                     pair = new_stringpair(&s);
   686                 }
   687                 catch (bad_alloc&) {
   688                     clear_opt_field(s);
   689                     throw bad_alloc();
   690                 }
   691 
   692                 clear_opt_field(s);
   693 
   694                 _il = stringpair_list_add(_il, pair);
   695                 if (_il == NULL) {
   696                     free_stringpair_list(il);
   697                     throw bad_alloc();
   698                 }
   699             }
   700 
   701             return il;
   702         }
   703         
   704         ::message * text_message_to_C(TextMessage *msg)
   705         {
   706             assert(msg);
   707 			if (!msg)
   708 				throw invalid_argument("msg");
   709 
   710             ::message * msg2 = new_message((PEP_msg_direction) msg->Dir);
   711             if (msg2 == NULL)
   712                 throw bad_alloc();
   713 
   714             msg2->id = str(msg->Id);
   715             msg2->shortmsg = str(msg->ShortMsg);
   716             msg2->longmsg = str(msg->LongMsg);
   717             msg2->longmsg_formatted = str(msg->LongMsgFormatted);
   718             msg2->attachments = bloblist(msg->Attachments);
   719             msg2->sent = new_timestamp(msg->Sent);
   720             msg2->recv = new_timestamp(msg->Recv);
   721             msg2->from = new_identity(&msg->From);
   722             msg2->to = identities(msg->To);
   723             msg2->recv_by = new_identity(&msg->RecvBy);
   724             msg2->cc = identities(msg->Cc);
   725             msg2->bcc = identities(msg->Bcc);
   726             msg2->reply_to = identities(msg->ReplyTo);
   727             msg2->references = new_stringlist(msg->References);
   728             msg2->keywords = new_stringlist(msg->Keywords);
   729             msg2->comments = str(msg->Comments);
   730             msg2->opt_fields = stringpair_list(msg->OptFields);
   731 
   732             return msg2;
   733         }
   734 
   735         ::message * text_message_to_C(TextMessageEx *msg)
   736         {
   737             assert(msg);
   738             if (!msg)
   739                 throw invalid_argument("msg");
   740 
   741             ::message * msg2 = new_message((PEP_msg_direction)msg->Dir);
   742             if (msg2 == NULL)
   743                 throw bad_alloc();
   744 
   745             msg2->id = str(msg->Id);
   746             msg2->shortmsg = str(msg->ShortMsg);
   747             msg2->longmsg = str(msg->LongMsg);
   748             msg2->longmsg_formatted = str(msg->LongMsgFormatted);
   749             msg2->attachments = bloblistEx(msg->Attachments);
   750             msg2->sent = new_timestamp(msg->Sent);
   751             msg2->recv = new_timestamp(msg->Recv);
   752             msg2->from = new_identity(&msg->From);
   753             msg2->to = identities(msg->To);
   754             msg2->recv_by = new_identity(&msg->RecvBy);
   755             msg2->cc = identities(msg->Cc);
   756             msg2->bcc = identities(msg->Bcc);
   757             msg2->reply_to = identities(msg->ReplyTo);
   758             msg2->references = new_stringlist(msg->References);
   759             msg2->keywords = new_stringlist(msg->Keywords);
   760             msg2->comments = str(msg->Comments);
   761             msg2->opt_fields = stringpair_list(msg->OptFields);
   762 
   763             return msg2;
   764         }
   765 
   766 		void opt_field_array_from_C(stringpair_list_t* spair_list, LPSAFEARRAY* pair_list_out) {
   767 			assert(spair_list);
   768 			assert(pair_list_out);
   769 			
   770 			if (!spair_list)
   771 				return;
   772 
   773 			*pair_list_out = array_from_C<StringPair, stringpair_list_t>(spair_list);
   774 		}
   775 
   776 		void clear_opt_field_array(LPSAFEARRAY* opt_field_array) {
   777 			if (opt_field_array){
   778 				SafeArrayDestroy(*opt_field_array);
   779 				*opt_field_array = NULL;
   780 			}
   781 		}
   782     }
   783 }