src/mime.c
author vb
Sun, 08 Mar 2015 12:18:20 +0100
changeset 93 6f3f781caaa0
parent 91 00c67be2d56d
child 94 9ec29aa10b58
permissions -rw-r--r--
correcting address lists
vb@48
     1
#include "mime.h"
vb@48
     2
vb@62
     3
#include <libetpan/mailmime.h>
vb@48
     4
#include <string.h>
vb@48
     5
#include <stdlib.h>
vb@48
     6
#include <assert.h>
vb@48
     7
#include <errno.h>
vb@48
     8
#include <unistd.h>
vb@48
     9
vb@48
    10
#include "etpan_mime.h"
vb@63
    11
#include "wrappers.h"
vb@48
    12
vb@89
    13
static PEP_STATUS render_mime(struct mailmime *mime, char **mimetext)
vb@48
    14
{
vb@89
    15
    PEP_STATUS status = PEP_STATUS_OK;
vb@48
    16
    int fd;
vb@48
    17
    FILE *file = NULL;
vb@48
    18
    size_t size;
vb@48
    19
    char *buf = NULL;
vb@89
    20
    int col;
vb@89
    21
    int r;
vb@51
    22
    char *template = strdup("/tmp/pEp.XXXXXXXXXXXXXXXXXXXX");
vb@48
    23
    assert(template);
vb@48
    24
    if (template == NULL)
vb@48
    25
        goto enomem;
vb@48
    26
vb@89
    27
    *mimetext = NULL;
vb@89
    28
vb@63
    29
    fd = Mkstemp(template);
vb@48
    30
    assert(fd != -1);
vb@48
    31
    if (fd == -1)
vb@48
    32
        goto err_file;
vb@48
    33
vb@48
    34
    r = unlink(template);
vb@48
    35
    assert(r == 0);
vb@90
    36
    if (r)
vb@48
    37
        goto err_file;
vb@48
    38
vb@48
    39
    free(template);
vb@48
    40
    template = NULL;
vb@48
    41
vb@63
    42
    file = Fdopen(fd, "w+");
vb@48
    43
    assert(file);
vb@48
    44
    if (file == NULL) {
vb@48
    45
        switch (errno) {
vb@48
    46
            case ENOMEM:
vb@48
    47
                goto enomem;
vb@48
    48
            default:
vb@48
    49
                goto err_file;
vb@48
    50
        }
vb@48
    51
    }
vb@48
    52
vb@48
    53
    fd = -1;
vb@48
    54
vb@48
    55
    col = 0;
vb@48
    56
    r = mailmime_write_file(file, &col, mime);
vb@48
    57
    assert(r == MAILIMF_NO_ERROR);
vb@48
    58
    if (r == MAILIMF_ERROR_MEMORY)
vb@48
    59
        goto enomem;
vb@48
    60
    else if (r != MAILIMF_NO_ERROR)
vb@48
    61
        goto err_file;
vb@48
    62
vb@48
    63
    off_t len = ftello(file);
vb@48
    64
    assert(len != -1);
vb@48
    65
    if (len == -1 && errno == EOVERFLOW)
vb@48
    66
        goto err_file;
vb@48
    67
Edouard@70
    68
    if (len + 1 > SIZE_MAX)
vb@48
    69
        goto err_buffer;
vb@48
    70
vb@48
    71
    size = (size_t) len;
vb@48
    72
vb@51
    73
    errno = 0;
vb@48
    74
    rewind(file);
vb@51
    75
    assert(errno == 0);
vb@62
    76
    switch (errno) {
vb@63
    77
        case 0:
vb@63
    78
            break;
vb@62
    79
        case ENOMEM:
vb@62
    80
            goto enomem;
vb@62
    81
        default:
vb@62
    82
            goto err_file;
vb@62
    83
    }
vb@48
    84
vb@48
    85
    buf = calloc(1, size + 1);
vb@48
    86
    assert(buf);
vb@48
    87
    if (buf == NULL)
vb@48
    88
        goto enomem;
vb@63
    89
 
vb@63
    90
    size_t _read;
vb@89
    91
    _read = Fread(buf, size, 1, file);
vb@63
    92
    assert(_read == size);
vb@62
    93
vb@63
    94
    r = Fclose(file);
vb@62
    95
    assert(r == 0);
vb@62
    96
vb@87
    97
    *mimetext = buf;
vb@48
    98
    return PEP_STATUS_OK;
vb@48
    99
vb@48
   100
err_buffer:
vb@88
   101
    status = PEP_BUFFER_TOO_SMALL;
vb@88
   102
    goto pep_error;
vb@48
   103
vb@48
   104
err_file:
vb@88
   105
    status = PEP_CANNOT_CREATE_TEMP_FILE;
vb@88
   106
    goto pep_error;
vb@48
   107
vb@48
   108
enomem:
vb@88
   109
    status = PEP_OUT_OF_MEMORY;
vb@52
   110
vb@88
   111
pep_error:
vb@48
   112
    free(buf);
vb@48
   113
    free(template);
vb@48
   114
vb@62
   115
    if (file) {
vb@63
   116
        r = Fclose(file);
vb@62
   117
        assert(r == 0);
vb@62
   118
    }
vb@62
   119
    else if (fd != -1) {
vb@63
   120
        r = Close(fd);
vb@62
   121
        assert(r == 0);
vb@62
   122
    }
vb@48
   123
vb@89
   124
    return status;
vb@89
   125
}
vb@89
   126
