diff -urN src.orig/mime.c src/mime.c --- src.orig/mime.c 2007-08-30 17:31:06.000000000 +0300 +++ src/mime.c 2007-11-06 09:11:06.000000000 +0200 @@ -562,6 +562,17 @@ /* make p point to the next character after the closing ';' */ p += (header_value_len+1); +{ + uschar mime_filename_buffer[256]; + uschar mime_filename_rfc2231[1024]; + uschar mime_filename_charset[24]; + int decoding_failed = 0; + int size; + + memset(mime_filename_buffer,0,sizeof(mime_filename_buffer)); + memset(mime_filename_rfc2231,0,sizeof(mime_filename_rfc2231)); + memset(mime_filename_charset,0,sizeof(mime_filename_charset)); + /* grab all param=value tags on the remaining line, check if they are interesting */ NEXT_PARAM_SEARCH: while (*p != 0) { int j; @@ -586,11 +597,91 @@ goto NEXT_PARAM_SEARCH; }; } + + // found an RFC 2231 filename? + if ((mime_filename == NULL) && (strncmpic("content-disposition:",header,20) == 0) && (strncmpic("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++; + if (q - p > 0) { + uschar buffer[256]; + uschar *temp_string, *err_msg; + int temp_string_len1 = 0; + int temp_string_len2 = 0; + + size = q - p; + 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); + + if (decoding_failed == 0) { + + if (Ustrlen(mime_filename_charset) == 0) { + uschar *i = p; + + while((*i != '\'') && ((i - header) < Ustrlen(header))) i++; + + if (i - p > 0) { + size = i - p; + if (size > sizeof(mime_filename_charset) - 1) size = sizeof(mime_filename_charset) - 1; + Ustrncpy(mime_filename_charset, p, size); + p = i; + + while((*p == '\'') && ((p - header) < Ustrlen(header))) p++; + } + } + + memset(buffer,0,sizeof(buffer)); + size = q - p; + if (size > sizeof(buffer) - 1) size = sizeof(buffer) - 1; + Ustrncpy(buffer, p, q - p); + + temp_string = expand_string(string_sprintf( + "=?%s?Q?${sg{%s}{\\N%%([\\dA-Fa-f]{2})\\N}{=\\$1}}?=", mime_filename_charset, buffer)); + temp_string_len1 = Ustrlen(temp_string); + temp_string = rfc2047_decode(temp_string, FALSE, NULL, 32, &temp_string_len2, &err_msg); + + if (Ustrlen(temp_string) == temp_string_len1) { + decoding_failed = 1; + } else { + size = Ustrlen(temp_string); + if (size > sizeof(mime_filename_buffer) - Ustrlen(mime_filename_buffer) - 1) size = sizeof(mime_filename_buffer) - Ustrlen(mime_filename_buffer) - 1; + Ustrncpy(mime_filename_buffer + Ustrlen(mime_filename_buffer), temp_string, Ustrlen(temp_string)); + } + } + + p = q; + } + } + /* There is something, but not one of our interesting parameters. Advance to the next semicolon */ while(*p != ';') p++; p++; }; + + if (strncmpic("content-disposition:",header,20) == 0) { + uschar *param_value = NULL; + int param_value_len = 0; + + if (decoding_failed) { + size = Ustrlen(mime_filename_rfc2231); + if (size > sizeof(mime_filename_buffer) - 1) size = sizeof(mime_filename_buffer) - 1; + Ustrncpy(mime_filename_buffer, mime_filename_rfc2231, Ustrlen(mime_filename_rfc2231)); + } + + param_value_len = Ustrlen(mime_filename_buffer); + param_value = (uschar *)malloc(param_value_len+1); + memset(param_value,0,param_value_len+1); + Ustrncpy(param_value, mime_filename_buffer, param_value_len); + debug_printf("Found %s MIME parameter in %s header, value is '%s'\n", "filename", mime_header_list[i].name, param_value); + mime_filename = param_value; + } +} + }; }; };