X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib-mime%2Frfc2047.c;h=a4d3b194adfbea92374ccdef563dbd2944ada433;hp=c28b2b9bb5e6fe3d66950593622c0b5aa36f77b5;hb=f2ff91d8b7627e22af9715d384b6f9e9e802a39e;hpb=b2ae7c03f2b772f2663768931ef51ff7aa1caf33 diff --git a/lib-mime/rfc2047.c b/lib-mime/rfc2047.c index c28b2b9..a4d3b19 100644 --- a/lib-mime/rfc2047.c +++ b/lib-mime/rfc2047.c @@ -27,23 +27,13 @@ * please see the file GPL in the top level source directory. */ -#include -#include -#include +#include #include -#include "mutt.h" #include "charset.h" #include "thread.h" -#include -#include -#include -#include -#include -#include - /* If you are debugging this file, comment out the following line. */ /*#define NDEBUG*/ @@ -74,7 +64,7 @@ convert_string(const char *from, const char *f, ssize_t flen, cd = mutt_iconv_open(to, from, 0); - if (cd == (iconv_t)(-1)) + if (cd == MUTT_ICONV_ERROR) return -1; obl = 4 * flen + 1; @@ -158,7 +148,7 @@ char *mutt_choose_charset(const char *fromcode, const char *charsets, p_delete(&res); } - mutt_canonical_charset(buf, sizeof(buf), tocode); + charset_canonicalize(buf, sizeof(buf), tocode); m_strreplace(&tocode, buf); } @@ -272,7 +262,7 @@ static size_t try_block(const char *d, ssize_t dlen, ssize_t ibl = dlen; iconv_t cd = mutt_iconv_open(tocode, fromcode, 0); - assert (cd != (iconv_t)(-1)); + assert (cd != MUTT_ICONV_ERROR); ob = buf1; @@ -305,7 +295,7 @@ static size_t try_block(const char *d, ssize_t dlen, len_q = len + (ob - buf1) + 2 * count; /* Apparently RFC 1468 says to use B encoding for iso-2022-jp. */ - if (!ascii_strcasecmp(tocode, "ISO-2022-JP")) + if (mime_which_token(tocode, -1) == MIME_ISO_2022_JP) len_q = ENCWORD_LEN_MAX + 1; if (len_b < len_q && len_b <= ENCWORD_LEN_MAX) { @@ -339,7 +329,7 @@ encode_block(char *s, char *d, ssize_t dlen, if (fromcode) { cd = mutt_iconv_open(tocode, fromcode, 0); - assert (cd != (iconv_t) (-1)); + assert (cd != MUTT_ICONV_ERROR); ib = d, ibl = dlen, ob = buf1, obl = sizeof(buf1) - m_strlen(tocode); n1 = my_iconv(cd, &ib, &ibl, &ob, &obl); n2 = my_iconv(cd, 0, 0, &ob, &obl); @@ -362,7 +352,7 @@ static size_t choose_block(char *d, size_t dlen, int col, encoder_t **encoder, ssize_t *wlen) { size_t n, nn; - int utf8 = fromcode && !ascii_strcasecmp(fromcode, "UTF-8"); + int utf8 = mime_which_token(fromcode, -1) == MIME_UTF_8; n = dlen; for (;;) { @@ -453,7 +443,7 @@ static int rfc2047_encode(const char *d, ssize_t dlen, int col, } /* Hack to avoid labelling 8-bit data as us-ascii. */ - if (!icode && mutt_is_us_ascii(tocode)) + if (!icode && charset_is_us_ascii(tocode)) tocode = "unknown-8bit"; /* Adjust t0 for maximum length of line. */ @@ -565,7 +555,7 @@ static int rfc2047_encode(const char *d, ssize_t dlen, int col, } -void _rfc2047_encode_string(char **pd, int encode_specials, int col) +static void _rfc2047_encode_string(char **pd, int encode_specials, int col) { char *e; ssize_t elen; @@ -605,89 +595,80 @@ void rfc2047_encode_adrlist(address_t *addr, const char *tag) /* Decoding functions */ /****************************************************************************/ -/* decode one word into d[len] */ -static int rfc2047_decode_word(char *d, size_t len, const char *s) +/* decode one word into d[len] =?cst?[QB]?....?= */ +static int +rfc2047_decode_word(char *d, size_t len, const char *p, const char *end) { - const char *p, *eotoken; - char *charset = NULL; - int enc = 0, count = 0; - char *d0; + char charset[STRING] = ""; + const char *t; + char *q, *d0 = NULL; + int enc = 0; - /* =?[QB]?cset?.?= */ - for (p = s; (eotoken = strchr(p, '?')); p = eotoken + 1) { - switch (++count) { - const char *t; - char *q; + p += 2; /* =? */ - case 2: - /* ignore language specification a la RFC 2231 */ - t = memchr(p, '*', eotoken - p) ?: eotoken; - charset = p_dupstr(p, t - p); - break; + t = strchr(p, '?'); + if (!t) + return -1; + m_strncpy(charset, sizeof(charset), p, t - p); - case 3: - switch (*p) { - case 'q': case 'Q': - enc = ENCQUOTEDPRINTABLE; - break; + switch (t[1]) { + case 'q': case 'Q': + enc = ENCQUOTEDPRINTABLE; + break; - case 'b': case 'B': - enc = ENCBASE64; - break; + case 'b': case 'B': + enc = ENCBASE64; + break; - default: - p_delete(&charset); - return -1; + default: + return -1; + } + + if (t[2] != '?') + return -1; + + p = t + 3; /* skip ?[QB]? */ + d0 = q = p_new(char, end - p + 1); /* it's enough space to decode */ + + if (enc == ENCQUOTEDPRINTABLE) { + while (p < end - 2) { + if (*p == '=' && hexval(p[1]) >= 0 && hexval(p[2]) >= 0) { + *q++ = (hexval (p[1]) << 4) | hexval (p[2]); + p += 3; + } else + if (*p == '_') { + *q++ = ' '; + p++; + } else { + *q++ = *p++; } - break; + } + } else { /* enc == ENCBASE64 */ + int c, b = 0, k = 0; - case 4: - d0 = q = p_new(char, m_strlen(s) + 1); - - if (enc == ENCQUOTEDPRINTABLE) { - while (p < eotoken) { - if (*p == '=' && hexval(p[1]) >= 0 && hexval(p[2]) >= 0) { - *q++ = (hexval (p[1]) << 4) | hexval (p[2]); - p += 3; - } else - if (*p == '_') { - *q++ = ' '; - p++; - } else { - *q++ = *p++; - } - } - *q = 0; - } else { /* enc == ENCBASE64 */ - int c, b = 0, k = 0; - - while (p < eotoken) { - if (*p == '=') - break; - - c = base64val(*p++); - if (c < 0) - continue; - - if (k + 6 >= 8) { - k -= 2; - *q++ = b | (c >> k); - b = c << (8 - k); - } else { - b |= c << (k + 2); - k += 6; - } - } - *q = 0; + while (p < end - 2) { + if (*p == '=') + break; + + c = base64val(*p++); + if (c < 0) + continue; + + if (k + 6 >= 8) { + k -= 2; + *q++ = b | (c >> k); + b = c << (8 - k); + } else { + b |= c << (k + 2); + k += 6; } - break; } } + *q = '\0'; - if (charset) + if (*charset) mutt_convert_string(&d0, charset, Charset, M_ICONV_HOOK_FROM); m_strcpy(d, len, d0); - p_delete(&charset); p_delete(&d0); return 0; } @@ -712,7 +693,7 @@ static const char *find_encoded_word(const char *s, const char **x) continue; s += 3; - while (0x20 <= *s && *s < 0x7f && *s != '?') { + while (0x20 <= *s && *s < 0x7f && (*s != '?' || s[1] != '=')) { s++; } @@ -776,14 +757,12 @@ static ssize_t lwsrlen(const char *s, ssize_t n) /* try to decode anything that looks like a valid RFC2047 encoded * header field, ignoring RFC822 parsing rules */ -void rfc2047_decode (char **pd) +void rfc2047_decode(char **pd) { - const char *p, *q; - size_t m, n; - int found_encoded = 0; - char *d0, *d; const char *s = *pd; - size_t dlen; + char *d0, *d; + ssize_t dlen; + int found_encoded = 0; if (!s || !*s) return; @@ -792,80 +771,68 @@ void rfc2047_decode (char **pd) d = d0 = p_new(char, dlen + 1); while (*s && dlen > 0) { - if (!(p = find_encoded_word (s, &q))) { + const char *p, *q; + + p = find_encoded_word(s, &q); + + if (!p) { /* no encoded words */ - if (!option (OPTSTRICTMIME)) { - n = m_strlen(s); - if (found_encoded && (m = lwslen (s, n)) != 0) { - if (m != n) - *d = ' ', d++, dlen--; - n -= m, s += m; - } - if (ascii_strcasecmp (AssumedCharset, "us-ascii")) { - char *t; - ssize_t tlen; - - t = p_dupstr(s, n); - if (mutt_convert_nonmime_string (&t) == 0) { - tlen = m_strlen(t); - strncpy (d, t, tlen); - d += tlen; - } - else { - strncpy (d, s, n); - d += n; - } - p_delete(&t); - break; + ssize_t m, n; + + n = m_strlen(s); + if (found_encoded && (m = lwslen(s, n)) != 0) { + if (m != n) + *d++ = ' ', dlen--; + n -= m, s += m; + } + + if (mime_which_token(AssumedCharset, -1) == MIME_US_ASCII) { + char *t; + + t = p_dupstr(s, n); + if (mutt_convert_nonmime_string(&t) == 0) { + d += m_strcpy(d, dlen, t); + } else { + d += m_strcpy(d, dlen, s); } + p_delete(&t); + break; } - strncpy (d, s, dlen); - d += dlen; + + d += m_strcpy(d, dlen, s); break; } if (p != s) { + ssize_t m, n; + n = (p - s); /* ignore spaces between encoded words * and linear white spaces between encoded word and *text */ - if (!option (OPTSTRICTMIME)) { - if (found_encoded && (m = lwslen (s, n)) != 0) { - if (m != n) - *d = ' ', d++, dlen--; - n -= m, s += m; - } - - if ((m = n - lwsrlen (s, n)) != 0) { - if (m > dlen) - m = dlen; - memcpy (d, s, m); - d += m; - dlen -= m; - if (m != n) - *d = ' ', d++, dlen--; - } + if (found_encoded && (m = lwslen(s, n)) != 0) { + if (m != n) + *d++ = ' ', dlen--; + n -= m, s += m; } - else if (!found_encoded || strspn (s, " \t\r\n") != n) { - if (n > dlen) - n = dlen; - memcpy (d, s, n); - d += n; - dlen -= n; + + if ((m = n - lwsrlen(s, n)) != 0) { + m = m_strncpy(d, dlen, s, m); + d += m; + dlen -= m; + if (m != n) + *d++ = ' ', dlen--; } } - rfc2047_decode_word(d, dlen, p); + rfc2047_decode_word(d, dlen, p, q); found_encoded = 1; s = q; - n = m_strlen(d); - dlen -= n; - d += n; + while (*d && dlen) + d++, dlen--; } - *d = 0; p_delete(pd); *pd = d0; - str_adjust (pd); } void rfc2047_decode_adrlist(address_t *a)