vb@89
   127
static PEP_STATUS mime_html_text(
vb@89
   128
        const char *plaintext,
vb@89
   129
        const char *htmltext,
vb@89
   130
        struct mailmime **result
vb@89
   131
    )
vb@89
   132
{
vb@89
   133
    PEP_STATUS status = PEP_STATUS_OK;
vb@89
   134
    struct mailmime * mime = NULL;
vb@89
   135
    struct mailmime * submime = NULL;
vb@89
   136
    int r;
vb@89
   137
vb@89
   138
    assert(plaintext);
vb@89
   139
    assert(htmltext);
vb@89
   140
    assert(result);
vb@89
   141
vb@89
   142
    *result = NULL;
vb@89
   143
vb@89
   144
    mime = part_multiple_new("multipart/alternative", NULL);
vb@89
   145
    assert(mime);
vb@89
   146
    if (mime == NULL)
vb@89
   147
        goto enomem;
vb@89
   148
vb@89
   149
    submime = get_text_part("text/plain", plaintext, strlen(plaintext),
vb@89
   150
            MAILMIME_MECHANISM_QUOTED_PRINTABLE);
vb@89
   151
    assert(submime);
vb@89
   152
    if (submime == NULL)
vb@89
   153
        goto enomem;
vb@89
   154
vb@89
   155
    r = mailmime_smart_add_part(mime, submime);
vb@89
   156
    assert(r == MAILIMF_NO_ERROR);
vb@89
   157
    if (r == MAILIMF_ERROR_MEMORY) {
vb@89
   158
        goto enomem;
vb@89
   159
    }
vb@89
   160
    else {
vb@89
   161
        // mailmime_smart_add_part() takes ownership of submime
vb@89
   162
        submime = NULL;
vb@89
   163
    }
vb@89
   164
vb@89
   165
    submime = get_text_part("text/html", htmltext, strlen(htmltext),
vb@89
   166
            MAILMIME_MECHANISM_QUOTED_PRINTABLE);
vb@89
   167
    assert(submime);
vb@89
   168
    if (submime == NULL)
vb@89
   169
        goto enomem;
vb@89
   170
vb@89
   171
    r = mailmime_smart_add_part(mime, submime);
vb@89
   172
    assert(r == MAILIMF_NO_ERROR);
vb@89
   173
    if (r == MAILIMF_ERROR_MEMORY)
vb@89
   174
        goto enomem;
vb@89
   175
    else {
vb@89
   176
        // mailmime_smart_add_part() takes ownership of submime
vb@89
   177
        submime = NULL;
vb@89
   178
    }
vb@89
   179
vb@89
   180
    *result = mime;
vb@89
   181
    return PEP_STATUS_OK;
vb@89
   182
vb@89
   183
enomem:
vb@89
   184
    status = PEP_OUT_OF_MEMORY;
vb@89
   185
vb@89
   186
pep_error:
vb@59
   187
    if (mime)
vb@59
   188
        mailmime_free(mime);
vb@89
   189
vb@48
   190
    if (submime)
vb@48
   191
        mailmime_free(submime);
vb@48
   192
vb@88
   193
    return status;
vb@48
   194
}
vb@88
   195
