Fix MIME parsing of filenames specified using multiple parameters. Bug 3099
[exim.git] / src / src / mime.c
index 975ddca857b24256be218e5497e08ef0819b1013..5f9e1ade720185914b7f845195b21b9dad78101c 100644 (file)
@@ -587,10 +587,10 @@ while(1)
 
        while (*p)
          {
-         DEBUG(D_acl) debug_printf_indent("MIME:   considering paramlist '%s'\n", p);
+         DEBUG(D_acl)
+           debug_printf_indent("MIME:   considering paramlist '%s'\n", p);
 
-         if (  !mime_filename
-            && strncmpic(CUS"content-disposition:", header, 20) == 0
+         if (  strncmpic(CUS"content-disposition:", header, 20) == 0
             && strncmpic(CUS"filename*", p, 9) == 0
             )
            {                                   /* RFC 2231 filename */
@@ -604,11 +604,12 @@ while(1)
 
            if (q && *q)
              {
-             uschar * temp_string, * err_msg;
+             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);
@@ -623,26 +624,32 @@ while(1)
                  /* 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 (*s)                       /* there was a ' */
+                   {
+                   if ((size = s-q) > 0)
+                     mime_filename_charset = string_copyn(q, size);
 
-                 if (*(p = s)) p++;
-                 while(*p == '\'') p++;        /* p is after 2nd ' */
+                   if (*(fname = s)) fname++;
+                   while(*fname == '\'') fname++;    /* fname is after 2nd ' */
+                   }
                  }
-               else
-                 p = q;
 
-               DEBUG(D_acl) debug_printf_indent("MIME:    charset %s fname '%s'\n",
-                 mime_filename_charset ? mime_filename_charset : US"<NULL>", p);
+               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(p, mime_filename_charset, &slen);
-               DEBUG(D_acl) debug_printf_indent("MIME:    2047-name %s\n", temp_string);
+               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);
+                                             NULL, &err_msg);
+               DEBUG(D_acl)
+                 debug_printf_indent("MIME:    plain-name %s\n", temp_string);
 
-               if (!temp_string || (size = Ustrlen(temp_string))  == slen)
+               if (!temp_string || (size = Ustrlen(temp_string)) == slen)
                  decoding_failed = TRUE;
                else
                  /* build up a decoded filename over successive
@@ -651,9 +658,9 @@ while(1)
                  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 */
@@ -682,7 +689,7 @@ while(1)
 
 
          /* There is something, but not one of our interesting parameters.
-            Advance past the next semicolon */
+         Advance past the next semicolon */
          p = mime_next_semicolon(p);
          if (*p) p++;
          }                             /* param scan on line */
@@ -800,5 +807,5 @@ return rc;
 
 #endif /*WITH_CONTENT_SCAN*/
 
-/* vi: sw ai sw=2
+/* vi: aw ai sw=2
 */