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