diff options
-rw-r--r-- | OPS | 1 | ||||
-rw-r--r-- | charset.c | 225 | ||||
-rw-r--r-- | charset.h | 34 | ||||
-rw-r--r-- | compose.c | 32 | ||||
-rw-r--r-- | functions.h | 1 | ||||
-rw-r--r-- | handler.c | 151 |
6 files changed, 100 insertions, 344 deletions
@@ -32,7 +32,6 @@ OP_COMPOSE_GET_ATTACHMENT "get a temporary copy of an attachment" OP_COMPOSE_ISPELL "run ispell on the message" OP_COMPOSE_NEW_MIME "compose new attachment using mailcap entry" OP_COMPOSE_TOGGLE_RECODE "toggle recoding of this attachment" -OP_COMPOSE_RECODE "recode this attachment to/from the local charset" OP_COMPOSE_POSTPONE_MESSAGE "save this message to send later" OP_COMPOSE_RENAME_FILE "rename/move an attached file" OP_COMPOSE_SEND_MESSAGE "send the message" @@ -211,231 +211,6 @@ size_t mutt_iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, } -/************************************************************* - * General decoder framework - * Used in handler.c for converting to mutt's Charset - */ - -#define MIN(a,b) (((a) <= (b)) ? (a): (b)) - -DECODER *mutt_open_decoder (const char *src, const char *dest) -{ - DECODER *d = safe_calloc (1, sizeof (DECODER));; - - d->in.size = DECODER_BUFFSIZE; - d->out.size = DECODER_BUFFSIZE; - - if (dest && src && (d->cd = mutt_iconv_open (dest, src)) != (iconv_t)-1) - { - d->_in = &d->in; - d->outrepl = mutt_is_utf8 (dest) ? "\357\277\275" : "?"; - } - else - { - d->just_take_id = 1; - d->_in = &d->out; - } - return d; -} - -void mutt_free_decoder (DECODER **dpp) -{ - safe_free ((void **) dpp); -} - -static void _process_data (DECODER *d, short force) -{ - if (force) d->forced = 1; - - if (!d->just_take_id) - { - const char *ib = d->in.buff; - size_t ibl = d->in.used; - char *ob = d->out.buff + d->out.used; - size_t obl = d->out.size - d->out.used; - - mutt_iconv (d->cd, &ib, &ibl, &ob, &obl, 0, d->outrepl); - memmove (d->in.buff, ib, ibl); - d->in.used = ibl; - d->out.used = d->out.size - obl; - } -} - -void mutt_decoder_push (DECODER *d, void *_buff, size_t blen, size_t *taken) -{ - if (!_buff || !blen) - { - _process_data (d, 1); - return; - } - - if ((*taken = MIN(blen, d->_in->size - d->_in->used))) - { - memcpy (d->_in->buff + d->_in->used, _buff, *taken); - d->_in->used += *taken; - } -} - -int mutt_decoder_push_one (DECODER *d, char c) -{ - if (d->_in->used == d->_in->size) - return -1; - - d->_in->buff[d->_in->used++] = c; - return 0; -} - -void mutt_decoder_pop (DECODER *d, void *_buff, size_t blen, size_t *popped) -{ - unsigned char *buff = _buff; - - _process_data (d, 0); - - if ((*popped = MIN (blen, d->out.used))) - { - memcpy (buff, d->out.buff, *popped); - memmove (d->out.buff, d->out.buff + *popped, d->out.used - *popped); - d->out.used -= *popped; - } -} - -void mutt_decoder_pop_to_state (DECODER *d, STATE *s) -{ - char tmp[DECODER_BUFFSIZE]; - size_t i, l; - - if (s->prefix) - { - do - { - mutt_decoder_pop (d, tmp, sizeof (tmp), &l); - for (i = 0; i < l; i++) - state_prefix_putc (tmp[i], s); - } - while (l > 0); - } - else - { - do - { - mutt_decoder_pop (d, tmp, sizeof (tmp), &l); - fwrite (tmp, l, 1, s->fpout); - } - while (l > 0); - } -} - - -int mutt_recode_file (const char *fname, const char *src, const char *dest) -{ - FILE *fp, *tmpfp; - char tempfile[_POSIX_PATH_MAX]; - char buffer[1024]; - char tmp[1024]; - int c; - int rv = -1; - int source_file_is_unchanged = 1; - - size_t lf, lpu, lpo; - char *t; - DECODER *dec; - - if ((fp = fopen (fname, "r+")) == NULL) - { - mutt_error (_("Can't open %s: %s."), fname, strerror (errno)); - return -1; - } - - mutt_mktemp (tempfile); - if ((tmpfp = safe_fopen (tempfile, "w+")) == NULL) - { - mutt_error (_("Can't open %s: %s."), tempfile, strerror (errno)); - fclose (fp); - return -1; - } - - dec = mutt_open_decoder (src, dest); - - while ((lf = fread (buffer, 1, sizeof (buffer), fp)) > 0) - { - for (t = buffer; lf; t += lpu) - { - mutt_decoder_push (dec, t, lf, &lpu); - lf -= lpu; - - do - { - mutt_decoder_pop (dec, tmp, sizeof (tmp), &lpo); - if (lpo) - { - if (fwrite (tmp, lpo, 1, tmpfp) == EOF) - goto bail; - } - } - while (lpo); - } - } - if (lf == EOF && !feof(fp)) - { - goto bail; - } - - mutt_decoder_push (dec, NULL, 0, NULL); - do - { - mutt_decoder_pop (dec, tmp, sizeof (tmp), &lpo); - if (lpo) - { - if (fwrite (tmp, lpo, 1, tmpfp) == EOF) - goto bail; - } - } - while (lpo); - - mutt_free_decoder (&dec); - - fclose (fp); fp = NULL; - rewind (tmpfp); - - - source_file_is_unchanged = 0; - - /* don't use safe_fopen here - we're just going - * to overwrite the old file. - */ - if ((fp = fopen (fname, "w")) == NULL) - goto bail; - - while ((c = fgetc (tmpfp)) != EOF) - if (fputc (c, fp) == EOF) - goto bail; - - rv = 0; - unlink (tempfile); - -bail: - if (rv == -1) - { - if (source_file_is_unchanged) - { - mutt_error (_("Error while recoding %s. " - "Leave it unchanged."), - fname); - } - else - { - mutt_error (_("Error while recoding %s. " - "See %s for recovering your data."), - fname, tempfile); - } - } - - if (fp) fclose (fp); - if (tmpfp) fclose (tmpfp); - return rv; -} - - /* * Convert a string * Used in rfc2047.c and rfc2231.c @@ -21,40 +21,6 @@ #include <iconv.h> -#define DECODER_BUFFSIZE 4096 - -struct decoder_buff -{ - size_t size, used; - char buff[DECODER_BUFFSIZE]; -}; - -typedef struct decoder -{ - /*short src_is_utf8;*/ - short just_take_id; - short forced; - char *outrepl; - - /* conversion descriptor */ - iconv_t cd; - - /* the buffers */ - struct decoder_buff in; - struct decoder_buff out; - struct decoder_buff *_in; -} -DECODER; - -DECODER *mutt_open_decoder (const char *, const char *); -void mutt_decoder_push (DECODER *, void *, size_t, size_t *); -void mutt_decoder_pop (DECODER *, void *, size_t, size_t *); -void mutt_decoder_pop_to_state (DECODER *, STATE *); -void mutt_free_decoder (DECODER **); -int mutt_decoder_push_one (DECODER *, char); - -int mutt_recode_file (const char *, const char *, const char *); - int mutt_convert_string (char **, const char *, const char *); iconv_t mutt_iconv_open (const char *, const char *); @@ -892,38 +892,6 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */ menu->redraw = REDRAW_CURRENT; break; } - - case OP_COMPOSE_RECODE: - { - const char *chs; - int rv; - - CHECK_COUNT; - if (!mutt_is_text_type (CURRENT->type, CURRENT->subtype)) - { - mutt_error (_("Recoding only affects text attachments.")); - break; - } - - if (!(chs = mutt_get_parameter ("charset", CURRENT->parameter))) - chs = SendCharset; - - if (CURRENT->noconv) - rv = mutt_recode_file (CURRENT->filename, chs, Charset); - else - rv = mutt_recode_file (CURRENT->filename, Charset, chs); - - mutt_update_encoding (CURRENT); - - if (rv == 0) - { - mutt_message (_("Recoding successful.")); - CURRENT->noconv = !CURRENT->noconv; - } - - menu->redraw = REDRAW_CURRENT; - break; - } #undef CURRENT case OP_COMPOSE_EDIT_DESCRIPTION: diff --git a/functions.h b/functions.h index 4b9e762e..9f44e577 100644 --- a/functions.h +++ b/functions.h @@ -292,7 +292,6 @@ struct binding_t OpCompose[] = { { "edit-to", OP_COMPOSE_EDIT_TO, "t" }, { "edit-type", OP_EDIT_TYPE, "\024" }, { "write-fcc", OP_COMPOSE_WRITE_MESSAGE, "w" }, - { "recode-attachment",OP_COMPOSE_RECODE, NULL }, { "toggle-unlink", OP_COMPOSE_TOGGLE_UNLINK, "u" }, { "toggle-recode", OP_COMPOSE_TOGGLE_RECODE, NULL }, { "update-encoding", OP_COMPOSE_UPDATE_ENCODING, "U" }, @@ -38,6 +38,9 @@ #endif +#define BUFI_SIZE 1000 +#define BUFO_SIZE 2000 + typedef void handler_f (BODY *, STATE *); typedef handler_f *handler_t; @@ -64,11 +67,60 @@ int Index_64[128] = { 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 }; -void mutt_decode_xbit (STATE *s, BODY *b, int istext, DECODER *dec) +static void state_prefix_put (const char *d, size_t dlen, STATE *s) +{ + if (s->prefix) + while (dlen--) + state_prefix_putc (*d++, s); + else + fwrite (d, dlen, 1, s->fpout); +} + +static void convert_to_state(iconv_t cd, char *bufi, size_t *l, STATE *s) +{ + char bufo[BUFO_SIZE]; + const char *ib; + char *ob; + size_t ibl, obl; + + if (!bufi) + { + if (cd != (iconv_t)(-1)) + { + ob = bufo, obl = sizeof (bufo); + iconv (cd, 0, 0, &ob, &obl); + if (ob != bufo) + state_prefix_put (bufo, ob - bufo, s); + } + return; + } + + if (cd == (iconv_t)(-1)) + { + state_prefix_put (bufi, *l, s); + *l = 0; + return; + } + + ib = bufi, ibl = *l; + for (;;) + { + ob = bufo, obl = sizeof (bufo); + mutt_iconv (cd, &ib, &ibl, &ob, &obl, 0, "?"); + if (ob == bufo) + break; + state_prefix_put (bufo, ob - bufo, s); + } + memmove (bufi, ib, ibl); + *l = ibl; +} + +void mutt_decode_xbit (STATE *s, BODY *b, int istext, iconv_t cd) { long len = b->length; int c, ch; - int l = 0; + char bufi[BUFI_SIZE]; + size_t l = 0; if (istext) { @@ -87,16 +139,13 @@ void mutt_decode_xbit (STATE *s, BODY *b, int istext, DECODER *dec) ungetc(ch, s->fpin); } - mutt_decoder_push_one (dec, c); - if (l++ == 1024) - { - mutt_decoder_pop_to_state (dec, s); - l = 0; - } + bufi[l++] = c; + if (l == sizeof (bufi)) + convert_to_state (cd, bufi, &l, s); } - mutt_decoder_push (dec, NULL, 0, NULL); - mutt_decoder_pop_to_state (dec, s); + convert_to_state (cd, bufi, &l, s); + convert_to_state (cd, 0, 0, s); state_reset_prefix (s); } @@ -116,11 +165,12 @@ static int handler_state_fgetc(STATE *s) return ch; } -void mutt_decode_quoted (STATE *s, BODY *b, int istext, DECODER *dec) +void mutt_decode_quoted (STATE *s, BODY *b, int istext, iconv_t cd) { long len = b->length; int ch; - int l = 0; + char bufi[BUFI_SIZE]; + size_t l = 0; state_set_prefix(s); @@ -179,26 +229,24 @@ void mutt_decode_quoted (STATE *s, BODY *b, int istext, DECODER *dec) if(ch != EOF) { - mutt_decoder_push_one (dec, ch); - if (l++ == 1024) - { - mutt_decoder_pop_to_state (dec, s); - l = 0; - } + bufi[l++] = ch; + if (l == sizeof (bufi)) + convert_to_state (cd, bufi, &l, s); } } - mutt_decoder_push (dec, NULL, 0, NULL); - mutt_decoder_pop_to_state (dec, s); + convert_to_state (cd, bufi, &l, s); + convert_to_state (cd, 0, 0, s); state_reset_prefix(s); } -void mutt_decode_base64 (STATE *s, BODY *b, int istext, DECODER *dec) +void mutt_decode_base64 (STATE *s, BODY *b, int istext, iconv_t cd) { long len = b->length; char buf[5]; int c1, c2, c3, c4, ch, cr = 0, i; + char bufi[BUFI_SIZE]; size_t l = 0; buf[4] = 0; @@ -226,14 +274,14 @@ void mutt_decode_base64 (STATE *s, BODY *b, int istext, DECODER *dec) ch = (c1 << 2) | (c2 >> 4); if (cr && ch != '\n') - mutt_decoder_push_one (dec, '\r'); + bufi[l++] = '\r'; cr = 0; if (istext && ch == '\r') cr = 1; else - mutt_decoder_push_one (dec, ch); + bufi[l++] = ch; if (buf[2] == '=') break; @@ -241,39 +289,36 @@ void mutt_decode_base64 (STATE *s, BODY *b, int istext, DECODER *dec) ch = ((c2 & 0xf) << 4) | (c3 >> 2); if (cr && ch != '\n') - mutt_decoder_push_one (dec, '\r'); + bufi[l++] = '\r'; cr = 0; if (istext && ch == '\r') cr = 1; else - mutt_decoder_push_one (dec, ch); + bufi[l++] = ch; if (buf[3] == '=') break; c4 = base64val (buf[3]); ch = ((c3 & 0x3) << 6) | c4; if (cr && ch != '\n') - mutt_decoder_push_one (dec, '\r'); + bufi[l++] = '\r'; cr = 0; if (istext && ch == '\r') cr = 1; else - mutt_decoder_push_one (dec, ch); + bufi[l++] = ch; - if ((l += 3) >= 1024) - { - mutt_decoder_pop_to_state (dec, s); - l = 0; - } + if (l + 8 >= sizeof (bufi)) + convert_to_state (cd, bufi, &l, s); } - if (cr) mutt_decoder_push_one (dec, '\r'); - - mutt_decoder_push (dec, NULL, 0, NULL); - mutt_decoder_pop_to_state (dec, s); + if (cr) bufi[l++] = '\r'; + + convert_to_state (cd, bufi, &l, s); + convert_to_state (cd, 0, 0, s); state_reset_prefix(s); } @@ -285,12 +330,14 @@ unsigned char decode_byte (char ch) return ch - 32; } -void mutt_decode_uuencoded (STATE *s, BODY *b, int istext, DECODER *dec) +void mutt_decode_uuencoded (STATE *s, BODY *b, int istext, iconv_t cd) { char tmps[SHORT_STRING]; char linelen, c, l, out; char *pt; long len = b->length; + char bufi[BUFI_SIZE]; + size_t k; if(istext) state_set_prefix(s); @@ -320,18 +367,18 @@ void mutt_decode_uuencoded (STATE *s, BODY *b, int istext, DECODER *dec) out = decode_byte (*pt) << l; pt++; out |= (decode_byte (*pt) >> (6 - l)); - mutt_decoder_push_one (dec, out); + bufi[k++] = out; c++; if (c == linelen) break; } - mutt_decoder_pop_to_state (dec, s); + convert_to_state (cd, bufi, &k, s); pt++; } } - mutt_decoder_push (dec, NULL, 0, NULL); - mutt_decoder_pop_to_state (dec, s); + convert_to_state (cd, bufi, &k, s); + convert_to_state (cd, 0, 0, s); state_reset_prefix(s); } @@ -1287,33 +1334,35 @@ static void external_body_handler (BODY *b, STATE *s) void mutt_decode_attachment (BODY *b, STATE *s) { - char *charset = mutt_get_parameter ("charset", b->parameter); int istext = mutt_is_text_type (b->type, b->subtype); - DECODER *dec; + iconv_t cd = (iconv_t)(-1); if (istext && s->flags & M_CHARCONV) - dec = mutt_open_decoder (charset, Charset); - else - dec = mutt_open_decoder (NULL, NULL); + { + char *charset = mutt_get_parameter ("charset", b->parameter); + if (charset) + cd = mutt_iconv_open (Charset, charset); + } fseek (s->fpin, b->offset, 0); switch (b->encoding) { case ENCQUOTEDPRINTABLE: - mutt_decode_quoted (s, b, istext, dec); + mutt_decode_quoted (s, b, istext, cd); break; case ENCBASE64: - mutt_decode_base64 (s, b, istext, dec); + mutt_decode_base64 (s, b, istext, cd); break; case ENCUUENCODED: - mutt_decode_uuencoded (s, b, istext, dec); + mutt_decode_uuencoded (s, b, istext, cd); break; default: - mutt_decode_xbit (s, b, istext, dec); + mutt_decode_xbit (s, b, istext, cd); break; } - mutt_free_decoder (&dec); + if (cd != (iconv_t)(-1)) + iconv_close (cd); } void mutt_body_handler (BODY *b, STATE *s) |