|
|
@ -39,6 +39,7 @@ |
|
|
|
|
|
|
|
#include "mailmime_disposition.h" |
|
|
|
#include "mailmime.h" |
|
|
|
#include "charconv.h" |
|
|
|
|
|
|
|
#include <ctype.h> |
|
|
|
#include <stdlib.h> |
|
|
@ -422,6 +423,223 @@ mailmime_disposition_parm_parse(const char * message, size_t length, |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
// filename-parm := "filename" "=" value |
|
|
|
*/ |
|
|
|
|
|
|
|
static int |
|
|
|
mailmime_extended_parm_parse(const char * message, size_t length, |
|
|
|
char * key, size_t * indx, char ** result) |
|
|
|
{ |
|
|
|
int r; |
|
|
|
size_t cur_token; |
|
|
|
char* built_str = NULL; |
|
|
|
size_t built_len = 0; |
|
|
|
|
|
|
|
cur_token = * indx; |
|
|
|
|
|
|
|
r = mailimf_token_case_insensitive_parse(message, length, |
|
|
|
&cur_token, key); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
|
|
|
|
// Ok, we know it's of this type. |
|
|
|
// So let's see if it's encoded or extended or both |
|
|
|
|
|
|
|
int encoded = 0; |
|
|
|
int extended = 0; |
|
|
|
|
|
|
|
// Find out if message is extended, encoded, or both |
|
|
|
r = mailimf_char_parse(message, length, &cur_token, '*'); |
|
|
|
|
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
r = mailimf_char_parse(message, length, &cur_token, '0'); |
|
|
|
|
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
extended = 1; |
|
|
|
r = mailimf_char_parse(message, length, &cur_token, '*'); |
|
|
|
if (r == MAILIMF_NO_ERROR) |
|
|
|
encoded = 1; |
|
|
|
else if (r != MAILIMF_ERROR_PARSE) |
|
|
|
return r; |
|
|
|
} |
|
|
|
else if (r != MAILIMF_ERROR_PARSE) |
|
|
|
return r; |
|
|
|
} |
|
|
|
else //if (r != MAILIMF_ERROR_PARSE) |
|
|
|
return r; |
|
|
|
|
|
|
|
r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
|
|
|
|
r = mailimf_cfws_parse(message, length, &cur_token); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) |
|
|
|
return r; |
|
|
|
|
|
|
|
// Ok, let's go. |
|
|
|
if (encoded || extended) { |
|
|
|
char* _charset = NULL; |
|
|
|
char* _lang = NULL; |
|
|
|
|
|
|
|
|
|
|
|
// Get the first of either |
|
|
|
if (encoded) { |
|
|
|
r = mailmime_extended_initial_value_parse(message, length, &cur_token, &built_str, &_charset, |
|
|
|
&_lang); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
} |
|
|
|
else if (extended) { |
|
|
|
r = mailmime_value_parse(message, length, &cur_token, &built_str); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
} |
|
|
|
// Ok, we have an initial string and know it's extended, so let's roll. |
|
|
|
if (extended && built_str) { |
|
|
|
built_len = strlen(built_str); |
|
|
|
|
|
|
|
while (1) { |
|
|
|
|
|
|
|
r = mailimf_unstrict_char_parse(message, length, &cur_token, ';'); |
|
|
|
if (r != MAILIMF_NO_ERROR && r != MAILIMF_ERROR_PARSE) |
|
|
|
return r; |
|
|
|
|
|
|
|
r = mailimf_cfws_parse(message, length, &cur_token); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) |
|
|
|
return r; |
|
|
|
|
|
|
|
// FIXME: this is where we have to check and see what really happens... |
|
|
|
r = mailimf_token_case_insensitive_parse(message, length, |
|
|
|
&cur_token, key); |
|
|
|
if (r == MAILIMF_ERROR_PARSE) |
|
|
|
break; |
|
|
|
|
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
|
|
|
|
// Ok, we know it's of this type. |
|
|
|
// So let's see if it's encoded or extended or both |
|
|
|
|
|
|
|
// int part_encoded = 0; |
|
|
|
// int part_extended = 0; |
|
|
|
|
|
|
|
// Find out if message part is extended, encoded, or both |
|
|
|
r = mailimf_char_parse(message, length, &cur_token, '*'); |
|
|
|
|
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
uint32_t part_num = 0; |
|
|
|
r = mailimf_number_parse(message, length, &cur_token, &part_num); |
|
|
|
|
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
// part_extended = 1; |
|
|
|
r = mailimf_char_parse(message, length, &cur_token, '*'); |
|
|
|
// See RFC2231, Section 4.1. FIXME - it's possible to have unencoded parts interspersed |
|
|
|
// with encoded post per RFC, so this may not be smart. Depends on if decoding is an issue with |
|
|
|
// interspersed ASCII segments. |
|
|
|
// However, at this point, we know that the first part of the parameter either contained encoding information, |
|
|
|
// or it shouldn't be encoded. Also, it seems very doubtful most clients would go to the trouble of mixing encoded |
|
|
|
// and non-encoded information when splitting the string. |
|
|
|
// The fix right now is to ignore the encoding flag at this point, as we will either decode the whole string, |
|
|
|
// or not at all. |
|
|
|
} |
|
|
|
else if (r != MAILIMF_ERROR_PARSE) |
|
|
|
return r; |
|
|
|
} |
|
|
|
else if (r != MAILIMF_ERROR_PARSE) |
|
|
|
return r; |
|
|
|
|
|
|
|
r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
|
|
|
|
r = mailimf_cfws_parse(message, length, &cur_token); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) |
|
|
|
return r; |
|
|
|
|
|
|
|
// Ok, let's go. |
|
|
|
// if (part_encoded || part_extended) { |
|
|
|
|
|
|
|
char* part_str = NULL; |
|
|
|
|
|
|
|
// See RFC2231, Section 4.1. FIXME - it's possible to have unencoded parts interspersed |
|
|
|
// with encoded post per RFC, so this may not be smart. Depends on if decoding is an issue with |
|
|
|
// interspersed ASCII segments. |
|
|
|
r = mailmime_value_parse(message, length, &cur_token, &part_str); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
|
|
|
|
size_t part_size = strlen(part_str); |
|
|
|
size_t new_size = built_len + part_size + 1; |
|
|
|
|
|
|
|
char* new_str = NULL; |
|
|
|
new_str = realloc((void*)built_str, new_size); |
|
|
|
if (new_str) { |
|
|
|
strncat(new_str, part_str, part_size); |
|
|
|
built_str = new_str; |
|
|
|
free(part_str); |
|
|
|
part_str = NULL; |
|
|
|
} |
|
|
|
else { |
|
|
|
free(built_str); |
|
|
|
return MAILIMF_ERROR_MEMORY; |
|
|
|
} |
|
|
|
|
|
|
|
// } |
|
|
|
built_len = strlen(built_str); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (encoded && built_str && _charset && _charset[0] != '\0') { |
|
|
|
char* replace_str = NULL; |
|
|
|
mailmime_parm_value_unescape(&replace_str, built_str); |
|
|
|
|
|
|
|
if (replace_str) { |
|
|
|
free(built_str); |
|
|
|
built_str = replace_str; |
|
|
|
replace_str = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (strcasecmp(_charset, "utf-8") != 0 && |
|
|
|
strcasecmp(_charset, "utf8") != 0) { |
|
|
|
|
|
|
|
// best effort |
|
|
|
r = charconv("utf-8", _charset, built_str, |
|
|
|
strlen(built_str), &replace_str); |
|
|
|
|
|
|
|
switch(r) { |
|
|
|
case MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: |
|
|
|
r = charconv("utf-8", "iso-8859-1", built_str, |
|
|
|
strlen(built_str), &replace_str); |
|
|
|
break; |
|
|
|
case MAIL_CHARCONV_ERROR_MEMORY: |
|
|
|
return MAILIMF_ERROR_MEMORY; |
|
|
|
case MAIL_CHARCONV_ERROR_CONV: |
|
|
|
return MAILIMF_ERROR_PARSE; |
|
|
|
} |
|
|
|
switch (r) { |
|
|
|
case MAIL_CHARCONV_ERROR_MEMORY: |
|
|
|
return MAILIMF_ERROR_MEMORY; |
|
|
|
case MAIL_CHARCONV_ERROR_CONV: |
|
|
|
return MAILIMF_ERROR_PARSE; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (replace_str) { |
|
|
|
built_str = replace_str; |
|
|
|
replace_str = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
* indx = cur_token; |
|
|
|
* result = built_str; |
|
|
|
|
|
|
|
return MAILIMF_NO_ERROR; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
filename-parm := "filename" "=" value |
|
|
|
*/ |
|
|
@ -435,23 +653,29 @@ mailmime_filename_parm_parse(const char * message, size_t length, |
|
|
|
size_t cur_token; |
|
|
|
|
|
|
|
cur_token = * indx; |
|
|
|
|
|
|
|
r = mailimf_token_case_insensitive_parse(message, length, |
|
|
|
&cur_token, "filename"); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
|
|
|
|
r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
|
|
|
|
r = mailimf_cfws_parse(message, length, &cur_token); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) |
|
|
|
return r; |
|
|
|
r = mailmime_extended_parm_parse(message, length, "filename", &cur_token, &value); |
|
|
|
|
|
|
|
r = mailmime_value_parse(message, length, &cur_token, &value); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
if (r != MAILIMF_NO_ERROR) { |
|
|
|
|
|
|
|
r = mailimf_token_case_insensitive_parse(message, length, |
|
|
|
&cur_token, "filename"); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
|
|
|
|
r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
|
|
|
|
r = mailimf_cfws_parse(message, length, &cur_token); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) |
|
|
|
return r; |
|
|
|
|
|
|
|
r = mailmime_value_parse(message, length, &cur_token, &value); |
|
|
|
if (r != MAILIMF_NO_ERROR) |
|
|
|
return r; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
* indx = cur_token; |
|
|
|
* result = value; |
|
|
|