]> diplodocus.org Git - nmh/blobdiff - uip/mhfixmsg.c
Added context_find_prefix().
[nmh] / uip / mhfixmsg.c
index 8a586182c599380ada477e48fbbd77a39e9a8b73..d3c23767b8928c7a4ce822d2236a41b0423c7815 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * mhfixmsg.c -- rewrite a message with various tranformations
+ * mhfixmsg.c -- rewrite a message with various transformations
  *
  * This code is Copyright (c) 2002 and 2013, by the authors of nmh.
  * See the COPYRIGHT file in the root directory of the nmh
@@ -91,6 +91,7 @@ typedef struct fix_transformations {
 
 int mhfixmsgsbr (CT *, const fix_transformations *, char *);
 static int fix_boundary (CT *, int *);
+static int copy_input_to_output (const char *, const char *);
 static int get_multipart_boundary (CT, char **);
 static int replace_boundary (CT, char *, char *);
 static int fix_types (CT, svector_t, int *);
@@ -118,8 +119,9 @@ static int content_encoding (CT, const char **);
 static int strip_crs (CT, int *);
 static int convert_charsets (CT, char *, int *);
 static int fix_always (CT, int *);
-static int write_content (CT, char *, char *, int, int);
-static int remove_file (char *);
+static int write_content (CT, const char *, char *, int, int);
+static void set_text_ctparams(CT, char *, int);
+static int remove_file (const char *);
 static void report (char *, char *, char *, char *, ...);
 static void pipeser (int);
 
@@ -346,16 +348,21 @@ main (int argc, char **argv) {
         ctp = cts;
 
         if ((ct = parse_mime (file))) {
-            if (ct->c_type == CT_TEXT) {
-                /* parse_mime() does not set lf_line_endings in struct text, so set it here. */
-                if (ct->c_ctparams == NULL) {
-                    if ((ct->c_ctparams = (struct text *) mh_xcalloc (1, sizeof (struct text))) == NULL) {
-                        adios (NULL, "out of memory");
-                    }
+            set_text_ctparams(ct, fx.decodetypes, fx.lf_line_endings);
+            *ctp++ = ct;
+        } else {
+            advise (NULL, "unable to parse message from file %s", file);
+            status = NOTOK;
+
+            /* If there's an outfile, pass the input message unchanged, so the message won't
+               get dropped from a pipeline. */
+            if (outfile) {
+                /* Something went wrong.  Output might be expected, such as if this were run
+                   as a filter.  Just copy the input to the output. */
+                if (copy_input_to_output (file, outfile) != OK) {
+                    advise (NULL, "unable to copy message to %s, it might be lost\n", outfile);
                 }
-                ((struct text *) ct->c_ctparams)->lf_line_endings = fx.lf_line_endings;
             }
-            *ctp++ = ct;
         }
     } else {
         /*
@@ -398,17 +405,23 @@ main (int argc, char **argv) {
 
                 msgnam = m_name (msgnum);
                 if ((ct = parse_mime (msgnam))) {
-                    if (ct->c_type == CT_TEXT) {
-                        /* parse_mime() does not set lf_line_endings in struct text, so set it here. */
-                        if (ct->c_ctparams == NULL) {
-                            if ((ct->c_ctparams = (struct text *) mh_xcalloc (1, sizeof (struct text))) ==
-                                NULL) {
-                                adios (NULL, "out of memory");
-                            }
+                    set_text_ctparams(ct, fx.decodetypes, fx.lf_line_endings);
+                    *ctp++ = ct;
+                } else {
+                    advise (NULL, "unable to parse message %s", msgnam);
+                    status = NOTOK;
+
+                    /* If there's an outfile, pass the input message unchanged, so the message won't
+                       get dropped from a pipeline. */
+                    if (outfile) {
+                        /* Something went wrong.  Output might be expected, such as if this were run
+                           as a filter.  Just copy the input to the output. */
+                        const char *input_filename = path (msgnam, TFILE);
+
+                        if (copy_input_to_output (input_filename, outfile) != OK) {
+                            advise (NULL, "unable to copy message to %s, it might be lost\n", outfile);
                         }
-                        ((struct text *) ct->c_ctparams)->lf_line_endings = fx.lf_line_endings;
                     }
-                    *ctp++ = ct;
                 }
             }
         }
@@ -516,19 +529,9 @@ mhfixmsgsbr (CT *ctp, const fix_transformations *fx, char *outfile) {
         /* Something went wrong.  Output might be expected, such
            as if this were run as a filter.  Just copy the input
            to the output. */
-        int in = open (input_filename, O_RDONLY);
-        int out = strcmp (outfile, "-")
-            ?  open (outfile, O_WRONLY | O_CREAT, m_gmprot ())
-            :  STDOUT_FILENO;
-
-        if (in != -1  &&  out != -1) {
-            cpydata (in, out, input_filename, outfile);
-        } else {
-            status = NOTOK;
+        if (copy_input_to_output (input_filename, outfile) != OK) {
+            advise (NULL, "unable to copy message to %s, it might be lost\n", outfile);
         }
-
-        close (out);
-        close (in);
     }
 
     if (modify_inplace) {
@@ -543,6 +546,29 @@ mhfixmsgsbr (CT *ctp, const fix_transformations *fx, char *outfile) {
 }
 
 
+/* Copy input message to output.  Assumes not modifying in place, so this
+   might be running as part of a pipeline. */
+static int
+copy_input_to_output (const char *input_filename, const char *output_filename) {
+    int in = open (input_filename, O_RDONLY);
+    int out = strcmp (output_filename, "-")
+        ?  open (output_filename, O_WRONLY | O_CREAT, m_gmprot ())
+        :  STDOUT_FILENO;
+    int status = OK;
+
+    if (in != -1  &&  out != -1) {
+        cpydata (in, out, input_filename, output_filename);
+    } else {
+        status = NOTOK;
+    }
+
+    close (out);
+    close (in);
+
+    return status;
+}
+
+
 static int
 fix_boundary (CT *ct, int *message_mods) {
     struct multipart *mp;
@@ -599,7 +625,16 @@ fix_boundary (CT *ct, int *message_mods) {
                 }
 
                 free (part_boundary);
+            } else {
+                /* Couldn't fix the boundary.  Report failure so that mhfixmsg
+                   doesn't modify the message. */
+                status = NOTOK;
             }
+        } else {
+            /* No multipart struct, even though the content type is
+               CT_MULTIPART.  Report failure so that mhfixmsg doesn't modify
+               the message. */
+            status = NOTOK;
         }
     }
 
@@ -1821,8 +1856,7 @@ decode_text_parts (CT ct, int encoding, const char *decodetypes, int *message_mo
         }
 
         lf_line_endings =
-            ct->c_type == CT_TEXT  &&  ct->c_ctparams  &&
-            ((struct text *) ct->c_ctparams)->lf_line_endings;
+            ct->c_ctparams  &&  ((struct text *) ct->c_ctparams)->lf_line_endings;
 
         switch (ct->c_encoding) {
         case CE_BASE64:
@@ -2283,7 +2317,7 @@ fix_always (CT ct, int *message_mods) {
 
 
 static int
-write_content (CT ct, char *input_filename, char *outfile, int modify_inplace,
+write_content (CT ct, const char *input_filename, char *outfile, int modify_inplace,
                int message_mods) {
     int status = OK;
 
@@ -2356,12 +2390,50 @@ write_content (CT ct, char *input_filename, char *outfile, int modify_inplace,
 }
 
 
+/*
+ * parse_mime() does not set lf_line_endings in struct text, so use this function to do it.
+ * It touches the parts the decodetypes identifies.
+ */
+static void
+set_text_ctparams(CT ct, char *decodetypes, int lf_line_endings) {
+    switch (ct->c_type) {
+    case CT_MULTIPART: {
+        struct multipart *m = (struct multipart *) ct->c_ctparams;
+        struct part *part;
+
+        for (part = m->mp_parts; part; part = part->mp_next) {
+            set_text_ctparams(part->mp_part, decodetypes, lf_line_endings);
+        }
+        break;
+    }
+
+    case CT_MESSAGE:
+        if (ct->c_subtype == MESSAGE_EXTERNAL) {
+            struct exbody *e = (struct exbody *) ct->c_ctparams;
+
+            set_text_ctparams(e->eb_content, decodetypes, lf_line_endings);
+        }
+        break;
+
+    default:
+        if (should_decode(decodetypes, ct->c_ctinfo.ci_type, ct->c_ctinfo.ci_subtype)) {
+            if (ct->c_ctparams == NULL) {
+                if ((ct->c_ctparams = (struct text *) mh_xcalloc (1, sizeof (struct text))) == NULL) {
+                    adios (NULL, "out of memory");
+                }
+            }
+            ((struct text *) ct->c_ctparams)->lf_line_endings = lf_line_endings;
+        }
+    }
+}
+
+
 /*
  * If "rmmproc" is defined, call that to remove the file.  Otherwise,
  * use the standard MH backup file.
  */
 static int
-remove_file (char *file) {
+remove_file (const char *file) {
     if (rmmproc) {
         char *rmm_command = concat (rmmproc, " ", file, NULL);
         int status = system (rmm_command);