src/mime.c
author Krista Bennett <krista@pep-project.org>
Wed, 06 Sep 2017 02:09:14 +0200
branch2028_fix
changeset 2036 81c4285cd4fc
parent 2035 61b05d325adc
child 2045 162803eb47e0
permissions -rw-r--r--
ENGINE-246: Fixed read-after-free issue - I'd copied and freed a duplicate message object, thinking that libetpan makes copies, not taking ownership, of message object parts. IN FUTURE, PLEASE NOTE THAT THIS IS WRONG. Leave the message object alone for as long as we're using libetpan, and don't try to optimise around it with copies, because you either lose memory or screw up ownership
vb@1513
     1
// This file is under GNU General Public License 3.0
vb@1513
     2
// see LICENSE.txt
vb@1513
     3
vb@126
     4
#include "pEp_internal.h"
vb@48
     5
#include "mime.h"
vb@48
     6
vb@48
     7
#include <string.h>
vb@48
     8
#include <stdlib.h>
vb@48
     9
#include <assert.h>
vb@48
    10
#include <errno.h>
vb@130
    11
krista@1878
    12
#include "resource_id.h"
vb@48
    13
#include "etpan_mime.h"
vb@63
    14
#include "wrappers.h"
vb@48
    15
vb@309
    16
static bool is_whitespace(char c)
vb@308
    17
{
vb@308
    18
    switch (c) {
vb@308
    19
        case ' ':
vb@308
    20
        case '\t':
vb@308
    21
        case '\r':
vb@308
    22
        case '\n':
vb@308
    23
            return true;
vb@308
    24
vb@308
    25
        default:
vb@308
    26
            return false;
vb@308
    27
    }
vb@308
    28
}
vb@308
    29
vb@117
    30
DYNAMIC_API bool is_PGP_message_text(const char *text)
vb@117
    31
{
vb@117
    32
    if (text == NULL)
vb@117
    33
        return false;
vb@117
    34
vb@309
    35
    for (; *text && is_whitespace(*text); text++);
vb@308
    36
vb@117
    37
    return strncmp(text, "-----BEGIN PGP MESSAGE-----", 27) == 0;
vb@117
    38
}
vb@117
    39
Edouard@373
    40
#define TMP_TEMPLATE "pEp.XXXXXXXXXXXXXXXXXXXX"
Edouard@373
    41
#ifdef _WIN32
Edouard@373
    42
#define PATH_SEP '\\'
Edouard@373
    43
#else
Edouard@373
    44
#define PATH_SEP '/'
Edouard@373
    45
#endif
Edouard@373
    46
markus@1042
    47
// This function was rewritten to use in-memory buffers instead of
markus@1042
    48
// temporary files when the pgp/mime support was implemented for
markus@1042
    49
// outlook, as the existing code did not work well on windows.
markus@1042
    50
vb@89
    51
static PEP_STATUS render_mime(struct mailmime *mime, char **mimetext)
vb@48
    52
{
vb@89
    53
    PEP_STATUS status = PEP_STATUS_OK;
vb@89
    54
    int col;
vb@89
    55
    int r;
markus@1042
    56
	size_t len;
markus@1042
    57
	char* buf = NULL;
Edouard@373
    58
markus@1042
    59
	MMAPString* buffer;
Edouard@373
    60
markus@1042
    61
	buffer = mmap_string_new(NULL);
markus@1042
    62
	if (buffer == NULL)
markus@1042
    63
		goto enomem;
markus@1042
    64
	
markus@1042
    65
	col = 0;
markus@1042
    66
	r = mailmime_write_mem(buffer, &col, mime);
markus@1042
    67
	assert(r == MAILIMF_NO_ERROR);
markus@1042
    68
	if (r == MAILIMF_ERROR_MEMORY)
markus@1042
    69
		goto enomem;
markus@1042
    70
	else if (r != MAILIMF_NO_ERROR)
markus@1042
    71
		goto err_file;
Edouard@373
    72
markus@1042
    73
	// we overallocate by 1 byte, so we have a terminating 0.
markus@1042
    74
	len = buffer->len;
markus@1042
    75
	buf = calloc(len + 1, 1);
markus@1042
    76
	if (buf == NULL)
markus@1042
    77
		goto enomem;
vb@48
    78
markus@1042
    79
	memcpy(buf, buffer->str, len);
markus@1042
    80
	mmap_string_free(buffer);
vb@62
    81
vb@87
    82
    *mimetext = buf;
vb@48
    83
    return PEP_STATUS_OK;
vb@48
    84
vb@48
    85
err_file:
vb@88
    86
    status = PEP_CANNOT_CREATE_TEMP_FILE;
vb@88
    87
    goto pep_error;
vb@48
    88
vb@48
    89
enomem:
vb@88
    90
    status = PEP_OUT_OF_MEMORY;
vb@52
    91
vb@88
    92
pep_error:
markus@1042
    93
	if (buffer)
markus@1042
    94
		mmap_string_free(buffer);
markus@1042
    95
	if (buf)
markus@1042
    96
		free(buf);
vb@89
    97
    return status;
vb@89
    98
}
vb@89
    99
vb@88
   100
vb@89
   101
static PEP_STATUS mime_attachment(
vb@89
   102
        bloblist_t *blob,
vb@89
   103
        struct mailmime **result
vb@88
   104
    )
vb@88
   105
{
vb@88
   106
    PEP_STATUS status = PEP_STATUS_OK;
vb@89
   107
    struct mailmime * mime = NULL;
vb@89
   108
    char * mime_type;
vb@89
   109
    assert(blob);
vb@89
   110
    assert(result);
vb@88
   111
vb@89
   112
    *result = NULL;
vb@88
   113
markus@1042
   114
// TODO: It seems the pep com server adapter sends an empty string here,
markus@1042
   115
// which leads to a crash later. Thus, we workaround here by treating an
markus@1042
   116
// empty string as NULL. We need to check whether the bug really is here,
markus@1042
   117
// or the pep com server adapter needs to be changed.
markus@1042
   118
    if (blob->mime_type == NULL || blob->mime_type[0] == '\0')
vb@89
   119
        mime_type = "application/octet-stream";
vb@89
   120
    else
vb@89
   121
        mime_type = blob->mime_type;
vb@89
   122
krista@1878
   123
    pEp_rid_list_t* resource = parse_uri(blob->filename);
krista@1878
   124
    mime = get_file_part(resource, mime_type, blob->value, blob->size);
krista@1878
   125
    free_rid_list(resource);
krista@1878
   126
    
vb@89
   127
    assert(mime);
vb@89
   128
    if (mime == NULL)
vb@89
   129
        goto enomem;
vb@89
   130
vb@89
   131
    *result = mime;
vb@89
   132
    return PEP_STATUS_OK;
vb@88
   133
vb@88
   134
enomem:
vb@88
   135
    status = PEP_OUT_OF_MEMORY;
vb@88
   136
vb@89
   137
    if (mime)
vb@89
   138
        mailmime_free(mime);
vb@89
   139
vb@88
   140
    return status;
vb@88
   141
}
vb@88
   142
krista@2011
   143
static PEP_STATUS mime_html_text(
krista@2011
   144
        const char *plaintext,
krista@2011
   145
        const char *htmltext,
krista@2036
   146
        bloblist_t *attachments,
krista@2011
   147
        struct mailmime **result
krista@2011
   148
    )
