CpEpEngine.cpp
author Volker Birk <vb@pep-project.org>
Thu, 16 Apr 2015 20:43:31 +0200
changeset 0 0aa9866d751c
child 4 fdd8cf02d2cc
permissions -rw-r--r--
initial commit
vb@0
     1
// CpEpEngine.cpp : Implementation of CpEpEngine
vb@0
     2
vb@0
     3
#include "stdafx.h"
vb@0
     4
#include "CpEpEngine.h"
vb@0
     5
vb@0
     6
vb@0
     7
// CpEpEngine
vb@0
     8
vb@0
     9
STDMETHODIMP CpEpEngine::InterfaceSupportsErrorInfo(REFIID riid)
vb@0
    10
{
vb@0
    11
	static const IID* const arr[] = 
vb@0
    12
	{
vb@0
    13
		&IID_IpEpEngine
vb@0
    14
	};
vb@0
    15
vb@0
    16
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
vb@0
    17
	{
vb@0
    18
		if (InlineIsEqualGUID(*arr[i],riid))
vb@0
    19
			return S_OK;
vb@0
    20
	}
vb@0
    21
	return S_FALSE;
vb@0
    22
}
vb@0
    23
vb@0
    24
#define FAIL(msg) error(msg)
vb@0
    25
vb@0
    26
using namespace std;
vb@0
    27
vb@0
    28
static CComSafeArray<BSTR> string_array(const ::stringlist_t *stringlist)
vb@0
    29
{
vb@0
    30
    CComSafeArray<BSTR> sa_string_list;
vb@0
    31
    int n = 0;
vb@0
    32
    for (const ::stringlist_t *k = stringlist; k != NULL; k = k->next) {
vb@0
    33
        if (k->value) {
vb@0
    34
            HRESULT _result = sa_string_list.Add(utf16_bstr(k->value).Detach(), false);
vb@0
    35
            assert(_result == S_OK);
vb@0
    36
            if (_result == E_OUTOFMEMORY)
vb@0
    37
                throw std::bad_alloc();
vb@0
    38
            ++n;
vb@0
    39
        }
vb@0
    40
    }
vb@0
    41
vb@0
    42
    return sa_string_list;
vb@0
    43
}
vb@0
    44
vb@0
    45
static ::stringlist_t * new_stringlist(const SAFEARRAY * safearray)
vb@0
    46
{
vb@0
    47
    CComSafeArray<BSTR> sa(safearray);
vb@0
    48
    int n_strings = 0;
vb@0
    49
    ::stringlist_t *_stringlist = ::new_stringlist((const char *) NULL);
vb@0
    50
    assert(_stringlist);
vb@0
    51
    if (_stringlist == NULL)
vb@0
    52
        throw std::bad_alloc();
vb@0
    53
vb@0
    54
    n_strings = sa.GetUpperBound() - sa.GetLowerBound() + 1;
vb@0
    55
    ::stringlist_t *k = _stringlist;
vb@0
    56
    for (int i = 0, j = sa.GetLowerBound(); i<n_strings; ++i, ++j) {
vb@0
    57
        k = ::stringlist_add(k, utf8_string(sa.GetAt(j)).c_str());
vb@0
    58
        assert(k);
vb@0
    59
        if (k == NULL) {
vb@0
    60
            ::free_stringlist(_stringlist);
vb@0
    61
            throw std::bad_alloc();
vb@0
    62
        }
vb@0
    63
    }
vb@0
    64
vb@0
    65
    return _stringlist;
vb@0
    66
}
vb@0
    67
vb@0
    68
static ::pEp_identity *new_identity(const pEp_identity_s * ident)
vb@0
    69
{
vb@0
    70
    ::pEp_identity *_ident;
vb@0
    71
vb@0
    72
    string _address;
vb@0
    73
    string _fpr;
vb@0
    74
    string _user_id;
vb@0
    75
    string _username;
vb@0
    76
vb@0
    77
    if (ident->address)
vb@0
    78
        _address = utf8_string(ident->address);
vb@0
    79
    if (ident->fpr) {
vb@0
    80
        _fpr = utf8_string(ident->fpr);
vb@0
    81
        for (auto p = _fpr.begin(); p != _fpr.end(); ++p) {
vb@0
    82
            if (*p >= 'A' && *p <= 'Z')
vb@0
    83
                continue;
vb@0
    84
            if (*p >= '0' && *p <= '9')
vb@0
    85
                continue;
vb@0
    86
            throw invalid_argument("invalid hex digits in fingerprint");
vb@0
    87
        }
vb@0
    88
    }
vb@0
    89
    if (ident->user_id)
vb@0
    90
        _user_id = utf8_string(ident->user_id);
vb@0
    91
    if (ident->username)
vb@0
    92
        _username = utf8_string(ident->username);
vb@0
    93
vb@0
    94
    _ident = ::new_identity(_address.c_str(), _fpr.c_str(), _user_id.c_str(), _username.c_str());
vb@0
    95
    assert(_ident);
vb@0
    96
    if (_ident == NULL)
vb@0
    97
        throw bad_alloc();
vb@0
    98
vb@0
    99
    _ident->comm_type = (PEP_comm_type) ident->comm_type;
vb@0
   100
vb@0
   101
    if (ident->lang) {
vb@0
   102
        string _lang = utf8_string(ident->lang);
vb@0
   103
        if (_lang.length() != 0) {
vb@0
   104
            if (_lang.length() != 2) {
vb@0
   105
                ::free_identity(_ident);
vb@0
   106
                throw invalid_argument("invalid language code");
vb@0
   107
            }
vb@0
   108
            if (_lang[0] < 'a' || _lang[0] > 'z') {
vb@0
   109
                ::free_identity(_ident);
vb@0
   110
                throw invalid_argument("invalid language code");
vb@0
   111
            }
vb@0
   112
            if (_lang[1] < 'a' || _lang[1] > 'z') {
vb@0
   113
                ::free_identity(_ident);
vb@0
   114
                throw invalid_argument("invalid language code");
vb@0
   115
            }
vb@0
   116
            _ident->lang[0] = _lang[0];
vb@0
   117
            _ident->lang[1] = _lang[1];
vb@0
   118
        }
vb@0
   119
    }
vb@0
   120
vb@0
   121
    return _ident;
vb@0
   122
}
vb@0
   123
