/*
- * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
+ * Copyright (C) 1996-2000,2002 Michael R. Elkins <me@mutt.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
fwrite (d, dlen, 1, s->fpout);
}
-void mutt_convert_to_state(iconv_t cd, char *bufi, size_t *l, STATE *s)
+static void mutt_convert_to_state(iconv_t cd, char *bufi, size_t *l, STATE *s)
{
char bufo[BUFO_SIZE];
ICONV_CONST char *ib;
*l = ibl;
}
-void mutt_decode_xbit (STATE *s, long len, int istext, iconv_t cd)
+static void mutt_decode_xbit (STATE *s, long len, int istext, iconv_t cd)
{
int c, ch;
char bufi[BUFI_SIZE];
int last)
{
char *d, *s;
- char c;
+ char c = 0;
- int kind;
+ int kind = -1;
int soft = 0;
/* decode the line */
}
if (!soft && last == '\n')
- *d++ = '\n';
+ {
+ /* neither \r nor \n as part of line-terminating CRLF
+ * may be qp-encoded, so remove \r and \n-terminate;
+ * see RfC2045, sect. 6.7, (1): General 8bit representation */
+ if (kind == 0 && c == '\r')
+ *(d-1) = '\n';
+ else
+ *d++ = '\n';
+ }
*d = '\0';
*l = d - dest;
*
*/
-void mutt_decode_quoted (STATE *s, long len, int istext, iconv_t cd)
+static void mutt_decode_quoted (STATE *s, long len, int istext, iconv_t cd)
{
char line[STRING];
char decline[2*STRING];
state_reset_prefix(s);
}
-unsigned char decode_byte (char ch)
+static unsigned char decode_byte (char ch)
{
if (ch == 96)
return 0;
return ch - 32;
}
-void mutt_decode_uuencoded (STATE *s, long len, int istext, iconv_t cd)
+static void mutt_decode_uuencoded (STATE *s, long len, int istext, iconv_t cd)
{
char tmps[SHORT_STRING];
char linelen, c, l, out;
RICH_FLUSHRIGHT, RICH_COLOR, RICH_LAST_TAG };
static struct {
- const char *tag_name;
+ const wchar_t *tag_name;
int index;
} EnrichedTags[] = {
- { "param", RICH_PARAM },
- { "bold", RICH_BOLD },
- { "italic", RICH_ITALIC },
- { "underline", RICH_UNDERLINE },
- { "nofill", RICH_NOFILL },
- { "excerpt", RICH_EXCERPT },
- { "indent", RICH_INDENT },
- { "indentright", RICH_INDENT_RIGHT },
- { "center", RICH_CENTER },
- { "flushleft", RICH_FLUSHLEFT },
- { "flushright", RICH_FLUSHRIGHT },
- { "flushboth", RICH_FLUSHLEFT },
- { "color", RICH_COLOR },
- { "x-color", RICH_COLOR },
+ { L"param", RICH_PARAM },
+ { L"bold", RICH_BOLD },
+ { L"italic", RICH_ITALIC },
+ { L"underline", RICH_UNDERLINE },
+ { L"nofill", RICH_NOFILL },
+ { L"excerpt", RICH_EXCERPT },
+ { L"indent", RICH_INDENT },
+ { L"indentright", RICH_INDENT_RIGHT },
+ { L"center", RICH_CENTER },
+ { L"flushleft", RICH_FLUSHLEFT },
+ { L"flushright", RICH_FLUSHRIGHT },
+ { L"flushboth", RICH_FLUSHLEFT },
+ { L"color", RICH_COLOR },
+ { L"x-color", RICH_COLOR },
{ NULL, -1 }
};
struct enriched_state
{
- char *buffer;
- char *line;
- char *param;
+ wchar_t *buffer;
+ wchar_t *line;
+ wchar_t *param;
size_t buff_len;
size_t line_len;
size_t line_used;
/* Strip trailing white space */
size_t y = stte->line_used - 1;
- while (y && ISSPACE (stte->line[y]))
+ while (y && iswspace (stte->line[y]))
{
- stte->line[y] = '\0';
+ stte->line[y] = (wchar_t) '\0';
y--;
stte->line_used--;
stte->line_len--;
/* Strip leading whitespace */
y = 0;
- while (stte->line[y] && ISSPACE (stte->line[y]))
+ while (stte->line[y] && iswspace (stte->line[y]))
y++;
if (y)
{
}
}
}
- state_puts (stte->line, stte->s);
+ state_putws ((const wchar_t*) stte->line, stte->s);
}
state_putc ('\n', stte->s);
- stte->line[0] = '\0';
+ stte->line[0] = (wchar_t) '\0';
stte->line_len = 0;
stte->line_used = 0;
stte->indent_len = 0;
if (stte->buff_used)
{
- stte->buffer[stte->buff_used] = '\0';
+ stte->buffer[stte->buff_used] = (wchar_t) '\0';
stte->line_used += stte->buff_used;
if (stte->line_used > stte->line_max)
{
stte->line_max = stte->line_used;
- safe_realloc (&stte->line, stte->line_max + 1);
+ safe_realloc (&stte->line, (stte->line_max + 1) * sizeof (wchar_t));
}
- strcat (stte->line, stte->buffer); /* __STRCAT_CHECKED__ */
+ wcscat (stte->line, stte->buffer);
stte->line_len += stte->word_len;
stte->word_len = 0;
stte->buff_used = 0;
}
- if (wrap)
+ if (wrap)
enriched_wrap(stte);
+ fflush (stte->s->fpout);
}
-static void enriched_putc (int c, struct enriched_state *stte)
+static void enriched_putwc (wchar_t c, struct enriched_state *stte)
{
if (stte->tag_level[RICH_PARAM])
{
if (stte->tag_level[RICH_COLOR])
{
if (stte->param_used + 1 >= stte->param_len)
- safe_realloc (&stte->param, (stte->param_len += STRING));
+ safe_realloc (&stte->param, (stte->param_len += STRING) * sizeof (wchar_t));
stte->param[stte->param_used++] = c;
}
if (stte->buff_len < stte->buff_used + 3)
{
stte->buff_len += LONG_STRING;
- safe_realloc (&stte->buffer, stte->buff_len + 1);
+ safe_realloc (&stte->buffer, (stte->buff_len + 1) * sizeof (wchar_t));
}
- if ((!stte->tag_level[RICH_NOFILL] && ISSPACE (c)) || c == '\0' )
+ if ((!stte->tag_level[RICH_NOFILL] && iswspace (c)) || c == (wchar_t) '\0')
{
- if (c == '\t')
+ if (c == (wchar_t) '\t')
stte->word_len += 8 - (stte->line_len + stte->word_len) % 8;
else
stte->word_len++;
if (stte->tag_level[RICH_BOLD])
{
stte->buffer[stte->buff_used++] = c;
- stte->buffer[stte->buff_used++] = '\010';
+ stte->buffer[stte->buff_used++] = (wchar_t) '\010';
stte->buffer[stte->buff_used++] = c;
}
else if (stte->tag_level[RICH_UNDERLINE])
{
stte->buffer[stte->buff_used++] = '_';
- stte->buffer[stte->buff_used++] = '\010';
+ stte->buffer[stte->buff_used++] = (wchar_t) '\010';
stte->buffer[stte->buff_used++] = c;
}
else if (stte->tag_level[RICH_ITALIC])
{
stte->buffer[stte->buff_used++] = c;
- stte->buffer[stte->buff_used++] = '\010';
+ stte->buffer[stte->buff_used++] = (wchar_t) '\010';
stte->buffer[stte->buff_used++] = '_';
}
else
}
}
-static void enriched_puts (char *s, struct enriched_state *stte)
+static void enriched_puts (const char *s, struct enriched_state *stte)
{
- char *c;
+ const char *c;
- if (stte->buff_len < stte->buff_used + mutt_strlen(s))
+ if (stte->buff_len < stte->buff_used + mutt_strlen (s))
{
stte->buff_len += LONG_STRING;
- safe_realloc (&stte->buffer, stte->buff_len + 1);
+ safe_realloc (&stte->buffer, (stte->buff_len + 1) * sizeof (wchar_t));
}
c = s;
while (*c)
{
- stte->buffer[stte->buff_used++] = *c;
+ stte->buffer[stte->buff_used++] = (wchar_t) *c;
c++;
}
}
-static void enriched_set_flags (const char *tag, struct enriched_state *stte)
+static void enriched_set_flags (const wchar_t *tag, struct enriched_state *stte)
{
- const char *tagptr = tag;
+ const wchar_t *tagptr = tag;
int i, j;
- if (*tagptr == '/')
+ if (*tagptr == (wchar_t) '/')
tagptr++;
for (i = 0, j = -1; EnrichedTags[i].tag_name; i++)
- if (ascii_strcasecmp (EnrichedTags[i].tag_name,tagptr) == 0)
+ if (wcscasecmp (EnrichedTags[i].tag_name, tagptr) == 0)
{
j = EnrichedTags[i].index;
break;
if (j == RICH_CENTER || j == RICH_FLUSHLEFT || j == RICH_FLUSHRIGHT)
enriched_flush (stte, 1);
- if (*tag == '/')
+ if (*tag == (wchar_t) '/')
{
if (stte->tag_level[j]) /* make sure not to go negative */
stte->tag_level[j]--;
if ((stte->s->flags & M_DISPLAY) && j == RICH_PARAM && stte->tag_level[RICH_COLOR])
{
- stte->param[stte->param_used] = '\0';
- if (!ascii_strcasecmp(stte->param, "black"))
+ stte->param[stte->param_used] = (wchar_t) '\0';
+ if (!wcscasecmp(L"black", stte->param))
{
enriched_puts("\033[30m", stte);
}
- else if (!ascii_strcasecmp(stte->param, "red"))
+ else if (!wcscasecmp(L"red", stte->param))
{
enriched_puts("\033[31m", stte);
}
- else if (!ascii_strcasecmp(stte->param, "green"))
+ else if (!wcscasecmp(L"green", stte->param))
{
enriched_puts("\033[32m", stte);
}
- else if (!ascii_strcasecmp(stte->param, "yellow"))
+ else if (!wcscasecmp(L"yellow", stte->param))
{
enriched_puts("\033[33m", stte);
}
- else if (!ascii_strcasecmp(stte->param, "blue"))
+ else if (!wcscasecmp(L"blue", stte->param))
{
enriched_puts("\033[34m", stte);
}
- else if (!ascii_strcasecmp(stte->param, "magenta"))
+ else if (!wcscasecmp(L"magenta", stte->param))
{
enriched_puts("\033[35m", stte);
}
- else if (!ascii_strcasecmp(stte->param, "cyan"))
+ else if (!wcscasecmp(L"cyan", stte->param))
{
enriched_puts("\033[36m", stte);
}
- else if (!ascii_strcasecmp(stte->param, "white"))
+ else if (!wcscasecmp(L"white", stte->param))
{
enriched_puts("\033[37m", stte);
}
if (j == RICH_PARAM)
{
stte->param_used = 0;
- stte->param[0] = '\0';
+ stte->param[0] = (wchar_t) '\0';
}
}
else
}
}
-int text_enriched_handler (BODY *a, STATE *s)
+static int text_enriched_handler (BODY *a, STATE *s)
{
enum {
TEXT, LANGLE, TAG, BOGUS_TAG, NEWLINE, ST_EOF, DONE
long bytes = a->length;
struct enriched_state stte;
- int c = 0;
+ wchar_t wc = 0;
int tag_len = 0;
- char tag[LONG_STRING + 1];
+ wchar_t tag[LONG_STRING + 1];
memset (&stte, 0, sizeof (stte));
stte.s = s;
stte.WrapMargin = ((s->flags & M_DISPLAY) ? (COLS-4) : ((COLS-4)<72)?(COLS-4):72);
stte.line_max = stte.WrapMargin * 4;
- stte.line = (char *) safe_calloc (1, stte.line_max + 1);
- stte.param = (char *) safe_calloc (1, STRING);
+ stte.line = (wchar_t *) safe_calloc (1, (stte.line_max + 1) * sizeof (wchar_t));
+ stte.param = (wchar_t *) safe_calloc (1, (STRING) * sizeof (wchar_t));
stte.param_len = STRING;
stte.param_used = 0;
{
if (state != ST_EOF)
{
- if (!bytes || (c = fgetc (s->fpin)) == EOF)
+ if (!bytes || (wc = fgetwc (s->fpin)) == WEOF)
state = ST_EOF;
else
bytes--;
switch (state)
{
case TEXT :
- switch (c)
+ switch (wc)
{
case '<' :
state = LANGLE;
}
else
{
- enriched_putc (' ', &stte);
+ enriched_putwc ((wchar_t) ' ', &stte);
state = NEWLINE;
}
break;
default:
- enriched_putc (c, &stte);
+ enriched_putwc (wc, &stte);
}
break;
case LANGLE :
- if (c == '<')
+ if (wc == (wchar_t) '<')
{
- enriched_putc (c, &stte);
+ enriched_putwc (wc, &stte);
state = TEXT;
break;
}
}
/* Yes, fall through (it wasn't a <<, so this char is first in TAG) */
case TAG :
- if (c == '>')
+ if (wc == (wchar_t) '>')
{
- tag[tag_len] = '\0';
+ tag[tag_len] = (wchar_t) '\0';
enriched_set_flags (tag, &stte);
state = TEXT;
}
else if (tag_len < LONG_STRING) /* ignore overly long tags */
- tag[tag_len++] = c;
+ tag[tag_len++] = wc;
else
state = BOGUS_TAG;
break;
case BOGUS_TAG :
- if (c == '>')
+ if (wc == (wchar_t) '>')
state = TEXT;
break;
case NEWLINE :
- if (c == '\n')
+ if (wc == (wchar_t) '\n')
enriched_flush (&stte, 1);
else
{
- ungetc (c, s->fpin);
+ ungetwc (wc, s->fpin);
bytes++;
state = TEXT;
}
break;
case ST_EOF :
- enriched_putc ('\0', &stte);
+ enriched_putwc ((wchar_t) '\0', &stte);
enriched_flush (&stte, 1);
state = DONE;
break;
}
/* handles message/rfc822 body parts */
-int message_handler (BODY *a, STATE *s)
+static int message_handler (BODY *a, STATE *s)
{
struct stat st;
BODY *b;
{
mutt_copy_hdr (s->fpin, s->fpout, off_start, b->parts->offset,
(((s->flags & M_WEED) || ((s->flags & (M_DISPLAY|M_PRINTING)) && option (OPTWEED))) ? (CH_WEED | CH_REORDER) : 0) |
- (s->prefix ? CH_PREFIX : 0) | CH_DECODE | CH_FROM, s->prefix);
+ (s->prefix ? CH_PREFIX : 0) | CH_DECODE | CH_FROM |
+ ((s->flags & M_DISPLAY) ? CH_DISPLAY : 0), s->prefix);
if (s->prefix)
state_puts (s->prefix, s);
return (0);
}
-int multipart_handler (BODY *a, STATE *s)
+static int multipart_handler (BODY *a, STATE *s)
{
BODY *b, *p;
char length[5];
else
state_putc ('\n', s);
}
- else
- {
- if (p->description && mutt_can_decode (p))
- state_printf (s, "Content-Description: %s\n", p->description);
- if (p->form_name)
- state_printf(s, "%s: \n", p->form_name);
-
- }
rc = mutt_body_handler (p, s);
state_putc ('\n', s);
if (rc)
{
+ mutt_error (_("One or more parts of this message could not be displayed"));
dprint (1, (debugfile, "Failed on attachment #%d, type %s/%s.\n", count, TYPE(p), NONULL (p->subtype)));
}
- if (rc || ((s->flags & M_REPLYING)
- && (option (OPTINCLUDEONLYFIRST)) && (s->flags & M_FIRSTDONE)))
+ if ((s->flags & M_REPLYING)
+ && (option (OPTINCLUDEONLYFIRST)) && (s->flags & M_FIRSTDONE))
break;
}
if (a->encoding == ENCBASE64 || a->encoding == ENCQUOTEDPRINTABLE ||
a->encoding == ENCUUENCODED)
mutt_free_body (&b);
-
+
+ /* make failure of a single part non-fatal */
+ if (rc < 0)
+ rc = 1;
return rc;
}
-int autoview_handler (BODY *a, STATE *s)
+static int autoview_handler (BODY *a, STATE *s)
{
rfc1524_entry *entry = rfc1524_new_entry ();
char buffer[LONG_STRING];
mutt_copy_hdr(s->fpin, s->fpout, ftello (s->fpin), b->parts->offset,
(option (OPTWEED) ? (CH_WEED | CH_REORDER) : 0) |
- CH_DECODE, NULL);
+ CH_DECODE | CH_DISPLAY, NULL);
}
}
else
access_type);
mutt_copy_hdr (s->fpin, s->fpout, ftello (s->fpin), b->parts->offset,
(option (OPTWEED) ? (CH_WEED | CH_REORDER) : 0) |
- CH_DECODE , NULL);
+ CH_DECODE | CH_DISPLAY, NULL);
}
}
iconv_close (cd);
}
+/* when generating format=flowed ($text_flowed is set) from format=fixed,
+ * strip all trailing spaces to improve interoperability;
+ * if $text_flowed is unset, simply verbatim copy input
+ */
+static int text_plain_handler (BODY *b, STATE *s)
+{
+ char *buf = NULL;
+ size_t l = 0, sz = 0;
+
+ while ((buf = mutt_read_line (buf, &sz, s->fpin, NULL, 0)))
+ {
+ if (mutt_strcmp (buf, "-- ") != 0 && option (OPTTEXTFLOWED))
+ {
+ l = mutt_strlen (buf);
+ while (l > 0 && buf[l-1] == ' ')
+ buf[--l] = 0;
+ }
+ if (s->prefix)
+ state_puts (s->prefix, s);
+ state_puts (buf, s);
+ state_putc ('\n', s);
+ }
+
+ FREE (&buf);
+ return 0;
+}
+
int mutt_body_handler (BODY *b, STATE *s)
{
int decode = 0;
else if (ascii_strcasecmp ("flowed", mutt_get_parameter ("format", b->parameter)) == 0)
handler = rfc3676_handler;
else
- plaintext = 1;
+ handler = text_plain_handler;
}
else if (ascii_strcasecmp ("enriched", b->subtype) == 0)
handler = text_enriched_handler;
if (!handler)
handler = multipart_handler;
+
+ if (b->encoding != ENC7BIT && b->encoding != ENC8BIT
+ && b->encoding != ENCBINARY)
+ {
+ dprint (1, (debugfile, "Bad encoding type %d for multipart entity, "
+ "assuming 7 bit\n", b->encoding));
+ b->encoding = ENC7BIT;
+ }
}
else if (WithCrypto && b->type == TYPEAPPLICATION)
{
- if ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (b))
+ if (option (OPTDONTHANDLEPGPKEYS)
+ && !ascii_strcasecmp("pgp-keys", b->subtype))
+ {
+ /* pass raw part through for key extraction */
+ plaintext = 1;
+ }
+ else if ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (b))
handler = crypt_pgp_application_pgp_handler;
- if ((WithCrypto & APPLICATION_SMIME) && mutt_is_application_smime(b))
+ else if ((WithCrypto & APPLICATION_SMIME) && mutt_is_application_smime(b))
handler = crypt_smime_application_smime_handler;
}
-
- if (plaintext || handler)
+ /* only respect disposition == attachment if we're not
+ displaying from the attachment menu (i.e. pager) */
+ if ((!option (OPTHONORDISP) || (b->disposition != DISPATTACH ||
+ option(OPTVIEWATTACH))) &&
+ (plaintext || handler))
{
fseeko (s->fpin, b->offset, 0);
{
/* decode to a tempfile, saving the original destination */
fp = s->fpout;
- mutt_mktemp (tempfile);
+ mutt_mktemp (tempfile, sizeof (tempfile));
if ((s->fpout = safe_fopen (tempfile, "w")) == NULL)
{
mutt_error _("Unable to open temporary file!");
{
b->length = ftello (s->fpout);
b->offset = 0;
- fclose (s->fpout);
+ safe_fclose (&s->fpout);
/* restore final destination and substitute the tempfile for input */
s->fpout = fp;
b->offset = tmpoffset;
/* restore the original source stream */
- fclose (s->fpin);
+ safe_fclose (&s->fpin);
s->fpin = fp;
}
}
s->flags |= M_FIRSTDONE;
}
- else if (s->flags & M_DISPLAY)
+ /* print hint to use attachment menu for disposition == attachment
+ if we're not already being called from there */
+ else if ((s->flags & M_DISPLAY) || (b->disposition == DISPATTACH &&
+ !option (OPTVIEWATTACH) &&
+ option (OPTHONORDISP) &&
+ (plaintext || handler)))
{
state_mark_attach (s);
- state_printf (s, _("[-- %s/%s is unsupported "), TYPE (b), b->subtype);
+ if (option (OPTHONORDISP) && b->disposition == DISPATTACH)
+ fputs (_("[-- This is an attachment "), s->fpout);
+ else
+ state_printf (s, _("[-- %s/%s is unsupported "), TYPE (b), b->subtype);
if (!option (OPTVIEWATTACH))
{
if (km_expand_key (type, sizeof(type),