vb@89
   196
static PEP_STATUS mime_attachment(
vb@89
   197
        bloblist_t *blob,
vb@89
   198
        struct mailmime **result
vb@88
   199
    )
vb@88
   200
{
vb@88
   201
    PEP_STATUS status = PEP_STATUS_OK;
vb@89
   202
    struct mailmime * mime = NULL;
vb@89
   203
    char * mime_type;
vb@88
   204
vb@89
   205
    assert(blob);
vb@89
   206
    assert(result);
vb@88
   207
vb@89
   208
    *result = NULL;
vb@88
   209
vb@89
   210
    if (blob->mime_type == NULL)
vb@89
   211
        mime_type = "application/octet-stream";
vb@89
   212
    else
vb@89
   213
        mime_type = blob->mime_type;
vb@89
   214
vb@89
   215
    mime = get_file_part(blob->file_name, mime_type, blob->data, blob->size);
vb@89
   216
    assert(mime);
vb@89
   217
    if (mime == NULL)
vb@89
   218
        goto enomem;
vb@89
   219
vb@89
   220
    *result = mime;
vb@89
   221
    return PEP_STATUS_OK;
vb@88
   222
vb@88
   223
enomem:
vb@88
   224
    status = PEP_OUT_OF_MEMORY;
vb@88
   225
vb@88
   226
pep_error:
vb@89
   227
    if (mime)
vb@89
   228
        mailmime_free(mime);
vb@89
   229
vb@88
   230
    return status;
vb@88
   231
}
vb@88
   232
vb@90
   233
static struct mailimf_mailbox_list * mbl_from_identity(const pEp_identity *ident)
vb@90
   234
{
vb@90
   235
    struct mailimf_mailbox_list *mbl = NULL;
vb@90
   236
    struct mailimf_mailbox *mb = NULL;
vb@90
   237
    clist *list = NULL;
vb@90
   238
    int r;
vb@90
   239
vb@90
   240
    assert(ident);
vb@90
   241
vb@90
   242
    list = clist_new();
vb@90
   243
    if (list == NULL)
vb@90
   244
        goto enomem;
vb@90
   245
vb@90
   246
    mb = mailbox_from_string(ident->username, ident->address);
vb@90
   247
    if (mb == NULL)
vb@90
   248
        goto enomem;
vb@90
   249
vb@90
   250
    r = clist_append(list, mb);
vb@90
   251
    if (r)
vb@90
   252
        goto enomem;
vb@90
   253
vb@90
   254
    mbl = mailimf_mailbox_list_new(list);
vb@90
   255
    if (mbl == NULL)
vb@90
   256
        goto enomem;
vb@90
   257
vb@90
   258
    return mbl;
vb@90
   259
vb@90
   260
enomem:
vb@90
   261
    if (mb)
vb@90
   262
        mailimf_mailbox_free(mb);
vb@90
   263
vb@90
   264
    if (list)
vb@90
   265
        clist_free(list);
vb@90
   266
vb@90
   267
    return NULL;
vb@90
   268
}
vb@90
   269
vb@93
   270