krista@2011
   149
{
krista@2011
   150
    PEP_STATUS status = PEP_STATUS_OK;
krista@2011
   151
    struct mailmime * top_level_html_mime = NULL;
krista@2011
   152
    struct mailmime * mime = NULL;
krista@2011
   153
    struct mailmime * submime = NULL;
krista@2011
   154
    int r;
krista@2011
   155
krista@2011
   156
    assert(plaintext);
krista@2011
   157
    assert(htmltext);
krista@2011
   158
    assert(result);
krista@2011
   159
krista@2011
   160
    *result = NULL;
krista@2011
   161
krista@2011
   162
    mime = part_multiple_new("multipart/alternative");
krista@2011
   163
    assert(mime);
krista@2011
   164
    if (mime == NULL)
krista@2011
   165
        goto enomem;
krista@2011
   166
krista@2011
   167
    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
krista@2011
   168
    
krista@2012
   169
    submime = get_text_part(NULL, "text/plain", plaintext, strlen(plaintext),
krista@2011
   170
            MAILMIME_MECHANISM_QUOTED_PRINTABLE);
krista@2011
   171
    free_rid_list(resource);
krista@2011
   172
    resource = NULL;
krista@2011
   173
    
krista@2011
   174
    assert(submime);
krista@2011
   175
    if (submime == NULL)
krista@2011
   176
        goto enomem;
krista@2011
   177
krista@2011
   178
    r = mailmime_smart_add_part(mime, submime);
krista@2011
   179
    assert(r == MAILIMF_NO_ERROR);
krista@2011
   180
    if (r == MAILIMF_ERROR_MEMORY) {
krista@2011
   181
        goto enomem;
krista@2011
   182
    }
krista@2011
   183
    else {
krista@2011
   184
        // mailmime_smart_add_part() takes ownership of submime
krista@2011
   185
        submime = NULL;
krista@2011
   186
    }
krista@2011
   187
krista@2036
   188
    bool inlined_attachments = false;
krista@2036
   189
    
krista@2036
   190
    bloblist_t* traversal_ptr = attachments;
krista@2036
   191
    
krista@2036
   192
    while (traversal_ptr) {
krista@2036
   193
        if (traversal_ptr->disposition == PEP_CONTENT_DISP_INLINE) {
krista@2036
   194
            inlined_attachments = true;
krista@2036
   195
            break;
krista@2036
   196
        }
krista@2036
   197
        traversal_ptr = traversal_ptr->next;
krista@2036
   198
    }
krista@2011
   199
krista@2011
   200
    if (inlined_attachments) {
krista@2011
   201
        /* Noooooo... dirk, why do you do this to me? */
krista@2011
   202
        submime = part_multiple_new("multipart/related");
krista@2011
   203
        assert(submime);
krista@2011
   204
        if (submime == NULL)
krista@2011
   205
            goto enomem;
krista@2011
   206
krista@2011
   207
        top_level_html_mime = submime;
krista@2011
   208
        
krista@2011
   209
        r = mailmime_smart_add_part(mime, top_level_html_mime);
krista@2011
   210
        assert(r == MAILIMF_NO_ERROR);
krista@2011
   211
        if (r == MAILIMF_ERROR_MEMORY) {
krista@2011
   212
            goto enomem;
krista@2011
   213
        }
krista@2011
   214
        else {
krista@2011
   215
            // mailmime_smart_add_part() takes ownership of submime
krista@2011
   216
            submime = NULL;
krista@2011
   217
        }
krista@2011
   218
    }
krista@2011
   219
    else {
krista@2011
   220
        top_level_html_mime = mime;
krista@2011
   221
    }
krista@2011
   222
krista@2012
   223
//    resource = new_rid_node(PEP_RID_FILENAME, "msg.html");
krista@2012
   224
    submime = get_text_part(NULL, "text/html", htmltext, strlen(htmltext),
krista@2011
   225
            MAILMIME_MECHANISM_QUOTED_PRINTABLE);
krista@2011
   226
    free_rid_list(resource);
krista@2011
   227
    resource = NULL;
krista@2011
   228
    
krista@2011
   229
    assert(submime);
krista@2011
   230
    if (submime == NULL)
krista@2011
   231
        goto enomem;
krista@2011
   232
krista@2011
   233
    r = mailmime_smart_add_part(top_level_html_mime, submime);
krista@2011
   234
    assert(r == MAILIMF_NO_ERROR);
krista@2011
   235
    if (r == MAILIMF_ERROR_MEMORY)
krista@2011
   236
        goto enomem;
krista@2011
   237
    else {
krista@2011
   238
        // mailmime_smart_add_part() takes ownership of submime
krista@2011
   239
        submime = NULL;
krista@2011
   240
    }
krista@2011
   241
krista@2011
   242
    bloblist_t *_a;
krista@2036
   243
    for (_a = attachments; _a != NULL; _a = _a->next) {
krista@2036
   244
        if (_a->disposition != PEP_CONTENT_DISP_INLINE)
krista@2036
   245
            continue;
krista@2011
   246
        status = mime_attachment(_a, &submime);
krista@2011
   247
        if (status != PEP_STATUS_OK)
krista@2011
   248
            return PEP_UNKNOWN_ERROR; // FIXME
krista@2011
   249
krista@2011
   250
        r = mailmime_smart_add_part(top_level_html_mime, submime);
krista@2011
   251
        assert(r == MAILIMF_NO_ERROR);
krista@2011
   252
        if (r == MAILIMF_ERROR_MEMORY) {
krista@2011
   253
            goto enomem;
krista@2011
   254
        }
krista@2011
   255
        else {
krista@2011
   256
            // mailmime_smart_add_part() takes ownership of submime
krista@2011
   257
            submime = NULL;
krista@2011
   258
        }
krista@2011
   259
    }
krista@2011
   260
krista@2011
   261
    *result = mime;
krista@2011
   262
    return PEP_STATUS_OK;
krista@2011
   263
krista@2011
   264
enomem:
krista@2011
   265
    status = PEP_OUT_OF_MEMORY;
krista@2011
   266
krista@2011
   267
    if (mime)
krista@2011
   268
        mailmime_free(mime);
krista@2011
   269
krista@2011
   270
    if (submime)
krista@2011
   271
        mailmime_free(submime);
krista@2011
   272
krista@2011
   273
    return status;
krista@2011
   274
}
krista@2011
   275
vb@94
   276
static struct mailimf_mailbox * identity_to_mailbox(const pEp_identity *ident)
vb@94
   277
{
vb@94
   278
    char *_username = NULL;
vb@94
   279
    struct mailimf_mailbox *mb;
vb@94
   280
vb@977
   281
    _username = ident->username ? mailmime_encode_subject_header("utf-8",
vb@977
   282
            ident->username, 0) : strdup("");
vb@94
   283
    if (_username == NULL)
vb@94
   284
        goto enomem;
vb@94
   285
vb@94
   286
    mb = mailbox_from_string(_username, ident->address);
vb@94
   287
    if (mb == NULL)
vb@94
   288
        goto enomem;
vb@94
   289
vb@94
   290
    free(_username);
vb@94
   291
    _username = NULL;
vb@94
   292
vb@94
   293
    return mb;
vb@94
   294
vb@94
   295
enomem:
vb@94
   296
    free(_username);
vb@94
   297
    return NULL;
vb@94
   298
}
vb@94
   299
vb@94
   300
static struct mailimf_mailbox_list * identity_to_mbl(
vb@94
   301
        const pEp_identity *ident)
vb@90
   302
{
vb@90
   303
    struct mailimf_mailbox_list *mbl = NULL;
vb@90
   304
    struct mailimf_mailbox *mb = NULL;
vb@90
   305
    clist *list = NULL;
vb@90
   306
    int r;
vb@90
   307
vb@90
   308
    assert(ident);
vb@90
   309
vb@90
   310
    list = clist_new();
vb@90
   311
    if (list == NULL)
vb@90
   312
        goto enomem;
vb@90
   313
vb@94
   314
    mb = identity_to_mailbox(ident);
vb@90
   315
    if (mb == NULL)
vb@90
   316
        goto enomem;
vb@90
   317
vb@90
   318
    r = clist_append(list, mb);
vb@90
   319
    if (r)
vb@90
   320
        goto enomem;
vb@90
   321
vb@90
   322
    mbl = mailimf_mailbox_list_new(list);
vb@90
   323
    if (mbl == NULL)
vb@90
   324
        goto enomem;
vb@90
   325
vb@90
   326
    return mbl;
vb@90
   327
vb@90
   328
enomem:
vb@90
   329
    if (mb)
vb@90
   330
        mailimf_mailbox_free(mb);
vb@90
   331
vb@90
   332
    if (list)
vb@90
   333
        clist_free(list);
vb@90
   334
vb@90
   335
    return NULL;
vb@90
   336
}
vb@90
   337
vb@94
   338
static struct mailimf_address_list * identity_list_to_mal(identity_list *il)
vb@90
   339
{
vb@93
   340
    struct mailimf_address_list *mal = NULL;
vb@90
   341
    struct mailimf_mailbox *mb = NULL;
vb@93
   342
    struct mailimf_address * addr = NULL;
vb@90
   343
    clist *list = NULL;
vb@90
   344
    int r;
vb@90
   345
vb@90
   346
    assert(il);
vb@90
   347
vb@90
   348
    list = clist_new();
vb@90
   349
    if (list == NULL)
vb@90
   350
        goto enomem;
vb@90
   351
vb@90
   352
    identity_list *_il;
vb@1016
   353
    for (_il = il; _il && _il->ident; _il = _il->next) {
vb@94
   354
        mb = identity_to_mailbox(_il->ident);
vb@90
   355
        if (mb == NULL)
vb@90
   356
            goto enomem;
vb@90
   357
vb@93
   358
        addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
vb@93
   359
        if (addr == NULL)
vb@93
   360
            goto enomem;
vb@93
   361
        mb = NULL;
vb@93
   362
vb@93
   363
        r = clist_append(list, addr);
vb@90
   364
        if (r)
vb@90
   365
            goto enomem;
vb@93
   366
        addr = NULL;
vb@90
   367
    }
vb@93
   368
    mal = mailimf_address_list_new(list);
vb@93
   369
    if (mal == NULL)
vb@90
   370
        goto enomem;
vb@90
   371
vb@93
   372
    return mal;
vb@90
   373
vb@90
   374
enomem:
vb@90
   375
    if (mb)
vb@90
   376
        mailimf_mailbox_free(mb);
vb@90
   377
vb@93
   378
    if (addr)
vb@93
   379
        mailimf_address_free(addr);
vb@93
   380
vb@90
   381
    if (list)
vb@90
   382
        clist_free(list);
vb@90
   383
vb@90
   384
    return NULL;
vb@90
   385
}
vb@90
   386
vb@94
   387
static clist * stringlist_to_clist(stringlist_t *sl)
vb@91
   388
{
vb@91
   389
    clist * cl = clist_new();
vb@91
   390
    assert(cl);
vb@91
   391
    if (cl == NULL)
vb@91
   392
        return NULL;
vb@91
   393
vb@91
   394
    stringlist_t *_sl;
vb@91
   395
    for (_sl = sl; _sl; _sl = _sl->next) {
vb@91
   396
        int r;
vb@94
   397
        char * value = mailmime_encode_subject_header("utf-8", _sl->value, 0);
vb@91
   398
        assert(value);
vb@91
   399
        if (value == NULL) {
vb@91
   400
            clist_free(cl);
vb@91
   401
            return NULL;
vb@91
   402
        }
vb@91
   403
        r = clist_append(cl, value);
vb@91
   404
        assert(r == 0);
vb@91
   405
        if (r) {
vb@91
   406
            free(value);
vb@91
   407
            clist_free(cl);
vb@91
   408
            return NULL;
vb@91
   409
        }
vb@91
   410
    }
vb@91
   411
vb@91
   412
    return cl;
vb@91
   413
}
vb@91
   414
vb@89
   415
