#include <h/mh.h>
#include <fcntl.h>
-#include <h/signals.h>
#include <h/md5.h>
#include <h/mts.h>
#include <h/tws.h>
int bogus_mp_content;
int suppress_extraneous_trailing_semicolon_warning;
int extraneous_trailing_semicolon;
+int suppress_multiple_mime_version_warning = 1;
+
+/* list of preferred type/subtype pairs, for -prefer */
+char *preferred_types[NPREFS],
+ *preferred_subtypes[NPREFS];
+int npreferred;
+
/*
* Structures for TEXT messages
int find_cache (CT, int, int *, char *, char *, int);
/* mhmisc.c */
-int part_ok (CT, int);
+int part_ok (CT);
int type_ok (CT, int);
void content_error (char *, CT, char *, ...);
static int InitText (CT);
static int InitMultiPart (CT);
static void reverse_parts (CT);
+static void prefer_parts(CT ct);
static int InitMessage (CT);
static int InitApplication (CT);
static int init_encoding (CT, OpenCEFunc);
if (!strcasecmp (hp->name, VRSN_FIELD)) {
int ucmp;
char c, *cp, *dp;
+ char *vrsn;
- if (ct->c_vrsn) {
- advise (NULL, "message %s has multiple %s: fields",
- ct->c_file, VRSN_FIELD);
- goto next_header;
- }
- ct->c_vrsn = add (hp->value, NULL);
+ vrsn = add (hp->value, NULL);
/* Now, cleanup this field */
- cp = ct->c_vrsn;
+ cp = vrsn;
while (isspace ((unsigned char) *cp))
cp++;
admonish (NULL, "message %s has unknown value for %s: field (%s)",
ct->c_file, VRSN_FIELD, cp);
}
+ if (!ct->c_vrsn) {
+ ct->c_vrsn = vrsn;
+ } else {
+ if (! suppress_multiple_mime_version_warning)
+ advise (NULL, "message %s has multiple %s: fields",
+ ct->c_file, VRSN_FIELD);
+ free(vrsn);
+ }
}
else if (!strcasecmp (hp->name, TYPE_FIELD)) {
/* Get Content-Type field */
admonish (NULL,
"\"%s/%s\" type in message %s must be encoded in\n"
- "7bit, 8bit, or binary, per RFC 2045 (6.4). One workaround "
- "is to\nmanually edit the file and change the \"%s\"\n"
+ "7bit, 8bit, or binary, per RFC 2045 (6.4). "
+ "mhfixmsg -fixcte can fix it, or\n"
+ "manually edit the file and change the \"%s\"\n"
"Content-Transfer-Encoding to one of those. For now",
ci->ci_type, ci->ci_subtype, ct->c_file, bp);
free (cte);
last_part:
/* reverse the order of the parts for multipart/alternative */
- if (ct->c_subtype == MULTI_ALTERNATE)
+ if (ct->c_subtype == MULTI_ALTERNATE) {
reverse_parts (ct);
+ prefer_parts (ct);
+ }
/*
* label all subparts with part number, and
/*
- * reverse the order of the parts of a multipart/alternative
+ * reverse the order of the parts of a multipart/alternative,
+ * presumably to put the "most favored" alternative first, for
+ * ease of choosing/displaying it later on. from a mail message on
+ * nmh-workers, from kenh:
+ * "Stock" MH 6.8.5 did not have a reverse_parts() function, but I
+ * see code in mhn that did the same thing... Acccording to the RCS
+ * logs, that code was around from the initial checkin of mhn.c by
+ * John Romine in 1992, which is as far back as we have."
*/
-
static void
reverse_parts (CT ct)
{
}
}
+static void
+move_preferred_part (CT ct, char *type, char *subtype)
+{
+ struct multipart *m = (struct multipart *) ct->c_ctparams;
+ struct part *part, *prev, *head, *nhead, *ntail;
+ struct part h, n;
+ CI ci;
+
+ /* move the matching part(s) to the head of the list: walk the
+ * list of parts, move matching parts to a new list (maintaining
+ * their order), and finally, concatenate the old list onto the
+ * new.
+ */
+
+ head = &h;
+ nhead = &n;
+
+ head->mp_next = m->mp_parts;
+ nhead->mp_next = NULL;
+ ntail = nhead;
+
+ prev = head;
+ part = head->mp_next;
+ while (part != NULL) {
+ ci = &part->mp_part->c_ctinfo;
+ if (!strcasecmp(ci->ci_type, type) &&
+ (!subtype || !strcasecmp(ci->ci_subtype, subtype))) {
+ prev->mp_next = part->mp_next;
+ part->mp_next = NULL;
+ ntail->mp_next = part;
+ ntail = part;
+ part = prev->mp_next;
+ } else {
+ prev = part;
+ part = prev->mp_next;
+ }
+ }
+ ntail->mp_next = head->mp_next;
+ m->mp_parts = nhead->mp_next;
+
+}
+
+/*
+ * move parts that match the user's preferences (-prefer) to the head
+ * of the line. process preferences in reverse so first one given
+ * ends up first in line
+ */
+static void
+prefer_parts(CT ct)
+{
+ int i;
+ for (i = npreferred-1; i >= 0; i--)
+ move_preferred_part(ct, preferred_types[i], preferred_subtypes[i]);
+}
}
if (utf8) {
for (++p, --inbytes;
- inbytes > 0 && (((unsigned char) *q) & 0xc0) == 0x80;
+ inbytes > 0 && (((unsigned char) *p) & 0xc0) == 0x80;
++p, --inbytes)
continue;
} else {