From: Richard Russon Date: Thu, 18 Jan 2018 11:13:04 +0000 (+0000) Subject: move functions to library X-Git-Tag: neomutt-20180223~39^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=66e5ba89547bf1e7fa384c7a153241196f30bc7e;p=neomutt move functions to library --- diff --git a/Makefile.autosetup b/Makefile.autosetup index a774d6b06..b6f4538bc 100644 --- a/Makefile.autosetup +++ b/Makefile.autosetup @@ -60,7 +60,7 @@ NEOMUTTOBJS= mutt_account.o addrbook.o alias.o attach.o bcache.o body.o \ curs_main.o edit.o editmsg.o enter.o envelope.o filter.o \ flags.o from.o group.o handler.o hdrline.o \ header.o help.o history.o hook.o init.o keymap.o main.o \ - mbox.o mbyte.o menu.o mh.o muttlib.o mutt_address.o \ + mbox.o menu.o mh.o muttlib.o mutt_address.o \ mutt_socket.o tags.o mx.o \ newsrc.o nntp.o pager.o parameter.o parse.o pattern.o pop.o \ pop_auth.o pop_lib.o postpone.o query.o recvattach.o recvcmd.o \ @@ -93,7 +93,7 @@ ALLOBJS+= $(NEOMUTTOBJS) LIBMUTT= libmutt.a LIBMUTTOBJS= mutt/base64.o mutt/buffer.o mutt/charset.o mutt/date.o mutt/debug.o mutt/exit.o \ mutt/file.o mutt/hash.o mutt/idna.o mutt/list.o mutt/mapping.o mutt/mbyte.o mutt/md5.o \ - mutt/memory.o mutt/message.o mutt/regex.o mutt/sha1.o mutt/signal.o mutt/string.o + mutt/memory.o mutt/message.o mutt/mime.o mutt/regex.o mutt/sha1.o mutt/signal.o mutt/string.o CLEANFILES+= $(LIBMUTT) $(LIBMUTTOBJS) MUTTLIBS+= $(LIBMUTT) ALLOBJS+= $(LIBMUTTOBJS) diff --git a/attach.c b/attach.c index 69515289a..149dfc67e 100644 --- a/attach.c +++ b/attach.c @@ -38,7 +38,6 @@ #include "globals.h" #include "header.h" #include "mailbox.h" -#include "mime.h" #include "mutt_curses.h" #include "mx.h" #include "ncrypt/ncrypt.h" diff --git a/body.c b/body.c index b25e6421b..1e5d58509 100644 --- a/body.c +++ b/body.c @@ -27,7 +27,6 @@ #include "mutt/mutt.h" #include "body.h" #include "header.h" -#include "mime.h" #include "parameter.h" #include "protos.h" diff --git a/browser.c b/browser.c index a31856814..53723c273 100644 --- a/browser.c +++ b/browser.c @@ -47,7 +47,7 @@ #include "globals.h" #include "keymap.h" #include "mailbox.h" -#include "mbyte.h" +#include "mutt_account.h" #include "mutt_curses.h" #include "mutt_menu.h" #include "mx.h" @@ -572,7 +572,7 @@ static const char *group_index_format_str(char *buf, size_t buflen, size_t col, char *desc = mutt_str_strdup(folder->ff->nd->desc); if (NewsgroupsCharset && *NewsgroupsCharset) mutt_ch_convert_string(&desc, NewsgroupsCharset, Charset, MUTT_ICONV_HOOK_FROM); - mutt_filter_unprintable(&desc); + mutt_mb_filter_unprintable(&desc); snprintf(fmt, sizeof(fmt), "%%%ss", prec); snprintf(buf, buflen, fmt, desc); diff --git a/commands.c b/commands.c index c182c34c2..ba6ccecab 100644 --- a/commands.c +++ b/commands.c @@ -45,7 +45,6 @@ #include "header.h" #include "keymap.h" #include "mailbox.h" -#include "mime.h" #include "mutt_curses.h" #include "mutt_menu.h" #include "mx.h" diff --git a/compose.c b/compose.c index f68a3f0f8..7b7b3d752 100644 --- a/compose.c +++ b/compose.c @@ -44,7 +44,6 @@ #include "header.h" #include "keymap.h" #include "mailbox.h" -#include "mime.h" #include "mutt_curses.h" #include "mutt_menu.h" #include "mx.h" diff --git a/copy.c b/copy.c index 0fe851162..64c4b36e2 100644 --- a/copy.c +++ b/copy.c @@ -35,7 +35,6 @@ #include "globals.h" #include "header.h" #include "mailbox.h" -#include "mime.h" #include "mutt_curses.h" #include "mx.h" #include "ncrypt/ncrypt.h" diff --git a/globals.h b/globals.h index 5b66941c0..e33582716 100644 --- a/globals.h +++ b/globals.h @@ -96,17 +96,6 @@ WHERE int CurrentMenu; WHERE struct Alias *Aliases; WHERE struct ListHead UserHeader INITVAL(STAILQ_HEAD_INITIALIZER(UserHeader)); -#ifdef MAIN_C -const char *const BodyTypes[] = { - "x-unknown", "audio", "application", "image", "message", - "model", "multipart", "text", "video", "*", -}; -const char *const BodyEncodings[] = { - "x-unknown", "7bit", "8bit", "quoted-printable", - "base64", "binary", "x-uuencoded", -}; -#endif - /* All the variables below are backing for config items */ WHERE struct Address *EnvelopeFromAddress; diff --git a/handler.c b/handler.c index 7b5269fea..b06bf4bb3 100644 --- a/handler.c +++ b/handler.c @@ -41,7 +41,6 @@ #include "filter.h" #include "globals.h" #include "keymap.h" -#include "mime.h" #include "mutt_curses.h" #include "ncrypt/ncrypt.h" #include "opcodes.h" @@ -57,19 +56,6 @@ typedef int (*handler_t)(struct Body *b, struct State *s); -// clang-format off -const int IndexHex[128] = { - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1, - -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 -}; -// clang-format on - static void print_part_line(struct State *s, struct Body *b, int n) { char length[5]; diff --git a/hcache/hcache.c b/hcache/hcache.c index 321d9e03d..acd094cd3 100644 --- a/hcache/hcache.c +++ b/hcache/hcache.c @@ -56,7 +56,6 @@ #include "hcache.h" #include "hcache/hcversion.h" #include "header.h" -#include "mbyte.h" #include "parameter.h" #include "protos.h" #include "tags.h" diff --git a/init.c b/init.c index 53a197df3..5342fa579 100644 --- a/init.c +++ b/init.c @@ -50,7 +50,6 @@ #include "keymap.h" #include "mailbox.h" #include "mbtable.h" -#include "mbyte.h" #include "mutt_curses.h" #include "mutt_menu.h" #include "mx.h" @@ -2614,7 +2613,7 @@ static int parse_set(struct Buffer *tmp, struct Buffer *s, unsigned long data, FREE((void *) MuttVars[idx].var); *((char **) MuttVars[idx].var) = mutt_str_strdup(tmp->data); if (mutt_str_strcmp(MuttVars[idx].name, "charset") == 0) - mutt_set_charset(Charset); + mutt_ch_set_charset(Charset); if ((mutt_str_strcmp(MuttVars[idx].name, "show_multipart_alternative") == 0) && @@ -4082,7 +4081,7 @@ void mutt_init(int skip_sys_rc, struct ListHead *commands) From = mutt_addr_parse_list(NULL, p); mutt_ch_set_langinfo_charset(); - mutt_set_charset(Charset); + mutt_ch_set_charset(Charset); Matches = mutt_mem_calloc(MatchesListsize, sizeof(char *)); diff --git a/mbyte.c b/mbyte.c deleted file mode 100644 index cc0a39540..000000000 --- a/mbyte.c +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @file - * Convert strings between multibyte and utf8 encodings - * - * @authors - * Copyright (C) 2000 Edmund Grimley Evans - * Copyright (C) 2000 Takashi Takizawa - * - * @copyright - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include "mutt/mutt.h" -#include "mbyte.h" - -#ifndef EILSEQ -#define EILSEQ EINVAL -#endif - -bool Charset_is_utf8 = false; - -void mutt_set_charset(char *charset) -{ - char buffer[STRING]; - - mutt_ch_canonical_charset(buffer, sizeof(buffer), charset); - - if (mutt_ch_is_utf8(buffer)) - { - Charset_is_utf8 = true; - ReplacementChar = 0xfffd; - } - else - { - Charset_is_utf8 = false; - ReplacementChar = '?'; - } - -#if defined(HAVE_BIND_TEXTDOMAIN_CODESET) && defined(ENABLE_NLS) - bind_textdomain_codeset(PACKAGE, buffer); -#endif -} - -bool is_display_corrupting_utf8(wchar_t wc) -{ - if (wc == (wchar_t) 0x200f || /* bidi markers: #3827 */ - wc == (wchar_t) 0x200e || wc == (wchar_t) 0x00ad || /* soft hyphen: #3848 */ - wc == (wchar_t) 0xfeff || /* zero width no-break space */ - (wc >= (wchar_t) 0x2066 && /* misc directional markers */ - wc <= (wchar_t) 0x2069) || - (wc >= (wchar_t) 0x202a && /* misc directional markers: #3854 */ - wc <= (wchar_t) 0x202e)) - return true; - else - return false; -} - -int mutt_filter_unprintable(char **s) -{ - struct Buffer *b = NULL; - wchar_t wc; - size_t k, k2; - char scratch[MB_LEN_MAX + 1]; - char *p = *s; - mbstate_t mbstate1, mbstate2; - - b = mutt_buffer_new(); - if (!b) - return -1; - memset(&mbstate1, 0, sizeof(mbstate1)); - memset(&mbstate2, 0, sizeof(mbstate2)); - for (; (k = mbrtowc(&wc, p, MB_LEN_MAX, &mbstate1)); p += k) - { - if (k == (size_t)(-1) || k == (size_t)(-2)) - { - k = 1; - memset(&mbstate1, 0, sizeof(mbstate1)); - wc = ReplacementChar; - } - if (!IsWPrint(wc)) - wc = '?'; - else if (Charset_is_utf8 && is_display_corrupting_utf8(wc)) - continue; - k2 = wcrtomb(scratch, wc, &mbstate2); - scratch[k2] = '\0'; - mutt_buffer_addstr(b, scratch); - } - FREE(s); - *s = b->data ? b->data : mutt_mem_calloc(1, 1); - FREE(&b); - return 0; -} diff --git a/mbyte.h b/mbyte.h deleted file mode 100644 index 11be857c0..000000000 --- a/mbyte.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @file - * Convert strings between multibyte and utf8 encodings - * - * @authors - * Copyright (C) 2000 Edmund Grimley Evans - * - * @copyright - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, either version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#ifndef _NEOMUTT_MBYTE_H -#define _NEOMUTT_MBYTE_H - -#include -#include - -void mutt_set_charset(char *charset); -extern bool Charset_is_utf8; -bool is_display_corrupting_utf8(wchar_t wc); -int mutt_filter_unprintable(char **s); - -#endif /* _NEOMUTT_MBYTE_H */ diff --git a/menu.c b/menu.c index 04e83edff..c3a7ae677 100644 --- a/menu.c +++ b/menu.c @@ -32,7 +32,6 @@ #include "context.h" #include "globals.h" #include "keymap.h" -#include "mbyte.h" #include "mutt_curses.h" #include "mutt_menu.h" #include "opcodes.h" diff --git a/mutt/charset.c b/mutt/charset.c index c7d108a39..1b35fd01b 100644 --- a/mutt/charset.c +++ b/mutt/charset.c @@ -27,26 +27,32 @@ * * | Data | Description * | :------------------ | :-------------------------------------------------- + * | #Charset | User's chosen character set + * | #Charset_is_utf8 | Is the user's current character set utf-8? + * | #lookup_charset | Look for a preferred character set name * | #PreferredMIMENames | Lookup table of preferred charsets + * | #ReplacementChar | When a Unicode character can't be displayed, use this instead * * | Function | Description * | :----------------------------- | :--------------------------------------------------------- - * | mutt_ch_canonical_charset() | Canonicalise the charset of a string - * | mutt_ch_charset_lookup() | Look for a replacement character set - * | mutt_ch_check_charset() | Does iconv understand a character set? - * | mutt_ch_chscmp() | Are the names of two character sets equivalent? - * | mutt_ch_convert_string() | Convert a string between encodings - * | mutt_ch_fgetconv() | Convert a file's character set - * | mutt_ch_fgetconvs() | Convert a file's charset into a string buffer - * | mutt_ch_fgetconv_close() | Close an fgetconv handle - * | mutt_ch_fgetconv_open() | Prepare a file for charset conversion - * | mutt_ch_get_default_charset() | Get the default character set - * | mutt_ch_iconv() | Change the encoding of a string - * | mutt_ch_iconv_lookup() | Look for a replacement character set - * | mutt_ch_iconv_open() | Set up iconv for conversions - * | mutt_ch_lookup_add() | Add a new character set lookup - * | mutt_ch_lookup_remove() | Remove all the character set lookups - * | mutt_ch_set_langinfo_charset() | Set the user's choice of character set + * | mutt_ch_canonical_charset() | Canonicalise the charset of a string + * | mutt_ch_charset_lookup() | Look for a replacement character set + * | mutt_ch_check_charset() | Does iconv understand a character set? + * | mutt_ch_chscmp() | Are the names of two character sets equivalent? + * | mutt_ch_convert_nonmime_string() | XXX + * | mutt_ch_convert_string() | Convert a string between encodings + * | mutt_ch_fgetconv() | Convert a file's character set + * | mutt_ch_fgetconvs() | Convert a file's charset into a string buffer + * | mutt_ch_fgetconv_close() | Close an fgetconv handle + * | mutt_ch_fgetconv_open() | Prepare a file for charset conversion + * | mutt_ch_get_default_charset() | Get the default character set + * | mutt_ch_iconv() | Change the encoding of a string + * | mutt_ch_iconv_lookup() | Look for a replacement character set + * | mutt_ch_iconv_open() | Set up iconv for conversions + * | mutt_ch_lookup_add() | Add a new character set lookup + * | mutt_ch_lookup_remove() | Remove all the character set lookups + * | mutt_ch_set_charset() | Update the records for a new character set + * | mutt_ch_set_langinfo_charset() | Set the user's choice of character set */ #include "config.h" @@ -55,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +80,16 @@ char *AssumedCharset; /**< Encoding schemes for messages without indication */ char *Charset; /**< User's choice of character set */ +/** + * ReplacementChar - When a Unicode character can't be displayed, use this instead + */ +wchar_t ReplacementChar = '?'; + +/** + * Charset_is_utf8 - Is the user's current character set utf-8? + */ +bool Charset_is_utf8 = false; + /** * struct Lookup - Regex to String lookup table * @@ -267,6 +284,49 @@ static const char *lookup_charset(enum LookupType type, const char *cs) return NULL; } +/** + * mutt_ch_convert_nonmime_string - Try to convert a string using a list of character sets + * @param ps[in,out] String to be converted + * @retval 0 Success + * @retval -1 Error + * + * Work through #AssumedCharset looking for a character set conversion that + * works. Failing that, try mutt_ch_get_default_charset(). + */ +int mutt_ch_convert_nonmime_string(char **ps) +{ + const char *c1 = NULL; + + for (const char *c = AssumedCharset; c; c = c1 ? c1 + 1 : 0) + { + char *u = *ps; + char *s = NULL; + char *fromcode = NULL; + size_t n; + size_t ulen = mutt_str_strlen(*ps); + + if (!u || !*u) + return 0; + + c1 = strchr(c, ':'); + n = c1 ? c1 - c : mutt_str_strlen(c); + if (!n) + return 0; + fromcode = mutt_mem_malloc(n + 1); + mutt_str_strfcpy(fromcode, c, n + 1); + s = mutt_str_substr_dup(u, u + ulen); + int m = mutt_ch_convert_string(&s, fromcode, Charset, 0); + FREE(&fromcode); + if (m == 0) + { + return 0; + } + } + mutt_ch_convert_string(ps, (const char *) mutt_ch_get_default_charset(), + Charset, MUTT_ICONV_HOOK_FROM); + return -1; +} + /** * mutt_ch_canonical_charset - Canonicalise the charset of a string * @param buf Buffer for canonical character set name @@ -858,3 +918,35 @@ char *mutt_ch_fgetconvs(char *buf, size_t buflen, struct FgetConv *fc) return NULL; } + +/** + * mutt_ch_set_charset - Update the records for a new character set + * @param charset New character set + * + * Check if this chararacter set is utf-8 and pick a suitable replacement + * character for unprintable characters. + * + * @note This calls `bind_textdomain_codeset()` which will affect future + * message translations. + */ +void mutt_ch_set_charset(char *charset) +{ + char buffer[STRING]; + + mutt_ch_canonical_charset(buffer, sizeof(buffer), charset); + + if (mutt_ch_is_utf8(buffer)) + { + Charset_is_utf8 = true; + ReplacementChar = 0xfffd; + } + else + { + Charset_is_utf8 = false; + ReplacementChar = '?'; + } + +#if defined(HAVE_BIND_TEXTDOMAIN_CODESET) && defined(ENABLE_NLS) + bind_textdomain_codeset(PACKAGE, buffer); +#endif +} diff --git a/mutt/charset.h b/mutt/charset.h index 9d92170d1..6b3b07030 100644 --- a/mutt/charset.h +++ b/mutt/charset.h @@ -26,11 +26,14 @@ #include #include #include +#include struct Buffer; extern char *AssumedCharset; extern char *Charset; +extern bool Charset_is_utf8; +extern wchar_t ReplacementChar; /** * struct FgetConv - Cursor for converting a file's encoding @@ -83,6 +86,7 @@ void mutt_ch_canonical_charset(char *buf, size_t buflen, const char int mutt_ch_chscmp(const char *cs1, const char *cs2); char * mutt_ch_get_default_charset(void); void mutt_ch_set_langinfo_charset(void); +void mutt_ch_set_charset(char *charset); bool mutt_ch_lookup_add(enum LookupType type, const char *pat, const char *replace, struct Buffer *err); void mutt_ch_lookup_remove(void); @@ -92,6 +96,7 @@ iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, in size_t mutt_ch_iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft, const char **inrepls, const char *outrepl); const char * mutt_ch_iconv_lookup(const char *chs); int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags); +int mutt_ch_convert_nonmime_string(char **ps); bool mutt_ch_check_charset(const char *cs, bool strict); struct FgetConv *mutt_ch_fgetconv_open(FILE *file, const char *from, const char *to, int flags); diff --git a/mutt/mbyte.c b/mutt/mbyte.c index daa4f74a3..9cde9f057 100644 --- a/mutt/mbyte.c +++ b/mutt/mbyte.c @@ -29,18 +29,20 @@ * | :---------------------- | :-------------------------------------------------- * | #ReplacementChar | When a Unicode character can't be displayed, use this instead * - * | Function | Description - * | :---------------------- | :--------------------------------------------------------- - * | mutt_mb_charlen() | Count the bytes in a (multibyte) character - * | mutt_mb_get_initials() | Turn a name into initials - * | mutt_mb_is_lower() | Does a multi-byte string contain only lowercase characters? - * | mutt_mb_is_shell_char() | Is character not typically part of a pathname - * | mutt_mb_mbstowcs() | Convert a string from multibyte to wide characters - * | mutt_mb_wcstombs() | Convert a string from wide to multibyte characters - * | mutt_mb_wcswidth() | Measure the screen width of a string - * | mutt_mb_wcwidth() | Measure the screen width of a character - * | mutt_mb_width() | Measure a string's display width (in screen columns) - * | mutt_mb_width_ceiling() | Keep the end of the string on-screen + * | Function | Description + * | :----------------------------------- | :--------------------------------------------------------- + * | mutt_mb_charlen() | Count the bytes in a (multibyte) character + * | mutt_mb_filter_unprintable() | Replace unprintable characters + * | mutt_mb_get_initials() | Turn a name into initials + * | mutt_mb_is_display_corrupting_utf8() | Will this character corrupt the display? + * | mutt_mb_is_lower() | Does a multi-byte string contain only lowercase characters? + * | mutt_mb_is_shell_char() | Is character not typically part of a pathname + * | mutt_mb_mbstowcs() | Convert a string from multibyte to wide characters + * | mutt_mb_wcstombs() | Convert a string from wide to multibyte characters + * | mutt_mb_wcswidth() | Measure the screen width of a string + * | mutt_mb_wcwidth() | Measure the screen width of a character + * | mutt_mb_width() | Measure a string's display width (in screen columns) + * | mutt_mb_width_ceiling() | Keep the end of the string on-screen */ #include "config.h" @@ -51,17 +53,14 @@ #include #include #include +#include "buffer.h" +#include "charset.h" #include "mbyte.h" #include "memory.h" #include "string2.h" bool OPT_LOCALES; /**< (pseudo) set if user has valid locale definition */ -/** - * ReplacementChar - When a Unicode character can't be displayed, use this instead - */ -wchar_t ReplacementChar = '?'; - /** * mutt_mb_charlen - Count the bytes in a (multibyte) character * @param[in] s String to be examined @@ -385,3 +384,81 @@ bool mutt_mb_is_lower(const char *s) return true; } + +/** + * mutt_mb_is_display_corrupting_utf8 - Will this character corrupt the display? + * @param wc Character to examine + * @retval true Character would corrupt the display + * @retval false Character is safe to display + * + * @note This list isn't complete. + */ +bool mutt_mb_is_display_corrupting_utf8(wchar_t wc) +{ + if ((wc == (wchar_t) 0x00ad) || /* soft hyphen */ + (wc == (wchar_t) 0x200e) || /* left-to-right mark */ + (wc == (wchar_t) 0x200f) || /* right-to-left mark */ + (wc == (wchar_t) 0xfeff)) /* zero width no-break space */ + { + return true; + } + + /* left-to-right isolate, right-to-left isolate, first strong isolate, + * pop directional isolate */ + if ((wc >= (wchar_t) 0x2066) && (wc <= (wchar_t) 0x2069)) + return true; + + /* left-to-right embedding, right-to-left embedding, pop directional formatting, + * left-to-right override, right-to-left override */ + if ((wc >= (wchar_t) 0x202a) && (wc <= (wchar_t) 0x202e)) + return true; + + return false; +} + +/** + * mutt_mb_filter_unprintable - Replace unprintable characters + * @param[in,out] s String to modify + * @retval 0 Success + * @retval -1 Error + * + * Unprintable characters will be replaced with #ReplacementChar. + * + * @note The source string will be freed and a newly allocated string will be + * returned in its place. The caller should free the returned string. + */ +int mutt_mb_filter_unprintable(char **s) +{ + struct Buffer *b = NULL; + wchar_t wc; + size_t k, k2; + char scratch[MB_LEN_MAX + 1]; + char *p = *s; + mbstate_t mbstate1, mbstate2; + + b = mutt_buffer_new(); + if (!b) + return -1; + memset(&mbstate1, 0, sizeof(mbstate1)); + memset(&mbstate2, 0, sizeof(mbstate2)); + for (; (k = mbrtowc(&wc, p, MB_LEN_MAX, &mbstate1)); p += k) + { + if ((k == (size_t) -1) || (k == (size_t) -2)) + { + k = 1; + memset(&mbstate1, 0, sizeof(mbstate1)); + wc = ReplacementChar; + } + if (!IsWPrint(wc)) + wc = '?'; + else if (Charset_is_utf8 && mutt_mb_is_display_corrupting_utf8(wc)) + continue; + k2 = wcrtomb(scratch, wc, &mbstate2); + scratch[k2] = '\0'; + mutt_buffer_addstr(b, scratch); + } + FREE(s); + *s = b->data ? b->data : mutt_mem_calloc(1, 1); + FREE(&b); + return 0; +} diff --git a/mutt/mbyte.h b/mutt/mbyte.h index cd097b233..c30c75da7 100644 --- a/mutt/mbyte.h +++ b/mutt/mbyte.h @@ -30,7 +30,6 @@ #include extern bool OPT_LOCALES; -extern wchar_t ReplacementChar; #ifdef LOCALES_HACK #define IsPrint(c) (isprint((unsigned char) (c)) || ((unsigned char) (c) >= 0xa0)) @@ -52,5 +51,7 @@ int mutt_mb_wcswidth(const wchar_t *s, size_t n); int mutt_mb_wcwidth(wchar_t wc); size_t mutt_mb_width_ceiling(const wchar_t *s, size_t n, int w1); int mutt_mb_width(const char *str, int col, bool display); +int mutt_mb_filter_unprintable(char **s); +bool mutt_mb_is_display_corrupting_utf8(wchar_t wc); #endif /* _MUTT_MBYTE_H */ diff --git a/mutt/mime.c b/mutt/mime.c new file mode 100644 index 000000000..7e9d88f66 --- /dev/null +++ b/mutt/mime.c @@ -0,0 +1,74 @@ +/** + * @file + * Constants and macros for managing MIME encoding + * + * @authors + * Copyright (C) 2018 Richard Russon + * + * @copyright + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +/** + * @page mime Constants and macros for managing MIME encoding + * + * Constants and macros for managing MIME encoding. + * + * | Data | Description + * | :------------- | :-------------------------------------------------- + * | #BodyEncodings | Common MIME body encodings + * | #BodyTypes | Common MIME body types + * | #IndexHex | Lookup table for ASCII hex digits + * | #MimeSpecials | Characters that need special treatment in MIME + */ + +#include "config.h" +#include "mime.h" + +// clang-format off +/** + * IndexHex - Lookup table for ASCII hex digits + */ +const int IndexHex[128] = { + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1, + -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 +}; +// clang-format on + +/** + * BodyTypes - Common MIME body types + */ +const char *const BodyTypes[] = { + "x-unknown", "audio", "application", "image", "message", + "model", "multipart", "text", "video", "*", +}; + +/** + * BodyEncodings - Common MIME body encodings + */ +const char *const BodyEncodings[] = { + "x-unknown", "7bit", "8bit", "quoted-printable", + "base64", "binary", "x-uuencoded", +}; + +/** + * MimeSpecials - Characters that need special treatment in MIME + */ +const char MimeSpecials[] = "@.,;:<>[]\\\"()?/= \t"; diff --git a/mime.h b/mutt/mime.h similarity index 93% rename from mime.h rename to mutt/mime.h index 82bf1cfee..598e20a23 100644 --- a/mime.h +++ b/mutt/mime.h @@ -67,7 +67,10 @@ enum ContentDisposition /* MIME encoding/decoding global vars */ -extern const int IndexHex[]; +extern const int IndexHex[128]; +extern const char *const BodyTypes[]; +extern const char *const BodyEncodings[]; +extern const char MimeSpecials[]; #define hexval(c) IndexHex[(unsigned int) (c)] @@ -76,14 +79,8 @@ extern const int IndexHex[]; ((x)->type == TYPEMESSAGE && ((strcasecmp((x)->subtype, "rfc822") == 0) || \ (strcasecmp((x)->subtype, "news") == 0)))) -extern const char *BodyTypes[]; -extern const char *BodyEncodings[]; - #define TYPE(X) \ ((X->type == TYPEOTHER) && (X->xtype != NULL) ? X->xtype : BodyTypes[(X->type)]) #define ENCODING(X) BodyEncodings[(X)] -/* other MIME-related global variables */ -extern const char MimeSpecials[]; - #endif /* _MUTT_MIME_H */ diff --git a/mutt/mutt.h b/mutt/mutt.h index b03cba2ae..ebf4c8a9f 100644 --- a/mutt/mutt.h +++ b/mutt/mutt.h @@ -43,6 +43,7 @@ * -# @subpage md5 * -# @subpage memory * -# @subpage message + * -# @subpage mime * -# @subpage regex * -# @subpage sha1 * -# @subpage signal @@ -67,6 +68,7 @@ #include "md5.h" #include "memory.h" #include "message.h" +#include "mime.h" #include "regex3.h" #include "sha1.h" #include "signal2.h" diff --git a/muttlib.c b/muttlib.c index dba155b99..322e9a0d5 100644 --- a/muttlib.c +++ b/muttlib.c @@ -51,7 +51,6 @@ #include "globals.h" #include "header.h" #include "mailbox.h" -#include "mime.h" #include "mutt_curses.h" #include "mx.h" #include "ncrypt/ncrypt.h" diff --git a/ncrypt/crypt.c b/ncrypt/crypt.c index eb506f58c..b34baa157 100644 --- a/ncrypt/crypt.c +++ b/ncrypt/crypt.c @@ -44,7 +44,6 @@ #include "envelope.h" #include "globals.h" #include "header.h" -#include "mime.h" #include "mutt_curses.h" #include "ncrypt.h" #include "options.h" diff --git a/ncrypt/crypt_gpgme.c b/ncrypt/crypt_gpgme.c index ef659c7bf..7186551e1 100644 --- a/ncrypt/crypt_gpgme.c +++ b/ncrypt/crypt_gpgme.c @@ -53,7 +53,6 @@ #include "globals.h" #include "header.h" #include "keymap.h" -#include "mime.h" #include "mutt_curses.h" #include "mutt_menu.h" #include "ncrypt.h" diff --git a/ncrypt/gnupgparse.c b/ncrypt/gnupgparse.c index 2fdf9130e..777c22207 100644 --- a/ncrypt/gnupgparse.c +++ b/ncrypt/gnupgparse.c @@ -42,7 +42,6 @@ #include "mutt.h" #include "filter.h" #include "globals.h" -#include "mime.h" #include "ncrypt.h" #include "options.h" #include "pgpinvoke.h" diff --git a/ncrypt/pgp.c b/ncrypt/pgp.c index 7a76cfce1..973a35e2d 100644 --- a/ncrypt/pgp.c +++ b/ncrypt/pgp.c @@ -50,7 +50,6 @@ #include "filter.h" #include "globals.h" #include "header.h" -#include "mime.h" #include "mutt_curses.h" #include "ncrypt.h" #include "options.h" diff --git a/ncrypt/pgpkey.c b/ncrypt/pgpkey.c index c41e8fd8e..ff11f60f4 100644 --- a/ncrypt/pgpkey.c +++ b/ncrypt/pgpkey.c @@ -43,7 +43,6 @@ #include "globals.h" #include "gnupgparse.h" #include "keymap.h" -#include "mime.h" #include "mutt_curses.h" #include "mutt_menu.h" #include "ncrypt.h" diff --git a/ncrypt/smime.c b/ncrypt/smime.c index 3e1433ec5..cc861adac 100644 --- a/ncrypt/smime.c +++ b/ncrypt/smime.c @@ -44,7 +44,6 @@ #include "globals.h" #include "header.h" #include "keymap.h" -#include "mime.h" #include "mutt_curses.h" #include "mutt_menu.h" #include "ncrypt.h" diff --git a/pager.c b/pager.c index 89e691d28..806964e90 100644 --- a/pager.c +++ b/pager.c @@ -45,7 +45,6 @@ #include "header.h" #include "keymap.h" #include "mailbox.h" -#include "mbyte.h" #include "mutt_curses.h" #include "mutt_menu.h" #include "mx.h" @@ -1264,7 +1263,7 @@ static int format_line(struct Line **line_info, int n, unsigned char *buf, int f mutt_debug(3, "skip zero-width character U+%04X\n", (unsigned short) wc); continue; } - if (is_display_corrupting_utf8(wc)) + if (mutt_mb_is_display_corrupting_utf8(wc)) { mutt_debug(3, "filtered U+%04X\n", (unsigned short) wc); continue; diff --git a/parse.c b/parse.c index c0b92045d..b8ce65de7 100644 --- a/parse.c +++ b/parse.c @@ -36,7 +36,6 @@ #include "globals.h" #include "header.h" #include "mailbox.h" -#include "mime.h" #include "ncrypt/ncrypt.h" #include "options.h" #include "parameter.h" diff --git a/postpone.c b/postpone.c index bafd442de..4ef981f3e 100644 --- a/postpone.c +++ b/postpone.c @@ -40,7 +40,6 @@ #include "header.h" #include "keymap.h" #include "mailbox.h" -#include "mime.h" #include "mutt_menu.h" #include "ncrypt/ncrypt.h" #include "opcodes.h" diff --git a/recvattach.c b/recvattach.c index 352c99828..7303e3f5c 100644 --- a/recvattach.c +++ b/recvattach.c @@ -40,7 +40,6 @@ #include "header.h" #include "keymap.h" #include "mailbox.h" -#include "mime.h" #include "mutt_curses.h" #include "mutt_menu.h" #include "mx.h" diff --git a/rfc2047.c b/rfc2047.c index 591f07aa5..9f71e1a43 100644 --- a/rfc2047.c +++ b/rfc2047.c @@ -31,8 +31,6 @@ #include "rfc2047.h" #include "address.h" #include "globals.h" -#include "mbyte.h" -#include "mime.h" #include "options.h" /* If you are debugging this file, comment out the following line. */ @@ -85,42 +83,6 @@ static size_t convert_string(const char *f, size_t flen, const char *from, return n; } -int convert_nonmime_string(char **ps) -{ - const char *c1 = NULL; - - for (const char *c = AssumedCharset; c; c = c1 ? c1 + 1 : 0) - { - char *u = *ps; - char *s = NULL; - char *fromcode = NULL; - size_t m, n; - size_t ulen = mutt_str_strlen(*ps); - size_t slen; - - if (!u || !*u) - return 0; - - c1 = strchr(c, ':'); - n = c1 ? c1 - c : mutt_str_strlen(c); - if (!n) - return 0; - fromcode = mutt_mem_malloc(n + 1); - mutt_str_strfcpy(fromcode, c, n + 1); - m = convert_string(u, ulen, fromcode, Charset, &s, &slen); - FREE(&fromcode); - if (m != (size_t)(-1)) - { - FREE(ps); - *ps = s; - return 0; - } - } - mutt_ch_convert_string(ps, (const char *) mutt_ch_get_default_charset(), - Charset, MUTT_ICONV_HOOK_FROM); - return -1; -} - char *mutt_choose_charset(const char *fromcode, const char *charsets, char *u, size_t ulen, char **d, size_t *dlen) { @@ -738,7 +700,7 @@ static int rfc2047_decode_word(char *d, const char *s, size_t len) if (charset) mutt_ch_convert_string(&d0, charset, Charset, MUTT_ICONV_HOOK_FROM); - mutt_filter_unprintable(&d0); + mutt_mb_filter_unprintable(&d0); mutt_str_strfcpy(d, d0, len); rc = 0; error_out_0: @@ -831,7 +793,7 @@ void rfc2047_decode(char **pd) n = mutt_str_strlen(s); t = mutt_mem_malloc(n + 1); mutt_str_strfcpy(t, s, n + 1); - convert_nonmime_string(&t); + mutt_ch_convert_nonmime_string(&t); tlen = mutt_str_strlen(t); strncpy(d, t, tlen); d += tlen; diff --git a/rfc2047.h b/rfc2047.h index e029e5503..0ea6291d9 100644 --- a/rfc2047.h +++ b/rfc2047.h @@ -29,7 +29,6 @@ struct Address; char *mutt_choose_charset(const char *fromcode, const char *charsets, char *u, size_t ulen, char **d, size_t *dlen); -int convert_nonmime_string(char **ps); void rfc2047_encode_string(char **pd, int encode_specials, int col); void rfc2047_encode_addrlist(struct Address *addr, const char *tag); diff --git a/rfc2231.c b/rfc2231.c index c1ef506c7..19cc4f48d 100644 --- a/rfc2231.c +++ b/rfc2231.c @@ -38,8 +38,6 @@ #include "mutt/mutt.h" #include "rfc2231.h" #include "globals.h" -#include "mbyte.h" -#include "mime.h" #include "options.h" #include "parameter.h" #include "rfc2047.h" @@ -248,7 +246,7 @@ void rfc2231_decode_parameters(struct Parameter **headp) if (Rfc2047Parameters && p->value && strstr(p->value, "=?")) rfc2047_decode(&p->value); else if (AssumedCharset && *AssumedCharset) - convert_nonmime_string(&p->value); + mutt_ch_convert_nonmime_string(&p->value); *last = p; last = &p->next; @@ -261,7 +259,7 @@ void rfc2231_decode_parameters(struct Parameter **headp) s = rfc2231_get_charset(p->value, charset, sizeof(charset)); rfc2231_decode_one(p->value, s); mutt_ch_convert_string(&p->value, charset, Charset, MUTT_ICONV_HOOK_FROM); - mutt_filter_unprintable(&p->value); + mutt_mb_filter_unprintable(&p->value); *last = p; last = &p->next; diff --git a/send.c b/send.c index 95033c972..0e64a4773 100644 --- a/send.c +++ b/send.c @@ -43,7 +43,6 @@ #include "globals.h" #include "header.h" #include "mailbox.h" -#include "mime.h" #include "mutt_curses.h" #include "ncrypt/ncrypt.h" #include "options.h" diff --git a/sendlib.c b/sendlib.c index 139d77f4e..20c67f6d5 100644 --- a/sendlib.c +++ b/sendlib.c @@ -49,7 +49,6 @@ #include "globals.h" #include "header.h" #include "mailbox.h" -#include "mime.h" #include "mutt_curses.h" #include "mx.h" #include "ncrypt/ncrypt.h" @@ -78,8 +77,6 @@ #include #endif -const char MimeSpecials[] = "@.,;:<>[]\\\"()?/= \t"; - static void encode_quoted(struct FgetConv *fc, FILE *fout, int istext) { int c, linelen = 0; diff --git a/system.c b/system.c index b0c2a9862..da87a7d6b 100644 --- a/system.c +++ b/system.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "mutt/mutt.h" #include "mutt.h" #include "protos.h" diff --git a/url.c b/url.c index d97daa7a3..ba0b0d0fa 100644 --- a/url.c +++ b/url.c @@ -34,7 +34,6 @@ #include "address.h" #include "envelope.h" #include "globals.h" -#include "mime.h" #include "protos.h" #include "rfc2047.h"