X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/4a78cbcd4fa986d9c1e7bd0a5a4bdb619faeb7cb..03b8e51a39f9c4c4c2182512602eb22736751a0c:/uip/mhfixmsg.c diff --git a/uip/mhfixmsg.c b/uip/mhfixmsg.c index d81337d6..df475646 100644 --- a/uip/mhfixmsg.c +++ b/uip/mhfixmsg.c @@ -12,15 +12,12 @@ #include #include #include -#ifdef HAVE_ICONV -# include -#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) {