<<< Date Index >>>     <<< Thread Index >>>

Re: Bug#222191: patch-1.4.1.tt.compat.1 for mutt fixes this bug



On Fri, Dec 19, 2003 at 03:30:36PM +0100, Alain Bench wrote:
> Hi Carlos,
> 
>  On Tuesday, December 16, 2003 at 9:00:09 PM -0200, Carlos Laviola wrote:
> 
> > This [patch-1.4.1.tt.compat.1-ter] implements some cool features from
> > the mutt-ja project
> 
>     Nice work, thanks for the adaptation to 1.5.5.1/CVS. Can I make 4
> quick little unsure and untested comments?
> 
>  1) You removed all 1.4.1 pgp.c changes. You may want to look at
> patch-1.5.5.1.tt.ja.1.beta to find adapted changes.
> 
>  2) You retained state_puts_conv() function and prototype in muttlib.c
> and mutt.h: It was used only in 1.4.1 pgp.c changes.
> 
>  3) You can drop the "-ter" suffix in name and full PATCHES tag. It was
> not an author name, but the third of a set of patches ("", bis, ter...)
> to patch-1.4.tt.ja.1. And update Mutt version number. And add your
> initials as adapter. Suggested tag: patch-1.5.5.1.tt.compat.1-cl
> 
>  4) s/safe_free/FREE/

Thanks for the suggestions, I have fixed everything you've mentioned and
the patch looks much cleaner now indeed.  I'm thinking this patch name
is a bit strange, so if the Debian mutt maintainers feel like changing
it, I have no problems.  Here it is, attached again.

>     Unfortunately list is not usable for western. I mean a usefull
> setting could have been $assumed_charset="utf-8:windows-1252", and this
> even _works_ for raw headers. But for non-MIME bodies only the first of
> list is used. And if non-MIME UTF-8 do happen sometimes, it's much less
> frequently than non-MIME CP-1252 (and exact subsets).
> 
>     Lists do work for the other feature, though:
> $file_charset="ucs-2:utf-8:windows-1252" works as expected.

Aha.

-- 
Carlos Laviola <claviola@xxxxxxxxx>
AlterNex S/A - (21) 2530-7007
diff -urN mutt/charset.c mutt.new/charset.c
--- mutt/charset.c      2002-12-11 09:19:39.000000000 -0200
+++ mutt.new/charset.c  2003-12-20 20:22:50.000000000 -0200
@@ -581,3 +581,87 @@
     iconv_close (fc->cd);
   FREE (_fc);
 }
+
+char *mutt_get_first_charset (const char *charset)
+{
+  static char fcharset[SHORT_STRING];
+  const char *c, *c1;
+  size_t n;
+
+  c = charset;
+  if (!mutt_strlen(c))
+    return "us-ascii";   
+  if (!(c1 = strchr (c, ':')))
+    return charset;
+  strfcpy (fcharset, c, c1 - c + 1);
+  return fcharset;
+}
+
+static size_t convert_string (ICONV_CONST char *f, size_t flen,
+                             const char *from, const char *to,
+                             char **t, size_t *tlen)
+{
+  iconv_t cd;
+  char *buf, *ob;
+  size_t obl, n;
+  int e;
+
+  cd = mutt_iconv_open (to, from, 0);
+  if (cd == (iconv_t)(-1))
+    return (size_t)(-1);
+  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))
+  {
+    e = errno;
+    FREE (&buf);
+    iconv_close (cd);
+    errno = e;
+    return (size_t)(-1);
+  }
+  *ob = '\0';
+
+  *tlen = ob - buf;
+
+  safe_realloc ((void **) &buf, ob - buf + 1);
+  *t = buf;
+  iconv_close (cd);
+
+  return n;
+}
+
+int mutt_convert_nomime_string (char **ps)
+{
+  const char *c, *c1;
+
+  for (c = AssumedCharset; c; c = c1 ? c1 + 1 : 0)
+  {
+    char *u = *ps;
+    char *s;
+    char *fromcode;
+    size_t m, n;
+    size_t ulen = mutt_strlen (*ps);
+    size_t slen;
+
+    if (!u || !*u)
+      return 0;
+
+    c1 = strchr (c, ':');
+    n = c1 ? c1 - c : mutt_strlen (c);
+    if (!n)
+      continue;
+    fromcode = safe_malloc (n + 1);
+    strfcpy (fromcode, c, n + 1);
+    m = convert_string (u, ulen, fromcode, Charset, &s, &slen);
+    FREE (&fromcode);
+    if (m != (size_t)(-1))
+    {
+      FREE (ps);
+      *ps = s;
+      return 0;
+    }
+  }
+  return -1;
+}
+
diff -urN mutt/charset.h mutt.new/charset.h
--- mutt/charset.h      2003-03-03 11:01:06.000000000 -0300
+++ mutt.new/charset.h  2003-12-20 20:20:55.000000000 -0200
@@ -35,6 +35,8 @@
 #endif
 
 int mutt_convert_string (char **, const char *, const char *, int);
