From c4bc9ed8bee57f8fd58ad10fb5d8941e090993db Mon Sep 17 00:00:00 2001 From: Ken Hornstein Date: Sun, 12 May 2019 20:07:56 -0400 Subject: [PATCH] Cleanup MIME header handling in mhbuild Per discussion on nmh-workers, cleanup the handling of MIME headers in mhbuild. The following logic should now apply. If mhbuild is run with -auto AND a MIME-Version header is detected, then exit silently with no error (and leave the draft untouched). Otherwise, if a MIME-Version header or ANY Content-* header is found, exit with an error. Note that this means if mhbuild is run with -auto then an error will be returned if any Content-* headers are seen. Previously, mhbuild would silently eat any Content-Type headers seen in an existing draft; this behavior was brought forward from MH 6 and no one could explain the reason for this behavior. This behavior has been removed. --- man/mhbuild.man | 13 ++++- test/mhbuild/test-mhbuild | 107 ++++++++++++++++++++++++++++++++++++++ uip/mhbuildsbr.c | 36 ++++++++----- 3 files changed, 143 insertions(+), 13 deletions(-) diff --git a/man/mhbuild.man b/man/mhbuild.man index 46a05074..47d9f874 100644 --- a/man/mhbuild.man +++ b/man/mhbuild.man @@ -969,13 +969,24 @@ Template for composing contents. (RFC 6531) .SH DEFAULTS .nf +\-noauto \-autoheaderencoding \-contentid \-headers \-maxunencoded 78 -\-nocheck \-nodisposition \-norfc934mode \-noverbose \-realsize +.SH DEFAULTS (with \-auto) +.nf +\-autoheaderencoding +\-contentid +\-headers +\-maxunencoded 78 +\-nodisposition +\-norfc934mode +\-noverbose +\-realsize +\-nodirectives .fi diff --git a/test/mhbuild/test-mhbuild b/test/mhbuild/test-mhbuild index 8d08661a..6f69080e 100755 --- a/test/mhbuild/test-mhbuild +++ b/test/mhbuild/test-mhbuild @@ -36,6 +36,113 @@ EOF run_test "mhbuild -nodirectives `mhpath last`" check "`mhpath last`" "$expected" +start_test "Checking for MIME-Version handling in draft" + +cat > "`mhpath new`" <<'EOF' +From: Somebody +To: Nobody +Subject: Test message +MIME-Version: 1.0 +-------- +This is a test +EOF + +cat >"$expected" <<'EOF' +From: Somebody +To: Nobody +Subject: Test message +MIME-Version: 1.0 +-------- +This is a test +EOF + +run_test "mhbuild `mhpath last`" "mhbuild: draft shouldn't contain MIME-Version: field" +check "`mhpath last`" "$expected" 'keep first' + +cat >"$expected" <<'EOF' +From: Somebody +To: Nobody +Subject: Test message +MIME-Version: 1.0 +-------- +This is a test +EOF + +run_test "mhbuild -auto `mhpath last`" +check "`mhpath last`" "$expected" + +start_test "Checking for arbitrary Content header handling in draft" + +cat > "`mhpath new`" <<'EOF' +From: Somebody +To: Nobody +Subject: Test message +Content-Fart: nothing +-------- +This is a test +EOF + +cat >"$expected" <<'EOF' +From: Somebody +To: Nobody +Subject: Test message +Content-Fart: nothing +-------- +This is a test +EOF + +run_test "mhbuild `mhpath last`" "mhbuild: draft shouldn't contain Content-Fart: field" +check "`mhpath last`" "$expected" 'keep first' + +cat >"$expected" <<'EOF' +From: Somebody +To: Nobody +Subject: Test message +Content-Fart: nothing +-------- +This is a test +EOF + +run_test "mhbuild -auto `mhpath last`" "mhbuild: draft shouldn't contain Content-Fart: field" +check "`mhpath last`" "$expected" + +start_test "Checking for out-of-order Content header handling in draft" + +cat > "`mhpath new`" <<'EOF' +From: Somebody +To: Nobody +Subject: Test message +Content-Fart: nothing +MIME-Version: 1.0 +-------- +This is a test +EOF + +cat >"$expected" <<'EOF' +From: Somebody +To: Nobody +Subject: Test message +Content-Fart: nothing +MIME-Version: 1.0 +-------- +This is a test +EOF + +run_test "mhbuild `mhpath last`" "mhbuild: draft shouldn't contain MIME-Version: field" +check "`mhpath last`" "$expected" 'keep first' + +cat >"$expected" <<'EOF' +From: Somebody +To: Nobody +Subject: Test message +Content-Fart: nothing +MIME-Version: 1.0 +-------- +This is a test +EOF + +run_test "mhbuild -auto `mhpath last`" +check "`mhpath last`" "$expected" finish_test exit $failed diff --git a/uip/mhbuildsbr.c b/uip/mhbuildsbr.c index 04dc4a7b..b96e63ac 100644 --- a/uip/mhbuildsbr.c +++ b/uip/mhbuildsbr.c @@ -190,9 +190,20 @@ build_mime (char *infile, int autobuild, int dist, int directives, case FLDPLUS: compnum++; - /* abort if draft has Mime-Version or C-T-E header field */ - if (strcasecmp (name, VRSN_FIELD) == 0 || - strcasecmp (name, ENCODING_FIELD) == 0) { + /* + * If we are running with autobuild set, then silently + * exit if we find a MIME-Version header. For any other MIME + * header, return an error. + * + * RFC 2045, Section 9 says that any valid MIME header should + * start with "Content-", so we will match on that rather than + * enumerate all current MIME headers. + * + * Because the headers could be in any order, just check for + * MIME-Version here; check for Content-* later. + */ + + if (strcasecmp (name, VRSN_FIELD) == 0) { if (autobuild) { fclose(in); free (ct); @@ -201,15 +212,6 @@ build_mime (char *infile, int autobuild, int dist, int directives, die("draft shouldn't contain %s: field", name); } - /* ignore any Content-Type fields in the header */ - if (!strcasecmp (name, TYPE_FIELD)) { - while (state == FLDPLUS) { - bufsz = sizeof buf; - state = m_getfld2(&gstate, name, buf, &bufsz); - } - goto finish_field; - } - /* get copies of the buffers */ np = mh_xstrdup(name); vp = mh_xstrdup(buf); @@ -365,6 +367,16 @@ finish_field: } m_getfld_state_destroy (&gstate); + /* + * If we see any Content-* headers at this point, it is an error. + */ + + for (hp = ct->c_first_hf; hp != NULL; hp = hp->next) { + if (uprf (hp->name, "Content-")) { + die ("draft shouldn't contain %s: field", hp->name); + } + } + if (header_encoding != CE_8BIT) { /* * Iterate through the list of headers and call the function to MIME-ify -- 2.56.0