From: David Levine Date: Mon, 19 Aug 2013 05:42:01 +0000 (-0500) Subject: Added -replacetextplain switch to mhfixmsg. If enabled, -reformat X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/74e9deda951a5b0151e18225c87f567f72ee11a4?ds=sidebyside;hp=a9dd3e44a1d78e038a97c54f27aa778f41371ae9 Added -replacetextplain switch to mhfixmsg. If enabled, -reformat will replace any existing text/plain part, such as those that are empty or that don't match their corresponding text/html part. --- diff --git a/man/mhfixmsg.man b/man/mhfixmsg.man index 629014d6..9996d304 100644 --- a/man/mhfixmsg.man +++ b/man/mhfixmsg.man @@ -17,6 +17,7 @@ mhfixmsg \- rewrite MIME messages with various transformations .I codeset .RB "| " \-notextcodeset ] .RB [ \-reformat " | " \-noreformat ] +.RB [ \-replacetextplain " | " \-noreplacetextplain ] .RB [ \-fixboundary " | " \-nofixboundary ] .RB [ \-fixcte " | " \-nofixcte ] .RB [ \-file @@ -93,6 +94,16 @@ inserts that text/plain part at the beginning of the containing multipart/alternative part, if present. If not, it creates a multipart/alternative part. .PP +The +.B \-replacetextplain +switch broadens the applicability of +.B \-reformat +by always replacing a corresponding text/plain part, if one exists. +If +.B \-verbose +if enabled, the replacement will be shown as two steps: a removal of +the text/plain part followed by the usual insertion of a new part. +.PP .B \-reformat requires a profile entry for each text part subtype to be reformatted. The mhfixmsg-format-text/subtype profile entries are based on external @@ -300,6 +311,7 @@ is checked. .RB ` "\-decodetext 8bit"' .RB ` \-notextcodeset ' .RB ` \-reformat ' +.RB ` \-noreplacetextplain ' .RB ` \-fixboundary ' .RB ` \-fixcte ' .RB ` \-noverbose ' diff --git a/test/mhfixmsg/test-mhfixmsg b/test/mhfixmsg/test-mhfixmsg index 851c3c97..1a01de2f 100755 --- a/test/mhfixmsg/test-mhfixmsg +++ b/test/mhfixmsg/test-mhfixmsg @@ -41,6 +41,7 @@ Usage: mhfixmsg [+folder] [msgs] [switches] -nodecodetext -[no]textcodeset -[no]reformat + -[no]replacetextplain -[no]fixboundary -[no]fixcte -file file @@ -943,6 +944,104 @@ mhfixmsg last -outfile "$actual" check "$expected" "$actual" +# check -replacetextplain +cat >"$expected" < +eticket + + + Yes, the text/plain part really was empty. + + + +------=_Part_876302-- +EOF + +cat >`mhpath new` <<'EOF' +To: recipient@example.com +From: sender@example.com +Subject: mhfixmsg replacement of bad text/plain part test +MIME-Version: 1.0 +Content-Type: multipart/alternative; boundary="----=_Part_876302" + +------=_Part_876302 +Content-Type: text/plain; charset="iso-8859-15" +Content-Transfer-Encoding: 7bit +Content-Disposition: inline + + + +------=_Part_876302 +Content-Type: text/html; charset="UTF-8" +Content-Transfer-Encoding: 8bit +Content-Disposition: inline + + +eticket + + + Yes, the text/plain part really was empty. + + + +------=_Part_876302-- +EOF + +mhfixmsg last -replacetextplain -outfile "$actual" +check "$expected" "$actual" + +# check -noreplacetextplain +cat >"$expected" < +eticket + + + Yes, the text/plain part really was empty. + + + +------=_Part_876302-- +EOF + +mhfixmsg last -replacetextplain -noreplacetextplain -outfile "$actual" +check "$expected" "$actual" + + # check rmmproc cat >"$MH_TEST_DIR/Mail/rmmproc" <<'EOF' mv "$1" "$1.backup" diff --git a/uip/mhfixmsg.c b/uip/mhfixmsg.c index ff189a0e..0548f1b2 100644 --- a/uip/mhfixmsg.c +++ b/uip/mhfixmsg.c @@ -23,6 +23,8 @@ X("notextcodeset", 0, NTEXTCODESETSW) \ X("reformat", 0, REFORMATSW) \ X("noreformat", 0, NREFORMATSW) \ + X("replacetextplain", 0, REPLACETEXTPLAINSW) \ + X("noreplacetextplain", 0, NREPLACETEXTPLAINSW) \ X("fixboundary", 0, FIXBOUNDARYSW) \ X("nofixboundary", 0, NFIXBOUNDARYSW) \ X("fixcte", 0, FIXCTESW) \ @@ -78,6 +80,7 @@ typedef struct fix_transformations { int fixboundary; int fixcte; int reformat; + int replacetextplain; int decodetext; char *textcodeset; } fix_transformations; @@ -90,7 +93,7 @@ static int replace_boundary (CT, char *, const char *); static char *update_attr (char *, const char *, const char *e); static int fix_multipart_cte (CT, int *); static int set_ce (CT, int); -static int ensure_text_plain (CT *, CT, int *); +static int ensure_text_plain (CT *, CT, int *, int); static CT build_text_plain_part (CT); static CT divide_part (CT); static void copy_ctinfo (CI, CI); @@ -128,6 +131,7 @@ main (int argc, char **argv) { int status = OK; fix_transformations fx; fx.reformat = fx.fixcte = fx.fixboundary = 1; + fx.replacetextplain = 0; fx.decodetext = CE_8BIT; fx.textcodeset = NULL; @@ -205,6 +209,12 @@ main (int argc, char **argv) { case NREFORMATSW: fx.reformat = 0; continue; + case REPLACETEXTPLAINSW: + fx.replacetextplain = 1; + continue; + case NREPLACETEXTPLAINSW: + fx.replacetextplain = 0; + continue; case FILESW: if (! (cp = *argp++) || (*cp == '-' && cp[1])) @@ -410,7 +420,8 @@ mhfixmsgsbr (CT *ctp, const fix_transformations *fx, char *outfile) { status = fix_multipart_cte (*ctp, &message_mods); } if (status == OK && fx->reformat) { - status = ensure_text_plain (ctp, NULL, &message_mods); + status = + ensure_text_plain (ctp, NULL, &message_mods, fx->replacetextplain); } if (status == OK && fx->decodetext) { status = decode_text_parts (*ctp, fx->decodetext, &message_mods); @@ -873,7 +884,7 @@ set_ce (CT ct, int encoding) { /* Make sure each text part has a corresponding text/plain part. */ static int -ensure_text_plain (CT *ct, CT parent, int *message_mods) { +ensure_text_plain (CT *ct, CT parent, int *message_mods, int replacetextplain) { int status = OK; switch ((*ct)->c_type) { @@ -886,17 +897,36 @@ ensure_text_plain (CT *ct, CT parent, int *message_mods) { if (parent && parent->c_type == CT_MULTIPART && parent->c_subtype == MULTI_ALTERNATE) { struct multipart *mp = (struct multipart *) parent->c_ctparams; - struct part *part; + struct part *part, *prev; int new_subpart_number = 1; /* See if there is a sibling text/plain. */ - for (part = mp->mp_parts; part; part = part->mp_next) { + for (prev = part = mp->mp_parts; part; part = part->mp_next) { ++new_subpart_number; if (part->mp_part->c_type == CT_TEXT && part->mp_part->c_subtype == TEXT_PLAIN) { - has_text_plain = 1; + if (replacetextplain) { + struct part *old_part; + if (part == mp->mp_parts) { + old_part = mp->mp_parts; + mp->mp_parts = part->mp_next; + } else { + old_part = prev->mp_next; + prev->mp_next = part->mp_next; + } + if (verbosw) { + report (parent->c_partno, parent->c_file, + "remove text/plain part %s", + old_part->mp_part->c_partno); + } + free_content (old_part->mp_part); + free (old_part); + } else { + has_text_plain = 1; + } break; } + prev = part; } if (! has_text_plain) { @@ -967,7 +997,8 @@ ensure_text_plain (CT *ct, CT parent, int *message_mods) { for (part = mp->mp_parts; status == OK && part; part = part->mp_next) { if ((*ct)->c_type == CT_MULTIPART) { - status = ensure_text_plain (&part->mp_part, *ct, message_mods); + status = ensure_text_plain (&part->mp_part, *ct, message_mods, + replacetextplain); } } break; @@ -978,7 +1009,8 @@ ensure_text_plain (CT *ct, CT parent, int *message_mods) { struct exbody *e; e = (struct exbody *) (*ct)->c_ctparams; - status = ensure_text_plain (&e->eb_content, *ct, message_mods); + status = ensure_text_plain (&e->eb_content, *ct, message_mods, + replacetextplain); } break; }