Changes specific to mutt-ng:
+2005-02-23:
+ * Integrated assume_charset patch from http://www.emaillab.org/mutt/download15.html.en
+
2005-02-22:
* Merged mutt changes
* Sidebar now honors the imap_home_namespace
+patch-1.5.6.tt.assumed_charset.1
patch-1.5.6.tg.hcache.12
patch-1.5.5.1.pdmef.short_mbox_name.1
rr.compressed
iconv_close (fc->cd);
FREE (_fc);
}
+
+char *mutt_get_first_charset (const char *charset)
+{
+ static char fcharset[SHORT_STRING];
+ const char *c, *c1;
+
+ 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_nonmime_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;
+}
+
#endif
int mutt_convert_string (char **, const char *, const char *, int);
+char *mutt_get_first_charset (const char *);
+int mutt_convert_nonmime_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 *);
WHERE char *AliasFile;
WHERE char *AliasFmt;
+WHERE char *AssumedCharset;
WHERE char *AttachSep;
WHERE char *Attribution;
WHERE char *AttachFormat;
WHERE char *DsnReturn;
WHERE char *Editor;
WHERE char *EscChar;
+WHERE char *FileCharset;
WHERE char *FolderFormat;
WHERE char *ForwFmt;
WHERE char *Fqdn;
Quotebuf[0] = '\0';
- if (istext && s->flags & M_CHARCONV)
+ if (istext)
{
- char *charset = mutt_get_parameter ("charset", b->parameter);
- if (charset && Charset)
- cd = mutt_iconv_open (Charset, charset, M_ICONV_HOOK_FROM);
+ 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);
** 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
+ ** 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.
+ */
#ifdef USE_NNTP
{ "ask_follow_up", DT_BOOL, R_NONE, OPTASKFOLLOWUP, 0 },
/*
** signed.
** (PGP only)
*/
+ { "file_charset", DT_STR, R_NONE, UL &FileCharset, UL 0 },
+ /*
+ ** .pp
+ ** 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
** 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, 1 },
+ /*
+ ** .pp
+ ** 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
OPTSORTRE,
OPTSPAMSEP,
OPTSTATUSONTOP,
+ OPTSTRICTMIME,
OPTSTRICTTHREADS,
OPTSTUFFQUOTED,
OPTSUSPEND,
* 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
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++)
{
+ if (!option (OPTSTRICTMIME)) {
+ /* As iso-2022-* has a characer of '"' with non-ascii state,
+ * ignore it. */
+ if (*s == 0x1b && i < sizeof (buffer) - 2)
+ {
+ if (s[1] == '(' && (s[2] == 'B' || s[2] == 'J'))
+ state_ascii = 1;
+ else
+ state_ascii = 0;
+ }
+ }
+ if (state_ascii && *s == '"')
+ break;
if (*s == '\\')
{
/* Quote the next character */
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);
}
}
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;
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_nonmime_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;
if (p != s)
{
n = (size_t) (p - s);
- /* ignore spaces between encoded words */
- if (!found_encoded || strspn (s, " \t\r\n") != n)
+ /* ignore spaces between encoded words
+ * and linear white spaces between encoded word and *text */
+ 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;
{
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)
rfc2047_decode (&a->val);
if (option (OPTRFC2047PARAMS) && p->value && strstr (p->value, "=?"))
rfc2047_decode (&p->value);
+ else if (!option (OPTSTRICTMIME))
+ {
+ if (ascii_strcasecmp (AssumedCharset, "us-ascii"))
+ mutt_convert_nonmime_string (&p->value);
+ }
*last = p;
last = &p->next;
}
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
CONTENT *info;
CONTENT_STATE state;
FILE *fp = NULL;
+ char *fromcode;
char *tocode;
char buffer[100];
char chsbuf[STRING];
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;
body->unlink = 1;
body->use_disp = 0;
body->disposition = DISPINLINE;
+ body->noconv = 1;
mutt_parse_mime_message (ctx, hdr);