vb@0
   124
static void copy_identity(pEp_identity_s * ident_s, const pEp_identity * ident)
vb@0
   125
{
vb@0
   126
    ::memset(ident_s, 0, sizeof(pEp_identity_s));
vb@0
   127
vb@0
   128
    if (ident->address)
vb@0
   129
        ident_s->address = utf16_bstr(ident->address).Detach();
vb@0
   130
    if (ident->fpr)
vb@0
   131
        ident_s->fpr = utf16_bstr(ident->fpr).Detach();
vb@0
   132
    if (ident->user_id)
vb@0
   133
        ident_s->user_id = utf16_bstr(ident->user_id).Detach();
vb@0
   134
    if (ident->username)
vb@0
   135
        ident_s->username = utf16_bstr(ident->username).Detach();
vb@0
   136
    ident_s->comm_type = (pEp_comm_type) ident->comm_type;
vb@0
   137
    if (ident->lang)
vb@0
   138
        ident_s->lang = utf16_bstr(ident->lang).Detach();
vb@0
   139
}
vb@0
   140
vb@0
   141
// CpEpEngine
vb@0
   142
vb@0
   143
::pEp_identity *CpEpEngine::new_identity(const CpEpEngine::pEp_identity_cpp& ident)
vb@0
   144
{
vb@0
   145
    ::pEp_identity *_ident = ::new_identity(ident.address.c_str(), ident.fpr.c_str(), ident.user_id.c_str(), ident.username.c_str());
vb@0
   146
    assert(_ident);
vb@0
   147
    if (_ident == NULL)
vb@0
   148
        throw bad_alloc();
vb@0
   149
vb@0
   150
    _ident->comm_type = (::PEP_comm_type) ident.comm_type;
vb@0
   151
    _ident->me = ident.me;
vb@0
   152
vb@0
   153
    assert(ident.lang.size() == 0 || ident.lang.size() == 2);
vb@0
   154
vb@0
   155
    if (ident.lang.size()) {
vb@0
   156
        _ident->lang[0] = ident.lang[0];
vb@0
   157
        _ident->lang[1] = ident.lang[1];
vb@0
   158
    }
vb@0
   159
vb@0
   160
    return _ident;
vb@0
   161
}
vb@0
   162
vb@0
   163
STDMETHODIMP CpEpEngine::log(BSTR title, BSTR entity, BSTR description, BSTR comment)
vb@0
   164
{
vb@0
   165
    string _title;
vb@0
   166
    string _entity;
vb@0
   167
    string _description;
vb@0
   168
    string _comment;
vb@0
   169
    HRESULT result = S_OK;
vb@0
   170
vb@0
   171
    assert(title);
vb@0
   172
    if (title)
vb@0
   173
        _title = utf8_string(title);
vb@0
   174
    else
vb@0
   175
        result = E_INVALIDARG;
vb@0
   176
vb@0
   177
    assert(entity);
vb@0
   178
    if (entity)
vb@0
   179
        _entity = utf8_string(entity);
vb@0
   180
    else
vb@0
   181
        result = E_INVALIDARG;
vb@0
   182
vb@0
   183
    if (description)
vb@0
   184
        _description = utf8_string(description);
vb@0
   185
vb@0
   186
    if (comment)
vb@0
   187
        _comment = utf8_string(comment);
vb@0
   188
vb@0
   189
    if (result != S_OK)
vb@0
   190
        return result;
vb@0
   191
vb@0
   192
    PEP_STATUS _status = ::log_event(get_session(), _title.c_str(), _entity.c_str(), _description.c_str(), _comment.c_str());
vb@0
   193
    assert(_status == PEP_STATUS_OK);
vb@0
   194
    if (_status != PEP_STATUS_OK)
vb@0
   195
        return FAIL(L"log_event");
vb@0
   196
    else
vb@0
   197
        return S_OK;
vb@0
   198
}
vb@0
   199
vb@0
   200
vb@0
   201
STDMETHODIMP CpEpEngine::decrypt(BSTR ctext, BSTR * ptext, LPSAFEARRAY * key_list, pEp_STATUS * status)
vb@0
   202
{
vb@0
   203
    assert(ctext);
vb@0
   204
    assert(ptext);
vb@0
   205
    assert(key_list);
vb@0
   206
    assert(status);
vb@0
   207
vb@0
   208
    if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
vb@0
   209
        if (ptext)
vb@0
   210
            *ptext = NULL;
vb@0
   211
        if (key_list)
vb@0
   212
            *key_list = NULL;
vb@0
   213
        if (status)
vb@0
   214
            *status = pEp_UNENCRYPTED;
vb@0
   215
        return E_INVALIDARG;
vb@0
   216
    }
vb@0
   217
vb@0
   218
    string _ctext = utf8_string(ctext);
vb@0
   219
vb@0
   220
    char *_ptext = NULL;
vb@0
   221
    size_t _psize = 0;
vb@0
   222
    ::stringlist_t *_keylist = NULL;
vb@0
   223
    PEP_STATUS _status;
vb@0
   224
vb@0
   225
    _status = ::decrypt_and_verify(get_session(), _ctext.c_str(), _ctext.size(), &_ptext, &_psize, &_keylist);
vb@0
   226
    assert(_status != PEP_OUT_OF_MEMORY);
vb@0
   227
    if (_status == PEP_OUT_OF_MEMORY)
vb@0
   228
        return E_OUTOFMEMORY;
vb@0
   229
vb@0
   230
    *status = (pEp_STATUS) _status;
