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