X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/e996186ed31572ee94c32abf6083f57d69777888..92128dac:/uip/mhfixmsg.c?ds=sidebyside diff --git a/uip/mhfixmsg.c b/uip/mhfixmsg.c index df475646..f5488532 100644 --- a/uip/mhfixmsg.c +++ b/uip/mhfixmsg.c @@ -53,15 +53,11 @@ int debugsw; /* Needed by 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 */ -CT parse_mime (char *); void reverse_parts (CT); /* mhoutsbr.c */ int output_message (CT, char *); -/* mhshowsbr.c */ -int show_content_aux (CT, int, int, char *, char *); - /* mhmisc.c */ void flush_errors (void); @@ -85,7 +81,7 @@ int mhfixmsgsbr (CT *, const fix_transformations *, char *); 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 int replace_boundary (CT, char *, char *); static int fix_multipart_cte (CT, int *); static int set_ce (CT, int); static int ensure_text_plain (CT *, CT, int *, int); @@ -100,12 +96,12 @@ static int boundary_in_content (FILE **, char *, const char *); static void transfer_noncontent_headers (CT, CT); 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 content_encoding (CT, const char **); static int strip_crs (CT, int *); 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 void report (char *, char *, char *, char *, ...); static void pipeser (int); @@ -291,11 +287,12 @@ main (int argc, char **argv) { } } - if (! (cts = (CT *) calloc ((size_t) 2, sizeof *cts))) + if (! (cts = (CT *) calloc ((size_t) 2, sizeof *cts))) { adios (NULL, "out of memory"); + } ctp = cts; - if ((ct = parse_mime (file))) *ctp++ = ct; + if ((ct = parse_mime (file))) { *ctp++ = ct; } } else { /* * message(s) are coming from a folder @@ -325,8 +322,9 @@ main (int argc, char **argv) { done (1); seq_setprev (mp); /* set the previous-sequence */ - if (! (cts = (CT *) calloc ((size_t) (mp->numsel + 1), sizeof *cts))) + if (! (cts = (CT *) calloc ((size_t) (mp->numsel + 1), sizeof *cts))) { adios (NULL, "out of memory"); + } ctp = cts; for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { @@ -334,7 +332,7 @@ main (int argc, char **argv) { char *msgnam; msgnam = m_name (msgnum); - if ((ct = parse_mime (msgnam))) *ctp++ = ct; + if ((ct = parse_mime (msgnam))) { *ctp++ = ct; } } } @@ -450,7 +448,7 @@ mhfixmsgsbr (CT *ctp, const fix_transformations *fx, char *outfile) { } if (modify_inplace) { - if (status != OK) (void) m_unlink (outfile); + if (status != OK) { (void) m_unlink (outfile); } free (outfile); outfile = NULL; } @@ -516,7 +514,7 @@ fix_boundary (CT *ct, int *message_mods) { ++*message_mods; if (verbosw) { - report (NULL, filename, + report (NULL, NULL, filename, "fix multipart boundary"); } } @@ -563,10 +561,11 @@ get_multipart_boundary (CT ct, char **part_boundary) { while (begin >= (off_t) ct->c_begin) { fseeko (ct->c_fp, begin, SEEK_SET); while ((bytes_read = fread (buffer, 1, sizeof buffer, ct->c_fp)) > 0) { - char *end = buffer + bytes_read - 1; - char *cp; + char *cp = rfind_str (buffer, bytes_read, "--"); + + if (cp) { + char *end; - if ((cp = rfind_str (buffer, bytes_read, "--"))) { /* Trim off trailing "--" and anything beyond. */ *cp-- = '\0'; if ((end = rfind_str (buffer, cp - buffer, "\n"))) { @@ -622,7 +621,7 @@ get_multipart_boundary (CT ct, char **part_boundary) { /* Open and copy ct->c_file to file, replacing the multipart boundary. */ static int -replace_boundary (CT ct, char *file, const char *boundary) { +replace_boundary (CT ct, char *file, char *boundary) { FILE *fpin, *fpout; int compnum, state; char buf[BUFSIZ], name[NAMESZ]; @@ -668,10 +667,22 @@ replace_boundary (CT ct, char *file, const char *boundary) { if (strcasecmp (TYPE_FIELD, np)) { fprintf (fpout, "%s:%s", np, vp); } else { - char *new_boundary = update_attr (vp, "boundary=", boundary); - - fprintf (fpout, "%s:%s\n", np, new_boundary); - free (new_boundary); + char *new_ctline, *new_params; + + replace_param(&ct->c_ctinfo.ci_first_pm, + &ct->c_ctinfo.ci_last_pm, "boundary", + boundary, 0); + + new_ctline = concat(" ", ct->c_ctinfo.ci_type, "/", + ct->c_ctinfo.ci_subtype, NULL); + new_params = output_params(strlen(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 : ""); + free(new_ctline); + if (new_params) + free(new_params); } free (vp); @@ -746,7 +757,7 @@ fix_multipart_cte (CT ct, int *message_mods) { ++*message_mods; if (verbosw) { char *encoding = cpytrim (hf->value); - report (ct->c_partno, ct->c_file, + report (NULL, ct->c_partno, ct->c_file, "replace Content-Transfer-Encoding of %s " "with 8 bit", encoding); free (encoding); @@ -837,7 +848,7 @@ ensure_text_plain (CT *ct, CT parent, int *message_mods, int replacetextplain) { int has_text_plain = 0; /* Nothing to do for text/plain. */ - if ((*ct)->c_subtype == TEXT_PLAIN) return OK; + if ((*ct)->c_subtype == TEXT_PLAIN) { return OK; } if (parent && parent->c_type == CT_MULTIPART && parent->c_subtype == MULTI_ALTERNATE) { @@ -860,7 +871,7 @@ ensure_text_plain (CT *ct, CT parent, int *message_mods, int replacetextplain) { prev->mp_next = part->mp_next; } if (verbosw) { - report (parent->c_partno, parent->c_file, + report (NULL, parent->c_partno, parent->c_file, "remove text/plain part %s", old_part->mp_part->c_partno); } @@ -891,7 +902,7 @@ ensure_text_plain (CT *ct, CT parent, int *message_mods, int replacetextplain) { ++*message_mods; if (verbosw) { - report (parent->c_partno, parent->c_file, + report (NULL, parent->c_partno, parent->c_file, "insert text/plain part"); } } else { @@ -918,7 +929,7 @@ ensure_text_plain (CT *ct, CT parent, int *message_mods, int replacetextplain) { ++*message_mods; if (verbosw) { - report ((*ct)->c_partno, (*ct)->c_file, + report (NULL, (*ct)->c_partno, (*ct)->c_file, "insert text/plain part"); } } else { @@ -1028,19 +1039,19 @@ divide_part (CT ct) { static void copy_ctinfo (CI dest, CI src) { - char **s_ap, **d_ap, **s_vp, **d_vp; + PM s_pm, d_pm; dest->ci_type = src->ci_type ? add (src->ci_type, NULL) : NULL; dest->ci_subtype = src->ci_subtype ? add (src->ci_subtype, NULL) : NULL; - for (s_ap = src->ci_attrs, d_ap = dest->ci_attrs, - s_vp = src->ci_values, d_vp = dest->ci_values; - *s_ap; - ++s_ap, ++d_ap, ++s_vp, ++d_vp) { - *d_ap = add (*s_ap, NULL); - *d_vp = *s_vp; + for (s_pm = src->ci_first_pm; s_pm; s_pm = s_pm->pm_next) { + 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); + if (s_pm->pm_lang) + d_pm->pm_lang = getcpy(s_pm->pm_lang); } - *d_ap = NULL; dest->ci_comment = src->ci_comment ? add (src->ci_comment, NULL) : NULL; dest->ci_magic = src->ci_magic ? add (src->ci_magic, NULL) : NULL; @@ -1082,40 +1093,25 @@ reformat_part (CT ct, char *file, char *type, char *subtype, int c_type) { Could show_multi() in mhshowsbr.c avoid this? */ /* Check for invo_name-format-type/subtype. */ - cp = concat (invo_name, "-format-", type, "/", subtype, NULL); - if ((cf = context_find (cp)) && *cf != '\0') { + if ((cf = context_find_by_type ("format", type, subtype)) == NULL) { + if (verbosw) { + advise (NULL, "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; + } else { if (strchr (cf, '>')) { - free (cp); advise (NULL, "'>' prohibited in \"%s\",\nplease fix your " "%s-format-%s/%s profile entry", cf, invo_name, type, - subtype); - return NOTOK; - } - } else { - free (cp); - - /* Check for invo_name-format-type. */ - cp = concat (invo_name, "-format-", type, NULL); - if (! (cf = context_find (cp)) || *cf == '\0') { - free (cp); - if (verbosw) { - advise (NULL, "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; - } + subtype ? subtype : ""); - if (strchr (cf, '>')) { - free (cp); - advise (NULL, "'>' prohibited in \"%s\"", cf); return NOTOK; } } - free (cp); cp = concat (cf, " >", file, NULL); - status = show_content_aux (ct, 1, 0, cp, NULL); + status = show_content_aux (ct, 0, cp, NULL, NULL); free (cp); /* Unlink decoded content tmp file and free its filename to avoid @@ -1150,12 +1146,9 @@ reformat_part (CT ct, char *file, char *type, char *subtype, int c_type) { /* Identifies 7bit or 8bit content based on charset. */ static int charset_encoding (CT ct) { - /* norm_charmap() is case sensitive. */ - char *charset = upcase (content_charset (ct)); int encoding = - strcmp (norm_charmap (charset), "US-ASCII") ? CE_8BIT : CE_7BIT; + strcasecmp (content_charset (ct), "US-ASCII") ? CE_8BIT : CE_7BIT; - free (charset); return encoding; } @@ -1169,7 +1162,6 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { CT ct; struct part *p; struct multipart *m; - char *cp; const struct str2init *ctinit; if ((ct = (CT) calloc (1, sizeof *ct)) == NULL) @@ -1184,7 +1176,7 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { c_cefile, c_encoding, c_digested, c_digest[16], c_ctexbody, c_ctinitfnx, c_ceopenfnx, c_ceclosefnx, c_cesizefnx, - c_umask, c_pid, c_rfc934, + c_umask, c_rfc934, c_showproc, c_termproc, c_storeproc, c_storage, c_folder */ @@ -1211,6 +1203,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)) == -1) { + free (ct); return NULL; } } @@ -1221,6 +1214,7 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { if ((found_boundary = boundary_in_content (&new_part->c_fp, new_part->c_file, boundary)) == -1) { + free (ct); return NULL; } } @@ -1241,6 +1235,7 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { if (found_boundary) { advise (NULL, "giving up trying to find a unique boundary"); + free (ct); return NULL; } } @@ -1269,14 +1264,8 @@ build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { ct->c_ctinfo.ci_subtype = add (subtypename, NULL); } - name = concat (" ", typename, "/", subtypename, boundary_indicator, - boundary, NULL); - if ((cp = strstr (name, boundary_indicator))) { - ct->c_ctinfo.ci_attrs[0] = name; - ct->c_ctinfo.ci_attrs[1] = NULL; - /* ci_values don't get free'd, so point into ci_attrs. */ - ct->c_ctinfo.ci_values[0] = cp + strlen (boundary_indicator); - } + add_param(&ct->c_ctinfo.ci_first_pm, &ct->c_ctinfo.ci_last_pm, + "boundary", boundary, 0); p = (struct part *) mh_xmalloc (sizeof *p); p->mp_next = (struct part *) mh_xmalloc (sizeof *p->mp_next); @@ -1430,16 +1419,19 @@ decode_text_parts (CT ct, int encoding, int *message_mods) { int ct_encoding; if (decode_part (ct) == OK && ct->c_cefile.ce_file) { - if ((ct_encoding = content_encoding (ct)) == CE_BINARY && - encoding != CE_BINARY) { + const char *reason = NULL; + + if ((ct_encoding = content_encoding (ct, &reason)) == CE_BINARY + && encoding != CE_BINARY) { /* The decoding isn't acceptable so discard it. Leave status as OK to allow other transformations. */ if (verbosw) { - report (ct->c_partno, ct->c_file, - "will not decode%s because it is binary", + 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 - : ""); + : "", + reason); } (void) m_unlink (ct->c_cefile.ce_file); free (ct->c_cefile.ce_file); @@ -1449,7 +1441,7 @@ decode_text_parts (CT ct, int encoding, int *message_mods) { /* The decoding isn't acceptable so discard it. Leave status as OK to allow other transformations. */ if (verbosw) { - report (ct->c_partno, ct->c_file, + 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 @@ -1469,7 +1461,7 @@ decode_text_parts (CT ct, int encoding, int *message_mods) { if (set_ce (ct, enc) == OK) { ++*message_mods; if (verbosw) { - report (ct->c_partno, ct->c_file, "decode%s", + report (NULL, ct->c_partno, ct->c_file, "decode%s", ct->c_ctline ? ct->c_ctline : ""); } strip_crs (ct, message_mods); @@ -1523,9 +1515,10 @@ decode_text_parts (CT ct, int encoding, int *message_mods) { /* See if the decoded content is 7bit, 8bit, or binary. It's binary if it has any NUL characters, a CR not followed by a LF, or lines - greater than 998 characters in length. */ + greater than 998 characters in length. If binary, reason is set + to a string explaining why. */ static int -content_encoding (CT ct) { +content_encoding (CT ct, const char **reason) { CE ce = &ct->c_cefile; int encoding = CE_7BIT; @@ -1550,6 +1543,16 @@ content_encoding (CT ct) { if (*cp == '\0' || ++line_len > 998 || (*cp != '\n' && last_char_was_cr)) { encoding = CE_BINARY; + if (*cp == '\0') { + *reason = "null character"; + } else if (line_len > 998) { + *reason = "line length > 998"; + } else if (*cp != '\n' && last_char_was_cr) { + *reason = "CR not followed by LF"; + } else { + /* Should not reach this. */ + *reason = ""; + } break; } else if (*cp == '\n') { line_len = 0; @@ -1571,8 +1574,7 @@ content_encoding (CT ct) { static int strip_crs (CT ct, int *message_mods) { - /* norm_charmap() is case sensitive. */ - char *charset = upcase (content_charset (ct)); + char *charset = content_charset (ct); int status = OK; /* Only strip carriage returns if content is ASCII or another @@ -1580,10 +1582,10 @@ strip_crs (CT ct, int *message_mods) { 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 (charset), "US-ASCII") || - ! strncmp (norm_charmap (charset), "ISO-8859-", 9) || - ! strncmp (norm_charmap (charset), "UTF-8", 5) || - ! strncmp (norm_charmap (charset), "WINDOWS-12", 10)) { + if (! strcasecmp (charset, "US-ASCII") || + ! strcasecmp (charset, "UTF-8") || + ! strncasecmp (charset, "ISO-8859-", 9) || + ! strncasecmp (charset, "WINDOWS-12", 10)) { char **file = NULL; FILE **fp = NULL; size_t begin; @@ -1630,7 +1632,7 @@ strip_crs (CT ct, int *message_mods) { size_t i; int last_char_was_cr = 0; - if (end > 0) bytes_to_read -= bytes_read; + if (end > 0) { bytes_to_read -= bytes_read; } for (i = 0, cp = buffer; i < bytes_read; ++i, ++cp) { if (*cp == '\n' && last_char_was_cr) { @@ -1665,11 +1667,19 @@ strip_crs (CT ct, int *message_mods) { if (*cp == '\r') { last_char_was_cr = 1; } else if (last_char_was_cr) { - if (*cp != '\n') write (fd, "\r", 1); - write (fd, cp, 1); + if (*cp != '\n') { + if (write (fd, "\r", 1) < 0) { + advise (tempfile, "write of CR failed"); + } + } + if (write (fd, cp, 1) < 0) { + advise (tempfile, "write failed"); + } last_char_was_cr = 0; } else { - write (fd, cp, 1); + if (write (fd, cp, 1) < 0) { + advise (tempfile, "write failed"); + } last_char_was_cr = 0; } } @@ -1693,7 +1703,7 @@ strip_crs (CT ct, int *message_mods) { ++*message_mods; if (verbosw) { - report (ct->c_partno, + report (NULL, ct->c_partno, begin == 0 && end == 0 ? "" : *file, "stripped CRs"); } @@ -1707,7 +1717,6 @@ strip_crs (CT ct, int *message_mods) { } } - free (charset); return status; } @@ -1720,9 +1729,16 @@ convert_charsets (CT ct, char *dest_charset, int *message_mods) { case CT_TEXT: if (ct->c_subtype == TEXT_PLAIN) { 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); + if (status == OK) { + if (verbosw) { + report (NULL, ct->c_partno, ct->c_file, + "convert %s to %s", + content_charset(ct), dest_charset); + } + } else { + report ("iconv", ct->c_partno, ct->c_file, + "failed to convert %s to %s", + content_charset(ct), dest_charset); } } break; @@ -1791,8 +1807,8 @@ write_content (CT ct, char *input_filename, char *outfile, int modify_inplace, } } } - if (new != -1) close (new); - if (old != -1) close (old); + if (new != -1) { close (new); } + if (old != -1) { close (old); } (void) m_unlink (outfile); if (i < 0) { @@ -1854,7 +1870,7 @@ remove_file (char *file) { static void -report (char *partno, char *filename, char *message, ...) { +report (char *what, char *partno, char *filename, char *message, ...) { va_list args; char *fmt; @@ -1863,7 +1879,7 @@ report (char *partno, char *filename, char *message, ...) { fmt = concat (filename, partno ? " part " : ", ", partno ? partno : "", partno ? ", " : "", message, NULL); - advertise (NULL, NULL, fmt, args); + advertise (what, NULL, fmt, args); free (fmt); va_end (args);