vb@0
   231
    if (_ptext == NULL) {
vb@0
   232
        if (_keylist) {
vb@0
   233
            string msg;
vb@0
   234
            if (_keylist->value[0] != 0) {
vb@0
   235
                msg = _keylist->value;
vb@0
   236
            }
vb@0
   237
            else {
vb@0
   238
                for (::stringlist_t *s = _keylist->next; s != NULL; s = s->next) {
vb@0
   239
                    if (s->value) {
vb@0
   240
                        msg += s->value;
vb@0
   241
                        msg += ";";
vb@0
   242
                    }
vb@0
   243
                }
vb@0
   244
            }
vb@0
   245
            ::free_stringlist(_keylist);
vb@0
   246
vb@0
   247
            return FAIL(utf16_bstr(msg));
vb@0
   248
        }
vb@0
   249
        else
vb@0
   250
            return FAIL(L"cannot decrypt");
vb@0
   251
    }
vb@0
   252
vb@0
   253
    *ptext = utf16_bstr(_ptext).Detach();
vb@0
   254
    pEp_free(_ptext);
vb@0
   255
vb@0
   256
    if (_keylist && _keylist->value)
vb@0
   257
        *key_list = string_array(_keylist).Detach();
vb@0
   258
    else
vb@0
   259
        *key_list = NULL;
vb@0
   260
    ::free_stringlist(_keylist);
vb@0
   261
vb@0
   262
    return S_OK;
vb@0
   263
}
vb@0
   264
vb@0
   265
STDMETHODIMP CpEpEngine::decrypt_b(BSTR ctext, LPSAFEARRAY * ptext, LPSAFEARRAY * key_list, pEp_STATUS * status)
vb@0
   266
{
vb@0
   267
    assert(ctext);
vb@0
   268
    assert(ptext);
vb@0
   269
    assert(key_list);
vb@0
   270
    assert(status);
vb@0
   271
vb@0
   272
    if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
vb@0
   273
        if (ptext)
vb@0
   274
            *ptext = NULL;
vb@0
   275
        if (key_list)
vb@0
   276
            *key_list = NULL;
vb@0
   277
        if (status)
vb@0
   278
            *status = pEp_UNENCRYPTED;
vb@0
   279
        return E_INVALIDARG;
vb@0
   280
    }
vb@0
   281
vb@0
   282
    // Welcome to Windoze string hell!
vb@0
   283
vb@0
   284
    char *_ctext = NULL;
vb@0
   285
    _bstr_t bstr_ctext(ctext, true);
vb@0
   286
    int w_csize = bstr_ctext.length() + 1;
vb@0
   287
    int _csize = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, (wchar_t *) bstr_ctext, w_csize, NULL, 0, NULL, NULL);
vb@0
   288
    if (_csize) {
vb@0
   289
        _ctext = new char[_csize];
vb@0
   290
        WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, (wchar_t *) bstr_ctext, w_csize, _ctext, _csize, NULL, NULL);
vb@0
   291
    }
vb@0
   292
vb@0
   293
    char *_ptext = NULL;
vb@0
   294
    size_t _psize = 0;
vb@0
   295
    ::stringlist_t *_keylist = NULL;
vb@0
   296
    PEP_STATUS _status;
vb@0
   297
vb@0
   298
    _status = ::decrypt_and_verify(get_session(), _ctext, _csize, &_ptext, &_psize, &_keylist);
vb@0
   299
    assert(_status != PEP_OUT_OF_MEMORY);
vb@0
   300
    delete[] _ctext;
vb@0
   301
    if (_status == PEP_OUT_OF_MEMORY) {
vb@0
   302
        ::free_stringlist(_keylist);
vb@0
   303
        return E_OUTOFMEMORY;
vb@0
   304
    }
vb@0
   305
    *status = (pEp_STATUS) _status;
vb@0
   306
vb@0
   307
    if (_ptext == NULL) {
vb@0
   308
        ::free_stringlist(_keylist);
vb@0
   309
        return FAIL(L"decrypt_and_verify");
vb@0
   310
    }
vb@0
   311
vb@0
   312
    CComSafeArray<BYTE> sa_ptext;
vb@0
   313
vb@0
   314
    HRESULT _result = sa_ptext.Create(_psize, 0);
vb@0
   315
    assert(_result == S_OK);
vb@0
   316
    if (_result == E_OUTOFMEMORY) {
vb@0
   317
        pEp_free(_ptext);
vb@0
   318
        ::free_stringlist(_keylist);
vb@0
   319
        return E_OUTOFMEMORY;
vb@0
   320
    }
vb@0
   321
    else if (_result != S_OK) {
vb@0
   322
        pEp_free(_ptext);
vb@0
   323
        ::free_stringlist(_keylist);
vb@0
   324
        return FAIL(L"CComSafeArray<BYTE>::Create");
vb@0
   325
    }
vb@0
   326
vb@0
   327
    memcpy(sa_ptext.m_psa->pvData, _ptext, _psize);
vb@0
   328
    *ptext = sa_ptext.Detach();
vb@0
   329
    ::pEp_free(_ptext);
vb@0
   330
vb@0
   331
    if (_keylist && _keylist->value)
vb@0
   332
        *key_list = string_array(_keylist).Detach();
vb@0
   333
    else
vb@0
   334
        *key_list = NULL;
vb@0
   335
    ::free_stringlist(_keylist);
vb@0
   336
vb@0
   337
    return S_OK;
vb@0
   338
}
vb@0
   339
vb@0
   340
