diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2003-03-27 21:35:06 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2003-03-27 21:35:06 +0000 |
commit | caeb09a20e112766b486af17407861bc6526254c (patch) | |
tree | 246fed4d42f33081ab64884af2150ed870df5f18 /mailbox | |
parent | 6039d2007f9118629016b04df97b5d3b5bea12ee (diff) | |
download | mailutils-caeb09a20e112766b486af17407861bc6526254c.tar.gz mailutils-caeb09a20e112766b486af17407861bc6526254c.tar.bz2 |
(_hexdigits): Must be zero-terminated,
otherwise the native Darwin linker refuses to load it.
(qp_decode): Bugfix: in accordance with rfc1892 a sequence
of whitespace is allowed in an encoded string provided that
it is followed by a printable character.
(qp_encode): Preserve trailing whitespace.
Diffstat (limited to 'mailbox')
-rw-r--r-- | mailbox/filter_trans.c | 230 |
1 files changed, 137 insertions, 93 deletions
diff --git a/mailbox/filter_trans.c b/mailbox/filter_trans.c index f8b2dc039..ab1f196f8 100644 --- a/mailbox/filter_trans.c +++ b/mailbox/filter_trans.c @@ -251,7 +251,7 @@ base64_init (filter_t filter) return ENOMEM; ts->min_size = 4; - ts->s_buf = calloc (4, 1); + ts->s_buf = calloc (ts->min_size, 1); if (ts->s_buf == NULL) { free (ts); @@ -348,7 +348,10 @@ base64_encode (const char *iptr, size_t isize, char *optr, size_t osize, /*------------------------------------------------------ * quoted-printable decoder/encoder *------------------------------------------------------*/ -static const char _hexdigits[16] = "0123456789ABCDEF"; +static const char _hexdigits[] = "0123456789ABCDEF"; + +#define QP_LINE_MAX 76 +#define ISWS(c) ((c)==' ' || (c)=='\t') static int qp_init (filter_t filter) @@ -358,8 +361,8 @@ qp_init (filter_t filter) if (ts == NULL) return ENOMEM; - ts->min_size = 4; - ts->s_buf = calloc (4, 1); + ts->min_size = QP_LINE_MAX; + ts->s_buf = calloc (ts->min_size, 1); if (ts->s_buf == NULL) { free (ts); @@ -380,80 +383,121 @@ qp_decode (const char *iptr, size_t isize, char *optr, size_t osize, char c; int last_char = 0; size_t consumed = 0; - + size_t wscount = 0; + *nbytes = 0; while (consumed < isize && *nbytes < osize) { c = *iptr++; - if (c == '=') + + if (ISWS (c)) { - /* There must be 2 more characters before I consume this. */ - if ((consumed + 2) >= isize) - return consumed; - else + wscount++; + consumed++; + } + else + { + /* Octets with values of 9 and 32 MAY be + represented as US-ASCII TAB (HT) and SPACE characters, + respectively, but MUST NOT be so represented at the end + of an encoded line. Any TAB (HT) or SPACE characters + on an encoded line MUST thus be followed on that line + by a printable character. */ + + if (wscount) { - /* you get =XX where XX are hex characters. */ - char chr[3]; - int new_c; - - chr[3] = 0; - chr[0] = *iptr++; - /* Ignore LF. */ - if (chr[0] != '\n') + if (c != '\r' && c != '\n') { - chr[1] = *iptr++; - new_c = strtoul (chr, NULL, 16); - *optr++ = new_c; - (*nbytes)++; - consumed += 3; + size_t sz; + + if (consumed >= isize) + break; + + if (*nbytes + wscount > osize) + sz = osize - *nbytes; + else + sz = wscount; + memcpy (optr, iptr - wscount - 1, sz); + optr += sz; + (*nbytes) += sz; + if (wscount > sz) + { + wscount -= sz; + break; + } } + wscount = 0; + } + + if (c == '=') + { + /* There must be 2 more characters before I consume this. */ + if (consumed + 2 >= isize) + break; else - consumed += 2; + { + /* you get =XX where XX are hex characters. */ + char chr[3]; + int new_c; + + chr[3] = 0; + chr[0] = *iptr++; + /* Ignore LF. */ + if (chr[0] != '\n') + { + chr[1] = *iptr++; + new_c = strtoul (chr, NULL, 16); + *optr++ = new_c; + (*nbytes)++; + consumed += 3; + } + else + consumed += 2; + } } - } - /* CR character. */ - else if (c == '\r') - { - /* There must be at least 1 more character before I consume this. */ - if ((consumed + 1) >= isize ) - return (consumed); - else + /* CR character. */ + else if (c == '\r') { - iptr++; /* Skip the CR character. */ - *optr++ = '\n'; - (*nbytes)++; - consumed += 2; + /* There must be at least 1 more character before + I consume this. */ + if (consumed + 1 >= isize) + break; + else + { + iptr++; /* Skip the CR character. */ + *optr++ = '\n'; + (*nbytes)++; + consumed += 2; + } } - } - else if ((c == 9) || (c == 32)) - { - if ((last_char == 9) || (last_char == 32)) - consumed++; else { *optr++ = c; (*nbytes)++; consumed++; } - } - else - { - *optr++ = c; - (*nbytes)++; - consumed++; - } + } last_char = c; } - return consumed; + return consumed - wscount; } +#define SOFTBRK() \ + /* check if we have enough room for the soft linebreak */\ + if (*nbytes + 2 > osize) \ + break;\ + *optr++ = '=';\ + *optr++ = '\n';\ + (*nbytes) += 2;\ + *line_len = 0; + static int qp_encode (const char *iptr, size_t isize, char *optr, size_t osize, size_t *nbytes, int *line_len) { -#define QP_LINE_MAX 76 - int c; + unsigned int c; size_t consumed = 0; + size_t wscount = 0; *nbytes = 0; @@ -464,28 +508,37 @@ qp_encode (const char *iptr, size_t isize, char *optr, size_t osize, while (consumed < isize) { - if (*line_len == QP_LINE_MAX) + int simple_char; + + /* candidate byte to convert */ + c = *(unsigned char*) iptr; + simple_char = (c >= 32 && c <= 60) + || (c >= 62 && c <= 126) + || c == '\t' + || c == '\n'; + + if (*line_len == QP_LINE_MAX + || (c == '\n' && consumed && ISWS (optr[-1])) + || (!simple_char && *line_len >= (QP_LINE_MAX - 3))) { /* to cut a qp line requires two bytes */ - if ((*nbytes) + 2 > osize) - return consumed; + if (*nbytes + 2 > osize) + break; *optr++ = '='; *optr++ = '\n'; (*nbytes) += 2; *line_len = 0; } - - /* candidate byte to convert */ - c = *iptr; - - if (((c >= 32) && (c <= 60)) || - ((c >= 62) && (c <= 126)) || - (c == 9)) + + if (ISWS (c)) + wscount++; + + if (simple_char) { /* a non-quoted character uses up one byte */ if (*nbytes + 1 > osize) - return consumed; + break; *optr++ = c; (*nbytes)++; @@ -493,43 +546,34 @@ qp_encode (const char *iptr, size_t isize, char *optr, size_t osize, iptr++; consumed++; + + if (!ISWS (c)) + wscount = 0; + + if (c == '\n') + *line_len = 0; } else { - /* can we store the quoted character in the remaining of the - line ? */ - if (*line_len >= (QP_LINE_MAX - 3)) - { - /* check if we have enough room to store the padding */ - if (*nbytes + *line_len - QP_LINE_MAX + 3 > osize) - return consumed; - - /* add spaces. */ - while (*line_len < QP_LINE_MAX) - { - *optr++ = ' '; - (*nbytes)++; - (*line_len)++; - } - } - else - { - /* a quoted character uses up three bytes */ - if ((*nbytes) + 3 > osize) - return consumed; + /* a quoted character uses up three bytes */ + if ((*nbytes) + 3 > osize) + break; - *optr++ = '='; - *optr++ = _hexdigits[(c >> 4) & 0xf]; - *optr++ = _hexdigits[c & 0xf]; + *optr++ = '='; + *optr++ = _hexdigits[(c >> 4) & 0xf]; + *optr++ = _hexdigits[c & 0xf]; - (*nbytes) += 3; - (*line_len) += 3; + (*nbytes) += 3; + (*line_len) += 3; - /* we've actuall used up one byte of input */ - iptr ++; - consumed ++; - } + /* we've actuall used up one byte of input */ + iptr++; + consumed++; + wscount = 0; } } - return consumed; + if (wscount) + wscount--; + (*nbytes) -= wscount; + return consumed - wscount; } |