p≡p COM server adapter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

598 lines
19 KiB

#include "stdafx.h"
#include "pEp_utility.h"
using namespace ATL;
namespace pEp {
namespace utility {
pEp_identity_cpp::pEp_identity_cpp(const ::pEp_identity *_ident)
{
if (!_ident)
return;
if (_ident->address)
address = _ident->address;
if (_ident->fpr)
fpr = _ident->fpr;
if (_ident->user_id)
user_id = _ident->user_id;
if (_ident->username)
username = _ident->username;
comm_type = (pEpComType)_ident->comm_type;
lang = _ident->lang;
me = _ident->me;
flags = (int)_ident->flags;
}
pEp_identity_cpp::pEp_identity_cpp(const pEpIdentity *_ident)
{
if (!_ident)
return;
if (_ident->Address)
address = utf8_string(_ident->Address);
if (_ident->Fpr)
fpr = utf8_string(_ident->Fpr);
if (_ident->UserId)
user_id = utf8_string(_ident->UserId);
if (_ident->UserName)
username = utf8_string(_ident->UserName);
comm_type = _ident->CommType;
if (_ident->Lang)
lang = utf8_string(_ident->Lang);
me = _ident->UserName;
flags = (int)_ident->Flags;
}
pEp_identity * pEp_identity_cpp::to_pEp_identity()
{
::pEp_identity *_ident = ::new_identity(this->address.c_str(), this->fpr.c_str(), this->user_id.c_str(), this->username.c_str());
assert(_ident);
if (_ident == NULL)
throw bad_alloc();
_ident->comm_type = (::PEP_comm_type) this->comm_type;
assert(this->lang.size() == 0 || this->lang.size() == 2);
if (this->lang.size()) {
_ident->lang[0] = this->lang[0];
_ident->lang[1] = this->lang[1];
}
_ident->me = this->me;
_ident->flags = (identity_flags) this->flags;
return _ident;
}
pEpIdentity * pEp_identity_cpp::to_pEp_identity_s()
{
pEpIdentity *_ident = (pEpIdentity *)calloc(1, sizeof(pEpIdentity));
assert(_ident);
if (_ident == NULL)
throw bad_alloc();
_ident->Address = utf16_bstr(this->address);
_ident->CommType = this->comm_type;
_ident->Fpr = utf16_bstr(this->fpr);
_ident->Lang = utf16_bstr(this->lang);
_ident->UserName = utf16_bstr(this->username);
_ident->UserId = utf16_bstr(this->user_id);
_ident->Me = this->me;
_ident->Flags = (pEpIdentityFlags) this->flags;
return _ident;
}
void copy_identity(pEpIdentity * ident_s, const pEp_identity * ident)
{
assert(ident_s);
if (!ident_s)
throw invalid_argument("ident_s");
::memset(ident_s, 0, sizeof(pEpIdentity));
if (ident) {
if (ident->address)
ident_s->Address = utf16_bstr(ident->address);
if (ident->fpr)
ident_s->Fpr = utf16_bstr(ident->fpr);
if (ident->user_id)
ident_s->UserId = utf16_bstr(ident->user_id);
if (ident->username)
ident_s->UserName = utf16_bstr(ident->username);
ident_s->CommType = (pEpComType)ident->comm_type;
if (ident->lang)
ident_s->Lang = utf16_bstr(ident->lang);
ident_s->Me = ident->me;
ident_s->Flags = (pEpIdentityFlags)ident->flags;
}
}
::pEp_identity *new_identity(const pEpIdentity * ident)
{
if (ident == NULL)
return NULL;
::pEp_identity *_ident;
string _address;
string _fpr;
string _user_id;
string _username;
if (ident->Address)
_address = utf8_string(ident->Address);
if (ident->Fpr) {
_fpr = utf8_string(ident->Fpr);
for (auto p = _fpr.begin(); p != _fpr.end(); ++p) {
if (*p >= 'A' && *p <= 'Z')
continue;
if (*p >= '0' && *p <= '9')
continue;
throw invalid_argument("invalid hex digits in fingerprint");
}
}
if (ident->UserId)
_user_id = utf8_string(ident->UserId);
if (ident->UserName)
_username = utf8_string(ident->UserName);
_ident = ::new_identity(_address.c_str(), _fpr.c_str(), _user_id.c_str(), _username.c_str());
assert(_ident);
if (_ident == NULL)
throw bad_alloc();
_ident->comm_type = (PEP_comm_type)ident->CommType;
if (ident->Lang) {
string _lang = utf8_string(ident->Lang);
if (_lang.length() != 0) {
if (_lang.length() != 2) {
::free_identity(_ident);
throw invalid_argument("invalid language code");
}
if (_lang[0] < 'a' || _lang[0] > 'z') {
::free_identity(_ident);
throw invalid_argument("invalid language code");
}
if (_lang[1] < 'a' || _lang[1] > 'z') {
::free_identity(_ident);
throw invalid_argument("invalid language code");
}
_ident->lang[0] = _lang[0];
_ident->lang[1] = _lang[1];
}
}
_ident->me = ident->Me;
_ident->flags = (identity_flags_t)ident->Flags;
return _ident;
}
template< class T2, class T > T2 from_C(T *tl);
BSTR bstr(char *s)
{
if (s == NULL)
return _bstr_t(L"").Detach();
return utf16_bstr(s);
}
template<> Blob *from_C< Blob *, bloblist_t >(bloblist_t *tl)
{
assert(tl);
CComSafeArray<BYTE> sa;
if (tl) {
sa.Create(tl->size);
if (tl->size) {
char *data;
SafeArrayAccessData(sa, (void **)&data);
memcpy(data, tl->value, tl->size);
SafeArrayUnaccessData(sa);
}
}
else {
sa.Create((ULONG)0);
}
Blob *_blob = new Blob();
_blob->value = sa.Detach();
_blob->MimeType = bstr(tl->mime_type);
_blob->Filename = bstr(tl->filename);
return _blob;
}
template< class T > int length(T *);
template< class T2, class T > SAFEARRAY * array_from_C(T *tl)
{
if (tl == NULL)
return newSafeArray<T2>(0);
int len = length<T>(tl);
LPSAFEARRAY sa = newSafeArray<T2>(len);
LONG lbound, ubound;
SafeArrayGetLBound(sa, 1, &lbound);
SafeArrayGetUBound(sa, 1, &ubound);
T *_tl = tl;
for (LONG i = lbound; i <= ubound; _tl = _tl->next, i++) {
HRESULT result = SafeArrayPutElement(sa, &i, from_C<T2 *, T>(_tl));
if (!SUCCEEDED(result))
throw bad_alloc();
}
return sa;
}
void clear_identity_s(pEpIdentity& ident)
{
SysFreeString(ident.Address);
SysFreeString(ident.Fpr);
SysFreeString(ident.Lang);
SysFreeString(ident.UserName);
SysFreeString(ident.UserId);
memset(&ident, 0, sizeof(pEpIdentity));
}
template<> pEpIdentity from_C< pEpIdentity, pEp_identity >(pEp_identity *tl)
{
pEpIdentity _ident;
memset(&_ident, 0, sizeof(_ident));
if (tl)
copy_identity(&_ident, tl);
return _ident;
}
pEpIdentity identity_s(pEp_identity *ident)
{
return from_C< pEpIdentity, pEp_identity >(ident);
}
template<> pEpIdentity *from_C< pEpIdentity *, identity_list >(identity_list *il)
{
pEpIdentity *ident = new pEpIdentity();
memset(ident, 0, sizeof(pEpIdentity));
if (il)
copy_identity(ident, il->ident);
return ident;
}
template<> StringPair *from_C< StringPair *, stringpair_list_t >(stringpair_list_t * sp)
{
StringPair *fld = new StringPair();
if (sp) {
fld->Name = bstr(sp->value->key);
fld->Value = bstr(sp->value->value);
}
return fld;
}
template<> int length<identity_list>(identity_list *tl)
{
return identity_list_length(tl);
}
template<> int length<bloblist_t>(bloblist_t *tl)
{
return bloblist_length(tl);
}
template<> int length<stringpair_list_t>(stringpair_list_t *tl)
{
return stringpair_list_length(tl);
}
void clear_text_message(TextMessage *msg)
{
assert(msg);
if (!msg)
return;
SysFreeString(msg->Id);
SysFreeString(msg->ShortMsg);
SysFreeString(msg->LongMsg);
SysFreeString(msg->LongMsgFormatted);
SafeArrayDestroy(msg->Attachments);
clear_identity_s(msg->From);
SafeArrayDestroy(msg->To);
clear_identity_s(msg->RecvBy);
SafeArrayDestroy(msg->Cc);
SafeArrayDestroy(msg->Bcc);
SafeArrayDestroy(msg->ReplyTo);
SafeArrayDestroy(msg->References);
SafeArrayDestroy(msg->Keywords);
SysFreeString(msg->Comments);
SafeArrayDestroy(msg->OptFields);
memset(msg, 0, sizeof(TextMessage));
}
void text_message_from_C(TextMessage *msg2, const ::message *msg)
{
assert(msg2);
assert(msg);
if (!msg2) {
msg2 = (TextMessage *)calloc(1, sizeof(TextMessage));
assert(msg2);
if (!msg2)
throw bad_alloc();
}
else {
clear_text_message(msg2);
}
if (!msg)
return;
msg2->Dir = (pEpMsgDirection)msg->dir;
msg2->Id = bstr(msg->id);
msg2->ShortMsg = bstr(msg->shortmsg);
msg2->LongMsg = bstr(msg->longmsg);
msg2->LongMsgFormatted = bstr(msg->longmsg_formatted);
msg2->Attachments = array_from_C<Blob, bloblist_t>(msg->attachments);
if (msg->sent)
msg2->Sent = timegm(msg->sent);
if (msg->recv)
msg2->Recv = timegm(msg->recv);
msg2->From = identity_s(msg->from);
msg2->To = array_from_C<pEpIdentity, identity_list>(msg->to);
msg2->RecvBy = identity_s(msg->recv_by);
msg2->Cc = array_from_C<pEpIdentity, identity_list>(msg->cc);
msg2->Bcc = array_from_C<pEpIdentity, identity_list>(msg->bcc);
msg2->ReplyTo = array_from_C<pEpIdentity, identity_list>(msg->reply_to);
msg2->References = string_array(msg->references);
msg2->Keywords = string_array(msg->keywords);
msg2->Comments = bstr(msg->comments);
msg2->OptFields = array_from_C<StringPair, stringpair_list_t>(msg->opt_fields);
msg2->EncFormat = (pEpEncFormat)msg->enc_format;
msg2->SenderFpr = bstr(msg->_sender_fpr);
}
char * str(BSTR s)
{
string str = utf8_string(s);
char *_s = _strdup(str.c_str());
if (_s == NULL)
throw bad_alloc();
return _s;
}
void clear_blob(Blob& b)
{
SysFreeString(b.Filename);
SysFreeString(b.MimeType);
SafeArrayDestroy(b.value);
memset(&b, 0, sizeof(Blob));
}
bloblist_t *bloblist(SAFEARRAY *sa)
{
if (sa == NULL)
return NULL;
LONG lbound, ubound;
SafeArrayGetLBound(sa, 1, &lbound);
SafeArrayGetUBound(sa, 1, &ubound);
size_t size = ubound - lbound + 1;
if (size <= 0)
return NULL;
bloblist_t *bl = new_bloblist(NULL, 0, NULL, NULL);
if (bl == NULL)
throw bad_alloc();
bloblist_t *_bl = bl;
for (LONG i = lbound; i <= ubound; i++) {
Blob b;
memset(&b, 0, sizeof(Blob));
SafeArrayGetElement(sa, &i, &b);
LONG _lbound, _ubound;
SafeArrayGetLBound(b.value, 1, &_lbound);
SafeArrayGetUBound(b.value, 1, &_ubound);
size_t size = _ubound - _lbound + 1;
char *buffer;
if (size) {
buffer = (char *)malloc(size + 1);
if (buffer == NULL)
throw bad_alloc();
char *data;
SafeArrayAccessData(b.value, (void **)&data);
memcpy(buffer, data, size);
buffer[size] = 0; // safeguard
SafeArrayUnaccessData(sa);
}
else {
buffer = _strdup("");
if (buffer == NULL)
throw bad_alloc();
}
_bl = bloblist_add(_bl, buffer, size, str(b.MimeType), str(b.Filename));
if (_bl == NULL) {
free(buffer);
clear_blob(b);
free_bloblist(bl);
throw bad_alloc();
}
clear_blob(b);
}
return bl;
}
identity_list *identities(SAFEARRAY * sa)
{
if (sa == NULL)
return NULL;
LONG lbound, ubound;
SafeArrayGetLBound(sa, 1, &lbound);
SafeArrayGetUBound(sa, 1, &ubound);
size_t size = ubound - lbound + 1;
if (size <= 0)
return NULL;
identity_list *il = new_identity_list(NULL);
identity_list *_il = il;
for (LONG i = lbound; i <= ubound; i++) {
pEpIdentity s;
memset(&s, 0, sizeof(pEpIdentity));
SafeArrayGetElement(sa, &i, &s);
pEp_identity *ident;
try {
ident = new_identity(&s);
}
catch (bad_alloc&) {
clear_identity_s(s);
throw bad_alloc();
}
clear_identity_s(s);
_il = identity_list_add(_il, ident);
if (_il == NULL) {
free_identity_list(il);
throw bad_alloc();
}
}
return il;
}
stringpair_t *new_stringpair(StringPair *fld)
{
stringpair_t *pair;
if (!fld) {
pair = ::new_stringpair(NULL, NULL);
}
else {
pair = ::new_stringpair(str(fld->Name), str(fld->Value));
}
if (pair == NULL)
throw bad_alloc();
return pair;
}
void clear_opt_field(StringPair& f)
{
SysFreeString(f.Name);
SysFreeString(f.Value);
memset(&f, 0, sizeof(StringPair));
}
stringpair_list_t *stringpair_list(SAFEARRAY * sa)
{
if (sa == NULL)
return NULL;
LONG lbound, ubound;
SafeArrayGetLBound(sa, 1, &lbound);
SafeArrayGetUBound(sa, 1, &ubound);
size_t size = ubound - lbound + 1;
if (size <= 0)
return NULL;
stringpair_list_t *il = new_stringpair_list(NULL);
stringpair_list_t *_il = il;
for (LONG i = lbound; i <= ubound; i++) {
StringPair s;
memset(&s, 0, sizeof(StringPair));
SafeArrayGetElement(sa, &i, &s);
stringpair_t *pair;
try {
pair = new_stringpair(&s);
}
catch (bad_alloc&) {
clear_opt_field(s);
throw bad_alloc();
}
clear_opt_field(s);
_il = stringpair_list_add(_il, pair);
if (_il == NULL) {
free_stringpair_list(il);
throw bad_alloc();
}
}
return il;
}
::message * text_message_to_C(TextMessage *msg)
{
assert(msg);
if (!msg)
throw invalid_argument("msg");
::message * msg2 = new_message((PEP_msg_direction)msg->Dir);
if (msg2 == NULL)
throw bad_alloc();
msg2->id = str(msg->Id);
msg2->shortmsg = str(msg->ShortMsg);
msg2->longmsg = str(msg->LongMsg);
msg2->longmsg_formatted = str(msg->LongMsgFormatted);
msg2->attachments = bloblist(msg->Attachments);
msg2->sent = new_timestamp(msg->Sent);
msg2->recv = new_timestamp(msg->Recv);
msg2->from = new_identity(&msg->From);
msg2->to = identities(msg->To);
msg2->recv_by = new_identity(&msg->RecvBy);
msg2->cc = identities(msg->Cc);
msg2->bcc = identities(msg->Bcc);
msg2->reply_to = identities(msg->ReplyTo);
msg2->references = new_stringlist(msg->References);
msg2->keywords = new_stringlist(msg->Keywords);
msg2->comments = str(msg->Comments);
msg2->opt_fields = stringpair_list(msg->OptFields);
msg2->enc_format = (PEP_enc_format)msg->EncFormat;
return msg2;
}
void opt_field_array_from_C(stringpair_list_t* spair_list, LPSAFEARRAY* pair_list_out) {
assert(spair_list);
assert(pair_list_out);
if (!spair_list)
return;
*pair_list_out = array_from_C<StringPair, stringpair_list_t>(spair_list);
}
void clear_opt_field_array(LPSAFEARRAY* opt_field_array) {
if (opt_field_array) {
SafeArrayDestroy(*opt_field_array);
*opt_field_array = NULL;
}
}
}
}