From: Thomas Roessler Date: Mon, 28 Aug 2000 09:37:44 +0000 (+0000) Subject: Do character set selection for RFC2231 encodings. From EGE, but X-Git-Tag: mutt-1-3-8-rel~12 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d5a7673eb772377c22adfb9cfbc1efd9d6239182;p=mutt Do character set selection for RFC2231 encodings. From EGE, but with choose_charset renamed to mutt_choose_charset. --- diff --git a/rfc2047.c b/rfc2047.c index 2020416e..255a6e08 100644 --- a/rfc2047.c +++ b/rfc2047.c @@ -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; diff --git a/rfc2047.h b/rfc2047.h index ee0bc5ea..2f6bd887 100644 --- a/rfc2047.h +++ b/rfc2047.h @@ -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 *); diff --git a/rfc2231.c b/rfc2231.c index 31bfd406..ae8fc977 100644 --- a/rfc2231.c +++ b/rfc2231.c @@ -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; } - diff --git a/rfc2231.h b/rfc2231.h index 13ed07e4..0f24b06b 100644 --- a/rfc2231.h +++ b/rfc2231.h @@ -20,5 +20,5 @@ */ void rfc2231_decode_parameters (PARAMETER **); -int rfc2231_encode (char *, size_t, unsigned char *); +int rfc2231_encode_string (char **); diff --git a/sendlib.c b/sendlib.c index a0bf4706..6f991ff4 100644 --- a/sendlib.c +++ b/sendlib.c @@ -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);