STDMETHODIMP CpEpEngine::verify(BSTR text, BSTR signature, LPSAFEARRAY * key_list, pEp_STATUS * verify_status)
vb@0
   341
{
vb@0
   342
    assert(text);
vb@0
   343
    assert(signature);
vb@0
   344
    assert(key_list);
vb@0
   345
vb@0
   346
    if (text == NULL || signature == NULL || key_list == NULL)
vb@0
   347
        return E_INVALIDARG;
vb@0
   348
vb@0
   349
    string _text = utf8_string(text);
vb@0
   350
    string _signature = utf8_string(signature);
vb@0
   351
vb@0
   352
    ::stringlist_t *_keylist = NULL;
vb@0
   353
    PEP_STATUS _status;
vb@0
   354
    _status = ::verify_text(get_session(), _text.c_str(), _text.size(), _signature.c_str(), _signature.size(), &_keylist);
vb@0
   355
    assert(_status != PEP_OUT_OF_MEMORY);
vb@0
   356
    if (_status == PEP_OUT_OF_MEMORY)
vb@0
   357
        return E_OUTOFMEMORY;
vb@0
   358
    if (_status == PEP_DECRYPT_WRONG_FORMAT || _status == PEP_UNKNOWN_ERROR)
vb@0
   359
        return FAIL(L"verify_text");
vb@0
   360
vb@0
   361
    *verify_status = (pEp_STATUS) _status;
vb@0
   362
vb@0
   363
    if (_keylist && _keylist->value)
vb@0
   364
        *key_list = string_array(_keylist).Detach();
vb@0
   365
    else
vb@0
   366
        *key_list = NULL;
vb@0
   367
    ::free_stringlist(_keylist);
vb@0
   368
vb@0
   369
    return S_OK;
vb@0
   370
}
vb@0
   371
vb@0
   372
STDMETHODIMP CpEpEngine::encrypt(SAFEARRAY * key_list, BSTR ptext, BSTR * ctext, pEp_STATUS * status)
vb@0
   373
{
vb@0
   374
    assert(key_list);
vb@0
   375
    assert(ptext);
vb@0
   376
    assert(ctext);
vb@0
   377
    assert(status);
vb@0
   378
vb@0
   379
    if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
vb@0
   380
        if (ctext)
vb@0
   381
            *ctext = NULL;
vb@0
   382
        if (status)
vb@0
   383
            *status = pEp_UNKNOWN_ERROR;
vb@0
   384
        return E_INVALIDARG;
vb@0
   385
    }
vb@0
   386
vb@0
   387
    HRESULT result = S_OK;
vb@0
   388
vb@0
   389
    ::stringlist_t *_keylist = new_stringlist(key_list);
vb@0
   390
    string _ptext = utf8_string(ptext);
vb@0
   391
vb@0
   392
    char *_ctext = NULL;
vb@0
   393
    size_t _csize = 0;
vb@0
   394
    PEP_STATUS _status;
vb@0
   395
vb@0
   396
    _status = ::encrypt_and_sign(get_session(), _keylist, _ptext.c_str(), _ptext.size(), &_ctext, &_csize);
vb@0
   397
vb@0
   398
    assert(_status != PEP_OUT_OF_MEMORY);
vb@0
   399
    ::free_stringlist(_keylist);
vb@0
   400
    if (_status == PEP_OUT_OF_MEMORY)
vb@0
   401
        return E_OUTOFMEMORY;
vb@0
   402
    *status = (pEp_STATUS) _status;
vb@0
   403
vb@0
   404
    if (_ctext == NULL)
vb@0
   405
        return FAIL(L"encrypt_and_sign");
vb@0
   406
vb@0
   407
    *ctext = utf16_bstr(_ctext).Detach();
vb@0
   408
    pEp_free(_ctext);
vb@0
   409
vb@0
   410
    return S_OK;
vb@0
   411
}
vb@0
   412
vb@0
   413
STDMETHODIMP CpEpEngine::encrypt_b(SAFEARRAY * key_list, SAFEARRAY * ptext, BSTR * ctext, pEp_STATUS * status)
vb@0
   414
{
vb@0
   415
    assert(key_list);
vb@0
   416
    assert(ptext);
vb@0
   417
    assert(ctext);
vb@0
   418
    assert(status);
vb@0
   419
vb@0
   420
    if (ctext == NULL || ptext == NULL || key_list == NULL || status == NULL) {
vb@0
   421
        if (ctext)
vb@0
   422
            *ctext = NULL;
vb@0
   423
        if (status)
vb@0
   424
            *status = pEp_UNKNOWN_ERROR;
vb@0
   425
        return E_INVALIDARG;
vb@0
   426
    }
vb@0
   427
vb@0
   428
    HRESULT result = S_OK;
vb@0
   429
vb@0
   430
    ::stringlist_t *_keylist = new_stringlist(key_list);
vb@0
   431
vb@0
   432
    char *_ctext = NULL;
vb@0
   433
    size_t _csize = 0;
vb@0
   434
    ::PEP_STATUS _status;
vb@0
   435
vb@0
   436
    _status = ::encrypt_and_sign(get_session(), _keylist, (const char *) ptext->pvData, ptext->rgsabound[0].cElements, &_ctext, &_csize);
vb@0
   437
    assert(_status != PEP_OUT_OF_MEMORY);
vb@0
   438
    ::free_stringlist(_keylist);
vb@0
   439
    if (_status == PEP_OUT_OF_MEMORY)
vb@0
   440
        return E_OUTOFMEMORY;
vb@0
   441
    *status = (pEp_STATUS) _status;
vb@0
   442
vb@0
   443
    if (_ctext == NULL)
vb@0
   444
        return FAIL(L"encrypt_and_sign");
vb@0
   445
vb@0
   446
    *status = (pEp_STATUS) _status;
vb@0
   447
    wchar_t *w_ctext = NULL;
vb@0
   448
    int w_csize = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, _ctext, _csize, NULL, 0);
vb@0
   449
    if (w_csize) {
vb@0
   450
        w_ctext = new wchar_t[w_csize + 1];
vb@0
   451
        MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, _ctext, _csize, w_ctext, w_csize);
vb@0
   452
        w_ctext[w_csize] = 0; // this is for debugging; Visual Studio will crash without that if you're unlucky
vb@0
   453
    }
vb@0
   454
    *ctext = ::SysAllocStringLen(w_ctext, w_csize);
