summaryrefslogtreecommitdiff
path: root/mailbox
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2003-03-27 21:35:06 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2003-03-27 21:35:06 +0000
commitcaeb09a20e112766b486af17407861bc6526254c (patch)
tree246fed4d42f33081ab64884af2150ed870df5f18 /mailbox
parent6039d2007f9118629016b04df97b5d3b5bea12ee (diff)
downloadmailutils-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.c230
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;
}

Return to:

Send suggestions and report system problems to the System administrator.