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);
> }