static struct mailimf_address_list * mal_from_identity_list(identity_list *il)
vb@90
   271
{
vb@93
   272
    struct mailimf_address_list *mal = NULL;
vb@90
   273
    struct mailimf_mailbox *mb = NULL;
vb@93
   274
    struct mailimf_address * addr = NULL;
vb@90
   275
    clist *list = NULL;
vb@90
   276
    int r;
vb@90
   277
vb@90
   278
    assert(il);
vb@90
   279
vb@90
   280
    list = clist_new();
vb@90
   281
    if (list == NULL)
vb@90
   282
        goto enomem;
vb@90
   283
vb@90
   284
    identity_list *_il;
vb@90
   285
    for (_il = il; _il; _il = _il->next) {
vb@90
   286
        mb = mailbox_from_string(_il->ident->username, _il->ident->address);
vb@90
   287
        if (mb == NULL)
vb@90
   288
            goto enomem;
vb@90
   289
vb@93
   290
        addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
vb@93
   291
        if (addr == NULL)
vb@93
   292
            goto enomem;
vb@93
   293
        mb = NULL;
vb@93
   294
vb@93
   295
        r = clist_append(list, addr);
vb@90
   296
        if (r)
vb@90
   297
            goto enomem;
vb@93
   298
        addr = NULL;
vb@90
   299
    }
vb@93
   300
    mal = mailimf_address_list_new(list);
vb@93
   301
    if (mal == NULL)
vb@90
   302
        goto enomem;
vb@90
   303
vb@93
   304
    return mal;
vb@90
   305
vb@90
   306
enomem:
vb@90
   307
    if (mb)
vb@90
   308
        mailimf_mailbox_free(mb);
vb@90
   309
vb@93
   310
    if (addr)
vb@93
   311
        mailimf_address_free(addr);
vb@93
   312
vb@90
   313
    if (list)
vb@90
   314
        clist_free(list);
vb@90
   315
vb@90
   316
    return NULL;
vb@90
   317
}
vb@90
   318
vb@91
   319
static clist * clist_from_stringlist(stringlist_t *sl)
vb@91
   320
{
vb@91
   321
    clist * cl = clist_new();
vb@91
   322
    assert(cl);
vb@91
   323
    if (cl == NULL)
vb@91
   324
        return NULL;
vb@91
   325
vb@91
   326
    stringlist_t *_sl;
vb@91
   327
    for (_sl = sl; _sl; _sl = _sl->next) {
vb@91
   328
        int r;
vb@91
   329
        char * value = strdup(_sl->value);
vb@91
   330
        assert(value);
vb@91
   331
        if (value == NULL) {
vb@91
   332
            clist_free(cl);
vb@91
   333
            return NULL;
vb@91
   334
        }
vb@91
   335
        r = clist_append(cl, value);
vb@91
   336
        assert(r == 0);
vb@91
   337
        if (r) {
vb@91
   338
            free(value);
vb@91
   339
            clist_free(cl);
vb@91
   340
            return NULL;
vb@91
   341
        }
vb@91
   342
    }
vb@91
   343
vb@91
   344
    return cl;
vb@91
   345
}
vb@91
   346
vb@89
   347
