src/mime.c
author vb
Sun, 08 Feb 2015 11:33:04 -0500
changeset 48 9ff5d2dfa75a
child 51 761bc0b46b98
permissions -rw-r--r--
...
vb@48
     1
#include "mime.h"
vb@48
     2
vb@48
     3
#include <libetpan/libetpan.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@48
    15
        char **resulttext
vb@48
    16
    )
vb@48
    17
{
vb@48
    18
    struct mailmime * msg_mime = NULL;
vb@48
    19
	struct mailimf_fields * fields = NULL;
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@48
    28
    PEP_STATUS error = PEP_OUT_OF_MEMORY;
vb@48
    29
vb@48
    30
    assert(plaintext);
vb@48
    31
    assert(resulttext);
vb@48
    32
vb@48
    33
    *resulttext = NULL;
vb@48
    34
vb@48
    35
    msg_mime = mailmime_new_message_data(NULL);
vb@48
    36
    assert(msg_mime);
vb@48
    37
    if (msg_mime == NULL)
vb@48
    38
        goto enomem;
vb@48
    39
vb@48
    40
    fields = mailimf_fields_new_empty();
vb@48
    41
    assert(fields);
vb@48
    42
    if (fields == NULL)
vb@48
    43
        goto enomem;
vb@48
    44
vb@48
    45
    mailmime_set_imf_fields(msg_mime, fields);
vb@48
    46
vb@48
    47
    mime = part_multiple_new("multipart/mixed", NULL);
vb@48
    48
    assert(mime);
vb@48
    49
    if (mime == NULL)
vb@48
    50
        goto enomem;
vb@48
    51
vb@48
    52
    submime = get_text_part("text/plain", plaintext, strlen(plaintext),
vb@48
    53
            MAILMIME_MECHANISM_QUOTED_PRINTABLE);
vb@48
    54
    assert(submime);
vb@48
    55
    if (submime == NULL) {
vb@48
    56
        mailmime_free(msg_mime);
vb@48
    57
        goto enomem;
vb@48
    58
    }
vb@48
    59
vb@48
    60
    r = mailmime_smart_add_part(mime, submime);
vb@48
    61
    assert(r == MAILIMF_NO_ERROR);
vb@48
    62
    if (r == MAILIMF_ERROR_MEMORY) {
vb@48
    63
        mailmime_free(msg_mime);
vb@48
    64
        goto enomem;
vb@48
    65
    }
vb@48
    66
    else {
vb@48
    67
        // mailmime_smart_add_part() takes ownership of submime
vb@48
    68
        submime = NULL;
vb@48
    69
    }
vb@48
    70
vb@48
    71
    r = mailmime_add_part(msg_mime, mime);
vb@48
    72
    assert(r == MAILIMF_NO_ERROR);
vb@48
    73
    if (r == MAILIMF_ERROR_MEMORY) {
vb@48
    74
        goto enomem;
vb@48
    75
    }
vb@48
    76
    // mailmime_add_part() takes ownership of mime
vb@48
    77
vb@48
    78
    char *template = strdup("/tmp/temp.XXXXXXXXXXXXXXXXXXXX");
vb@48
    79
    assert(template);
vb@48
    80
    if (template == NULL)
vb@48
    81
        goto enomem;
vb@48
    82
vb@48
    83
    do {
vb@48
    84
        fd = mkstemp(template);
vb@48
    85
    } while (fd == -1 && errno == EINTR);
vb@48
    86
vb@48
    87
    assert(fd != -1);
vb@48
    88
    if (fd == -1)
vb@48
    89
        goto err_file;
vb@48
    90
vb@48
    91
    r = unlink(template);
vb@48
    92
    assert(r == 0);
vb@48
    93
    if (r == -1)
vb@48
    94
        goto err_file;
vb@48
    95
vb@48
    96
    free(template);
vb@48
    97
    template = NULL;
vb@48
    98
vb@48
    99
    do {
vb@48
   100
        file = fdopen(fd, "w+");
vb@48
   101
    } while (file == NULL && errno == EINTR);
vb@48
   102
vb@48
   103
    assert(file);
vb@48
   104
    if (file == NULL) {
vb@48
   105
        switch (errno) {
vb@48
   106
            case ENOMEM:
vb@48
   107
                goto enomem;
vb@48
   108
            default:
vb@48
   109
                goto err_file;
vb@48
   110
        }
vb@48
   111
    }
vb@48
   112
vb@48
   113
    fd = -1;
vb@48
   114
vb@48
   115
    col = 0;
vb@48
   116
    r = mailmime_write_file(file, &col, mime);
vb@48
   117
    assert(r == MAILIMF_NO_ERROR);
vb@48
   118
    if (r == MAILIMF_ERROR_MEMORY)
vb@48
   119
        goto enomem;
vb@48
   120
    else if (r != MAILIMF_NO_ERROR)
vb@48
   121
        goto err_file;
vb@48
   122
vb@48
   123
    off_t len = ftello(file);
vb@48
   124
    assert(len != -1);
vb@48
   125
    if (len == -1 && errno == EOVERFLOW)
vb@48
   126
        goto err_file;
vb@48
   127
vb@48
   128
    if (len + 1 > SIZE_T_MAX)
vb@48
   129
        goto err_buffer;
vb@48
   130
vb@48
   131
    size = (size_t) len;
vb@48
   132
vb@48
   133
    rewind(file);
vb@48
   134
vb@48
   135
    buf = calloc(1, size + 1);
vb@48
   136
    assert(buf);
vb@48
   137
    if (buf == NULL)
vb@48
   138
        goto enomem;
vb@48
   139
    
vb@48
   140
    char *_buf = buf;
vb@48
   141
    size_t rest = size;
vb@48
   142
    for (size_t bytes_read = 0; rest > 0; rest -= bytes_read, _buf += rest) {
vb@48
   143
        assert(feof(file) == 0);
vb@48
   144
        if (feof(file))
vb@48
   145
            goto err_file;
vb@48
   146
        bytes_read = fread(_buf, rest, 1, file);
vb@48
   147
        if (ferror(file))
vb@48
   148
            goto err_file;
vb@48
   149
    }
vb@48
   150
vb@48
   151
    fclose(file);
vb@48
   152
    mailmime_free(msg_mime);
vb@48
   153
    *resulttext = buf;
vb@48
   154
    return PEP_STATUS_OK;
vb@48
   155
vb@48
   156
err_buffer:
vb@48
   157
    error = PEP_BUFFER_TOO_SMALL;
vb@48
   158
    goto enomem;
vb@48
   159
vb@48
   160
err_file:
vb@48
   161
    error = PEP_CANNOT_CREATE_TEMP_FILE;
vb@48
   162
vb@48
   163
enomem:
vb@48
   164
    free(buf);
vb@48
   165
    free(template);
vb@48
   166
vb@48
   167
    if (file)
vb@48
   168
        fclose(file);
vb@48
   169
    else if (fd != -1)
vb@48
   170
        close(fd);
vb@48
   171
vb@48
   172
    if (msg_mime)
vb@48
   173
        mailmime_free(msg_mime);
vb@48
   174
    if (fields)
vb@48
   175
        mailimf_fields_free(fields);
vb@48
   176
    if (submime)
vb@48
   177
        mailmime_free(submime);
vb@48
   178
vb@48
   179
    return error;
vb@48
   180
}