+static void
+mime_vars_reset(void)
+{
+mime_anomaly_level = 0;
+mime_anomaly_text = NULL;
+mime_boundary = NULL;
+mime_charset = NULL;
+mime_decoded_filename = NULL;
+mime_filename = NULL;
+mime_content_description = NULL;
+mime_content_disposition = NULL;
+mime_content_id = NULL;
+mime_content_transfer_encoding = NULL;
+mime_content_type = NULL;
+mime_is_multipart = 0;
+mime_content_size = 0;
+}
+
+
+/* Grab a parameter value, dealing with quoting.
+
+Arguments:
+ str Input string. Updated on return to point to terminating ; or NUL
+
+Return:
+ Allocated string with parameter value
+*/
+static uschar *
+mime_param_val(uschar ** sp)
+{
+uschar * s = *sp;
+gstring * val = NULL;
+
+/* debug_printf_indent(" considering paramval '%s'\n", s); */
+
+while (*s && *s != ';') /* ; terminates */
+ if (*s == '"')
+ {
+ s++; /* skip opening " */
+ while (*s && *s != '"') /* " protects ; */
+ val = string_catn(val, s++, 1);
+ if (*s) s++; /* skip closing " */
+ }
+ else
+ val = string_catn(val, s++, 1);
+*sp = s;
+return string_from_gstring(val);
+}
+
+static uschar *
+mime_next_semicolon(uschar * s)
+{
+while (*s && *s != ';') /* ; terminates */
+ if (*s == '"')
+ {
+ s++; /* skip opening " */
+ while (*s && *s != '"') /* " protects ; */
+ s++;
+ if (*s) s++; /* skip closing " */
+ }
+ else
+ s++;
+return s;
+}
+
+
+static uschar *
+rfc2231_to_2047(const uschar * fname, const uschar * charset, int * len)
+{
+gstring * val = string_catn(NULL, US"=?", 2);
+uschar c;
+
+if (charset)
+ val = string_cat(val, charset);
+val = string_catn(val, US"?Q?", 3);
+
+while ((c = *fname))
+ if (c == '%' && isxdigit(fname[1]) && isxdigit(fname[2]))
+ {
+ val = string_catn(val, US"=", 1);
+ val = string_catn(val, ++fname, 2);
+ fname += 2;
+ }
+ else
+ val = string_catn(val, fname++, 1);
+
+val = string_catn(val, US"?=", 2);
+*len = val->ptr;
+return string_from_gstring(val);
+}
+
+