src/mime.c
author vb
Mon, 09 Feb 2015 09:49:26 -0500
changeset 59 88429085f8da
parent 57 03f99659418e
child 62 ad5e484720e1
permissions -rw-r--r--
...
     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         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     assert(errno == 0);
   183     clearerr(file);
   184 
   185     buf = calloc(1, size + 1);
   186     assert(buf);
   187     if (buf == NULL)
   188         goto enomem;
   189     
   190     char *_buf = buf;
   191     size_t rest = size;
   192     for (size_t bytes_read = 0; rest > 0; rest -= bytes_read, _buf += rest) {
   193         assert(feof(file) == 0);
   194         if (feof(file))
   195             goto err_file;
   196         bytes_read = rest * fread(_buf, rest, 1, file);
   197         if (ferror(file))
   198             goto err_file;
   199     }
   200 
   201     fclose(file);
   202     mailmime_free(mime);
   203     *resulttext = buf;
   204     return PEP_STATUS_OK;
   205 
   206 err_buffer:
   207     error = PEP_BUFFER_TOO_SMALL;
   208     goto release;
   209 
   210 err_file:
   211     error = PEP_CANNOT_CREATE_TEMP_FILE;
   212     goto release;
   213 
   214 enomem:
   215     error = PEP_OUT_OF_MEMORY;
   216 
   217 release:
   218     free(buf);
   219     free(template);
   220 
   221     if (file)
   222         fclose(file);
   223     else if (fd != -1)
   224         close(fd);
   225 
   226     if (mime)
   227         mailmime_free(mime);
   228     if (submime)
   229         mailmime_free(submime);
   230 
   231     return error;
   232 }