src/mime.c
changeset 89 aef5a4bc78f3
parent 88 ac617f70bd7f
child 90 42b5eb9d5af2
     1.1 --- a/src/mime.c	Wed Mar 04 13:32:07 2015 +0100
     1.2 +++ b/src/mime.c	Sat Mar 07 20:29:13 2015 +0100
     1.3 @@ -10,124 +10,22 @@
     1.4  #include "etpan_mime.h"
     1.5  #include "wrappers.h"
     1.6  
     1.7 -DYNAMIC_API PEP_STATUS mime_encode_text(
     1.8 -        const char *plaintext,
     1.9 -        const char *htmltext,
    1.10 -        bloblist_t *attachments,
    1.11 -        char **mimetext
    1.12 -    )
    1.13 +static PEP_STATUS render_mime(struct mailmime *mime, char **mimetext)
    1.14  {
    1.15 -    struct mailmime * mime = NULL;
    1.16 -    struct mailmime * submime = NULL;
    1.17 -    int col;
    1.18 -    int r;
    1.19 +    PEP_STATUS status = PEP_STATUS_OK;
    1.20      int fd;
    1.21      FILE *file = NULL;
    1.22      size_t size;
    1.23      char *buf = NULL;
    1.24 -    PEP_STATUS status;
    1.25 -
    1.26 -    assert(plaintext);
    1.27 -    assert(mimetext);
    1.28 -
    1.29 -    *mimetext = NULL;
    1.30 -
    1.31 -    if (htmltext) {
    1.32 -        mime = part_multiple_new("multipart/alternative", NULL);
    1.33 -        assert(mime);
    1.34 -        if (mime == NULL)
    1.35 -            goto enomem;
    1.36 -
    1.37 -        submime = get_text_part("text/plain", plaintext, strlen(plaintext),
    1.38 -                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
    1.39 -        assert(submime);
    1.40 -        if (submime == NULL)
    1.41 -            goto enomem;
    1.42 -
    1.43 -        r = mailmime_smart_add_part(mime, submime);
    1.44 -        assert(r == MAILIMF_NO_ERROR);
    1.45 -        if (r == MAILIMF_ERROR_MEMORY) {
    1.46 -            goto enomem;
    1.47 -        }
    1.48 -        else {
    1.49 -            // mailmime_smart_add_part() takes ownership of submime
    1.50 -            submime = NULL;
    1.51 -        }
    1.52 -
    1.53 -        submime = get_text_part("text/html", htmltext, strlen(htmltext),
    1.54 -                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
    1.55 -        assert(submime);
    1.56 -        if (submime == NULL)
    1.57 -            goto enomem;
    1.58 -
    1.59 -        r = mailmime_smart_add_part(mime, submime);
    1.60 -        assert(r == MAILIMF_NO_ERROR);
    1.61 -        if (r == MAILIMF_ERROR_MEMORY)
    1.62 -            goto enomem;
    1.63 -        else {
    1.64 -            // mailmime_smart_add_part() takes ownership of submime
    1.65 -            submime = NULL;
    1.66 -        }
    1.67 -    }
    1.68 -    else {
    1.69 -        mime = get_text_part("text/plain", plaintext, strlen(plaintext),
    1.70 -                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
    1.71 -        assert(mime);
    1.72 -        if (mime == NULL)
    1.73 -            goto enomem;
    1.74 -    }
    1.75 -
    1.76 -    if (attachments) {
    1.77 -        submime = mime;
    1.78 -        mime = part_multiple_new("multipart/mixed", NULL);
    1.79 -        assert(mime);
    1.80 -        if (mime == NULL)
    1.81 -            goto enomem;
    1.82 -
    1.83 -        r = mailmime_smart_add_part(mime, submime);
    1.84 -        assert(r == MAILIMF_NO_ERROR);
    1.85 -        if (r == MAILIMF_ERROR_MEMORY) {
    1.86 -            goto enomem;
    1.87 -        }
    1.88 -        else {
    1.89 -            // mailmime_smart_add_part() takes ownership of submime
    1.90 -            submime = NULL;
    1.91 -        }
    1.92 -
    1.93 -        bloblist_t *_a;
    1.94 -        for (_a = attachments; _a != NULL; _a = _a->next) {
    1.95 -            char * mime_type;
    1.96 -
    1.97 -            assert(_a->data);
    1.98 -            assert(_a->size);
    1.99 -
   1.100 -            if (_a->mime_type == NULL)
   1.101 -                mime_type = "application/octet-stream";
   1.102 -            else
   1.103 -                mime_type = _a->mime_type;
   1.104 -
   1.105 -            submime = get_file_part(_a->file_name, mime_type, _a->data, _a->size);
   1.106 -            assert(submime);
   1.107 -            if (submime == NULL)
   1.108 -                goto enomem;
   1.109 -
   1.110 -            r = mailmime_smart_add_part(mime, submime);
   1.111 -            assert(r == MAILIMF_NO_ERROR);
   1.112 -            if (r == MAILIMF_ERROR_MEMORY) {
   1.113 -                goto enomem;
   1.114 -            }
   1.115 -            else {
   1.116 -                // mailmime_smart_add_part() takes ownership of submime
   1.117 -                submime = NULL;
   1.118 -            }
   1.119 -        }
   1.120 -    }
   1.121 -
   1.122 +    int col;
   1.123 +    int r;
   1.124      char *template = strdup("/tmp/pEp.XXXXXXXXXXXXXXXXXXXX");
   1.125      assert(template);
   1.126      if (template == NULL)
   1.127          goto enomem;
   1.128  
   1.129 +    *mimetext = NULL;
   1.130 +
   1.131      fd = Mkstemp(template);
   1.132      assert(fd != -1);
   1.133      if (fd == -1)
   1.134 @@ -190,13 +88,12 @@
   1.135          goto enomem;
   1.136   
   1.137      size_t _read;
   1.138 -    _read = Fread1(buf, size, file);
   1.139 +    _read = Fread(buf, size, 1, file);
   1.140      assert(_read == size);
   1.141  
   1.142      r = Fclose(file);
   1.143      assert(r == 0);
   1.144  
   1.145 -    mailmime_free(mime);
   1.146      *mimetext = buf;
   1.147      return PEP_STATUS_OK;
   1.148  
   1.149 @@ -224,38 +121,312 @@
   1.150          assert(r == 0);
   1.151      }
   1.152  
   1.153 +    return status;
   1.154 +}
   1.155 +
   1.156 +static PEP_STATUS mime_html_text(
   1.157 +        const char *plaintext,
   1.158 +        const char *htmltext,
   1.159 +        struct mailmime **result
   1.160 +    )
   1.161 +{
   1.162 +    PEP_STATUS status = PEP_STATUS_OK;
   1.163 +    struct mailmime * mime = NULL;
   1.164 +    struct mailmime * submime = NULL;
   1.165 +    int r;
   1.166 +
   1.167 +    assert(plaintext);
   1.168 +    assert(htmltext);
   1.169 +    assert(result);
   1.170 +
   1.171 +    *result = NULL;
   1.172 +
   1.173 +    mime = part_multiple_new("multipart/alternative", NULL);
   1.174 +    assert(mime);
   1.175 +    if (mime == NULL)
   1.176 +        goto enomem;
   1.177 +
   1.178 +    submime = get_text_part("text/plain", plaintext, strlen(plaintext),
   1.179 +            MAILMIME_MECHANISM_QUOTED_PRINTABLE);
   1.180 +    assert(submime);
   1.181 +    if (submime == NULL)
   1.182 +        goto enomem;
   1.183 +
   1.184 +    r = mailmime_smart_add_part(mime, submime);
   1.185 +    assert(r == MAILIMF_NO_ERROR);
   1.186 +    if (r == MAILIMF_ERROR_MEMORY) {
   1.187 +        goto enomem;
   1.188 +    }
   1.189 +    else {
   1.190 +        // mailmime_smart_add_part() takes ownership of submime
   1.191 +        submime = NULL;
   1.192 +    }
   1.193 +
   1.194 +    submime = get_text_part("text/html", htmltext, strlen(htmltext),
   1.195 +            MAILMIME_MECHANISM_QUOTED_PRINTABLE);
   1.196 +    assert(submime);
   1.197 +    if (submime == NULL)
   1.198 +        goto enomem;
   1.199 +
   1.200 +    r = mailmime_smart_add_part(mime, submime);
   1.201 +    assert(r == MAILIMF_NO_ERROR);
   1.202 +    if (r == MAILIMF_ERROR_MEMORY)
   1.203 +        goto enomem;
   1.204 +    else {
   1.205 +        // mailmime_smart_add_part() takes ownership of submime
   1.206 +        submime = NULL;
   1.207 +    }
   1.208 +
   1.209 +    *result = mime;
   1.210 +    return PEP_STATUS_OK;
   1.211 +
   1.212 +enomem:
   1.213 +    status = PEP_OUT_OF_MEMORY;
   1.214 +
   1.215 +pep_error:
   1.216      if (mime)
   1.217          mailmime_free(mime);
   1.218 +
   1.219      if (submime)
   1.220          mailmime_free(submime);
   1.221  
   1.222      return status;
   1.223  }
   1.224  
   1.225 -DYNAMIC_API PEP_STATUS mime_decode_text(
   1.226 -        const char *mimetext,
   1.227 -        char **plaintext,
   1.228 -        char **htmltext,
   1.229 -        bloblist_t **attachments
   1.230 +static PEP_STATUS mime_attachment(
   1.231 +        bloblist_t *blob,
   1.232 +        struct mailmime **result
   1.233      )
   1.234  {
   1.235      PEP_STATUS status = PEP_STATUS_OK;
   1.236 +    struct mailmime * mime = NULL;
   1.237 +    char * mime_type;
   1.238  
   1.239 -    assert(mimetext);
   1.240 -    assert(plaintext);
   1.241 -    assert(htmltext);
   1.242 -    assert(attachments);
   1.243 +    assert(blob);
   1.244 +    assert(result);
   1.245  
   1.246 -    *plaintext = NULL;
   1.247 -    *htmltext = NULL;
   1.248 -    *attachments = NULL;
   1.249 +    *result = NULL;
   1.250  
   1.251 -    return status;
   1.252 +    if (blob->mime_type == NULL)
   1.253 +        mime_type = "application/octet-stream";
   1.254 +    else
   1.255 +        mime_type = blob->mime_type;
   1.256 +
   1.257 +    mime = get_file_part(blob->file_name, mime_type, blob->data, blob->size);
   1.258 +    assert(mime);
   1.259 +    if (mime == NULL)
   1.260 +        goto enomem;
   1.261 +
   1.262 +    *result = mime;
   1.263 +    return PEP_STATUS_OK;
   1.264  
   1.265  enomem:
   1.266      status = PEP_OUT_OF_MEMORY;
   1.267  
   1.268  pep_error:
   1.269 +    if (mime)
   1.270 +        mailmime_free(mime);
   1.271 +
   1.272      return status;
   1.273  }
   1.274  
   1.275 +static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result)
   1.276 +{
   1.277 +    PEP_STATUS status = PEP_STATUS_OK;
   1.278 +    struct mailimf_fields * fields = NULL;
   1.279 +    int r;
   1.280 +    clist * list;
   1.281 +    clist * fields_list = NULL;
   1.282 +    char *subject = msg->shortmsg ? msg->shortmsg : "pEp";
   1.283 +
   1.284 +    assert(msg);
   1.285 +    assert(msg->from);
   1.286 +    assert(msg->from->address);
   1.287 +    assert(result);
   1.288 +
   1.289 +    *result = NULL;
   1.290 +
   1.291 +    fields_list = clist_new();
   1.292 +    assert(fields_list);
   1.293 +    if (fields_list == NULL)
   1.294 +        goto enomem;
   1.295 +
   1.296 +    r = _append_field(fields_list, MAILIMF_FIELD_MESSAGE_ID,
   1.297 +            (_new_func_t) mailimf_message_id_new, msg->id);
   1.298 +    if (r == -1)
   1.299 +        goto enomem;
   1.300 +
   1.301 +    r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
   1.302 +            (_new_func_t) mailimf_subject_new, subject);
   1.303 +    if (r == -1)
   1.304 +        goto enomem;
   1.305 +
   1.306 +    fields = mailimf_fields_new(fields_list);
   1.307 +    assert(fields);
   1.308 +    if (fields == NULL)
   1.309 +        goto enomem;
   1.310 +
   1.311 +    *result = fields;
   1.312 +
   1.313 +    return PEP_STATUS_OK;
   1.314 +
   1.315 +enomem:
   1.316 +    status = PEP_OUT_OF_MEMORY;
   1.317 +
   1.318 +pep_error:
   1.319 +    if (fields_list)
   1.320 +        clist_free(fields_list);
   1.321 +
   1.322 +    if (fields)
   1.323 +        mailimf_fields_free(fields);
   1.324 +
   1.325 +    return status;
   1.326 +}
   1.327 +
   1.328 +DYNAMIC_API PEP_STATUS mime_encode_message(
   1.329 +        const message *msg,
   1.330 +        char **mimetext
   1.331 +    )
   1.332 +{
   1.333 +    struct mailmime * msg_mime = NULL;
   1.334 +    struct mailmime * mime = NULL;
   1.335 +    struct mailmime * submime = NULL;
   1.336 +    char *buf = NULL;
   1.337 +    int r;
   1.338 +    PEP_STATUS status;
   1.339 +    char *subject;
   1.340 +    char *plaintext;
   1.341 +    char *htmltext;
   1.342 +
   1.343 +    assert(msg);
   1.344 +    assert(mimetext);
   1.345 +
   1.346 +    *mimetext = NULL;
   1.347 +
   1.348 +    subject = (msg->shortmsg) ? msg->shortmsg : "pEp";
   1.349 +    plaintext = (msg->longmsg) ? msg->longmsg : "";
   1.350 +    htmltext = msg->longmsg_formatted;
   1.351 +
   1.352 +    if (htmltext) {
   1.353 +        status = mime_html_text(plaintext, htmltext, &mime);
   1.354 +        if (status != PEP_STATUS_OK)
   1.355 +            goto pep_error;
   1.356 +    }
   1.357 +    else {
   1.358 +        mime = get_text_part("text/plain", msg->longmsg, strlen(msg->longmsg),
   1.359 +                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
   1.360 +        assert(mime);
   1.361 +        if (mime == NULL)
   1.362 +            goto enomem;
   1.363 +    }
   1.364 +
   1.365 +    if (msg->attachments) {
   1.366 +        submime = mime;
   1.367 +        mime = part_multiple_new("multipart/mixed", NULL);
   1.368 +        assert(mime);
   1.369 +        if (mime == NULL)
   1.370 +            goto enomem;
   1.371 +
   1.372 +        r = mailmime_smart_add_part(mime, submime);
   1.373 +        assert(r == MAILIMF_NO_ERROR);
   1.374 +        if (r == MAILIMF_ERROR_MEMORY) {
   1.375 +            goto enomem;
   1.376 +        }
   1.377 +        else {
   1.378 +            // mailmime_smart_add_part() takes ownership of submime
   1.379 +            submime = NULL;
   1.380 +        }
   1.381 +
   1.382 +        bloblist_t *_a;
   1.383 +        for (_a = msg->attachments; _a != NULL; _a = _a->next) {
   1.384 +            char * mime_type;
   1.385 +
   1.386 +            assert(_a->data);
   1.387 +            assert(_a->size);
   1.388 +
   1.389 +            status = mime_attachment(_a, &submime);
   1.390 +            if (status != PEP_STATUS_OK)
   1.391 +                goto pep_error;
   1.392 +
   1.393 +            r = mailmime_smart_add_part(mime, submime);
   1.394 +            assert(r == MAILIMF_NO_ERROR);
   1.395 +            if (r == MAILIMF_ERROR_MEMORY) {
   1.396 +                goto enomem;
   1.397 +            }
   1.398 +            else {
   1.399 +                // mailmime_smart_add_part() takes ownership of submime
   1.400 +                submime = NULL;
   1.401 +            }
   1.402 +        }
   1.403 +    }
   1.404 +
   1.405 +    msg_mime = mailmime_new_message_data(NULL);
   1.406 +    mailmime_add_part(msg_mime, mime);
   1.407 +
   1.408 +    status = render_mime(mime, &buf);
   1.409 +    if (status != PEP_STATUS_OK)
   1.410 +        goto pep_error;
   1.411 +
   1.412 +    mailmime_free(msg_mime);
   1.413 +    *mimetext = buf;
   1.414 +    return PEP_STATUS_OK;
   1.415 +
   1.416 +enomem:
   1.417 +    status = PEP_OUT_OF_MEMORY;
   1.418 +
   1.419 +pep_error:
   1.420 +    if (msg_mime)
   1.421 +        mailmime_free(mime);
   1.422 +    else
   1.423 +        if (mime)
   1.424 +            mailmime_free(mime);
   1.425 +
   1.426 +    if (submime)
   1.427 +        mailmime_free(submime);
   1.428 +
   1.429 +    return status;
   1.430 +}
   1.431 +
   1.432 +DYNAMIC_API PEP_STATUS mime_decode_message(
   1.433 +        const char *mimetext,
   1.434 +        message **msg
   1.435 +    )
   1.436 +{
   1.437 +    PEP_STATUS status = PEP_STATUS_OK;
   1.438 +    struct mailmime * mime = NULL;
   1.439 +    int r;
   1.440 +
   1.441 +    assert(mimetext);
   1.442 +    assert(msg);
   1.443 +
   1.444 +    *msg = NULL;
   1.445 +    
   1.446 +    size_t index = 0;
   1.447 +    r = mailmime_parse(mimetext, strlen(mimetext), &index, &mime);
   1.448 +    assert(r == 0);
   1.449 +    assert(mime);
   1.450 +    if (r != 0) {
   1.451 +        if (r == MAILIMF_ERROR_MEMORY)
   1.452 +            goto enomem;
   1.453 +        else
   1.454 +            goto err_mime;
   1.455 +    }
   1.456 +
   1.457 +    mailmime_free(mime);
   1.458 +
   1.459 +    return status;
   1.460 +
   1.461 +err_mime:
   1.462 +    status = PEP_ILLEGAL_VALUE;
   1.463 +    goto pep_error;
   1.464 +
   1.465 +enomem:
   1.466 +    status = PEP_OUT_OF_MEMORY;
   1.467 +
   1.468 +pep_error:
   1.469 +    if (mime)
   1.470 +        mailmime_free(mime);
   1.471 +
   1.472 +    return status;
   1.473 +}
   1.474 +