static mime_parameter mime_parameter_list[] = {
/* name namelen value */
- { US"name=", 5, &mime_filename },
- { US"filename=", 9, &mime_filename },
- { US"charset=", 8, &mime_charset },
- { US"boundary=", 9, &mime_boundary }
+ { US"name", 4, &mime_filename },
+ { US"filename", 8, &mime_filename },
+ { US"charset", 7, &mime_charset },
+ { US"boundary", 8, &mime_boundary }
};
if (*(p = q)) p++; /* jump past the ; */
{
- uschar * mime_fname = NULL;
- uschar * mime_fname_rfc2231 = NULL;
+ gstring * mime_fname = NULL;
+ gstring * mime_fname_rfc2231 = NULL;
uschar * mime_filename_charset = NULL;
BOOL decoding_failed = FALSE;
DEBUG(D_acl)
debug_printf_indent("MIME: considering paramlist '%s'\n", p);
- if ( 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)
+ /* look for interesting parameters */
+ for (mime_parameter * mp = mime_parameter_list;
+ mp < mime_parameter_list + nelem(mime_parameter_list);
+ mp++
+ ) if (strncmpic(mp->name, p, mp->namelen) == 0)
+ {
+ p += mp->namelen;
+ if (*p == '*') /* RFC 2231 */
{
- uschar * temp_string, * err_msg, * fname = q;
- int slen;
-
- /* build up an un-decoded filename over successive
- filename*= parameters (for use when 2047 decode fails) */
-/*XXX could grow a gstring here */
-
- mime_fname_rfc2231 = string_sprintf("%#s%s",
- mime_fname_rfc2231, q);
-
- if (!decoding_failed)
+ while (isdigit(*++p)) ; /* ignore cont-cnt values */
+ if (*p == '*') p++; /* step over sep chset mark */
+ if (*p == '=')
{
- int size;
- if (!mime_filename_charset)
+ uschar * q;
+ p++; /* step over = */
+ q = mime_param_val(&p); /* p now trailing ; or NUL */
+
+ if (q && *q) /* q is the dequoted value */
{
- uschar * s = q;
+ uschar * err_msg, * fname = q;
+ int slen;
+
+ /* build up an un-decoded filename over successive
+ filename*= parameters (for use when 2047 decode fails) */
- /* look for a ' in the "filename" */
- while(*s != '\'' && *s) s++; /* s is 1st ' or NUL */
+ mime_fname_rfc2231 = string_cat(mime_fname_rfc2231, q);
- if (*s) /* there was a ' */
+ if (!decoding_failed)
{
- if ((size = s-q) > 0)
- mime_filename_charset = string_copyn(q, size);
-
- if (*(fname = s)) fname++;
- while(*fname == '\'') fname++; /* fname is after 2nd ' */
- }
- }
-
- DEBUG(D_acl)
- debug_printf_indent("MIME: charset %s fname '%s'\n",
- mime_filename_charset ? mime_filename_charset : US"<NULL>",
- fname);
-
- temp_string = rfc2231_to_2047(fname, mime_filename_charset,
- &slen);
- DEBUG(D_acl)
- debug_printf_indent("MIME: 2047-name %s\n", temp_string);
-
- temp_string = rfc2047_decode(temp_string, FALSE, NULL, ' ',
- NULL, &err_msg);
- DEBUG(D_acl)
- debug_printf_indent("MIME: plain-name %s\n", temp_string);
-
- if (!temp_string || (size = Ustrlen(temp_string)) == 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;
- } /*!decoding_failed*/
- } /*q*/
- } /*2231 filename*/
-
- else
- /* look for interesting parameters */
- for (mime_parameter * mp = mime_parameter_list;
- mp < mime_parameter_list + nelem(mime_parameter_list);
- mp++
- ) if (strncmpic(mp->name, p, mp->namelen) == 0)
- {
- uschar * q;
- uschar * dummy_errstr;
+ if (!mime_filename_charset)
+ { /* try for RFC 2231 chset/lang */
+ uschar * s = q;
+
+ /* look for a ' in the raw paramval */
+ while(*s != '\'' && *s) s++; /* s is 1st ' or NUL */
+
+ if (*s) /* there was a ' */
+ {
+ int size;
+ if ((size = s-q) > 0)
+ mime_filename_charset = string_copyn(q, size);
+
+ if (*(fname = s)) fname++;
+ while(*fname == '\'') fname++; /*fname is after 2nd '*/
+ }
+ }
+
+ DEBUG(D_acl)
+ debug_printf_indent("MIME: charset %s fname '%s'\n",
+ mime_filename_charset ? mime_filename_charset : US"<NULL>",
+ fname);
+
+ fname = rfc2231_to_2047(fname, mime_filename_charset,
+ &slen);
+ DEBUG(D_acl)
+ debug_printf_indent("MIME: 2047-name %s\n", fname);
+
+ fname = rfc2047_decode(fname, FALSE, NULL, ' ',
+ NULL, &err_msg);
+ DEBUG(D_acl) debug_printf_indent(
+ "MIME: plain-name %s\n", fname);
+
+ if (!fname || Ustrlen(fname) == slen)
+ decoding_failed = TRUE;
+ else if (mp->value == &mime_filename)
+ {
+ /* build up a decoded filename over successive
+ filename*= parameters */
+
+ mime_fname = string_cat(mime_fname, fname);
+ mime_filename = string_from_gstring(mime_fname);
+ }
+ } /*!decoding_failed*/
+ } /*q*/
+
+ if (*p) p++; /* p is past ; */
+ goto param_done; /* done matching param names */
+ } /*2231 param coding extension*/
+ }
+ else if (*p == '=')
+ { /* non-2231 param */
+ uschar * q, * dummy_errstr;
/* grab the value and copy to its expansion variable */
- p += mp->namelen;
+
+ if (*p) p++; /* step over = */
q = mime_param_val(&p); /* p now trailing ; or NUL */
*mp->value = q && *q
"MIME: found %s parameter in %s header, value '%s'\n",
mp->name, mh->name, *mp->value);
- break; /* done matching param names */
+ if (*p) p++; /* p is past ; */
+ goto param_done; /* done matching param names */
}
-
+ } /* interesting parameters */
/* There is something, but not one of our interesting parameters.
Advance past the next semicolon */
+
p = mime_next_semicolon(p);
if (*p) p++;
- } /* param scan on line */
+ param_done:
+ } /* param scan on line */
if (strncmpic(CUS"content-disposition:", header, 20) == 0)
{
- if (decoding_failed) mime_filename = mime_fname_rfc2231;
+ if (decoding_failed)
+ mime_filename = string_from_gstring(mime_fname_rfc2231);
DEBUG(D_acl) debug_printf_indent(
"MIME: found %s parameter in %s header, value is '%s'\n",
"filename", mh->name, mime_filename);
}
}
- }
+ break;
+ } /* interesting headers */
/* set additional flag variables (easier access) */
if ( mime_content_type