static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result)
vb@89
   348
{
vb@89
   349
    PEP_STATUS status = PEP_STATUS_OK;
vb@89
   350
    struct mailimf_fields * fields = NULL;
vb@89
   351
    int r;
vb@89
   352
    clist * fields_list = NULL;
vb@89
   353
    char *subject = msg->shortmsg ? msg->shortmsg : "pEp";
vb@89
   354
vb@89
   355
    assert(msg);
vb@89
   356
    assert(msg->from);
vb@89
   357
    assert(msg->from->address);
vb@89
   358
    assert(result);
vb@89
   359
vb@89
   360
    *result = NULL;
vb@89
   361
vb@89
   362
    fields_list = clist_new();
vb@89
   363
    assert(fields_list);
vb@89
   364
    if (fields_list == NULL)
vb@89
   365
        goto enomem;
vb@89
   366
vb@90
   367
    if (msg->id) {
vb@90
   368
        char *_msgid = strdup(msg->id);
vb@90
   369
        if (_msgid == NULL)
vb@90
   370
            goto enomem;
vb@89
   371
vb@90
   372
        r = _append_field(fields_list, MAILIMF_FIELD_MESSAGE_ID,
vb@90
   373
                (_new_func_t) mailimf_message_id_new, _msgid);
vb@90
   374
        if (r) {
vb@90
   375
            free(_msgid);
vb@90
   376
            goto enomem;
vb@90
   377
        }
vb@90
   378
    }
vb@90
   379
vb@90
   380
    /* if (subject) */ {
vb@90
   381
        char *_subject = strdup(subject);
vb@90
   382
        if (_subject == NULL)
vb@90
   383
            goto enomem;
vb@90
   384
vb@90
   385
        r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
vb@90
   386
                (_new_func_t) mailimf_subject_new, _subject);
vb@90
   387
        if (r) {
vb@90
   388
            free(_subject);
vb@90
   389
            goto enomem;
vb@90
   390
        }
vb@90
   391
    }
vb@90
   392
vb@90
   393
    if (msg->sent) {
vb@90
   394
        struct mailimf_date_time * dt = timestamp_to_etpantime(msg->sent);
vb@90
   395
        if (dt == NULL)
vb@90
   396
            goto enomem;
vb@90
   397
vb@90
   398
        r = _append_field(fields_list, MAILIMF_FIELD_ORIG_DATE,
vb@90
   399
                (_new_func_t) mailimf_orig_date_new, dt);
vb@90
   400
        if (r) {
vb@90
   401
            mailimf_date_time_free(dt);
vb@90
   402
            goto enomem;
vb@90
   403
        }
vb@90
   404
        dt = NULL;
vb@90
   405
    }
vb@90
   406
vb@91
   407
    /* if (msg->from) */ {
vb@90
   408
        struct mailimf_mailbox_list *from = mbl_from_identity(msg->from);
vb@90
   409
        if (from == NULL)
vb@90
   410
            goto enomem;
vb@90
   411
vb@90
   412
        r = _append_field(fields_list, MAILIMF_FIELD_FROM,
vb@90
   413
                (_new_func_t) mailimf_from_new, from);
vb@90
   414
        if (r) {
vb@90
   415
            mailimf_mailbox_list_free(from);
vb@90
   416
            goto enomem;
vb@90
   417
        }
vb@90
   418
    }
vb@90
   419
vb@90
   420
    if (msg->to) {
vb@93
   421
        struct mailimf_address_list *to = mal_from_identity_list(msg->to);
vb@90
   422
        if (to == NULL)
vb@90
   423
            goto enomem;
vb@90
   424
vb@91
   425
        r = _append_field(fields_list, MAILIMF_FIELD_TO,
vb@90
   426
                (_new_func_t) mailimf_to_new, to);
vb@90
   427
        if (r) {
vb@93
   428
            mailimf_address_list_free(to);
vb@90
   429
            goto enomem;
vb@90
   430
        }
vb@90
   431
    }
vb@89
   432
vb@91
   433
    if (msg->cc) {
vb@93
   434
        struct mailimf_address_list *cc = mal_from_identity_list(msg->cc);
vb@91
   435
        if (cc == NULL)
vb@91
   436
            goto enomem;
vb@91
   437
vb@91
   438
        r = _append_field(fields_list, MAILIMF_FIELD_CC,
vb@91
   439
                (_new_func_t) mailimf_cc_new, cc);
vb@91
   440
        if (r) {
vb@93
   441
            mailimf_address_list_free(cc);
vb@91
   442
            goto enomem;
vb@91
   443
        }
vb@91
   444
    }
vb@91
   445
    
