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