From 27bab789681ae7002d273b3ab9cb111fb1b5df59 Mon Sep 17 00:00:00 2001 From: Krista Grothoff Date: Tue, 13 Dec 2016 15:11:40 +0100 Subject: [PATCH] modifications for memoryhole and main texts in attachments --- build-windows/build_headers.list | 1 - src/low-level/imf/mailimf.c | 84 ++++-- src/low-level/mime/mailmime_content.c | 354 ++++++++++++++------------ src/low-level/mime/mailmime_types.c | 3 + src/low-level/mime/mailmime_types.h | 1 + 5 files changed, 257 insertions(+), 186 deletions(-) diff --git a/build-windows/build_headers.list b/build-windows/build_headers.list index 4b68d83..7f12816 100644 --- a/build-windows/build_headers.list +++ b/build-windows/build_headers.list @@ -129,7 +129,6 @@ src\low-level\mh\mailmh.h src\low-level\mime\mailmime.h src\low-level\mime\mailmime_content.h src\low-level\mime\mailmime_decode.h -src\low-level\mime\mailmime_encode.h src\low-level\mime\mailmime_disposition.h src\low-level\mime\mailmime_types.h src\low-level\mime\mailmime_types_helper.h diff --git a/src/low-level/imf/mailimf.c b/src/low-level/imf/mailimf.c index 8d9ce4a..d58ecae 100644 --- a/src/low-level/imf/mailimf.c +++ b/src/low-level/imf/mailimf.c @@ -574,15 +574,15 @@ mailimf_struct_multiple_parse(const char * message, size_t length, r = parser(message, length, &cur_token, &value); if (r != MAILIMF_NO_ERROR) { if (r == MAILIMF_ERROR_PARSE) - break; + break; else { - res = r; - goto free; + res = r; + goto free; } } r = clist_append(struct_list, value); if (r < 0) { - (* destructor)(value); + (*destructor)(value); res = MAILIMF_ERROR_MEMORY; goto free; } @@ -7529,30 +7529,26 @@ int mailimf_envelope_fields_parse(const char * message, size_t length, } while (1) { - struct mailimf_field * elt; + struct mailimf_field *elt; r = mailimf_envelope_field_parse(message, length, &cur_token, &elt); if (r == MAILIMF_NO_ERROR) { r = clist_append(list, elt); if (r < 0) { - res = MAILIMF_ERROR_MEMORY; - goto free; + res = MAILIMF_ERROR_MEMORY; + goto free; } - } - else if (r == MAILIMF_ERROR_PARSE) { + } else if (r == MAILIMF_ERROR_PARSE) { r = mailimf_ignore_field_parse(message, length, &cur_token); if (r == MAILIMF_NO_ERROR) { - /* do nothing */ - } - else if (r == MAILIMF_ERROR_PARSE) { - break; - } - else { - res = r; - goto free; + /* do nothing */ + } else if (r == MAILIMF_ERROR_PARSE) { + break; + } else { + res = r; + goto free; } - } - else { + } else { res = r; goto free; } @@ -7776,3 +7772,53 @@ mailimf_optional_fields_parse(const char * message, size_t length, err: return res; } + +LIBETPAN_EXPORT +int +mailimf_memoryhole_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r = MAILIMF_ERROR_PARSE; + int res; + + cur_token = * indx; + + list = NULL; + + const char* rfc822_header_string = "Content-Type: text/rfc822-headers;"; + const size_t rfc822_header_strlen = 34; + + const char* cur_char = message + cur_token; + + if ((cur_token + rfc822_header_strlen) <= length && + strncmp(cur_char, rfc822_header_string, rfc822_header_strlen) == 0) { + r = mailimf_envelope_fields_parse(message, length, &cur_token, + result); + } + + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + default: + res = r; + goto err; + } + + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} diff --git a/src/low-level/mime/mailmime_content.c b/src/low-level/mime/mailmime_content.c index 006b44e..752454d 100644 --- a/src/low-level/mime/mailmime_content.c +++ b/src/low-level/mime/mailmime_content.c @@ -790,35 +790,35 @@ int mailmime_multipart_next_parse(const char * message, size_t length, if (cur_token >= length) return MAILIMF_ERROR_PARSE; - - switch(state) { + + switch (state) { case MULTIPART_NEXT_STATE_0: switch (message[cur_token]) { case ' ': - state = MULTIPART_NEXT_STATE_0; - break; + state = MULTIPART_NEXT_STATE_0; + break; case '\t': - state = MULTIPART_NEXT_STATE_0; - break; + state = MULTIPART_NEXT_STATE_0; + break; case '\r': - state = MULTIPART_NEXT_STATE_1; - break; + state = MULTIPART_NEXT_STATE_1; + break; case '\n': - state = MULTIPART_NEXT_STATE_2; - break; + state = MULTIPART_NEXT_STATE_2; + break; default: - return MAILIMF_ERROR_PARSE; + return MAILIMF_ERROR_PARSE; } break; case MULTIPART_NEXT_STATE_1: switch (message[cur_token]) { case '\n': - state = MULTIPART_NEXT_STATE_2; - break; + state = MULTIPART_NEXT_STATE_2; + break; default: - return MAILIMF_ERROR_PARSE; + return MAILIMF_ERROR_PARSE; } break; } @@ -831,6 +831,7 @@ int mailmime_multipart_next_parse(const char * message, size_t length, return MAILIMF_NO_ERROR; } +/* N.B. Modified to allow add enigmail memoryhole Subject header to fields. */ static int mailmime_multipart_body_parse(const char * message, size_t length, size_t * indx, char * boundary, @@ -911,13 +912,14 @@ mailmime_multipart_body_parse(const char * message, size_t length, preamble_length = preamble_end - preamble_begin; part_begin = cur_token; + while (1) { r = mailmime_lwsp_parse(message, length, &cur_token); if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { res = r; goto err; } - + r = mailimf_crlf_parse(message, length, &cur_token); if (r == MAILIMF_NO_ERROR) { part_begin = cur_token; @@ -941,7 +943,10 @@ mailmime_multipart_body_parse(const char * message, size_t length, } final_part = 0; - + + /* Go through the whole block of parts corresponding to this boundary, + parse each by consuming each one and going back to the top of + the loop */ while (!final_part) { size_t bp_token; struct mailmime * mime_bp; @@ -949,7 +954,7 @@ mailmime_multipart_body_parse(const char * message, size_t length, size_t data_size; struct mailimf_fields * fields; struct mailmime_fields * mime_fields; - + r = mailmime_body_part_dash2_transport_crlf_parse(message, length, &cur_token, boundary, &data_str, &data_size); if (r == MAILIMF_ERROR_PARSE) { @@ -962,29 +967,44 @@ mailmime_multipart_body_parse(const char * message, size_t length, if (r == MAILIMF_NO_ERROR) { bp_token = 0; - - r = mailimf_optional_fields_parse(data_str, data_size, + + struct mailimf_fields * envelope_fields = NULL; + + int is_memoryhole_part = 0; + + + r = mailimf_memoryhole_fields_parse(data_str, data_size, &bp_token, &fields); - if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { - res = r; - goto free; - } - - r = mailimf_crlf_parse(data_str, data_size, &bp_token); - if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { - mailimf_fields_free(fields); - res = r; - goto free; - } - + + if (r == MAILIMF_NO_ERROR) { + is_memoryhole_part = 1; + } + else { + r = mailimf_optional_fields_parse(data_str, data_size, + &bp_token, &fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + r = mailimf_crlf_parse(data_str, data_size, &bp_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free; + } + } + mime_fields = NULL; r = mailmime_fields_parse(fields, &mime_fields); - mailimf_fields_free(fields); + + /* mailimf_fields_free(fields); */ /* we don't do this now to preserve for memoryhole */ + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { res = r; goto free; } - + r = mailmime_parse_with_default(data_str, data_size, &bp_token, default_subtype, NULL, mime_fields, &mime_bp); @@ -1006,6 +1026,8 @@ mailmime_multipart_body_parse(const char * message, size_t length, goto free; } + mime_bp->mm_imf_fields = fields; + r = mailmime_multipart_next_parse(message, length, &cur_token); if (r == MAILIMF_NO_ERROR) { /* do nothing */ @@ -1089,7 +1111,8 @@ mailmime_multipart_body_parse(const char * message, size_t length, enum { MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, - MAILMIME_DEFAULT_TYPE_MESSAGE + MAILMIME_DEFAULT_TYPE_MESSAGE, + MAILMIME_DEFAULT_TYPE_RFC2822_EXTRA_HEADERS }; @@ -1240,29 +1263,28 @@ static void remove_unparsed_mime_headers(struct mailimf_fields * fields) } } -static int mailmime_parse_with_default(const char * message, size_t length, - size_t * indx, int default_type, - struct mailmime_content * content_type, - struct mailmime_fields * mime_fields, - struct mailmime ** result) -{ +static int mailmime_parse_with_default(const char *message, size_t length, + size_t *indx, int default_type, + struct mailmime_content *content_type, + struct mailmime_fields *mime_fields, + struct mailmime **result) { size_t cur_token; int body_type; int encoding; - struct mailmime_data * body; - char * boundary; - struct mailimf_fields * fields; - clist * list; - struct mailmime * msg_mime; + struct mailmime_data *body; + char *boundary; + struct mailimf_fields *fields; + clist *list; + struct mailmime *msg_mime; - struct mailmime * mime; + struct mailmime *mime; int r; int res; - struct mailmime_data * preamble; - struct mailmime_data * epilogue; + struct mailmime_data *preamble; + struct mailmime_data *epilogue; /* note that when this function is called, content type is always detached, @@ -1271,23 +1293,23 @@ static int mailmime_parse_with_default(const char * message, size_t length, preamble = NULL; epilogue = NULL; - - cur_token = * indx; + + cur_token = *indx; /* get content type */ if (content_type == NULL) { if (mime_fields != NULL) { - clistiter * cur; - - for(cur = clist_begin(mime_fields->fld_list) ; cur != NULL ; - cur = clist_next(cur)) { - struct mailmime_field * field; - + clistiter *cur; + + for (cur = clist_begin(mime_fields->fld_list); cur != NULL; + cur = clist_next(cur)) { + struct mailmime_field *field; + field = clist_content(cur); if (field->fld_type == MAILMIME_FIELD_TYPE) { content_type = field->fld_data.fld_content; - + /* detach content type from list */ field->fld_data.fld_content = NULL; clist_delete(mime_fields->fld_list, cur); @@ -1309,17 +1331,16 @@ static int mailmime_parse_with_default(const char * message, size_t length, if (default_type == MAILMIME_DEFAULT_TYPE_TEXT_PLAIN) { content_type = mailmime_get_content_text(); if (content_type == NULL) { - res = MAILIMF_ERROR_MEMORY; - goto err; + res = MAILIMF_ERROR_MEMORY; + goto err; } - } - else /* message */ { + } else /* message */ { body_type = MAILMIME_MESSAGE; - + content_type = mailmime_get_content_message(); if (content_type == NULL) { - res = MAILIMF_ERROR_MEMORY; - goto err; + res = MAILIMF_ERROR_MEMORY; + goto err; } } } @@ -1333,19 +1354,19 @@ static int mailmime_parse_with_default(const char * message, size_t length, switch (content_type->ct_type->tp_data.tp_composite_type->ct_type) { case MAILMIME_COMPOSITE_TYPE_MULTIPART: boundary = mailmime_extract_boundary(content_type); - + if (boundary == NULL) - body_type = MAILMIME_SINGLE; + body_type = MAILMIME_SINGLE; else - body_type = MAILMIME_MULTIPLE; + body_type = MAILMIME_MULTIPLE; break; - + case MAILMIME_COMPOSITE_TYPE_MESSAGE: if (strcasecmp(content_type->ct_subtype, "rfc822") == 0) - body_type = MAILMIME_MESSAGE; + body_type = MAILMIME_MESSAGE; else - body_type = MAILMIME_SINGLE; + body_type = MAILMIME_SINGLE; break; default: @@ -1365,20 +1386,19 @@ static int mailmime_parse_with_default(const char * message, size_t length, encoding = mailmime_transfer_encoding_get(mime_fields); else encoding = MAILMIME_MECHANISM_8BIT; - + if (body_type == MAILMIME_MESSAGE) { switch (encoding) { - case MAILMIME_MECHANISM_QUOTED_PRINTABLE: - case MAILMIME_MECHANISM_BASE64: - body_type = MAILMIME_SINGLE; - break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + case MAILMIME_MECHANISM_BASE64: + body_type = MAILMIME_SINGLE; + break; } } - - cur_token = * indx; - body = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, 1, - message + cur_token, length - cur_token, - NULL); + + cur_token = *indx; + body = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, 1, message + cur_token, + length - cur_token, NULL); if (body == NULL) { free(boundary); res = MAILIMF_ERROR_MEMORY; @@ -1392,107 +1412,109 @@ static int mailmime_parse_with_default(const char * message, size_t length, fields = NULL; switch (body_type) { - case MAILMIME_MESSAGE: - { - struct mailmime_fields * submime_fields; - - r = mailimf_envelope_and_optional_fields_parse(message, length, - &cur_token, &fields); - if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { - res = r; - goto free_content; - } - - r = mailimf_crlf_parse(message, length, &cur_token); - if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { - mailimf_fields_free(fields); - res = r; + case MAILMIME_MESSAGE: { + struct mailmime_fields *submime_fields; + + r = mailimf_envelope_and_optional_fields_parse(message, length, &cur_token, + &fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_content; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free_content; + } + + submime_fields = NULL; + r = mailmime_fields_parse(fields, &submime_fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free_content; + } + + remove_unparsed_mime_headers(fields); + + r = mailmime_parse_with_default(message, length, &cur_token, + MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, NULL, + submime_fields, &msg_mime); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } else if (r == MAILIMF_ERROR_PARSE) { + mailmime_fields_free(mime_fields); + msg_mime = NULL; + } else { + mailmime_fields_free(mime_fields); + res = r; + goto free_content; + } + } + + break; + + case MAILMIME_MULTIPLE: { + int default_subtype; + + default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN; + if (content_type != NULL) + if (strcasecmp(content_type->ct_subtype, "digest") == 0) + default_subtype = MAILMIME_DEFAULT_TYPE_MESSAGE; + + cur_token = *indx; + r = mailmime_multipart_body_parse(message, length, &cur_token, boundary, + default_subtype, &list, &preamble, + &epilogue); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } else if (r == MAILIMF_ERROR_PARSE) { + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; goto free_content; } - - submime_fields = NULL; - r = mailmime_fields_parse(fields, &submime_fields); + } else { + res = r; + goto free_content; + } + + free(boundary); + } break; + + default: /* MAILMIME_SINGLE */ + if (strcasecmp(content_type->ct_subtype, "rfc822-headers") == 0) { + // default_subtype = MAILMIME_DEFAULT_TYPE_RFC2822_EXTRA_HEADERS; + struct mailmime_fields *submime_fields; + + r = mailimf_envelope_and_optional_fields_parse(message, length, + &cur_token, &fields); if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { - mailimf_fields_free(fields); - res = r; - goto free_content; - } - - remove_unparsed_mime_headers(fields); - - r = mailmime_parse_with_default(message, length, - &cur_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, - NULL, submime_fields, &msg_mime); - if (r == MAILIMF_NO_ERROR) { - /* do nothing */ - } - else if (r == MAILIMF_ERROR_PARSE) { - mailmime_fields_free(mime_fields); - msg_mime = NULL; - } - else { - mailmime_fields_free(mime_fields); res = r; goto free_content; } } - - break; - - case MAILMIME_MULTIPLE: - { - int default_subtype; - - default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN; - if (content_type != NULL) - if (strcasecmp(content_type->ct_subtype, "digest") == 0) - default_subtype = MAILMIME_DEFAULT_TYPE_MESSAGE; - - cur_token = * indx; - r = mailmime_multipart_body_parse(message, length, - &cur_token, boundary, - default_subtype, - &list, &preamble, &epilogue); - if (r == MAILIMF_NO_ERROR) { - /* do nothing */ - } - else if (r == MAILIMF_ERROR_PARSE) { - list = clist_new(); - if (list == NULL) { - res = MAILIMF_ERROR_MEMORY; - goto free_content; - } - } - else { - res = r; - goto free_content; - } - - free(boundary); - } - break; - - default: /* MAILMIME_SINGLE */ - /* do nothing */ + /* else do nothing */ break; } - mime = mailmime_new(body_type, message, length, - mime_fields, content_type, - body, preamble, /* preamble */ - epilogue, /* epilogue */ - list, fields, msg_mime); + mime = mailmime_new(body_type, message, length, mime_fields, content_type, + body, preamble, /* preamble */ + epilogue, /* epilogue */ + list, fields, msg_mime); if (mime == NULL) { res = MAILIMF_ERROR_MEMORY; goto free; } - * result = mime; - * indx = length; + *result = mime; + *indx = length; return MAILIMF_NO_ERROR; - free: +free: if (epilogue != NULL) mailmime_data_free(epilogue); if (preamble != NULL) @@ -1500,12 +1522,12 @@ static int mailmime_parse_with_default(const char * message, size_t length, if (msg_mime != NULL) mailmime_free(msg_mime); if (list != NULL) { - clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_foreach(list, (clist_func)mailmime_free, NULL); clist_free(list); } - free_content: +free_content: mailmime_content_free(content_type); - err: +err: return res; } diff --git a/src/low-level/mime/mailmime_types.c b/src/low-level/mime/mailmime_types.c index 2493500..2f88c65 100644 --- a/src/low-level/mime/mailmime_types.c +++ b/src/low-level/mime/mailmime_types.c @@ -436,6 +436,7 @@ struct mailmime * mailmime_new(int mm_type, mime->mm_mime_fields = mm_mime_fields; mime->mm_content_type = mm_content_type; + mime->mm_imf_fields = NULL; mime->mm_body = mm_body; switch (mm_type) { @@ -505,6 +506,8 @@ void mailmime_free(struct mailmime * mime) if (mime->mm_mime_fields != NULL) mailmime_fields_free(mime->mm_mime_fields); + if (mime->mm_imf_fields != NULL) + mailimf_fields_free(mime->mm_imf_fields); if (mime->mm_content_type != NULL) mailmime_content_free(mime->mm_content_type); free(mime); diff --git a/src/low-level/mime/mailmime_types.h b/src/low-level/mime/mailmime_types.h index f29605e..276a8f0 100644 --- a/src/low-level/mime/mailmime_types.h +++ b/src/low-level/mime/mailmime_types.h @@ -322,6 +322,7 @@ struct mailmime { struct mailmime_fields * mm_mime_fields; struct mailmime_content * mm_content_type; + struct mailimf_fields * mm_imf_fields; /* preserves the whole set of fields from a part for memoryhole */ struct mailmime_data * mm_body; union {