+ /*
+ ** Read the content headers. We will parse the
+ ** MIME related header fields into their various
+ ** structures and set internal flags related to
+ ** content type/subtype, etc.
+ */
+
+ hp = ct->c_first_hf; /* start at first header field */
+ while (hp) {
+ /* Get MIME-Version field */
+ if (!mh_strcasecmp(hp->name, VRSN_FIELD)) {
+ int ucmp;
+ char c;
+ unsigned char *cp, *dp;
+
+ if (ct->c_vrsn) {
+ advise(NULL, "message %s has multiple %s: fields", ct->c_file, VRSN_FIELD);
+ goto next_header;
+ }
+ ct->c_vrsn = mh_xstrdup(hp->value);
+
+ /* Now, cleanup this field */
+ cp = ct->c_vrsn;
+
+ while (isspace(*cp))
+ cp++;
+ for (dp = strchr(cp, '\n'); dp; dp = strchr(dp, '\n'))
+ *dp++ = ' ';
+ for (dp = cp + strlen(cp) - 1; dp >= cp; dp--)
+ if (!isspace(*dp))
+ break;
+ *++dp = '\0';
+ if (debugsw)
+ fprintf(stderr, "%s: %s\n", VRSN_FIELD, cp);
+
+ if (*cp == '(' && get_comment(ct, &cp, 0) == NOTOK)
+ goto out;
+
+ for (dp = cp; istoken(*dp); dp++)
+ continue;
+ c = *dp;
+ *dp = '\0';
+ ucmp = !mh_strcasecmp(cp, VRSN_VALUE);
+ *dp = c;
+ if (!ucmp) {
+ admonish(NULL, "message %s has unknown value for %s: field (%s)", ct->c_file, VRSN_FIELD, cp);
+ }
+
+ } else if (!mh_strcasecmp(hp->name, TYPE_FIELD)) {
+ /* Get Content-Type field */
+ struct str2init *s2i;
+ CI ci = &ct->c_ctinfo;
+
+ /* Check if we've already seen a Content-Type header */
+ if (ct->c_ctline) {
+ advise(NULL, "message %s has multiple %s: fields", ct->c_file, TYPE_FIELD);
+ goto next_header;
+ }
+
+ /* Parse the Content-Type field */
+ if (get_ctinfo(hp->value, ct, 0) == NOTOK)
+ goto out;
+
+ /*
+ ** Set the Init function and the internal
+ ** flag for this content type.
+ */
+ for (s2i = str2cts; s2i->si_key; s2i++)
+ if (!mh_strcasecmp(ci->ci_type, s2i->si_key))
+ break;
+ if (!s2i->si_key && !uprf(ci->ci_type, "X-"))
+ s2i++;
+ ct->c_type = s2i->si_val;
+ ct->c_ctinitfnx = s2i->si_init;
+
+ } else if (!mh_strcasecmp(hp->name, ENCODING_FIELD)) {
+ /* Get Content-Transfer-Encoding field */
+ char c;
+ unsigned char *cp, *dp;
+ struct str2init *s2i;
+
+ /*
+ ** Check if we've already seen the
+ ** Content-Transfer-Encoding field
+ */
+ if (ct->c_celine) {
+ advise(NULL, "message %s has multiple %s: fields", ct->c_file, ENCODING_FIELD);
+ goto next_header;
+ }
+
+ /* get copy of this field */
+ ct->c_celine = cp = mh_xstrdup(hp->value);
+
+ while (isspace(*cp))
+ cp++;
+ for (dp = cp; istoken(*dp); dp++)
+ continue;
+ c = *dp;
+ *dp = '\0';
+
+ /*
+ ** Find the internal flag and Init function
+ ** for this transfer encoding.
+ */
+ for (s2i = str2ces; s2i->si_key; s2i++)
+ if (!mh_strcasecmp(cp, s2i->si_key))
+ break;
+ if (!s2i->si_key && !uprf(cp, "X-"))
+ s2i++;
+ *dp = c;
+ ct->c_encoding = s2i->si_val;
+
+ /* Call the Init function for this encoding */
+ if (s2i->si_init && (*s2i->si_init) (ct) == NOTOK)
+ goto out;
+
+ } else if (!mh_strcasecmp(hp->name, ID_FIELD)) {
+ /* Get Content-ID field */
+ ct->c_id = add(hp->value, ct->c_id);
+
+ } else if (!mh_strcasecmp(hp->name, DESCR_FIELD)) {
+ /* Get Content-Description field */
+ ct->c_descr = add(hp->value, ct->c_descr);
+
+ } else if (!mh_strcasecmp(hp->name, DISPO_FIELD)) {
+ /* Get Content-Disposition field */
+ ct->c_dispo = add(hp->value, ct->c_dispo);
+ }
+