X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/942561da2455ee50a1eb82c8c4f2bdb5e25133d1..e56972cabb200aa655374e95bbbbcf18d0ddabe0:/uip/mhfixmsg.c?ds=sidebyside diff --git a/uip/mhfixmsg.c b/uip/mhfixmsg.c index cd169dff..4ececa5d 100644 --- a/uip/mhfixmsg.c +++ b/uip/mhfixmsg.c @@ -14,7 +14,7 @@ #include #define MHFIXMSG_SWITCHES \ - X("decodetext 8bit|7bit", 0, DECODETEXTSW) \ + X("decodetext 8bit|7bit|binary", 0, DECODETEXTSW) \ X("nodecodetext", 0, NDECODETEXTSW) \ X("decodetypes", 0, DECODETYPESW) \ X("crlflinebreaks", 0, CRLFLINEBREAKSSW) \ @@ -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,9 +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 write_content (CT, const char *, char *, int, int); static void set_text_ctparams(CT, char *, int); -static int remove_file (char *); +static int remove_file (const char *); static void report (char *, char *, char *, char *, ...); static void pipeser (int); @@ -176,12 +177,15 @@ main (int argc, char **argv) { done (0); case DECODETEXTSW: - if (! (cp = *argp++) || *cp == '-') + if (! (cp = *argp++) || *cp == '-') { adios (NULL, "missing argument to %s", argp[-2]); + } if (! strcasecmp (cp, "8bit")) { fx.decodetext = CE_8BIT; } else if (! strcasecmp (cp, "7bit")) { fx.decodetext = CE_7BIT; + } else if (! strcasecmp (cp, "binary")) { + fx.decodetext = CE_BINARY; } else { adios (NULL, "invalid argument to %s", argp[-2]); } @@ -190,8 +194,9 @@ main (int argc, char **argv) { fx.decodetext = 0; continue; case DECODETYPESW: - if (! (cp = *argp++) || *cp == '-') + if (! (cp = *argp++) || *cp == '-') { adios (NULL, "missing argument to %s", argp[-2]); + } fx.decodetypes = cp; continue; case CRLFLINEBREAKSSW: @@ -201,8 +206,9 @@ main (int argc, char **argv) { fx.lf_line_endings = 1; continue; case TEXTCHARSETSW: - if (! (cp = *argp++) || (*cp == '-' && cp[1])) + if (! (cp = *argp++) || (*cp == '-' && cp[1])) { adios (NULL, "missing argument to %s", argp[-2]); + } fx.textcharset = cp; continue; case NTEXTCHARSETSW: @@ -221,8 +227,9 @@ main (int argc, char **argv) { fx.fixcte = 0; continue; case FIXTYPESW: - if (! (cp = *argp++) || (*cp == '-' && cp[1])) + if (! (cp = *argp++) || (*cp == '-' && cp[1])) { adios (NULL, "missing argument to %s", argp[-2]); + } if (! strncasecmp (cp, "multipart/", 10) || ! strncasecmp (cp, "message/", 8)) { adios (NULL, "-fixtype %s not allowed", cp); @@ -245,18 +252,21 @@ main (int argc, char **argv) { fx.replacetextplain = 0; continue; case FILESW: - if (! (cp = *argp++) || (*cp == '-' && cp[1])) + 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])) + 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 == '-') + if (!(rmmproc = *argp++) || *rmmproc == '-') { adios (NULL, "missing argument to %s", argp[-2]); + } continue; case NRPRCSW: rmmproc = NULL; @@ -276,10 +286,11 @@ main (int argc, char **argv) { } } if (*cp == '+' || *cp == '@') { - if (folder) + if (folder) { adios (NULL, "only one folder at a time!"); - else + } else { folder = pluspath (cp); + } } else { if (*cp == '/') { /* Interpret a full path as a filename, not a message. */ @@ -304,11 +315,13 @@ main (int argc, char **argv) { suppress_bogus_mp_content_warning = skip_mp_cte_check = 1; suppress_extraneous_trailing_semicolon_warning = 1; - if (! context_find ("path")) + if (! context_find ("path")) { free (path ("./", TFOLDER)); + } - if (file && msgs.size) + if (file && msgs.size) { adios (NULL, "cannot specify msg and file at same time!"); + } /* * check if message is coming from file @@ -349,6 +362,19 @@ main (int argc, char **argv) { if ((ct = parse_mime (file))) { 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); + } + } } } else { /* @@ -356,27 +382,33 @@ main (int argc, char **argv) { */ CT ct; - if (! msgs.size) + if (! msgs.size) { app_msgarg(&msgs, "cur"); - if (! folder) + } + if (! folder) { folder = getfolder (1); + } maildir = m_maildir (folder); - if (chdir (maildir) == NOTOK) + if (chdir (maildir) == NOTOK) { adios (maildir, "unable to change directory to"); + } /* read folder and create message structure */ - if (! (mp = folder_read (folder, 1))) + if (! (mp = folder_read (folder, 1))) { adios (NULL, "unable to read folder %s", folder); + } /* check for empty folder */ - if (mp->nummsg == 0) + if (mp->nummsg == 0) { adios (NULL, "no messages in %s", folder); + } /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) - if (! m_convert (mp, msgs.msgs[msgnum])) + if (! m_convert (mp, msgs.msgs[msgnum])) { done (1); + } seq_setprev (mp); /* set the previous-sequence */ if (! (cts = @@ -393,6 +425,21 @@ main (int argc, char **argv) { if ((ct = parse_mime (msgnam))) { 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); + } + } } } } @@ -425,6 +472,8 @@ main (int argc, char **argv) { if (fx.fixtypes != NULL) { svector_free (fx.fixtypes); } free (outfile); free (file); + free (folder); + free (arguments); /* done is freects_done, which will clean up all of cts. */ done (status); @@ -500,19 +549,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) { @@ -527,6 +566,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; @@ -743,8 +805,9 @@ replace_boundary (CT ct, char *file, char *boundary) { fprintf (fpout, "%s:%s%s\n", np, new_ctline, new_params ? new_params : ""); free(new_ctline); - if (new_params) + if (new_params) { free(new_params); + } } free (vp); @@ -1782,6 +1845,12 @@ set_ct_type (CT ct, int type, int subtype, int encoding) { } +/* + * It's not necessary to update the charset parameter of a Content-Type + * header for a text part. According to RFC 2045 Sec. 6.4, the body + * (content) was originally in the specified charset, "and will be in + * that character set again after decoding." + */ static int decode_text_parts (CT ct, int encoding, const char *decodetypes, int *message_mods) { int status = OK; @@ -1855,12 +1924,13 @@ decode_text_parts (CT ct, int encoding, const char *decodetypes, int *message_mo ct->c_cefile.ce_file = NULL; } else { int enc; - if (ct_encoding == CE_BINARY) + if (ct_encoding == CE_BINARY) { enc = CE_BINARY; - else if (ct_encoding == CE_8BIT && encoding == CE_7BIT) + } else if (ct_encoding == CE_8BIT && encoding == CE_7BIT) { enc = CE_QUOTED; - else + } else { enc = charset_encoding (ct); + } if (set_ce (ct, enc) == OK) { ++*message_mods; if (verbosw) { @@ -2275,7 +2345,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; @@ -2391,7 +2461,7 @@ set_text_ctparams(CT ct, char *decodetypes, int lf_line_endings) { * 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);