moving libetpan dependent code to etpan_mime.c sync
authorVolker Birk <vb@pep-project.org>
Fri, 05 Apr 2019 16:56:44 +0200
branchsync
changeset 34393333c94c7827
parent 3438 e30150dc6007
child 3440 7b7f587af002
moving libetpan dependent code to etpan_mime.c
src/etpan_mime.c
src/mime.c
sync/cond_act_sync.yml2
sync/sync.fsm
     1.1 --- a/src/etpan_mime.c	Wed Apr 03 17:52:41 2019 +0200
     1.2 +++ b/src/etpan_mime.c	Fri Apr 05 16:56:44 2019 +0200
     1.3 @@ -6,7 +6,11 @@
     1.4  #include <libetpan/mailprivacy_tools.h>
     1.5  #endif
     1.6  
     1.7 +#include "pEp_internal.h"
     1.8  #include "platform.h"
     1.9 +#include "mime.h"
    1.10 +#include "wrappers.h"
    1.11 +#include "resource_id.h"
    1.12  
    1.13  #include <string.h>
    1.14  #include <stdlib.h>
    1.15 @@ -935,3 +939,1775 @@
    1.16      }    
    1.17      return false;
    1.18  }
    1.19 +
    1.20 +#define TMP_TEMPLATE "pEp.XXXXXXXXXXXXXXXXXXXX"
    1.21 +#ifdef _WIN32
    1.22 +#define PATH_SEP '\\'
    1.23 +#else
    1.24 +#define PATH_SEP '/'
    1.25 +#endif
    1.26 +
    1.27 +static PEP_STATUS interpret_MIME(struct mailmime *mime,
    1.28 +                                 message *msg);
    1.29 +
    1.30 +// This function was rewritten to use in-memory buffers instead of
    1.31 +// temporary files when the pgp/mime support was implemented for
    1.32 +// outlook, as the existing code did not work well on windows.
    1.33 +
    1.34 +static PEP_STATUS render_mime(struct mailmime *mime, char **mimetext)
    1.35 +{
    1.36 +    PEP_STATUS status = PEP_STATUS_OK;
    1.37 +    int col;
    1.38 +    int r;
    1.39 +	size_t len;
    1.40 +	char* buf = NULL;
    1.41 +
    1.42 +	MMAPString* buffer;
    1.43 +
    1.44 +	buffer = mmap_string_new(NULL);
    1.45 +	if (buffer == NULL)
    1.46 +		goto enomem;
    1.47 +	
    1.48 +	col = 0;
    1.49 +	r = mailmime_write_mem(buffer, &col, mime);
    1.50 +	assert(r == MAILIMF_NO_ERROR);
    1.51 +	if (r == MAILIMF_ERROR_MEMORY)
    1.52 +		goto enomem;
    1.53 +	else if (r != MAILIMF_NO_ERROR)
    1.54 +		goto err_file;
    1.55 +
    1.56 +	// we overallocate by 1 byte, so we have a terminating 0.
    1.57 +	len = buffer->len;
    1.58 +	buf = calloc(len + 1, 1);
    1.59 +	if (buf == NULL)
    1.60 +		goto enomem;
    1.61 +
    1.62 +	memcpy(buf, buffer->str, len);
    1.63 +	mmap_string_free(buffer);
    1.64 +
    1.65 +    *mimetext = buf;
    1.66 +    return PEP_STATUS_OK;
    1.67 +
    1.68 +err_file:
    1.69 +    status = PEP_CANNOT_CREATE_TEMP_FILE;
    1.70 +    goto pEp_error;
    1.71 +
    1.72 +enomem:
    1.73 +    status = PEP_OUT_OF_MEMORY;
    1.74 +
    1.75 +pEp_error:
    1.76 +	if (buffer)
    1.77 +		mmap_string_free(buffer);
    1.78 +	if (buf)
    1.79 +		free(buf);
    1.80 +    return status;
    1.81 +}
    1.82 +
    1.83 +static PEP_STATUS mime_attachment(
    1.84 +        bloblist_t *blob,
    1.85 +        struct mailmime **result,
    1.86 +        bool transport_encode
    1.87 +    )
    1.88 +{
    1.89 +    PEP_STATUS status = PEP_STATUS_OK;
    1.90 +    struct mailmime * mime = NULL;
    1.91 +    char * mime_type;
    1.92 +    assert(blob);
    1.93 +    assert(result);
    1.94 +
    1.95 +    *result = NULL;
    1.96 +
    1.97 +// TODO: It seems the pEp COM server adapter sends an empty string here,
    1.98 +// which leads to a crash later. Thus, we workaround here by treating an
    1.99 +// empty string as NULL. We need to check whether the bug really is here,
   1.100 +// or the pEp COM server adapter needs to be changed.
   1.101 +    if (blob->mime_type == NULL || blob->mime_type[0] == '\0')
   1.102 +        mime_type = "application/octet-stream";
   1.103 +    else
   1.104 +        mime_type = blob->mime_type;
   1.105 +
   1.106 +    pEp_rid_list_t* resource = parse_uri(blob->filename);
   1.107 +
   1.108 +    bool already_ascii = !(must_chunk_be_encoded(blob->value, blob->size, true));
   1.109 +
   1.110 +    mime = get_file_part(resource, mime_type, blob->value, blob->size, 
   1.111 +                          (already_ascii ? false : transport_encode));
   1.112 +    free_rid_list(resource);
   1.113 +    
   1.114 +    assert(mime);
   1.115 +    if (mime == NULL)
   1.116 +        goto enomem;
   1.117 +
   1.118 +    *result = mime;
   1.119 +    return PEP_STATUS_OK;
   1.120 +
   1.121 +enomem:
   1.122 +    status = PEP_OUT_OF_MEMORY;
   1.123 +
   1.124 +    if (mime)
   1.125 +        mailmime_free(mime);
   1.126 +
   1.127 +    return status;
   1.128 +}
   1.129 +
   1.130 +static PEP_STATUS mime_html_text(
   1.131 +        const char *plaintext,
   1.132 +        const char *htmltext,
   1.133 +        bloblist_t *attachments,
   1.134 +        struct mailmime **result,
   1.135 +        bool transport_encode
   1.136 +    )
   1.137 +{
   1.138 +    PEP_STATUS status = PEP_STATUS_OK;
   1.139 +    struct mailmime * top_level_html_mime = NULL;
   1.140 +    struct mailmime * mime = NULL;
   1.141 +    struct mailmime * submime = NULL;
   1.142 +    int r;
   1.143 +
   1.144 +    assert(plaintext);
   1.145 +    assert(htmltext);
   1.146 +    assert(result);
   1.147 +
   1.148 +    *result = NULL;
   1.149 +
   1.150 +    mime = part_multiple_new("multipart/alternative");
   1.151 +    assert(mime);
   1.152 +    if (mime == NULL)
   1.153 +        goto enomem;
   1.154 +
   1.155 +    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
   1.156 +    
   1.157 +    int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
   1.158 +    submime = get_text_part(NULL, "text/plain", plaintext, strlen(plaintext),
   1.159 +            encoding_type);
   1.160 +    free_rid_list(resource);
   1.161 +    resource = NULL;
   1.162 +    
   1.163 +    assert(submime);
   1.164 +    if (submime == NULL)
   1.165 +        goto enomem;
   1.166 +
   1.167 +    r = mailmime_smart_add_part(mime, submime);
   1.168 +    assert(r == MAILIMF_NO_ERROR);
   1.169 +    if (r == MAILIMF_ERROR_MEMORY) {
   1.170 +        goto enomem;
   1.171 +    }
   1.172 +    else {
   1.173 +        // mailmime_smart_add_part() takes ownership of submime
   1.174 +        submime = NULL;
   1.175 +    }
   1.176 +
   1.177 +    bool inlined_attachments = false;
   1.178 +    
   1.179 +    bloblist_t* traversal_ptr = attachments;
   1.180 +    
   1.181 +    while (traversal_ptr) {
   1.182 +        if (traversal_ptr->disposition == PEP_CONTENT_DISP_INLINE) {
   1.183 +            inlined_attachments = true;
   1.184 +            break;
   1.185 +        }
   1.186 +        traversal_ptr = traversal_ptr->next;
   1.187 +    }
   1.188 +
   1.189 +    if (inlined_attachments) {
   1.190 +        /* Noooooo... dirk, why do you do this to me? */
   1.191 +        submime = part_multiple_new("multipart/related");
   1.192 +        assert(submime);
   1.193 +        if (submime == NULL)
   1.194 +            goto enomem;
   1.195 +
   1.196 +        top_level_html_mime = submime;
   1.197 +        
   1.198 +        r = mailmime_smart_add_part(mime, top_level_html_mime);
   1.199 +        assert(r == MAILIMF_NO_ERROR);
   1.200 +        if (r == MAILIMF_ERROR_MEMORY) {
   1.201 +            goto enomem;
   1.202 +        }
   1.203 +        else {
   1.204 +            // mailmime_smart_add_part() takes ownership of submime
   1.205 +            submime = NULL;
   1.206 +        }
   1.207 +    }
   1.208 +    else {
   1.209 +        top_level_html_mime = mime;
   1.210 +    }
   1.211 +
   1.212 +//    resource = new_rid_node(PEP_RID_FILENAME, "msg.html");
   1.213 +    submime = get_text_part(NULL, "text/html", htmltext, strlen(htmltext),
   1.214 +            encoding_type);
   1.215 +    free_rid_list(resource);
   1.216 +    resource = NULL;
   1.217 +    
   1.218 +    assert(submime);
   1.219 +    if (submime == NULL)
   1.220 +        goto enomem;
   1.221 +
   1.222 +    r = mailmime_smart_add_part(top_level_html_mime, submime);
   1.223 +    assert(r == MAILIMF_NO_ERROR);
   1.224 +    if (r == MAILIMF_ERROR_MEMORY)
   1.225 +        goto enomem;
   1.226 +    else {
   1.227 +        // mailmime_smart_add_part() takes ownership of submime
   1.228 +        submime = NULL;
   1.229 +    }
   1.230 +
   1.231 +    bloblist_t *_a;
   1.232 +    for (_a = attachments; _a != NULL; _a = _a->next) {
   1.233 +        if (_a->disposition != PEP_CONTENT_DISP_INLINE)
   1.234 +            continue;
   1.235 +        status = mime_attachment(_a, &submime, transport_encode);
   1.236 +        if (status != PEP_STATUS_OK)
   1.237 +            return PEP_UNKNOWN_ERROR; // FIXME
   1.238 +
   1.239 +        r = mailmime_smart_add_part(top_level_html_mime, submime);
   1.240 +        assert(r == MAILIMF_NO_ERROR);
   1.241 +        if (r == MAILIMF_ERROR_MEMORY) {
   1.242 +            goto enomem;
   1.243 +        }
   1.244 +        else {
   1.245 +            // mailmime_smart_add_part() takes ownership of submime
   1.246 +            submime = NULL;
   1.247 +        }
   1.248 +    }
   1.249 +
   1.250 +    *result = mime;
   1.251 +    return PEP_STATUS_OK;
   1.252 +
   1.253 +enomem:
   1.254 +    status = PEP_OUT_OF_MEMORY;
   1.255 +
   1.256 +    if (mime)
   1.257 +        mailmime_free(mime);
   1.258 +
   1.259 +    if (submime)
   1.260 +        mailmime_free(submime);
   1.261 +
   1.262 +    return status;
   1.263 +}
   1.264 +
   1.265 +
   1.266 +// FIXME: maybe need to add transport_encode field here
   1.267 +static struct mailimf_mailbox * identity_to_mailbox(const pEp_identity *ident)
   1.268 +{
   1.269 +    char *_username = NULL;
   1.270 +    struct mailimf_mailbox *mb;
   1.271 +
   1.272 +    if (!ident->username)
   1.273 +        _username = strdup("");
   1.274 +    else
   1.275 +        _username = must_field_value_be_encoded(ident->username) ?
   1.276 +                    mailmime_encode_subject_header("utf-8", ident->username, 0) : 
   1.277 +                    strdup(ident->username);
   1.278 +                  
   1.279 +    assert(_username);
   1.280 +    if (_username == NULL)
   1.281 +        goto enomem;
   1.282 +
   1.283 +    mb = mailbox_from_string(_username, ident->address);
   1.284 +    if (mb == NULL)
   1.285 +        goto enomem;
   1.286 +
   1.287 +    free(_username);
   1.288 +    _username = NULL;
   1.289 +
   1.290 +    return mb;
   1.291 +
   1.292 +enomem:
   1.293 +    free(_username);
   1.294 +    return NULL;
   1.295 +}
   1.296 +
   1.297 +static struct mailimf_mailbox_list * identity_to_mbl(
   1.298 +        const pEp_identity *ident)
   1.299 +{
   1.300 +    struct mailimf_mailbox_list *mbl = NULL;
   1.301 +    struct mailimf_mailbox *mb = NULL;
   1.302 +    clist *list = NULL;
   1.303 +    int r;
   1.304 +
   1.305 +    assert(ident);
   1.306 +
   1.307 +    list = clist_new();
   1.308 +    if (list == NULL)
   1.309 +        goto enomem;
   1.310 +
   1.311 +    mb = identity_to_mailbox(ident);
   1.312 +    if (mb == NULL)
   1.313 +        goto enomem;
   1.314 +
   1.315 +    r = clist_append(list, mb);
   1.316 +    if (r)
   1.317 +        goto enomem;
   1.318 +
   1.319 +    mbl = mailimf_mailbox_list_new(list);
   1.320 +    if (mbl == NULL)
   1.321 +        goto enomem;
   1.322 +
   1.323 +    return mbl;
   1.324 +
   1.325 +enomem:
   1.326 +    if (mb)
   1.327 +        mailimf_mailbox_free(mb);
   1.328 +
   1.329 +    if (list)
   1.330 +        clist_free(list);
   1.331 +
   1.332 +    return NULL;
   1.333 +}
   1.334 +
   1.335 +static struct mailimf_address_list * identity_list_to_mal(identity_list *il)
   1.336 +{
   1.337 +    struct mailimf_address_list *mal = NULL;
   1.338 +    struct mailimf_mailbox *mb = NULL;
   1.339 +    struct mailimf_address * addr = NULL;
   1.340 +    clist *list = NULL;
   1.341 +    int r;
   1.342 +
   1.343 +    assert(il);
   1.344 +
   1.345 +    list = clist_new();
   1.346 +    if (list == NULL)
   1.347 +        goto enomem;
   1.348 +
   1.349 +    identity_list *_il;
   1.350 +    for (_il = il; _il && _il->ident; _il = _il->next) {
   1.351 +        mb = identity_to_mailbox(_il->ident);
   1.352 +        if (mb == NULL)
   1.353 +            goto enomem;
   1.354 +
   1.355 +        addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
   1.356 +        if (addr == NULL)
   1.357 +            goto enomem;
   1.358 +        mb = NULL;
   1.359 +
   1.360 +        r = clist_append(list, addr);
   1.361 +        if (r)
   1.362 +            goto enomem;
   1.363 +        addr = NULL;
   1.364 +    }
   1.365 +    mal = mailimf_address_list_new(list);
   1.366 +    if (mal == NULL)
   1.367 +        goto enomem;
   1.368 +
   1.369 +    return mal;
   1.370 +
   1.371 +enomem:
   1.372 +    if (mb)
   1.373 +        mailimf_mailbox_free(mb);
   1.374 +
   1.375 +    if (addr)
   1.376 +        mailimf_address_free(addr);
   1.377 +
   1.378 +    if (list)
   1.379 +        clist_free(list);
   1.380 +
   1.381 +    return NULL;
   1.382 +}
   1.383 +
   1.384 +static clist * stringlist_to_clist(stringlist_t *sl, bool transport_encode)
   1.385 +{
   1.386 +    clist * cl = clist_new();
   1.387 +    assert(cl);
   1.388 +    if (cl == NULL)
   1.389 +        return NULL;
   1.390 +
   1.391 +    if (!sl || ((!sl->value || sl->value[0] == '\0') && sl->next == NULL))
   1.392 +        return cl;
   1.393 +        
   1.394 +    stringlist_t *_sl;
   1.395 +    for (_sl = sl; _sl; _sl = _sl->next) {
   1.396 +        int r;
   1.397 +        char * value = ((transport_encode && must_field_value_be_encoded(_sl->value)) ?
   1.398 +                        mailmime_encode_subject_header("utf-8", _sl->value, 0) :
   1.399 +                        strdup(_sl->value));
   1.400 +        assert(value);
   1.401 +        if (value == NULL) {
   1.402 +            clist_free(cl);
   1.403 +            return NULL;
   1.404 +        }
   1.405 +        r = clist_append(cl, value);
   1.406 +        assert(r == 0);
   1.407 +        if (r) {
   1.408 +            free(value);
   1.409 +            clist_free(cl);
   1.410 +            return NULL;
   1.411 +        }
   1.412 +    }
   1.413 +
   1.414 +    return cl;
   1.415 +}
   1.416 +
   1.417 +static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result)
   1.418 +{
   1.419 +    PEP_STATUS status = PEP_STATUS_OK;
   1.420 +    struct mailimf_fields * fields = NULL;
   1.421 +    int r;
   1.422 +    clist * fields_list = NULL;
   1.423 +    unsigned char pEpstr[] = PEP_SUBJ_STRING; // unsigned due to UTF-8 byte fun
   1.424 +#ifdef WIN32
   1.425 +    char* altstr = "pEp";
   1.426 +#else
   1.427 +    char* altstr = (char*)pEpstr;
   1.428 +#endif        
   1.429 +    char *subject = msg->shortmsg ? msg->shortmsg : altstr;
   1.430 +
   1.431 +    assert(msg);
   1.432 +    assert(result);
   1.433 +
   1.434 +    *result = NULL;
   1.435 +
   1.436 +    fields_list = clist_new();
   1.437 +    assert(fields_list);
   1.438 +    if (fields_list == NULL)
   1.439 +        goto enomem;
   1.440 +
   1.441 +    if (msg->id) {
   1.442 +        char *_msgid = strdup(msg->id);
   1.443 +        assert(_msgid);
   1.444 +        if (_msgid == NULL)
   1.445 +            goto enomem;
   1.446 +
   1.447 +        r = _append_field(fields_list, MAILIMF_FIELD_MESSAGE_ID,
   1.448 +                (_new_func_t) mailimf_message_id_new, _msgid);
   1.449 +        if (r) {
   1.450 +            free(_msgid);
   1.451 +            goto enomem;
   1.452 +        }
   1.453 +    }
   1.454 +
   1.455 +    if (msg->sent) {
   1.456 +        struct mailimf_date_time * dt = timestamp_to_etpantime(msg->sent);
   1.457 +        if (dt == NULL)
   1.458 +            goto enomem;
   1.459 +
   1.460 +        r = _append_field(fields_list, MAILIMF_FIELD_ORIG_DATE,
   1.461 +                (_new_func_t) mailimf_orig_date_new, dt);
   1.462 +        if (r) {
   1.463 +            mailimf_date_time_free(dt);
   1.464 +            goto enomem;
   1.465 +        }
   1.466 +        dt = NULL;
   1.467 +    }
   1.468 +
   1.469 +     if (msg->from) {
   1.470 +        struct mailimf_mailbox_list *from = identity_to_mbl(msg->from);
   1.471 +        if (from == NULL)
   1.472 +            goto enomem;
   1.473 +
   1.474 +        r = _append_field(fields_list, MAILIMF_FIELD_FROM,
   1.475 +                (_new_func_t) mailimf_from_new, from);
   1.476 +        if (r) {
   1.477 +            mailimf_mailbox_list_free(from);
   1.478 +            goto enomem;
   1.479 +        }
   1.480 +    }
   1.481 +
   1.482 +    if (msg->to) {
   1.483 +        struct mailimf_address_list *to = identity_list_to_mal(msg->to);
   1.484 +        if (to == NULL)
   1.485 +            goto enomem;
   1.486 +
   1.487 +        r = _append_field(fields_list, MAILIMF_FIELD_TO,
   1.488 +                (_new_func_t) mailimf_to_new, to);
   1.489 +        if (r) {
   1.490 +            mailimf_address_list_free(to);
   1.491 +            goto enomem;
   1.492 +        }
   1.493 +    }
   1.494 +
   1.495 +    char* _subject = NULL;
   1.496 +    if (!must_field_value_be_encoded(subject)) {
   1.497 +        _subject = strdup(subject);
   1.498 +        assert(_subject);
   1.499 +    }
   1.500 +    else {
   1.501 +        _subject = mailmime_encode_subject_header("utf-8", subject, 1);
   1.502 +    }
   1.503 +    if (_subject == NULL)
   1.504 +        goto enomem;
   1.505 +
   1.506 +    r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
   1.507 +            (_new_func_t) mailimf_subject_new, _subject);
   1.508 +    if (r) {
   1.509 +        free(_subject);
   1.510 +        goto enomem;
   1.511 +    }
   1.512 +
   1.513 +    if (msg->cc) {
   1.514 +        struct mailimf_address_list *cc = identity_list_to_mal(msg->cc);
   1.515 +        if (cc == NULL)
   1.516 +            goto enomem;
   1.517 +
   1.518 +        r = _append_field(fields_list, MAILIMF_FIELD_CC,
   1.519 +                (_new_func_t) mailimf_cc_new, cc);
   1.520 +        if (r) {
   1.521 +            mailimf_address_list_free(cc);
   1.522 +            goto enomem;
   1.523 +        }
   1.524 +    }
   1.525 +    
   1.526 +    if (msg->bcc) {
   1.527 +        struct mailimf_address_list *bcc = identity_list_to_mal(msg->bcc);
   1.528 +        if (bcc == NULL)
   1.529 +            goto enomem;
   1.530 +
   1.531 +        r = _append_field(fields_list, MAILIMF_FIELD_BCC,
   1.532 +                (_new_func_t) mailimf_bcc_new, bcc);
   1.533 +        if (r) {
   1.534 +            mailimf_address_list_free(bcc);
   1.535 +            goto enomem;
   1.536 +        }
   1.537 +    }
   1.538 +    
   1.539 +    if (msg->reply_to) {
   1.540 +        struct mailimf_address_list *reply_to = identity_list_to_mal(msg->reply_to);
   1.541 +        if (reply_to == NULL)
   1.542 +            goto enomem;
   1.543 +
   1.544 +        r = _append_field(fields_list, MAILIMF_FIELD_REPLY_TO,
   1.545 +                (_new_func_t) mailimf_reply_to_new, reply_to);
   1.546 +        if (r) {
   1.547 +            mailimf_address_list_free(reply_to);
   1.548 +            goto enomem;
   1.549 +        }
   1.550 +    }
   1.551 +
   1.552 +    if (msg->in_reply_to) {
   1.553 +        clist *in_reply_to = stringlist_to_clist(msg->in_reply_to, true);
   1.554 +        if (in_reply_to == NULL)
   1.555 +            goto enomem;
   1.556 +
   1.557 +        r = _append_field(fields_list, MAILIMF_FIELD_IN_REPLY_TO,
   1.558 +                (_new_func_t) mailimf_in_reply_to_new, in_reply_to);
   1.559 +        if (r) {
   1.560 +            clist_free(in_reply_to);
   1.561 +            goto enomem;
   1.562 +        }
   1.563 +    }
   1.564 +
   1.565 +    if (msg->references) {
   1.566 +        clist *references = stringlist_to_clist(msg->references, true);
   1.567 +        if (references == NULL)
   1.568 +            goto enomem;
   1.569 +
   1.570 +        r = _append_field(fields_list, MAILIMF_FIELD_REFERENCES,
   1.571 +                (_new_func_t) mailimf_references_new, references);
   1.572 +        if (r) {
   1.573 +            clist_free(references);
   1.574 +            goto enomem;
   1.575 +        }
   1.576 +    }
   1.577 +
   1.578 +    if (msg->keywords) {
   1.579 +        clist *keywords = stringlist_to_clist(msg->keywords, true);
   1.580 +        if (keywords == NULL)
   1.581 +            goto enomem;
   1.582 +
   1.583 +        r = _append_field(fields_list, MAILIMF_FIELD_KEYWORDS,
   1.584 +                (_new_func_t) mailimf_keywords_new, keywords);
   1.585 +        if (r) {
   1.586 +            clist_free(keywords);
   1.587 +            goto enomem;
   1.588 +        }
   1.589 +    }
   1.590 +
   1.591 +    if (msg->comments) {
   1.592 +        char *comments = NULL;
   1.593 +        if (!must_field_value_be_encoded(msg->comments)) {
   1.594 +            comments = strdup(msg->comments);
   1.595 +            assert(comments);
   1.596 +        }
   1.597 +        else  {
   1.598 +            comments = mailmime_encode_subject_header("utf-8", msg->comments, 0);
   1.599 +        }
   1.600 +        if (comments == NULL)
   1.601 +            goto enomem;
   1.602 +
   1.603 +        r = _append_field(fields_list, MAILIMF_FIELD_COMMENTS,
   1.604 +                (_new_func_t) mailimf_comments_new, comments);
   1.605 +        if (r) {
   1.606 +            free(comments);
   1.607 +            goto enomem;
   1.608 +        }
   1.609 +    }
   1.610 +
   1.611 +    if (msg->opt_fields) {
   1.612 +        stringpair_list_t *_l;
   1.613 +        for (_l = msg->opt_fields; _l && _l->value; _l = _l->next) {
   1.614 +            char *key = _l->value->key;
   1.615 +            char *value = _l->value->value;
   1.616 +            if (key && value) {
   1.617 +                r = _append_optional_field(fields_list, key, value);
   1.618 +
   1.619 +                if (r)
   1.620 +                    goto enomem;
   1.621 +            }
   1.622 +        }
   1.623 +    }
   1.624 +
   1.625 +    fields = mailimf_fields_new(fields_list);
   1.626 +    assert(fields);
   1.627 +    if (fields == NULL)
   1.628 +        goto enomem;
   1.629 +
   1.630 +    *result = fields;
   1.631 +
   1.632 +    return PEP_STATUS_OK;
   1.633 +
   1.634 +enomem:
   1.635 +    status = PEP_OUT_OF_MEMORY;
   1.636 +
   1.637 +    if (fields_list)
   1.638 +        clist_free(fields_list);
   1.639 +
   1.640 +    if (fields)
   1.641 +        mailimf_fields_free(fields);
   1.642 +
   1.643 +    return status;
   1.644 +}
   1.645 +
   1.646 +static bool has_exceptional_extension(char* filename) {
   1.647 +    if (!filename)
   1.648 +        return false;
   1.649 +    int len = strlen(filename);
   1.650 +    if (len < 4)
   1.651 +        return false;
   1.652 +    char* ext_start = filename + (len - 4);
   1.653 +    if (strcmp(ext_start, ".pgp") == 0 || strcmp(ext_start, ".gpg") == 0 ||
   1.654 +        strcmp(ext_start, ".asc") == 0 || strcmp(ext_start, ".pEp") == 0)
   1.655 +        return true;
   1.656 +    return false;
   1.657 +}
   1.658 +
   1.659 +static pEp_rid_list_t* choose_resource_id(pEp_rid_list_t* rid_list) {
   1.660 +    pEp_rid_list_t* retval = rid_list;
   1.661 +    
   1.662 +    /* multiple elements - least common case */
   1.663 +    if (rid_list && rid_list->next) {
   1.664 +        pEp_rid_list_t* rid_list_curr = rid_list;
   1.665 +        retval = rid_list; 
   1.666 +        
   1.667 +        while (rid_list_curr) {
   1.668 +            pEp_resource_id_type rid_type = rid_list_curr->rid_type;
   1.669 +            if (rid_type == PEP_RID_CID)
   1.670 +                retval = rid_list_curr;
   1.671 +            else if (rid_type == PEP_RID_FILENAME && has_exceptional_extension(rid_list_curr->rid))
   1.672 +                return rid_list_curr;
   1.673 +            rid_list_curr = rid_list_curr->next;
   1.674 +        }
   1.675 +    } 
   1.676 +    return retval;
   1.677 +}
   1.678 +
   1.679 +// static void split_inlined_and_attached(bloblist_t** inlined, bloblist_t** attached) {
   1.680 +//     bloblist_t** curr_pp = attached;
   1.681 +//     bloblist_t* curr = *curr_pp;
   1.682 +//     
   1.683 +//     bloblist_t* inline_ret = NULL;
   1.684 +//     bloblist_t** inline_curr_pp = &inline_ret;
   1.685 +//     
   1.686 +//     bloblist_t* att_ret = NULL;
   1.687 +//     bloblist_t** att_curr_pp = &att_ret;
   1.688 +//     
   1.689 +//     while (curr) {
   1.690 +//         if (curr->disposition == PEP_CONTENT_DISP_INLINE) {
   1.691 +//             *inline_curr_pp = curr;
   1.692 +//             inline_curr_pp = &(curr->next);
   1.693 +//         }
   1.694 +//         else {
   1.695 +//             *att_curr_pp = curr;
   1.696 +//             att_curr_pp = &(curr->next);            
   1.697 +//         }
   1.698 +//         *curr_pp = curr->next;
   1.699 +//         curr->next = NULL;
   1.700 +//         curr = *curr_pp;
   1.701 +//     }
   1.702 +//     
   1.703 +//     *inlined = inline_ret;
   1.704 +//     *attached = att_ret;
   1.705 +// }
   1.706 +
   1.707 +
   1.708 +static PEP_STATUS mime_encode_message_plain(
   1.709 +        const message *msg,
   1.710 +        bool omit_fields,
   1.711 +        struct mailmime **result,
   1.712 +        bool transport_encode
   1.713 +    )
   1.714 +{
   1.715 +    struct mailmime * mime = NULL;
   1.716 +    struct mailmime * submime = NULL;
   1.717 +    int r;
   1.718 +    PEP_STATUS status;
   1.719 +    //char *subject;
   1.720 +    char *plaintext;
   1.721 +    char *htmltext;
   1.722 +
   1.723 +    assert(msg);
   1.724 +    assert(result);
   1.725 +    
   1.726 +    //subject = (msg->shortmsg) ? msg->shortmsg : "pEp";  // not used, yet.
   1.727 +    plaintext = (msg->longmsg) ? msg->longmsg : "";
   1.728 +    htmltext = msg->longmsg_formatted;
   1.729 +
   1.730 +    if (htmltext && (htmltext[0] != '\0')) {
   1.731 +        /* first, we need to strip out the inlined attachments to ensure this
   1.732 +           gets set up correctly */
   1.733 +           
   1.734 +        status = mime_html_text(plaintext, htmltext, msg->attachments, &mime,
   1.735 +                                transport_encode);
   1.736 +                
   1.737 +        if (status != PEP_STATUS_OK)
   1.738 +            goto pEp_error;
   1.739 +    }
   1.740 +    else {
   1.741 +        pEp_rid_list_t* resource = NULL;
   1.742 +        if (is_PGP_message_text(plaintext)) {
   1.743 +            resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
   1.744 +            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_7BIT : 0);
   1.745 +            mime = get_text_part(resource, "application/octet-stream", plaintext,
   1.746 +                    strlen(plaintext), encoding_type);
   1.747 +        }
   1.748 +        else {
   1.749 +            resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
   1.750 +            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
   1.751 +            mime = get_text_part(resource, "text/plain", plaintext, strlen(plaintext),
   1.752 +                    encoding_type);
   1.753 +        }
   1.754 +        free_rid_list(resource);
   1.755 +        
   1.756 +        assert(mime);
   1.757 +        if (mime == NULL)
   1.758 +            goto enomem;
   1.759 +    }
   1.760 +
   1.761 +    bool normal_attachments = false;
   1.762 +    
   1.763 +    bloblist_t* traversal_ptr = msg->attachments;
   1.764 +    
   1.765 +    while (traversal_ptr) {
   1.766 +        if (traversal_ptr->disposition != PEP_CONTENT_DISP_INLINE) {
   1.767 +            normal_attachments = true;
   1.768 +            break;
   1.769 +        }
   1.770 +        traversal_ptr = traversal_ptr->next;
   1.771 +    }
   1.772 +
   1.773 +    if (normal_attachments) {
   1.774 +        submime = mime;
   1.775 +        mime = part_multiple_new("multipart/mixed");
   1.776 +        assert(mime);
   1.777 +        if (mime == NULL)
   1.778 +            goto enomem;
   1.779 +
   1.780 +        r = mailmime_smart_add_part(mime, submime);
   1.781 +        assert(r == MAILIMF_NO_ERROR);
   1.782 +        if (r == MAILIMF_ERROR_MEMORY) {
   1.783 +            goto enomem;
   1.784 +        }
   1.785 +        else {
   1.786 +            // mailmime_smart_add_part() takes ownership of submime
   1.787 +            submime = NULL;
   1.788 +        }
   1.789 +
   1.790 +        bloblist_t *_a;
   1.791 +        for (_a = msg->attachments; _a != NULL; _a = _a->next) {
   1.792 +
   1.793 +            if (_a->disposition == PEP_CONTENT_DISP_INLINE)
   1.794 +                continue;
   1.795 +
   1.796 +            status = mime_attachment(_a, &submime, transport_encode);
   1.797 +            if (status != PEP_STATUS_OK)
   1.798 +                goto pEp_error;
   1.799 +
   1.800 +            r = mailmime_smart_add_part(mime, submime);
   1.801 +            assert(r == MAILIMF_NO_ERROR);
   1.802 +            if (r == MAILIMF_ERROR_MEMORY) {
   1.803 +                goto enomem;
   1.804 +            }
   1.805 +            else {
   1.806 +                // mailmime_smart_add_part() takes ownership of submime
   1.807 +                submime = NULL;
   1.808 +            }
   1.809 +        }
   1.810 +    }
   1.811 +
   1.812 +    *result = mime;
   1.813 +    return PEP_STATUS_OK;
   1.814 +
   1.815 +enomem:
   1.816 +    status = PEP_OUT_OF_MEMORY;
   1.817 +
   1.818 +pEp_error:
   1.819 +    if (mime)
   1.820 +        mailmime_free(mime);
   1.821 +
   1.822 +    if (submime)
   1.823 +        mailmime_free(submime);
   1.824 +
   1.825 +    return status;
   1.826 +}
   1.827 +
   1.828 +static PEP_STATUS mime_encode_message_PGP_MIME(
   1.829 +        const message * msg,
   1.830 +        bool omit_fields,
   1.831 +        struct mailmime **result
   1.832 +    )
   1.833 +{
   1.834 +    struct mailmime * mime = NULL;
   1.835 +    struct mailmime * submime = NULL;
   1.836 +	struct mailmime_parameter * param;
   1.837 +    int r;
   1.838 +    PEP_STATUS status;
   1.839 +    char *plaintext;
   1.840 +    size_t plaintext_size;
   1.841 +
   1.842 +    assert(msg->attachments && msg->attachments->next &&
   1.843 +            msg->attachments->next->value);
   1.844 +
   1.845 +    plaintext = msg->attachments->next->value;
   1.846 +    plaintext_size = msg->attachments->next->size;
   1.847 +
   1.848 +    mime = part_multiple_new("multipart/encrypted");
   1.849 +    assert(mime);
   1.850 +    if (mime == NULL)
   1.851 +        goto enomem;
   1.852 +
   1.853 +    param = mailmime_param_new_with_data("protocol", "application/pgp-encrypted");
   1.854 +    clist_append(mime->mm_content_type->ct_parameters, param);
   1.855 +
   1.856 +    submime = get_pgp_encrypted_part();
   1.857 +    assert(submime);
   1.858 +    if (submime == NULL)
   1.859 +        goto enomem;
   1.860 +
   1.861 +    r = mailmime_smart_add_part(mime, submime);
   1.862 +    assert(r == MAILIMF_NO_ERROR);
   1.863 +    if (r == MAILIMF_ERROR_MEMORY) {
   1.864 +        goto enomem;
   1.865 +    }
   1.866 +    else {
   1.867 +        // mailmime_smart_add_part() takes ownership of submime
   1.868 +        submime = NULL;
   1.869 +    }
   1.870 +
   1.871 +    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
   1.872 +    submime = get_text_part(resource, "application/octet-stream", plaintext,
   1.873 +            plaintext_size, MAILMIME_MECHANISM_7BIT);
   1.874 +            
   1.875 +    free_rid_list(resource);
   1.876 +    
   1.877 +    assert(submime);
   1.878 +    if (submime == NULL)
   1.879 +        goto enomem;
   1.880 +
   1.881 +    r = mailmime_smart_add_part(mime, submime);
   1.882 +    assert(r == MAILIMF_NO_ERROR);
   1.883 +    if (r == MAILIMF_ERROR_MEMORY) {
   1.884 +        goto enomem;
   1.885 +    }
   1.886 +    else {
   1.887 +        // mailmime_smart_add_part() takes ownership of submime
   1.888 +        submime = NULL;
   1.889 +    }
   1.890 +
   1.891 +    *result = mime;
   1.892 +    return PEP_STATUS_OK;
   1.893 +
   1.894 +enomem:
   1.895 +    status = PEP_OUT_OF_MEMORY;
   1.896 +
   1.897 +    if (mime)
   1.898 +        mailmime_free(mime);
   1.899 +
   1.900 +    if (submime)
   1.901 +        mailmime_free(submime);
   1.902 +
   1.903 +    return status;
   1.904 +}
   1.905 +
   1.906 +DYNAMIC_API PEP_STATUS mime_encode_message(
   1.907 +        const message * msg,
   1.908 +        bool omit_fields,
   1.909 +        char **mimetext
   1.910 +    )
   1.911 +{
   1.912 +    return _mime_encode_message_internal(msg, omit_fields, mimetext, true);
   1.913 +}
   1.914 +
   1.915 +PEP_STATUS _mime_encode_message_internal(
   1.916 +        const message * msg,
   1.917 +        bool omit_fields,
   1.918 +        char **mimetext,
   1.919 +        bool transport_encode
   1.920 +    )
   1.921 +{
   1.922 +    PEP_STATUS status = PEP_STATUS_OK;
   1.923 +    struct mailmime * msg_mime = NULL;
   1.924 +    struct mailmime * mime = NULL;
   1.925 +    struct mailimf_fields * fields = NULL;
   1.926 +    char *buf = NULL;
   1.927 +    int r;
   1.928 +
   1.929 +    assert(msg);
   1.930 +    assert(mimetext);
   1.931 +
   1.932 +    if (!(msg && mimetext))
   1.933 +        return PEP_ILLEGAL_VALUE;
   1.934 +
   1.935 +    *mimetext = NULL;
   1.936 +
   1.937 +    switch (msg->enc_format) {
   1.938 +        case PEP_enc_none:
   1.939 +            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
   1.940 +            break;
   1.941 +
   1.942 +        case PEP_enc_pieces:
   1.943 +            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
   1.944 +            break;
   1.945 +
   1.946 +        case PEP_enc_S_MIME:
   1.947 +            NOT_IMPLEMENTED
   1.948 +                
   1.949 +        case PEP_enc_PGP_MIME:
   1.950 +            status = mime_encode_message_PGP_MIME(msg, omit_fields, &mime);
   1.951 +            break;
   1.952 +
   1.953 +        case PEP_enc_PEP:
   1.954 +            NOT_IMPLEMENTED
   1.955 +
   1.956 +        default:
   1.957 +            NOT_IMPLEMENTED
   1.958 +    }
   1.959 +
   1.960 +    if (status != PEP_STATUS_OK)
   1.961 +        goto pEp_error;
   1.962 +
   1.963 +    msg_mime = mailmime_new_message_data(NULL);
   1.964 +    assert(msg_mime);
   1.965 +    if (msg_mime == NULL)
   1.966 +        goto enomem;
   1.967 +
   1.968 +    r = mailmime_add_part(msg_mime, mime);
   1.969 +    if (r) {
   1.970 +        mailmime_free(mime);
   1.971 +        goto enomem;
   1.972 +    }
   1.973 +    mime = NULL;
   1.974 +
   1.975 +    if (!omit_fields) {
   1.976 +        status = build_fields(msg, &fields);
   1.977 +        if (status != PEP_STATUS_OK)
   1.978 +            goto pEp_error;
   1.979 +
   1.980 +        mailmime_set_imf_fields(msg_mime, fields);
   1.981 +    }
   1.982 +
   1.983 +    status = render_mime(msg_mime, &buf);
   1.984 +    if (status != PEP_STATUS_OK)
   1.985 +        goto pEp_error;
   1.986 +
   1.987 +    mailmime_free(msg_mime);
   1.988 +    *mimetext = buf;
   1.989 +
   1.990 +    return PEP_STATUS_OK;
   1.991 +
   1.992 +enomem:
   1.993 +    status = PEP_OUT_OF_MEMORY;
   1.994 +
   1.995 +pEp_error:
   1.996 +    if (msg_mime)
   1.997 +        mailmime_free(msg_mime);
   1.998 +    else
   1.999 +        if (mime)
  1.1000 +            mailmime_free(mime);
  1.1001 +
  1.1002 +    return status;
  1.1003 +}
  1.1004 +
  1.1005 +static pEp_identity *mailbox_to_identity(const struct mailimf_mailbox * mb)
  1.1006 +{
  1.1007 +    char *username = NULL;
  1.1008 +
  1.1009 +    assert(mb);
  1.1010 +    assert(mb->mb_addr_spec);
  1.1011 +
  1.1012 +    if (mb->mb_addr_spec == NULL)
  1.1013 +        return NULL;
  1.1014 +
  1.1015 +    if (mb->mb_display_name) {
  1.1016 +        size_t index = 0;
  1.1017 +        const int r = mailmime_encoded_phrase_parse("utf-8", mb->mb_display_name,
  1.1018 +                strlen(mb->mb_display_name), &index, "utf-8", &username);
  1.1019 +        if (r)
  1.1020 +            goto enomem;
  1.1021 +    }
  1.1022 +
  1.1023 +    pEp_identity *ident = new_identity(mb->mb_addr_spec, NULL, NULL, username);
  1.1024 +    if (ident == NULL)
  1.1025 +        goto enomem;
  1.1026 +    free(username);
  1.1027 +
  1.1028 +    return ident;
  1.1029 +
  1.1030 +enomem:
  1.1031 +    free(username);
  1.1032 +    return NULL;
  1.1033 +}
  1.1034 +
  1.1035 +static pEp_identity * mbl_to_identity(const struct mailimf_mailbox_list * mbl)
  1.1036 +{
  1.1037 +    struct mailimf_mailbox * mb = clist_content(clist_begin(mbl->mb_list));
  1.1038 +    return mailbox_to_identity(mb);
  1.1039 +}
  1.1040 +
  1.1041 +static identity_list * mal_to_identity_list(
  1.1042 +        const struct mailimf_address_list *mal
  1.1043 +    )
  1.1044 +{
  1.1045 +    assert(mal);
  1.1046 +    clist *list = mal->ad_list;
  1.1047 +
  1.1048 +    identity_list *il = new_identity_list(NULL);
  1.1049 +    if (il == NULL)
  1.1050 +        goto enomem;
  1.1051 +
  1.1052 +    identity_list *_il = il;
  1.1053 +    for (clistiter *cur = clist_begin(list); cur != NULL ; cur = clist_next(cur)) {
  1.1054 +        pEp_identity *ident;
  1.1055 +
  1.1056 +        struct mailimf_address *addr = clist_content(cur);
  1.1057 +        switch(addr->ad_type) {
  1.1058 +            case MAILIMF_ADDRESS_MAILBOX:
  1.1059 +                ident = mailbox_to_identity(addr->ad_data.ad_mailbox);
  1.1060 +                if (ident == NULL)
  1.1061 +                    goto enomem;
  1.1062 +                _il = identity_list_add(_il, ident);
  1.1063 +                if (_il == NULL)
  1.1064 +                    goto enomem;
  1.1065 +                break;
  1.1066 +
  1.1067 +            case MAILIMF_ADDRESS_GROUP:
  1.1068 +                {
  1.1069 +                    struct mailimf_mailbox_list * mbl =
  1.1070 +                            addr->ad_data.ad_group->grp_mb_list;
  1.1071 +                    for (clistiter *cur2 = clist_begin(mbl->mb_list); cur2 != NULL;
  1.1072 +                            cur2 = clist_next(cur2)) {
  1.1073 +                        ident = mailbox_to_identity(clist_content(cur));
  1.1074 +                        if (ident == NULL)
  1.1075 +                            goto enomem;
  1.1076 +                        _il = identity_list_add(_il, ident);
  1.1077 +                        if (_il == NULL)
  1.1078 +                            goto enomem;
  1.1079 +                    }
  1.1080 +                }
  1.1081 +                break;
  1.1082 +
  1.1083 +            default:
  1.1084 +                assert(0);
  1.1085 +                goto enomem;
  1.1086 +        }
  1.1087 +    }
  1.1088 +
  1.1089 +    return il;
  1.1090 +
  1.1091 +enomem:
  1.1092 +    free_identity_list(il);
  1.1093 +    return NULL;
  1.1094 +}
  1.1095 +
  1.1096 +static stringlist_t * clist_to_stringlist(const clist *list)
  1.1097 +{
  1.1098 +    char *text = NULL;;
  1.1099 +    stringlist_t * sl = new_stringlist(NULL);
  1.1100 +    if (sl == NULL)
  1.1101 +        return NULL;
  1.1102 +
  1.1103 +    stringlist_t *_sl = sl;
  1.1104 +    for (clistiter *cur = clist_begin(list); cur != NULL; cur = clist_next(cur)) {
  1.1105 +        char *phrase = clist_content(cur);
  1.1106 +        size_t index = 0;
  1.1107 +        
  1.1108 +        const int r = mailmime_encoded_phrase_parse("utf-8", phrase, strlen(phrase),
  1.1109 +                &index, "utf-8", &text);
  1.1110 +        if (r)
  1.1111 +            goto enomem;
  1.1112 +
  1.1113 +        _sl = stringlist_add(_sl, text);
  1.1114 +        if (_sl == NULL)
  1.1115 +            goto enomem;
  1.1116 +
  1.1117 +        free(text);
  1.1118 +        text = NULL;
  1.1119 +    }
  1.1120 +
  1.1121 +    return sl;
  1.1122 +
  1.1123 +enomem:
  1.1124 +    free_stringlist(sl);
  1.1125 +    free(text);
  1.1126 +
  1.1127 +    return NULL;
  1.1128 +}
  1.1129 +
  1.1130 +static PEP_STATUS read_fields(message *msg, clist *fieldlist)
  1.1131 +{
  1.1132 +    PEP_STATUS status = PEP_STATUS_OK;
  1.1133 +    struct mailimf_field * _field;
  1.1134 +    clistiter *cur;
  1.1135 +    size_t index;
  1.1136 +    int r;
  1.1137 +    
  1.1138 +    stringpair_list_t *opt = msg->opt_fields;
  1.1139 +
  1.1140 +    if (!fieldlist)
  1.1141 +        return PEP_STATUS_OK;
  1.1142 +        
  1.1143 +    for (cur = clist_begin(fieldlist); cur != NULL; cur = clist_next(cur)) {
  1.1144 +        _field = clist_content(cur);
  1.1145 +
  1.1146 +        switch (_field->fld_type) {
  1.1147 +            case MAILIMF_FIELD_MESSAGE_ID:
  1.1148 +                {
  1.1149 +                    char * text = _field->fld_data.fld_message_id->mid_value;
  1.1150 +
  1.1151 +                    free(msg->id);
  1.1152 +                    index = 0;
  1.1153 +                    r = mailmime_encoded_phrase_parse("utf-8", text,
  1.1154 +                            strlen(text), &index, "utf-8", &msg->id);
  1.1155 +                    if (r)
  1.1156 +                        goto enomem;
  1.1157 +                }
  1.1158 +                break;
  1.1159 +
  1.1160 +            case MAILIMF_FIELD_SUBJECT:
  1.1161 +                {
  1.1162 +                    char * text = _field->fld_data.fld_subject->sbj_value;
  1.1163 +
  1.1164 +                    free(msg->shortmsg);
  1.1165 +                    index = 0;
  1.1166 +                    r = mailmime_encoded_phrase_parse("utf-8", text,
  1.1167 +                            strlen(text), &index, "utf-8", &msg->shortmsg);
  1.1168 +                    if (r)
  1.1169 +                        goto enomem;
  1.1170 +                }
  1.1171 +                break;
  1.1172 +
  1.1173 +            case MAILIMF_FIELD_ORIG_DATE:
  1.1174 +                {
  1.1175 +                    struct mailimf_date_time *date =
  1.1176 +                        _field->fld_data.fld_orig_date->dt_date_time;
  1.1177 +
  1.1178 +                    free_timestamp(msg->sent);
  1.1179 +                    msg->sent = etpantime_to_timestamp(date);
  1.1180 +                    if (msg->sent == NULL)
  1.1181 +                        goto enomem;
  1.1182 +                }
  1.1183 +                break;
  1.1184 +
  1.1185 +            case MAILIMF_FIELD_FROM:
  1.1186 +                {
  1.1187 +                    struct mailimf_mailbox_list *mbl =
  1.1188 +                            _field->fld_data.fld_from->frm_mb_list;
  1.1189 +                    pEp_identity *ident;
  1.1190 +
  1.1191 +                    ident = mbl_to_identity(mbl);
  1.1192 +                    if (ident == NULL)
  1.1193 +                        goto pEp_error;
  1.1194 +
  1.1195 +                    free_identity(msg->from);
  1.1196 +                    msg->from = ident;
  1.1197 +                }
  1.1198 +                break;
  1.1199 +
  1.1200 +            case MAILIMF_FIELD_TO:
  1.1201 +                {
  1.1202 +                    struct mailimf_address_list *mal =
  1.1203 +                            _field->fld_data.fld_to->to_addr_list;
  1.1204 +                    identity_list *il = mal_to_identity_list(mal);
  1.1205 +                    if (il == NULL)
  1.1206 +                        goto enomem;
  1.1207 +
  1.1208 +                    free_identity_list(msg->to);
  1.1209 +                    msg->to = il;
  1.1210 +                }
  1.1211 +                break;
  1.1212 +
  1.1213 +            case MAILIMF_FIELD_CC:
  1.1214 +                {
  1.1215 +                    struct mailimf_address_list *mal =
  1.1216 +                            _field->fld_data.fld_cc->cc_addr_list;
  1.1217 +                    identity_list *il = mal_to_identity_list(mal);
  1.1218 +                    if (il == NULL)
  1.1219 +                        goto enomem;
  1.1220 +
  1.1221 +                    free_identity_list(msg->cc);
  1.1222 +                    msg->cc = il;
  1.1223 +                }
  1.1224 +                break;
  1.1225 +
  1.1226 +            case MAILIMF_FIELD_BCC:
  1.1227 +                {
  1.1228 +                    struct mailimf_address_list *mal =
  1.1229 +                            _field->fld_data.fld_bcc->bcc_addr_list;
  1.1230 +                    identity_list *il = mal_to_identity_list(mal);
  1.1231 +                    if (il == NULL)
  1.1232 +                        goto enomem;
  1.1233 +
  1.1234 +                    free_identity_list(msg->bcc);
  1.1235 +                    msg->bcc = il;
  1.1236 +                }
  1.1237 +                break;
  1.1238 +
  1.1239 +            case MAILIMF_FIELD_REPLY_TO:
  1.1240 +                {
  1.1241 +                    struct mailimf_address_list *mal =
  1.1242 +                            _field->fld_data.fld_reply_to->rt_addr_list;
  1.1243 +                    identity_list *il = mal_to_identity_list(mal);
  1.1244 +                    if (il == NULL)
  1.1245 +                        goto enomem;
  1.1246 +
  1.1247 +                    free_identity_list(msg->reply_to);
  1.1248 +                    msg->reply_to = il;
  1.1249 +                }
  1.1250 +                break;
  1.1251 +
  1.1252 +            case MAILIMF_FIELD_IN_REPLY_TO:
  1.1253 +                {
  1.1254 +                    clist *list = _field->fld_data.fld_in_reply_to->mid_list;
  1.1255 +                    stringlist_t *sl = clist_to_stringlist(list);
  1.1256 +                    if (sl == NULL)
  1.1257 +                        goto enomem;
  1.1258 +
  1.1259 +                    free_stringlist(msg->in_reply_to);
  1.1260 +                    msg->in_reply_to = sl;
  1.1261 +                }
  1.1262 +                break;
  1.1263 +
  1.1264 +            case MAILIMF_FIELD_REFERENCES:
  1.1265 +                {
  1.1266 +                    clist *list = _field->fld_data.fld_references->mid_list;
  1.1267 +                    stringlist_t *sl = clist_to_stringlist(list);
  1.1268 +                    if (sl == NULL)
  1.1269 +                        goto enomem;
  1.1270 +
  1.1271 +                    free_stringlist(msg->references);
  1.1272 +                    msg->references = sl;
  1.1273 +                }
  1.1274 +                break;
  1.1275 +
  1.1276 +            case MAILIMF_FIELD_KEYWORDS:
  1.1277 +                {
  1.1278 +                    clist *list = _field->fld_data.fld_keywords->kw_list;
  1.1279 +                    stringlist_t *sl = clist_to_stringlist(list);
  1.1280 +                    if (sl == NULL)
  1.1281 +                        goto enomem;
  1.1282 +
  1.1283 +                    free_stringlist(msg->keywords);
  1.1284 +                    msg->keywords = sl;
  1.1285 +                }
  1.1286 +                break;
  1.1287 +
  1.1288 +            case MAILIMF_FIELD_COMMENTS:
  1.1289 +                {
  1.1290 +                    char * text = _field->fld_data.fld_comments->cm_value;
  1.1291 +
  1.1292 +                    free(msg->comments);
  1.1293 +                    index = 0;
  1.1294 +                    r = mailmime_encoded_phrase_parse("utf-8", text,
  1.1295 +                            strlen(text), &index, "utf-8", &msg->comments);
  1.1296 +                    if (r)
  1.1297 +                        goto enomem;
  1.1298 +                }
  1.1299 +                break;
  1.1300 +
  1.1301 +            case MAILIMF_FIELD_OPTIONAL_FIELD:
  1.1302 +                {
  1.1303 +                    char * name =
  1.1304 +                            _field->fld_data.fld_optional_field->fld_name;
  1.1305 +                    char * value =
  1.1306 +                            _field->fld_data.fld_optional_field->fld_value;
  1.1307 +                    char *_value;
  1.1308 +
  1.1309 +                    index = 0;
  1.1310 +                    r = mailmime_encoded_phrase_parse("utf-8", value,
  1.1311 +                            strlen(value), &index, "utf-8", &_value);
  1.1312 +                    if (r)
  1.1313 +                        goto enomem;
  1.1314 +
  1.1315 +                    stringpair_t *pair = new_stringpair(name, _value);
  1.1316 +                    if (pair == NULL)
  1.1317 +                        goto enomem;
  1.1318 +
  1.1319 +                    opt = stringpair_list_add(opt, pair);
  1.1320 +                    free(_value);
  1.1321 +                    if (opt == NULL)
  1.1322 +                        goto enomem;
  1.1323 +
  1.1324 +                    if (msg->opt_fields == NULL)
  1.1325 +                        msg->opt_fields = opt;
  1.1326 +                }
  1.1327 +                break;
  1.1328 +        }
  1.1329 +    }
  1.1330 +    
  1.1331 +    return PEP_STATUS_OK;
  1.1332 +
  1.1333 +enomem:
  1.1334 +    status = PEP_OUT_OF_MEMORY;
  1.1335 +
  1.1336 +pEp_error:
  1.1337 +    return status;
  1.1338 +}
  1.1339 +
  1.1340 +static PEP_STATUS interpret_body(struct mailmime *part, char **longmsg, size_t *size)
  1.1341 +{
  1.1342 +    const char *text;
  1.1343 +    char *_longmsg;
  1.1344 +    size_t length;
  1.1345 +    size_t _size;
  1.1346 +    size_t index;
  1.1347 +    char *type = NULL;
  1.1348 +    char *charset = NULL;
  1.1349 +
  1.1350 +    assert(part);
  1.1351 +    assert(longmsg);
  1.1352 +
  1.1353 +    *longmsg = NULL;
  1.1354 +    if (size)
  1.1355 +        *size = 0;
  1.1356 +
  1.1357 +    if (part->mm_body == NULL)
  1.1358 +        return PEP_ILLEGAL_VALUE;
  1.1359 +
  1.1360 +    text = part->mm_body-> dt_data.dt_text.dt_data;
  1.1361 +    if (text == NULL)
  1.1362 +        return PEP_ILLEGAL_VALUE;
  1.1363 +
  1.1364 +    length = part->mm_body->dt_data.dt_text.dt_length;
  1.1365 +
  1.1366 +    if (part->mm_body->dt_encoded) {
  1.1367 +        int code = part->mm_body->dt_encoding;
  1.1368 +        index = 0;
  1.1369 +        int r = mailmime_part_parse(text, length, &index, code, &_longmsg, &_size);
  1.1370 +        switch (r) {
  1.1371 +            case MAILIMF_NO_ERROR:
  1.1372 +                break;
  1.1373 +            case MAILIMF_ERROR_MEMORY:
  1.1374 +                return PEP_OUT_OF_MEMORY;
  1.1375 +            default:
  1.1376 +                return PEP_ILLEGAL_VALUE;
  1.1377 +        }
  1.1378 +    }
  1.1379 +    else {
  1.1380 +        _size = length + 1;
  1.1381 +        _longmsg = strndup(text, length);
  1.1382 +        if (_longmsg == NULL)
  1.1383 +            return PEP_OUT_OF_MEMORY;
  1.1384 +    }
  1.1385 +
  1.1386 +    if (part->mm_content_type) {
  1.1387 +        if (_get_content_type(part->mm_content_type, &type, &charset) == 0) {
  1.1388 +            if (charset && strncasecmp(charset, "utf-8", 5) != 0) {
  1.1389 +                char * _text;
  1.1390 +                int r = charconv("utf-8", charset, _longmsg, _size, &_text);
  1.1391 +                switch (r) {
  1.1392 +                    case MAILIMF_NO_ERROR:
  1.1393 +                        break;
  1.1394 +                    case MAILIMF_ERROR_MEMORY:
  1.1395 +                        return PEP_OUT_OF_MEMORY;
  1.1396 +                    default:
  1.1397 +                        return PEP_ILLEGAL_VALUE;
  1.1398 +                }
  1.1399 +                free(_longmsg);
  1.1400 +                _longmsg = _text;
  1.1401 +            }
  1.1402 +        }
  1.1403 +    }
  1.1404 +    // FIXME: KG - we now have the text we want.
  1.1405 +    // Now we need to strip sigs and process them if they are there..
  1.1406 +    
  1.1407 +
  1.1408 +    *longmsg = _longmsg;
  1.1409 +    if (size)
  1.1410 +        *size = _size;
  1.1411 +
  1.1412 +    return PEP_STATUS_OK;
  1.1413 +}
  1.1414 +
  1.1415 +// THIS IS A BEST-EFFORT ONLY FUNCTION, AND WE ARE NOT DOING MORE THAN THE
  1.1416 +// SUBJECT FOR NOW.
  1.1417 +static PEP_STATUS interpret_protected_headers(
  1.1418 +        struct mailmime* mime, 
  1.1419 +        message* msg
  1.1420 +    )
  1.1421 +{
  1.1422 +    // N.B. this is *very much* enigmail output specific, and right now,
  1.1423 +    // we only care about subject replacement.
  1.1424 +    const char* header_string = "Content-Type: text/rfc822-headers; protected-headers=\"v1\"\nContent-Disposition: inline\n\n";
  1.1425 +    size_t content_length = mime->mm_length;
  1.1426 +    size_t header_strlen = strlen(header_string);
  1.1427 +    if (header_strlen < content_length) {
  1.1428 +        const char* headerblock = mime->mm_mime_start;
  1.1429 +        size_t subject_len = 0;
  1.1430 +        headerblock = strstr(headerblock, header_string);
  1.1431 +        if (headerblock) {
  1.1432 +            const char* subj_start = "Subject: ";
  1.1433 +            headerblock = strstr(headerblock, subj_start);
  1.1434 +            if (headerblock) {
  1.1435 +                size_t subj_len = strlen(subj_start);
  1.1436 +                headerblock += subj_len;
  1.1437 +                char* end_pt = strstr(headerblock, "\n");
  1.1438 +                if (end_pt) {
  1.1439 +                    if (end_pt != mime->mm_mime_start && *(end_pt - 1) == '\r')
  1.1440 +                        end_pt--;
  1.1441 +                    subject_len = end_pt - headerblock;
  1.1442 +                    char* new_subj = (char*)calloc(subject_len + 1, 1);
  1.1443 +                    if (new_subj) {
  1.1444 +                        strlcpy(new_subj, headerblock, subject_len + 1);
  1.1445 +                        free(msg->shortmsg);
  1.1446 +                        msg->shortmsg = new_subj;
  1.1447 +                    }    
  1.1448 +                } // if there's no endpoint, there's something wrong here so we ignore all
  1.1449 +                  // This is best effort.
  1.1450 +            }
  1.1451 +        }
  1.1452 +    }
  1.1453 +    return PEP_STATUS_OK;
  1.1454 +}
  1.1455 +
  1.1456 +// ONLY for main part!!!
  1.1457 +static PEP_STATUS process_multipart_related(struct mailmime *mime,
  1.1458 +                                            message *msg) {
  1.1459 +    PEP_STATUS status = PEP_STATUS_OK;
  1.1460 +
  1.1461 +    assert(mime);
  1.1462 +    assert(msg);
  1.1463 +
  1.1464 +    clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;                                                
  1.1465 +
  1.1466 +    if (partlist == NULL)
  1.1467 +        return PEP_ILLEGAL_VALUE;
  1.1468 +
  1.1469 +    clistiter *cur = clist_begin(partlist);
  1.1470 +    struct mailmime *part = clist_content(cur);
  1.1471 +    
  1.1472 +    if (part == NULL)
  1.1473 +        return PEP_ILLEGAL_VALUE;
  1.1474 +
  1.1475 +    struct mailmime_content *content = part->mm_content_type;    
  1.1476 +    assert(content);
  1.1477 +    
  1.1478 +    if (content == NULL)
  1.1479 +        return PEP_ILLEGAL_VALUE;
  1.1480 +
  1.1481 +    if (_is_text_part(content, "html")) {
  1.1482 +        status = interpret_body(part, &msg->longmsg_formatted,
  1.1483 +                NULL);
  1.1484 +        if (status)
  1.1485 +            return status;
  1.1486 +    }
  1.1487 +    else {
  1.1488 +        // ???
  1.1489 +        // This is what we would have done before, so... no
  1.1490 +        // worse than the status quo. But FIXME!
  1.1491 +        status = interpret_MIME(part, msg);
  1.1492 +        if (status)
  1.1493 +            return status;
  1.1494 +    }
  1.1495 +    
  1.1496 +    for (cur = clist_next(cur); cur; cur = clist_next(cur)) {
  1.1497 +        part = clist_content(cur);
  1.1498 +        if (part == NULL)
  1.1499 +            return PEP_ILLEGAL_VALUE;
  1.1500 +
  1.1501 +        content = part->mm_content_type;
  1.1502 +        assert(content);
  1.1503 +        if (content == NULL)
  1.1504 +            return PEP_ILLEGAL_VALUE;
  1.1505 +
  1.1506 +        status = interpret_MIME(part, msg);
  1.1507 +        if (status)
  1.1508 +            return status;
  1.1509 +    }
  1.1510 +    return status;
  1.1511 +}
  1.1512 +
  1.1513 +static PEP_STATUS interpret_MIME(
  1.1514 +        struct mailmime *mime,
  1.1515 +        message *msg
  1.1516 +    )
  1.1517 +{
  1.1518 +    PEP_STATUS status = PEP_STATUS_OK;
  1.1519 +
  1.1520 +    assert(mime);
  1.1521 +    assert(msg);
  1.1522 +
  1.1523 +    struct mailmime_content *content = mime->mm_content_type;
  1.1524 +    if (content) {
  1.1525 +        if (_is_multipart(content, "alternative")) {
  1.1526 +            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
  1.1527 +            if (partlist == NULL)
  1.1528 +                return PEP_ILLEGAL_VALUE;
  1.1529 +
  1.1530 +            clistiter *cur;
  1.1531 +            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
  1.1532 +                struct mailmime *part = clist_content(cur);
  1.1533 +                if (part == NULL)
  1.1534 +                    return PEP_ILLEGAL_VALUE;
  1.1535 +
  1.1536 +                content = part->mm_content_type;
  1.1537 +                assert(content);
  1.1538 +                if (content == NULL)
  1.1539 +                    return PEP_ILLEGAL_VALUE;
  1.1540 +
  1.1541 +                if (_is_text_part(content, "plain") && msg->longmsg == NULL) {
  1.1542 +                    status = interpret_body(part, &msg->longmsg, NULL);
  1.1543 +                    if (status)
  1.1544 +                        return status;
  1.1545 +                }
  1.1546 +                else if (_is_text_part(content, "rfc822-headers")) {
  1.1547 +                    status = interpret_protected_headers(part, msg);
  1.1548 +                    if (status)
  1.1549 +                        return status;
  1.1550 +                }
  1.1551 +                else if (_is_text_part(content, "html") &&
  1.1552 +                        msg->longmsg_formatted == NULL) {
  1.1553 +                    status = interpret_body(part, &msg->longmsg_formatted,
  1.1554 +                            NULL);
  1.1555 +                    if (status)
  1.1556 +                        return status;
  1.1557 +                }
  1.1558 +                else if (_is_multipart(content, "related") && 
  1.1559 +                    msg->longmsg_formatted == NULL) {
  1.1560 +                    status = process_multipart_related(part, msg);
  1.1561 +                    if (status)
  1.1562 +                        return status;
  1.1563 +                }
  1.1564 +                else /* add as attachment */ {
  1.1565 +                    status = interpret_MIME(part, msg);
  1.1566 +                    if (status)
  1.1567 +                        return status;
  1.1568 +                }
  1.1569 +            }
  1.1570 +        }
  1.1571 +        else if (_is_multipart(content, "encrypted")) {
  1.1572 +            if (msg->longmsg == NULL)
  1.1573 +                msg->longmsg = strdup("");
  1.1574 +            assert(msg->longmsg);
  1.1575 +            if (!msg->longmsg)
  1.1576 +                return PEP_OUT_OF_MEMORY;
  1.1577 +
  1.1578 +            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
  1.1579 +            if (partlist == NULL)
  1.1580 +                return PEP_ILLEGAL_VALUE;
  1.1581 +
  1.1582 +            clistiter *cur;
  1.1583 +            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
  1.1584 +                struct mailmime *part= clist_content(cur);
  1.1585 +                if (part == NULL)
  1.1586 +                    return PEP_ILLEGAL_VALUE;
  1.1587 +
  1.1588 +                status = interpret_MIME(part, msg);
  1.1589 +                if (status != PEP_STATUS_OK)
  1.1590 +                    return status;
  1.1591 +            }
  1.1592 +        }
  1.1593 +        else if (_is_multipart(content, NULL)) {
  1.1594 +            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
  1.1595 +            if (partlist == NULL)
  1.1596 +                return PEP_ILLEGAL_VALUE;
  1.1597 +
  1.1598 +            clistiter *cur;
  1.1599 +            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
  1.1600 +                struct mailmime *part= clist_content(cur);
  1.1601 +                if (part == NULL)
  1.1602 +                    return PEP_ILLEGAL_VALUE;
  1.1603 +                status = interpret_MIME(part, msg);
  1.1604 +                if (status != PEP_STATUS_OK)
  1.1605 +                    return status;
  1.1606 +            }
  1.1607 +        }
  1.1608 +        else {
  1.1609 +            if (_is_text_part(content, "html") &&
  1.1610 +                msg->longmsg_formatted == NULL &&
  1.1611 +                msg->longmsg == NULL) {
  1.1612 +                status = interpret_body(mime, &msg->longmsg_formatted,
  1.1613 +                                        NULL);
  1.1614 +                if (status)
  1.1615 +                    return status;
  1.1616 +            }
  1.1617 +            else if (_is_text_part(content, "rfc822-headers")) {
  1.1618 +                status = interpret_protected_headers(mime, msg);
  1.1619 +                if (status)
  1.1620 +                    return status;
  1.1621 +            }
  1.1622 +            else if (_is_text_part(content, "plain") && 
  1.1623 +                     msg->longmsg == NULL && msg->longmsg_formatted == NULL) {
  1.1624 +                status = interpret_body(mime, &msg->longmsg, NULL);
  1.1625 +                if (status)
  1.1626 +                    return status;
  1.1627 +            }            
  1.1628 +            else if (_is_text_part(content, NULL) && 
  1.1629 +                     !_is_text_part(content, "plain") &&
  1.1630 +                     msg->longmsg == NULL) {
  1.1631 +                status = interpret_body(mime, &msg->longmsg, NULL);
  1.1632 +                if (status)
  1.1633 +                    return status;
  1.1634 +            }
  1.1635 +            else {
  1.1636 +                char *data = NULL;
  1.1637 +                size_t size = 0;
  1.1638 +                char * mime_type;
  1.1639 +                char * charset;
  1.1640 +                char * filename;
  1.1641 +                int r;
  1.1642 +
  1.1643 +                r = _get_content_type(content, &mime_type, &charset);
  1.1644 +                switch (r) {
  1.1645 +                    case 0:
  1.1646 +                        break;
  1.1647 +                    case EINVAL:
  1.1648 +                        return PEP_ILLEGAL_VALUE;
  1.1649 +                    case ENOMEM:
  1.1650 +                        return PEP_OUT_OF_MEMORY;
  1.1651 +                    default:
  1.1652 +                        return PEP_UNKNOWN_ERROR;
  1.1653 +                }
  1.1654 +
  1.1655 +                assert(mime_type);
  1.1656 +
  1.1657 +                status = interpret_body(mime, &data, &size);
  1.1658 +                if (status)
  1.1659 +                    return status;
  1.1660 +
  1.1661 +                pEp_rid_list_t* resource_id_list = _get_resource_id_list(mime);
  1.1662 +                pEp_rid_list_t* chosen_resource_id = choose_resource_id(resource_id_list);
  1.1663 +                
  1.1664 +                //filename = _get_filename_or_cid(mime);
  1.1665 +                char *_filename = NULL;
  1.1666 +                
  1.1667 +                if (chosen_resource_id) {
  1.1668 +                    filename = chosen_resource_id->rid;
  1.1669 +                    size_t index = 0;
  1.1670 +                    /* NOTA BENE */
  1.1671 +                    /* The prefix we just added shouldn't be a problem - this is about decoding %XX (RFC 2392) */
  1.1672 +                    /* If it becomes one, we have some MESSY fixing to do. :(                                  */
  1.1673 +                    r = mailmime_encoded_phrase_parse("utf-8", filename,
  1.1674 +                            strlen(filename), &index, "utf-8", &_filename);
  1.1675 +                    if (r) {
  1.1676 +                        goto enomem;
  1.1677 +                    }
  1.1678 +                    char* file_prefix = NULL;
  1.1679 +                    
  1.1680 +                    /* in case there are others later */
  1.1681 +                    switch (chosen_resource_id->rid_type) {
  1.1682 +                        case PEP_RID_CID:
  1.1683 +                            file_prefix = "cid";
  1.1684 +                            break;
  1.1685 +                        case PEP_RID_FILENAME:
  1.1686 +                            file_prefix = "file";
  1.1687 +                            break;
  1.1688 +                        default:
  1.1689 +                            break;
  1.1690 +                    }
  1.1691 +
  1.1692 +                    
  1.1693 +                    if (file_prefix) {
  1.1694 +                        filename = build_uri(file_prefix, _filename);
  1.1695 +                        free(_filename);
  1.1696 +                        _filename = filename;
  1.1697 +                    }
  1.1698 +                }
  1.1699 +
  1.1700 +                bloblist_t *_a = bloblist_add(msg->attachments, data, size,
  1.1701 +                        mime_type, _filename);
  1.1702 +                free(_filename);
  1.1703 +                free_rid_list(resource_id_list);
  1.1704 +                resource_id_list = NULL;
  1.1705 +                if (_a == NULL)
  1.1706 +                    return PEP_OUT_OF_MEMORY;
  1.1707 +                if (msg->attachments == NULL)
  1.1708 +                    msg->attachments = _a;
  1.1709 +            }
  1.1710 +        }
  1.1711 +    }
  1.1712 +
  1.1713 +    return PEP_STATUS_OK;
  1.1714 +
  1.1715 +enomem:
  1.1716 +    return PEP_OUT_OF_MEMORY;
  1.1717 +}
  1.1718 +
  1.1719 +DYNAMIC_API PEP_STATUS mime_decode_message(
  1.1720 +        const char *mimetext,
  1.1721 +        size_t size,
  1.1722 +        message **msg
  1.1723 +    )
  1.1724 +{
  1.1725 +    PEP_STATUS status = PEP_STATUS_OK;
  1.1726 +    struct mailmime * mime = NULL;
  1.1727 +    int r;
  1.1728 +    message *_msg = NULL;
  1.1729 +    size_t index;
  1.1730 +
  1.1731 +    assert(mimetext);
  1.1732 +    assert(msg);
  1.1733 +
  1.1734 +    if (!(mimetext && msg))
  1.1735 +        return PEP_ILLEGAL_VALUE;
  1.1736 +
  1.1737 +    *msg = NULL;
  1.1738 +
  1.1739 +    index = 0;
  1.1740 +    r = mailmime_parse(mimetext, size, &index, &mime);
  1.1741 +    assert(r == 0);
  1.1742 +    assert(mime);
  1.1743 +    if (r) {
  1.1744 +        if (r == MAILIMF_ERROR_MEMORY)
  1.1745 +            goto enomem;
  1.1746 +        else
  1.1747 +            goto err_mime;
  1.1748 +    }
  1.1749 +
  1.1750 +    _msg = calloc(1, sizeof(message));
  1.1751 +    assert(_msg);
  1.1752 +    if (_msg == NULL)
  1.1753 +        goto enomem;
  1.1754 +
  1.1755 +    clist * _fieldlist = _get_fields(mime);
  1.1756 +    if (_fieldlist) {
  1.1757 +        status = read_fields(_msg, _fieldlist);
  1.1758 +        if (status != PEP_STATUS_OK)
  1.1759 +            goto pEp_error;
  1.1760 +    }
  1.1761 +
  1.1762 +    struct mailmime_content *content = _get_content(mime);
  1.1763 +
  1.1764 +    if (content) {
  1.1765 +        status = interpret_MIME(mime->mm_data.mm_message.mm_msg_mime,
  1.1766 +                _msg);
  1.1767 +        if (status != PEP_STATUS_OK)
  1.1768 +            goto pEp_error;
  1.1769 +    }
  1.1770 +
  1.1771 +    mailmime_free(mime);
  1.1772 +    *msg = _msg;
  1.1773 +
  1.1774 +    return status;
  1.1775 +
  1.1776 +err_mime:
  1.1777 +    status = PEP_ILLEGAL_VALUE;
  1.1778 +    goto pEp_error;
  1.1779 +
  1.1780 +enomem:
  1.1781 +    status = PEP_OUT_OF_MEMORY;
  1.1782 +
  1.1783 +pEp_error:
  1.1784 +    free_message(_msg);
  1.1785 +
  1.1786 +    if (mime)
  1.1787 +        mailmime_free(mime);
  1.1788 +
  1.1789 +    return status;
  1.1790 +}
     2.1 --- a/src/mime.c	Wed Apr 03 17:52:41 2019 +0200
     2.2 +++ b/src/mime.c	Fri Apr 05 16:56:44 2019 +0200
     2.3 @@ -1,7 +1,6 @@
     2.4  // This file is under GNU General Public License 3.0
     2.5  // see LICENSE.txt
     2.6  
     2.7 -#include "pEp_internal.h"
     2.8  #include "mime.h"
     2.9  
    2.10  #include <string.h>
    2.11 @@ -9,13 +8,7 @@
    2.12  #include <assert.h>
    2.13  #include <errno.h>
    2.14  
    2.15 -#include "resource_id.h"
    2.16  #include "etpan_mime.h"
    2.17 -#include "wrappers.h"
    2.18 -
    2.19 -static PEP_STATUS interpret_MIME(struct mailmime *mime,
    2.20 -                                 message *msg);
    2.21 -
    2.22  
    2.23  static bool is_whitespace(char c)
    2.24  {
    2.25 @@ -40,1772 +33,3 @@
    2.26  
    2.27      return strncmp(text, "-----BEGIN PGP MESSAGE-----", 27) == 0;
    2.28  }
    2.29 -
    2.30 -#define TMP_TEMPLATE "pEp.XXXXXXXXXXXXXXXXXXXX"
    2.31 -#ifdef _WIN32
    2.32 -#define PATH_SEP '\\'
    2.33 -#else
    2.34 -#define PATH_SEP '/'
    2.35 -#endif
    2.36 -
    2.37 -// This function was rewritten to use in-memory buffers instead of
    2.38 -// temporary files when the pgp/mime support was implemented for
    2.39 -// outlook, as the existing code did not work well on windows.
    2.40 -
    2.41 -static PEP_STATUS render_mime(struct mailmime *mime, char **mimetext)
    2.42 -{
    2.43 -    PEP_STATUS status = PEP_STATUS_OK;
    2.44 -    int col;
    2.45 -    int r;
    2.46 -	size_t len;
    2.47 -	char* buf = NULL;
    2.48 -
    2.49 -	MMAPString* buffer;
    2.50 -
    2.51 -	buffer = mmap_string_new(NULL);
    2.52 -	if (buffer == NULL)
    2.53 -		goto enomem;
    2.54 -	
    2.55 -	col = 0;
    2.56 -	r = mailmime_write_mem(buffer, &col, mime);
    2.57 -	assert(r == MAILIMF_NO_ERROR);
    2.58 -	if (r == MAILIMF_ERROR_MEMORY)
    2.59 -		goto enomem;
    2.60 -	else if (r != MAILIMF_NO_ERROR)
    2.61 -		goto err_file;
    2.62 -
    2.63 -	// we overallocate by 1 byte, so we have a terminating 0.
    2.64 -	len = buffer->len;
    2.65 -	buf = calloc(len + 1, 1);
    2.66 -	if (buf == NULL)
    2.67 -		goto enomem;
    2.68 -
    2.69 -	memcpy(buf, buffer->str, len);
    2.70 -	mmap_string_free(buffer);
    2.71 -
    2.72 -    *mimetext = buf;
    2.73 -    return PEP_STATUS_OK;
    2.74 -
    2.75 -err_file:
    2.76 -    status = PEP_CANNOT_CREATE_TEMP_FILE;
    2.77 -    goto pEp_error;
    2.78 -
    2.79 -enomem:
    2.80 -    status = PEP_OUT_OF_MEMORY;
    2.81 -
    2.82 -pEp_error:
    2.83 -	if (buffer)
    2.84 -		mmap_string_free(buffer);
    2.85 -	if (buf)
    2.86 -		free(buf);
    2.87 -    return status;
    2.88 -}
    2.89 -
    2.90 -static PEP_STATUS mime_attachment(
    2.91 -        bloblist_t *blob,
    2.92 -        struct mailmime **result,
    2.93 -        bool transport_encode
    2.94 -    )
    2.95 -{
    2.96 -    PEP_STATUS status = PEP_STATUS_OK;
    2.97 -    struct mailmime * mime = NULL;
    2.98 -    char * mime_type;
    2.99 -    assert(blob);
   2.100 -    assert(result);
   2.101 -
   2.102 -    *result = NULL;
   2.103 -
   2.104 -// TODO: It seems the pEp COM server adapter sends an empty string here,
   2.105 -// which leads to a crash later. Thus, we workaround here by treating an
   2.106 -// empty string as NULL. We need to check whether the bug really is here,
   2.107 -// or the pEp COM server adapter needs to be changed.
   2.108 -    if (blob->mime_type == NULL || blob->mime_type[0] == '\0')
   2.109 -        mime_type = "application/octet-stream";
   2.110 -    else
   2.111 -        mime_type = blob->mime_type;
   2.112 -
   2.113 -    pEp_rid_list_t* resource = parse_uri(blob->filename);
   2.114 -
   2.115 -    bool already_ascii = !(must_chunk_be_encoded(blob->value, blob->size, true));
   2.116 -
   2.117 -    mime = get_file_part(resource, mime_type, blob->value, blob->size, 
   2.118 -                          (already_ascii ? false : transport_encode));
   2.119 -    free_rid_list(resource);
   2.120 -    
   2.121 -    assert(mime);
   2.122 -    if (mime == NULL)
   2.123 -        goto enomem;
   2.124 -
   2.125 -    *result = mime;
   2.126 -    return PEP_STATUS_OK;
   2.127 -
   2.128 -enomem:
   2.129 -    status = PEP_OUT_OF_MEMORY;
   2.130 -
   2.131 -    if (mime)
   2.132 -        mailmime_free(mime);
   2.133 -
   2.134 -    return status;
   2.135 -}
   2.136 -
   2.137 -static PEP_STATUS mime_html_text(
   2.138 -        const char *plaintext,
   2.139 -        const char *htmltext,
   2.140 -        bloblist_t *attachments,
   2.141 -        struct mailmime **result,
   2.142 -        bool transport_encode
   2.143 -    )
   2.144 -{
   2.145 -    PEP_STATUS status = PEP_STATUS_OK;
   2.146 -    struct mailmime * top_level_html_mime = NULL;
   2.147 -    struct mailmime * mime = NULL;
   2.148 -    struct mailmime * submime = NULL;
   2.149 -    int r;
   2.150 -
   2.151 -    assert(plaintext);
   2.152 -    assert(htmltext);
   2.153 -    assert(result);
   2.154 -
   2.155 -    *result = NULL;
   2.156 -
   2.157 -    mime = part_multiple_new("multipart/alternative");
   2.158 -    assert(mime);
   2.159 -    if (mime == NULL)
   2.160 -        goto enomem;
   2.161 -
   2.162 -    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
   2.163 -    
   2.164 -    int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
   2.165 -    submime = get_text_part(NULL, "text/plain", plaintext, strlen(plaintext),
   2.166 -            encoding_type);
   2.167 -    free_rid_list(resource);
   2.168 -    resource = NULL;
   2.169 -    
   2.170 -    assert(submime);
   2.171 -    if (submime == NULL)
   2.172 -        goto enomem;
   2.173 -
   2.174 -    r = mailmime_smart_add_part(mime, submime);
   2.175 -    assert(r == MAILIMF_NO_ERROR);
   2.176 -    if (r == MAILIMF_ERROR_MEMORY) {
   2.177 -        goto enomem;
   2.178 -    }
   2.179 -    else {
   2.180 -        // mailmime_smart_add_part() takes ownership of submime
   2.181 -        submime = NULL;
   2.182 -    }
   2.183 -
   2.184 -    bool inlined_attachments = false;
   2.185 -    
   2.186 -    bloblist_t* traversal_ptr = attachments;
   2.187 -    
   2.188 -    while (traversal_ptr) {
   2.189 -        if (traversal_ptr->disposition == PEP_CONTENT_DISP_INLINE) {
   2.190 -            inlined_attachments = true;
   2.191 -            break;
   2.192 -        }
   2.193 -        traversal_ptr = traversal_ptr->next;
   2.194 -    }
   2.195 -
   2.196 -    if (inlined_attachments) {
   2.197 -        /* Noooooo... dirk, why do you do this to me? */
   2.198 -        submime = part_multiple_new("multipart/related");
   2.199 -        assert(submime);
   2.200 -        if (submime == NULL)
   2.201 -            goto enomem;
   2.202 -
   2.203 -        top_level_html_mime = submime;
   2.204 -        
   2.205 -        r = mailmime_smart_add_part(mime, top_level_html_mime);
   2.206 -        assert(r == MAILIMF_NO_ERROR);
   2.207 -        if (r == MAILIMF_ERROR_MEMORY) {
   2.208 -            goto enomem;
   2.209 -        }
   2.210 -        else {
   2.211 -            // mailmime_smart_add_part() takes ownership of submime
   2.212 -            submime = NULL;
   2.213 -        }
   2.214 -    }
   2.215 -    else {
   2.216 -        top_level_html_mime = mime;
   2.217 -    }
   2.218 -
   2.219 -//    resource = new_rid_node(PEP_RID_FILENAME, "msg.html");
   2.220 -    submime = get_text_part(NULL, "text/html", htmltext, strlen(htmltext),
   2.221 -            encoding_type);
   2.222 -    free_rid_list(resource);
   2.223 -    resource = NULL;
   2.224 -    
   2.225 -    assert(submime);
   2.226 -    if (submime == NULL)
   2.227 -        goto enomem;
   2.228 -
   2.229 -    r = mailmime_smart_add_part(top_level_html_mime, submime);
   2.230 -    assert(r == MAILIMF_NO_ERROR);
   2.231 -    if (r == MAILIMF_ERROR_MEMORY)
   2.232 -        goto enomem;
   2.233 -    else {
   2.234 -        // mailmime_smart_add_part() takes ownership of submime
   2.235 -        submime = NULL;
   2.236 -    }
   2.237 -
   2.238 -    bloblist_t *_a;
   2.239 -    for (_a = attachments; _a != NULL; _a = _a->next) {
   2.240 -        if (_a->disposition != PEP_CONTENT_DISP_INLINE)
   2.241 -            continue;
   2.242 -        status = mime_attachment(_a, &submime, transport_encode);
   2.243 -        if (status != PEP_STATUS_OK)
   2.244 -            return PEP_UNKNOWN_ERROR; // FIXME
   2.245 -
   2.246 -        r = mailmime_smart_add_part(top_level_html_mime, submime);
   2.247 -        assert(r == MAILIMF_NO_ERROR);
   2.248 -        if (r == MAILIMF_ERROR_MEMORY) {
   2.249 -            goto enomem;
   2.250 -        }
   2.251 -        else {
   2.252 -            // mailmime_smart_add_part() takes ownership of submime
   2.253 -            submime = NULL;
   2.254 -        }
   2.255 -    }
   2.256 -
   2.257 -    *result = mime;
   2.258 -    return PEP_STATUS_OK;
   2.259 -
   2.260 -enomem:
   2.261 -    status = PEP_OUT_OF_MEMORY;
   2.262 -
   2.263 -    if (mime)
   2.264 -        mailmime_free(mime);
   2.265 -
   2.266 -    if (submime)
   2.267 -        mailmime_free(submime);
   2.268 -
   2.269 -    return status;
   2.270 -}
   2.271 -
   2.272 -
   2.273 -// FIXME: maybe need to add transport_encode field here
   2.274 -static struct mailimf_mailbox * identity_to_mailbox(const pEp_identity *ident)
   2.275 -{
   2.276 -    char *_username = NULL;
   2.277 -    struct mailimf_mailbox *mb;
   2.278 -
   2.279 -    if (!ident->username)
   2.280 -        _username = strdup("");
   2.281 -    else
   2.282 -        _username = must_field_value_be_encoded(ident->username) ?
   2.283 -                    mailmime_encode_subject_header("utf-8", ident->username, 0) : 
   2.284 -                    strdup(ident->username);
   2.285 -                  
   2.286 -    assert(_username);
   2.287 -    if (_username == NULL)
   2.288 -        goto enomem;
   2.289 -
   2.290 -    mb = mailbox_from_string(_username, ident->address);
   2.291 -    if (mb == NULL)
   2.292 -        goto enomem;
   2.293 -
   2.294 -    free(_username);
   2.295 -    _username = NULL;
   2.296 -
   2.297 -    return mb;
   2.298 -
   2.299 -enomem:
   2.300 -    free(_username);
   2.301 -    return NULL;
   2.302 -}
   2.303 -
   2.304 -static struct mailimf_mailbox_list * identity_to_mbl(
   2.305 -        const pEp_identity *ident)
   2.306 -{
   2.307 -    struct mailimf_mailbox_list *mbl = NULL;
   2.308 -    struct mailimf_mailbox *mb = NULL;
   2.309 -    clist *list = NULL;
   2.310 -    int r;
   2.311 -
   2.312 -    assert(ident);
   2.313 -
   2.314 -    list = clist_new();
   2.315 -    if (list == NULL)
   2.316 -        goto enomem;
   2.317 -
   2.318 -    mb = identity_to_mailbox(ident);
   2.319 -    if (mb == NULL)
   2.320 -        goto enomem;
   2.321 -
   2.322 -    r = clist_append(list, mb);
   2.323 -    if (r)
   2.324 -        goto enomem;
   2.325 -
   2.326 -    mbl = mailimf_mailbox_list_new(list);
   2.327 -    if (mbl == NULL)
   2.328 -        goto enomem;
   2.329 -
   2.330 -    return mbl;
   2.331 -
   2.332 -enomem:
   2.333 -    if (mb)
   2.334 -        mailimf_mailbox_free(mb);
   2.335 -
   2.336 -    if (list)
   2.337 -        clist_free(list);
   2.338 -
   2.339 -    return NULL;
   2.340 -}
   2.341 -
   2.342 -static struct mailimf_address_list * identity_list_to_mal(identity_list *il)
   2.343 -{
   2.344 -    struct mailimf_address_list *mal = NULL;
   2.345 -    struct mailimf_mailbox *mb = NULL;
   2.346 -    struct mailimf_address * addr = NULL;
   2.347 -    clist *list = NULL;
   2.348 -    int r;
   2.349 -
   2.350 -    assert(il);
   2.351 -
   2.352 -    list = clist_new();
   2.353 -    if (list == NULL)
   2.354 -        goto enomem;
   2.355 -
   2.356 -    identity_list *_il;
   2.357 -    for (_il = il; _il && _il->ident; _il = _il->next) {
   2.358 -        mb = identity_to_mailbox(_il->ident);
   2.359 -        if (mb == NULL)
   2.360 -            goto enomem;
   2.361 -
   2.362 -        addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
   2.363 -        if (addr == NULL)
   2.364 -            goto enomem;
   2.365 -        mb = NULL;
   2.366 -
   2.367 -        r = clist_append(list, addr);
   2.368 -        if (r)
   2.369 -            goto enomem;
   2.370 -        addr = NULL;
   2.371 -    }
   2.372 -    mal = mailimf_address_list_new(list);
   2.373 -    if (mal == NULL)
   2.374 -        goto enomem;
   2.375 -
   2.376 -    return mal;
   2.377 -
   2.378 -enomem:
   2.379 -    if (mb)
   2.380 -        mailimf_mailbox_free(mb);
   2.381 -
   2.382 -    if (addr)
   2.383 -        mailimf_address_free(addr);
   2.384 -
   2.385 -    if (list)
   2.386 -        clist_free(list);
   2.387 -
   2.388 -    return NULL;
   2.389 -}
   2.390 -
   2.391 -static clist * stringlist_to_clist(stringlist_t *sl, bool transport_encode)
   2.392 -{
   2.393 -    clist * cl = clist_new();
   2.394 -    assert(cl);
   2.395 -    if (cl == NULL)
   2.396 -        return NULL;
   2.397 -
   2.398 -    if (!sl || ((!sl->value || sl->value[0] == '\0') && sl->next == NULL))
   2.399 -        return cl;
   2.400 -        
   2.401 -    stringlist_t *_sl;
   2.402 -    for (_sl = sl; _sl; _sl = _sl->next) {
   2.403 -        int r;
   2.404 -        char * value = ((transport_encode && must_field_value_be_encoded(_sl->value)) ?
   2.405 -                        mailmime_encode_subject_header("utf-8", _sl->value, 0) :
   2.406 -                        strdup(_sl->value));
   2.407 -        assert(value);
   2.408 -        if (value == NULL) {
   2.409 -            clist_free(cl);
   2.410 -            return NULL;
   2.411 -        }
   2.412 -        r = clist_append(cl, value);
   2.413 -        assert(r == 0);
   2.414 -        if (r) {
   2.415 -            free(value);
   2.416 -            clist_free(cl);
   2.417 -            return NULL;
   2.418 -        }
   2.419 -    }
   2.420 -
   2.421 -    return cl;
   2.422 -}
   2.423 -
   2.424 -static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result)
   2.425 -{
   2.426 -    PEP_STATUS status = PEP_STATUS_OK;
   2.427 -    struct mailimf_fields * fields = NULL;
   2.428 -    int r;
   2.429 -    clist * fields_list = NULL;
   2.430 -    unsigned char pEpstr[] = PEP_SUBJ_STRING; // unsigned due to UTF-8 byte fun
   2.431 -#ifdef WIN32
   2.432 -    char* altstr = "pEp";
   2.433 -#else
   2.434 -    char* altstr = (char*)pEpstr;
   2.435 -#endif        
   2.436 -    char *subject = msg->shortmsg ? msg->shortmsg : altstr;
   2.437 -
   2.438 -    assert(msg);
   2.439 -    assert(result);
   2.440 -
   2.441 -    *result = NULL;
   2.442 -
   2.443 -    fields_list = clist_new();
   2.444 -    assert(fields_list);
   2.445 -    if (fields_list == NULL)
   2.446 -        goto enomem;
   2.447 -
   2.448 -    if (msg->id) {
   2.449 -        char *_msgid = strdup(msg->id);
   2.450 -        assert(_msgid);
   2.451 -        if (_msgid == NULL)
   2.452 -            goto enomem;
   2.453 -
   2.454 -        r = _append_field(fields_list, MAILIMF_FIELD_MESSAGE_ID,
   2.455 -                (_new_func_t) mailimf_message_id_new, _msgid);
   2.456 -        if (r) {
   2.457 -            free(_msgid);
   2.458 -            goto enomem;
   2.459 -        }
   2.460 -    }
   2.461 -
   2.462 -    if (msg->sent) {
   2.463 -        struct mailimf_date_time * dt = timestamp_to_etpantime(msg->sent);
   2.464 -        if (dt == NULL)
   2.465 -            goto enomem;
   2.466 -
   2.467 -        r = _append_field(fields_list, MAILIMF_FIELD_ORIG_DATE,
   2.468 -                (_new_func_t) mailimf_orig_date_new, dt);
   2.469 -        if (r) {
   2.470 -            mailimf_date_time_free(dt);
   2.471 -            goto enomem;
   2.472 -        }
   2.473 -        dt = NULL;
   2.474 -    }
   2.475 -
   2.476 -     if (msg->from) {
   2.477 -        struct mailimf_mailbox_list *from = identity_to_mbl(msg->from);
   2.478 -        if (from == NULL)
   2.479 -            goto enomem;
   2.480 -
   2.481 -        r = _append_field(fields_list, MAILIMF_FIELD_FROM,
   2.482 -                (_new_func_t) mailimf_from_new, from);
   2.483 -        if (r) {
   2.484 -            mailimf_mailbox_list_free(from);
   2.485 -            goto enomem;
   2.486 -        }
   2.487 -    }
   2.488 -
   2.489 -    if (msg->to) {
   2.490 -        struct mailimf_address_list *to = identity_list_to_mal(msg->to);
   2.491 -        if (to == NULL)
   2.492 -            goto enomem;
   2.493 -
   2.494 -        r = _append_field(fields_list, MAILIMF_FIELD_TO,
   2.495 -                (_new_func_t) mailimf_to_new, to);
   2.496 -        if (r) {
   2.497 -            mailimf_address_list_free(to);
   2.498 -            goto enomem;
   2.499 -        }
   2.500 -    }
   2.501 -
   2.502 -    char* _subject = NULL;
   2.503 -    if (!must_field_value_be_encoded(subject)) {
   2.504 -        _subject = strdup(subject);
   2.505 -        assert(_subject);
   2.506 -    }
   2.507 -    else {
   2.508 -        _subject = mailmime_encode_subject_header("utf-8", subject, 1);
   2.509 -    }
   2.510 -    if (_subject == NULL)
   2.511 -        goto enomem;
   2.512 -
   2.513 -    r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
   2.514 -            (_new_func_t) mailimf_subject_new, _subject);
   2.515 -    if (r) {
   2.516 -        free(_subject);
   2.517 -        goto enomem;
   2.518 -    }
   2.519 -
   2.520 -    if (msg->cc) {
   2.521 -        struct mailimf_address_list *cc = identity_list_to_mal(msg->cc);
   2.522 -        if (cc == NULL)
   2.523 -            goto enomem;
   2.524 -
   2.525 -        r = _append_field(fields_list, MAILIMF_FIELD_CC,
   2.526 -                (_new_func_t) mailimf_cc_new, cc);
   2.527 -        if (r) {
   2.528 -            mailimf_address_list_free(cc);
   2.529 -            goto enomem;
   2.530 -        }
   2.531 -    }
   2.532 -    
   2.533 -    if (msg->bcc) {
   2.534 -        struct mailimf_address_list *bcc = identity_list_to_mal(msg->bcc);
   2.535 -        if (bcc == NULL)
   2.536 -            goto enomem;
   2.537 -
   2.538 -        r = _append_field(fields_list, MAILIMF_FIELD_BCC,
   2.539 -                (_new_func_t) mailimf_bcc_new, bcc);
   2.540 -        if (r) {
   2.541 -            mailimf_address_list_free(bcc);
   2.542 -            goto enomem;
   2.543 -        }
   2.544 -    }
   2.545 -    
   2.546 -    if (msg->reply_to) {
   2.547 -        struct mailimf_address_list *reply_to = identity_list_to_mal(msg->reply_to);
   2.548 -        if (reply_to == NULL)
   2.549 -            goto enomem;
   2.550 -
   2.551 -        r = _append_field(fields_list, MAILIMF_FIELD_REPLY_TO,
   2.552 -                (_new_func_t) mailimf_reply_to_new, reply_to);
   2.553 -        if (r) {
   2.554 -            mailimf_address_list_free(reply_to);
   2.555 -            goto enomem;
   2.556 -        }
   2.557 -    }
   2.558 -
   2.559 -    if (msg->in_reply_to) {
   2.560 -        clist *in_reply_to = stringlist_to_clist(msg->in_reply_to, true);
   2.561 -        if (in_reply_to == NULL)
   2.562 -            goto enomem;
   2.563 -
   2.564 -        r = _append_field(fields_list, MAILIMF_FIELD_IN_REPLY_TO,
   2.565 -                (_new_func_t) mailimf_in_reply_to_new, in_reply_to);
   2.566 -        if (r) {
   2.567 -            clist_free(in_reply_to);
   2.568 -            goto enomem;
   2.569 -        }
   2.570 -    }
   2.571 -
   2.572 -    if (msg->references) {
   2.573 -        clist *references = stringlist_to_clist(msg->references, true);
   2.574 -        if (references == NULL)
   2.575 -            goto enomem;
   2.576 -
   2.577 -        r = _append_field(fields_list, MAILIMF_FIELD_REFERENCES,
   2.578 -                (_new_func_t) mailimf_references_new, references);
   2.579 -        if (r) {
   2.580 -            clist_free(references);
   2.581 -            goto enomem;
   2.582 -        }
   2.583 -    }
   2.584 -
   2.585 -    if (msg->keywords) {
   2.586 -        clist *keywords = stringlist_to_clist(msg->keywords, true);
   2.587 -        if (keywords == NULL)
   2.588 -            goto enomem;
   2.589 -
   2.590 -        r = _append_field(fields_list, MAILIMF_FIELD_KEYWORDS,
   2.591 -                (_new_func_t) mailimf_keywords_new, keywords);
   2.592 -        if (r) {
   2.593 -            clist_free(keywords);
   2.594 -            goto enomem;
   2.595 -        }
   2.596 -    }
   2.597 -
   2.598 -    if (msg->comments) {
   2.599 -        char *comments = NULL;
   2.600 -        if (!must_field_value_be_encoded(msg->comments)) {
   2.601 -            comments = strdup(msg->comments);
   2.602 -            assert(comments);
   2.603 -        }
   2.604 -        else  {
   2.605 -            comments = mailmime_encode_subject_header("utf-8", msg->comments, 0);
   2.606 -        }
   2.607 -        if (comments == NULL)
   2.608 -            goto enomem;
   2.609 -
   2.610 -        r = _append_field(fields_list, MAILIMF_FIELD_COMMENTS,
   2.611 -                (_new_func_t) mailimf_comments_new, comments);
   2.612 -        if (r) {
   2.613 -            free(comments);
   2.614 -            goto enomem;
   2.615 -        }
   2.616 -    }
   2.617 -
   2.618 -    if (msg->opt_fields) {
   2.619 -        stringpair_list_t *_l;
   2.620 -        for (_l = msg->opt_fields; _l && _l->value; _l = _l->next) {
   2.621 -            char *key = _l->value->key;
   2.622 -            char *value = _l->value->value;
   2.623 -            if (key && value) {
   2.624 -                r = _append_optional_field(fields_list, key, value);
   2.625 -
   2.626 -                if (r)
   2.627 -                    goto enomem;
   2.628 -            }
   2.629 -        }
   2.630 -    }
   2.631 -
   2.632 -    fields = mailimf_fields_new(fields_list);
   2.633 -    assert(fields);
   2.634 -    if (fields == NULL)
   2.635 -        goto enomem;
   2.636 -
   2.637 -    *result = fields;
   2.638 -
   2.639 -    return PEP_STATUS_OK;
   2.640 -
   2.641 -enomem:
   2.642 -    status = PEP_OUT_OF_MEMORY;
   2.643 -
   2.644 -    if (fields_list)
   2.645 -        clist_free(fields_list);
   2.646 -
   2.647 -    if (fields)
   2.648 -        mailimf_fields_free(fields);
   2.649 -
   2.650 -    return status;
   2.651 -}
   2.652 -
   2.653 -static bool has_exceptional_extension(char* filename) {
   2.654 -    if (!filename)
   2.655 -        return false;
   2.656 -    int len = strlen(filename);
   2.657 -    if (len < 4)
   2.658 -        return false;
   2.659 -    char* ext_start = filename + (len - 4);
   2.660 -    if (strcmp(ext_start, ".pgp") == 0 || strcmp(ext_start, ".gpg") == 0 ||
   2.661 -        strcmp(ext_start, ".asc") == 0 || strcmp(ext_start, ".pEp") == 0)
   2.662 -        return true;
   2.663 -    return false;
   2.664 -}
   2.665 -
   2.666 -static pEp_rid_list_t* choose_resource_id(pEp_rid_list_t* rid_list) {
   2.667 -    pEp_rid_list_t* retval = rid_list;
   2.668 -    
   2.669 -    /* multiple elements - least common case */
   2.670 -    if (rid_list && rid_list->next) {
   2.671 -        pEp_rid_list_t* rid_list_curr = rid_list;
   2.672 -        retval = rid_list; 
   2.673 -        
   2.674 -        while (rid_list_curr) {
   2.675 -            pEp_resource_id_type rid_type = rid_list_curr->rid_type;
   2.676 -            if (rid_type == PEP_RID_CID)
   2.677 -                retval = rid_list_curr;
   2.678 -            else if (rid_type == PEP_RID_FILENAME && has_exceptional_extension(rid_list_curr->rid))
   2.679 -                return rid_list_curr;
   2.680 -            rid_list_curr = rid_list_curr->next;
   2.681 -        }
   2.682 -    } 
   2.683 -    return retval;
   2.684 -}
   2.685 -
   2.686 -// static void split_inlined_and_attached(bloblist_t** inlined, bloblist_t** attached) {
   2.687 -//     bloblist_t** curr_pp = attached;
   2.688 -//     bloblist_t* curr = *curr_pp;
   2.689 -//     
   2.690 -//     bloblist_t* inline_ret = NULL;
   2.691 -//     bloblist_t** inline_curr_pp = &inline_ret;
   2.692 -//     
   2.693 -//     bloblist_t* att_ret = NULL;
   2.694 -//     bloblist_t** att_curr_pp = &att_ret;
   2.695 -//     
   2.696 -//     while (curr) {
   2.697 -//         if (curr->disposition == PEP_CONTENT_DISP_INLINE) {
   2.698 -//             *inline_curr_pp = curr;
   2.699 -//             inline_curr_pp = &(curr->next);
   2.700 -//         }
   2.701 -//         else {
   2.702 -//             *att_curr_pp = curr;
   2.703 -//             att_curr_pp = &(curr->next);            
   2.704 -//         }
   2.705 -//         *curr_pp = curr->next;
   2.706 -//         curr->next = NULL;
   2.707 -//         curr = *curr_pp;
   2.708 -//     }
   2.709 -//     
   2.710 -//     *inlined = inline_ret;
   2.711 -//     *attached = att_ret;
   2.712 -// }
   2.713 -
   2.714 -
   2.715 -static PEP_STATUS mime_encode_message_plain(
   2.716 -        const message *msg,
   2.717 -        bool omit_fields,
   2.718 -        struct mailmime **result,
   2.719 -        bool transport_encode
   2.720 -    )
   2.721 -{
   2.722 -    struct mailmime * mime = NULL;
   2.723 -    struct mailmime * submime = NULL;
   2.724 -    int r;
   2.725 -    PEP_STATUS status;
   2.726 -    //char *subject;
   2.727 -    char *plaintext;
   2.728 -    char *htmltext;
   2.729 -
   2.730 -    assert(msg);
   2.731 -    assert(result);
   2.732 -    
   2.733 -    //subject = (msg->shortmsg) ? msg->shortmsg : "pEp";  // not used, yet.
   2.734 -    plaintext = (msg->longmsg) ? msg->longmsg : "";
   2.735 -    htmltext = msg->longmsg_formatted;
   2.736 -
   2.737 -    if (htmltext && (htmltext[0] != '\0')) {
   2.738 -        /* first, we need to strip out the inlined attachments to ensure this
   2.739 -           gets set up correctly */
   2.740 -           
   2.741 -        status = mime_html_text(plaintext, htmltext, msg->attachments, &mime,
   2.742 -                                transport_encode);
   2.743 -                
   2.744 -        if (status != PEP_STATUS_OK)
   2.745 -            goto pEp_error;
   2.746 -    }
   2.747 -    else {
   2.748 -        pEp_rid_list_t* resource = NULL;
   2.749 -        if (is_PGP_message_text(plaintext)) {
   2.750 -            resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
   2.751 -            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_7BIT : 0);
   2.752 -            mime = get_text_part(resource, "application/octet-stream", plaintext,
   2.753 -                    strlen(plaintext), encoding_type);
   2.754 -        }
   2.755 -        else {
   2.756 -            resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
   2.757 -            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
   2.758 -            mime = get_text_part(resource, "text/plain", plaintext, strlen(plaintext),
   2.759 -                    encoding_type);
   2.760 -        }
   2.761 -        free_rid_list(resource);
   2.762 -        
   2.763 -        assert(mime);
   2.764 -        if (mime == NULL)
   2.765 -            goto enomem;
   2.766 -    }
   2.767 -
   2.768 -    bool normal_attachments = false;
   2.769 -    
   2.770 -    bloblist_t* traversal_ptr = msg->attachments;
   2.771 -    
   2.772 -    while (traversal_ptr) {
   2.773 -        if (traversal_ptr->disposition != PEP_CONTENT_DISP_INLINE) {
   2.774 -            normal_attachments = true;
   2.775 -            break;
   2.776 -        }
   2.777 -        traversal_ptr = traversal_ptr->next;
   2.778 -    }
   2.779 -
   2.780 -    if (normal_attachments) {
   2.781 -        submime = mime;
   2.782 -        mime = part_multiple_new("multipart/mixed");
   2.783 -        assert(mime);
   2.784 -        if (mime == NULL)
   2.785 -            goto enomem;
   2.786 -
   2.787 -        r = mailmime_smart_add_part(mime, submime);
   2.788 -        assert(r == MAILIMF_NO_ERROR);
   2.789 -        if (r == MAILIMF_ERROR_MEMORY) {
   2.790 -            goto enomem;
   2.791 -        }
   2.792 -        else {
   2.793 -            // mailmime_smart_add_part() takes ownership of submime
   2.794 -            submime = NULL;
   2.795 -        }
   2.796 -
   2.797 -        bloblist_t *_a;
   2.798 -        for (_a = msg->attachments; _a != NULL; _a = _a->next) {
   2.799 -
   2.800 -            if (_a->disposition == PEP_CONTENT_DISP_INLINE)
   2.801 -                continue;
   2.802 -
   2.803 -            status = mime_attachment(_a, &submime, transport_encode);
   2.804 -            if (status != PEP_STATUS_OK)
   2.805 -                goto pEp_error;
   2.806 -
   2.807 -            r = mailmime_smart_add_part(mime, submime);
   2.808 -            assert(r == MAILIMF_NO_ERROR);
   2.809 -            if (r == MAILIMF_ERROR_MEMORY) {
   2.810 -                goto enomem;
   2.811 -            }
   2.812 -            else {
   2.813 -                // mailmime_smart_add_part() takes ownership of submime
   2.814 -                submime = NULL;
   2.815 -            }
   2.816 -        }
   2.817 -    }
   2.818 -
   2.819 -    *result = mime;
   2.820 -    return PEP_STATUS_OK;
   2.821 -
   2.822 -enomem:
   2.823 -    status = PEP_OUT_OF_MEMORY;
   2.824 -
   2.825 -pEp_error:
   2.826 -    if (mime)
   2.827 -        mailmime_free(mime);
   2.828 -
   2.829 -    if (submime)
   2.830 -        mailmime_free(submime);
   2.831 -
   2.832 -    return status;
   2.833 -}
   2.834 -
   2.835 -static PEP_STATUS mime_encode_message_PGP_MIME(
   2.836 -        const message * msg,
   2.837 -        bool omit_fields,
   2.838 -        struct mailmime **result
   2.839 -    )
   2.840 -{
   2.841 -    struct mailmime * mime = NULL;
   2.842 -    struct mailmime * submime = NULL;
   2.843 -	struct mailmime_parameter * param;
   2.844 -    int r;
   2.845 -    PEP_STATUS status;
   2.846 -    char *plaintext;
   2.847 -    size_t plaintext_size;
   2.848 -
   2.849 -    assert(msg->attachments && msg->attachments->next &&
   2.850 -            msg->attachments->next->value);
   2.851 -
   2.852 -    plaintext = msg->attachments->next->value;
   2.853 -    plaintext_size = msg->attachments->next->size;
   2.854 -
   2.855 -    mime = part_multiple_new("multipart/encrypted");
   2.856 -    assert(mime);
   2.857 -    if (mime == NULL)
   2.858 -        goto enomem;
   2.859 -
   2.860 -    param = mailmime_param_new_with_data("protocol", "application/pgp-encrypted");
   2.861 -    clist_append(mime->mm_content_type->ct_parameters, param);
   2.862 -
   2.863 -    submime = get_pgp_encrypted_part();
   2.864 -    assert(submime);
   2.865 -    if (submime == NULL)
   2.866 -        goto enomem;
   2.867 -
   2.868 -    r = mailmime_smart_add_part(mime, submime);
   2.869 -    assert(r == MAILIMF_NO_ERROR);
   2.870 -    if (r == MAILIMF_ERROR_MEMORY) {
   2.871 -        goto enomem;
   2.872 -    }
   2.873 -    else {
   2.874 -        // mailmime_smart_add_part() takes ownership of submime
   2.875 -        submime = NULL;
   2.876 -    }
   2.877 -
   2.878 -    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
   2.879 -    submime = get_text_part(resource, "application/octet-stream", plaintext,
   2.880 -            plaintext_size, MAILMIME_MECHANISM_7BIT);
   2.881 -            
   2.882 -    free_rid_list(resource);
   2.883 -    
   2.884 -    assert(submime);
   2.885 -    if (submime == NULL)
   2.886 -        goto enomem;
   2.887 -
   2.888 -    r = mailmime_smart_add_part(mime, submime);
   2.889 -    assert(r == MAILIMF_NO_ERROR);
   2.890 -    if (r == MAILIMF_ERROR_MEMORY) {
   2.891 -        goto enomem;
   2.892 -    }
   2.893 -    else {
   2.894 -        // mailmime_smart_add_part() takes ownership of submime
   2.895 -        submime = NULL;
   2.896 -    }
   2.897 -
   2.898 -    *result = mime;
   2.899 -    return PEP_STATUS_OK;
   2.900 -
   2.901 -enomem:
   2.902 -    status = PEP_OUT_OF_MEMORY;
   2.903 -
   2.904 -    if (mime)
   2.905 -        mailmime_free(mime);
   2.906 -
   2.907 -    if (submime)
   2.908 -        mailmime_free(submime);
   2.909 -
   2.910 -    return status;
   2.911 -}
   2.912 -
   2.913 -DYNAMIC_API PEP_STATUS mime_encode_message(
   2.914 -        const message * msg,
   2.915 -        bool omit_fields,
   2.916 -        char **mimetext
   2.917 -    )
   2.918 -{
   2.919 -    return _mime_encode_message_internal(msg, omit_fields, mimetext, true);
   2.920 -}
   2.921 -
   2.922 -PEP_STATUS _mime_encode_message_internal(
   2.923 -        const message * msg,
   2.924 -        bool omit_fields,
   2.925 -        char **mimetext,
   2.926 -        bool transport_encode
   2.927 -    )
   2.928 -{
   2.929 -    PEP_STATUS status = PEP_STATUS_OK;
   2.930 -    struct mailmime * msg_mime = NULL;
   2.931 -    struct mailmime * mime = NULL;
   2.932 -    struct mailimf_fields * fields = NULL;
   2.933 -    char *buf = NULL;
   2.934 -    int r;
   2.935 -
   2.936 -    assert(msg);
   2.937 -    assert(mimetext);
   2.938 -
   2.939 -    if (!(msg && mimetext))
   2.940 -        return PEP_ILLEGAL_VALUE;
   2.941 -
   2.942 -    *mimetext = NULL;
   2.943 -
   2.944 -    switch (msg->enc_format) {
   2.945 -        case PEP_enc_none:
   2.946 -            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
   2.947 -            break;
   2.948 -
   2.949 -        case PEP_enc_pieces:
   2.950 -            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode);
   2.951 -            break;
   2.952 -
   2.953 -        case PEP_enc_S_MIME:
   2.954 -            NOT_IMPLEMENTED
   2.955 -                
   2.956 -        case PEP_enc_PGP_MIME:
   2.957 -            status = mime_encode_message_PGP_MIME(msg, omit_fields, &mime);
   2.958 -            break;
   2.959 -
   2.960 -        case PEP_enc_PEP:
   2.961 -            NOT_IMPLEMENTED
   2.962 -
   2.963 -        default:
   2.964 -            NOT_IMPLEMENTED
   2.965 -    }
   2.966 -
   2.967 -    if (status != PEP_STATUS_OK)
   2.968 -        goto pEp_error;
   2.969 -
   2.970 -    msg_mime = mailmime_new_message_data(NULL);
   2.971 -    assert(msg_mime);
   2.972 -    if (msg_mime == NULL)
   2.973 -        goto enomem;
   2.974 -
   2.975 -    r = mailmime_add_part(msg_mime, mime);
   2.976 -    if (r) {
   2.977 -        mailmime_free(mime);
   2.978 -        goto enomem;
   2.979 -    }
   2.980 -    mime = NULL;
   2.981 -
   2.982 -    if (!omit_fields) {
   2.983 -        status = build_fields(msg, &fields);
   2.984 -        if (status != PEP_STATUS_OK)
   2.985 -            goto pEp_error;
   2.986 -
   2.987 -        mailmime_set_imf_fields(msg_mime, fields);
   2.988 -    }
   2.989 -
   2.990 -    status = render_mime(msg_mime, &buf);
   2.991 -    if (status != PEP_STATUS_OK)
   2.992 -        goto pEp_error;
   2.993 -
   2.994 -    mailmime_free(msg_mime);
   2.995 -    *mimetext = buf;
   2.996 -
   2.997 -    return PEP_STATUS_OK;
   2.998 -
   2.999 -enomem:
  2.1000 -    status = PEP_OUT_OF_MEMORY;
  2.1001 -
  2.1002 -pEp_error:
  2.1003 -    if (msg_mime)
  2.1004 -        mailmime_free(msg_mime);
  2.1005 -    else
  2.1006 -        if (mime)
  2.1007 -            mailmime_free(mime);
  2.1008 -
  2.1009 -    return status;
  2.1010 -}
  2.1011 -
  2.1012 -static pEp_identity *mailbox_to_identity(const struct mailimf_mailbox * mb)
  2.1013 -{
  2.1014 -    char *username = NULL;
  2.1015 -
  2.1016 -    assert(mb);
  2.1017 -    assert(mb->mb_addr_spec);
  2.1018 -
  2.1019 -    if (mb->mb_addr_spec == NULL)
  2.1020 -        return NULL;
  2.1021 -
  2.1022 -    if (mb->mb_display_name) {
  2.1023 -        size_t index = 0;
  2.1024 -        const int r = mailmime_encoded_phrase_parse("utf-8", mb->mb_display_name,
  2.1025 -                strlen(mb->mb_display_name), &index, "utf-8", &username);
  2.1026 -        if (r)
  2.1027 -            goto enomem;
  2.1028 -    }
  2.1029 -
  2.1030 -    pEp_identity *ident = new_identity(mb->mb_addr_spec, NULL, NULL, username);
  2.1031 -    if (ident == NULL)
  2.1032 -        goto enomem;
  2.1033 -    free(username);
  2.1034 -
  2.1035 -    return ident;
  2.1036 -
  2.1037 -enomem:
  2.1038 -    free(username);
  2.1039 -    return NULL;
  2.1040 -}
  2.1041 -
  2.1042 -static pEp_identity * mbl_to_identity(const struct mailimf_mailbox_list * mbl)
  2.1043 -{
  2.1044 -    struct mailimf_mailbox * mb = clist_content(clist_begin(mbl->mb_list));
  2.1045 -    return mailbox_to_identity(mb);
  2.1046 -}
  2.1047 -
  2.1048 -static identity_list * mal_to_identity_list(
  2.1049 -        const struct mailimf_address_list *mal
  2.1050 -    )
  2.1051 -{
  2.1052 -    assert(mal);
  2.1053 -    clist *list = mal->ad_list;
  2.1054 -
  2.1055 -    identity_list *il = new_identity_list(NULL);
  2.1056 -    if (il == NULL)
  2.1057 -        goto enomem;
  2.1058 -
  2.1059 -    identity_list *_il = il;
  2.1060 -    for (clistiter *cur = clist_begin(list); cur != NULL ; cur = clist_next(cur)) {
  2.1061 -        pEp_identity *ident;
  2.1062 -
  2.1063 -        struct mailimf_address *addr = clist_content(cur);
  2.1064 -        switch(addr->ad_type) {
  2.1065 -            case MAILIMF_ADDRESS_MAILBOX:
  2.1066 -                ident = mailbox_to_identity(addr->ad_data.ad_mailbox);
  2.1067 -                if (ident == NULL)
  2.1068 -                    goto enomem;
  2.1069 -                _il = identity_list_add(_il, ident);
  2.1070 -                if (_il == NULL)
  2.1071 -                    goto enomem;
  2.1072 -                break;
  2.1073 -
  2.1074 -            case MAILIMF_ADDRESS_GROUP:
  2.1075 -                {
  2.1076 -                    struct mailimf_mailbox_list * mbl =
  2.1077 -                            addr->ad_data.ad_group->grp_mb_list;
  2.1078 -                    for (clistiter *cur2 = clist_begin(mbl->mb_list); cur2 != NULL;
  2.1079 -                            cur2 = clist_next(cur2)) {
  2.1080 -                        ident = mailbox_to_identity(clist_content(cur));
  2.1081 -                        if (ident == NULL)
  2.1082 -                            goto enomem;
  2.1083 -                        _il = identity_list_add(_il, ident);
  2.1084 -                        if (_il == NULL)
  2.1085 -                            goto enomem;
  2.1086 -                    }
  2.1087 -                }
  2.1088 -                break;
  2.1089 -
  2.1090 -            default:
  2.1091 -                assert(0);
  2.1092 -                goto enomem;
  2.1093 -        }
  2.1094 -    }
  2.1095 -
  2.1096 -    return il;
  2.1097 -
  2.1098 -enomem:
  2.1099 -    free_identity_list(il);
  2.1100 -    return NULL;
  2.1101 -}
  2.1102 -
  2.1103 -static stringlist_t * clist_to_stringlist(const clist *list)
  2.1104 -{
  2.1105 -    char *text = NULL;;
  2.1106 -    stringlist_t * sl = new_stringlist(NULL);
  2.1107 -    if (sl == NULL)
  2.1108 -        return NULL;
  2.1109 -
  2.1110 -    stringlist_t *_sl = sl;
  2.1111 -    for (clistiter *cur = clist_begin(list); cur != NULL; cur = clist_next(cur)) {
  2.1112 -        char *phrase = clist_content(cur);
  2.1113 -        size_t index = 0;
  2.1114 -        
  2.1115 -        const int r = mailmime_encoded_phrase_parse("utf-8", phrase, strlen(phrase),
  2.1116 -                &index, "utf-8", &text);
  2.1117 -        if (r)
  2.1118 -            goto enomem;
  2.1119 -
  2.1120 -        _sl = stringlist_add(_sl, text);
  2.1121 -        if (_sl == NULL)
  2.1122 -            goto enomem;
  2.1123 -
  2.1124 -        free(text);
  2.1125 -        text = NULL;
  2.1126 -    }
  2.1127 -
  2.1128 -    return sl;
  2.1129 -
  2.1130 -enomem:
  2.1131 -    free_stringlist(sl);
  2.1132 -    free(text);
  2.1133 -
  2.1134 -    return NULL;
  2.1135 -}
  2.1136 -
  2.1137 -static PEP_STATUS read_fields(message *msg, clist *fieldlist)
  2.1138 -{
  2.1139 -    PEP_STATUS status = PEP_STATUS_OK;
  2.1140 -    struct mailimf_field * _field;
  2.1141 -    clistiter *cur;
  2.1142 -    size_t index;
  2.1143 -    int r;
  2.1144 -    
  2.1145 -    stringpair_list_t *opt = msg->opt_fields;
  2.1146 -
  2.1147 -    if (!fieldlist)
  2.1148 -        return PEP_STATUS_OK;
  2.1149 -        
  2.1150 -    for (cur = clist_begin(fieldlist); cur != NULL; cur = clist_next(cur)) {
  2.1151 -        _field = clist_content(cur);
  2.1152 -
  2.1153 -        switch (_field->fld_type) {
  2.1154 -            case MAILIMF_FIELD_MESSAGE_ID:
  2.1155 -                {
  2.1156 -                    char * text = _field->fld_data.fld_message_id->mid_value;
  2.1157 -
  2.1158 -                    free(msg->id);
  2.1159 -                    index = 0;
  2.1160 -                    r = mailmime_encoded_phrase_parse("utf-8", text,
  2.1161 -                            strlen(text), &index, "utf-8", &msg->id);
  2.1162 -                    if (r)
  2.1163 -                        goto enomem;
  2.1164 -                }
  2.1165 -                break;
  2.1166 -
  2.1167 -            case MAILIMF_FIELD_SUBJECT:
  2.1168 -                {
  2.1169 -                    char * text = _field->fld_data.fld_subject->sbj_value;
  2.1170 -
  2.1171 -                    free(msg->shortmsg);
  2.1172 -                    index = 0;
  2.1173 -                    r = mailmime_encoded_phrase_parse("utf-8", text,
  2.1174 -                            strlen(text), &index, "utf-8", &msg->shortmsg);
  2.1175 -                    if (r)
  2.1176 -                        goto enomem;
  2.1177 -                }
  2.1178 -                break;
  2.1179 -
  2.1180 -            case MAILIMF_FIELD_ORIG_DATE:
  2.1181 -                {
  2.1182 -                    struct mailimf_date_time *date =
  2.1183 -                        _field->fld_data.fld_orig_date->dt_date_time;
  2.1184 -
  2.1185 -                    free_timestamp(msg->sent);
  2.1186 -                    msg->sent = etpantime_to_timestamp(date);
  2.1187 -                    if (msg->sent == NULL)
  2.1188 -                        goto enomem;
  2.1189 -                }
  2.1190 -                break;
  2.1191 -
  2.1192 -            case MAILIMF_FIELD_FROM:
  2.1193 -                {
  2.1194 -                    struct mailimf_mailbox_list *mbl =
  2.1195 -                            _field->fld_data.fld_from->frm_mb_list;
  2.1196 -                    pEp_identity *ident;
  2.1197 -
  2.1198 -                    ident = mbl_to_identity(mbl);
  2.1199 -                    if (ident == NULL)
  2.1200 -                        goto pEp_error;
  2.1201 -
  2.1202 -                    free_identity(msg->from);
  2.1203 -                    msg->from = ident;
  2.1204 -                }
  2.1205 -                break;
  2.1206 -
  2.1207 -            case MAILIMF_FIELD_TO:
  2.1208 -                {
  2.1209 -                    struct mailimf_address_list *mal =
  2.1210 -                            _field->fld_data.fld_to->to_addr_list;
  2.1211 -                    identity_list *il = mal_to_identity_list(mal);
  2.1212 -                    if (il == NULL)
  2.1213 -                        goto enomem;
  2.1214 -
  2.1215 -                    free_identity_list(msg->to);
  2.1216 -                    msg->to = il;
  2.1217 -                }
  2.1218 -                break;
  2.1219 -
  2.1220 -            case MAILIMF_FIELD_CC:
  2.1221 -                {
  2.1222 -                    struct mailimf_address_list *mal =
  2.1223 -                            _field->fld_data.fld_cc->cc_addr_list;
  2.1224 -                    identity_list *il = mal_to_identity_list(mal);
  2.1225 -                    if (il == NULL)
  2.1226 -                        goto enomem;
  2.1227 -
  2.1228 -                    free_identity_list(msg->cc);
  2.1229 -                    msg->cc = il;
  2.1230 -                }
  2.1231 -                break;
  2.1232 -
  2.1233 -            case MAILIMF_FIELD_BCC:
  2.1234 -                {
  2.1235 -                    struct mailimf_address_list *mal =
  2.1236 -                            _field->fld_data.fld_bcc->bcc_addr_list;
  2.1237 -                    identity_list *il = mal_to_identity_list(mal);
  2.1238 -                    if (il == NULL)
  2.1239 -                        goto enomem;
  2.1240 -
  2.1241 -                    free_identity_list(msg->bcc);
  2.1242 -                    msg->bcc = il;
  2.1243 -                }
  2.1244 -                break;
  2.1245 -
  2.1246 -            case MAILIMF_FIELD_REPLY_TO:
  2.1247 -                {
  2.1248 -                    struct mailimf_address_list *mal =
  2.1249 -                            _field->fld_data.fld_reply_to->rt_addr_list;
  2.1250 -                    identity_list *il = mal_to_identity_list(mal);
  2.1251 -                    if (il == NULL)
  2.1252 -                        goto enomem;
  2.1253 -
  2.1254 -                    free_identity_list(msg->reply_to);
  2.1255 -                    msg->reply_to = il;
  2.1256 -                }
  2.1257 -                break;
  2.1258 -
  2.1259 -            case MAILIMF_FIELD_IN_REPLY_TO:
  2.1260 -                {
  2.1261 -                    clist *list = _field->fld_data.fld_in_reply_to->mid_list;
  2.1262 -                    stringlist_t *sl = clist_to_stringlist(list);
  2.1263 -                    if (sl == NULL)
  2.1264 -                        goto enomem;
  2.1265 -
  2.1266 -                    free_stringlist(msg->in_reply_to);
  2.1267 -                    msg->in_reply_to = sl;
  2.1268 -                }
  2.1269 -                break;
  2.1270 -
  2.1271 -            case MAILIMF_FIELD_REFERENCES:
  2.1272 -                {
  2.1273 -                    clist *list = _field->fld_data.fld_references->mid_list;
  2.1274 -                    stringlist_t *sl = clist_to_stringlist(list);
  2.1275 -                    if (sl == NULL)
  2.1276 -                        goto enomem;
  2.1277 -
  2.1278 -                    free_stringlist(msg->references);
  2.1279 -                    msg->references = sl;
  2.1280 -                }
  2.1281 -                break;
  2.1282 -
  2.1283 -            case MAILIMF_FIELD_KEYWORDS:
  2.1284 -                {
  2.1285 -                    clist *list = _field->fld_data.fld_keywords->kw_list;
  2.1286 -                    stringlist_t *sl = clist_to_stringlist(list);
  2.1287 -                    if (sl == NULL)
  2.1288 -                        goto enomem;
  2.1289 -
  2.1290 -                    free_stringlist(msg->keywords);
  2.1291 -                    msg->keywords = sl;
  2.1292 -                }
  2.1293 -                break;
  2.1294 -
  2.1295 -            case MAILIMF_FIELD_COMMENTS:
  2.1296 -                {
  2.1297 -                    char * text = _field->fld_data.fld_comments->cm_value;
  2.1298 -
  2.1299 -                    free(msg->comments);
  2.1300 -                    index = 0;
  2.1301 -                    r = mailmime_encoded_phrase_parse("utf-8", text,
  2.1302 -                            strlen(text), &index, "utf-8", &msg->comments);
  2.1303 -                    if (r)
  2.1304 -                        goto enomem;
  2.1305 -                }
  2.1306 -                break;
  2.1307 -
  2.1308 -            case MAILIMF_FIELD_OPTIONAL_FIELD:
  2.1309 -                {
  2.1310 -                    char * name =
  2.1311 -                            _field->fld_data.fld_optional_field->fld_name;
  2.1312 -                    char * value =
  2.1313 -                            _field->fld_data.fld_optional_field->fld_value;
  2.1314 -                    char *_value;
  2.1315 -
  2.1316 -                    index = 0;
  2.1317 -                    r = mailmime_encoded_phrase_parse("utf-8", value,
  2.1318 -                            strlen(value), &index, "utf-8", &_value);
  2.1319 -                    if (r)
  2.1320 -                        goto enomem;
  2.1321 -
  2.1322 -                    stringpair_t *pair = new_stringpair(name, _value);
  2.1323 -                    if (pair == NULL)
  2.1324 -                        goto enomem;
  2.1325 -
  2.1326 -                    opt = stringpair_list_add(opt, pair);
  2.1327 -                    free(_value);
  2.1328 -                    if (opt == NULL)
  2.1329 -                        goto enomem;
  2.1330 -
  2.1331 -                    if (msg->opt_fields == NULL)
  2.1332 -                        msg->opt_fields = opt;
  2.1333 -                }
  2.1334 -                break;
  2.1335 -        }
  2.1336 -    }
  2.1337 -    
  2.1338 -    return PEP_STATUS_OK;
  2.1339 -
  2.1340 -enomem:
  2.1341 -    status = PEP_OUT_OF_MEMORY;
  2.1342 -
  2.1343 -pEp_error:
  2.1344 -    return status;
  2.1345 -}
  2.1346 -
  2.1347 -static PEP_STATUS interpret_body(struct mailmime *part, char **longmsg, size_t *size)
  2.1348 -{
  2.1349 -    const char *text;
  2.1350 -    char *_longmsg;
  2.1351 -    size_t length;
  2.1352 -    size_t _size;
  2.1353 -    size_t index;
  2.1354 -    char *type = NULL;
  2.1355 -    char *charset = NULL;
  2.1356 -
  2.1357 -    assert(part);
  2.1358 -    assert(longmsg);
  2.1359 -
  2.1360 -    *longmsg = NULL;
  2.1361 -    if (size)
  2.1362 -        *size = 0;
  2.1363 -
  2.1364 -    if (part->mm_body == NULL)
  2.1365 -        return PEP_ILLEGAL_VALUE;
  2.1366 -
  2.1367 -    text = part->mm_body-> dt_data.dt_text.dt_data;
  2.1368 -    if (text == NULL)
  2.1369 -        return PEP_ILLEGAL_VALUE;
  2.1370 -
  2.1371 -    length = part->mm_body->dt_data.dt_text.dt_length;
  2.1372 -
  2.1373 -    if (part->mm_body->dt_encoded) {
  2.1374 -        int code = part->mm_body->dt_encoding;
  2.1375 -        index = 0;
  2.1376 -        int r = mailmime_part_parse(text, length, &index, code, &_longmsg, &_size);
  2.1377 -        switch (r) {
  2.1378 -            case MAILIMF_NO_ERROR:
  2.1379 -                break;
  2.1380 -            case MAILIMF_ERROR_MEMORY:
  2.1381 -                return PEP_OUT_OF_MEMORY;
  2.1382 -            default:
  2.1383 -                return PEP_ILLEGAL_VALUE;
  2.1384 -        }
  2.1385 -    }
  2.1386 -    else {
  2.1387 -        _size = length + 1;
  2.1388 -        _longmsg = strndup(text, length);
  2.1389 -        if (_longmsg == NULL)
  2.1390 -            return PEP_OUT_OF_MEMORY;
  2.1391 -    }
  2.1392 -
  2.1393 -    if (part->mm_content_type) {
  2.1394 -        if (_get_content_type(part->mm_content_type, &type, &charset) == 0) {
  2.1395 -            if (charset && strncasecmp(charset, "utf-8", 5) != 0) {
  2.1396 -                char * _text;
  2.1397 -                int r = charconv("utf-8", charset, _longmsg, _size, &_text);
  2.1398 -                switch (r) {
  2.1399 -                    case MAILIMF_NO_ERROR:
  2.1400 -                        break;
  2.1401 -                    case MAILIMF_ERROR_MEMORY:
  2.1402 -                        return PEP_OUT_OF_MEMORY;
  2.1403 -                    default:
  2.1404 -                        return PEP_ILLEGAL_VALUE;
  2.1405 -                }
  2.1406 -                free(_longmsg);
  2.1407 -                _longmsg = _text;
  2.1408 -            }
  2.1409 -        }
  2.1410 -    }
  2.1411 -    // FIXME: KG - we now have the text we want.
  2.1412 -    // Now we need to strip sigs and process them if they are there..
  2.1413 -    
  2.1414 -
  2.1415 -    *longmsg = _longmsg;
  2.1416 -    if (size)
  2.1417 -        *size = _size;
  2.1418 -
  2.1419 -    return PEP_STATUS_OK;
  2.1420 -}
  2.1421 -
  2.1422 -// THIS IS A BEST-EFFORT ONLY FUNCTION, AND WE ARE NOT DOING MORE THAN THE
  2.1423 -// SUBJECT FOR NOW.
  2.1424 -static PEP_STATUS interpret_protected_headers(
  2.1425 -        struct mailmime* mime, 
  2.1426 -        message* msg
  2.1427 -    )
  2.1428 -{
  2.1429 -    // N.B. this is *very much* enigmail output specific, and right now,
  2.1430 -    // we only care about subject replacement.
  2.1431 -    const char* header_string = "Content-Type: text/rfc822-headers; protected-headers=\"v1\"\nContent-Disposition: inline\n\n";
  2.1432 -    size_t content_length = mime->mm_length;
  2.1433 -    size_t header_strlen = strlen(header_string);
  2.1434 -    if (header_strlen < content_length) {
  2.1435 -        const char* headerblock = mime->mm_mime_start;
  2.1436 -        size_t subject_len = 0;
  2.1437 -        headerblock = strstr(headerblock, header_string);
  2.1438 -        if (headerblock) {
  2.1439 -            const char* subj_start = "Subject: ";
  2.1440 -            headerblock = strstr(headerblock, subj_start);
  2.1441 -            if (headerblock) {
  2.1442 -                size_t subj_len = strlen(subj_start);
  2.1443 -                headerblock += subj_len;
  2.1444 -                char* end_pt = strstr(headerblock, "\n");
  2.1445 -                if (end_pt) {
  2.1446 -                    if (end_pt != mime->mm_mime_start && *(end_pt - 1) == '\r')
  2.1447 -                        end_pt--;
  2.1448 -                    subject_len = end_pt - headerblock;
  2.1449 -                    char* new_subj = (char*)calloc(subject_len + 1, 1);
  2.1450 -                    if (new_subj) {
  2.1451 -                        strlcpy(new_subj, headerblock, subject_len + 1);
  2.1452 -                        free(msg->shortmsg);
  2.1453 -                        msg->shortmsg = new_subj;
  2.1454 -                    }    
  2.1455 -                } // if there's no endpoint, there's something wrong here so we ignore all
  2.1456 -                  // This is best effort.
  2.1457 -            }
  2.1458 -        }
  2.1459 -    }
  2.1460 -    return PEP_STATUS_OK;
  2.1461 -}
  2.1462 -
  2.1463 -// ONLY for main part!!!
  2.1464 -static PEP_STATUS process_multipart_related(struct mailmime *mime,
  2.1465 -                                            message *msg) {
  2.1466 -    PEP_STATUS status = PEP_STATUS_OK;
  2.1467 -
  2.1468 -    assert(mime);
  2.1469 -    assert(msg);
  2.1470 -
  2.1471 -    clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;                                                
  2.1472 -
  2.1473 -    if (partlist == NULL)
  2.1474 -        return PEP_ILLEGAL_VALUE;
  2.1475 -
  2.1476 -    clistiter *cur = clist_begin(partlist);
  2.1477 -    struct mailmime *part = clist_content(cur);
  2.1478 -    
  2.1479 -    if (part == NULL)
  2.1480 -        return PEP_ILLEGAL_VALUE;
  2.1481 -
  2.1482 -    struct mailmime_content *content = part->mm_content_type;    
  2.1483 -    assert(content);
  2.1484 -    
  2.1485 -    if (content == NULL)
  2.1486 -        return PEP_ILLEGAL_VALUE;
  2.1487 -
  2.1488 -    if (_is_text_part(content, "html")) {
  2.1489 -        status = interpret_body(part, &msg->longmsg_formatted,
  2.1490 -                NULL);
  2.1491 -        if (status)
  2.1492 -            return status;
  2.1493 -    }
  2.1494 -    else {
  2.1495 -        // ???
  2.1496 -        // This is what we would have done before, so... no
  2.1497 -        // worse than the status quo. But FIXME!
  2.1498 -        status = interpret_MIME(part, msg);
  2.1499 -        if (status)
  2.1500 -            return status;
  2.1501 -    }
  2.1502 -    
  2.1503 -    for (cur = clist_next(cur); cur; cur = clist_next(cur)) {
  2.1504 -        part = clist_content(cur);
  2.1505 -        if (part == NULL)
  2.1506 -            return PEP_ILLEGAL_VALUE;
  2.1507 -
  2.1508 -        content = part->mm_content_type;
  2.1509 -        assert(content);
  2.1510 -        if (content == NULL)
  2.1511 -            return PEP_ILLEGAL_VALUE;
  2.1512 -
  2.1513 -        status = interpret_MIME(part, msg);
  2.1514 -        if (status)
  2.1515 -            return status;
  2.1516 -    }
  2.1517 -    return status;
  2.1518 -}
  2.1519 -
  2.1520 -static PEP_STATUS interpret_MIME(
  2.1521 -        struct mailmime *mime,
  2.1522 -        message *msg
  2.1523 -    )
  2.1524 -{
  2.1525 -    PEP_STATUS status = PEP_STATUS_OK;
  2.1526 -
  2.1527 -    assert(mime);
  2.1528 -    assert(msg);
  2.1529 -
  2.1530 -    struct mailmime_content *content = mime->mm_content_type;
  2.1531 -    if (content) {
  2.1532 -        if (_is_multipart(content, "alternative")) {
  2.1533 -            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
  2.1534 -            if (partlist == NULL)
  2.1535 -                return PEP_ILLEGAL_VALUE;
  2.1536 -
  2.1537 -            clistiter *cur;
  2.1538 -            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
  2.1539 -                struct mailmime *part = clist_content(cur);
  2.1540 -                if (part == NULL)
  2.1541 -                    return PEP_ILLEGAL_VALUE;
  2.1542 -
  2.1543 -                content = part->mm_content_type;
  2.1544 -                assert(content);
  2.1545 -                if (content == NULL)
  2.1546 -                    return PEP_ILLEGAL_VALUE;
  2.1547 -
  2.1548 -                if (_is_text_part(content, "plain") && msg->longmsg == NULL) {
  2.1549 -                    status = interpret_body(part, &msg->longmsg, NULL);
  2.1550 -                    if (status)
  2.1551 -                        return status;
  2.1552 -                }
  2.1553 -                else if (_is_text_part(content, "rfc822-headers")) {
  2.1554 -                    status = interpret_protected_headers(part, msg);
  2.1555 -                    if (status)
  2.1556 -                        return status;
  2.1557 -                }
  2.1558 -                else if (_is_text_part(content, "html") &&
  2.1559 -                        msg->longmsg_formatted == NULL) {
  2.1560 -                    status = interpret_body(part, &msg->longmsg_formatted,
  2.1561 -                            NULL);
  2.1562 -                    if (status)
  2.1563 -                        return status;
  2.1564 -                }
  2.1565 -                else if (_is_multipart(content, "related") && 
  2.1566 -                    msg->longmsg_formatted == NULL) {
  2.1567 -                    status = process_multipart_related(part, msg);
  2.1568 -                    if (status)
  2.1569 -                        return status;
  2.1570 -                }
  2.1571 -                else /* add as attachment */ {
  2.1572 -                    status = interpret_MIME(part, msg);
  2.1573 -                    if (status)
  2.1574 -                        return status;
  2.1575 -                }
  2.1576 -            }
  2.1577 -        }
  2.1578 -        else if (_is_multipart(content, "encrypted")) {
  2.1579 -            if (msg->longmsg == NULL)
  2.1580 -                msg->longmsg = strdup("");
  2.1581 -            assert(msg->longmsg);
  2.1582 -            if (!msg->longmsg)
  2.1583 -                return PEP_OUT_OF_MEMORY;
  2.1584 -
  2.1585 -            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
  2.1586 -            if (partlist == NULL)
  2.1587 -                return PEP_ILLEGAL_VALUE;
  2.1588 -
  2.1589 -            clistiter *cur;
  2.1590 -            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
  2.1591 -                struct mailmime *part= clist_content(cur);
  2.1592 -                if (part == NULL)
  2.1593 -                    return PEP_ILLEGAL_VALUE;
  2.1594 -
  2.1595 -                status = interpret_MIME(part, msg);
  2.1596 -                if (status != PEP_STATUS_OK)
  2.1597 -                    return status;
  2.1598 -            }
  2.1599 -        }
  2.1600 -        else if (_is_multipart(content, NULL)) {
  2.1601 -            clist *partlist = mime->mm_data.mm_multipart.mm_mp_list;
  2.1602 -            if (partlist == NULL)
  2.1603 -                return PEP_ILLEGAL_VALUE;
  2.1604 -
  2.1605 -            clistiter *cur;
  2.1606 -            for (cur = clist_begin(partlist); cur; cur = clist_next(cur)) {
  2.1607 -                struct mailmime *part= clist_content(cur);
  2.1608 -                if (part == NULL)
  2.1609 -                    return PEP_ILLEGAL_VALUE;
  2.1610 -                status = interpret_MIME(part, msg);
  2.1611 -                if (status != PEP_STATUS_OK)
  2.1612 -                    return status;
  2.1613 -            }
  2.1614 -        }
  2.1615 -        else {
  2.1616 -            if (_is_text_part(content, "html") &&
  2.1617 -                msg->longmsg_formatted == NULL &&
  2.1618 -                msg->longmsg == NULL) {
  2.1619 -                status = interpret_body(mime, &msg->longmsg_formatted,
  2.1620 -                                        NULL);
  2.1621 -                if (status)
  2.1622 -                    return status;
  2.1623 -            }
  2.1624 -            else if (_is_text_part(content, "rfc822-headers")) {
  2.1625 -                status = interpret_protected_headers(mime, msg);
  2.1626 -                if (status)
  2.1627 -                    return status;
  2.1628 -            }
  2.1629 -            else if (_is_text_part(content, "plain") && 
  2.1630 -                     msg->longmsg == NULL && msg->longmsg_formatted == NULL) {
  2.1631 -                status = interpret_body(mime, &msg->longmsg, NULL);
  2.1632 -                if (status)
  2.1633 -                    return status;
  2.1634 -            }            
  2.1635 -            else if (_is_text_part(content, NULL) && 
  2.1636 -                     !_is_text_part(content, "plain") &&
  2.1637 -                     msg->longmsg == NULL) {
  2.1638 -                status = interpret_body(mime, &msg->longmsg, NULL);
  2.1639 -                if (status)
  2.1640 -                    return status;
  2.1641 -            }
  2.1642 -            else {
  2.1643 -                char *data = NULL;
  2.1644 -                size_t size = 0;
  2.1645 -                char * mime_type;
  2.1646 -                char * charset;
  2.1647 -                char * filename;
  2.1648 -                int r;
  2.1649 -
  2.1650 -                r = _get_content_type(content, &mime_type, &charset);
  2.1651 -                switch (r) {
  2.1652 -                    case 0:
  2.1653 -                        break;
  2.1654 -                    case EINVAL:
  2.1655 -                        return PEP_ILLEGAL_VALUE;
  2.1656 -                    case ENOMEM:
  2.1657 -                        return PEP_OUT_OF_MEMORY;
  2.1658 -                    default:
  2.1659 -                        return PEP_UNKNOWN_ERROR;
  2.1660 -                }
  2.1661 -
  2.1662 -                assert(mime_type);
  2.1663 -
  2.1664 -                status = interpret_body(mime, &data, &size);
  2.1665 -                if (status)
  2.1666 -                    return status;
  2.1667 -
  2.1668 -                pEp_rid_list_t* resource_id_list = _get_resource_id_list(mime);
  2.1669 -                pEp_rid_list_t* chosen_resource_id = choose_resource_id(resource_id_list);
  2.1670 -                
  2.1671 -                //filename = _get_filename_or_cid(mime);
  2.1672 -                char *_filename = NULL;
  2.1673 -                
  2.1674 -                if (chosen_resource_id) {
  2.1675 -                    filename = chosen_resource_id->rid;
  2.1676 -                    size_t index = 0;
  2.1677 -                    /* NOTA BENE */
  2.1678 -                    /* The prefix we just added shouldn't be a problem - this is about decoding %XX (RFC 2392) */
  2.1679 -                    /* If it becomes one, we have some MESSY fixing to do. :(                                  */
  2.1680 -                    r = mailmime_encoded_phrase_parse("utf-8", filename,
  2.1681 -                            strlen(filename), &index, "utf-8", &_filename);
  2.1682 -                    if (r) {
  2.1683 -                        goto enomem;
  2.1684 -                    }
  2.1685 -                    char* file_prefix = NULL;
  2.1686 -                    
  2.1687 -                    /* in case there are others later */
  2.1688 -                    switch (chosen_resource_id->rid_type) {
  2.1689 -                        case PEP_RID_CID:
  2.1690 -                            file_prefix = "cid";
  2.1691 -                            break;
  2.1692 -                        case PEP_RID_FILENAME:
  2.1693 -                            file_prefix = "file";
  2.1694 -                            break;
  2.1695 -                        default:
  2.1696 -                            break;
  2.1697 -                    }
  2.1698 -
  2.1699 -                    
  2.1700 -                    if (file_prefix) {
  2.1701 -                        filename = build_uri(file_prefix, _filename);
  2.1702 -                        free(_filename);
  2.1703 -                        _filename = filename;
  2.1704 -                    }
  2.1705 -                }
  2.1706 -
  2.1707 -                bloblist_t *_a = bloblist_add(msg->attachments, data, size,
  2.1708 -                        mime_type, _filename);
  2.1709 -                free(_filename);
  2.1710 -                free_rid_list(resource_id_list);
  2.1711 -                resource_id_list = NULL;
  2.1712 -                if (_a == NULL)
  2.1713 -                    return PEP_OUT_OF_MEMORY;
  2.1714 -                if (msg->attachments == NULL)
  2.1715 -                    msg->attachments = _a;
  2.1716 -            }
  2.1717 -        }
  2.1718 -    }
  2.1719 -
  2.1720 -    return PEP_STATUS_OK;
  2.1721 -
  2.1722 -enomem:
  2.1723 -    return PEP_OUT_OF_MEMORY;
  2.1724 -}
  2.1725 -
  2.1726 -DYNAMIC_API PEP_STATUS mime_decode_message(
  2.1727 -        const char *mimetext,
  2.1728 -        size_t size,
  2.1729 -        message **msg
  2.1730 -    )
  2.1731 -{
  2.1732 -    PEP_STATUS status = PEP_STATUS_OK;
  2.1733 -    struct mailmime * mime = NULL;
  2.1734 -    int r;
  2.1735 -    message *_msg = NULL;
  2.1736 -    size_t index;
  2.1737 -
  2.1738 -    assert(mimetext);
  2.1739 -    assert(msg);
  2.1740 -
  2.1741 -    if (!(mimetext && msg))
  2.1742 -        return PEP_ILLEGAL_VALUE;
  2.1743 -
  2.1744 -    *msg = NULL;
  2.1745 -
  2.1746 -    index = 0;
  2.1747 -    r = mailmime_parse(mimetext, size, &index, &mime);
  2.1748 -    assert(r == 0);
  2.1749 -    assert(mime);
  2.1750 -    if (r) {
  2.1751 -        if (r == MAILIMF_ERROR_MEMORY)
  2.1752 -            goto enomem;
  2.1753 -        else
  2.1754 -            goto err_mime;
  2.1755 -    }
  2.1756 -
  2.1757 -    _msg = calloc(1, sizeof(message));
  2.1758 -    assert(_msg);
  2.1759 -    if (_msg == NULL)
  2.1760 -        goto enomem;
  2.1761 -
  2.1762 -    clist * _fieldlist = _get_fields(mime);
  2.1763 -    if (_fieldlist) {
  2.1764 -        status = read_fields(_msg, _fieldlist);
  2.1765 -        if (status != PEP_STATUS_OK)
  2.1766 -            goto pEp_error;
  2.1767 -    }
  2.1768 -
  2.1769 -    struct mailmime_content *content = _get_content(mime);
  2.1770 -
  2.1771 -    if (content) {
  2.1772 -        status = interpret_MIME(mime->mm_data.mm_message.mm_msg_mime,
  2.1773 -                _msg);
  2.1774 -        if (status != PEP_STATUS_OK)
  2.1775 -            goto pEp_error;
  2.1776 -    }
  2.1777 -
  2.1778 -    mailmime_free(mime);
  2.1779 -    *msg = _msg;
  2.1780 -
  2.1781 -    return status;
  2.1782 -
  2.1783 -err_mime:
  2.1784 -    status = PEP_ILLEGAL_VALUE;
  2.1785 -    goto pEp_error;
  2.1786 -
  2.1787 -enomem:
  2.1788 -    status = PEP_OUT_OF_MEMORY;
  2.1789 -
  2.1790 -pEp_error:
  2.1791 -    free_message(_msg);
  2.1792 -
  2.1793 -    if (mime)
  2.1794 -        mailmime_free(mime);
  2.1795 -
  2.1796 -    return status;
  2.1797 -}
     3.1 --- a/sync/cond_act_sync.yml2	Wed Apr 03 17:52:41 2019 +0200
     3.2 +++ b/sync/cond_act_sync.yml2	Fri Apr 05 16:56:44 2019 +0200
     3.3 @@ -37,6 +37,14 @@
     3.4      *result = t1->size == t2->size && memcmp(t1->buf, t2->buf, t1->size) == 0;
     3.5  ||
     3.6  
     3.7 +condition notMe
     3.8 +||
     3.9 +    TID_t *t1 = &session->sync_state.keysync.me;
    3.10 +    TID_t *t2 = &session->own_sync_state.me;
    3.11 +
    3.12 +    *result = t1->size != t2->size || memcmp(t1->buf, t2->buf, t1->size) != 0;
    3.13 +||
    3.14 +
    3.15  condition keyElectionWon
    3.16  ||
    3.17      pEp_identity *from = session->sync_state.common.from;
    3.18 @@ -107,6 +115,14 @@
    3.19      with "dst" > &session->own_sync_state.transaction
    3.20  }
    3.21  
    3.22 +action identifySole {
    3.23 +    call "new_UUID" with "dst" > &session->own_sync_state.me
    3.24 +    call "copy_UUID" {
    3.25 +        with "src" > &session->own_sync_state.me
    3.26 +        with "dst" > &session->sync_state.keysync.me
    3.27 +    }
    3.28 +}
    3.29 +
    3.30  function "show_handshake" {
    3.31      param "type";
    3.32      ||
     4.1 --- a/sync/sync.fsm	Wed Apr 03 17:52:41 2019 +0200
     4.2 +++ b/sync/sync.fsm	Fri Apr 05 16:56:44 2019 +0200
     4.3 @@ -61,8 +61,10 @@
     4.4  
     4.5          // handshaking without existing Device group
     4.6          state HandshakingNew {
     4.7 -            on Init
     4.8 +            on Init {
     4.9 +                do identifySole;
    4.10                  do showSoleHandshake;
    4.11 +            }
    4.12  
    4.13              // Cancel is Rollback
    4.14              on Cancel {
    4.15 @@ -91,8 +93,10 @@
    4.16                  go HandshakingNewPhase1;
    4.17              }
    4.18  
    4.19 -            on CommitAccept
    4.20 -                go HandshakingNewPhase1Own;
    4.21 +            on CommitAccept {
    4.22 +                if notMe
    4.23 +                    go HandshakingNewPhase1Own;
    4.24 +            }
    4.25          }
    4.26  
    4.27          state HandshakingNewPhase1 {
    4.28 @@ -105,7 +109,8 @@
    4.29              }
    4.30  
    4.31              on CommitAccept
    4.32 -                go NewGroup;
    4.33 +                if notMe
    4.34 +                    go NewGroup;
    4.35          }
    4.36  
    4.37          state HandshakingNewPhase1Own {
    4.38 @@ -121,7 +126,8 @@
    4.39              }
    4.40  
    4.41              on Accept
    4.42 -                go NewGroup;
    4.43 +                if notMe
    4.44 +                    go NewGroup;
    4.45          }
    4.46  
    4.47          state NewGroup {
    4.48 @@ -170,7 +176,7 @@
    4.49                  go HandshakingJoinPhase1;
    4.50              }
    4.51  
    4.52 -            on CommitAccept
    4.53 +            on CommitAcceptForGroup
    4.54                  go HandshakingJoinPhase1Own;
    4.55          }
    4.56  
    4.57 @@ -183,7 +189,7 @@
    4.58                  go End;
    4.59              }
    4.60  
    4.61 -            on CommitAccept
    4.62 +            on CommitAcceptForGroup
    4.63                  go JoinGroup;
    4.64          }
    4.65  
    4.66 @@ -249,7 +255,7 @@
    4.67  
    4.68              // Accept is Phase1Commit
    4.69              on Accept {
    4.70 -                send CommitAccept;
    4.71 +                send CommitAcceptForGroup;
    4.72                  go HandshakingGroupedPhase1;
    4.73              }
    4.74  
    4.75 @@ -329,14 +335,19 @@
    4.76  
    4.77          message CommitAccept 7 {
    4.78              field TID transaction;
    4.79 +            field TID me;
    4.80          }
    4.81  
    4.82 -        message GroupKeysAndClose 8, security=attach_own_keys {
    4.83 +        message CommitAcceptForGroup 8 {
    4.84 +            field TID transaction;
    4.85 +        }
    4.86 +
    4.87 +        message GroupKeysAndClose 9, security=attach_own_keys {
    4.88              field TID transaction;
    4.89              field IdentityList ownIdentities;
    4.90          }
    4.91  
    4.92 -        message GroupKeys 9, security=attach_own_keys {
    4.93 +        message GroupKeys 10, security=attach_own_keys {
    4.94              field IdentityList ownIdentities;
    4.95          }
    4.96      }