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