]> diplodocus.org Git - nmh/blobdiff - uip/mhfixmsg.c
Remove mhbuild backup files at end of a couple of tests, if successful.
[nmh] / uip / mhfixmsg.c
index d81337d6e42534ea2eec6b994f4939580a93e454..df475646d993ecb771a9f8bc100e3260635f9a6b 100644 (file)
 #include <h/utils.h>
 #include <h/signals.h>
 #include <fcntl.h>
-#ifdef HAVE_ICONV
-#   include <iconv.h>
-#endif
 
 #define MHFIXMSG_SWITCHES \
     X("decodetext 8bit|7bit", 0, DECODETEXTSW) \
     X("nodecodetext", 0, NDECODETEXTSW) \
-    X("textcodeset", 0, TEXTCODESETSW) \
-    X("notextcodeset", 0, NTEXTCODESETSW) \
+    X("textcharset", 0, TEXTCHARSETSW) \
+    X("notextcharset", 0, NTEXTCHARSETSW) \
     X("reformat", 0, REFORMATSW) \
     X("noreformat", 0, NREFORMATSW) \
     X("replacetextplain", 0, REPLACETEXTPLAINSW) \
@@ -81,7 +78,7 @@ typedef struct fix_transformations {
     int reformat;
     int replacetextplain;
     int decodetext;
-    char *textcodeset;
+    char *textcharset;
 } fix_transformations;
 
 int mhfixmsgsbr (CT *, const fix_transformations *, char *);
@@ -89,7 +86,6 @@ static void reverse_alternative_parts (CT);
 static int fix_boundary (CT *, int *);
 static int get_multipart_boundary (CT, char **);
 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 *, int);
@@ -106,13 +102,10 @@ static int set_ct_type (CT, int type, int subtype, int encoding);
 static int decode_text_parts (CT, int, int *);
 static int content_encoding (CT);
 static int strip_crs (CT, int *);
-static int convert_codesets (CT, char *, int *);
-static int convert_codeset (CT, char *, int *);
-static char *content_codeset (CT);
+static int convert_charsets (CT, char *, int *);
 static int write_content (CT, char *, char *, int, int);
 static int remove_file (char *);
 static void report (char *, char *, char *, ...);
-static char *upcase (char *);
 static void pipeser (int);
 
 