+char *mutt_get_first_charset (const char *);
+int mutt_convert_nomime_string (char **);
 
 iconv_t mutt_iconv_open (const char *, const char *, int);
 size_t mutt_iconv (iconv_t, ICONV_CONST char **, size_t *, char **, size_t *, 
ICONV_CONST char **, const char *);
diff -urN mutt/curs_lib.c mutt.new/curs_lib.c
--- mutt/curs_lib.c     2003-10-24 10:52:28.000000000 -0200
+++ mutt.new/curs_lib.c 2003-12-20 20:20:55.000000000 -0200
@@ -139,6 +139,19 @@
     CLEARLINE (LINES-1);
 }
 
+static void fix_end_of_file (const char *data)
+{
+  FILE *fp;
+  int c;
+
+  if ((fp = safe_fopen (data, "a+")) == NULL)
+    return;
+  fseek (fp,-1,SEEK_END);
+  if ((c = fgetc(fp)) != '\n')
+    fputc ('\n', fp);
+  safe_fclose (&fp);
+}
+
 void mutt_edit_file (const char *editor, const char *data)
 {
   char cmd[LONG_STRING];
@@ -147,6 +160,7 @@
   mutt_expand_file_fmt (cmd, sizeof (cmd), editor, data);
   if (mutt_system (cmd) == -1)
     mutt_error (_("Error running \"%s\"!"), cmd);
+  fix_end_of_file (data);
   keypad (stdscr, TRUE);
   clearok (stdscr, TRUE);
 }
@@ -575,7 +589,7 @@
       wc = replacement_char ();
     }
     if (arboreal && wc < M_TREE_MAX)