static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result)
vb@89
   416
{
vb@89
   417
    PEP_STATUS status = PEP_STATUS_OK;
vb@89
   418
    struct mailimf_fields * fields = NULL;
vb@89
   419
    int r;
vb@89
   420
    clist * fields_list = NULL;
vb@89
   421
    char *subject = msg->shortmsg ? msg->shortmsg : "pEp";
vb@89
   422
vb@89
   423
    assert(msg);
vb@89
   424
    assert(msg->from);
vb@89
   425
    assert(msg->from->address);
vb@89
   426
    assert(result);
vb@89
   427
vb@89
   428
    *result = NULL;
vb@89
   429
vb@89
   430
    fields_list = clist_new();
vb@89
   431
    assert(fields_list);
vb@89
   432
    if (fields_list == NULL)
vb@89
   433
        goto enomem;
vb@89
   434
vb@90
   435
    if (msg->id) {
vb@90
   436
        char *_msgid = strdup(msg->id);
vb@90
   437
        if (_msgid == NULL)
vb@90
   438
            goto enomem;
vb@89
   439
vb@90
   440
        r = _append_field(fields_list, MAILIMF_FIELD_MESSAGE_ID,
vb@90
   441
                (_new_func_t) mailimf_message_id_new, _msgid);
vb@90
   442
        if (r) {
vb@90
   443
            free(_msgid);
vb@90
   444
            goto enomem;
vb@90
   445
        }
vb@90
   446
    }
vb@90
   447
vb@90
   448
    if (msg->sent) {
vb@90
   449
        struct mailimf_date_time * dt = timestamp_to_etpantime(msg->sent);
vb@90
   450
        if (dt == NULL)
vb@90
   451
            goto enomem;
vb@90
   452
vb@90
   453
        r = _append_field(fields_list, MAILIMF_FIELD_ORIG_DATE,
vb@90
   454
                (_new_func_t) mailimf_orig_date_new, dt);
vb@90
   455
        if (r) {
vb@90
   456
            mailimf_date_time_free(dt);
vb@90
   457
            goto enomem;
vb@90
   458
        }
vb@90
   459
        dt = NULL;
vb@90
   460
    }
vb@90
   461
vb@91
   462
    /* if (msg->from) */ {
vb@94
   463
        struct mailimf_mailbox_list *from = identity_to_mbl(msg->from);
vb@90
   464
        if (from == NULL)
vb@90
   465
            goto enomem;
vb@90
   466
vb@90
   467
        r = _append_field(fields_list, MAILIMF_FIELD_FROM,
vb@90
   468
                (_new_func_t) mailimf_from_new, from);
vb@90
   469
        if (r) {
vb@90
   470
            mailimf_mailbox_list_free(from);
vb@90
   471
            goto enomem;
vb@90
   472
        }
vb@90
   473
    }
vb@90
   474
vb@90
   475
    if (msg->to) {
vb@94
   476
        struct mailimf_address_list *to = identity_list_to_mal(msg->to);
vb@90
   477
        if (to == NULL)
vb@90
   478
            goto enomem;
vb@90
   479
vb@91
   480
        r = _append_field(fields_list, MAILIMF_FIELD_TO,
vb@90
   481
                (_new_func_t) mailimf_to_new, to);
vb@90
   482
        if (r) {
vb@93
   483
            mailimf_address_list_free(to);
vb@90
   484
            goto enomem;
vb@90
   485
        }
vb@90
   486
    }
vb@89
   487
vb@112
   488
    /* if (subject) */ {
vb@112
   489
        char *_subject = mailmime_encode_subject_header("utf-8", subject, 1);
vb@112
   490
        if (_subject == NULL)
vb@112
   491
            goto enomem;
vb@112
   492
vb@112
   493
        r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
vb@112
   494
                (_new_func_t) mailimf_subject_new, _subject);
vb@112
   495
        if (r) {
vb@112
   496
            free(_subject);
vb@112
   497
            goto enomem;
vb@112
   498
        }
vb@112
   499
    }
vb@112
   500
vb@91
   501
    if (msg->cc) {
vb@94
   502
        struct mailimf_address_list *cc = identity_list_to_mal(msg->cc);
vb@91
   503
        if (cc == NULL)
vb@91
   504
            goto enomem;
vb@91
   505
vb@91
   506
        r = _append_field(fields_list, MAILIMF_FIELD_CC,
vb@91
   507
                (_new_func_t) mailimf_cc_new, cc);
vb@91
   508
        if (r) {
vb@93
   509
            mailimf_address_list_free(cc);
vb@91
   510
            goto enomem;
vb@91
   511
        }
vb@91
   512
    }
vb@91
   513
    
vb@91
   514
    if (msg->bcc) {
vb@94
   515
        struct mailimf_address_list *bcc = identity_list_to_mal(msg->bcc);
vb@91
   516
        if (bcc == NULL)
vb@91
   517
            goto enomem;
vb@91
   518
vb@91
   519
        r = _append_field(fields_list, MAILIMF_FIELD_BCC,
vb@91
   520
                (_new_func_t) mailimf_bcc_new, bcc);
vb@91
   521
        if (r) {
vb@93
   522
            mailimf_address_list_free(bcc);
vb@91
   523
            goto enomem;
vb@91
   524
        }
vb@91
   525
    }
vb@91
   526
    
vb@91
   527
    if (msg->reply_to) {
vb@94
   528
        struct mailimf_address_list *reply_to = identity_list_to_mal(msg->reply_to);
vb@91
   529
        if (reply_to == NULL)
vb@91
   530
            goto enomem;
vb@91
   531
vb@91
   532
        r = _append_field(fields_list, MAILIMF_FIELD_REPLY_TO,
vb@91
   533
                (_new_func_t) mailimf_reply_to_new, reply_to);
vb@91
   534
        if (r) {
vb@94
   535
            mailimf_address_list_free(reply_to);
vb@91
   536
            goto enomem;
vb@91
   537
        }
vb@91
   538
    }
vb@91
   539
vb@91
   540
    if (msg->in_reply_to) {
vb@94
   541
        clist *in_reply_to = stringlist_to_clist(msg->in_reply_to);
vb@91
   542
        if (in_reply_to == NULL)
vb@91
   543
            goto enomem;
vb@91
   544
vb@91
   545
        r = _append_field(fields_list, MAILIMF_FIELD_IN_REPLY_TO,
vb@91
   546
                (_new_func_t) mailimf_in_reply_to_new, in_reply_to);
vb@91
   547
        if (r) {
vb@94
   548
            clist_free(in_reply_to);
vb@91
   549
            goto enomem;
vb@91
   550
        }
vb@91
   551
    }
vb@91
   552
vb@91
   553
    if (msg->references) {
vb@94
   554
        clist *references = stringlist_to_clist(msg->references);
vb@91
   555
        if (references == NULL)
vb@91
   556
            goto enomem;
vb@91
   557
vb@91
   558
        r = _append_field(fields_list, MAILIMF_FIELD_REFERENCES,
vb@91
   559
                (_new_func_t) mailimf_references_new, references);
vb@91
   560
        if (r) {
vb@91
   561
            clist_free(references);
vb@91
   562
            goto enomem;
vb@91
   563
        }
vb@91
   564
    }
vb@91
   565
vb@91
   566
    if (msg->keywords) {
vb@94
   567
        clist *keywords = stringlist_to_clist(msg->keywords);
vb@91
   568
        if (keywords == NULL)
vb@91
   569
            goto enomem;
vb@91
   570
vb@91
   571
        r = _append_field(fields_list, MAILIMF_FIELD_KEYWORDS,
vb@91
   572
                (_new_func_t) mailimf_keywords_new, keywords);
vb@91
   573
        if (r) {
vb@91
   574
            clist_free(keywords);
vb@91
   575
            goto enomem;
vb@91
   576
        }
vb@91
   577
    }
vb@91
   578
vb@91
   579
    if (msg->comments) {
vb@94
   580
        char *comments = mailmime_encode_subject_header("utf-8", msg->comments,
vb@94
   581
                0);
vb@91
   582
        if (comments == NULL)
vb@91
   583
            goto enomem;
vb@91
   584
vb@91
   585
        r = _append_field(fields_list, MAILIMF_FIELD_COMMENTS,
vb@91
   586
                (_new_func_t) mailimf_comments_new, comments);
vb@91
   587
        if (r) {
vb@91
   588
            free(comments);
vb@91
   589
            goto enomem;
vb@91
   590
        }
vb@91
   591
    }
vb@91
   592
vb@98
   593
    if (msg->opt_fields) {
vb@110
   594
        stringpair_list_t *_l;
vb@281
   595
        for (_l = msg->opt_fields; _l && _l->value; _l = _l->next) {
vb@110
   596
            char *key = _l->value->key;
vb@110
   597
            char *value = _l->value->value;
vb@281
   598
            if (key && value) {
vb@281
   599
                char *_value = mailmime_encode_subject_header("utf-8", value, 0);
vb@281
   600
                if (_value == NULL)
vb@281
   601
                    goto enomem;
vb@110
   602
vb@281
   603
                r = _append_optional_field(fields_list, key, _value);
vb@281
   604
                free(_value);
vb@281
   605
                if (r)
vb@281
   606
                    goto enomem;
vb@281
   607
            }
vb@110
   608
        }
vb@98
   609
    }
vb@94
   610
vb@89
   611
    fields = mailimf_fields_new(fields_list);
vb@89
   612
    assert(fields);
vb@89
   613
    if (fields == NULL)
vb@89
   614
        goto enomem;
vb@89
   615
vb@89
   616
    *result = fields;
vb@89
   617
vb@89
   618
    return PEP_STATUS_OK;
vb@89
   619
vb@89
   620
enomem:
vb@89
   621
    status = PEP_OUT_OF_MEMORY;
vb@89
   622
vb@89
   623
    if (fields_list)
vb@89
   624
        clist_free(fields_list);
vb@89
   625
vb@89
   626
    if (fields)
vb@89
   627
        mailimf_fields_free(fields);