vb@91
   446
    if (msg->bcc) {
vb@93
   447
        struct mailimf_address_list *bcc = mal_from_identity_list(msg->bcc);
vb@91
   448
        if (bcc == NULL)
vb@91
   449
            goto enomem;
vb@91
   450
vb@91
   451
        r = _append_field(fields_list, MAILIMF_FIELD_BCC,
vb@91
   452
                (_new_func_t) mailimf_bcc_new, bcc);
vb@91
   453
        if (r) {
vb@93
   454
            mailimf_address_list_free(bcc);
vb@91
   455
            goto enomem;
vb@91
   456
        }
vb@91
   457
    }
vb@91
   458
    
vb@91
   459
    if (msg->reply_to) {
vb@91
   460
        struct mailimf_mailbox_list *reply_to= mbl_from_identity(msg->reply_to);
vb@91
   461
        if (reply_to == NULL)
vb@91
   462
            goto enomem;
vb@91
   463
vb@91
   464
        r = _append_field(fields_list, MAILIMF_FIELD_REPLY_TO,
vb@91
   465
                (_new_func_t) mailimf_reply_to_new, reply_to);
vb@91
   466
        if (r) {
vb@91
   467
            mailimf_mailbox_list_free(reply_to);
vb@91
   468
            goto enomem;
vb@91
   469
        }
vb@91
   470
    }
vb@91
   471
vb@91
   472
    if (msg->in_reply_to) {
vb@91
   473
        char *in_reply_to = strdup(msg->in_reply_to);
vb@91
   474
        if (in_reply_to == NULL)
vb@91
   475
            goto enomem;
vb@91
   476
vb@91
   477
        r = _append_field(fields_list, MAILIMF_FIELD_IN_REPLY_TO,
vb@91
   478
                (_new_func_t) mailimf_in_reply_to_new, in_reply_to);
vb@91
   479
        if (r) {
vb@91
   480
            free(in_reply_to);
vb@91
   481
            goto enomem;
vb@91
   482
        }
vb@91
   483
    }
vb@91
   484
vb@91
   485
    if (msg->references) {
vb@91
   486
        clist *references = clist_from_stringlist(msg->references);
vb@91
   487
        if (references == NULL)
vb@91
   488
            goto enomem;
vb@91
   489
vb@91
   490
        r = _append_field(fields_list, MAILIMF_FIELD_REFERENCES,
vb@91
   491
                (_new_func_t) mailimf_references_new, references);
vb@91
   492
        if (r) {
vb@91
   493
            clist_free(references);
vb@91
   494
            goto enomem;
vb@91
   495
        }
vb@91
   496
    }
vb@91
   497
vb@91
   498
    if (msg->keywords) {
vb@91
   499
        clist *keywords = clist_from_stringlist(msg->keywords);
vb@91
   500
        if (keywords == NULL)
vb@91
   501
            goto enomem;
vb@91
   502
vb@91
   503
        r = _append_field(fields_list, MAILIMF_FIELD_KEYWORDS,
vb@91
   504
                (_new_func_t) mailimf_keywords_new, keywords);
vb@91
   505
        if (r) {
vb@91
   506
            clist_free(keywords);
vb@91
   507
            goto enomem;
vb@91
   508
        }
vb@91
   509
    }
vb@91
   510
vb@91
   511
    if (msg->comments) {
vb@91
   512
        char *comments = strdup(msg->comments);
vb@91
   513
        if (comments == NULL)
vb@91
   514
            goto enomem;
vb@91
   515
vb@91
   516
        r = _append_field(fields_list, MAILIMF_FIELD_COMMENTS,
vb@91
   517
                (_new_func_t) mailimf_comments_new, comments);
vb@91
   518
        if (r) {
vb@91
   519
            free(comments);
vb@91
   520
            goto enomem;
vb@91
   521
        }
vb@91
   522
    }
vb@91
   523
vb@89
   524
    fields = mailimf_fields_new(fields_list);
vb@89
   525
    assert(fields);
vb@89
   526
    if (fields == NULL)