vb@0
   455
    assert(ctext);
vb@0
   456
    delete[] w_ctext;
vb@0
   457
    pEp_free(_ctext);
vb@0
   458
    if (ctext == NULL)
vb@0
   459
        return E_OUTOFMEMORY;
vb@0
   460
vb@0
   461
    return S_OK;
vb@0
   462
}
vb@0
   463
vb@0
   464
STDMETHODIMP CpEpEngine::safeword(LONG value, BSTR lang, BSTR * word)
vb@0
   465
{
vb@0
   466
    assert(value >= 0 && value <= 65535);
vb@0
   467
    assert(word);
vb@0
   468
vb@0
   469
    HRESULT result = S_OK;
vb@0
   470
vb@0
   471
    uint16_t _value = 0;
vb@0
   472
    if (value < 0 || value > 65535)
vb@0
   473
        result = E_INVALIDARG;
vb@0
   474
    else
vb@0
   475
        _value = (uint16_t) value;
vb@0
   476
vb@0
   477
    string _lang = "en";
vb@0
   478
    if (lang) {
vb@0
   479
        _lang = utf8_string(lang);
vb@0
   480
        if (_lang.length() != 2)
vb@0
   481
            result = E_INVALIDARG;
vb@0
   482
    }
vb@0
   483
vb@0
   484
    if (word == NULL)
vb@0
   485
        result = E_INVALIDARG;
vb@0
   486
vb@0
   487
    if (result != S_OK)
vb@0
   488
        return result;
vb@0
   489
vb@0
   490
    char *_word = NULL;
vb@0
   491
    size_t _wsize = 0;
vb@0
   492
vb@0
   493
    PEP_STATUS status = ::safeword(get_session(), _value, _lang.c_str(), &_word, &_wsize);
vb@0
   494
    assert(status != PEP_OUT_OF_MEMORY);
vb@0
   495
    if (status == PEP_OUT_OF_MEMORY)
vb@0
   496
        return E_OUTOFMEMORY;
vb@0
   497
vb@0
   498
    if (_word == NULL) {
vb@0
   499
        *word = NULL;
vb@0
   500
        return FAIL(L"safeword");
vb@0
   501
    }
vb@0
   502
    else {
vb@0
   503
        *word = utf16_bstr(_word).Detach();
vb@0
   504
        pEp_free(_word);
vb@0
   505
        return S_OK;
vb@0
   506
    }
vb@0
   507
}
vb@0
   508
vb@0
   509
STDMETHODIMP CpEpEngine::safewords(BSTR fpr, BSTR lang, LONG max_words, BSTR * words)
vb@0
   510
{
vb@0
   511
    assert(fpr);
vb@0
   512
    assert(max_words >= 0);
vb@0
   513
    assert(words);
vb@0
   514
vb@0
   515
    HRESULT result = S_OK;
vb@0
   516
vb@0
   517
    string _fpr;
vb@0
   518
    if (fpr)
vb@0
   519
        _fpr = utf8_string(fpr);
vb@0
   520
    else
vb@0
   521
        result = E_INVALIDARG;
vb@0
   522
vb@0
   523
    string _lang;
vb@0
   524
    if (lang) {
vb@0
   525
        _lang = utf8_string(lang);
vb@0
   526
        if (_lang.length()) {
vb@0
   527
            if (_lang.length() != 2)
vb@0
   528
                result = E_INVALIDARG;
vb@0
   529
        }
vb@0
   530
        else
vb@0
   531
            _lang = "en";
vb@0
   532
    }
vb@0
   533
    else
vb@0
   534
        _lang = "en";
vb@0
   535
vb@0
   536
    if (max_words < 0)
vb@0
   537
        result = E_INVALIDARG;
vb@0
   538
vb@0
   539
    if (words == NULL)
vb@0
   540
        result = E_INVALIDARG;
vb@0
   541
vb@0
   542
    if (result != S_OK)
vb@0
   543
        return result;
vb@0
   544
vb@0
   545
    char *_words = NULL;
vb@0
   546
    size_t _wsize = 0;
vb@0
   547
vb@0
   548
    PEP_STATUS status = ::safewords(get_session(), _fpr.c_str(), _lang.c_str(), &_words, &_wsize, max_words);
vb@0
   549
    assert(status != PEP_OUT_OF_MEMORY);
vb@0
   550
    if (status == PEP_OUT_OF_MEMORY)
vb@0
   551
        return E_OUTOFMEMORY;
vb@0
   552
vb@0
   553
    if (_words == NULL) {
vb@0
   554
        *words = NULL;
vb@0
   555
        return FAIL(L"safewords");
vb@0
   556
    }
vb@0
   557
    else {
vb@0
   558
        *words = utf16_bstr(_words).Detach();
vb@0
   559
        pEp_free(_words);
vb@0
   560
        return S_OK;
vb@0
   561
    }
vb@0
   562
}
vb@0
   563
vb@0
   564
STDMETHODIMP CpEpEngine::get_identity(BSTR address, pEp_identity_s * ident)
vb@0
   565
{
vb@0
   566
    assert(address);
vb@0
   567
    assert(ident);
vb@0
   568
vb@0
   569
    if (address == NULL)
vb@0
   570
        return E_INVALIDARG;
vb@0
   571
vb@0
   572
    if (ident == NULL)
vb@0
   573
        return E_INVALIDARG;
vb@0
   574
vb@0
   575
    string _address = utf8_string(address);
vb@0
   576
    ::pEp_identity *_ident = NULL;
vb@0
   577
    PEP_STATUS status = ::get_identity(get_session(), _address.c_str(), &_ident);
vb@0
   578
    assert(status != PEP_OUT_OF_MEMORY);
vb@0
   579
    if (status == PEP_OUT_OF_MEMORY)
vb@0
   580
        return E_OUTOFMEMORY;
vb@0
   581
vb@0
   582
    if (_ident == NULL) {
vb@0
   583
        return FAIL(L"get_identity");
vb@0
   584
    }
vb@0
   585
vb@0
   586
    copy_identity(ident, _ident);
vb@0
   587
    ::free_identity(_ident);
vb@0
   588
vb@0
   589
    return S_OK;
vb@0
   590
}
vb@0
   591
