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

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



Even though I don't really like the assumed_charset feature, I'm
somewhat tempted to adding it to mutt; I'd welcome comments on that.

Generating RFC2047-encoded MIME parameters with mutt is, however, a
standards violation that is *not* going to make it into the code.
RFC2231 is the standard for this.  Mutt implements that standard.
That's all I have to say about this.
-- 
Thomas Roessler · Personal soap box at <http://log.does-not-exist.org/>.






On 2003-12-26 09:10:29 -0200, Carlos Laviola wrote:
> From: Carlos Laviola <claviola@xxxxxxxxx>
> To: Alain Bench <veronatif@xxxxxxx>
> Cc: 222191@xxxxxxxxxxxxxxx, mutt-dev@xxxxxxxx
> Date: Fri, 26 Dec 2003 09:10:29 -0200
> Subject: Re: Bug#222191: patch-1.4.1.tt.compat.1 for mutt fixes this bug
> X-Spam-Level: 
> 
> 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);
>  }