vb@89
   527
        goto enomem;
vb@89
   528
vb@89
   529
    *result = fields;
vb@89
   530
vb@89
   531
    return PEP_STATUS_OK;
vb@89
   532
vb@89
   533
enomem:
vb@89
   534
    status = PEP_OUT_OF_MEMORY;
vb@89
   535
vb@89
   536
pep_error:
vb@89
   537
    if (fields_list)
vb@89
   538
        clist_free(fields_list);
vb@89
   539
vb@89
   540
    if (fields)
vb@89
   541
        mailimf_fields_free(fields);
vb@89
   542
vb@89
   543
    return status;
vb@89
   544
}
vb@89
   545
vb@89
   546
DYNAMIC_API PEP_STATUS mime_encode_message(
vb@89
   547
        const message *msg,
vb@89
   548
        char **mimetext
vb@89
   549
    )
vb@89
   550
{
vb@89
   551
    struct mailmime * msg_mime = NULL;
vb@89
   552
    struct mailmime * mime = NULL;
vb@89
   553
    struct mailmime * submime = NULL;
vb@90
   554
    struct mailimf_fields * fields = NULL;
vb@89
   555
    char *buf = NULL;
vb@89
   556
    int r;
vb@89
   557
    PEP_STATUS status;
vb@89
   558
    char *subject;
vb@89
   559
    char *plaintext;
vb@89
   560
    char *htmltext;
vb@89
   561
vb@89
   562
    assert(msg);
vb@89
   563
    assert(mimetext);
vb@89
   564
vb@89
   565
    *mimetext = NULL;
vb@89
   566
vb@89
   567
    subject = (msg->shortmsg) ? msg->shortmsg : "pEp";
vb@89
   568
    plaintext = (msg->longmsg) ? msg->longmsg : "";
vb@89
   569
    htmltext = msg->longmsg_formatted;
vb@89
   570
vb@89
   571
    if (htmltext) {
vb@89
   572
        status = mime_html_text(plaintext, htmltext, &mime);
vb@89
   573
        if (status != PEP_STATUS_OK)
vb@89
   574
            goto pep_error;
vb@89
   575
    }
vb@89
   576
    else {
vb@90
   577
        mime = get_text_part("text/plain", plaintext, strlen(plaintext),
vb@89
   578
                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
vb@89
   579
        assert(mime);
vb@89
   580
        if (mime == NULL)
vb@89
   581
            goto enomem;
vb@89
   582
    }
vb@89
   583
vb@89
   584
    if (msg->attachments) {
vb@89
   585
        submime = mime;
vb@89
   586
        mime = part_multiple_new("multipart/mixed", NULL);
vb@89
   587
        assert(mime);
vb@89
   588
        if (mime == NULL)
vb@89
   589
            goto enomem;
vb@89
   590
vb@89
   591
        r = mailmime_smart_add_part(mime, submime);
vb@89
   592
        assert(r == MAILIMF_NO_ERROR);
vb@89
   593
        if (r == MAILIMF_ERROR_MEMORY) {
vb@89
   594
            goto enomem;
vb@89
   595
        }
vb@89
   596
        else {
vb@89
   597
            // mailmime_smart_add_part() takes ownership of submime
vb@89
   598
            submime = NULL;
vb@89
   599
        }
vb@89
   600
vb@89
   601
        bloblist_t *_a;
vb@89
   602
        for (_a = msg->attachments; _a != NULL; _a = _a->next) {
vb@89
   603
            char * mime_type;
vb@89
   604
vb@89
   605
            assert(_a->data);
vb@89
   606
            assert(_a->size);
vb@89
   607
vb@89
   608
            status = mime_attachment(_a, &submime);
vb@89
   609
            if (status != PEP_STATUS_OK)
vb@89
   610
                goto pep_error;
vb@89
   611
vb@89
   612
            r = mailmime_smart_add_part(mime, submime);
vb@89
   613
            assert(r == MAILIMF_NO_ERROR);
vb@89
   614
            if (r == MAILIMF_ERROR_MEMORY) {
vb@89
   615
                goto enomem;
vb@89
   616
            }
vb@89
   617
            else {
vb@89
   618
                // mailmime_smart_add_part() takes ownership of submime
vb@89
   619
                submime = NULL;
vb@89
   620
            }
vb@89
   621
        }
vb@89
   622
    }
vb@89
   623
vb@89
   624
    msg_mime = mailmime_new_message_data(NULL);
vb@90
   625
    assert(msg_mime);
vb@90
   626
    if (msg_mime == NULL)
vb@90
   627
        goto enomem;
vb@89
   628
vb@90
   629
    r = mailmime_add_part(msg_mime, mime);
vb@90
   630
    if (r) {
vb@90
   631
        mailmime_free(mime);
vb@90
   632
        goto enomem;
vb@90
   633
    }
vb@90
   634
vb@90
   635
    status = build_fields(msg, &fields);
vb@90
   636
    if (status != PEP_STATUS_OK)
vb@90
   637
        goto pep_error;
vb@90
   638
vb@90
   639
    mailmime_set_imf_fields(msg_mime, fields);
vb@90
   640
vb@90
   641
    status = render_mime(msg_mime, &buf);
vb@89
   642
    if (status != PEP_STATUS_OK)
vb@89
   643
        goto pep_error;
vb@89
   644
vb@89
   645
    mailmime_free(msg_mime);
vb@89
   646
    *mimetext = buf;
vb@90
   647
vb@89
   648
    return PEP_STATUS_OK;
vb@89
   649
vb@89
   650
enomem:
vb@89
   651
    status = PEP_OUT_OF_MEMORY;
vb@89
   652
vb@89
   653
pep_error:
vb@89
   654
    if (msg_mime)
vb@90
   655
        mailmime_free(msg_mime);
vb@89
   656
    else
vb@89
   657
        if (mime)
vb@89
   658
            mailmime_free(mime);
vb@89
   659
vb@89
   660
    if (submime)
vb@89
   661
        mailmime_free(submime);
vb@89
   662
vb@89
   663
    return status;
vb@89
   664
}
vb@89
   665
vb@89
   666
DYNAMIC_API PEP_STATUS mime_decode_message(
vb@89
   667
        const char *mimetext,
vb@89
   668
        message **msg
vb@89
   669
    )
vb@89
   670
{
vb@89
   671
    PEP_STATUS status = PEP_STATUS_OK;
vb@89
   672
    struct mailmime * mime = NULL;
vb@89
   673
    int r;
vb@89
   674
vb@89
   675
    assert(mimetext);
vb@89
   676
    assert(msg);
vb@89
   677
vb@89
   678
    *msg = NULL;
vb@89
   679
    
vb@89
   680
    size_t index = 0;
vb@89
   681
    r = mailmime_parse(mimetext, strlen(mimetext), &index, &mime);
vb@89
   682
    assert(r == 0);
vb@89
   683
    assert(mime);
vb@90
   684
    if (r) {
vb@89
   685
        if (r == MAILIMF_ERROR_MEMORY)
vb@89
   686
            goto enomem;
vb@89
   687
        else
vb@89
   688
            goto err_mime;
vb@89
   689
    }
vb@89
   690
vb@89
   691
    mailmime_free(mime);
vb@89
   692
vb@89
   693
    return status;
vb@89
   694
vb@89
   695
err_mime:
vb@89
   696
    status = PEP_ILLEGAL_VALUE;
vb@89
   697
    goto pep_error;
vb@89
   698
vb@89
   699
enomem:
vb@89
   700
    status = PEP_OUT_OF_MEMORY;
vb@89
   701
vb@89
   702
pep_error:
vb@89
   703
    if (mime)
vb@89
   704
        mailmime_free(mime);
vb@89
   705
vb@89
   706
    return status;
vb@89
   707
}
vb@89
   708