vb@0
   592
STDMETHODIMP CpEpEngine::set_identity(pEp_identity_s * ident)
vb@0
   593
{
vb@0
   594
    assert(ident);
vb@0
   595
    assert(ident->address);
vb@0
   596
    assert(ident->fpr);
vb@0
   597
    assert(ident->username);
vb@0
   598
    assert(ident->user_id);
vb@0
   599
vb@0
   600
    if (ident == NULL || ident->address == NULL || ident->fpr == NULL
vb@0
   601
        || ident->username == NULL || ident->user_id == NULL)
vb@0
   602
        return E_INVALIDARG;
vb@0
   603
vb@0
   604
    ::pEp_identity *_ident = new_identity(ident);
vb@0
   605
    ::PEP_STATUS status = ::set_identity(get_session(), _ident);
vb@0
   606
    ::free_identity(_ident);
vb@0
   607
vb@0
   608
    if (status != ::PEP_STATUS_OK)
vb@0
   609
        return FAIL(L"set_identity");
vb@0
   610
    else
vb@0
   611
        return S_OK;
vb@0
   612
}
vb@0
   613
vb@0
   614
STDMETHODIMP CpEpEngine::generate_keypair(pEp_identity_s * ident, BSTR * fpr)
vb@0
   615
{
vb@0
   616
    assert(ident);
vb@0
   617
    assert(ident->address);
vb@0
   618
    assert(ident->username);
vb@0
   619
    assert(fpr);
vb@0
   620
vb@0
   621
    if (ident == NULL || ident->address == NULL || ident->username == NULL || fpr == NULL)
vb@0
   622
        return E_INVALIDARG;
vb@0
   623
vb@0
   624
    ::pEp_identity *_ident = new_identity(ident);
vb@0
   625
    ::pEp_free(_ident->fpr);
vb@0
   626
    _ident->fpr = NULL;
vb@0
   627
vb@0
   628
    ::PEP_STATUS status = ::generate_keypair(get_session(), _ident);
vb@0
   629
    assert(status != ::PEP_OUT_OF_MEMORY);
vb@0
   630
    if (status == ::PEP_OUT_OF_MEMORY) {
vb@0
   631
        ::free_identity(_ident);
vb@0
   632
        return E_OUTOFMEMORY;
vb@0
   633
    }
vb@0
   634
vb@0
   635
    if (_ident->fpr)
vb@0
   636
        *fpr = utf16_bstr(_ident->fpr).Detach();
vb@0
   637
vb@0
   638
    ::free_identity(_ident);
vb@0
   639
vb@0
   640
    if (status != ::PEP_STATUS_OK)
vb@0
   641
        return FAIL(L"generate_keypair");
vb@0
   642
vb@0
   643
    return S_OK;
vb@0
   644
}
vb@0
   645
vb@0
   646
STDMETHODIMP CpEpEngine::delete_keypair(BSTR fpr)
vb@0
   647
{
vb@0
   648
    assert(fpr);
vb@0
   649
vb@0
   650
    if (fpr == NULL)
vb@0
   651
        return E_INVALIDARG;
vb@0
   652
vb@0
   653
    string _fpr = utf8_string(fpr);
vb@0
   654
vb@0
   655
    ::PEP_STATUS status = ::delete_keypair(get_session(), _fpr.c_str());
vb@0
   656
    assert(status != PEP_OUT_OF_MEMORY);
vb@0
   657
    if (status == PEP_OUT_OF_MEMORY)
vb@0
   658
        return E_OUTOFMEMORY;
vb@0
   659
vb@0
   660
    if (status != ::PEP_STATUS_OK)
vb@0
   661
        return FAIL(L"delete_keypair");
vb@0
   662
    else
vb@0
   663
        return S_OK;
vb@0
   664
}
vb@0
   665
vb@0
   666
STDMETHODIMP CpEpEngine::import_key(BSTR key_data)
vb@0
   667
{
vb@0
   668
    assert(key_data);
vb@0
   669
vb@0
   670
    if (key_data == NULL)
vb@0
   671
        return E_INVALIDARG;
vb@0
   672
vb@0
   673
    string _key_data = utf8_string(key_data);
vb@0
   674
vb@0
   675
    PEP_STATUS status = ::import_key(get_session(), _key_data.c_str(), _key_data.length());
vb@0
   676
    assert(status != PEP_OUT_OF_MEMORY);
vb@0
   677
    if (status == PEP_OUT_OF_MEMORY)
vb@0
   678
        return E_OUTOFMEMORY;
vb@0
   679
vb@0
   680
    if (status != pEp_STATUS_OK)
vb@0
   681
        return FAIL(L"import_key");
vb@0
   682
    else
vb@0
   683
        return S_OK;
vb@0
   684
}
vb@0
   685
vb@0
   686
STDMETHODIMP CpEpEngine::import_key_b(SAFEARRAY * key_data)
vb@0
   687
{
vb@0
   688
    assert(key_data);
vb@0
   689
vb@0
   690
    if (key_data == NULL)
vb@0
   691
        return E_INVALIDARG;
vb@0
   692
vb@0
   693
    ::PEP_STATUS status = ::import_key(get_session(), (const char *) key_data->pvData, key_data->rgsabound[0].cElements);
vb@0
   694
    assert(status != ::PEP_OUT_OF_MEMORY);
vb@0
   695
    if (status == ::PEP_OUT_OF_MEMORY)
vb@0
   696
        return E_OUTOFMEMORY;
vb@0
   697
vb@0
   698
    if (status != ::PEP_STATUS_OK)
vb@0
   699
        return FAIL(L"import_key");
vb@0
   700
    else
vb@0
   701
        return S_OK;
vb@0
   702
}
vb@0
   703
