...
authorvb
Sat, 07 Mar 2015 20:29:13 +0100
changeset 89aef5a4bc78f3
parent 88 ac617f70bd7f
child 90 42b5eb9d5af2
...
src/etpan_mime.c
src/etpan_mime.h
src/message_api.c
src/mime.c
src/mime.h
src/platform_windows.h
src/transport.c
src/transport.h
src/wrappers.h
test/mime_test.cc
     1.1 --- a/src/etpan_mime.c	Wed Mar 04 13:32:07 2015 +0100
     1.2 +++ b/src/etpan_mime.c	Sat Mar 07 20:29:13 2015 +0100
     1.3 @@ -1,12 +1,15 @@
     1.4  #include <string.h>
     1.5  #include <stdlib.h>
     1.6  #include <unistd.h>
     1.7 +#include <assert.h>
     1.8  
     1.9  #include "etpan_mime.h"
    1.10  #ifndef mailmime_param_new_with_data
    1.11  #include <libetpan/mailprivacy_tools.h>
    1.12  #endif
    1.13  
    1.14 +time_t mail_mkgmtime(struct tm * tmp);
    1.15 +
    1.16  #define MAX_MESSAGE_ID 512
    1.17  
    1.18  static char * generate_boundary(const char * boundary_prefix)
    1.19 @@ -242,3 +245,101 @@
    1.20      return NULL;
    1.21  }
    1.22  
    1.23 +struct mailimf_field * _new_field(
    1.24 +        int type,
    1.25 +        _new_func_t new_func,
    1.26 +        void *value
    1.27 +    )
    1.28 +{
    1.29 +    void *data = new_func(value);
    1.30 +    assert(data);
    1.31 +    if (data == NULL)
    1.32 +        return NULL;
    1.33 +
    1.34 +    struct mailimf_field * result = calloc(1, sizeof(struct mailimf_field));
    1.35 +    assert(result);
    1.36 +    if (result == NULL) {
    1.37 +        free(data);
    1.38 +        return NULL;
    1.39 +    }
    1.40 +
    1.41 +    result->fld_type = type;
    1.42 +    result->fld_data.fld_return_path = data;
    1.43 +
    1.44 +    return result;
    1.45 +}
    1.46 +
    1.47 +void _free_field(struct mailimf_field *field)
    1.48 +{
    1.49 +    if (field)
    1.50 +        free(field->fld_data.fld_return_path);
    1.51 +    free(field);
    1.52 +}
    1.53 +
    1.54 +int _append_field(
    1.55 +        clist *list,
    1.56 +        int type,
    1.57 +        _new_func_t new_func,
    1.58 +        void *value
    1.59 +    )
    1.60 +{
    1.61 +    int r;
    1.62 +    struct mailimf_field * field;
    1.63 +
    1.64 +    assert(list);
    1.65 +    assert(new_func);
    1.66 +    assert(value);
    1.67 +
    1.68 +    field = _new_field(type, new_func, value);
    1.69 +    if (field == NULL)
    1.70 +        return -1;
    1.71 +
    1.72 +
    1.73 +    r = clist_append(list, field);
    1.74 +    if (r == -1)
    1.75 +        _free_field(field);
    1.76 +
    1.77 +    return r;
    1.78 +}
    1.79 +
    1.80 +struct mailimf_date_time * timestamp_to_etpantime(const struct tm *ts)
    1.81 +{
    1.82 +    struct mailimf_date_time * result = calloc(1,
    1.83 +            sizeof(struct mailimf_date_time));
    1.84 +    assert(result);
    1.85 +    if (result == NULL)
    1.86 +        return NULL;
    1.87 +
    1.88 +    assert(ts);
    1.89 +
    1.90 +    result->dt_sec = ts->tm_sec;
    1.91 +    result->dt_min = ts->tm_min;
    1.92 +    result->dt_hour = ts->tm_hour;
    1.93 +    result->dt_day = ts->tm_mday;
    1.94 +    result->dt_month = ts->tm_mon + 1;
    1.95 +    result->dt_year = ts->tm_year + 1900;
    1.96 +    result->dt_zone = (int) (ts->tm_gmtoff / 36L);
    1.97 +
    1.98 +    return result;
    1.99 +}
   1.100 +
   1.101 +struct tm * etpantime_to_timestamp(const struct mailimf_date_time *et)
   1.102 +{
   1.103 +    struct tm * result = calloc(1, sizeof(struct tm));
   1.104 +    assert(result);
   1.105 +    if (result == NULL)
   1.106 +        return NULL;
   1.107 +
   1.108 +    assert(et);
   1.109 +
   1.110 +    result->tm_sec = et->dt_sec;
   1.111 +    result->tm_min = et->dt_min;
   1.112 +    result->tm_hour = et->dt_hour;
   1.113 +    result->tm_mday = et->dt_day;
   1.114 +    result->tm_mon = et->dt_month - 1;
   1.115 +    result->tm_year = et->dt_year - 1900;
   1.116 +    result->tm_gmtoff = 36L * (long) et->dt_zone;
   1.117 +
   1.118 +    return result;
   1.119 +}
   1.120 +
     2.1 --- a/src/etpan_mime.h	Wed Mar 04 13:32:07 2015 +0100
     2.2 +++ b/src/etpan_mime.h	Sat Mar 07 20:29:13 2015 +0100
     2.3 @@ -2,7 +2,6 @@
     2.4  
     2.5  #include <libetpan/libetpan.h>
     2.6  
     2.7 -
     2.8  struct mailmime * part_new_empty(
     2.9          struct mailmime_content * content,
    2.10          struct mailmime_fields * mime_fields,
    2.11 @@ -29,3 +28,23 @@
    2.12          const char * boundary_prefix
    2.13      );
    2.14  
    2.15 +typedef void *(*_new_func_t)(void *);
    2.16 +
    2.17 +struct mailimf_field * _new_field(
    2.18 +        int type,
    2.19 +        _new_func_t new_func,
    2.20 +        void *value
    2.21 +    );
    2.22 +
    2.23 +void _free_field(struct mailimf_field *field);
    2.24 +
    2.25 +int _append_field(
    2.26 +        clist *list,
    2.27 +        int type,
    2.28 +        _new_func_t new_func,
    2.29 +        void *value
    2.30 +    );
    2.31 +
    2.32 +struct mailimf_date_time * timestamp_to_etpantime(const struct tm *ts);
    2.33 +struct tm * etpantime_to_timestamp(const struct mailimf_date_time *et);
    2.34 +
     3.1 --- a/src/message_api.c	Wed Mar 04 13:32:07 2015 +0100
     3.2 +++ b/src/message_api.c	Sat Mar 07 20:29:13 2015 +0100
     3.3 @@ -248,12 +248,18 @@
     3.4              }
     3.5  
     3.6              if (src->enc_format == PEP_enc_none) {
     3.7 -                char *_ptext = ptext;
     3.8 -                status = mime_encode_text(_ptext, src->longmsg_formatted,
     3.9 -                        src->attachments, &ptext);
    3.10 +                message *_src = (message *) malloc(sizeof(message));
    3.11 +                assert(_src);
    3.12 +                if (_src == NULL)
    3.13 +                    goto enomem;
    3.14 +                memcpy(_src, src, sizeof(message));
    3.15 +                _src->shortmsg = "pEp";
    3.16 +                _src->longmsg = ptext;
    3.17 +                status = mime_encode_message(src, &ptext);
    3.18                  assert(status == PEP_STATUS_OK);
    3.19                  if (free_ptext)
    3.20 -                    free(_ptext);
    3.21 +                    free(_src->longmsg);
    3.22 +                free(_src);
    3.23                  assert(ptext);
    3.24                  if (ptext == NULL)
    3.25                      goto pep_error;
     4.1 --- a/src/mime.c	Wed Mar 04 13:32:07 2015 +0100
     4.2 +++ b/src/mime.c	Sat Mar 07 20:29:13 2015 +0100
     4.3 @@ -10,124 +10,22 @@
     4.4  #include "etpan_mime.h"
     4.5  #include "wrappers.h"
     4.6  
     4.7 -DYNAMIC_API PEP_STATUS mime_encode_text(
     4.8 -        const char *plaintext,
     4.9 -        const char *htmltext,
    4.10 -        bloblist_t *attachments,
    4.11 -        char **mimetext
    4.12 -    )
    4.13 +static PEP_STATUS render_mime(struct mailmime *mime, char **mimetext)
    4.14  {
    4.15 -    struct mailmime * mime = NULL;
    4.16 -    struct mailmime * submime = NULL;
    4.17 -    int col;
    4.18 -    int r;
    4.19 +    PEP_STATUS status = PEP_STATUS_OK;
    4.20      int fd;
    4.21      FILE *file = NULL;
    4.22      size_t size;
    4.23      char *buf = NULL;
    4.24 -    PEP_STATUS status;
    4.25 -
    4.26 -    assert(plaintext);
    4.27 -    assert(mimetext);
    4.28 -
    4.29 -    *mimetext = NULL;
    4.30 -
    4.31 -    if (htmltext) {
    4.32 -        mime = part_multiple_new("multipart/alternative", NULL);
    4.33 -        assert(mime);
    4.34 -        if (mime == NULL)
    4.35 -            goto enomem;
    4.36 -
    4.37 -        submime = get_text_part("text/plain", plaintext, strlen(plaintext),
    4.38 -                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
    4.39 -        assert(submime);
    4.40 -        if (submime == NULL)
    4.41 -            goto enomem;
    4.42 -
    4.43 -        r = mailmime_smart_add_part(mime, submime);
    4.44 -        assert(r == MAILIMF_NO_ERROR);
    4.45 -        if (r == MAILIMF_ERROR_MEMORY) {
    4.46 -            goto enomem;
    4.47 -        }
    4.48 -        else {
    4.49 -            // mailmime_smart_add_part() takes ownership of submime
    4.50 -            submime = NULL;
    4.51 -        }
    4.52 -
    4.53 -        submime = get_text_part("text/html", htmltext, strlen(htmltext),
    4.54 -                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
    4.55 -        assert(submime);
    4.56 -        if (submime == NULL)
    4.57 -            goto enomem;
    4.58 -
    4.59 -        r = mailmime_smart_add_part(mime, submime);
    4.60 -        assert(r == MAILIMF_NO_ERROR);
    4.61 -        if (r == MAILIMF_ERROR_MEMORY)
    4.62 -            goto enomem;
    4.63 -        else {
    4.64 -            // mailmime_smart_add_part() takes ownership of submime
    4.65 -            submime = NULL;
    4.66 -        }
    4.67 -    }
    4.68 -    else {
    4.69 -        mime = get_text_part("text/plain", plaintext, strlen(plaintext),
    4.70 -                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
    4.71 -        assert(mime);
    4.72 -        if (mime == NULL)
    4.73 -            goto enomem;
    4.74 -    }
    4.75 -
    4.76 -    if (attachments) {
    4.77 -        submime = mime;
    4.78 -        mime = part_multiple_new("multipart/mixed", NULL);
    4.79 -        assert(mime);
    4.80 -        if (mime == NULL)
    4.81 -            goto enomem;
    4.82 -
    4.83 -        r = mailmime_smart_add_part(mime, submime);
    4.84 -        assert(r == MAILIMF_NO_ERROR);
    4.85 -        if (r == MAILIMF_ERROR_MEMORY) {
    4.86 -            goto enomem;
    4.87 -        }
    4.88 -        else {
    4.89 -            // mailmime_smart_add_part() takes ownership of submime
    4.90 -            submime = NULL;
    4.91 -        }
    4.92 -
    4.93 -        bloblist_t *_a;
    4.94 -        for (_a = attachments; _a != NULL; _a = _a->next) {
    4.95 -            char * mime_type;
    4.96 -
    4.97 -            assert(_a->data);
    4.98 -            assert(_a->size);
    4.99 -
   4.100 -            if (_a->mime_type == NULL)
   4.101 -                mime_type = "application/octet-stream";
   4.102 -            else
   4.103 -                mime_type = _a->mime_type;
   4.104 -
   4.105 -            submime = get_file_part(_a->file_name, mime_type, _a->data, _a->size);
   4.106 -            assert(submime);
   4.107 -            if (submime == NULL)
   4.108 -                goto enomem;
   4.109 -
   4.110 -            r = mailmime_smart_add_part(mime, submime);
   4.111 -            assert(r == MAILIMF_NO_ERROR);
   4.112 -            if (r == MAILIMF_ERROR_MEMORY) {
   4.113 -                goto enomem;
   4.114 -            }
   4.115 -            else {
   4.116 -                // mailmime_smart_add_part() takes ownership of submime
   4.117 -                submime = NULL;
   4.118 -            }
   4.119 -        }
   4.120 -    }
   4.121 -
   4.122 +    int col;
   4.123 +    int r;
   4.124      char *template = strdup("/tmp/pEp.XXXXXXXXXXXXXXXXXXXX");
   4.125      assert(template);
   4.126      if (template == NULL)
   4.127          goto enomem;
   4.128  
   4.129 +    *mimetext = NULL;
   4.130 +
   4.131      fd = Mkstemp(template);
   4.132      assert(fd != -1);
   4.133      if (fd == -1)
   4.134 @@ -190,13 +88,12 @@
   4.135          goto enomem;
   4.136   
   4.137      size_t _read;
   4.138 -    _read = Fread1(buf, size, file);
   4.139 +    _read = Fread(buf, size, 1, file);
   4.140      assert(_read == size);
   4.141  
   4.142      r = Fclose(file);
   4.143      assert(r == 0);
   4.144  
   4.145 -    mailmime_free(mime);
   4.146      *mimetext = buf;
   4.147      return PEP_STATUS_OK;
   4.148  
   4.149 @@ -224,38 +121,312 @@
   4.150          assert(r == 0);
   4.151      }
   4.152  
   4.153 +    return status;
   4.154 +}
   4.155 +
   4.156 +static PEP_STATUS mime_html_text(
   4.157 +        const char *plaintext,
   4.158 +        const char *htmltext,
   4.159 +        struct mailmime **result
   4.160 +    )
   4.161 +{
   4.162 +    PEP_STATUS status = PEP_STATUS_OK;
   4.163 +    struct mailmime * mime = NULL;
   4.164 +    struct mailmime * submime = NULL;
   4.165 +    int r;
   4.166 +
   4.167 +    assert(plaintext);
   4.168 +    assert(htmltext);
   4.169 +    assert(result);
   4.170 +
   4.171 +    *result = NULL;
   4.172 +
   4.173 +    mime = part_multiple_new("multipart/alternative", NULL);
   4.174 +    assert(mime);
   4.175 +    if (mime == NULL)
   4.176 +        goto enomem;
   4.177 +
   4.178 +    submime = get_text_part("text/plain", plaintext, strlen(plaintext),
   4.179 +            MAILMIME_MECHANISM_QUOTED_PRINTABLE);
   4.180 +    assert(submime);
   4.181 +    if (submime == NULL)
   4.182 +        goto enomem;
   4.183 +
   4.184 +    r = mailmime_smart_add_part(mime, submime);
   4.185 +    assert(r == MAILIMF_NO_ERROR);
   4.186 +    if (r == MAILIMF_ERROR_MEMORY) {
   4.187 +        goto enomem;
   4.188 +    }
   4.189 +    else {
   4.190 +        // mailmime_smart_add_part() takes ownership of submime
   4.191 +        submime = NULL;
   4.192 +    }
   4.193 +
   4.194 +    submime = get_text_part("text/html", htmltext, strlen(htmltext),
   4.195 +            MAILMIME_MECHANISM_QUOTED_PRINTABLE);
   4.196 +    assert(submime);
   4.197 +    if (submime == NULL)
   4.198 +        goto enomem;
   4.199 +
   4.200 +    r = mailmime_smart_add_part(mime, submime);
   4.201 +    assert(r == MAILIMF_NO_ERROR);
   4.202 +    if (r == MAILIMF_ERROR_MEMORY)
   4.203 +        goto enomem;
   4.204 +    else {
   4.205 +        // mailmime_smart_add_part() takes ownership of submime
   4.206 +        submime = NULL;
   4.207 +    }
   4.208 +
   4.209 +    *result = mime;
   4.210 +    return PEP_STATUS_OK;
   4.211 +
   4.212 +enomem:
   4.213 +    status = PEP_OUT_OF_MEMORY;
   4.214 +
   4.215 +pep_error:
   4.216      if (mime)
   4.217          mailmime_free(mime);
   4.218 +
   4.219      if (submime)
   4.220          mailmime_free(submime);
   4.221  
   4.222      return status;
   4.223  }
   4.224  
   4.225 -DYNAMIC_API PEP_STATUS mime_decode_text(
   4.226 -        const char *mimetext,
   4.227 -        char **plaintext,
   4.228 -        char **htmltext,
   4.229 -        bloblist_t **attachments
   4.230 +static PEP_STATUS mime_attachment(
   4.231 +        bloblist_t *blob,
   4.232 +        struct mailmime **result
   4.233      )
   4.234  {
   4.235      PEP_STATUS status = PEP_STATUS_OK;
   4.236 +    struct mailmime * mime = NULL;
   4.237 +    char * mime_type;
   4.238  
   4.239 -    assert(mimetext);
   4.240 -    assert(plaintext);
   4.241 -    assert(htmltext);
   4.242 -    assert(attachments);
   4.243 +    assert(blob);
   4.244 +    assert(result);
   4.245  
   4.246 -    *plaintext = NULL;
   4.247 -    *htmltext = NULL;
   4.248 -    *attachments = NULL;
   4.249 +    *result = NULL;
   4.250  
   4.251 -    return status;
   4.252 +    if (blob->mime_type == NULL)
   4.253 +        mime_type = "application/octet-stream";
   4.254 +    else
   4.255 +        mime_type = blob->mime_type;
   4.256 +
   4.257 +    mime = get_file_part(blob->file_name, mime_type, blob->data, blob->size);
   4.258 +    assert(mime);
   4.259 +    if (mime == NULL)
   4.260 +        goto enomem;
   4.261 +
   4.262 +    *result = mime;
   4.263 +    return PEP_STATUS_OK;
   4.264  
   4.265  enomem:
   4.266      status = PEP_OUT_OF_MEMORY;
   4.267  
   4.268  pep_error:
   4.269 +    if (mime)
   4.270 +        mailmime_free(mime);
   4.271 +
   4.272      return status;
   4.273  }
   4.274  
   4.275 +static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result)
   4.276 +{
   4.277 +    PEP_STATUS status = PEP_STATUS_OK;
   4.278 +    struct mailimf_fields * fields = NULL;
   4.279 +    int r;
   4.280 +    clist * list;
   4.281 +    clist * fields_list = NULL;
   4.282 +    char *subject = msg->shortmsg ? msg->shortmsg : "pEp";
   4.283 +
   4.284 +    assert(msg);
   4.285 +    assert(msg->from);
   4.286 +    assert(msg->from->address);
   4.287 +    assert(result);
   4.288 +
   4.289 +    *result = NULL;
   4.290 +
   4.291 +    fields_list = clist_new();
   4.292 +    assert(fields_list);
   4.293 +    if (fields_list == NULL)
   4.294 +        goto enomem;
   4.295 +
   4.296 +    r = _append_field(fields_list, MAILIMF_FIELD_MESSAGE_ID,
   4.297 +            (_new_func_t) mailimf_message_id_new, msg->id);
   4.298 +    if (r == -1)
   4.299 +        goto enomem;
   4.300 +
   4.301 +    r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
   4.302 +            (_new_func_t) mailimf_subject_new, subject);
   4.303 +    if (r == -1)
   4.304 +        goto enomem;
   4.305 +
   4.306 +    fields = mailimf_fields_new(fields_list);
   4.307 +    assert(fields);
   4.308 +    if (fields == NULL)
   4.309 +        goto enomem;
   4.310 +
   4.311 +    *result = fields;
   4.312 +
   4.313 +    return PEP_STATUS_OK;
   4.314 +
   4.315 +enomem:
   4.316 +    status = PEP_OUT_OF_MEMORY;
   4.317 +
   4.318 +pep_error:
   4.319 +    if (fields_list)
   4.320 +        clist_free(fields_list);
   4.321 +
   4.322 +    if (fields)
   4.323 +        mailimf_fields_free(fields);
   4.324 +
   4.325 +    return status;
   4.326 +}
   4.327 +
   4.328 +DYNAMIC_API PEP_STATUS mime_encode_message(
   4.329 +        const message *msg,
   4.330 +        char **mimetext
   4.331 +    )
   4.332 +{
   4.333 +    struct mailmime * msg_mime = NULL;
   4.334 +    struct mailmime * mime = NULL;
   4.335 +    struct mailmime * submime = NULL;
   4.336 +    char *buf = NULL;
   4.337 +    int r;
   4.338 +    PEP_STATUS status;
   4.339 +    char *subject;
   4.340 +    char *plaintext;
   4.341 +    char *htmltext;
   4.342 +
   4.343 +    assert(msg);
   4.344 +    assert(mimetext);
   4.345 +
   4.346 +    *mimetext = NULL;
   4.347 +
   4.348 +    subject = (msg->shortmsg) ? msg->shortmsg : "pEp";
   4.349 +    plaintext = (msg->longmsg) ? msg->longmsg : "";
   4.350 +    htmltext = msg->longmsg_formatted;
   4.351 +
   4.352 +    if (htmltext) {
   4.353 +        status = mime_html_text(plaintext, htmltext, &mime);
   4.354 +        if (status != PEP_STATUS_OK)
   4.355 +            goto pep_error;
   4.356 +    }
   4.357 +    else {
   4.358 +        mime = get_text_part("text/plain", msg->longmsg, strlen(msg->longmsg),
   4.359 +                MAILMIME_MECHANISM_QUOTED_PRINTABLE);
   4.360 +        assert(mime);
   4.361 +        if (mime == NULL)
   4.362 +            goto enomem;
   4.363 +    }
   4.364 +
   4.365 +    if (msg->attachments) {
   4.366 +        submime = mime;
   4.367 +        mime = part_multiple_new("multipart/mixed", NULL);
   4.368 +        assert(mime);
   4.369 +        if (mime == NULL)
   4.370 +            goto enomem;
   4.371 +
   4.372 +        r = mailmime_smart_add_part(mime, submime);
   4.373 +        assert(r == MAILIMF_NO_ERROR);
   4.374 +        if (r == MAILIMF_ERROR_MEMORY) {
   4.375 +            goto enomem;
   4.376 +        }
   4.377 +        else {
   4.378 +            // mailmime_smart_add_part() takes ownership of submime
   4.379 +            submime = NULL;
   4.380 +        }
   4.381 +
   4.382 +        bloblist_t *_a;
   4.383 +        for (_a = msg->attachments; _a != NULL; _a = _a->next) {
   4.384 +            char * mime_type;
   4.385 +
   4.386 +            assert(_a->data);
   4.387 +            assert(_a->size);
   4.388 +
   4.389 +            status = mime_attachment(_a, &submime);
   4.390 +            if (status != PEP_STATUS_OK)
   4.391 +                goto pep_error;
   4.392 +
   4.393 +            r = mailmime_smart_add_part(mime, submime);
   4.394 +            assert(r == MAILIMF_NO_ERROR);
   4.395 +            if (r == MAILIMF_ERROR_MEMORY) {
   4.396 +                goto enomem;
   4.397 +            }
   4.398 +            else {
   4.399 +                // mailmime_smart_add_part() takes ownership of submime
   4.400 +                submime = NULL;
   4.401 +            }
   4.402 +        }
   4.403 +    }
   4.404 +
   4.405 +    msg_mime = mailmime_new_message_data(NULL);
   4.406 +    mailmime_add_part(msg_mime, mime);
   4.407 +
   4.408 +    status = render_mime(mime, &buf);
   4.409 +    if (status != PEP_STATUS_OK)
   4.410 +        goto pep_error;
   4.411 +
   4.412 +    mailmime_free(msg_mime);
   4.413 +    *mimetext = buf;
   4.414 +    return PEP_STATUS_OK;
   4.415 +
   4.416 +enomem:
   4.417 +    status = PEP_OUT_OF_MEMORY;
   4.418 +
   4.419 +pep_error:
   4.420 +    if (msg_mime)
   4.421 +        mailmime_free(mime);
   4.422 +    else
   4.423 +        if (mime)
   4.424 +            mailmime_free(mime);
   4.425 +
   4.426 +    if (submime)
   4.427 +        mailmime_free(submime);
   4.428 +
   4.429 +    return status;
   4.430 +}
   4.431 +
   4.432 +DYNAMIC_API PEP_STATUS mime_decode_message(
   4.433 +        const char *mimetext,
   4.434 +        message **msg
   4.435 +    )
   4.436 +{
   4.437 +    PEP_STATUS status = PEP_STATUS_OK;
   4.438 +    struct mailmime * mime = NULL;
   4.439 +    int r;
   4.440 +
   4.441 +    assert(mimetext);
   4.442 +    assert(msg);
   4.443 +
   4.444 +    *msg = NULL;
   4.445 +    
   4.446 +    size_t index = 0;
   4.447 +    r = mailmime_parse(mimetext, strlen(mimetext), &index, &mime);
   4.448 +    assert(r == 0);
   4.449 +    assert(mime);
   4.450 +    if (r != 0) {
   4.451 +        if (r == MAILIMF_ERROR_MEMORY)
   4.452 +            goto enomem;
   4.453 +        else
   4.454 +            goto err_mime;
   4.455 +    }
   4.456 +
   4.457 +    mailmime_free(mime);
   4.458 +
   4.459 +    return status;
   4.460 +
   4.461 +err_mime:
   4.462 +    status = PEP_ILLEGAL_VALUE;
   4.463 +    goto pep_error;
   4.464 +
   4.465 +enomem:
   4.466 +    status = PEP_OUT_OF_MEMORY;
   4.467 +
   4.468 +pep_error:
   4.469 +    if (mime)
   4.470 +        mailmime_free(mime);
   4.471 +
   4.472 +    return status;
   4.473 +}
   4.474 +
     5.1 --- a/src/mime.h	Wed Mar 04 13:32:07 2015 +0100
     5.2 +++ b/src/mime.h	Sat Mar 07 20:29:13 2015 +0100
     5.3 @@ -7,13 +7,10 @@
     5.4  #endif
     5.5  
     5.6  
     5.7 -// mime_encode_text() - encode a MIME message
     5.8 +// mime_encode_message() - encode a MIME message
     5.9  //
    5.10  //  parameters:
    5.11 -//      plaintext (in)          plaintext of message as UTF-8 string
    5.12 -//      htmltext (in)           optional HTML version of message as UTF-8
    5.13 -//                              string or NULL if it does not apply
    5.14 -//      attachments (in)        attatchments or NULL if there are none
    5.15 +//      msg (in)                message to encode
    5.16  //      mimetext (out)          the resulting encoded text or NULL on any error
    5.17  //
    5.18  //  return value:
    5.19 @@ -26,25 +23,20 @@
    5.20  //      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
    5.21  //
    5.22  //  caveat:
    5.23 -//      the resulttext will go to the ownership of the caller; plaintext,
    5.24 -//      htmltext and attachments will remain in the ownership of the caller
    5.25 +//      the resulttext will go to the ownership of the caller
    5.26 +//      the message will remain in the ownership of the caller
    5.27  
    5.28 -DYNAMIC_API PEP_STATUS mime_encode_text(
    5.29 -        const char *plaintext,
    5.30 -        const char *htmltext,
    5.31 -        bloblist_t *attachments,
    5.32 +DYNAMIC_API PEP_STATUS mime_encode_message(
    5.33 +        const message * msg,
    5.34          char **mimetext
    5.35      );
    5.36  
    5.37  
    5.38 -// mime_decode_text() - decode a MIME message
    5.39 +// mime_decode_message() - decode a MIME message
    5.40  //
    5.41  //  parameters:
    5.42  //      mimetext (in)           MIME encoded text to decode
    5.43 -//      plaintext (out)         plaintext of message as UTF-8 string
    5.44 -//      htmltext (out)          optional HTML version of message as UTF-8
    5.45 -//                              string or NULL if it does not apply
    5.46 -//      attachments (out)       attatchments or NULL if there are none
    5.47 +//      msg (out)               decoded message
    5.48  //
    5.49  //  return value:
    5.50  //      PEP_STATUS_OK           if everything worked
    5.51 @@ -56,14 +48,12 @@
    5.52  //      PEP_OUT_OF_MEMORY       if not enough memory could be allocated
    5.53  //
    5.54  //  caveat:
    5.55 -//      plaintext, htmltext and attachments will go to the ownership of the
    5.56 -//      caller; mimetext will remain in the ownership of the caller
    5.57 +//      the decoded message will go to the ownership of the caller; mimetext
    5.58 +//      will remain in the ownership of the caller
    5.59  
    5.60 -DYNAMIC_API PEP_STATUS mime_decode_text(
    5.61 +DYNAMIC_API PEP_STATUS mime_decode_message(
    5.62          const char *mimetext,
    5.63 -        char **plaintext,
    5.64 -        char **htmltext,
    5.65 -        bloblist_t **attachments
    5.66 +        message **msg
    5.67      );
    5.68  
    5.69  #ifdef __cplusplus
     6.1 --- a/src/platform_windows.h	Wed Mar 04 13:32:07 2015 +0100
     6.2 +++ b/src/platform_windows.h	Sat Mar 07 20:29:13 2015 +0100
     6.3 @@ -18,7 +18,7 @@
     6.4  #define strdup(A) _strdup(A)
     6.5  #endif
     6.6  #ifndef snprintf
     6.7 -#define snprintf _snprintf
     6.8 +#define snprintf(...) _snprintf(__VA_ARGS__)
     6.9  #endif
    6.10  #ifndef strtok_r
    6.11  #define strtok_r(A, B, C) strtok_s((A), (B), (C))
     7.1 --- a/src/transport.c	Wed Mar 04 13:32:07 2015 +0100
     7.2 +++ b/src/transport.c	Sat Mar 07 20:29:13 2015 +0100
     7.3 @@ -229,13 +229,18 @@
     7.4          free(msg->longmsg);
     7.5          free(msg->longmsg_formatted);
     7.6          free_bloblist(msg->attachments);
     7.7 +        free(msg->sent);
     7.8 +        free(msg->recv);
     7.9          free_identity(msg->from);
    7.10          free_identity_list(msg->to);
    7.11          free_identity(msg->recv_by);
    7.12          free_identity_list(msg->cc);
    7.13          free_identity_list(msg->bcc);
    7.14          free_identity(msg->reply_to);
    7.15 -        free(msg->refering_id);
    7.16 +        free(msg->in_reply_to);
    7.17 +        free_stringlist(msg->references);
    7.18 +        free_stringlist(msg->keywords);
    7.19 +        free(msg->comments);
    7.20          free(msg);
    7.21      }
    7.22  }
    7.23 @@ -289,8 +294,20 @@
    7.24  
    7.25      msg->rawmsg_ref = src->rawmsg_ref;
    7.26      msg->rawmsg_size = src->rawmsg_size;
    7.27 -    msg->sent = src->sent;
    7.28 -    msg->recv = src->recv;
    7.29 +
    7.30 +    if (src->sent) {
    7.31 +        msg->sent = malloc(sizeof(timestamp));
    7.32 +        if (msg->sent == NULL)
    7.33 +            goto enomem;
    7.34 +        memcpy(msg->sent, src->sent, sizeof(timestamp));
    7.35 +    }
    7.36 +
    7.37 +    if (src->recv) {
    7.38 +        msg->recv = malloc(sizeof(timestamp));
    7.39 +        if (msg->recv == NULL)
    7.40 +            goto enomem;
    7.41 +        memcpy(msg->recv, src->recv, sizeof(timestamp));
    7.42 +    }
    7.43  
    7.44      if (src->recv_by) {
    7.45          msg->recv_by = identity_dup(src->recv_by);
    7.46 @@ -316,21 +333,40 @@
    7.47              goto enomem;
    7.48      }
    7.49  
    7.50 -    if (src->refering_id) {
    7.51 -        msg->refering_id = strdup(src->refering_id);
    7.52 -        assert(msg->refering_id);
    7.53 -        if (msg->refering_id == NULL)
    7.54 +    if (src->in_reply_to) {
    7.55 +        msg->in_reply_to = strdup(src->in_reply_to);
    7.56 +        assert(msg->in_reply_to);
    7.57 +        if (msg->in_reply_to == NULL)
    7.58              goto enomem;
    7.59      }
    7.60  
    7.61      msg->refering_msg_ref = src->refering_msg_ref;
    7.62      
    7.63 +    if (src->references) {
    7.64 +        msg->references = stringlist_dup(src->references);
    7.65 +        if (msg->references == NULL)
    7.66 +            goto enomem;
    7.67 +    }
    7.68 +
    7.69      if (src->refered_by) {
    7.70          msg->refered_by = message_ref_list_dup(src->refered_by);
    7.71          if (msg->refered_by == NULL)
    7.72              goto enomem;
    7.73      }
    7.74  
    7.75 +    if (src->keywords) {
    7.76 +        msg->keywords = stringlist_dup(src->keywords);
    7.77 +        if (msg->keywords == NULL)
    7.78 +            goto enomem;
    7.79 +    }
    7.80 +
    7.81 +    if (src->comments) {
    7.82 +        msg->comments = strdup(src->comments);
    7.83 +        assert(msg->comments);
    7.84 +        if (msg->comments == NULL)
    7.85 +            goto enomem;
    7.86 +    }
    7.87 +
    7.88      msg->enc_format = src->enc_format;
    7.89  
    7.90      return msg;
     8.1 --- a/src/transport.h	Wed Mar 04 13:32:07 2015 +0100
     8.2 +++ b/src/transport.h	Sat Mar 07 20:29:13 2015 +0100
     8.3 @@ -180,17 +180,17 @@
     8.4  
     8.5  typedef struct _message {
     8.6      PEP_msg_direction dir;
     8.7 -    char * id;                              // UTF-8 string of message ID
     8.8 -    char * shortmsg;                        // UTF-8 string of short message
     8.9 -    char * longmsg;                         // UTF-8 string of long message
    8.10 +    char *id;                               // UTF-8 string of message ID
    8.11 +    char *shortmsg;                         // UTF-8 string of short message
    8.12 +    char *longmsg;                          // UTF-8 string of long message
    8.13                                              // (plain)
    8.14 -    char * longmsg_formatted;               // UTF-8 string of long message
    8.15 +    char *longmsg_formatted;                // UTF-8 string of long message
    8.16                                              // (formatted)
    8.17 -    bloblist_t * attachments;               // blobs with attachements
    8.18 -    char * rawmsg_ref;                      // reference to raw message data
    8.19 +    bloblist_t *attachments;                // blobs with attachements
    8.20 +    char *rawmsg_ref;                       // reference to raw message data
    8.21      size_t rawmsg_size;                     // size of raw message data
    8.22 -    timestamp sent;                         // when the message is sent
    8.23 -    timestamp recv;                         // when the message is received
    8.24 +    timestamp *sent;                        // when the message is sent
    8.25 +    timestamp *recv;                        // when the message is received
    8.26      pEp_identity *from;                     // whom the message is from
    8.27      identity_list *to;                      // whom the message is to
    8.28      pEp_identity *recv_by;                  // via which identity the message
    8.29 @@ -198,10 +198,14 @@
    8.30      identity_list *cc;                      // whom a CC is being sent
    8.31      identity_list *bcc;                     // whom a BCC is being sent
    8.32      pEp_identity *reply_to;                 // where a reply should go to
    8.33 -    char * refering_id;                     // UTF-8 string of refering message ID
    8.34 +    char *in_reply_to;                      // UTF-8 string with MessageID of
    8.35 +                                            // refering message
    8.36      struct _message *refering_msg_ref;      // reference to refering message
    8.37 +    stringlist_t *references;               // list of UTF-8 strings with references
    8.38      struct _message_ref_list *refered_by;   // list of references to messages being
    8.39                                              // refered
    8.40 +    stringlist_t *keywords;                 // list of UTF-8 strings with keywords
    8.41 +    char *comments;                         // UTF-8 string with comments
    8.42      PEP_enc_format enc_format;              // format of encrypted data
    8.43  } message;
    8.44  
     9.1 --- a/src/wrappers.h	Wed Mar 04 13:32:07 2015 +0100
     9.2 +++ b/src/wrappers.h	Sat Mar 07 20:29:13 2015 +0100
     9.3 @@ -2,8 +2,8 @@
     9.4  
     9.5  #include <errno.h>
     9.6  #include <stdarg.h>
     9.7 -#include <stdio.h>
     9.8 -#include <unistd.h>
     9.9 +
    9.10 +#ifdef EOF // stdio.h
    9.11  
    9.12  static inline FILE * Fopen(const char *filename, const char *mode)
    9.13  {
    9.14 @@ -15,6 +15,19 @@
    9.15  
    9.16      return f;
    9.17  }
    9.18 +#define fopen >@<
    9.19 +
    9.20 +static inline FILE * Fdopen(int fildes, const char *mode)
    9.21 +{
    9.22 +    FILE * f;
    9.23 +
    9.24 +    do {
    9.25 +        f = fdopen(fildes, mode);
    9.26 +    } while (f == NULL && errno == EINTR);
    9.27 +
    9.28 +    return f;
    9.29 +}
    9.30 +#define fdopen >@<
    9.31  
    9.32  static inline char *Fgets(char * str, int size, FILE * stream)
    9.33  {
    9.34 @@ -26,6 +39,19 @@
    9.35  
    9.36      return s;
    9.37  }
    9.38 +#define fgets >@<
    9.39 +
    9.40 +static inline int Fputs(const char *str, FILE * stream)
    9.41 +{
    9.42 +    int r;
    9.43 +
    9.44 +    do {
    9.45 +        r = fputs(str, stream);
    9.46 +    } while (r == EOF && errno == EINTR);
    9.47 +
    9.48 +    return r;
    9.49 +}
    9.50 +#define fputs >@<
    9.51  
    9.52  static inline int Fclose(FILE *stream)
    9.53  {
    9.54 @@ -33,10 +59,11 @@
    9.55  
    9.56      do {
    9.57          r = fclose(stream);
    9.58 -    } while (r == -1 && errno == EINTR);
    9.59 +    } while (r == EOF && errno == EINTR);
    9.60  
    9.61      return r;
    9.62  }
    9.63 +#define fclose >@<
    9.64  
    9.65  static inline FILE * Freopen(
    9.66          const char *filename,
    9.67 @@ -52,6 +79,7 @@
    9.68  
    9.69      return f;
    9.70  }
    9.71 +#define freopen >@<
    9.72  
    9.73  static inline int Fprintf(FILE * stream, const char * format, ...)
    9.74  {
    9.75 @@ -68,6 +96,53 @@
    9.76  
    9.77      return n;
    9.78  }
    9.79 +#define fprintf >@<
    9.80 +
    9.81 +static inline size_t Fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream)
    9.82 +{
    9.83 +    size_t r = 0;
    9.84 +
    9.85 +    do {
    9.86 +        clearerr(stream);
    9.87 +        size_t n = fwrite((char *) ptr + r, size, nitems, stream);
    9.88 +        nitems -= n;
    9.89 +        r += n * size;
    9.90 +    } while (nitems && ferror(stream) == EINTR);
    9.91 +
    9.92 +    return r;
    9.93 +}
    9.94 +#define fwrite >@<
    9.95 +
    9.96 +static inline size_t Fread(void *ptr, size_t size, size_t nitems, FILE *stream)
    9.97 +{
    9.98 +    size_t r = 0;
    9.99 +
   9.100 +    do {
   9.101 +        clearerr(stream);
   9.102 +        size_t n = fread((char *) ptr + r, size, nitems, stream);
   9.103 +        nitems -= n;
   9.104 +        r += n * size;
   9.105 +    } while (!feof(stream) && nitems && ferror(stream) == EINTR);
   9.106 +
   9.107 +    return r;
   9.108 +}
   9.109 +#define fread >@<
   9.110 +
   9.111 +static inline int Fflush(FILE *stream)
   9.112 +{
   9.113 +    int r;
   9.114 +
   9.115 +    do {
   9.116 +        r = fflush(stream);
   9.117 +    } while (r == -1 && errno == EINTR);
   9.118 +
   9.119 +    return r;
   9.120 +}
   9.121 +#define fflush >@<
   9.122 +
   9.123 +#endif // stdio.h
   9.124 +
   9.125 +#ifdef F_OK // unistd.h
   9.126  
   9.127  static inline int Mkstemp(char *template)
   9.128  {
   9.129 @@ -79,17 +154,7 @@
   9.130  
   9.131      return fd;
   9.132  }
   9.133 -
   9.134 -static inline FILE * Fdopen(int fildes, const char *mode)
   9.135 -{
   9.136 -    FILE * f;
   9.137 -
   9.138 -    do {
   9.139 -        f = fdopen(fildes, mode);
   9.140 -    } while (f == NULL && errno == EINTR);
   9.141 -
   9.142 -    return f;
   9.143 -}
   9.144 +#define mkstemp >@<
   9.145  
   9.146  static inline int Close(int fildes)
   9.147  {
   9.148 @@ -101,29 +166,161 @@
   9.149  
   9.150      return r;
   9.151  }
   9.152 +#define close >@<
   9.153  
   9.154 -static inline size_t Fread1(void *ptr, size_t size, FILE *stream)
   9.155 +static inline ssize_t Write(int fildes, const void *buf, size_t nbyte)
   9.156  {
   9.157 -    char *_buf = ptr;
   9.158 -    size_t rest = size;
   9.159 -    size_t bytes_read;
   9.160 +    ssize_t r;
   9.161  
   9.162 -    for (bytes_read = 0; rest > 0; _buf += rest) {
   9.163 -        clearerr(stream);
   9.164 +    do {
   9.165 +        r = write(fildes, buf, nbyte);
   9.166 +    } while (r == -1 && errno == EINTR);
   9.167  
   9.168 -        bytes_read = rest * fread(_buf, rest, 1, stream);
   9.169 -        rest -= bytes_read;
   9.170 +    return r;
   9.171 +}
   9.172 +#define write >@<
   9.173  
   9.174 -        if (ferror(stream) != 0 && ferror(stream) != EINTR)
   9.175 -            goto err_file;
   9.176 +static inline ssize_t Read(int fildes, void *buf, size_t nbyte)
   9.177 +{
   9.178 +    ssize_t r;
   9.179  
   9.180 -        if (feof(stream))
   9.181 -            goto err_file;
   9.182 -    }
   9.183 +    do {
   9.184 +        r = read(fildes, buf, nbyte);
   9.185 +    } while (r == -1 && errno == EINTR);
   9.186  
   9.187 -    return size;
   9.188 +    return r;
   9.189 +}
   9.190 +#define read >@<
   9.191  
   9.192 -err_file:
   9.193 -    return size - rest;
   9.194 +static inline int Ftruncate(int fildes, off_t length)
   9.195 +{
   9.196 +    int r;
   9.197 +
   9.198 +    do {
   9.199 +        r = ftruncate(fildes, length);
   9.200 +    } while (r == -1 && errno == EINTR);
   9.201 +
   9.202 +    return r;
   9.203  }
   9.204 +#define ftruncate >@<
   9.205  
   9.206 +static inline int Dup2(int fildes, int fildes2)
   9.207 +{
   9.208 +    int fd;
   9.209 +
   9.210 +    do {
   9.211 +        fd = dup2(fildes, fildes2);
   9.212 +    } while (fd == -1 && errno == EINTR);
   9.213 +
   9.214 +    return fd;
   9.215 +}
   9.216 +#define dup2 >@<
   9.217 +
   9.218 +#endif
   9.219 +
   9.220 +#ifdef FD_CLR // select.h
   9.221 +
   9.222 +static inline int Select(
   9.223 +        int nfds,
   9.224 +        fd_set *readfds,
   9.225 +        fd_set *writefds,
   9.226 +        fd_set *errorfds,
   9.227 +        struct timeval *timeout
   9.228 +    )
   9.229 +{
   9.230 +    int r;
   9.231 +
   9.232 +    do {
   9.233 +        r = select(nfds, readfds, writefds, errorfds, timeout);
   9.234 +    } while (r == -1 && errno == EINTR);
   9.235 +
   9.236 +    return r;
   9.237 +}
   9.238 +#define select >@<
   9.239 +
   9.240 +#endif // select.h
   9.241 +
   9.242 +#ifdef F_SETLKW // fcntl.h
   9.243 +
   9.244 +static inline int Fcntl(int fildes, int cmd, void *structure)
   9.245 +{
   9.246 +    int r;
   9.247 +
   9.248 +    do {
   9.249 +        r = fcntl(fildes, cmd, structure);
   9.250 +    } while (r == -1 && errno == EINTR);
   9.251 +
   9.252 +    return r;
   9.253 +}
   9.254 +// fnctl does only risk EINTR if cmd == F_SETLKW
   9.255 +
   9.256 +static inline int Open(const char *path, int oflag, ...)
   9.257 +{
   9.258 +    int fd;
   9.259 +
   9.260 +    do {
   9.261 +        fd = open(path, oflag, 0);
   9.262 +    } while (fd == -1 && errno == EINTR);
   9.263 +
   9.264 +    return fd;
   9.265 +}
   9.266 +#define open >@<
   9.267 +
   9.268 +static inline int Creat(const char *path, mode_t mode)
   9.269 +{
   9.270 +    int fd;
   9.271 +
   9.272 +    do {
   9.273 +        fd = creat(path, mode);
   9.274 +    } while (fd == -1 && errno == EINTR);
   9.275 +
   9.276 +    return fd;
   9.277 +}
   9.278 +#define creat >@<
   9.279 +
   9.280 +#endif // fcntl.h
   9.281 +
   9.282 +#ifdef MSG_PEEK // socket.h
   9.283 +
   9.284 +static inline ssize_t Recv(int socket, void *buffer, size_t length, int flags)
   9.285 +{
   9.286 +    ssize_t r;
   9.287 +
   9.288 +    do {
   9.289 +        r = recv(socket, buffer, length, flags);
   9.290 +    } while (r == -1 && errno == EINTR);
   9.291 +
   9.292 +    return r;
   9.293 +}
   9.294 +#define recv >@<
   9.295 +
   9.296 +static inline ssize_t Send(int socket, const void *buffer, size_t length, int flags)
   9.297 +{
   9.298 +    ssize_t r;
   9.299 +
   9.300 +    do {
   9.301 +        r = send(socket, buffer, length, flags);
   9.302 +    } while (r == -1 && errno == EINTR);
   9.303 +
   9.304 +    return r;
   9.305 +}
   9.306 +#define send >@<
   9.307 +
   9.308 +#endif // socket.h
   9.309 +
   9.310 +#ifdef WNOHANG // wait.h
   9.311 +
   9.312 +static inline pid_t Waitpid(pid_t pid, int *stat_loc, int options)
   9.313 +{
   9.314 +    pid_t r;
   9.315 +
   9.316 +    do {
   9.317 +        r = waitpid(pid, stat_loc, options);
   9.318 +    } while (r == -1 && errno == EINTR);
   9.319 +
   9.320 +    return r;
   9.321 +}
   9.322 +#define waitpid >@<
   9.323 +
   9.324 +#endif
   9.325 +
    10.1 --- a/test/mime_test.cc	Wed Mar 04 13:32:07 2015 +0100
    10.2 +++ b/test/mime_test.cc	Sat Mar 07 20:29:13 2015 +0100
    10.3 @@ -1,4 +1,5 @@
    10.4  #include <iostream>
    10.5 +#include <fstream>
    10.6  #include <string>
    10.7  #include <assert.h>
    10.8  #include "mime.h"
    10.9 @@ -18,12 +19,22 @@
   10.10  
   10.11      // mime test code
   10.12  
   10.13 -    // testing plain
   10.14 +    // testing multipart/alternative
   10.15  
   10.16 -    string bla2 = "my message to yöu";
   10.17 +    message *msg2 = new_message(PEP_dir_incoming,
   10.18 +            new_identity("vb@dingens.org", NULL, NULL, NULL),
   10.19 +            new_identity_list(new_identity("trischa@dingens.org", NULL, NULL, NULL)),
   10.20 +            "my sübject");
   10.21 +    assert(msg2);
   10.22 +    string text2 = "my mèssage to yoü";
   10.23 +    msg2->longmsg = strdup(text2.c_str());
   10.24 +    string html2 = "<html><body><p>my message to you</p></body></html>";
   10.25 +    msg2->longmsg_formatted = strdup(html2.c_str());
   10.26 +    assert(msg2->longmsg_formatted);
   10.27 +
   10.28      cout << "encoding message…\n";
   10.29      char *result2;
   10.30 -    PEP_STATUS status2 = mime_encode_text(bla2.c_str(), NULL, NULL, &result2);
   10.31 +    PEP_STATUS status2 = mime_encode_message(msg2, &result2);
   10.32      assert(result2);
   10.33      assert(status2 == PEP_STATUS_OK);
   10.34  
   10.35 @@ -31,22 +42,7 @@
   10.36      cout << result2 << "\n";
   10.37  
   10.38      free(result2);
   10.39 -
   10.40 -    // testing multipart/alternative
   10.41 -
   10.42 -    string bla3 = "my message to yöu";
   10.43 -    string html3 = "<html><body><p>my message to you</p></body></html>";
   10.44 -
   10.45 -    cout << "encoding message…\n";
   10.46 -    char *result3;
   10.47 -    PEP_STATUS status3 = mime_encode_text(bla3.c_str(), html3.c_str(), NULL, &result3);
   10.48 -    assert(result3);
   10.49 -    assert(status3 == PEP_STATUS_OK);
   10.50 -
   10.51 -    cout << "result:\n";
   10.52 -    cout << result3 << "\n";
   10.53 -
   10.54 -    free(result3);
   10.55 +    free_message(msg2);
   10.56  
   10.57      cout << "calling release()\n";
   10.58      release(session);