diff -urN ../exim-4.86.2.orig/src/mime.c ./src/mime.c --- ../exim-4.86.2.orig/src/mime.c 2016-03-26 19:43:21.000000000 +0200 +++ ./src/mime.c 2016-03-26 20:20:40.000000000 +0200 @@ -543,33 +543,6 @@ } -static uschar * -rfc2231_to_2047(const uschar * fname, const uschar * charset, int * len) -{ -int size = 0, ptr = 0; -uschar * val = string_cat(NULL, &size, &ptr, US"=?", 2); -uschar c; - -if (charset) - val = string_cat(val, &size, &ptr, charset, Ustrlen(charset)); -val = string_cat(val, &size, &ptr, US"?Q?", 3); - -while ((c = *fname)) - if (c == '%' && isxdigit(fname[1]) && isxdigit(fname[2])) - { - val = string_cat(val, &size, &ptr, US"=", 1); - val = string_cat(val, &size, &ptr, ++fname, 2); - fname += 2; - } - else - val = string_cat(val, &size, &ptr, fname++, 1); - -val = string_cat(val, &size, &ptr, US"?=", 2); -val[*len = ptr] = '\0'; -return val; -} - - int mime_acl_check(uschar *acl, FILE *f, struct mime_boundary_context *context, uschar **user_msgptr, uschar **log_msgptr) @@ -655,10 +628,7 @@ if (*(p = q)) p++; /* jump past the ; */ { - uschar * mime_fname = NULL; - uschar * mime_fname_rfc2231 = NULL; - uschar * mime_filename_charset = NULL; - BOOL decoding_failed = FALSE; + BOOL header_is_content_disposition = (strncmpic(US"content-disposition:",header,20) == 0); /* grab all param=value tags on the remaining line, check if they are interesting */ @@ -669,75 +639,6 @@ DEBUG(D_acl) debug_printf("MIME: considering paramlist '%s'\n", p); - if ( !mime_filename - && strncmpic(CUS"content-disposition:", header, 20) == 0 - && strncmpic(CUS"filename*", p, 9) == 0 - ) - { /* RFC 2231 filename */ - uschar * q; - - /* find value of the filename */ - p += 9; - while(*p != '=' && *p) p++; - if (*p) p++; /* p is filename or NUL */ - q = mime_param_val(&p); /* p now trailing ; or NUL */ - - if (q && *q) - { - uschar * temp_string, * err_msg; - int slen; - - /* build up an un-decoded filename over successive - filename*= parameters (for use when 2047 decode fails) */ - - mime_fname_rfc2231 = string_sprintf("%#s%s", - mime_fname_rfc2231, q); - - if (!decoding_failed) - { - int size; - if (!mime_filename_charset) - { - uschar * s = q; - - /* look for a ' in the "filename" */ - while(*s != '\'' && *s) s++; /* s is 1st ' or NUL */ - - if ((size = s-q) > 0) - mime_filename_charset = string_copyn(q, size); - - if (*(p = s)) p++; - while(*p == '\'') p++; /* p is after 2nd ' */ - } - else - p = q; - - DEBUG(D_acl) debug_printf("MIME: charset %s fname '%s'\n", - mime_filename_charset ? mime_filename_charset : US"", p); - - temp_string = rfc2231_to_2047(p, mime_filename_charset, &slen); - DEBUG(D_acl) debug_printf("MIME: 2047-name %s\n", temp_string); - - temp_string = rfc2047_decode(temp_string, FALSE, NULL, ' ', - NULL, &err_msg); - DEBUG(D_acl) debug_printf("MIME: plain-name %s\n", temp_string); - - size = Ustrlen(temp_string); - - if (size == slen) - decoding_failed = TRUE; - else - /* build up a decoded filename over successive - filename*= parameters */ - - mime_filename = mime_fname = mime_fname - ? string_sprintf("%s%s", mime_fname, temp_string) - : temp_string; - } - } - } - - else /* look for interesting parameters */ for (mp = mime_parameter_list; mp < mime_parameter_list + nelem(mime_parameter_list); @@ -760,6 +661,83 @@ mp->name, mh->name, *mp->value); break; /* done matching param names */ + } else { + if (header_is_content_disposition && (strncmpic(US"filename=",mp->name,9) == 0)) { + uschar * param_value = NULL; + int param_value_len = 0; + uschar mime_filename_rfc2231[1024]; + int size; + BOOL rfc2231_decoded = FALSE; + + memset(mime_filename_rfc2231, 0, sizeof(mime_filename_rfc2231)); + + // found an RFC 2231 filename? + while (strncmpic(US"filename*",p,9) == 0) { + // find value of the filename + p += 9; + while((*p != '=') && ((p - header) < Ustrlen(header))) p++; + p++; + uschar *q = p; + while((*q != ';') && ((q - header) < Ustrlen(header))) q++; + size = q - p; + uschar *q_prev = q; + q_prev--; + if ((size > 1) && (*p == '"') && (*q_prev == '"')) { + p++; + size -= 2; + } + if (size > 0) { + if (size > sizeof(mime_filename_rfc2231) - Ustrlen(mime_filename_rfc2231) - 1) size = sizeof(mime_filename_rfc2231) - Ustrlen(mime_filename_rfc2231) - 1; + Ustrncpy(mime_filename_rfc2231 + Ustrlen(mime_filename_rfc2231), p, size); + } + p = q; p++; + } + + if (Ustrlen(mime_filename_rfc2231) > 0) { + uschar mime_filename_charset[24]; + uschar *i1 = mime_filename_rfc2231; + uschar *i2 = mime_filename_rfc2231; + uschar *temp_string, *err_msg; + int temp_string_len1 = 0; + + memset(mime_filename_charset, 0, sizeof(mime_filename_charset)); + + while ((*i1 != '\'') && ((i1 - i2) < Ustrlen(mime_filename_rfc2231)-2)) i1++; + i2 = i1; i2++; + + if ((i1 - mime_filename_rfc2231 > 0) && (*i1 == '\'') && (*i2 == '\'')) { + size = i1 - mime_filename_rfc2231; + if (size > sizeof(mime_filename_charset) - 1) size = sizeof(mime_filename_charset) - 1; + Ustrncpy(mime_filename_charset, mime_filename_rfc2231, size); + i1 += 2; + + temp_string = expand_string(string_sprintf( + "=?%s?Q?${sg{%s}{\\N%%([\\dA-Fa-f]{2})\\N}{=\\$1}}?=", mime_filename_charset, i1)); + temp_string_len1 = Ustrlen(temp_string); + temp_string = rfc2047_decode(temp_string, FALSE, NULL, 32, NULL, &err_msg); + param_value_len = Ustrlen(temp_string); + + if ((param_value_len > 0) && (param_value_len != temp_string_len1)) { + rfc2231_decoded = TRUE; + + param_value = (uschar *)malloc(param_value_len+1); + memset(param_value, 0, param_value_len+1); + Ustrncpy(param_value, temp_string, param_value_len); + debug_printf("Found %s MIME parameter in %s header, value is '%s'\n", mp->name, mh->name, param_value); + *((uschar **)(mp->value)) = param_value; + } + } + if (!rfc2231_decoded) { + param_value_len = Ustrlen(mime_filename_rfc2231); + param_value = (uschar *)malloc(param_value_len+1); + memset(param_value,0,param_value_len+1); + Ustrncpy(param_value, mime_filename_rfc2231, param_value_len); + param_value = rfc2047_decode(param_value, check_rfc2047_length, NULL, 32, ¶m_value_len, &err_msg); + debug_printf("Found %s MIME parameter in %s header, value is '%s'\n", mp->name, mh->name, param_value); + *((uschar **)(mp->value)) = param_value; + } + } + } } @@ -769,14 +747,6 @@ if (*p) p++; } /* param scan on line */ - if (strncmpic(CUS"content-disposition:", header, 20) == 0) - { - if (decoding_failed) mime_filename = mime_fname_rfc2231; - - DEBUG(D_acl) debug_printf( - "MIME: found %s parameter in %s header, value is '%s'\n", - "filename", mh->name, mime_filename); - } } } }