+/*
+ * 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;
+}
+
+