vb@0
   704
STDMETHODIMP CpEpEngine::export_key(BSTR fpr, BSTR * key_data)
vb@0
   705
{
vb@0
   706
    assert(fpr);
vb@0
   707
    assert(key_data);
vb@0
   708
vb@0
   709
    if (fpr == NULL || key_data == NULL)
vb@0
   710
        return E_INVALIDARG;
vb@0
   711
vb@0
   712
    string _fpr = utf8_string(fpr);
vb@0
   713
    char *_key_data = NULL;
vb@0
   714
    size_t _size = 0;
vb@0
   715
vb@0
   716
    ::PEP_STATUS status = ::export_key(get_session(), _fpr.c_str(), &_key_data, &_size);
vb@0
   717
    assert(status != ::PEP_OUT_OF_MEMORY);
vb@0
   718
    if (status == ::PEP_OUT_OF_MEMORY)
vb@0
   719
        return E_OUTOFMEMORY;
vb@0
   720
vb@0
   721
    if (status != ::PEP_STATUS_OK)
vb@0
   722
        return FAIL(L"export_key");
vb@0
   723
vb@0
   724
    _bstr_t b_key_data(utf16_string(_key_data).c_str());
vb@0
   725
    pEp_free(_key_data);
vb@0
   726
    *key_data = b_key_data.Detach();
vb@0
   727
vb@0
   728
    return S_OK;
vb@0
   729
}
vb@0
   730
vb@0
   731
STDMETHODIMP CpEpEngine::recv_key(BSTR pattern)
vb@0
   732
{
vb@0
   733
    assert(pattern);
vb@0
   734
vb@0
   735
    if (pattern == NULL)
vb@0
   736
        return E_INVALIDARG;
vb@0
   737
vb@0
   738
    string _pattern = utf8_string(pattern);
vb@0
   739
vb@0
   740
    PEP_STATUS status = ::recv_key(get_session(), _pattern.c_str());
vb@0
   741
    assert(status != PEP_OUT_OF_MEMORY);
vb@0
   742
    if (status == PEP_OUT_OF_MEMORY)
vb@0
   743
        return E_OUTOFMEMORY;
vb@0
   744
vb@0
   745
    if (status != ::PEP_STATUS_OK)
vb@0
   746
        return FAIL(L"recv_key");
vb@0
   747
    else
vb@0
   748
        return S_OK;
vb@0
   749
}
vb@0
   750
vb@0
   751
STDMETHODIMP CpEpEngine::find_keys(BSTR pattern, LPSAFEARRAY * key_list)
vb@0
   752
{
vb@0
   753
    assert(pattern);
vb@0
   754
    assert(key_list);
vb@0
   755
vb@0
   756
    if (pattern == NULL || key_list == NULL)
vb@0
   757
        return E_INVALIDARG;
vb@0
   758
vb@0
   759
    string _pattern = utf8_string(pattern);
vb@0
   760
    ::stringlist_t *_keylist = NULL;
vb@0
   761
vb@0
   762
    PEP_STATUS status = ::find_keys(get_session(), _pattern.c_str(), &_keylist);
vb@0
   763
    assert(status != PEP_OUT_OF_MEMORY);
vb@0
   764
    if (status == PEP_OUT_OF_MEMORY)
vb@0
   765
        return E_OUTOFMEMORY;
vb@0
   766
vb@0
   767
    if (status != ::PEP_STATUS_OK)
vb@0
   768
        return FAIL(L"find_keys");
vb@0
   769
vb@0
   770
    if (_keylist && _keylist->value) {
vb@0
   771
        *key_list = string_array(_keylist).Detach();
vb@0
   772
    }
vb@0
   773
    else {
vb@0
   774
        ::free_stringlist(_keylist);
vb@0
   775
        return FAIL(L"find_keys: no keys found");
vb@0
   776
    }
vb@0
   777
vb@0
   778
    ::free_stringlist(_keylist);
vb@0
   779
    return S_OK;
vb@0
   780
}
vb@0
   781
vb@0
   782
STDMETHODIMP CpEpEngine::send_key(BSTR pattern)
vb@0
   783
{
vb@0
   784
    assert(pattern);
vb@0
   785
vb@0
   786
    if (pattern == NULL)
vb@0
   787
        return E_INVALIDARG;
vb@0
   788
vb@0
   789
    string _pattern = utf8_string(pattern);
vb@0
   790
vb@0
   791
    ::PEP_STATUS status = ::send_key(get_session(), _pattern.c_str());
vb@0
   792
vb@0
   793
    if (status != ::PEP_STATUS_OK)
vb@0
   794
        return FAIL(L"send_key");
vb@0
   795
    else
vb@0
   796
        return S_OK;
vb@0
   797
}
vb@0
   798
vb@0
   799
STDMETHODIMP CpEpEngine::examine_identity(pEp_identity_s * ident)
vb@0
   800
{
vb@0
   801
    assert(ident);
vb@0
   802
    if (ident == NULL)
vb@0
   803
        return E_INVALIDARG;
vb@0
   804
vb@0
   805
    try {
vb@0
   806
        identity_queue->push_back(ident);
vb@0
   807
    }
vb@0
   808
    catch (bad_alloc) {
vb@0
   809
        return E_OUTOFMEMORY;
vb@0
   810
    }
vb@0
   811
vb@0
   812
    return S_OK;
vb@0
   813
}
vb@0
   814
vb@0
   815