-      w = 1; /* hack */
+      w = mutt_mbswidth ((char *)s,1); /* hack */
     else
     {
       if (!IsWPrint (wc))
diff -urN mutt/globals.h mutt.new/globals.h
--- mutt/globals.h      2003-07-15 08:41:32.000000000 -0300
+++ mutt.new/globals.h  2003-12-20 20:20:55.000000000 -0200
@@ -32,6 +32,7 @@
 
 WHERE char *AliasFile;
 WHERE char *AliasFmt;
+WHERE char *AssumedCharset;
 WHERE char *AttachSep;
 WHERE char *Attribution;
 WHERE char *AttachFormat;
@@ -45,6 +46,7 @@
 WHERE char *DsnReturn;
 WHERE char *Editor;
 WHERE char *EscChar;
+WHERE char *FileCharset;
 WHERE char *FolderFormat;
 WHERE char *ForwFmt;
 WHERE char *Fqdn;
diff -urN mutt/handler.c mutt.new/handler.c
--- mutt/handler.c      2003-10-24 10:52:28.000000000 -0200
+++ mutt.new/handler.c  2003-12-20 20:20:55.000000000 -0200
@@ -1718,12 +1718,22 @@
   int istext = mutt_is_text_part (b);
   iconv_t cd = (iconv_t)(-1);
 
-  if (istext && s->flags & M_CHARCONV)
+  if (istext)
+  {
+    if(s->flags & M_CHARCONV)
   {
     char *charset = mutt_get_parameter ("charset", b->parameter);
+      if (!option (OPTSTRICTMIME) && !charset)
+        charset = mutt_get_first_charset (AssumedCharset);
     if (charset && Charset)
       cd = mutt_iconv_open (Charset, charset, M_ICONV_HOOK_FROM);
   }
+    else
+    {
+      if (b->file_charset)
+        cd = mutt_iconv_open (Charset, b->file_charset, M_ICONV_HOOK_FROM);
+    }
+  }
 
   fseek (s->fpin, b->offset, 0);
   switch (b->encoding)
diff -urN mutt/init.h mutt.new/init.h
--- mutt/init.h 2003-09-13 10:46:55.000000000 -0300
+++ mutt.new/init.h     2003-12-20 20:20:55.000000000 -0200
@@ -191,6 +191,24 @@
   ** If set, Mutt will prompt you for carbon-copy (Cc) recipients before
   ** editing the body of an outgoing message.
   */  
+  { "assumed_charset", DT_STR, R_NONE, UL &AssumedCharset, UL "us-ascii"},
+  /*
+  ** .pp
+  ** [mutt-ja]
+  ** This variable is a colon-separated list of character encoding
+  ** schemes for messages without character encoding indication.
+  ** Header field values and message body content without character encoding
+  ** indication would be assumed that they are written in one of this list.
+  ** By default, all the header fields and message body without any charset
+  ** indication are assumed to be in "us-ascii".
+  ** .pp
+  ** For example, Japanese users might prefer this:
+  ** .pp
+  **   set assumed_charset="iso-2022-jp:euc-jp:shift_jis:utf-8"
+  ** .pp
+  ** However, only the first content is valid for the message body.
+  ** This variable is valid only if $$strict_mime is unset.
+  */
   { "attach_format",   DT_STR,  R_NONE, UL &AttachFormat, UL "%u%D%I %t%4n 
%T%.40d%> [%.7m/%.10M, %.6e%?C?, %C?, %s] " },
   /*
   ** .pp
@@ -376,6 +394,19 @@
   ** ``$$crypt_replyencrypt'',
   ** ``$$crypt_autosign'', ``$$crypt_replysign'' and ``$$smime_is_default''.
   */
+  { "create_rfc2047_parameters",       DT_BOOL, R_NONE, 
OPTCREATERFC2047PARAMS, 0 },
+  /*
+  ** .pp
+  ** [mutt-ja]
+  ** When this variable is set, Mutt will add the following RFC-2047-encoded
+  ** MIME parameter to Content-Type header field as filename for attachment:
+  ** name="=?iso-2022-jp?B?GyRCO244MxsoQi50eHQ=?="
+  ** .pp
+  ** Note: this use of RFC 2047's encoding is explicitly prohibited
+  ** by the standard. You may set this variable only if a mailer
+  ** of recipients can not parse RFC 2231 parameters.
+  ** This variable is valid only if $$strict_mime is unset.
+  */
   { "date_format",     DT_STR,  R_BOTH, UL &DateFmt, UL "!%a, %b %d, %Y at 
%I:%M:%S%p %Z" },
   /*
   ** .pp
@@ -539,6 +570,21 @@
   ** signed.
   ** (PGP only)
   */
+  { "file_charset",    DT_STR,  R_NONE, UL &FileCharset, UL 0 },
+  /*
+  ** .pp
+  ** [mutt-ja]
+  ** This variable is a colon-separated list of character encoding
+  ** schemes for text file attatchments.
+  ** If unset, $$charset value will be used instead.
+  ** For example, the following configuration would work for Japanese
+  ** text handling:
+  ** .pp
+  **   set file_charset="iso-2022-jp:euc-jp:shift_jis:utf-8"
+  ** .pp
+  ** Note: "iso-2022-*" must be put at the head of the value as shown above
+  ** if included.
+  */
   { "folder",          DT_PATH, R_NONE, UL &Maildir, UL "~/Mail" },
   /*
   ** .pp
@@ -2482,6 +2528,20 @@
   ** Setting this variable causes the ``status bar'' to be displayed on
   ** the first line of the screen rather than near the bottom.
   */
+  { "strict_mime",     DT_BOOL, R_NONE, OPTSTRICTMIME, 0 },
+  /*
+  ** .pp
+  ** [mutt-ja]
+  ** When unset, non MIME-compliant messages that doesn't have any
+  ** charset indication in Content-Type: field can be displayed
+  ** (non MIME-compliant messages are often generated by old mailers
+  ** or buggy mailers like MS Outlook Express).
+  ** See also $$assumed_charset.
+  ** .pp
+  ** This option also replaces linear-white-space between encoded-word
+  ** and *text to a single space to prevent the display of MIME-encoded
+  ** Subject: field from being devided into multiple lines.
+  */
   { "strict_threads",  DT_BOOL, R_RESORT|R_RESORT_INIT|R_INDEX, 
OPTSTRICTTHREADS, 0 },
   /*
   ** .pp
diff -urN mutt/mutt.h mutt.new/mutt.h
--- mutt/mutt.h 2003-10-24 10:52:28.000000000 -0200
+++ mutt.new/mutt.h     2003-12-21 00:16:30.000000000 -0200
@@ -310,7 +310,6 @@
 #define M_SEL_MULTI    (1<<1)
 #define M_SEL_FOLDER   (1<<2)
 
-
 /* boolean vars */
 enum
 {
@@ -480,7 +479,12 @@
   OPTDONTHANDLEPGPKEYS,        /* (pseudo) used to extract PGP keys */
   OPTUNBUFFEREDINPUT,   /* (pseudo) don't use key buffer */
 
+  /* mutt-ja options */
+  OPTCREATERFC2047PARAMS,/* (pseudo) used to generate rfc2047 parameter */
+  OPTSTRICTMIME,       /* (pseudo) used to be strict in RFCs of MIME */
+
   OPTMAX
+
 };
 
 #define mutt_bit_alloc(n) calloc ((n + 7) / 8, sizeof (char))
@@ -589,6 +593,7 @@
                                 * If NULL, filename is used 
                                 * instead.
                                 */
+  char *file_charset;          /* charset of attached file */
   CONTENT *content;             /* structure used to store detailed info about
                                 * the content of the attachment.  this is used
                                 * to determine what content-transfer-encoding
diff -urN mutt/muttlib.c mutt.new/muttlib.c
--- mutt/muttlib.c      2003-10-24 10:52:28.000000000 -0200
+++ mutt.new/muttlib.c  2003-12-21 00:16:56.000000000 -0200
@@ -23,6 +23,7 @@
 #include "mailbox.h"
 #include "mx.h"
 #include "url.h"
+#include "mbyte.h"
 
 #include "reldate.h"
 
@@ -913,6 +914,42 @@
 }
 
 
+/* return width of multibyte character string */
+size_t mutt_mbswidth (char *s, size_t n)
+{
+  wchar_t wc;
+  size_t j,k,l,m;
+  mbstate_t mbstate;
+
+  l = 0;
+  if (!s)
+    return 0;
+  memset (&mbstate, 0, sizeof (mbstate));
+  while (*s && n)
+  {
+    j = (int)*s;
+    if (j < M_TREE_MAX)
+    {
+      if (Charset_is_utf8)
+        l += 1;        /* width of WACS character */
+      else
+        l++;
+      s++, n--;
+    }
+    else
+    {
+      k = mbrtowc (&wc, s, n, &mbstate);
+      if (k == (size_t)(-1) || k == (size_t)(-2))
+        break;
+      m = wcwidth (wc);
+      l += (m > 0) ? m : 0;
+      s += k, n -= k;
+    }
+  }
+  return l;
+}
+
+
 void mutt_FormatString (char *dest,            /* output buffer */
                        size_t destlen,         /* output buffer len */
                        const char *src,        /* template string */
@@ -1024,7 +1061,7 @@
            len = destlen - wlen;
          memcpy (wptr, buf, len);
          wptr += len;
-         wlen += len;
+         wlen += mutt_mbswidth (buf, len);
        }
        break; /* skip rest of input */
       }
@@ -1075,7 +1112,7 @@
 
        memcpy (wptr, buf, len);
        wptr += len;
-       wlen += len;
+       wlen += mutt_mbswidth (buf, len);
       }
     }
     else if (*src == '\\')
