Commit d5a7673e authored by Thomas Roessler's avatar Thomas Roessler

Do character set selection for RFC2231 encodings. From EGE, but

with choose_charset renamed to mutt_choose_charset.
parent a5948f71
......@@ -58,7 +58,7 @@ static size_t convert_string (const char *f, size_t flen,
cd = mutt_iconv_open (to, from);
if (cd == (iconv_t)(-1))
return (size_t)(-1);
obl = 4 * flen;
obl = 4 * flen + 1;
ob = buf = safe_malloc (obl);
n = iconv (cd, &f, &flen, &ob, &obl);
if (n == (size_t)(-1) || iconv (cd, 0, 0, &ob, &obl) == (size_t)(-1))
......@@ -69,18 +69,19 @@ static size_t convert_string (const char *f, size_t flen,
errno = e;
return (size_t)(-1);
}
x = realloc (buf, ob - buf);
*ob = '\0';
x = realloc (buf, ob - buf + 1);
*t = x ? x : buf;
*tlen = ob - buf;
iconv_close (cd);
return n;
}
static char *choose_charset (const char *fromcode, const char *charsets,
char *u, size_t ulen)
char *mutt_choose_charset (const char *fromcode, const char *charsets,
char *u, size_t ulen, char **d, size_t *dlen)
{
char *tocode = 0;
size_t bestn = 0;
char *e = 0, *tocode = 0;
size_t elen = 0, bestn = 0;
const char *p, *q;
for (p = charsets; p; p = q ? q + 1 : 0)
......@@ -103,15 +104,30 @@ static char *choose_charset (const char *fromcode, const char *charsets,
n = convert_string (u, ulen, fromcode, t, &s, &slen);
if (n == (size_t)(-1))
continue;
free (s);
if (!tocode || n < bestn)
{
free (tocode), tocode = t, bestn = n;
bestn = n;
free (tocode), tocode = t;
if (d)
free (e), e = s;
else
free (s);
elen = slen;
if (!bestn)
break;
}
else
{
free (t);
free (s);
}
}
if (tocode)
{
if (d)
*d = e;
if (dlen)
*dlen = elen;
}
return tocode;
}
......@@ -371,7 +387,7 @@ static int rfc2047_encode (const char *d, size_t dlen, int col,
tocode = fromcode;
if (icode)
{
if ((tocode1 = choose_charset (icode, charsets, u, ulen)))
if ((tocode1 = mutt_choose_charset (icode, charsets, u, ulen, 0, 0)))
tocode = tocode1;
else
ret = 2, icode = 0;
......
......@@ -16,6 +16,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
char *mutt_choose_charset (const char *fromcode, const char *charsets,
char *u, size_t ulen, char **d, size_t *dlen);
void rfc2047_encode_string (char **);
void rfc2047_encode_adrlist (ADDRESS *);
......
......@@ -302,46 +302,56 @@ static void rfc2231_join_continuations (PARAMETER **head,
}
}
int rfc2231_encode (char *dest, size_t l, unsigned char *src)
int rfc2231_encode_string (char **pd)
{
char *buff;
unsigned char *s;
char *t;
int encode = 0;
int ext = 0, encode = 0;
char *charset, *s, *t, *e, *d = 0;
size_t slen, dlen = 0;
size_t bufflen = 3 * strlen ((char *) src + 1);
buff = safe_malloc (bufflen);
if (!*pd)
return 0;
for (s = src; *s && !encode; s++)
if (!Charset || !SendCharset ||
!(charset = mutt_choose_charset (Charset, SendCharset,
*pd, strlen (*pd), &d, &dlen)))
{
if (*s & 0x80)
encode = 1;
charset = safe_strdup (Charset ? Charset : "unknown");
d = *pd, dlen = strlen (d);
}
if (!encode)
strfcpy (dest, (char *) src, l);
else
if (strcasecmp (charset, "us-ascii"))
encode = 1;
for (s = d, slen = dlen; slen; s++, slen--)
if (*s < 0x20 || *s >= 0x7f)
encode = 1, ++ext;
else if (strchr (MimeSpecials, *s))
++ext;
if (encode)
{
for (s = src, t = buff; *s && (t - buff) < bufflen - 4; s++)
{
if ((*s & 0x80) || *s == '\'')
e = safe_malloc (dlen + 2*ext + strlen (charset) + 3);
sprintf (e, "%s''", charset);
t = e + strlen (e);
for (s = d, slen = dlen; slen; s++, slen--)
if (*s < 0x20 || *s >= 0x7f || strchr (MimeSpecials, *s))
{
sprintf ((char *) t, "%%%02x", (unsigned int) *s);
sprintf (t, "%%%02X", (unsigned char)*s);
t += 3;
}
else
*t++ = *s;
}
*t = '\0';
if (Charset && SendCharset && mutt_strcasecmp (Charset, SendCharset))
mutt_convert_string (&buff, Charset, SendCharset);
snprintf (dest, l, "%s''%s", SendCharset ? SendCharset :
(Charset ? Charset : "unknown-8bit"), buff);
if (d != *pd)
free (d);
free (*pd);
*pd = e;
}
else if (d != *pd)
{
free (*pd);
*pd = d;
}
safe_free ((void **) &buff);
return encode;
}
......@@ -20,5 +20,5 @@
*/
void rfc2231_decode_parameters (PARAMETER **);
int rfc2231_encode (char *, size_t, unsigned char *);
int rfc2231_encode_string (char **);
......@@ -121,7 +121,7 @@ sysexits_h[] =
#define DISPOSITION(X) X==DISPATTACH?"attachment":"inline"
const char MimeSpecials[] = "@.,;<>[]\\\"()?/= \t";
const char MimeSpecials[] = "@.,;:<>[]\\\"()?/= \t";
char B64Chars[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
......@@ -346,7 +346,6 @@ int mutt_write_mime_header (BODY *a, FILE *f)
{
PARAMETER *p;
char buffer[STRING];
char tmp[STRING];
char *t;
char *fn;
int len;
......@@ -361,6 +360,7 @@ int mutt_write_mime_header (BODY *a, FILE *f)
for(p = a->parameter; p; p = p->next)
{
char *tmp;
if(!p->value)
continue;
......@@ -368,7 +368,8 @@ int mutt_write_mime_header (BODY *a, FILE *f)
fputc (';', f);
buffer[0] = 0;
encode = rfc2231_encode (tmp, sizeof (tmp), (unsigned char *) p->value);
tmp = safe_strdup (p->value);
encode = rfc2231_encode_string (&tmp);
rfc822_cat (buffer, sizeof (buffer), tmp, MimeSpecials);
/* Dirty hack to make messages readable by Outlook Express
......@@ -378,7 +379,9 @@ int mutt_write_mime_header (BODY *a, FILE *f)
if (!strcasecmp (p->attribute, "boundary") && !strcmp (buffer, tmp))
snprintf (buffer, sizeof (buffer), "\"%s\"", tmp);
safe_free ((void **)&tmp);
tmplen = mutt_strlen (buffer) + mutt_strlen (p->attribute) + 1;
if (len + tmplen + 2 > 76)
......@@ -411,6 +414,8 @@ int mutt_write_mime_header (BODY *a, FILE *f)
if (fn)
{
char *tmp;
/* Strip off the leading path... */
if ((t = strrchr (fn, '/')))
t++;
......@@ -418,8 +423,10 @@ int mutt_write_mime_header (BODY *a, FILE *f)
t = fn;
buffer[0] = 0;
encode = rfc2231_encode (tmp, sizeof (tmp), (unsigned char *) t);
tmp = safe_strdup (t);
encode = rfc2231_encode_string (&tmp);
rfc822_cat (buffer, sizeof (buffer), tmp, MimeSpecials);
safe_free ((void **)&tmp);
fprintf (f, "; filename%s=%s", encode ? "*" : "", buffer);
}
}
......@@ -1629,7 +1636,7 @@ static void encode_headers (LIST *h)
{
*p++ = 0;
SKIPWS (p);
tmp = strdup (p);
tmp = safe_strdup (p);
rfc2047_encode_string (&tmp);
safe_realloc ((void **) &h->data,
strlen (h->data) + 2 + strlen (tmp) + 1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment