]> granicus.if.org Git - mutt/commitdiff
Do character set selection for RFC2231 encodings. From EGE, but
authorThomas Roessler <roessler@does-not-exist.org>
Mon, 28 Aug 2000 09:37:44 +0000 (09:37 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Mon, 28 Aug 2000 09:37:44 +0000 (09:37 +0000)
with choose_charset renamed to mutt_choose_charset.

rfc2047.c
rfc2047.h
rfc2231.c
rfc2231.h
sendlib.c

index 2020416e34fc69cd9e24ab6d9ce30522c4742ca8..255a6e08725f773280502f6be9f388c2d0b85eec 100644 (file)
--- 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;
index ee0bc5eab5871497a21751bfd78df3e2e97aa3dd..2f6bd8877f0d004628ea693bdacdc23701f37a8c 100644 (file)
--- 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 *);
 
index 31bfd4061977b8736e1faaf89378baf7d802c223..ae8fc977f2f815a8ed8b041df9061b48fc45224b 100644 (file)
--- 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;
 }
-
index 13ed07e4a074f90dcff632371fb9364781c1ab34..0f24b06b559e9e9e257f5899429e1b45a3dcf9b0 100644 (file)
--- 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 **);
 
index a0bf470694fddd368b8e5b37eee295a174e6a9d0..6f991ff49773972cae6ac752c5c26eb24ee3ec45 100644 (file)
--- 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);