vb@89
   628
vb@89
   629
    return status;
vb@89
   630
}
vb@89
   631
krista@1873
   632
static bool has_exceptional_extension(char* filename) {
krista@1873
   633
    if (!filename)
krista@1873
   634
        return false;
krista@1873
   635
    int len = strlen(filename);
krista@1873
   636
    if (len < 4)
krista@1873
   637
        return false;
krista@1873
   638
    char* ext_start = filename + (len - 4);
krista@1873
   639
    if (strcmp(ext_start, ".pgp") == 0 || strcmp(ext_start, ".gpg") == 0 ||
krista@1873
   640
        strcmp(ext_start, ".asc") == 0 || strcmp(ext_start, ".pEp") == 0)
krista@1873
   641
        return true;
krista@1873
   642
    return false;
krista@1873
   643
}
krista@1873
   644
krista@1873
   645
static pEp_rid_list_t* choose_resource_id(pEp_rid_list_t* rid_list) {
krista@1882
   646
    pEp_rid_list_t* retval = rid_list;
krista@1873
   647
    
krista@1873
   648
    /* multiple elements - least common case */
krista@1873
   649
    if (rid_list && rid_list->next) {
krista@1873
   650
        pEp_rid_list_t* rid_list_curr = rid_list;
krista@1873
   651
        retval = rid_list; 
krista@1873
   652
        
krista@1873
   653
        while (rid_list_curr) {
krista@1873
   654
            pEp_resource_id_type rid_type = rid_list_curr->rid_type;
krista@1873
   655
            if (rid_type == PEP_RID_CID)
krista@1873
   656
                retval = rid_list_curr;
krista@1873
   657
            else if (rid_type == PEP_RID_FILENAME && has_exceptional_extension(rid_list_curr->rid))
krista@1873
   658
                return rid_list_curr;
krista@1873
   659
            rid_list_curr = rid_list_curr->next;
krista@1873
   660
        }
krista@1873
   661
    } 
krista@1873
   662
    return retval;
krista@1873
   663
}
krista@1873
   664
krista@2036
   665
// static void split_inlined_and_attached(bloblist_t** inlined, bloblist_t** attached) {
krista@2036
   666
//     bloblist_t** curr_pp = attached;
krista@2036
   667
//     bloblist_t* curr = *curr_pp;
krista@2036
   668
//     
krista@2036
   669
//     bloblist_t* inline_ret = NULL;
krista@2036
   670
//     bloblist_t** inline_curr_pp = &inline_ret;
krista@2036
   671
//     
krista@2036
   672
//     bloblist_t* att_ret = NULL;
krista@2036
   673
//     bloblist_t** att_curr_pp = &att_ret;
krista@2036
   674
//     
krista@2036
   675
//     while (curr) {
krista@2036
   676
//         if (curr->disposition == PEP_CONTENT_DISP_INLINE) {
krista@2036
   677
//             *inline_curr_pp = curr;
krista@2036
   678
//             inline_curr_pp = &(curr->next);
krista@2036
   679
//         }
krista@2036
   680
//         else {
krista@2036
   681
//             *att_curr_pp = curr;
krista@2036
   682
//             att_curr_pp = &(curr->next);            
krista@2036
   683
//         }
krista@2036
   684
//         *curr_pp = curr->next;
krista@2036
   685
//         curr->next = NULL;
krista@2036
   686
//         curr = *curr_pp;
krista@2036
   687
//     }
krista@2036
   688
//     
krista@2036
   689
//     *inlined = inline_ret;
krista@2036
   690
//     *attached = att_ret;
krista@2036
   691
// }
krista@2011
   692
krista@2011
   693
vb@114
   694
static PEP_STATUS mime_encode_message_plain(
vb@89
   695
        const message *msg,
vb@113
   696
        bool omit_fields,
vb@114
   697
        struct mailmime **result
vb@89
   698
    )
vb@89
   699
{
vb@89
   700
    struct mailmime * mime = NULL;
vb@89
   701
    struct mailmime * submime = NULL;
vb@89
   702
    int r;
vb@89
   703
    PEP_STATUS status;
roker@723
   704
    //char *subject;
vb@89
   705
    char *plaintext;
vb@89
   706
    char *htmltext;
vb@89
   707
vb@89
   708
    assert(msg);
vb@114
   709
    assert(result);
krista@2035
   710
    
roker@723
   711
    //subject = (msg->shortmsg) ? msg->shortmsg : "pEp";  // not used, yet.
vb@89
   712
    plaintext = (msg->longmsg) ? msg->longmsg : "";
vb@89
   713
    htmltext = msg->longmsg_formatted;
vb@89
   714
krista@1197
   715
    if (htmltext && (htmltext[0] != '\0')) {
krista@2011
   716
        /* first, we need to strip out the inlined attachments to ensure this
krista@2011
   717
           gets set up correctly */
krista@2036
   718
           
krista@2036
   719
        status = mime_html_text(plaintext, htmltext, msg->attachments, &mime);
krista@2027
   720
                
vb@89
   721
        if (status != PEP_STATUS_OK)
vb@89
   722
            goto pep_error;
vb@89
   723
    }
vb@89
   724
    else {
krista@1878
   725
        pEp_rid_list_t* resource = NULL;
krista@1878
   726
        if (is_PGP_message_text(plaintext)) {
krista@1878
   727
            resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
krista@1878
   728
            mime = get_text_part(resource, "application/octet-stream", plaintext,
vb@114
   729
                    strlen(plaintext), MAILMIME_MECHANISM_7BIT);
krista@1878
   730
        }
krista@1878
   731
        else {
krista@1878
   732
            resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
krista@1878
   733
            mime = get_text_part(resource, "text/plain", plaintext, strlen(plaintext),
vb@114
   734
                    MAILMIME_MECHANISM_QUOTED_PRINTABLE);
krista@1878
   735
        }
krista@1878
   736
        free_rid_list(resource);
krista@1878
   737
        
vb@89
   738
        assert(mime);
vb@89
   739
        if (mime == NULL)
vb@89
   740
            goto enomem;
vb@89
   741
    }
vb@89
   742
krista@2036
   743
    bool normal_attachments = false;
krista@2036
   744
    
krista@2036
   745
    bloblist_t* traversal_ptr = msg->attachments;
krista@2036
   746
    
krista@2036
   747
    while (traversal_ptr) {
krista@2036
   748
        if (traversal_ptr->disposition != PEP_CONTENT_DISP_INLINE) {
krista@2036
   749
            normal_attachments = true;
krista@2036
   750
            break;
krista@2036
   751
        }
krista@2036
   752
        traversal_ptr = traversal_ptr->next;
krista@2036
   753
    }
krista@2036
   754
krista@2035
   755
    if (normal_attachments) {
vb@89
   756
        submime = mime;
vb@116
   757
        mime = part_multiple_new("multipart/mixed");
vb@89
   758
        assert(mime);
vb@89
   759
        if (mime == NULL)
vb@89
   760
            goto enomem;
vb@89
   761
vb@89
   762
        r = mailmime_smart_add_part(mime, submime);
vb@89
   763
        assert(r == MAILIMF_NO_ERROR);
vb@89
   764
        if (r == MAILIMF_ERROR_MEMORY) {
vb@89
   765
            goto enomem;
vb@89
   766
        }
vb@89
   767
        else {
vb@89
   768
            // mailmime_smart_add_part() takes ownership of submime
vb@89
   769
            submime = NULL;
vb@89
   770
        }
vb@89
   771
vb@89
   772
        bloblist_t *_a;
krista@2036
   773
        for (_a = msg->attachments; _a != NULL; _a = _a->next) {
vb@89
   774
krista@2036
   775
            if (_a->disposition == PEP_CONTENT_DISP_INLINE)
krista@2036
   776
                continue;
krista@2036
   777
vb@89
   778
            status = mime_attachment(_a, &submime);
vb@89
   779
            if (status != PEP_STATUS_OK)
vb@89
   780
                goto pep_error;
vb@89
   781
vb@89
   782
            r = mailmime_smart_add_part(mime, submime);
vb@89
   783
            assert(r == MAILIMF_NO_ERROR);
vb@89
   784
            if (r == MAILIMF_ERROR_MEMORY) {
vb@89
   785
                goto enomem;
vb@89
   786
            }
vb@89
   787
            else {
vb@89
   788
                // mailmime_smart_add_part() takes ownership of submime
vb@89
   789
                submime = NULL;
vb@89
   790
            }
vb@89
   791
        }
vb@89
   792
    }
vb@89
   793
vb@114
   794
    *result = mime;
vb@114
   795
    return PEP_STATUS_OK;
vb@114
   796
vb@114
   797
enomem:
vb@114
   798
    status = PEP_OUT_OF_MEMORY;
vb@114
   799
vb@114
   800
pep_error:
vb@114
   801
    if (mime)
vb@114
   802
        mailmime_free(mime);
vb@114
   803
vb@114
   804
    if (submime)
vb@114
   805
        mailmime_free(submime);
vb@114
   806
vb@114
   807
    return status;
vb@114
   808
}
vb@114
   809
vb@114
   810
static PEP_STATUS mime_encode_message_PGP_MIME(
vb@114
   811
        const message * msg,
vb@114
   812
        bool omit_fields,
vb@114
   813
        struct mailmime **result
vb@114
   814
    )
