X-Git-Url: https://git.llucax.com/software/mutt-debian.git/blobdiff_plain/14c29200cb58d3c4a0830265f2433849781858d0..cefebddeeae89408bcf1b0474c5a734979e5e3ff:/handler.c?ds=sidebyside diff --git a/handler.c b/handler.c index d2ad711..57dab0f 100644 --- a/handler.c +++ b/handler.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1996-2000 Michael R. Elkins + * Copyright (C) 1996-2000,2002 Michael R. Elkins * * 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 @@ -74,7 +74,7 @@ static void state_prefix_put (const char *d, size_t dlen, STATE *s) 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; @@ -113,7 +113,7 @@ void mutt_convert_to_state(iconv_t cd, char *bufi, size_t *l, STATE *s) *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]; @@ -173,9 +173,9 @@ static void qp_decode_line (char *dest, char *src, size_t *l, int last) { char *d, *s; - char c; + char c = 0; - int kind; + int kind = -1; int soft = 0; /* decode the line */ @@ -191,7 +191,15 @@ static void qp_decode_line (char *dest, char *src, size_t *l, } 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; @@ -221,7 +229,7 @@ static void qp_decode_line (char *dest, char *src, size_t *l, * */ -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]; @@ -357,14 +365,14 @@ void mutt_decode_base64 (STATE *s, long len, int istext, iconv_t cd) 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; @@ -427,31 +435,31 @@ enum { RICH_PARAM=0, RICH_BOLD, RICH_UNDERLINE, RICH_ITALIC, RICH_NOFILL, 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; @@ -478,9 +486,9 @@ static void enriched_wrap (struct enriched_state *stte) /* 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--; @@ -490,7 +498,7 @@ static void enriched_wrap (struct enriched_state *stte) /* Strip leading whitespace */ y = 0; - while (stte->line[y] && ISSPACE (stte->line[y])) + while (stte->line[y] && iswspace (stte->line[y])) y++; if (y) { @@ -530,11 +538,11 @@ static void enriched_wrap (struct enriched_state *stte) } } } - 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; @@ -585,31 +593,32 @@ static void enriched_flush (struct enriched_state *stte, int wrap) 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; } @@ -620,12 +629,12 @@ static void enriched_putc (int c, struct enriched_state *stte) 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++; @@ -640,20 +649,20 @@ static void enriched_putc (int c, struct enriched_state *stte) 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 @@ -669,33 +678,33 @@ static void enriched_putc (int c, struct enriched_state *stte) } } -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; @@ -706,42 +715,42 @@ static void enriched_set_flags (const char *tag, struct enriched_state *stte) 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); } @@ -755,7 +764,7 @@ static void enriched_set_flags (const char *tag, struct enriched_state *stte) if (j == RICH_PARAM) { stte->param_used = 0; - stte->param[0] = '\0'; + stte->param[0] = (wchar_t) '\0'; } } else @@ -766,7 +775,7 @@ static void enriched_set_flags (const char *tag, struct enriched_state *stte) } } -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 @@ -774,16 +783,16 @@ int text_enriched_handler (BODY *a, STATE *s) 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; @@ -798,7 +807,7 @@ int text_enriched_handler (BODY *a, STATE *s) { if (state != ST_EOF) { - if (!bytes || (c = fgetc (s->fpin)) == EOF) + if (!bytes || (wc = fgetwc (s->fpin)) == EOF) state = ST_EOF; else bytes--; @@ -807,7 +816,7 @@ int text_enriched_handler (BODY *a, STATE *s) switch (state) { case TEXT : - switch (c) + switch (wc) { case '<' : state = LANGLE; @@ -820,20 +829,20 @@ int text_enriched_handler (BODY *a, STATE *s) } 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; } @@ -844,36 +853,36 @@ int text_enriched_handler (BODY *a, STATE *s) } /* 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; @@ -1057,7 +1066,7 @@ static int alternative_handler (BODY *a, STATE *s) } /* 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; @@ -1080,7 +1089,8 @@ int message_handler (BODY *a, STATE *s) { 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); @@ -1137,7 +1147,7 @@ int mutt_can_decode (BODY *a) return (0); } -int multipart_handler (BODY *a, STATE *s) +static int multipart_handler (BODY *a, STATE *s) { BODY *b, *p; char length[5]; @@ -1185,36 +1195,32 @@ int multipart_handler (BODY *a, STATE *s) 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]; @@ -1419,7 +1425,7 @@ static int external_body_handler (BODY *b, STATE *s) 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 @@ -1436,7 +1442,7 @@ static int external_body_handler (BODY *b, STATE *s) 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); } } @@ -1480,6 +1486,34 @@ void mutt_decode_attachment (BODY *b, STATE *s) 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[LONG_STRING]; + size_t l; + + while (fgets (buf, sizeof (buf), s->fpin)) + { + l = mutt_strlen (buf); + if (l > 0 && buf[l-1] == '\n') + buf[--l] = 0; + if (option (OPTTEXTFLOWED)) + { + 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); + } + + return 0; +} + int mutt_body_handler (BODY *b, STATE *s) { int decode = 0; @@ -1520,7 +1554,7 @@ int mutt_body_handler (BODY *b, STATE *s) 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; @@ -1564,17 +1598,34 @@ int mutt_body_handler (BODY *b, STATE *s) 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); @@ -1624,7 +1675,7 @@ int mutt_body_handler (BODY *b, STATE *s) { 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; @@ -1655,16 +1706,24 @@ int mutt_body_handler (BODY *b, STATE *s) 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),