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