src/mime.c
author vb
Wed, 04 Mar 2015 10:39:29 +0100
changeset 87 060a95de62a8
parent 70 c0382670c294
child 88 ac617f70bd7f
permissions -rw-r--r--
fixing Makefile
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@48
    13
DYNAMIC_API PEP_STATUS mime_encode_text(
vb@48
    14
        const char *plaintext,
vb@48
    15
        const char *htmltext,
vb@59
    16
        bloblist_t *attachments,
vb@87
    17
        char **mimetext
vb@48
    18
    )
vb@48
    19
{
vb@48
    20
    struct mailmime * mime = NULL;
vb@48
    21
    struct mailmime * submime = NULL;
vb@48
    22
    int col;
vb@48
    23
    int r;
vb@48
    24
    int fd;
vb@48
    25
    FILE *file = NULL;
vb@48
    26
    size_t size;
vb@48
    27
    char *buf = NULL;
vb@52
    28
    PEP_STATUS error;
vb@48
    29
vb@48
    30
    assert(plaintext);
vb@87
    31
    assert(mimetext);
vb@48
    32
vb@87
    33
    *mimetext = NULL;
vb@48
    34
vb@57
    35
    if (htmltext) {
vb@57
    36
        mime = part_multiple_new("multipart/alternative", NULL);
vb@57
    37
        assert(mime);
vb@57
    38
        if (mime == NULL)
vb@57
    39
            goto enomem;
vb@48
    40
vb@57
    41
        submime = get_text_part("text/plain", plaintext, strlen(plaintext),
vb@57
    42
                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
vb@57
    43
        assert(submime);
vb@59
    44
        if (submime == NULL)
vb@57
    45
            goto enomem;
vb@48
    46
vb@57
    47
        r = mailmime_smart_add_part(mime, submime);
vb@57
    48
        assert(r == MAILIMF_NO_ERROR);
vb@57
    49
        if (r == MAILIMF_ERROR_MEMORY) {
vb@57
    50
            goto enomem;
vb@57
    51
        }
vb@57
    52
        else {
vb@57
    53
            // mailmime_smart_add_part() takes ownership of submime
vb@57
    54
            submime = NULL;
vb@57
    55
        }
vb@57
    56
vb@57
    57
        submime = get_text_part("text/html", htmltext, strlen(htmltext),
vb@57
    58
                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
vb@57
    59
        assert(submime);
vb@59
    60
        if (submime == NULL)
vb@57
    61
            goto enomem;
vb@57
    62
vb@57
    63
        r = mailmime_smart_add_part(mime, submime);
vb@57
    64
        assert(r == MAILIMF_NO_ERROR);
vb@59
    65
        if (r == MAILIMF_ERROR_MEMORY)
vb@57
    66
            goto enomem;
vb@57
    67
        else {
vb@57
    68
            // mailmime_smart_add_part() takes ownership of submime
vb@57
    69
            submime = NULL;
vb@57
    70
        }
vb@48
    71
    }
vb@48
    72
    else {
vb@57
    73
        mime = get_text_part("text/plain", plaintext, strlen(plaintext),
vb@57
    74
                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
vb@57
    75
        assert(mime);
vb@59
    76
        if (mime == NULL)
vb@59
    77
            goto enomem;
vb@59
    78
    }
vb@59
    79
vb@59
    80
    if (attachments) {
vb@59
    81
        submime = mime;
vb@59
    82
        mime = part_multiple_new("multipart/mixed", NULL);
vb@59
    83
        assert(mime);
vb@59
    84
        if (mime == NULL)
vb@59
    85
            goto enomem;
vb@59
    86
vb@59
    87
        r = mailmime_smart_add_part(mime, submime);
vb@59
    88
        assert(r == MAILIMF_NO_ERROR);
vb@59
    89
        if (r == MAILIMF_ERROR_MEMORY) {
vb@57
    90
            goto enomem;
vb@57
    91
        }
vb@59
    92
        else {
vb@59
    93
            // mailmime_smart_add_part() takes ownership of submime
vb@59
    94
            submime = NULL;
vb@59
    95
        }
vb@59
    96
vb@59
    97
        bloblist_t *_a;
vb@59
    98
        for (_a = attachments; _a != NULL; _a = _a->next) {
vb@59
    99
            char * mime_type;
vb@59
   100
vb@59
   101
            assert(_a->data);
vb@59
   102
            assert(_a->size);
vb@59
   103
vb@59
   104
            if (_a->mime_type == NULL)
vb@59
   105
                mime_type = "application/octet-stream";
vb@59
   106
            else
vb@59
   107
                mime_type = _a->mime_type;
vb@59
   108
vb@59
   109
            submime = get_file_part(_a->file_name, mime_type, _a->data, _a->size);
vb@59
   110
            assert(submime);
vb@59
   111
            if (submime == NULL)
vb@59
   112
                goto enomem;
vb@59
   113
vb@59
   114
            r = mailmime_smart_add_part(mime, submime);
vb@59
   115
            assert(r == MAILIMF_NO_ERROR);
vb@59
   116
            if (r == MAILIMF_ERROR_MEMORY) {
vb@59
   117
                goto enomem;
vb@59
   118
            }
vb@59
   119
            else {
vb@59
   120
                // mailmime_smart_add_part() takes ownership of submime
vb@59
   121
                submime = NULL;
vb@59
   122
            }
vb@59
   123
        }
vb@48
   124
    }
vb@48
   125
vb@51
   126
    char *template = strdup("/tmp/pEp.XXXXXXXXXXXXXXXXXXXX");
vb@48
   127
    assert(template);
vb@48
   128
    if (template == NULL)
vb@48
   129
        goto enomem;
vb@48
   130
vb@63
   131
    fd = Mkstemp(template);
vb@48
   132
    assert(fd != -1);
vb@48
   133
    if (fd == -1)
vb@48
   134
        goto err_file;
vb@48
   135
vb@48
   136
    r = unlink(template);
vb@48
   137
    assert(r == 0);
vb@48
   138
    if (r == -1)
vb@48
   139
        goto err_file;
vb@48
   140
vb@48
   141
    free(template);
vb@48
   142
    template = NULL;
vb@48
   143
vb@63
   144
    file = Fdopen(fd, "w+");
vb@48
   145
    assert(file);
vb@48
   146
    if (file == NULL) {
vb@48
   147
        switch (errno) {
vb@48
   148
            case ENOMEM:
vb@48
   149
                goto enomem;
vb@48
   150
            default:
vb@48
   151
                goto err_file;
vb@48
   152
        }
vb@48
   153
    }
vb@48
   154
vb@48
   155
    fd = -1;
vb@48
   156
vb@48
   157
    col = 0;
vb@48
   158
    r = mailmime_write_file(file, &col, mime);
vb@48
   159
    assert(r == MAILIMF_NO_ERROR);
vb@48
   160
    if (r == MAILIMF_ERROR_MEMORY)
vb@48
   161
        goto enomem;
vb@48
   162
    else if (r != MAILIMF_NO_ERROR)
vb@48
   163
        goto err_file;
vb@48
   164
vb@48
   165
    off_t len = ftello(file);
vb@48
   166
    assert(len != -1);
vb@48
   167
    if (len == -1 && errno == EOVERFLOW)
vb@48
   168
        goto err_file;
vb@48
   169
Edouard@70
   170
    if (len + 1 > SIZE_MAX)
vb@48
   171
        goto err_buffer;
vb@48
   172
vb@48
   173
    size = (size_t) len;
vb@48
   174
vb@51
   175
    errno = 0;
vb@48
   176
    rewind(file);
vb@51
   177
    assert(errno == 0);
vb@63
   178
#ifdef NDEBUG
vb@62
   179
    switch (errno) {
vb@63
   180
        case 0:
vb@63
   181
            break;
vb@62
   182
        case ENOMEM:
vb@62
   183
            goto enomem;
vb@62
   184
        default:
vb@62
   185
            goto err_file;
vb@62
   186
    }
vb@63
   187
#endif
vb@48
   188
vb@48
   189
    buf = calloc(1, size + 1);
vb@48
   190
    assert(buf);
vb@48
   191
    if (buf == NULL)
vb@48
   192
        goto enomem;
vb@63
   193
 
vb@63
   194
    size_t _read;
vb@63
   195
    _read = Fread1(buf, size, file);
vb@63
   196
    assert(_read == size);
vb@62
   197
vb@63
   198
    r = Fclose(file);
vb@62
   199
    assert(r == 0);
vb@62
   200
vb@59
   201
    mailmime_free(mime);
vb@87
   202
    *mimetext = buf;
vb@48
   203
    return PEP_STATUS_OK;
vb@48
   204
vb@48
   205
err_buffer:
vb@48
   206
    error = PEP_BUFFER_TOO_SMALL;
vb@52
   207
    goto release;
vb@48
   208
vb@48
   209
err_file:
vb@48
   210
    error = PEP_CANNOT_CREATE_TEMP_FILE;
vb@52
   211
    goto release;
vb@48
   212
vb@48
   213
enomem:
vb@52
   214
    error = PEP_OUT_OF_MEMORY;
vb@52
   215
vb@52
   216
release:
vb@48
   217
    free(buf);
vb@48
   218
    free(template);
vb@48
   219
vb@62
   220
    if (file) {
vb@63
   221
        r = Fclose(file);
vb@62
   222
        assert(r == 0);
vb@62
   223
    }
vb@62
   224
    else if (fd != -1) {
vb@63
   225
        r = Close(fd);
vb@62
   226
        assert(r == 0);
vb@62
   227
    }
vb@48
   228
vb@59
   229
    if (mime)
vb@59
   230
        mailmime_free(mime);
vb@48
   231
    if (submime)
vb@48
   232
        mailmime_free(submime);
vb@48
   233
vb@48
   234
    return error;
vb@48
   235
}