diff -urN mutt/pager.c mutt.new/pager.c
--- mutt/pager.c        2003-10-24 10:52:28.000000000 -0200
+++ mutt.new/pager.c    2003-12-20 20:20:55.000000000 -0200
@@ -1706,15 +1706,13 @@
       CLEARLINE (statusoffset);
       if (IsHeader (extra))
       {
-       _mutt_make_string (buffer,
-                          COLS-9 < sizeof (buffer) ? COLS-9 : sizeof (buffer),
-                          NONULL (PagerFmt), Context, extra->hdr, 
M_FORMAT_MAKEPRINT);
+       _mutt_make_string (buffer, sizeof (buffer), NONULL (PagerFmt),
+                          Context, extra->hdr, M_FORMAT_MAKEPRINT);
       }
       else if (IsMsgAttach (extra))
       {
-       _mutt_make_string (buffer,
-                          COLS - 9 < sizeof (buffer) ? COLS - 9: sizeof 
(buffer),
-                          NONULL (PagerFmt), Context, extra->bdy->hdr, 
M_FORMAT_MAKEPRINT);
+       _mutt_make_string (buffer, sizeof (buffer), NONULL (PagerFmt),
+                          Context, extra->bdy->hdr, M_FORMAT_MAKEPRINT);
       }
       mutt_paddstr (COLS-10, IsHeader (extra) || IsMsgAttach (extra) ?
                    buffer : banner);
