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