vb@114
   815
{
vb@114
   816
    struct mailmime * mime = NULL;
vb@114
   817
    struct mailmime * submime = NULL;
vb@114
   818
	struct mailmime_parameter * param;
vb@114
   819
    int r;
vb@114
   820
    PEP_STATUS status;
roker@723
   821
    //char *subject;
vb@114
   822
    char *plaintext;
edouard@1274
   823
    size_t plaintext_size;
vb@114
   824
vb@260
   825
    assert(msg->attachments && msg->attachments->next &&
vb@301
   826
            msg->attachments->next->value);
vb@114
   827
roker@723
   828
    //subject = (msg->shortmsg) ? msg->shortmsg : "pEp"; // not used, yet.
vb@301
   829
    plaintext = msg->attachments->next->value;
edouard@1274
   830
    plaintext_size = msg->attachments->next->size;
vb@114
   831
vb@116
   832
    mime = part_multiple_new("multipart/encrypted");
vb@114
   833
    assert(mime);
vb@114
   834
    if (mime == NULL)
vb@114
   835
        goto enomem;
vb@114
   836
vb@114
   837
    param = mailmime_param_new_with_data("protocol", "application/pgp-encrypted");
vb@114
   838
    clist_append(mime->mm_content_type->ct_parameters, param);
vb@114
   839
vb@114
   840
    submime = get_pgp_encrypted_part();
vb@114
   841
    assert(submime);
vb@114
   842
    if (submime == NULL)
vb@114
   843
        goto enomem;
vb@114
   844
vb@114
   845
    r = mailmime_smart_add_part(mime, submime);
vb@114
   846
    assert(r == MAILIMF_NO_ERROR);
vb@114
   847
    if (r == MAILIMF_ERROR_MEMORY) {
vb@114
   848
        goto enomem;
vb@114
   849
    }
vb@114
   850
    else {
vb@114
   851
        // mailmime_smart_add_part() takes ownership of submime
vb@114
   852
        submime = NULL;
vb@114
   853
    }
vb@114
   854
krista@1878
   855
    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
krista@1878
   856
    submime = get_text_part(resource, "application/octet-stream", plaintext,
edouard@1274
   857
            plaintext_size, MAILMIME_MECHANISM_7BIT);
krista@1878
   858
            
krista@1878
   859
    free_rid_list(resource);
krista@1878
   860
    
vb@114
   861
    assert(submime);
vb@114
   862
    if (submime == NULL)
vb@114
   863
        goto enomem;
vb@114
   864
vb@114
   865
    r = mailmime_smart_add_part(mime, submime);
vb@114
   866
    assert(r == MAILIMF_NO_ERROR);
vb@114
   867
    if (r == MAILIMF_ERROR_MEMORY) {
vb@114
   868
        goto enomem;
vb@114
   869
    }
vb@114
   870
    else {
vb@114
   871
        // mailmime_smart_add_part() takes ownership of submime
vb@114
   872
        submime = NULL;
vb@114
   873
    }
vb@114
   874
vb@114
   875
    *result = mime;
vb@114
   876
    return PEP_STATUS_OK;
vb@114
   877
vb@114
   878
enomem:
vb@114
   879
    status = PEP_OUT_OF_MEMORY;
vb@114
   880
vb@114
   881
    if (mime)
vb@114
   882
        mailmime_free(mime);
vb@114
   883
vb@114
   884
    if (submime)
vb@114
   885
        mailmime_free(submime);
vb@114
   886
vb@114
   887
    return status;
vb@114
   888
}
vb@114
   889
vb@114
   890
DYNAMIC_API PEP_STATUS mime_encode_message(
vb@114
   891
        const message * msg,
vb@114
   892
        bool omit_fields,
vb@114
   893
        char **mimetext
vb@114
   894
    )
vb@114
   895
{
vb@114
   896
    PEP_STATUS status = PEP_STATUS_OK;
vb@114
   897
    struct mailmime * msg_mime = NULL;
vb@114
   898
    struct mailmime * mime = NULL;
vb@114
   899
    struct mailimf_fields * fields = NULL;
vb@114
   900
    char *buf = NULL;
vb@114
   901
    int r;
vb@114
   902
vb@114
   903
    assert(msg);
vb@114
   904
    assert(mimetext);
vb@114
   905
vb@260
   906
    if (!(msg && mimetext))
vb@191
   907
        return PEP_ILLEGAL_VALUE;
vb@191
   908
vb@114
   909
    *mimetext = NULL;
vb@114
   910
vb@114
   911
    switch (msg->enc_format) {
vb@114
   912
        case PEP_enc_none:
vb@114
   913
            status = mime_encode_message_plain(msg, omit_fields, &mime);
vb@114
   914
            break;
vb@114
   915
vb@114
   916
        case PEP_enc_pieces:
vb@114
   917
            status = mime_encode_message_plain(msg, omit_fields, &mime);
vb@114
   918
            break;
vb@114
   919
vb@114
   920
        case PEP_enc_S_MIME:
vb@114
   921
            NOT_IMPLEMENTED
vb@114
   922
                
vb@114
   923
        case PEP_enc_PGP_MIME:
vb@114
   924
            status = mime_encode_message_PGP_MIME(msg, omit_fields, &mime);
vb@114
   925
            break;
vb@114
   926
vb@114
   927
        case PEP_enc_PEP:
vb@114
   928
            NOT_IMPLEMENTED
edouard@1557
   929
edouard@1557
   930
        default:
edouard@1557
   931
            NOT_IMPLEMENTED
vb@114
   932
    }
vb@114
   933
vb@114
   934
    if (status != PEP_STATUS_OK)
vb@114
   935
        goto pep_error;
vb@114
   936
vb@89
   937
    msg_mime = mailmime_new_message_data(NULL);
vb@90
   938
    assert(msg_mime);
vb@90
   939
    if (msg_mime == NULL)
vb@90
   940
        goto enomem;
vb@89
   941
vb@90
   942
    r = mailmime_add_part(msg_mime, mime);
vb@90
   943
    if (r) {
vb@90
   944
        mailmime_free(mime);
vb@90
   945
        goto enomem;
vb@90
   946
    }
vb@114
   947
    mime = NULL;
vb@90
   948
vb@113
   949
    if (!omit_fields) {
vb@113
   950
        status = build_fields(msg, &fields);
vb@113
   951
        if (status != PEP_STATUS_OK)
vb@113
   952
            goto pep_error;
vb@90
   953
vb@113
   954
        mailmime_set_imf_fields(msg_mime, fields);
vb@113
   955
    }
vb@90
   956
vb@90
   957
    status = render_mime(msg_mime, &buf);
vb@89
   958
    if (status != PEP_STATUS_OK)
vb@89
   959
        goto pep_error;
vb@89
   960
vb@89
   961
    mailmime_free(msg_mime);
vb@89
   962
    *mimetext = buf;
vb@90
   963
vb@89
   964
    return PEP_STATUS_OK;
vb@89
   965
vb@89
   966
enomem:
vb@89
   967
    status = PEP_OUT_OF_MEMORY;
vb@89
   968
vb@89
   969
pep_error:
vb@89
   970
    if (msg_mime)
vb@90
   971
        mailmime_free(msg_mime);
vb@89
   972
    else
vb@89
   973
        if (mime)
vb@89
   974
            mailmime_free(mime);
vb@89
   975
vb@89
   976
    return status;
vb@89
   977
}
vb@89
   978
vb@94
   979
static pEp_identity *mailbox_to_identity(const struct mailimf_mailbox * mb)
vb@94
   980
{
vb@94
   981
    char *username = NULL;
vb@94
   982
vb@159
   983
    assert(mb);
vb@159
   984
    assert(mb->mb_addr_spec);
vb@159
   985
vb@159
   986
    if (mb->mb_addr_spec == NULL)
vb@159
   987
        return NULL;
vb@159
   988
vb@159
   989
    if (mb->mb_display_name) {
roker@871
   990
        size_t index = 0;
roker@871
   991
        const int r = mailmime_encoded_phrase_parse("utf-8", mb->mb_display_name,
vb@159
   992
                strlen(mb->mb_display_name), &index, "utf-8", &username);
vb@159
   993
        if (r)
vb@159
   994
            goto enomem;
vb@159
   995
    }
vb@94
   996
roker@871
   997
    pEp_identity *ident = new_identity(mb->mb_addr_spec, NULL, NULL, username);
vb@94
   998
    if (ident == NULL)
vb@94
   999
        goto enomem;
vb@94
  1000
    free(username);
vb@94
  1001
vb@94
  1002
    return ident;
vb@94
  1003
vb@94
  1004
enomem:
vb@94
  1005
    free(username);
vb@94
  1006
    return NULL;
vb@94
  1007
}
vb@94
  1008
vb@94
  1009
static pEp_identity * mbl_to_identity(const struct mailimf_mailbox_list * mbl)
vb@94
  1010
{
vb@94
  1011
    struct mailimf_mailbox * mb = clist_content(clist_begin(mbl->mb_list));
vb@94
  1012
    return mailbox_to_identity(mb);
vb@94
  1013
}
vb@94
  1014
vb@94
  1015
static identity_list * mal_to_identity_list(
vb@94
  1016
        const struct mailimf_address_list *mal
vb@94
  1017
    )
