Mercurial > dovecot > original-hg > dovecot-1.2
changeset 9248:ea84eb708efc HEAD
Split quoted-printable parsing to q-p body parsing and "Q" header parsing.
Fixed also several other issues in quoted-printable parsing to get it fully
RFC compliant.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 26 Jul 2009 16:32:18 -0400 |
parents | 7168ca62c556 |
children | 48b1f2b7144b |
files | src/lib-mail/message-header-decode.c src/lib-mail/quoted-printable.c src/lib-mail/quoted-printable.h |
diffstat | 3 files changed, 87 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-mail/message-header-decode.c Sun Jul 26 15:03:30 2009 -0400 +++ b/src/lib-mail/message-header-decode.c Sun Jul 26 16:32:18 2009 -0400 @@ -36,9 +36,9 @@ switch (data[start_pos[0]+1]) { case 'q': case 'Q': - quoted_printable_decode(data + start_pos[1] + 1, - start_pos[2] - start_pos[1] - 1, - NULL, decodebuf); + quoted_printable_q_decode(data + start_pos[1] + 1, + start_pos[2] - start_pos[1] - 1, + decodebuf); break; case 'b': case 'B':
--- a/src/lib-mail/quoted-printable.c Sun Jul 26 15:03:30 2009 -0400 +++ b/src/lib-mail/quoted-printable.c Sun Jul 26 16:32:18 2009 -0400 @@ -5,10 +5,88 @@ #include "hex-binary.h" #include "quoted-printable.h" +#define QP_IS_TRAILING_SPACE(c) \ + ((c) == ' ' || (c) == '\t') + void quoted_printable_decode(const unsigned char *src, size_t src_size, size_t *src_pos_r, buffer_t *dest) { char hexbuf[3]; + size_t src_pos, pos, next; + + hexbuf[2] = '\0'; + + next = 0; + for (src_pos = 0; src_pos < src_size; src_pos++) { + if (src[src_pos] != '=' && src[src_pos] != '\n') + continue; + + if (src[src_pos] == '\n') { + /* drop trailing whitespace */ + pos = src_pos; + if (pos > 0 && src[pos-1] == '\r') + pos--; + while (pos > 0 && QP_IS_TRAILING_SPACE(src[pos-1])) + pos--; + buffer_append(dest, src + next, pos - next); + next = src_pos+1; + buffer_append(dest, "\r\n", 2); + continue; + } + + /* '=' */ + buffer_append(dest, src + next, src_pos - next); + next = src_pos; + + if (src_pos+1 >= src_size) + break; + + if (src[src_pos+1] == '\n') { + /* =\n -> skip both */ + src_pos += 2; + next += 2; + continue; + } + + if (src_pos+2 >= src_size) + break; + + if (src[src_pos+1] == '\r' && src[src_pos+2] == '\n') { + /* =\r\n -> skip both */ + src_pos += 3; + next += 3; + continue; + } + + /* =<hex> */ + hexbuf[0] = src[src_pos+1]; + hexbuf[1] = src[src_pos+2]; + + if (hex_to_binary(hexbuf, dest) == 0) { + src_pos += 2; + next = src_pos + 1; + } else { + /* non-hex data, show as-is */ + next = src_pos; + } + } + if (src_pos == src_size) { + /* add everything but trailing spaces */ + if (src_pos > 0 && src[src_pos-1] == '\r') + src_pos--; + while (src_pos > 0 && QP_IS_TRAILING_SPACE(src[src_pos-1])) + src_pos--; + buffer_append(dest, src + next, src_pos - next); + next = src_pos; + } + + *src_pos_r = next; +} + +void quoted_printable_q_decode(const unsigned char *src, size_t src_size, + buffer_t *dest) +{ + char hexbuf[3]; size_t src_pos, next; hexbuf[2] = '\0'; @@ -19,32 +97,17 @@ continue; buffer_append(dest, src + next, src_pos - next); - next = src_pos+1; + next = src_pos; if (src[src_pos] == '_') { buffer_append_c(dest, ' '); - continue; - } - - if (src_pos+1 >= src_size) - break; - - if (src[src_pos+1] == '\n') { - /* =\n -> skip both */ - src_pos++; + next++; continue; } if (src_pos+2 >= src_size) break; - if (src[src_pos+1] == '\r' && src[src_pos+2] == '\n') { - /* =\r\n -> skip both */ - src_pos += 2; - next++; - continue; - } - /* =<hex> */ hexbuf[0] = src[src_pos+1]; hexbuf[1] = src[src_pos+2]; @@ -57,9 +120,5 @@ next = src_pos; } } - buffer_append(dest, src + next, src_size - next); - - if (src_pos_r != NULL) - *src_pos_r = src_pos; }
--- a/src/lib-mail/quoted-printable.h Sun Jul 26 15:03:30 2009 -0400 +++ b/src/lib-mail/quoted-printable.h Sun Jul 26 16:32:18 2009 -0400 @@ -5,9 +5,11 @@ size of src, and may be same as src. Decoding errors are ignored. This function may be called multiple times for parsing the same stream. - If src_pos is non-NULL, it's updated to first non-translated character in - src. */ + src_pos is updated to first non-translated character in src. */ void quoted_printable_decode(const unsigned char *src, size_t src_size, size_t *src_pos_r, buffer_t *dest); +/* Decode MIME "Q" encoding. */ +void quoted_printable_q_decode(const unsigned char *src, size_t src_size, + buffer_t *dest); #endif