diff -urN mutt/parse.c mutt.new/parse.c
--- mutt/parse.c        2003-10-24 10:52:28.000000000 -0200
+++ mutt.new/parse.c    2003-12-20 20:20:55.000000000 -0200
@@ -208,9 +208,22 @@
 
       if (*s == '"')
       {
+       int state_ascii = 1;
        s++;
-       for (i=0; *s && *s != '"' && i < sizeof (buffer) - 1; i++, s++)
+       for (i=0; *s && i < sizeof (buffer) - 1; i++, s++)
        {
+         /* escape sequence of iso-2022 */
+         if (*s == 0x1b)
+         {
+            if (s[1] == '(' && (s[2] == 'B' || s[2] == 'J'))
+              state_ascii = 1;
+            else
+              state_ascii = 0;
+          }
+          if (state_ascii)
+          {
+            if (*s == '"')
+             break;
          if (*s == '\\')
          {
            /* Quote the next character */
@@ -221,6 +234,9 @@
          else
            buffer[i] = *s;
        }
+         else
+           buffer[i] = *s;
+       }
        buffer[i] = 0;
        if (*s)
          s++; /* skip over the " */
@@ -379,7 +395,9 @@
   if (ct->type == TYPETEXT)
   {
     if (!(pc = mutt_get_parameter ("charset", ct->parameter)))
-      mutt_set_parameter ("charset", "us-ascii", &ct->parameter);
+      mutt_set_parameter ("charset", option (OPTSTRICTMIME) ? "us-ascii" :
+                         (const char *) mutt_get_first_charset 
(AssumedCharset),
+                         &ct->parameter);
   }
 
 }
diff -urN mutt/PATCHES mutt.new/PATCHES
--- mutt/PATCHES        2002-12-09 15:44:54.000000000 -0200
+++ mutt.new/PATCHES    2003-12-20 20:21:23.000000000 -0200
@@ -0,0 +1 @@
+patch-1.4.1.tt.compat.1
diff -urN mutt/pgp.c mutt.new/pgp.c
--- mutt/pgp.c  2003-10-24 10:52:28.000000000 -0200
+++ mutt.new/pgp.c      2003-12-21 00:14:34.000000000 -0200
@@ -368,7 +368,7 @@
        int c;
        rewind (pgpout);
        state_set_prefix (s);
-       fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
+       fc = fgetconv_open (pgpout, body_charset, Charset, 0);
        while ((c = fgetconv (fc)) != EOF)
          state_prefix_putc (c, s);
        fgetconv_close (&fc);
@@ -1302,12 +1302,8 @@
     int c;
     FGETCONV *fc;
     
-    if (flags & ENCRYPT)
-      send_charset = "us-ascii";
-    else
-      send_charset = "utf-8";
-    
-    fc = fgetconv_open (fp, from_charset, "utf-8", M_ICONV_HOOK_FROM);
+   send_charset = body_charset;
+   fc = fgetconv_open (fp, from_charset, send_charset, M_ICONV_HOOK_FROM);
     while ((c = fgetconv (fc)) != EOF)
       fputc (c, pgpin);
     
diff -urN mutt/protos.h mutt.new/protos.h
--- mutt/protos.h       2003-10-24 10:52:29.000000000 -0200
+++ mutt.new/protos.h   2003-12-20 20:20:55.000000000 -0200
@@ -346,6 +346,7 @@
 
 /* utf8.c */
 int mutt_wctoutf8 (char *s, unsigned int c);
+size_t mutt_mbswidth (char *s, size_t n);
 
 #ifdef LOCALES_HACK
 #define IsPrint(c) (isprint((unsigned char)(c)) || \
diff -urN mutt/rfc2047.c mutt.new/rfc2047.c
--- mutt/rfc2047.c      2003-10-24 10:52:29.000000000 -0200
+++ mutt.new/rfc2047.c  2003-12-20 20:23:59.000000000 -0200
@@ -706,13 +706,54 @@
   return 0;
 }
 