vb@94
  1018
{
roker@871
  1019
    assert(mal);
vb@94
  1020
    clist *list = mal->ad_list;
vb@94
  1021
roker@871
  1022
    identity_list *il = new_identity_list(NULL);
vb@94
  1023
    if (il == NULL)
vb@94
  1024
        goto enomem;
vb@94
  1025
vb@94
  1026
    identity_list *_il = il;
roker@871
  1027
    for (clistiter *cur = clist_begin(list); cur != NULL ; cur = clist_next(cur)) {
vb@94
  1028
        pEp_identity *ident;
vb@94
  1029
roker@871
  1030
        struct mailimf_address *addr = clist_content(cur);
vb@94
  1031
        switch(addr->ad_type) {
vb@94
  1032
            case MAILIMF_ADDRESS_MAILBOX:
vb@94
  1033
                ident = mailbox_to_identity(addr->ad_data.ad_mailbox);
vb@94
  1034
                if (ident == NULL)
vb@94
  1035
                    goto enomem;
vb@94
  1036
                _il = identity_list_add(_il, ident);
vb@94
  1037
                if (_il == NULL)
vb@94
  1038
                    goto enomem;
vb@94
  1039
                break;
vb@94
  1040
vb@94
  1041
            case MAILIMF_ADDRESS_GROUP:
vb@94
  1042
                {
vb@94
  1043
                    struct mailimf_mailbox_list * mbl =
vb@94
  1044
                            addr->ad_data.ad_group->grp_mb_list;
roker@871
  1045
                    for (clistiter *cur2 = clist_begin(mbl->mb_list); cur2 != NULL;
vb@94
  1046
                            cur2 = clist_next(cur2)) {
vb@94
  1047
                        ident = mailbox_to_identity(clist_content(cur));
vb@94
  1048
                        if (ident == NULL)
vb@94
  1049
                            goto enomem;
vb@94
  1050
                        _il = identity_list_add(_il, ident);
vb@94
  1051
                        if (_il == NULL)
vb@94
  1052
                            goto enomem;
vb@94
  1053
                    }
vb@94
  1054
                }
vb@94
  1055
                break;
vb@94
  1056
vb@94
  1057
            default:
vb@94
  1058
                assert(0);
vb@94
  1059
                goto enomem;
vb@94
  1060
        }
vb@94
  1061
    }
vb@94
  1062
vb@94
  1063
    return il;
vb@94
  1064
vb@94
  1065
enomem:
vb@94
  1066
    free_identity_list(il);
vb@94
  1067
    return NULL;
vb@94
  1068
}
vb@94
  1069
vb@94
  1070
static stringlist_t * clist_to_stringlist(const clist *list)
vb@94
  1071
{
vb@94
  1072
    char *text = NULL;;
vb@94
  1073
    stringlist_t * sl = new_stringlist(NULL);
vb@94
  1074
    if (sl == NULL)
vb@94
  1075
        return NULL;
vb@94
  1076
vb@94
  1077
    stringlist_t *_sl = sl;
roker@871
  1078
    for (clistiter *cur = clist_begin(list); cur != NULL; cur = clist_next(cur)) {
vb@94
  1079
        char *phrase = clist_content(cur);
roker@871
  1080
        size_t index = 0;
roker@871
  1081
        
roker@871
  1082
        const int r = mailmime_encoded_phrase_parse("utf-8", phrase, strlen(phrase),
vb@94
  1083
                &index, "utf-8", &text);
vb@94
  1084
        if (r)
vb@94
  1085
            goto enomem;
vb@94
  1086
vb@94
  1087
        _sl = stringlist_add(_sl, text);
vb@94
  1088
        if (_sl == NULL)
vb@94
  1089
            goto enomem;
vb@94
  1090
vb@94
  1091
        free(text);
vb@94
  1092
        text = NULL;
vb@94
  1093
    }
vb@94
  1094
vb@94
  1095
    return _sl;
vb@94
  1096
vb@94
  1097
enomem:
vb@94
  1098
    free_stringlist(sl);
vb@94
  1099
    free(text);
vb@94
  1100
vb@94
  1101
    return NULL;
vb@94
  1102
}
vb@94
  1103
vb@94
  1104
static PEP_STATUS read_fields(message *msg, clist *fieldlist)
vb@94
  1105
{
vb@94
  1106
    PEP_STATUS status = PEP_STATUS_OK;
vb@94
  1107
    struct mailimf_field * _field;
vb@94
  1108
    clistiter *cur;
vb@94
  1109
    size_t index;
vb@94
  1110
    int r;
vb@110
  1111
    stringpair_list_t *opt = msg->opt_fields;
vb@94
  1112
vb@94
  1113
    for (cur = clist_begin(fieldlist); cur != NULL; cur = clist_next(cur)) {
vb@94
  1114
        _field = clist_content(cur);
vb@94
  1115
vb@94
  1116
        switch (_field->fld_type) {
vb@94
  1117
            case MAILIMF_FIELD_MESSAGE_ID:
vb@94
  1118
                {
vb@94
  1119
                    char * text = _field->fld_data.fld_message_id->mid_value;
vb@116
  1120
vb@116
  1121
                    free(msg->id);
vb@94
  1122
                    index = 0;
vb@94
  1123
                    r = mailmime_encoded_phrase_parse("utf-8", text,
vb@94
  1124
                            strlen(text), &index, "utf-8", &msg->id);
vb@94
  1125
                    if (r)
vb@94
  1126
                        goto enomem;
vb@94
  1127
                }
vb@94
  1128
                break;
vb@94
  1129
vb@94
  1130
            case MAILIMF_FIELD_SUBJECT:
vb@94
  1131
                {
vb@94
  1132
                    char * text = _field->fld_data.fld_subject->sbj_value;
vb@116
  1133
vb@116
  1134
                    free(msg->shortmsg);
vb@94
  1135
                    index = 0;
vb@94
  1136
                    r = mailmime_encoded_phrase_parse("utf-8", text,
vb@94
  1137
                            strlen(text), &index, "utf-8", &msg->shortmsg);
vb@94
  1138
                    if (r)
vb@94
  1139
                        goto enomem;
vb@94
  1140
                }
vb@94
  1141
                break;
vb@94
  1142
vb@94
  1143
            case MAILIMF_FIELD_ORIG_DATE:
vb@94
  1144
                {
vb@94
  1145
                    struct mailimf_date_time *date =
vb@94
  1146
                        _field->fld_data.fld_orig_date->dt_date_time;
vb@116
  1147
vb@116
  1148
                    free_timestamp(msg->sent);
vb@94
  1149
                    msg->sent = etpantime_to_timestamp(date);
vb@94
  1150
                    if (msg->sent == NULL)
vb@94
  1151
                        goto enomem;
vb@94
  1152
                }
vb@94
  1153
                break;
vb@94
  1154
vb@94
  1155
            case MAILIMF_FIELD_FROM:
vb@94
  1156
                {
vb@94
  1157
                    struct mailimf_mailbox_list *mbl =
vb@94
  1158
                            _field->fld_data.fld_from->frm_mb_list;
vb@94
  1159
                    pEp_identity *ident;
vb@94
  1160
vb@94
  1161
                    ident = mbl_to_identity(mbl);
vb@94
  1162
                    if (ident == NULL)
vb@94
  1163
                        goto pep_error;
vb@94
  1164
vb@116
  1165
                    free_identity(msg->from);
vb@94
  1166
                    msg->from = ident;
vb@94
  1167
                }
vb@94
  1168
                break;
vb@94
  1169
vb@94
  1170
            case MAILIMF_FIELD_TO:
vb@94
  1171
                {
vb@94
  1172
                    struct mailimf_address_list *mal =
vb@94
  1173
                            _field->fld_data.fld_to->to_addr_list;
vb@94
  1174
                    identity_list *il = mal_to_identity_list(mal);
vb@94
  1175
                    if (il == NULL)
vb@94
  1176
                        goto enomem;
vb@116
  1177
vb@116
  1178
                    free_identity_list(msg->to);
vb@94
  1179
                    msg->to = il;
vb@94
  1180
                }
vb@94
  1181
                break;
vb@94
  1182
vb@94
  1183
            case MAILIMF_FIELD_CC:
vb@94
  1184
                {
vb@94
  1185
                    struct mailimf_address_list *mal =
vb@94
  1186
                            _field->fld_data.fld_cc->cc_addr_list;
vb@94
  1187
                    identity_list *il = mal_to_identity_list(mal);
vb@94
  1188
                    if (il == NULL)
vb@94
  1189
                        goto enomem;
vb@116
  1190
vb@116
  1191
                    free_identity_list(msg->cc);
vb@94
  1192
                    msg->cc = il;
vb@94
  1193
                }
vb@94
  1194
                break;
vb@94
  1195
vb@94
  1196
            case MAILIMF_FIELD_BCC:
vb@94
  1197
                {
vb@94
  1198
                    struct mailimf_address_list *mal =
vb@94
  1199
                            _field->fld_data.fld_bcc->bcc_addr_list;
vb@94
  1200
                    identity_list *il = mal_to_identity_list(mal);
vb@94
  1201
                    if (il == NULL)
vb@94
  1202
                        goto enomem;
vb@116
  1203
vb@116
  1204
                    free_identity_list(msg->bcc);
vb@94
  1205
                    msg->bcc = il;
vb@94
  1206
                }
vb@94
  1207
                break;
vb@94
  1208
vb@94
  1209
            case MAILIMF_FIELD_REPLY_TO:
vb@94
  1210
                {
vb@94
  1211
                    struct mailimf_address_list *mal =
vb@94
  1212
                            _field->fld_data.fld_reply_to->rt_addr_list;
vb@94
  1213
                    identity_list *il = mal_to_identity_list(mal);
vb@94
  1214
                    if (il == NULL)
vb@94
  1215
                        goto enomem;
vb@116
  1216
vb@116
  1217
                    free_identity_list(msg->reply_to);
vb@94
  1218
                    msg->reply_to = il;
vb@94
  1219
                }
vb@94
  1220
                break;
vb@94
  1221
vb@94
  1222
            case MAILIMF_FIELD_IN_REPLY_TO:
vb@94
  1223
                {
vb@94
  1224
                    clist *list = _field->fld_data.fld_in_reply_to->mid_list;
vb@94
  1225
                    stringlist_t *sl = clist_to_stringlist(list);
vb@94
  1226
                    if (sl == NULL)
vb@94
  1227
                        goto enomem;
vb@116
  1228
vb@116
  1229
                    free_stringlist(msg->in_reply_to);
vb@94
  1230
                    msg->in_reply_to = sl;
vb@94
  1231
                }
vb@94
  1232
                break;
vb@94
  1233
vb@94
  1234
            case MAILIMF_FIELD_REFERENCES:
vb@94
  1235
                {
vb@94
  1236
                    clist *list = _field->fld_data.fld_references->mid_list;
vb@94
  1237
                    stringlist_t *sl = clist_to_stringlist(list);
vb@94
  1238
                    if (sl == NULL)
vb@94
  1239
                        goto enomem;
vb@116
  1240
vb@116
  1241
                    free_stringlist(msg->references);
vb@94
  1242
                    msg->references = sl;
vb@94
  1243
                }
vb@94
  1244
                break;
vb@94
  1245
vb@94
  1246
            case MAILIMF_FIELD_KEYWORDS:
vb@94
  1247
                {
vb@94
  1248
                    clist *list = _field->fld_data.fld_keywords->kw_list;
vb@94
  1249
                    stringlist_t *sl = clist_to_stringlist(list);
vb@94
  1250
                    if (sl == NULL)
vb@94
  1251
                        goto enomem;
vb@116
  1252
vb@116
  1253
                    free_stringlist(msg->keywords);
vb@94
  1254
                    msg->keywords = sl;
vb@94
  1255
                }
vb@94
  1256
                break;
vb@94
  1257
vb@94
  1258
            case MAILIMF_FIELD_COMMENTS:
vb@94
  1259
                {
vb@94
  1260
                    char * text = _field->fld_data.fld_comments->cm_value;
vb@116
  1261
vb@116
  1262
                    free(msg->comments);
vb@94
  1263
                    index = 0;
vb@94
  1264
                    r = mailmime_encoded_phrase_parse("utf-8", text,
vb@94
  1265
                            strlen(text), &index, "utf-8", &msg->comments);
vb@94
  1266
                    if (r)
vb@94
  1267
                        goto enomem;
vb@94
  1268
                }
vb@94
  1269
                break;
vb@110
  1270
vb@110
  1271
            case MAILIMF_FIELD_OPTIONAL_FIELD:
vb@110
  1272
                {
vb@110
  1273
                    char * name =
vb@110
  1274
                            _field->fld_data.fld_optional_field->fld_name;
vb@110
  1275
                    char * value =
vb@110
  1276
                            _field->fld_data.fld_optional_field->fld_value;
vb@110
  1277
                    char *_value;
vb@110
  1278
vb@110
  1279
                    index = 0;
vb@110
  1280
                    r = mailmime_encoded_phrase_parse("utf-8", value,
vb@110
  1281
                            strlen(value), &index, "utf-8", &_value);
vb@110
  1282
                    if (r)
vb@110
  1283
                        goto enomem;
vb@110
  1284
vb@281
  1285
                    stringpair_t *pair = new_stringpair(name, _value);
vb@281
  1286
                    if (pair == NULL)
vb@281
  1287
                        goto enomem;
vb@110
  1288
vb@281
  1289
                    opt = stringpair_list_add(opt, pair);
vb@110
  1290
                    free(_value);
vb@110
  1291
                    if (opt == NULL)
vb@110
  1292
                        goto enomem;
vb@110
  1293
vb@110
  1294
                    if (msg->opt_fields == NULL)
vb@110
  1295
                        msg->opt_fields = opt;
vb@110
  1296
                }
vb@110
  1297
                break;
vb@94
  1298
        }
vb@94
  1299
    }
vb@94
  1300
vb@94
  1301
    return PEP_STATUS_OK;
vb@94
  1302
vb@94
  1303
enomem:
vb@94
  1304
    status = PEP_OUT_OF_MEMORY;
vb@94
  1305
vb@94
  1306
pep_error:
vb@94
  1307
    return status;
vb@94
  1308
}
vb@94
  1309
