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 }