+/* return length of linear white space */
+static size_t lwslen (const char *s, size_t n)
+{
+  const char *p = s;
+  size_t len = n;
+
+  if (n <= 0)
+    return 0;
+
+  for (; p < s + n; p++)
+    if (!strchr (" \t\r\n", *p))
+    {
+      len = (size_t)(p - s);
+      break;
+    }
+  if (strchr ("\r\n", *(p-1))) /* LWS doesn't end with CRLF */
+    len = (size_t)0;
+  return len;
+}
+
+/* return length of linear white space : reverse */
+static size_t lwsrlen (const char *s, size_t n)
+{
+  const char *p = s + n - 1;
+  size_t len = n;
+
+  if (n <= 0)
+    return 0;
+
+  if (strchr ("\r\n", *p)) /* LWS doesn't end with CRLF */
+    return (size_t)0;
+
+  for (; p >= s; p--)
+    if (!strchr (" \t\r\n", *p))
+    {
+      len = (size_t)(s + n - 1 - p);
+      break;
+    }
+  return len;
+}
+
 /* try to decode anything that looks like a valid RFC2047 encoded
  * header field, ignoring RFC822 parsing rules
  */
 void rfc2047_decode (char **pd)
 {
   const char *p, *q;
-  size_t n;
+  size_t m, n;
   int found_encoded = 0;
   char *d0, *d;
   const char *s = *pd;
@@ -729,6 +770,37 @@
     if (!(p = find_encoded_word (s, &q)))
     {
       /* no encoded words */
+      if (!option (OPTSTRICTMIME))
+      {
+        n = mutt_strlen (s);
+        if (found_encoded && (m = lwslen (s, n)) != 0)
+        {
+          if (m != n)
+            *d = ' ', d++, dlen--;
+          n -= m, s += m;
+        }
+        if (ascii_strcasecmp (AssumedCharset, "us-ascii"))
+        {
+          char *t;
+          size_t tlen;
+
+          t = safe_malloc (n + 1);
+          strfcpy (t, s, n + 1);
+          if (mutt_convert_nomime_string (&t) == 0)
+          {
+            tlen = mutt_strlen (t);
+            strncpy (d, t, tlen);
+            d += tlen;
+          }
+          else
+          {
+            strncpy (d, s, n);
+            d += n;
+          }
+          FREE(&t);
+          break;
+        }
+      }
       strncpy (d, s, dlen);
       d += dlen;
       break;
@@ -738,7 +810,27 @@
     {
       n = (size_t) (p - s);
       /* ignore spaces between encoded words */
-      if (!found_encoded || strspn (s, " \t\r\n") != n)
+      if (!option (OPTSTRICTMIME))
+      {
+        if (found_encoded && (m = lwslen (s, n)) != 0)
+        {
+          if (m != n)
+            *d = ' ', d++, dlen--;
+          n -= m, s += m;
+        }
+
+        if ((m = n - lwsrlen (s, n)) != 0)
+        {
+          if (m > dlen)
+            m = dlen;
+          memcpy (d, s, m);
+          d += m;
+          dlen -= m;
+          if (m != n)
+            *d = ' ', d++, dlen--;
+        }
+      }
+      else if (!found_encoded || strspn (s, " \t\r\n") != n)
       {
        if (n > dlen)
          n = dlen;
@@ -766,7 +858,7 @@
 {
   while (a)
   {
-    if (a->personal && strstr (a->personal, "=?") != NULL)
+    if (a->personal)
       rfc2047_decode (&a->personal);
 #ifdef EXACT_ADDRESS
     if (a->val && strstr (a->val, "=?") != NULL)
diff -urN mutt/rfc2231.c mutt.new/rfc2231.c
--- mutt/rfc2231.c      2003-10-24 10:52:29.000000000 -0200
+++ mutt.new/rfc2231.c  2003-12-20 20:20:55.000000000 -0200
@@ -113,6 +113,12 @@
 
       if (option (OPTRFC2047PARAMS) && p->value && strstr (p->value, "=?"))
        rfc2047_decode (&p->value);
+      else if (!option (OPTSTRICTMIME))
+      {
+        if (ascii_strcasecmp (AssumedCharset, "us-ascii"))
+          mutt_convert_nomime_string (&p->value);
+      }
+
 
       *last = p;
       last = &p->next;
diff -urN mutt/send.c mutt.new/send.c
--- mutt/send.c 2003-10-24 10:52:29.000000000 -0200
+++ mutt.new/send.c     2003-12-20 20:20:55.000000000 -0200
@@ -994,7 +994,7 @@
   {
     if (t->description)
     {
-      rfc2047_encode_string (&t->description);
+      _rfc2047_encode_string (&t->description, 0, 13);
     }
     if (recurse && t->parts)
       encode_descriptions (t->parts, recurse);
diff -urN mutt/sendlib.c mutt.new/sendlib.c
--- mutt/sendlib.c      2003-10-24 10:52:29.000000000 -0200
+++ mutt.new/sendlib.c  2003-12-20 20:24:40.000000000 -0200
@@ -403,6 +403,33 @@
     }
   }
 
+  if (a->use_disp && !option (OPTSTRICTMIME) && option 
(OPTCREATERFC2047PARAMS))
+  {
+    if(!(fn = a->d_filename))
+      fn = a->filename;
+
+    if (fn)
+    {
+      char *tmp;
+
+      /* Strip off the leading path... */
+      if ((t = strrchr (fn, '/')))
+       t++;
+      else
+       t = fn;
+
+      /* length of content-type */
+      len = 21 + mutt_strlen (TYPE (a)) + mutt_strlen (a->subtype);
+
+      buffer[0] = 0;
+      tmp = safe_strdup (t);
+      _rfc2047_encode_string (&tmp, 0, len);
+      rfc822_cat (buffer, sizeof (buffer), tmp, MimeSpecials);
+      FREE (&tmp);
+      fprintf (f, "; name=%s", buffer);
+    }
+  }
+
   fputc ('\n', f);
 
   if (a->description)
@@ -496,7 +523,7 @@
   }
 
   if (a->type == TYPETEXT && (!a->noconv))
-    fc = fgetconv_open (fpin, Charset, 
+    fc = fgetconv_open (fpin, a->file_charset, 
                        mutt_get_body_charset (send_charset, sizeof 
(send_charset), a),
                        0);
   else
@@ -896,6 +923,7 @@
   CONTENT *info;
   CONTENT_STATE state;
   FILE *fp = NULL;
+  char *fromcode;
   char *tocode;
   char buffer[100];
   char chsbuf[STRING];
@@ -930,15 +958,18 @@
   if (b != NULL && b->type == TYPETEXT && (!b->noconv && !b->force_charset))
   {
     char *chs = mutt_get_parameter ("charset", b->parameter);
+    char *fchs = b->use_disp ? ((FileCharset && *FileCharset) ?
+                                FileCharset : Charset) : Charset;
     if (Charset && (chs || SendCharset) &&
-       convert_file_from_to (fp, Charset, chs ? chs : SendCharset,
-                             0, &tocode, info) != (size_t)(-1))
+      convert_file_from_to (fp, fchs, chs ? chs : SendCharset,
+                             &fromcode, &tocode, info) != (size_t)(-1))
     {
       if (!chs)
       {
        mutt_canonical_charset (chsbuf, sizeof (chsbuf), tocode);
        mutt_set_parameter ("charset", chsbuf, &b->parameter);
       }
+      b->file_charset = fromcode;
       FREE (&tocode);
       safe_fclose (&fp);
       return info;
@@ -1318,6 +1349,7 @@
   body->unlink = 1;
   body->use_disp = 0;
   body->disposition = DISPINLINE;
+  body->noconv = 1;
 
   mutt_parse_mime_message (ctx, hdr);
 
@@ -1724,7 +1756,7 @@
     if (!tmp)
       continue;
     
-    rfc2047_encode_string (&tmp);
+    _rfc2047_encode_string (&tmp, 0, 0);
     safe_realloc (&h->data, mutt_strlen (h->data) + 2 + mutt_strlen (tmp) + 1);
 
     sprintf (h->data + i, ": %s", NONULL (tmp));  /* __SPRINTF_CHECKED__ */
@@ -2169,7 +2201,7 @@
 
   if (env->subject)
   {
-    rfc2047_encode_string (&env->subject);
+    _rfc2047_encode_string (&env->subject, 0, 9);
   }
   encode_headers (env->userhdrs);
 }