vb@147
  1310
static PEP_STATUS interpret_body(struct mailmime *part, char **longmsg, size_t *size)
vb@147
  1311
{
vb@147
  1312
    const char *text;
vb@159
  1313
    char *_longmsg;
vb@147
  1314
    size_t length;
vb@159
  1315
    size_t _size;
vb@147
  1316
    int code;
vb@147
  1317
    int r;
vb@147
  1318
    size_t index;
vb@159
  1319
    char *type = NULL;
vb@159
  1320
    char *charset = NULL;
vb@147
  1321
vb@147
  1322
    assert(part);
vb@147
  1323
    assert(longmsg);
vb@147
  1324
vb@147
  1325
    *longmsg = NULL;
vb@147
  1326
    if (size)
vb@147
  1327
        *size = 0;
vb@147
  1328
vb@147
  1329
    if (part->mm_body == NULL)
vb@147
  1330
        return PEP_ILLEGAL_VALUE;
vb@147
  1331
vb@147
  1332
    text = part->mm_body-> dt_data.dt_text.dt_data;
vb@147
  1333
    if (text == NULL)
vb@147
  1334
        return PEP_ILLEGAL_VALUE;
vb@147
  1335
vb@147
  1336
    length = part->mm_body->dt_data.dt_text.dt_length;
vb@147
  1337
vb@147
  1338
    if (part->mm_body->dt_encoded) {
vb@147
  1339
        code = part->mm_body->dt_encoding;
vb@147
  1340
        index = 0;
vb@159
  1341
        r = mailmime_part_parse(text, length, &index, code, &_longmsg, &_size);
vb@147
  1342
        switch (r) {
vb@147
  1343
            case MAILIMF_NO_ERROR:
vb@147
  1344
                break;
vb@147
  1345
            case MAILIMF_ERROR_MEMORY:
vb@147
  1346
                return PEP_OUT_OF_MEMORY;
vb@147
  1347
            default:
vb@147
  1348
                return PEP_ILLEGAL_VALUE;
vb@147
  1349
        }
vb@147
  1350
    }
vb@147
  1351
    else {
vb@289
  1352
        _size = length + 1;
vb@289
  1353
        _longmsg = strndup(text, length);
vb@159
  1354
        if (_longmsg == NULL)
vb@147
  1355
            return PEP_OUT_OF_MEMORY;
vb@147
  1356
    }
vb@147
  1357
vb@159
  1358
    if (part->mm_content_type) {
vb@159
  1359
        if (_get_content_type(part->mm_content_type, &type, &charset) == 0) {
vb@160
  1360
            if (charset && strncasecmp(charset, "utf-8", 5) != 0) {
vb@159
  1361
                char * _text;
vb@159
  1362
                int r = charconv("utf-8", charset, _longmsg, _size, &_text);
vb@159
  1363
                switch (r) {
vb@159
  1364
                    case MAILIMF_NO_ERROR:
vb@159
  1365
                        break;
vb@159
  1366
                    case MAILIMF_ERROR_MEMORY:
vb@159
  1367
                        return PEP_OUT_OF_MEMORY;
vb@159
  1368
                    default:
vb@159
  1369
                        return PEP_ILLEGAL_VALUE;
vb@159
  1370
                }
vb@159
  1371
                free(_longmsg);
vb@159
  1372
                _longmsg = _text;
vb@159
  1373
            }
vb@159
  1374
        }
vb@159
  1375
    }
krista@1536
  1376
    // FIXME: KG - we now have the text we want.
krista@1536
  1377
    // Now we need to strip sigs and process them if they are there..
krista@1536
  1378
    
vb@159
  1379
vb@159
  1380
    *longmsg = _longmsg;
vb@159
  1381
    if (size)
vb@159
  1382
        *size = _size;
vb@159
  1383
vb@147
  1384
    return PEP_STATUS_OK;
vb@147
  1385
}
vb@147
  1386
vb@118
  1387
static PEP_STATUS interpret_MIME(
vb@118
  1388
        struct mailmime *mime,
vb@118
  1389
        message *msg
vb@118
  1390
    )
vb@118
  1391
{
vb@118
  1392
    PEP_STATUS status = PEP_STATUS_OK;
vb@118
  1393
vb@118
  1394
    assert(mime);
vb@118
  1395
    assert(msg);
vb@118
  1396
vb@118
  1397
    struct mailmime_content *content = mime->mm_content_type;
vb@118
  1398
    if (content) {
vb@152
  1399
        if (_is_multipart(content, "alternative")) {
vb@118
  1400
            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
vb@118
  1401
            if (partlist == NULL)
vb@118
  1402
                return PEP_ILLEGAL_VALUE;
vb@118
  1403
vb@118
  1404
            clistiter *cur;
vb@118
  1405
            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
vb@120
  1406
                struct mailmime *part = clist_content(cur);
vb@118
  1407
                if (part == NULL)
vb@118
  1408
                    return PEP_ILLEGAL_VALUE;
vb@118
  1409
vb@120
  1410
                content = part->mm_content_type;
vb@120
  1411
                assert(content);
vb@120
  1412
                if (content == NULL)
vb@120
  1413
                    return PEP_ILLEGAL_VALUE;
vb@118
  1414
vb@152
  1415
                if (_is_text_part(content, "plain") && msg->longmsg == NULL) {
vb@152
  1416
                    status = interpret_body(part, &msg->longmsg, NULL);
vb@152
  1417
                    if (status)
vb@152
  1418
                        return status;
vb@152
  1419
                }
vb@152
  1420
                else if (_is_text_part(content, "html") &&
vb@152
  1421
                        msg->longmsg_formatted == NULL) {
vb@152
  1422
                    status = interpret_body(part, &msg->longmsg_formatted,
vb@152
  1423
                            NULL);
vb@152
  1424
                    if (status)
vb@152
  1425
                        return status;
vb@152
  1426
                }
vb@152
  1427
                else /* add as attachment */ {
vb@152
  1428
                    status = interpret_MIME(part, msg);
vb@152
  1429
                    if (status)
vb@152
  1430
                        return status;
vb@120
  1431
                }
vb@118
  1432
            }
vb@118
  1433
        }
vb@260
  1434
        else if (_is_multipart(content, "encrypted")) {
vb@260
  1435
            if (msg->longmsg == NULL)
vb@260
  1436
                msg->longmsg = strdup("");
vb@260
  1437
vb@260
  1438
            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
vb@260
  1439
            if (partlist == NULL)
vb@260
  1440
                return PEP_ILLEGAL_VALUE;
vb@260
  1441
vb@260
  1442
            clistiter *cur;
vb@260
  1443
            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
vb@260
  1444
                struct mailmime *part= clist_content(cur);
vb@260
  1445
                if (part == NULL)
vb@260
  1446
                    return PEP_ILLEGAL_VALUE;
vb@260
  1447
vb@260
  1448
                status = interpret_MIME(part, msg);
vb@260
  1449
                if (status != PEP_STATUS_OK)
vb@260
  1450
                    return status;
vb@260
  1451
            }
vb@260
  1452
        }
