]> diplodocus.org Git - nmh/blobdiff - uip/mhfixmsg.c
Update this for From, Resent-From, and Envelope-From. Also document
[nmh] / uip / mhfixmsg.c
index ff189a0edfb426d9c79d312ab7f03852bce96822..fd777699c8fd322f93bfdf2324f84d45132a8cb1 100644 (file)
@@ -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,19 +209,22 @@ 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]))
                     adios (NULL, "missing argument to %s", argp[-2]);
                 file = *cp == '-'  ?  add (cp, NULL)  :  path (cp, TFILE);
                 continue;
-
             case OUTFILESW:
                 if (! (cp = *argp++) || (*cp == '-' && cp[1]))
                     adios (NULL, "missing argument to %s", argp[-2]);
                 outfile = *cp == '-'  ?  add (cp, NULL)  :  path (cp, TFILE);
                 continue;
-
             case RPROCSW:
                 if (!(rmmproc = *argp++) || *rmmproc == '-')
                     adios (NULL, "missing argument to %s", argp[-2]);
@@ -225,7 +232,6 @@ main (int argc, char **argv) {
             case NRPRCSW:
                 rmmproc = NULL;
                 continue;
-
             case VERBSW:
                 verbosw = 1;
                 continue;
@@ -239,8 +245,14 @@ main (int argc, char **argv) {
                 adios (NULL, "only one folder at a time!");
             else
                 folder = pluspath (cp);
-        } else
-                app_msgarg(&msgs, cp);
+        } else {
+            if (*cp == '/') {
+                /* Interpret a full path as a filename, not a message. */
+                file = add (cp, NULL);
+            } else {
+                app_msgarg (&msgs, cp);
+            }
+        }
     }
 
     SIGNAL (SIGQUIT, quitser);
@@ -410,7 +422,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 +886,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 +899,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 +999,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 +1011,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;
     }
@@ -1588,8 +1622,15 @@ strip_crs (CT ct, int *message_mods) {
     char *codeset = upcase (content_codeset (ct));
     int status = OK;
 
-    /* Only strip carriage returns if content is ASCII. */
-    if (! strcmp (norm_charmap (codeset), "US-ASCII")) {
+    /* Only strip carriage returns if content is ASCII or another
+       codeset that has the same readily recognizable CR followed by a
+       LF.  We can include UTF-8 here because if the high-order bit of
+       a UTF-8 byte is 0, then it must be a single-byte ASCII
+       character. */
+    if (! strcmp (norm_charmap (codeset), "US-ASCII")  ||
+        ! strncmp (norm_charmap (codeset), "ISO-8859-", 9)  ||
+        ! strncmp (norm_charmap (codeset), "UTF-8", 5)  ||
+        ! strncmp (norm_charmap (codeset), "WINDOWS-12", 10)) {
         char **file = NULL;
         FILE **fp = NULL;
         size_t begin;
@@ -1672,12 +1713,11 @@ strip_crs (CT ct, int *message_mods) {
                             write (fd, cp, 1);
                             last_char_was_cr = 0;
                         }
-
                     }
                 }
 
                 if (close (fd)) {
-                    admonish (NULL, "unable to write temporaty file %s",
+                    admonish (NULL, "unable to write temporary file %s",
                               stripped_content_file);
                     unlink (stripped_content_file);
                     status = NOTOK;
@@ -1694,7 +1734,9 @@ strip_crs (CT ct, int *message_mods) {
 
                     ++*message_mods;
                     if (verbosw) {
-                        report (NULL, *file, "stripped CRs");
+                        report (ct->c_partno,
+                                begin == 0 && end == 0  ?  ""  :  *file,
+                                "stripped CRs");
                     }
                 }
             }
@@ -1843,7 +1885,8 @@ convert_codeset (CT ct, char *dest_codeset, int *message_mods) {
                                      min (bytes_to_read, sizeof src_buffer),
                                      *fp)) > 0) {
                 char dest_buffer[BUFSIZ];
-                char *ib = src_buffer, *ob = dest_buffer;
+                ICONV_CONST char *ib = src_buffer;
+                char *ob = dest_buffer;
                 size_t outbytes = sizeof dest_buffer;
                 size_t outbytes_before = outbytes;