STDMETHODIMP CpEpEngine::examine_myself(pEp_identity_s * myself)
vb@0
   816
{
vb@0
   817
    assert(myself);
vb@0
   818
    if (myself == NULL)
vb@0
   819
        return E_INVALIDARG;
vb@0
   820
vb@0
   821
    pEp_identity_cpp _ident(myself);
vb@0
   822
    _ident.me = true;
vb@0
   823
vb@0
   824
    ::log_event(get_session(), "examine_myself", "debug", _ident.address.c_str(), NULL);
vb@0
   825
    try {
vb@0
   826
        identity_queue->push_front(_ident);
vb@0
   827
    }
vb@0
   828
    catch (bad_alloc) {
vb@0
   829
        return E_OUTOFMEMORY;
vb@0
   830
    }
vb@0
   831
vb@0
   832
    return S_OK;
vb@0
   833
}
vb@0
   834
vb@0
   835
STDMETHODIMP CpEpEngine::myself(struct pEp_identity_s *ident, struct pEp_identity_s *result)
vb@0
   836
{
vb@0
   837
    assert(ident);
vb@0
   838
    assert(result);
vb@0
   839
vb@0
   840
    if (ident == NULL || result == NULL)
vb@0
   841
        return E_INVALIDARG;
vb@0
   842
vb@0
   843
    ::pEp_identity *_ident = new_identity(ident);
vb@0
   844
    assert(_ident);
vb@0
   845
    if (_ident == NULL)
vb@0
   846
        return E_OUTOFMEMORY;
vb@0
   847
vb@0
   848
    PEP_STATUS status = ::myself(get_session(), _ident);
vb@0
   849
vb@0
   850
    if (status == PEP_STATUS_OK) {
vb@0
   851
        assert(_ident->fpr);
vb@0
   852
        copy_identity(result, _ident);
vb@0
   853
        ::free_identity(_ident);
vb@0
   854
        return S_OK;
vb@0
   855
    }
vb@0
   856
    else {
vb@0
   857
        ::free_identity(_ident);
vb@0
   858
        if (status == PEP_OUT_OF_MEMORY)
vb@0
   859
            return E_OUTOFMEMORY;
vb@0
   860
        else
vb@0
   861
            return FAIL(L"myself");
vb@0
   862
    }
vb@0
   863
}
vb@0
   864
vb@0
   865
STDMETHODIMP CpEpEngine::update_identity(struct pEp_identity_s *ident, struct pEp_identity_s *result)
vb@0
   866
{
vb@0
   867
    assert(ident);
vb@0
   868
    assert(result);
vb@0
   869
vb@0
   870
    if (ident == NULL || result == NULL)
vb@0
   871
        return E_INVALIDARG;
vb@0
   872
vb@0
   873
    ::pEp_identity *_ident = new_identity(ident);
vb@0
   874
    assert(_ident);
vb@0
   875
    if (_ident == NULL)
vb@0
   876
        return E_OUTOFMEMORY;
vb@0
   877
vb@0
   878
    PEP_STATUS status = ::update_identity(get_session(), _ident);
vb@0
   879
vb@0
   880
    if (status == PEP_STATUS_OK) {
vb@0
   881
        assert(_ident->fpr);
vb@0
   882
        copy_identity(result, _ident);
vb@0
   883
        if (_ident->comm_type == PEP_ct_unknown || _ident->comm_type == PEP_ct_key_expired) {
vb@0
   884
            pEp_identity_cpp _ident_cpp(_ident);
vb@0
   885
            identity_queue->push_back(_ident_cpp);
vb@0
   886
        }
vb@0
   887
        ::free_identity(_ident);
vb@0
   888
        return S_OK;
vb@0
   889
    }
vb@0
   890
    else {
vb@0
   891
        ::free_identity(_ident);
vb@0
   892
        if (status == PEP_OUT_OF_MEMORY)
vb@0
   893
            return E_OUTOFMEMORY;
vb@0
   894
        else
vb@0
   895
            return FAIL(L"update_identity");
vb@0
   896
    }
vb@0
   897
}
vb@0
   898
vb@0
   899
::pEp_identity * CpEpEngine::retrieve_next_identity(void *management)
vb@0
   900
{
vb@0
   901
    assert(management);
vb@0
   902
    identity_queue_t *iq = (identity_queue_t *) management;
vb@0
   903
vb@0
   904
    do /* poll queue */ {
vb@0
   905
        if (iq->size())
vb@0
   906
            break;
vb@0
   907
        ::Sleep(100);
vb@0
   908
    } while (true);
vb@0
   909
vb@0
   910
    ::pEp_identity *_ident;
vb@0
   911
    pEp_identity_cpp& ident = iq->front();
vb@0
   912
vb@0
   913
    if (ident.address.size() == 0) {
vb@0
   914
        delete iq;
vb@0
   915
        return NULL;
vb@0
   916
    }
vb@0
   917
vb@0
   918
    _ident = new_identity(ident);
vb@0
   919
    iq->pop_front();
vb@0
   920
vb@0
   921
    return _ident;
vb@0
   922
}
vb@0
   923
vb@0
   924
HRESULT CpEpEngine::error(_bstr_t msg)
vb@0
   925
{
vb@0
   926
    _bstr_t helpFile = L"";
vb@0
   927
    _bstr_t source = L"pEp COM Adapter";
vb@0
   928
vb@0
   929
    ICreateErrorInfo *cei;
vb@0
   930
    if (SUCCEEDED(CreateErrorInfo(&cei))) {
vb@0
   931
        cei->SetDescription(msg);
vb@0
   932
        cei->SetGUID(__uuidof(IpEpEngine));
vb@0
   933
        cei->SetHelpContext(0);
vb@0
   934
        cei->SetHelpFile(helpFile);
vb@0
   935
        cei->SetSource(source);
vb@0
   936
vb@0
   937
        IErrorInfo *errinfo;
vb@0
   938
        if (SUCCEEDED(cei->QueryInterface(IID_IErrorInfo, (LPVOID FAR*) &errinfo))) {
vb@0
   939
            SetErrorInfo(0, errinfo);
vb@0
   940
            errinfo->Release();
vb@0
   941
        }
vb@0
   942
        cei->Release();
vb@0
   943
    }
vb@0
   944
    return E_FAIL;
vb@0
   945
}