vb@152
  1453
        else if (_is_multipart(content, NULL)) {
vb@118
  1454
            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
vb@118
  1455
            if (partlist == NULL)
vb@118
  1456
                return PEP_ILLEGAL_VALUE;
vb@118
  1457
vb@118
  1458
            clistiter *cur;
vb@118
  1459
            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
vb@118
  1460
                struct mailmime *part= clist_content(cur);
vb@118
  1461
                if (part == NULL)
vb@118
  1462
                    return PEP_ILLEGAL_VALUE;
vb@118
  1463
vb@118
  1464
                status = interpret_MIME(part, msg);
vb@118
  1465
                if (status != PEP_STATUS_OK)
vb@118
  1466
                    return status;
vb@118
  1467
            }
vb@118
  1468
        }
vb@118
  1469
        else {
krista@1229
  1470
            if (_is_text_part(content, "html") &&
krista@1229
  1471
                msg->longmsg_formatted == NULL) {
krista@1229
  1472
                status = interpret_body(mime, &msg->longmsg_formatted,
krista@1229
  1473
                                        NULL);
krista@1229
  1474
                if (status)
krista@1229
  1475
                    return status;
krista@1229
  1476
            }
krista@1229
  1477
            else if (_is_text_part(content, NULL) && msg->longmsg == NULL) {
vb@152
  1478
                status = interpret_body(mime, &msg->longmsg, NULL);
vb@152
  1479
                if (status)
vb@152
  1480
                    return status;
vb@152
  1481
            }
vb@152
  1482
            else {
vb@152
  1483
                char *data = NULL;
vb@157
  1484
                size_t size = 0;
vb@157
  1485
                char * mime_type;
vb@159
  1486
                char * charset;
vb@157
  1487
                char * filename;
vb@159
  1488
                int r;
vb@118
  1489
vb@159
  1490
                r = _get_content_type(content, &mime_type, &charset);
vb@159
  1491
                switch (r) {
vb@159
  1492
                    case 0:
vb@159
  1493
                        break;
vb@159
  1494
                    case EINVAL:
vb@159
  1495
                        return PEP_ILLEGAL_VALUE;
vb@159
  1496
                    case ENOMEM:
vb@159
  1497
                        return PEP_OUT_OF_MEMORY;
vb@159
  1498
                    default:
vb@159
  1499
                        return PEP_UNKNOWN_ERROR;
vb@157
  1500
                }
vb@154
  1501
vb@159
  1502
                assert(mime_type);
vb@159
  1503
vb@152
  1504
                status = interpret_body(mime, &data, &size);
vb@152
  1505
                if (status)
vb@152
  1506
                    return status;
vb@152
  1507
krista@1873
  1508
                pEp_rid_list_t* resource_id_list = _get_resource_id_list(mime);
krista@1873
  1509
                pEp_rid_list_t* chosen_resource_id = choose_resource_id(resource_id_list);
krista@1873
  1510
                
krista@1873
  1511
                //filename = _get_filename_or_cid(mime);
vb@481
  1512
                char *_filename = NULL;
krista@1873
  1513
                
krista@1873
  1514
                if (chosen_resource_id) {
krista@1873
  1515
                    filename = chosen_resource_id->rid;
vb@481
  1516
                    size_t index = 0;
krista@1873
  1517
                    /* NOTA BENE */
krista@1873
  1518
                    /* The prefix we just added shouldn't be a problem - this is about decoding %XX (RFC 2392) */
krista@1873
  1519
                    /* If it becomes one, we have some MESSY fixing to do. :(                                  */
vb@481
  1520
                    r = mailmime_encoded_phrase_parse("utf-8", filename,
vb@481
  1521
                            strlen(filename), &index, "utf-8", &_filename);
krista@1872
  1522
                    if (r) {
vb@481
  1523
                        goto enomem;
krista@1872
  1524
                    }
krista@1873
  1525
                    char* file_prefix = NULL;
krista@1873
  1526
                    
krista@1873
  1527
                    /* in case there are others later */
krista@1873
  1528
                    switch (chosen_resource_id->rid_type) {
krista@1873
  1529
                        case PEP_RID_CID:
krista@1873
  1530
                            file_prefix = "cid";
krista@1873
  1531
                            break;
krista@1873
  1532
                        case PEP_RID_FILENAME:
krista@1873
  1533
                            file_prefix = "file";
krista@1873
  1534
                            break;
krista@1873
  1535
                        default:
krista@1873
  1536
                            break;
krista@1873
  1537
                    }
krista@1873
  1538
krista@1873
  1539
                    
krista@1873
  1540
                    if (file_prefix) {
krista@1881
  1541
                        filename = build_uri(file_prefix, _filename);
krista@1873
  1542
                        free(_filename);
krista@1873
  1543
                        _filename = filename;
krista@1873
  1544
                    }
vb@481
  1545
                }
vb@154
  1546
vb@260
  1547
                bloblist_t *_a = bloblist_add(msg->attachments, data, size,
krista@1871
  1548
                        mime_type, _filename);
vb@481
  1549
                free(_filename);
krista@1902
  1550
                free_rid_list(resource_id_list);
krista@1902
  1551
                resource_id_list = NULL;
vb@260
  1552
                if (_a == NULL)
vb@260
  1553
                    return PEP_OUT_OF_MEMORY;
vb@152
  1554
                if (msg->attachments == NULL)
vb@260
  1555
                    msg->attachments = _a;
vb@152
  1556
            }
vb@118
  1557
        }
vb@118
  1558
    }
vb@118
  1559
vb@118
  1560
    return PEP_STATUS_OK;
vb@481
  1561
vb@481
  1562
enomem:
vb@481
  1563
    return PEP_OUT_OF_MEMORY;
vb@118
  1564
}
vb@118
  1565
vb@89
  1566
DYNAMIC_API PEP_STATUS mime_decode_message(
vb@89
  1567
        const char *mimetext,
vb@269
  1568
        size_t size,
vb@89
  1569
        message **msg
vb@89
  1570
    )
vb@89
  1571
{
vb@89
  1572
    PEP_STATUS status = PEP_STATUS_OK;
vb@89
  1573
    struct mailmime * mime = NULL;
vb@89
  1574
    int r;
vb@94
  1575
    message *_msg = NULL;
vb@94
  1576
    size_t index;
vb@89
  1577
vb@89
  1578
    assert(mimetext);
vb@89
  1579
    assert(msg);
vb@89
  1580
vb@191
  1581
    if (!(mimetext && msg))
vb@191
  1582
        return PEP_ILLEGAL_VALUE;
vb@191
  1583
vb@89
  1584
    *msg = NULL;
vb@113
  1585
vb@94
  1586
    index = 0;
vb@269
  1587
    r = mailmime_parse(mimetext, size, &index, &mime);
vb@89
  1588
    assert(r == 0);
vb@89
  1589
    assert(mime);
vb@90
  1590
    if (r) {
vb@89
  1591
        if (r == MAILIMF_ERROR_MEMORY)
vb@89
  1592
            goto enomem;
vb@89
  1593
        else
vb@89
  1594
            goto err_mime;
vb@89
  1595
    }
vb@89
  1596
vb@117
  1597
    _msg = calloc(1, sizeof(message));
vb@117
  1598
    assert(_msg);
vb@117
  1599
    if (_msg == NULL)
vb@117
  1600
        goto enomem;
vb@116
  1601
vb@147
  1602
    clist * _fieldlist = _get_fields(mime);
vb@147
  1603
    if (_fieldlist) {
vb@117
  1604
        status = read_fields(_msg, _fieldlist);
vb@116
  1605
        if (status != PEP_STATUS_OK)
vb@116
  1606
            goto pep_error;
vb@116
  1607
    }
vb@116
  1608
vb@147
  1609
    struct mailmime_content *content = _get_content(mime);
vb@117
  1610
vb@147
  1611
    if (content) {
vb@260
  1612
        status = interpret_MIME(mime->mm_data.mm_message.mm_msg_mime,
vb@260
  1613
                _msg);
vb@260
  1614
        if (status != PEP_STATUS_OK)
vb@260
  1615
            goto pep_error;
vb@116
  1616
    }
vb@116
  1617
vb@89
  1618
    mailmime_free(mime);
vb@94
  1619
    *msg = _msg;
vb@89
  1620
vb@89
  1621
    return status;
vb@89
  1622
vb@89
  1623
err_mime:
vb@89
  1624
    status = PEP_ILLEGAL_VALUE;
vb@89
  1625
    goto pep_error;
vb@89
  1626
vb@89
  1627
enomem:
vb@89
  1628
    status = PEP_OUT_OF_MEMORY;
vb@89
  1629
vb@89
  1630
pep_error:
vb@94
  1631
    free_message(_msg);
vb@94
  1632
vb@89
  1633
    if (mime)
vb@89
  1634
        mailmime_free(mime);
vb@89
  1635
vb@89
  1636
    return status;
vb@89
  1637
}