* please see the file GPL in the top level source directory.
*/
-#include <lib-lib/mem.h>
-#include <lib-lib/str.h>
-#include <lib-lib/ascii.h>
+#include <lib-lib/lib-lib.h>
#include <lib-mime/mime.h>
-#include "mutt.h"
#include "charset.h"
#include "thread.h"
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
/* If you are debugging this file, comment out the following line. */
/*#define NDEBUG*/
cd = mutt_iconv_open(to, from, 0);
- if (cd == (iconv_t)(-1))
+ if (cd == MUTT_ICONV_ERROR)
return -1;
obl = 4 * flen + 1;
p_delete(&res);
}
- mutt_canonical_charset(buf, sizeof(buf), tocode);
+ charset_canonicalize(buf, sizeof(buf), tocode);
m_strreplace(&tocode, buf);
}
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;
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) {
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);
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 (;;) {
}
/* 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. */
}
-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;
/* 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;
}
continue;
s += 3;
- while (0x20 <= *s && *s < 0x7f && *s != '?') {
+ while (0x20 <= *s && *s < 0x7f && (*s != '?' || s[1] != '=')) {
s++;
}
/* 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 int strict_mime = option(OPTSTRICTMIME);
+
const char *s = *pd;
- size_t dlen;
+ char *d0, *d;
+ ssize_t dlen;
+ int found_encoded = 0;
if (!s || !*s)
return;
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)) {
+ if (!strict_mime) {
+ ssize_t m, n;
+
n = m_strlen(s);
- if (found_encoded && (m = lwslen (s, n)) != 0) {
+ if (found_encoded && (m = lwslen(s, n)) != 0) {
if (m != n)
- *d = ' ', d++, dlen--;
+ *d++ = ' ', dlen--;
n -= m, s += m;
}
- if (ascii_strcasecmp (AssumedCharset, "us-ascii")) {
+
+ if (mime_which_token(AssumedCharset, -1) == MIME_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;
+ 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 (!strict_mime) {
+ if (found_encoded && (m = lwslen(s, n)) != 0) {
if (m != n)
- *d = ' ', d++, dlen--;
+ *d++ = ' ', dlen--;
n -= m, s += m;
}
- if ((m = n - lwsrlen (s, n)) != 0) {
- if (m > dlen)
- m = dlen;
- memcpy (d, s, m);
+ if ((m = n - lwsrlen(s, n)) != 0) {
+ m = m_strncpy(d, dlen, s, m);
d += m;
dlen -= m;
if (m != n)
- *d = ' ', d++, dlen--;
+ *d++ = ' ', dlen--;
}
- }
- else if (!found_encoded || strspn (s, " \t\r\n") != n) {
- if (n > dlen)
- n = dlen;
- memcpy (d, s, n);
+ } else
+ if (!found_encoded || (ssize_t)strspn(s, " \t\r\n") != n) {
+ n = m_strncpy(d, dlen, s, n);
d += n;
dlen -= n;
}
}
- 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)