X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/bc237bbae1393cacee9d534832a050f1148b0d8b..e6a316e73b70ee428ec701a5df2bcf795d4b1802:/uip/mhfixmsg.c diff --git a/uip/mhfixmsg.c b/uip/mhfixmsg.c index 553b14e3..2bbb0453 100644 --- a/uip/mhfixmsg.c +++ b/uip/mhfixmsg.c @@ -1,5 +1,4 @@ -/* - * mhfixmsg.c -- rewrite a message with various transformations +/* 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 @@ -7,10 +6,18 @@ */ #include +#include #include #include #include #include +#include "sbr/m_maildir.h" +#include "sbr/m_mktemp.h" +#include "sbr/mime_type.h" +#include "mhmisc.h" +#include "mhfree.h" +#include "mhoutsbr.h" +#include "mhshowsbr.h" #include #define MHFIXMSG_SWITCHES \ @@ -55,22 +62,6 @@ int debugsw; /* Needed by mhparse.c. */ #define quitser pipeser -/* mhparse.c */ -extern int skip_mp_cte_check; /* flag to InitMultiPart */ -extern int suppress_bogus_mp_content_warning; /* flag to InitMultiPart */ -extern int bogus_mp_content; /* flag from InitMultiPart */ -/* flags to/from parse_header_attrs */ -extern int suppress_extraneous_trailing_semicolon_warning; - -/* mhoutsbr.c */ -int output_message_fp (CT, FILE *, char *); - -/* mhmisc.c */ -void flush_errors (void); - -/* mhfree.c */ -extern CT *cts; - /* * static prototypes */ @@ -87,8 +78,8 @@ typedef struct fix_transformations { char *textcharset; } fix_transformations; -int mhfixmsgsbr (CT *, char *, const fix_transformations *, FILE **, char *, - FILE **); +static int mhfixmsgsbr (CT *, char *, const fix_transformations *, + FILE **, char *, FILE **); static int fix_boundary (CT *, int *); static int copy_input_to_output (const char *, FILE *, const char *, FILE *); static int get_multipart_boundary (CT, char **); @@ -116,7 +107,7 @@ static int should_decode(const char *, const char *, const char *); static int content_encoding (CT, const char **); static int strip_crs (CT, int *); static void update_cte (CT); -static int least_restrictive_encoding (CT); +static int least_restrictive_encoding (CT) PURE; static int less_restrictive (int, int); static int convert_charsets (CT, char *, int *); static int fix_always (CT, int *); @@ -125,7 +116,8 @@ static int fix_filename_encoding (CT); static int write_content (CT, const char *, char *, FILE *, 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 report (char *, char *, char *, char *, ...) + CHECK_PRINTF(4, 5); static void pipeser (int); @@ -232,11 +224,10 @@ main (int argc, char **argv) { adios (NULL, "missing argument to %s", argp[-2]); } if (! strncasecmp (cp, "multipart/", 10) || - ! strncasecmp (cp, "message/", 8)) { + ! strncasecmp (cp, "message/", 8)) adios (NULL, "-fixtype %s not allowed", cp); - } else if (! strchr (cp, '/')) { + if (! strchr (cp, '/')) adios (NULL, "-fixtype requires type/subtype"); - } if (fx.fixtypes == NULL) { fx.fixtypes = svector_create (10); } svector_push_back (fx.fixtypes, cp); continue; @@ -287,11 +278,9 @@ main (int argc, char **argv) { } } if (*cp == '+' || *cp == '@') { - if (folder) { + if (folder) adios (NULL, "only one folder at a time!"); - } else { - folder = pluspath (cp); - } + folder = pluspath (cp); } else { if (*cp == '/') { /* Interpret a full path as a filename, not a message. */ @@ -309,12 +298,12 @@ main (int argc, char **argv) { * Read the standard profile setup */ if ((fp = fopen (cp = etcpath ("mhn.defaults"), "r"))) { - readconfig ((struct node **) 0, fp, cp, 0); + readconfig(NULL, fp, cp, 0); fclose (fp); } - suppress_bogus_mp_content_warning = skip_mp_cte_check = 1; - suppress_extraneous_trailing_semicolon_warning = 1; + suppress_bogus_mp_content_warning = skip_mp_cte_check = true; + suppress_extraneous_trailing_semicolon_warning = true; if (! context_find ("path")) { free (path ("./", TFOLDER)); @@ -372,7 +361,7 @@ main (int argc, char **argv) { set_text_ctparams(ct, fx.decodetypes, fx.lf_line_endings); *ctp++ = ct; } else { - advise (NULL, "unable to parse message from file %s", file); + inform("unable to parse message from file %s", file); status = NOTOK; /* If there's an outfile, pass the input message unchanged, so the @@ -386,7 +375,7 @@ main (int argc, char **argv) { } if (copy_input_to_output (file, infp, outfile, outfp) != OK) { - advise (NULL, "unable to copy message to %s, " + inform("unable to copy message to %s, " "it might be lost\n", outfile); } @@ -406,7 +395,7 @@ main (int argc, char **argv) { if (! folder) { folder = getfolder (1); } - maildir = m_maildir (folder); + maildir = mh_xstrdup(m_maildir (folder)); /* chdir so that error messages, esp. from MIME parser, just refer to the message and not its path. */ @@ -442,7 +431,7 @@ main (int argc, char **argv) { set_text_ctparams(ct, fx.decodetypes, fx.lf_line_endings); *ctp++ = ct; } else { - advise (NULL, "unable to parse message %s", msgnam); + inform("unable to parse message %s", msgnam); status = NOTOK; /* If there's an outfile, pass the input message @@ -465,10 +454,8 @@ main (int argc, char **argv) { if (copy_input_to_output (input_filename, infp, outfile, outfp) != OK) { - advise (NULL, - "unable to copy message to %s, " - "it might be lost\n", - outfile); + inform("unable to copy message to %s, " + "it might be lost\n", outfile); } fclose (infp); @@ -489,7 +476,10 @@ main (int argc, char **argv) { if (*cts) { for (ctp = cts; *ctp; ++ctp) { - status += mhfixmsgsbr (ctp, maildir, &fx, &infp, outfile, &outfp); + status = + mhfixmsgsbr (ctp, maildir, &fx, &infp, outfile, &outfp) == OK + ? 0 + : 1; free_content (*ctp); if (using_stdin) { @@ -505,6 +495,7 @@ main (int argc, char **argv) { status = 1; } + free(maildir); free (cts); if (fx.fixtypes != NULL) { svector_free (fx.fixtypes); } @@ -515,7 +506,7 @@ main (int argc, char **argv) { free (folder); free (arguments); - done (status); + done (status == OK ? 0 : 1); return NOTOK; } @@ -523,7 +514,7 @@ main (int argc, char **argv) { /* * Apply transformations to one message. */ -int +static int mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, FILE **infp, char *outfile, FILE **outfp) { /* Store input filename in case one of the transformations, i.e., @@ -607,7 +598,7 @@ mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, to the output. */ if (copy_input_to_output (input_filename, *infp, outfile, *outfp) != OK) { - advise (NULL, "unable to copy message to %s, it might be lost\n", + inform("unable to copy message to %s, it might be lost\n", outfile); } } @@ -691,16 +682,16 @@ fix_boundary (CT *ct, int *message_mods) { } } else { *ct = NULL; - advise (NULL, "unable to parse fixed part"); + inform("unable to parse fixed part"); status = NOTOK; } free (filename); } else { - advise (NULL, "unable to replace broken boundary"); + inform("unable to replace broken boundary"); status = NOTOK; } } else { - advise (NULL, "unable to create temporary file in %s", + inform("unable to create temporary file in %s", get_temp_dir()); status = NOTOK; } @@ -766,11 +757,9 @@ get_multipart_boundary (CT ct, char **part_boundary) { } } - if (! end_boundary && begin > (off_t) (ct->c_begin + sizeof buffer)) { - begin -= sizeof buffer; - } else { + if (end_boundary || begin <= (off_t) (ct->c_begin + sizeof buffer)) break; - } + begin -= sizeof buffer; } /* Get boundary at beginning of multipart. */ @@ -821,11 +810,11 @@ replace_boundary (CT ct, char *file, char *boundary) { int compnum, state; char buf[NMH_BUFSIZ], name[NAMESZ]; char *np, *vp; - m_getfld_state_t gstate = 0; + m_getfld_state_t gstate; int status = OK; if (ct->c_file == NULL) { - advise (NULL, "missing input filename"); + inform("missing input filename"); return NOTOK; } @@ -840,10 +829,11 @@ replace_boundary (CT ct, char *file, char *boundary) { return NOTOK; } + gstate = m_getfld_state_init(fpin); for (compnum = 1;;) { int bufsz = (int) sizeof buf; - switch (state = m_getfld (&gstate, name, buf, &bufsz, fpin)) { + switch (state = m_getfld2(&gstate, name, buf, &bufsz)) { case FLD: case FLDPLUS: compnum++; @@ -855,7 +845,7 @@ replace_boundary (CT ct, char *file, char *boundary) { /* if necessary, get rest of field */ while (state == FLDPLUS) { bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, fpin); + state = m_getfld2(&gstate, name, buf, &bufsz); vp = add (buf, vp); /* add to previous value */ } @@ -870,13 +860,13 @@ replace_boundary (CT ct, char *file, char *boundary) { new_ctline = concat(" ", ct->c_ctinfo.ci_type, "/", ct->c_ctinfo.ci_subtype, NULL); - new_params = output_params(strlen(TYPE_FIELD) + + new_params = output_params(LEN(TYPE_FIELD) + strlen(new_ctline) + 1, ct->c_ctinfo.ci_first_pm, NULL, 0); fprintf (fpout, "%s:%s%s\n", np, new_ctline, - new_params ? new_params : ""); + FENDNULL(new_params)); free(new_ctline); - mh_xfree(new_params); + free(new_params); } free (vp); @@ -897,12 +887,12 @@ replace_boundary (CT ct, char *file, char *boundary) { case LENERR: case FMTERR: - advise (NULL, "message format error in component #%d", compnum); + inform("message format error in component #%d", compnum); status = NOTOK; break; default: - advise (NULL, "getfld() returned %d", state); + inform("getfld() returned %d", state); status = NOTOK; break; } @@ -984,7 +974,7 @@ fix_types (CT ct, svector_t fixtypes, int *message_mods) { *cp = '\0'; ct_subtype = mh_xstrdup(++cp); } else { - advise (NULL, "missing / in MIME type of %s %s", + inform("missing / in MIME type of %s %s", ct->c_file, ct->c_partno); free (ct_type); return NOTOK; @@ -999,7 +989,7 @@ fix_types (CT ct, svector_t fixtypes, int *message_mods) { ct->c_ctinfo.ci_subtype = ct_subtype; if (! replace_substring (&ct->c_ctline, type, ct_type_subtype)) { - advise (NULL, "did not find %s in %s", + inform("did not find %s in %s", type, ct->c_ctline); } @@ -1016,10 +1006,8 @@ fix_types (CT ct, svector_t fixtypes, int *message_mods) { type, ct_type_subtype); } break; - } else { - advise (NULL, "did not find %s in %s", - type, hf->value); } + inform("did not find %s in %s", type, hf->value); } } } @@ -1069,7 +1057,7 @@ replace_substring (char **str, const char *old, const char *new) { char * remove_parameter (char *str, const char *name) { /* It looks to me, based on the BNF in RFC 2045, than there can't - be whitespace betwwen the parameter name and the "=", or + be whitespace between the parameter name and the "=", or between the "=" and the parameter value. */ char *param_name = concat (name, "=", NULL); char *cp; @@ -1126,12 +1114,12 @@ fix_composite_cte (CT ct, int *message_mods) { for (hf = ct->c_first_hf; hf; hf = hf->next) { char *name = hf->name; - for (; *name && isspace ((unsigned char) *name); ++name) { + for (; isspace((unsigned char)*name); ++name) { continue; } if (! strncasecmp (name, ENCODING_FIELD, - strlen (ENCODING_FIELD))) { + LEN(ENCODING_FIELD))) { char *prefix = "Nmh-REPLACED-INVALID-"; HF h; @@ -1336,9 +1324,8 @@ ensure_text_plain (CT *ct, CT parent, int *message_mods, int replacetextplain) { parent->c_ctinfo.ci_subtype = mh_xstrdup("alternative"); if (! replace_substring (&parent->c_ctline, "/related", "/alternative")) { - advise (NULL, - "did not find multipart/related in %s", - parent->c_ctline); + inform("did not find multipart/related in %s", + parent->c_ctline); } /* Update Content-Type header field. */ @@ -1357,11 +1344,9 @@ ensure_text_plain (CT *ct, CT parent, int *message_mods, int replacetextplain) { multipart/alternative. */ remove_parameter (hf->value, "type"); break; - } else { - advise (NULL, "did not find multipart/" - "related in header %s", - hf->value); } + inform("did not find multipart/" + "related in header %s", hf->value); } } } else { @@ -1492,7 +1477,7 @@ build_text_plain_part (CT encoded_part) { /* This m_mktemp2() call closes the temp file. */ if ((tempfile = m_mktemp2 (NULL, invo_name, NULL, NULL)) == NULL) { - advise (NULL, "unable to create temporary file in %s", + inform("unable to create temporary file in %s", get_temp_dir()); } else { tmp_plain_file = mh_xstrdup (tempfile); @@ -1630,7 +1615,7 @@ decode_part (CT ct) { (void) m_unlink (tmp_decoded); free (tmp_decoded); if (fclose (file)) { - admonish (NULL, "unable to close temporary file %s", tempfile); + inform("unable to close temporary file %s, continuing...", tempfile); } return status; @@ -1657,16 +1642,16 @@ reformat_part (CT ct, char *file, char *type, char *subtype, int c_type) { /* Check for invo_name-format-type/subtype. */ if ((cf = context_find_by_type ("format", type, subtype)) == NULL) { if (verbosw) { - advise (NULL, "Don't know how to convert %s, there is no " + inform("Don't know how to convert %s, there is no " "%s-format-%s/%s profile entry", ct->c_file, invo_name, type, subtype); } return NOTOK; } if (strchr (cf, '>')) { - advise (NULL, "'>' prohibited in \"%s\",\nplease fix your " + inform("'>' prohibited in \"%s\",\nplease fix your " "%s-format-%s/%s profile entry", cf, invo_name, type, - subtype ? subtype : ""); + FENDNULL(subtype)); return NOTOK; } @@ -1757,8 +1742,7 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { boundary_in_content (&new_part->c_cefile.ce_fp, new_part->c_cefile.ce_file, boundary)) == NOTOK) { - free_content (ct); - return NULL; + goto return_null; } } @@ -1769,8 +1753,7 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { boundary_in_content (&new_part->c_fp, new_part->c_file, boundary)) == NOTOK) { - free_content (ct); - return NULL; + goto return_null; } } @@ -1783,15 +1766,14 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { snprintf (buffer2, sizeof buffer2, "%d", serial); boundary = concat (boundary_prefix, - first_alt->c_partno ? first_alt->c_partno : "", + FENDNULL(first_alt->c_partno), "-", buffer2, NULL); } } if (found_boundary) { - advise (NULL, "giving up trying to find a unique boundary"); - free_content (ct); - return NULL; + inform("giving up trying to find a unique boundary"); + goto return_null; } } @@ -1836,6 +1818,11 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { free (boundary); return ct; + +return_null: + free_content(ct); + free(boundary); + return NULL; } @@ -1877,7 +1864,7 @@ transfer_noncontent_headers (CT old, CT new) { while (hp) { HF next = hp->next; - if (strncasecmp (XXX_FIELD_PRF, hp->name, strlen (XXX_FIELD_PRF))) { + if (strncasecmp (XXX_FIELD_PRF, hp->name, LEN(XXX_FIELD_PRF))) { if (hp == old->c_last_hf) { if (hp == old->c_first_hf) { old->c_last_hf = old->c_first_hf = NULL; @@ -2026,8 +2013,7 @@ decode_text_parts (CT ct, int encoding, const char *decodetypes, report (NULL, ct->c_partno, ct->c_file, "will not decode%s because it is binary (%s)", ct->c_partno ? "" - : ct->c_ctline ? ct->c_ctline - : "", + : (FENDNULL(ct->c_ctline)), reason); } (void) m_unlink (ct->c_cefile.ce_file); @@ -2041,8 +2027,7 @@ decode_text_parts (CT ct, int encoding, const char *decodetypes, report (NULL, ct->c_partno, ct->c_file, "will not decode%s because it is 8bit", ct->c_partno ? "" - : ct->c_ctline ? ct->c_ctline - : ""); + : (FENDNULL(ct->c_ctline))); } (void) m_unlink (ct->c_cefile.ce_file); free (ct->c_cefile.ce_file); @@ -2061,7 +2046,7 @@ decode_text_parts (CT ct, int encoding, const char *decodetypes, ++*message_mods; if (verbosw) { report (NULL, ct->c_partno, ct->c_file, "decode%s", - ct->c_ctline ? ct->c_ctline : ""); + FENDNULL(ct->c_ctline)); } if (lf_line_endings) { strip_crs (ct, message_mods); @@ -2168,13 +2153,14 @@ content_encoding (CT ct, const char **reason) { *reason = ""; } break; - } else if (*cp == '\n') { + } + if (*cp == '\n') { line_len = 0; } else if (! isascii ((unsigned char) *cp)) { encoding = CE_8BIT; } - last_char_was_cr = *cp == '\r' ? 1 : 0; + last_char_was_cr = *cp == '\r'; } } @@ -2257,7 +2243,7 @@ strip_crs (CT ct, int *message_mods) { break; } - last_char_was_cr = *cp == '\r' ? 1 : 0; + last_char_was_cr = *cp == '\r'; } } @@ -2303,16 +2289,17 @@ strip_crs (CT ct, int *message_mods) { } if (close (fd)) { - admonish (NULL, "unable to write temporary file %s", + inform("unable to write temporary file %s, continuing...", stripped_content_file); (void) m_unlink (stripped_content_file); + free(stripped_content_file); status = NOTOK; } else { /* Replace the decoded file with the converted one. */ if (ct->c_cefile.ce_file && ct->c_cefile.ce_unlink) (void) m_unlink (ct->c_cefile.ce_file); - mh_xfree(ct->c_cefile.ce_file); + free(ct->c_cefile.ce_file); ct->c_cefile.ce_file = stripped_content_file; ct->c_cefile.ce_unlink = 1; @@ -2589,7 +2576,7 @@ static int fix_filename_param (char *name, char *value, PM *first_pm, PM *last_pm) { int fixed = 0; - if (has_prefix(value, "=?") && HasSuffix(value, "?=")) { + if (has_prefix(value, "=?") && has_suffix(value, "?=")) { /* Looks like an RFC 2047 encoded parameter. */ char decoded[PATH_MAX + 1]; @@ -2598,7 +2585,7 @@ fix_filename_param (char *name, char *value, PM *first_pm, PM *last_pm) { replace_param (first_pm, last_pm, name, decoded, 0); fixed = 1; } else { - advise (NULL, "failed to decode %s parameter %s", name, value); + inform("failed to decode %s parameter %s", name, value); } } @@ -2663,7 +2650,7 @@ fix_filename_encoding (CT ct) { free((void *)new_params); /* Cast away const. Sigh. */ free((void *)params); } else { - advise (NULL, "did not find semicolon in %s:%s\n", + inform("did not find semicolon in %s:%s\n", hf->name, hf->value); } } @@ -2718,15 +2705,15 @@ write_content (CT ct, const char *input_filename, char *outfile, FILE *outfp, expand filename to absolute path. */ int file = ct->c_file && ct->c_file[0] == '/'; - admonish (NULL, "unable to rename %s %s to %s", + inform("unable to rename %s %s to %s, continuing...", file ? "file" : "message", outfile, infile); status = NOTOK; } } } else { - admonish (NULL, "unable to remove input file %s, " - "not modifying it", infile); + inform("unable to remove input file %s, " + "not modifying it, continuing...", infile); (void) m_unlink (outfile); status = NOTOK; } @@ -2817,7 +2804,7 @@ report (char *what, char *partno, char *filename, char *message, ...) { if (verbosw) { va_start (args, message); fmt = concat (filename, partno ? " part " : ", ", - partno ? partno : "", partno ? ", " : "", message, NULL); + FENDNULL(partno), partno ? ", " : "", message, NULL); advertise (what, NULL, fmt, args);