@@ -132,17 +125,11 @@ main (int argc, char **argv) {
     fx.reformat = fx.fixcte = fx.fixboundary = 1;
     fx.replacetextplain = 0;
     fx.decodetext = CE_8BIT;
-    fx.textcodeset = NULL;
+    fx.textcharset = NULL;
 
-    done = freects_done;
-
-#ifdef LOCALE
-    setlocale(LC_ALL, "");
-#endif
-    invo_name = r1bindex (argv[0], '/');
+    if (nmh_init(argv[0], 1)) { return 1; }
 
-    /* read user profile/context */
-    context_read();
+    done = freects_done;
 
     arguments = getarguments (invo_name, argc, argv, 1);
     argp = arguments;
@@ -182,13 +169,13 @@ main (int argc, char **argv) {
             case NDECODETEXTSW:
                 fx.decodetext = 0;
                 continue;
-            case TEXTCODESETSW:
+            case TEXTCHARSETSW:
                 if (! (cp = *argp++) || (*cp == '-' && cp[1]))
                     adios (NULL, "missing argument to %s", argp[-2]);
-                fx.textcodeset = cp;
+                fx.textcharset = cp;
                 continue;
-            case NTEXTCODESETSW:
-                fx.textcodeset = 0;
+            case NTEXTCHARSETSW:
+                fx.textcharset = 0;
                 continue;
             case FIXBOUNDARYSW:
                 fx.fixboundary = 1;
@@ -299,7 +286,7 @@ main (int argc, char **argv) {
             }
 
             if (close (fd)) {
-                unlink (file);
+                (void) m_unlink (file);
                 adios (NULL, "failed to write temporary file");
             }
         }
@@ -362,7 +349,7 @@ main (int argc, char **argv) {
             status += mhfixmsgsbr (ctp, &fx, outfile);
 
             if (using_stdin) {
-                unlink (file);
+                (void) m_unlink (file);
 
                 if (! outfile) {
                     /* Just calling m_backup() unlinks the backup file. */
@@ -421,8 +408,8 @@ mhfixmsgsbr (CT *ctp, const fix_transformations *fx, char *outfile) {
     if (status == OK  &&  fx->decodetext) {
         status = decode_text_parts (*ctp, fx->decodetext, &message_mods);
     }
-    if (status == OK  &&  fx->textcodeset != NULL) {
-        status = convert_codesets (*ctp, fx->textcodeset, &message_mods);
+    if (status == OK  &&  fx->textcharset != NULL) {
+        status = convert_charsets (*ctp, fx->textcharset, &message_mods);
     }
 
     if (! (*ctp)->c_umask) {
@@ -463,7 +450,7 @@ mhfixmsgsbr (CT *ctp, const fix_transformations *fx, char *outfile) {
     }
 
     if (modify_inplace) {
-        if (status != OK) unlink (outfile);
+        if (status != OK) (void) m_unlink (outfile);
         free (outfile);
         outfile = NULL;
     }
@@ -724,44 +711,6 @@ replace_boundary (CT ct, char *file, const char *boundary) {
 }
 
 
-/* Change the value of a name=value pair in a header field body.
-   If the name isn't there, append them.  In any case, a new
-   string will be allocated and must be free'd by the caller.
-   Trims any trailing newlines. */
-static char *
-update_attr (char *body, const char *name, const char *value) {
-    char *bp = nmh_strcasestr (body, name);
-    char *new_body;
-
-    if (bp) {
-        char *other_attrs = strchr (bp, ';');
-
-        *(bp + strlen (name)) = '\0';
-        new_body = concat (body, "\"", value, "\"", NULL);
-
-        if (other_attrs) {
-            char *cp;
-
-            /* Trim any trailing newlines. */
-            for (cp = &other_attrs[strlen (other_attrs) - 1];
-                 cp > other_attrs  &&  *cp == '\n';
-                 *cp-- = '\0') continue;
-            new_body = add (other_attrs, new_body);
-        }
-    } else {
-        char *cp;
-
-        /* Append name/value pair, after first removing a final newline
-           and (extraneous) semicolon. */
-        if (*(cp = &body[strlen (body) - 1]) == '\n') *cp = '\0';
-        if (*(cp = &body[strlen (body) - 1]) == ';') *cp = '\0';
-        new_body = concat (body, "; ", name, "\"", value, "\"", NULL);
-    }
-
-    return new_body;
-}
-
-
 static int
 fix_multipart_cte (CT ct, int *message_mods) {
     int status = OK;
@@ -1041,7 +990,7 @@ build_text_plain_part (CT encoded_part) {
     }
 
     free_content (tp_part);
-    unlink (tmp_plain_file);
+    (void) m_unlink (tmp_plain_file);
     free (tmp_plain_file);
 
     return NULL;
@@ -1112,7 +1061,7 @@ decode_part (CT ct) {
        filename of the decoded content.  tmp_decoded will contain the
        encoded output, get rid of that. */
     status = output_message (ct, tmp_decoded);
-    unlink (tmp_decoded);
+    (void) m_unlink (tmp_decoded);
     free (tmp_decoded);
 
     return status;
@@ -1172,7 +1121,7 @@ reformat_part (CT ct, char *file, char *type, char *subtype, int c_type) {
     /* Unlink decoded content tmp file and free its filename to avoid
        leaks.  The file stream should already have been closed. */
     if (ct->c_cefile.ce_unlink) {
-        unlink (ct->c_cefile.ce_file);
+        (void) m_unlink (ct->c_cefile.ce_file);
         free (ct->c_cefile.ce_file);
         ct->c_cefile.ce_file = NULL;
         ct->c_cefile.ce_unlink = 0;
@@ -1202,11 +1151,11 @@ reformat_part (CT ct, char *file, char *type, char *subtype, int c_type) {
 static int
 charset_encoding (CT ct) {
     /* norm_charmap() is case sensitive. */
-    char *codeset = upcase (content_codeset (ct));
+    char *charset = upcase (content_charset (ct));
     int encoding =
-        strcmp (norm_charmap (codeset), "US-ASCII")  ?  CE_8BIT  :  CE_7BIT;
+        strcmp (norm_charmap (charset), "US-ASCII")  ?  CE_8BIT  :  CE_7BIT;
 
-    free (codeset);
+    free (charset);
     return encoding;
 }
 
@@ -1492,7 +1441,7 @@ decode_text_parts (CT ct, int encoding, int *message_mods) {
                                               :  ct->c_ctline  ?  ct->c_ctline
                                                                :  "");
                     }
-                    unlink (ct->c_cefile.ce_file);
+                    (void) m_unlink (ct->c_cefile.ce_file);
                     free (ct->c_cefile.ce_file);
                     ct->c_cefile.ce_file = NULL;
                 } else if (ct->c_encoding == CE_QUOTED  &&
@@ -1506,7 +1455,7 @@ decode_text_parts (CT ct, int encoding, int *message_mods) {
                                               :  ct->c_ctline  ?  ct->c_ctline
                                                                :  "");
                     }
-                    unlink (ct->c_cefile.ce_file);
+                    (void) m_unlink (ct->c_cefile.ce_file);
                     free (ct->c_cefile.ce_file);
                     ct->c_cefile.ce_file = NULL;
                 } else {
@@ -1623,18 +1572,18 @@ content_encoding (CT ct) {
 static int
 strip_crs (CT ct, int *message_mods) {
     /* norm_charmap() is case sensitive. */
-    char *codeset = upcase (content_codeset (ct));
+    char *charset = upcase (content_charset (ct));
     int status = OK;
 
     /* Only strip carriage returns if content is ASCII or another
-       codeset that has the same readily recognizable CR followed by a
+       charset 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)) {
+    if (! strcmp (norm_charmap (charset), "US-ASCII")  ||
+        ! strncmp (norm_charmap (charset), "ISO-8859-", 9)  ||
+        ! strncmp (norm_charmap (charset), "UTF-8", 5)  ||
+        ! strncmp (norm_charmap (charset), "WINDOWS-12", 10)) {
         char **file = NULL;
         FILE **fp = NULL;
         size_t begin;
@@ -1696,7 +1645,7 @@ strip_crs (CT ct, int *message_mods) {
             if (has_crs) {
                 int fd;
                 char *stripped_content_file;
-                char *tempfile = m_mktemp2 (NULL, invo_name, &fd, NULL); 
+                char *tempfile = m_mktemp2 (NULL, invo_name, &fd, NULL);
 
                 if (tempfile == NULL) {
                     adios (NULL, "unable to create temporary file in %s",
@@ -1729,13 +1678,13 @@ strip_crs (CT ct, int *message_mods) {
                 if (close (fd)) {
                     admonish (NULL, "unable to write temporary file %s",
                               stripped_content_file);
-                    unlink (stripped_content_file);
+                    (void) m_unlink (stripped_content_file);
                     status = NOTOK;
                 } else {
                     /* Replace the decoded file with the converted one. */
                     if (ct->c_cefile.ce_file) {
                         if (ct->c_cefile.ce_unlink) {
-                            unlink (ct->c_cefile.ce_file);
+                            (void) m_unlink (ct->c_cefile.ce_file);
                         }
                         free (ct->c_cefile.ce_file);
                     }
@@ -1758,42 +1707,23 @@ strip_crs (CT ct, int *message_mods) {
         }
     }
 
-    free (codeset);
+    free (charset);
     return status;
 }
 
 
-char *
-content_codeset (CT ct) {
-    const char *const charset = "charset";
-    char *default_codeset = NULL;
-    CI ctinfo = &ct->c_ctinfo;
-    char **ap, **vp;
-    char **src_codeset = NULL;
-
-    for (ap = ctinfo->ci_attrs, vp = ctinfo->ci_values; *ap; ++ap, ++vp) {
-        if (! strcasecmp (*ap, charset)) {
-            src_codeset = vp;
-            break;
-        }
-    }
-
-    /* RFC 2045, Sec. 5.2:  default to us-ascii. */
-    if (src_codeset == NULL) src_codeset = &default_codeset;
-    if (*src_codeset == NULL) *src_codeset = "US-ASCII";
-
-    return *src_codeset;
-}
-
-
 static int
-convert_codesets (CT ct, char *dest_codeset, int *message_mods) {
+convert_charsets (CT ct, char *dest_charset, int *message_mods) {
     int status = OK;
 
     switch (ct->c_type) {
     case CT_TEXT:
         if (ct->c_subtype == TEXT_PLAIN) {
-            status = convert_codeset (ct, dest_codeset, message_mods);
+            status = convert_charset (ct, dest_charset, message_mods);
+            if (verbosw  &&  status == OK) {
+               report (ct->c_partno, ct->c_file, "convert %s to %s",
+                       content_charset(ct), dest_charset);
+            }
         }
         break;
 
@@ -1805,7 +1735,7 @@ convert_codesets (CT ct, char *dest_codeset, int *message_mods) {
            For now, it gets passed along as-is by InitMultiPart(). */
         for (part = m->mp_parts; status == OK  &&  part; part = part->mp_next) {
             status =
-                convert_codesets (part->mp_part, dest_codeset, message_mods);
+                convert_charsets (part->mp_part, dest_charset, message_mods);
         }
         break;
     }
@@ -1816,7 +1746,7 @@ convert_codesets (CT ct, char *dest_codeset, int *message_mods) {
 
             e = (struct exbody *) ct->c_ctparams;
             status =
-                convert_codesets (e->eb_content, dest_codeset, message_mods);
+                convert_charsets (e->eb_content, dest_charset, message_mods);
         }
         break;
 
@@ -1828,161 +1758,6 @@ convert_codesets (CT ct, char *dest_codeset, int *message_mods) {
 }
 
 
-static int
-convert_codeset (CT ct, char *dest_codeset, int *message_mods) {
-    char *src_codeset = content_codeset (ct);
-    int status = OK;
-
-    /* norm_charmap() is case sensitive. */
-    char *src_codeset_u = upcase (src_codeset);
-    char *dest_codeset_u = upcase (dest_codeset);
-    int different_codesets =
-        strcmp (norm_charmap (src_codeset), norm_charmap (dest_codeset));
-
-    free (dest_codeset_u);
-    free (src_codeset_u);
-
-    if (different_codesets) {
-#ifdef HAVE_ICONV
-        iconv_t conv_desc = NULL;
-        char *dest;
-        int fd = -1;
-        char **file = NULL;
-        FILE **fp = NULL;
-        size_t begin;
-        size_t end;
-        int opened_input_file = 0;
-        char src_buffer[BUFSIZ];
-        HF hf;
-        char *tempfile;
-
-        if ((conv_desc = iconv_open (dest_codeset, src_codeset)) ==
-            (iconv_t) -1) {
-            advise (NULL, "Can't convert %s to %s", src_codeset, dest_codeset);
-            return -1;
-        }
-
-        if ((tempfile = m_mktemp2 (NULL, invo_name, &fd, NULL)) == NULL) {
-            adios (NULL, "unable to create temporary file in %s",
-                   get_temp_dir());
-        }
-        dest = add (tempfile, NULL);
-
-        if (ct->c_cefile.ce_file) {
-            file = &ct->c_cefile.ce_file;
-            fp = &ct->c_cefile.ce_fp;
-            begin = end = 0;
-        } else if (ct->c_file) {
-            file = &ct->c_file;
-            fp = &ct->c_fp;
-            begin = (size_t) ct->c_begin;
-            end = (size_t) ct->c_end;
-        } /* else no input file: shouldn't happen */
-
-        if (file  &&  *file  &&  fp) {
-            if (! *fp) {
-                if ((*fp = fopen (*file, "r")) == NULL) {
-                    advise (*file, "unable to open for reading");
-                    status = NOTOK;
-                } else {
-                    opened_input_file = 1;
-                }
-            }
-        }
-
-        if (fp  &&  *fp) {
-            size_t inbytes;
-            size_t bytes_to_read =
-                end > 0 && end > begin  ?  end - begin  :  sizeof src_buffer;
-
-            fseeko (*fp, begin, SEEK_SET);
-            while ((inbytes = fread (src_buffer, 1,
-                                     min (bytes_to_read, sizeof src_buffer),
-                                     *fp)) > 0) {
-                char dest_buffer[BUFSIZ];
-                ICONV_CONST char *ib = src_buffer;
-                char *ob = dest_buffer;
-                size_t outbytes = sizeof dest_buffer;
-                size_t outbytes_before = outbytes;
-
-                if (end > 0) bytes_to_read -= inbytes;
-
-                if (iconv (conv_desc, &ib, &inbytes, &ob, &outbytes) ==
-                    (size_t) -1) {
-                    status = NOTOK;
-                    break;
-                } else {
-                    write (fd, dest_buffer, outbytes_before - outbytes);
-                }
-            }
-
-            if (opened_input_file) {
-                fclose (*fp);
-                *fp = NULL;
-            }
-        }
-
-        iconv_close (conv_desc);
-        close (fd);
-
-        if (status == OK) {
-            /* Replace the decoded file with the converted one. */
-            if (ct->c_cefile.ce_file) {
-                if (ct->c_cefile.ce_unlink) {
-                    unlink (ct->c_cefile.ce_file);
-                }
-                free (ct->c_cefile.ce_file);
-            }
-            ct->c_cefile.ce_file = dest;
-            ct->c_cefile.ce_unlink = 1;
-
-            ++*message_mods;
-            if (verbosw) {
-                report (ct->c_partno, ct->c_file, "convert %s to %s",
-                        src_codeset, dest_codeset);
-            }
-
-            /* Update ci_attrs. */
-            src_codeset = dest_codeset;
-
-            /* Update ct->c_ctline. */
-            if (ct->c_ctline) {
-                char *ctline =
-                    update_attr (ct->c_ctline, "charset=", dest_codeset);
-
-                free (ct->c_ctline);
-                ct->c_ctline = ctline;
-            } /* else no CT line, which is odd */
-
-            /* Update Content-Type header field. */
-            for (hf = ct->c_first_hf; hf; hf = hf->next) {
-                if (! strcasecmp (TYPE_FIELD, hf->name)) {
-                    char *ctline_less_newline =
-                        update_attr (hf->value, "charset=", dest_codeset);
-                    char *ctline = concat (ctline_less_newline, "\n", NULL);
-                    free (ctline_less_newline);
-
-                    free (hf->value);
-                    hf->value = ctline;
-                    break;
-                }
-            }
-        } else {
-            unlink (dest);
-        }
-#else  /* ! HAVE_ICONV */
-        NMH_UNUSED (message_mods);
-
-        advise (NULL, "Can't convert %s to %s without iconv", src_codeset,
-                dest_codeset);
-        status = NOTOK;
-#endif /* ! HAVE_ICONV */
-    }
-
-    return status;
-}
-
-
 static int
 write_content (CT ct, char *input_filename, char *outfile, int modify_inplace,
                int message_mods) {
@@ -2018,7 +1793,7 @@ write_content (CT ct, char *input_filename, char *outfile, int modify_inplace,
                         }
                         if (new != -1) close (new);
                         if (old != -1) close (old);
-                        unlink (outfile);
+                        (void) m_unlink (outfile);
 
                         if (i < 0) {
                             /* The -file argument processing used path() to
@@ -2034,7 +1809,7 @@ write_content (CT ct, char *input_filename, char *outfile, int modify_inplace,
                 } else {
                     admonish (NULL, "unable to remove input file %s, "
                               "not modifying it", infile);
-                    unlink (outfile);
+                    (void) m_unlink (outfile);
                     status = NOTOK;
                 }
 
@@ -2044,7 +1819,7 @@ write_content (CT ct, char *input_filename, char *outfile, int modify_inplace,
             }
         } else {
             /* No modifications and didn't need the tmp outfile. */
-            unlink (outfile);
+            (void) m_unlink (outfile);
         }
     } else {
         /* Output is going to some file.  Produce it whether or not
@@ -2096,17 +1871,6 @@ report (char *partno, char *filename, char *message, ...) {
 }
 
 
-static char *
-upcase (char *str) {
-    char *up = cpytrim (str);
-    char *cp;
-
-    for (cp = up; *cp; ++cp) *cp = toupper ((unsigned char) *cp);
-
-    return up;
-}
-
-
 static void
 pipeser (int i)
 {