+/*
+ * Decodes UTF-8 encoded header values. Similar to fix_filename_param(), but
+ * does not modify any MIME parameter values.
+ */
+static int
+decode_header_field_bodies (CT ct, int *message_mods)
+{
+ int status = OK;
+
+ switch (ct->c_type) {
+ case CT_MULTIPART: {
+ struct multipart *m = (struct multipart *) ct->c_ctparams;
+ struct part *part;
+
+ for (part = m->mp_parts; status == OK && part; part = part->mp_next) {
+ status = decode_header_field_bodies (part->mp_part, message_mods);
+ }
+ break;
+ }
+
+ case CT_MESSAGE:
+ if (ct->c_subtype == MESSAGE_EXTERNAL) {
+ struct exbody *e = (struct exbody *) ct->c_ctparams;
+
+ status = decode_header_field_bodies (e->eb_content, message_mods);
+ }
+ break;
+ }
+
+ HF hf;
+
+ for (hf = ct->c_first_hf; hf; hf = hf->next) {
+ /* Only decode UTF-8 values. */
+ if (hf->value && has_suffix(hf->value, "?=\n") &&
+ (! strncasecmp (hf->value, " =?utf8?", 8) ||
+ ! strncasecmp (hf->value, " =?utf-8?", 9))) {
+ /* Looks like an RFC 2047 encoded parameter. */
+ char decoded[PATH_MAX + 1];
+
+ if (decode_rfc2047 (hf->value, decoded, sizeof decoded)) {
+ const size_t len = strlen(decoded);
+
+ /* decode_rfc2047() could truncate if the buffer fills up.
+ Detect and discard if that happened. */
+ if (len < sizeof(decoded) - 1 && strcmp(hf->value, decoded)) {
+ hf->value = mh_xrealloc (hf->value, len + 1);
+ strncpy (hf->value, decoded, len + 1);
+ ++*message_mods;
+ }
+ } else {
+ inform("failed to decode %s parameter %s", hf->name, hf->value);
+ status = NOTOK;
+ }
+ }
+ }
+
+ return status;
+}
+
+
+/*
+ * Factor out common code for loops in fix_filename_encoding().
+ */
+static int
+fix_filename_param (char *name, char *value, PM *first_pm, PM *last_pm)
+{
+ bool fixed = false;
+
+ if (has_prefix(value, "=?") && has_suffix(value, "?=")) {
+ /* Looks like an RFC 2047 encoded parameter. */
+ char decoded[PATH_MAX + 1];
+
+ if (decode_rfc2047 (value, decoded, sizeof decoded)) {
+ /* Encode using RFC 2231. */
+ replace_param (first_pm, last_pm, name, decoded, 0);
+ fixed = true;
+ } else {
+ inform("failed to decode %s parameter %s", name, value);
+ }
+ }
+
+ return fixed;
+}
+
+
+/*
+ * Replace RFC 2047 encoding with RFC 2231 encoding of name and
+ * filename parameters in Content-Type and Content-Disposition
+ * headers, respectively.
+ */