#include "charset.h"
#include "thread.h"
+#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#ifdef NDEBUG
#define assert(x)
#else
-#include <assert.h>
#endif
#define ENCWORD_LEN_MAX 75
#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
returns number of converted chars from f, see iconv(3)
*/
static ssize_t
-convert_string(const char *from, const char *f, size_t flen,
- const char *to, char **t, size_t *tlen)
+convert_string(const char *from, const char *f, ssize_t flen,
+ const char *to, char **t, ssize_t *tlen)
{
iconv_t cd;
char *buf, *ob;
- size_t obl;
- ssize_t n;
- int e;
+ ssize_t obl, n;
cd = mutt_iconv_open(to, from, 0);
n = my_iconv(cd, &f, &flen, &ob, &obl);
if (n < 0 || my_iconv(cd, 0, 0, &ob, &obl) < 0) {
- e = errno;
- p_delete(&buf);
- iconv_close (cd);
+ int e = errno;
+ iconv_close(cd);
errno = e;
+ p_delete(&buf);
return -1;
}
+ iconv_close(cd);
*ob = '\0';
*tlen = ob - buf;
-
- p_realloc(&buf, ob - buf + 1);
- *t = buf;
- iconv_close (cd);
+ *t = buf;
return n;
}
+/* choose the shortest encoding for u */
char *mutt_choose_charset(const char *fromcode, const char *charsets,
- char *u, size_t ulen, char **d, size_t *dlen)
+ char *u, ssize_t ulen, char **dst, ssize_t *dlen)
{
- char canonical_buff[LONG_STRING];
- char *e = 0, *tocode = 0;
- size_t elen = 0, bestn = 0;
- const char *p, *q;
+ char *res = NULL;
+ ssize_t reslen = 0;
+
+ char *tocode = NULL;
+ ssize_t bestn = 0;
- for (p = charsets; p; p = q ? q + 1 : 0) {
- char *s, *t;
- size_t slen, n;
+ const char *p = charsets;
- q = strchr (p, ':');
+ while (*p) {
+ char cset[SHORT_STRING];
+ const char *q;
+ char *s;
+ ssize_t slen, n;
- n = q ? q - p : m_strlen(p);
+ q = strchr(p, ':');
+ if (q) {
+ n = m_strncpy(cset, sizeof(cset), p, q - p);
+ p = ++q;
+ } else {
+ n = m_strcpy(cset, sizeof(cset), p);
+ 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;
+ }
- t = p_dupstr(p, n);
-
- n = convert_string(fromcode, u, ulen, t, &s, &slen);
- if (n == (size_t) (-1))
+ n = convert_string(fromcode, u, ulen, cset, &s, &slen);
+ if (n < 0)
continue;
if (!tocode || n < bestn) {
+ m_strreplace(&tocode, cset);
bestn = n;
- p_delete(&tocode);
- tocode = t;
- if (d) {
- p_delete(&e);
- e = s;
- } else {
- p_delete(&s);
- }
- elen = slen;
+
+ p_delete(&res);
+ res = s;
+ reslen = slen;
if (!bestn)
break;
} else {
- p_delete(&t);
p_delete(&s);
}
}
if (tocode) {
- if (d)
- *d = e;
- if (dlen)
- *dlen = elen;
+ char buf[LONG_STRING];
- mutt_canonical_charset(canonical_buff, sizeof(canonical_buff), tocode);
- m_strreplace(&tocode, canonical_buff);
+ if (dst && dlen) {
+ *dst = res;
+ *dlen = reslen;
+ } else {
+ p_delete(&res);
+ }
+
+ mutt_canonical_charset(buf, sizeof(buf), tocode);
+ m_strreplace(&tocode, buf);
}
return tocode;
}
-static size_t b_encoder (char *s, const char *d, size_t dlen,
- const char *tocode)
+
+/****************************************************************************/
+/* Encoding functions */
+/****************************************************************************/
+
+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)];
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 || c < 0x20 || c == '_' || strchr (MimeSpecials, 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;
}
* tocode, unless fromcode is 0, in which case the data is assumed to
* be already in tocode, which should be 8-bit and stateless.
*/
-static size_t try_block (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, size_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;
- size_t ibl, obl;
+ ssize_t ibl, obl;
int count, len, len_b, len_q;
if (fromcode) {
iconv_close (cd);
}
else {
- if (dlen > sizeof (buf1) - m_strlen(tocode))
- return sizeof (buf1) - m_strlen(tocode) + 1;
+ if (dlen > ssizeof(buf1) - m_strlen(tocode))
+ return ssizeof(buf1) - m_strlen(tocode) + 1;
memcpy (buf1, d, dlen);
ob = buf1 + dlen;
}
* Encode the data (d, dlen) into s using the encoder.
* Return the length of the encoded word.
*/
-static size_t encode_block (char *s, char *d, size_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;
iconv_t cd;
const char *ib;
char *ob;
- size_t ibl, obl, n1, n2;
if (fromcode) {
cd = mutt_iconv_open (tocode, fromcode, 0);
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);
- assert (n1 != (size_t) (-1) && n2 != (size_t) (-1));
+ assert (n1 >= 0 && n2 >= 0);
iconv_close (cd);
return (*encoder) (s, buf1, ob - buf1, tocode);
- }
- else
+ } else {
return (*encoder) (s, d, dlen, tocode);
+ }
}
/*
* and set the length *wlen of the encoded word and *encoder.
* We start in column col, which limits the length of the word.
*/
-static size_t choose_block (char *d, size_t dlen, int col,
- const char *fromcode, const char *tocode,
- encoder_t * encoder, size_t * wlen)
+static size_t choose_block(char *d, size_t dlen, int col,
+ const char *fromcode, const char *tocode,
+ encoder_t **encoder, ssize_t *wlen)
{
size_t n, nn;
int utf8 = fromcode && !ascii_strcasecmp (fromcode, "UTF-8");
* The input data is assumed to be a single line starting at column col;
* if col is non-zero, the preceding character was a space.
*/
-static int rfc2047_encode (const char *d, size_t dlen, int col,
+static int rfc2047_encode (const char *d, ssize_t dlen, int col,
const char *fromcode, const char *charsets,
- char **e, size_t * elen, char *specials)
+ char **e, ssize_t *elen, const char *specials)
{
int ret = 0;
char *buf;
- size_t bufpos, buflen;
+ ssize_t bufpos, buflen;
char *u, *t0, *t1, *t;
char *s0, *s1;
- size_t ulen, r, n, wlen;
- encoder_t encoder;
+ ssize_t ulen, r, n, wlen;
+ encoder_t *encoder;
char *tocode1 = 0;
const char *tocode;
const char *icode = "UTF-8";
/* Choose target charset. */
tocode = fromcode;
if (icode) {
- if ((tocode1 = mutt_choose_charset (icode, charsets, u, ulen, 0, 0)))
+ if ((tocode1 = mutt_choose_charset(icode, charsets, u, ulen,
+ NULL, NULL)))
tocode = tocode1;
else
ret = 2, icode = 0;
void _rfc2047_encode_string (char **pd, int encode_specials, int col)
{
char *e;
- size_t elen;
+ ssize_t elen;
const char *charsets;
if (!Charset || !*pd)
}
if (ascii_strcasecmp (AssumedCharset, "us-ascii")) {
char *t;
- size_t tlen;
+ ssize_t tlen;
t = p_dupstr(s, n);
if (mutt_convert_nonmime_string (&t) == 0) {
}
if (p != s) {
- n = (size_t) (p - s);
+ n = (p - s);
/* ignore spaces between encoded words
* and linear white spaces between encoded word and *text */
if (!option (OPTSTRICTMIME)) {
str_adjust (pd);
}
-void rfc2047_decode_adrlist (address_t * a)
+void rfc2047_decode_adrlist(address_t *a)
{
while (a) {
if (a->personal)
- rfc2047_decode (&a->personal);
+ rfc2047_decode(&a->personal);
a = a->next;
}
}
-void rfc2047_decode_envelope (ENVELOPE* e) {
-
- if (!e)
- return;
+void rfc2047_decode_envelope(ENVELOPE* e)
+{
+ assert (e);
/* do RFC2047 decoding */
- rfc2047_decode_adrlist (e->from);
- rfc2047_decode_adrlist (e->to);
- rfc2047_decode_adrlist (e->cc);
- rfc2047_decode_adrlist (e->bcc);
- rfc2047_decode_adrlist (e->reply_to);
- rfc2047_decode_adrlist (e->mail_followup_to);
- rfc2047_decode_adrlist (e->return_path);
- rfc2047_decode_adrlist (e->sender);
+ rfc2047_decode_adrlist(e->from);
+ rfc2047_decode_adrlist(e->to);
+ rfc2047_decode_adrlist(e->cc);
+ rfc2047_decode_adrlist(e->bcc);
+ rfc2047_decode_adrlist(e->reply_to);
+ rfc2047_decode_adrlist(e->mail_followup_to);
+ rfc2047_decode_adrlist(e->return_path);
+ rfc2047_decode_adrlist(e->sender);
if (e->subject) {
- rfc2047_decode (&e->subject);
- mutt_adjust_subject (e);
+ rfc2047_decode(&e->subject);
+ mutt_adjust_subject(e);
}
}