X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib-mime%2Frfc2047.c;h=5b88b4beee367013bfc5271461e7ffc9b71c306d;hp=06db45625f55f9756dc7e88c59eb6ad41772ae8f;hb=c5ca8b7eaa727392811813926cda758bceef80f1;hpb=a743b55a20cbf3a33699fdb24dcb8638e878cc46;ds=sidebyside diff --git a/lib-mime/rfc2047.c b/lib-mime/rfc2047.c index 06db456..5b88b4b 100644 --- a/lib-mime/rfc2047.c +++ b/lib-mime/rfc2047.c @@ -59,9 +59,6 @@ #define CONTINUATION_BYTE(c) (((c) & 0xc0) == 0x80) -typedef size_t (*encoder_t) (char *, const char *, size_t, - const char *); - /* converts f of len flen and charset from into *t of len *tlen and charset to @@ -115,9 +112,9 @@ char *mutt_choose_charset(const char *fromcode, const char *charsets, while (*p) { char cset[SHORT_STRING]; - ssize_t slen, n; const char *q; char *s; + ssize_t slen, n; q = strchr(p, ':'); if (q) { @@ -128,11 +125,11 @@ char *mutt_choose_charset(const char *fromcode, const char *charsets, p += n; } - if (!n || + if (!n || n > (ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 2 - 12)) { /* Assume that we never need more than 12 characters of encoded-text to encode a single character. */ - n > (ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 2 - 12)) continue; + } n = convert_string(fromcode, u, ulen, cset, &s, &slen); if (n < 0) @@ -169,32 +166,51 @@ char *mutt_choose_charset(const char *fromcode, const char *charsets, return tocode; } -static size_t b_encoder (char *s, const char *d, size_t dlen, - const char *tocode) + +/****************************************************************************/ +/* Encoding functions */ +/****************************************************************************/ + +static const char __qp_special[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, + 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +typedef size_t (encoder_t)(char *, const char *, ssize_t, const char *); + +static size_t +b_encoder(char *s, const char *d, ssize_t dlen, const char *tocode) { char *s0 = s; - memcpy (s, "=?", 2), s += 2; - memcpy (s, tocode, m_strlen(tocode)), s += m_strlen(tocode); - memcpy (s, "?B?", 3), s += 3; + s += sprintf(s, "=?%s?B?", tocode); + for (;;) { - if (!dlen) - break; - else if (dlen == 1) { + switch (dlen) { + case 0: + goto done; + + case 1: *s++ = __m_b64chars[(*d >> 2) & 0x3f]; *s++ = __m_b64chars[(*d & 0x03) << 4]; *s++ = '='; *s++ = '='; - break; - } - else if (dlen == 2) { + goto done; + + case 2: *s++ = __m_b64chars[(*d >> 2) & 0x3f]; *s++ = __m_b64chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)]; *s++ = __m_b64chars[(d[1] & 0x0f) << 2]; *s++ = '='; - break; - } - else { + goto done; + + default: *s++ = __m_b64chars[(*d >> 2) & 0x3f]; *s++ = __m_b64chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)]; *s++ = __m_b64chars[((d[1] & 0x0f) << 2) | ((d[2] >> 6) & 0x03)]; @@ -202,32 +218,36 @@ static size_t b_encoder (char *s, const char *d, size_t dlen, d += 3, dlen -= 3; } } - memcpy (s, "?=", 2), s += 2; + + done: + *s++ = '?'; + *s++ = '='; return s - s0; } -static size_t q_encoder (char *s, const char *d, size_t dlen, - const char *tocode) +static size_t +q_encoder(char *s, const char *d, ssize_t dlen, const char *tocode) { char *s0 = s; - memcpy (s, "=?", 2), s += 2; - memcpy (s, tocode, m_strlen(tocode)), s += m_strlen(tocode); - memcpy (s, "?Q?", 3), s += 3; + s += sprintf(s, "=?%s?Q?", tocode); while (dlen--) { unsigned char c = *d++; - if (c == ' ') + if (c == ' ') { *s++ = '_'; - else if (c >= 0x7f || c < 0x20 || c == '_' || strchr (MimeSpecials, c)) { + } else + if (c & 0x80 || __qp_special[c]) { *s++ = '='; *s++ = __m_b36chars_upper[c >> 4]; *s++ = __m_b36chars_upper[c & 0xf]; - } - else + } else { *s++ = c; + } } - memcpy (s, "?=", 2), s += 2; + + *s++ = '?'; + *s++ = '='; return s - s0; } @@ -242,66 +262,66 @@ static size_t q_encoder (char *s, const char *d, size_t dlen, */ static size_t try_block (const char *d, ssize_t dlen, const char *fromcode, const char *tocode, - encoder_t * encoder, ssize_t *wlen) + encoder_t **encoder, ssize_t *wlen) { char buf1[ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 1]; - iconv_t cd; - const char *ib; - char *ob, *p; - ssize_t ibl, obl; - int count, len, len_b, len_q; + ssize_t obl = sizeof(buf1) - m_strlen(tocode); + char *ob; if (fromcode) { - cd = mutt_iconv_open (tocode, fromcode, 0); - assert (cd != (iconv_t) (-1)); - ib = d, ibl = dlen, ob = buf1, obl = sizeof (buf1) - m_strlen(tocode); + const char *ib = d; + ssize_t ibl = dlen; + iconv_t cd = mutt_iconv_open(tocode, fromcode, 0); + + assert (cd != (iconv_t)(-1)); + + ob = buf1; + if (my_iconv(cd, &ib, &ibl, &ob, &obl) < 0 || my_iconv(cd, 0, 0, &ob, &obl) < 0) { - assert (errno == E2BIG); - iconv_close (cd); - assert (ib > d); + assert (errno == E2BIG && ib > d); + iconv_close(cd); return (ib - d == dlen) ? dlen : ib - d + 1; } iconv_close (cd); - } - else { - if (dlen > ssizeof(buf1) - m_strlen(tocode)) - return ssizeof(buf1) - m_strlen(tocode) + 1; - memcpy (buf1, d, dlen); + } else { + if (dlen > obl) + return obl + 1; + memcpy(buf1, d, dlen); ob = buf1 + dlen; } - count = 0; - for (p = buf1; p < ob; p++) { - unsigned char c = *p; + { + const char *p; + int count, len, len_b, len_q; - assert (strchr (MimeSpecials, '?')); - if (c >= 0x7f || c < 0x20 || *p == '_' || - (c != ' ' && strchr (MimeSpecials, *p))) - ++count; - } - - len = ENCWORD_LEN_MIN - 2 + m_strlen(tocode); - len_b = len + (((ob - buf1) + 2) / 3) * 4; - 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")) - len_q = ENCWORD_LEN_MAX + 1; + count = 0; + for (p = buf1; p < ob; p++) { + count += (*p & 0x80 || __qp_special[(int)*p]); + } - if (len_b < len_q && len_b <= ENCWORD_LEN_MAX) { - *encoder = b_encoder; - *wlen = len_b; - return 0; - } - else if (len_q <= ENCWORD_LEN_MAX) { - *encoder = q_encoder; - *wlen = len_q; - return 0; + len = ENCWORD_LEN_MIN - 2 + m_strlen(tocode); + len_b = len + (((ob - buf1) + 2) / 3) * 4; + 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")) + len_q = ENCWORD_LEN_MAX + 1; + + if (len_b < len_q && len_b <= ENCWORD_LEN_MAX) { + *encoder = b_encoder; + *wlen = len_b; + return 0; + } else + if (len_q <= ENCWORD_LEN_MAX) { + *encoder = q_encoder; + *wlen = len_q; + return 0; + } else { + return dlen; + } } - else - return dlen; } /* @@ -310,7 +330,7 @@ static size_t try_block (const char *d, ssize_t dlen, */ static size_t encode_block (char *s, char *d, ssize_t dlen, const char *fromcode, const char *tocode, - encoder_t encoder) + encoder_t *encoder) { char buf1[ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 1]; ssize_t ibl, obl, n1, n2; @@ -327,9 +347,9 @@ static size_t encode_block (char *s, char *d, ssize_t dlen, assert (n1 >= 0 && n2 >= 0); iconv_close (cd); return (*encoder) (s, buf1, ob - buf1, tocode); - } - else + } else { return (*encoder) (s, d, dlen, tocode); + } } /* @@ -340,7 +360,7 @@ static size_t encode_block (char *s, char *d, ssize_t dlen, */ static size_t choose_block(char *d, size_t dlen, int col, const char *fromcode, const char *tocode, - encoder_t *encoder, ssize_t *wlen) + encoder_t **encoder, ssize_t *wlen) { size_t n, nn; int utf8 = fromcode && !ascii_strcasecmp (fromcode, "UTF-8"); @@ -380,7 +400,7 @@ static int rfc2047_encode (const char *d, ssize_t dlen, int col, char *u, *t0, *t1, *t; char *s0, *s1; ssize_t ulen, r, n, wlen; - encoder_t encoder; + encoder_t *encoder; char *tocode1 = 0; const char *tocode; const char *icode = "UTF-8";