X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/3bd5ce286fa6983f3f3f9fda4ff7f2f96c2a22a2..e62400a894407812a6774c1a0eddde91142a42eb:/uip/mhfixmsg.c?ds=sidebyside diff --git a/uip/mhfixmsg.c b/uip/mhfixmsg.c index eba84526..b7f1917a 100644 --- a/uip/mhfixmsg.c +++ b/uip/mhfixmsg.c @@ -71,7 +71,6 @@ void flush_errors (void); /* mhfree.c */ extern CT *cts; -void freects_done (int) NORETURN; /* * static prototypes @@ -89,7 +88,7 @@ typedef struct fix_transformations { char *textcharset; } fix_transformations; -int mhfixmsgsbr (CT *, const fix_transformations *, char *); +int mhfixmsgsbr (CT *, char *, 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 **); @@ -134,7 +133,7 @@ int main (int argc, char **argv) { int msgnum; char *cp, *file = NULL, *folder = NULL; - char *maildir, buf[100], *outfile = NULL; + char *maildir = NULL, buf[100], *outfile = NULL; char **argp, **arguments; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp = NULL; @@ -154,8 +153,6 @@ main (int argc, char **argv) { if (nmh_init(argv[0], 2)) { return 1; } - done = freects_done; - arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; @@ -392,6 +389,8 @@ main (int argc, char **argv) { } maildir = m_maildir (folder); + /* chdir so that error messages, esp. from MIME parser, just + refer to the message and not its path. */ if (chdir (maildir) == NOTOK) { adios (maildir, "unable to change directory to"); } @@ -418,9 +417,8 @@ main (int argc, char **argv) { for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected(mp, msgnum)) { - char *msgnam; + char *msgnam = m_name (msgnum); - msgnam = m_name (msgnum); if ((ct = parse_mime (msgnam))) { set_text_ctparams(ct, fx.decodetypes, fx.lf_line_endings); *ctp++ = ct; @@ -428,16 +426,25 @@ main (int argc, char **argv) { 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 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); + /* Something went wrong. Output might be expected, + such as if this were run as a filter. Just copy + the input to the output. */ + /* Can't use path() here because 1) it might have been + called before and it caches the pwd, and 2) we call + chdir() after that. */ + char *input_filename = + concat (maildir, "/", msgnam, NULL); if (copy_input_to_output (input_filename, outfile) != OK) { - advise (NULL, "unable to copy message to %s, it might be lost\n", outfile); + advise (NULL, + "unable to copy message to %s, it might be lost\n", + outfile); } + free (input_filename); } } } @@ -453,7 +460,8 @@ main (int argc, char **argv) { if (*cts) { for (ctp = cts; *ctp; ++ctp) { - status += mhfixmsgsbr (ctp, &fx, outfile); + status += mhfixmsgsbr (ctp, maildir, &fx, outfile); + free_content (*ctp); if (using_stdin) { (void) m_unlink (file); @@ -464,6 +472,8 @@ main (int argc, char **argv) { } } } + + free (cts); } else { status = 1; } @@ -474,7 +484,6 @@ main (int argc, char **argv) { free (folder); free (arguments); - /* done is freects_done, which will clean up all of cts. */ done (status); return NOTOK; } @@ -484,10 +493,13 @@ main (int argc, char **argv) { * Apply transformations to one message. */ int -mhfixmsgsbr (CT *ctp, const fix_transformations *fx, char *outfile) { +mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, + char *outfile) { /* Store input filename in case one of the transformations, i.e., fix_boundary(), rewrites to a tmp file. */ - char *input_filename = add ((*ctp)->c_file, NULL); + char *input_filename = maildir + ? concat (maildir, "/", (*ctp)->c_file, NULL) + : add ((*ctp)->c_file, NULL); int modify_inplace = 0; int message_mods = 0; int status = OK; @@ -676,7 +688,7 @@ fix_boundary (CT *ct, int *message_mods) { */ static int get_multipart_boundary (CT ct, char **part_boundary) { - char buffer[BUFSIZ]; + char buffer[NMH_BUFSIZ]; char *end_boundary = NULL; off_t begin = (off_t) ct->c_end > (off_t) (ct->c_begin + sizeof buffer) ? (off_t) (ct->c_end - sizeof buffer) @@ -684,10 +696,10 @@ get_multipart_boundary (CT ct, char **part_boundary) { size_t bytes_read; int status = OK; - /* This will fail if the boundary spans fread() calls. BUFSIZ should + /* This will fail if the boundary spans fread() calls. NMH_BUFSIZ should be big enough, even if it's just 1024, to make that unlikely. */ - /* free_content() will close ct->c_fp. */ + /* free_content() will close ct->c_fp if bogus MP boundary is fixed. */ if (! ct->c_fp && (ct->c_fp = fopen (ct->c_file, "r")) == NULL) { advise (ct->c_file, "unable to open for reading"); return NOTOK; @@ -744,6 +756,11 @@ get_multipart_boundary (CT ct, char **part_boundary) { status = NOTOK; } + if (ct->c_fp) { + fclose (ct->c_fp); + ct->c_fp = NULL; + } + if (status == OK) { *part_boundary = end_boundary; } else { @@ -762,7 +779,7 @@ static int replace_boundary (CT ct, char *file, char *boundary) { FILE *fpin, *fpout; int compnum, state; - char buf[BUFSIZ], name[NAMESZ]; + char buf[NMH_BUFSIZ], name[NAMESZ]; char *np, *vp; m_getfld_state_t gstate = 0; int status = OK; @@ -819,9 +836,7 @@ 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) { - free(new_params); - } + mh_xfree(new_params); } free (vp); @@ -830,7 +845,7 @@ replace_boundary (CT ct, char *file, char *boundary) { continue; case BODY: - fputs ("\n", fpout); + putc('\n', fpout); /* buf will have a terminating NULL, skip it. */ if ((int) fwrite (buf, 1, bufsz-1, fpout) < bufsz-1) { advise (file, "fwrite"); @@ -924,10 +939,10 @@ fix_types (CT ct, svector_t fixtypes, int *message_mods) { * c_ctline */ /* Extract type and subtype from type/subtype. */ - ct_type = getcpy (ct_type_subtype); + ct_type = mh_xstrdup(ct_type_subtype); if ((cp = strchr (ct_type, '/'))) { *cp = '\0'; - ct_subtype = getcpy (++cp); + ct_subtype = mh_xstrdup(++cp); } else { advise (NULL, "missing / in MIME type of %s %s", ct->c_file, ct->c_partno); @@ -991,7 +1006,7 @@ replace_substring (char **str, const char *old, const char *new) { char *prefix, *new_str; if (cp - *str) { - prefix = getcpy (*str); + prefix = mh_xstrdup(*str); *(prefix + (cp - *str)) = '\0'; new_str = concat (prefix, new, remainder, NULL); free (prefix); @@ -1002,9 +1017,9 @@ replace_substring (char **str, const char *old, const char *new) { free (*str); return *str = new_str; - } else { - return NULL; } + + return NULL; } @@ -1180,9 +1195,9 @@ set_ce (CT ct, int encoding) { ct->c_celine = add (cte, NULL); return OK; - } else { - return NOTOK; } + + return NOTOK; } @@ -1410,12 +1425,12 @@ insert_new_text_plain_part (CT ct, int new_subpart_number, CT parent) { buffer, NULL); return 1; - } else { - free_content (new_part->mp_part); - free (new_part); - - return 0; } + + free_content (new_part->mp_part); + free (new_part); + + return 0; } @@ -1540,10 +1555,10 @@ copy_ctinfo (CI dest, CI src) { d_pm = add_param(&dest->ci_first_pm, &dest->ci_last_pm, s_pm->pm_name, s_pm->pm_value, 0); if (s_pm->pm_charset) { - d_pm->pm_charset = getcpy(s_pm->pm_charset); + d_pm->pm_charset = mh_xstrdup(s_pm->pm_charset); } if (s_pm->pm_lang) { - d_pm->pm_lang = getcpy(s_pm->pm_lang); + d_pm->pm_lang = mh_xstrdup(s_pm->pm_lang); } } @@ -1601,14 +1616,13 @@ reformat_part (CT ct, char *file, char *type, char *subtype, int c_type) { ct->c_file, invo_name, type, subtype); } return NOTOK; - } else { - if (strchr (cf, '>')) { - advise (NULL, "'>' prohibited in \"%s\",\nplease fix your " - "%s-format-%s/%s profile entry", cf, invo_name, type, - subtype ? subtype : ""); + } + if (strchr (cf, '>')) { + advise (NULL, "'>' prohibited in \"%s\",\nplease fix your " + "%s-format-%s/%s profile entry", cf, invo_name, type, + subtype ? subtype : ""); - return NOTOK; - } + return NOTOK; } cp = concat (cf, " >", file, NULL); @@ -1632,7 +1646,8 @@ reformat_part (CT ct, char *file, char *type, char *subtype, int c_type) { } output_encoding = content_encoding (ct, &reason); - if (set_ct_type (ct, c_type, output_subtype, output_encoding) == OK) { + if (status == OK && + set_ct_type (ct, c_type, output_subtype, output_encoding) == OK) { ct->c_cefile.ce_file = file; ct->c_cefile.ce_unlink = 1; } else { @@ -1782,7 +1797,7 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { */ static int boundary_in_content (FILE **fp, char *file, const char *boundary) { - char buffer[BUFSIZ]; + char buffer[NMH_BUFSIZ]; size_t bytes_read; int found_boundary = 0; @@ -2076,7 +2091,7 @@ content_encoding (CT ct, const char **reason) { if (ce->ce_file) { size_t line_len = 0; - char buffer[BUFSIZ]; + char buffer[NMH_BUFSIZ]; size_t inbytes; if (! ce->ce_fp && (ce->ce_fp = fopen (ce->ce_file, "r")) == NULL) { @@ -2171,7 +2186,7 @@ strip_crs (CT ct, int *message_mods) { } if (fp && *fp) { - char buffer[BUFSIZ]; + char buffer[NMH_BUFSIZ]; size_t bytes_read; size_t bytes_to_read = end > 0 && end > begin ? end - begin : sizeof buffer; @@ -2247,12 +2262,10 @@ strip_crs (CT ct, int *message_mods) { status = NOTOK; } else { /* Replace the decoded file with the converted one. */ - if (ct->c_cefile.ce_file) { - if (ct->c_cefile.ce_unlink) { - (void) m_unlink (ct->c_cefile.ce_file); - } - free (ct->c_cefile.ce_file); - } + 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); ct->c_cefile.ce_file = stripped_content_file; ct->c_cefile.ce_unlink = 1; @@ -2527,12 +2540,9 @@ fix_always (CT ct, int *message_mods) { */ static int fix_filename_param (char *name, char *value, PM *first_pm, PM *last_pm) { - size_t value_len; int fixed = 0; - if (((value_len = strlen (value)) > 0) && - strncmp (value, "=?", 2) == 0 && - strncmp (&value[value_len - 2], "?=", 2) == 0) { + if (HasPrefix(value, "=?") && HasSuffix(value, "?=")) { /* Looks like an RFC 2047 encoded parameter. */ char decoded[PATH_MAX + 1]; @@ -2603,8 +2613,8 @@ fix_filename_encoding (CT ct) { const char *const new_params = concat (params, "\n", NULL); replace_substring (&hf->value, semicolon_loc, new_params); - free ((char *) new_params); - free ((char *) params); + free((void *)new_params); /* Cast away const. Sigh. */ + free((void *)params); } else { advise (NULL, "did not find semicolon in %s:%s\n", hf->name, hf->value); @@ -2642,7 +2652,7 @@ write_content (CT ct, const char *input_filename, char *outfile, int modify_inpl int i = -1; if (old != -1 && new != -1) { - char buffer[BUFSIZ]; + char buffer[NMH_BUFSIZ]; while ((i = read (old, buffer, sizeof buffer)) > 0) { @@ -2741,12 +2751,11 @@ remove_file (const char *file) { free (rmm_command); return WIFEXITED (status) ? WEXITSTATUS (status) : NOTOK; - } else { - /* This is OK for a non-message file, it still uses the - BACKUP_PREFIX form. The backup file will be in the same - directory as file. */ - return rename (file, m_backup (file)); } + /* This is OK for a non-message file, it still uses the + BACKUP_PREFIX form. The backup file will be in the same + directory as file. */ + return rename (file, m_backup (file)); }