summaryrefslogtreecommitdiff
path: root/imap4d
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2017-12-16 22:55:31 +0200
committerSergey Poznyakoff <gray@gnu.org>2017-12-16 23:18:13 +0200
commitbd385c4a2d26215e080d6248435c9efe3bd1d0b1 (patch)
treed2fe1911109eae8221f7f638f5b3b2f58e845615 /imap4d
parent9d4dbe87b36ab7df8a9e00d47869ab251e404a19 (diff)
downloadmailutils-bd385c4a2d26215e080d6248435c9efe3bd1d0b1.tar.gz
mailutils-bd385c4a2d26215e080d6248435c9efe3bd1d0b1.tar.bz2
Fix the operation of CRLF and CRLFDOT filters.
When encoding, these filters used to retain any existing CRLF sequences untouched on output. As a result, it was not possible to predict the number of characters output having the number of characters and number of lines on input. Due to this imap4d fetch would produce invalid literal output on FETCH command if the requested stream (usually body), contained a mixture of LF and CRLF terminated lines. Moreover, encode + decode operations would not be idempotent in this case. To fix this, the default behavior of CRLF and CRLFDOT filter in encode mode is changed to translate each LF to CRLF, no matter what the prior character was. To invoke the former "normalizing" behavior, the "-n" option argument is provided for mu_filter_create_args. * imap4d/fetch.c (fetch_io): Use raw stream when possible. Use a temporary CRLF translator to ensure proper positioning if start offset is specified. This is suboptimal (to say the very least) and will be fixed as soon as possible. * imap4d/io.c (io_enable_crlf): New funcition (hopefully temporary). * libmailutils/filter/crlfdot.c: When encoding, retain input CRLF only if the -n option was used when creating the filter. Otherwise, translate it to CRCRLF. * libmailutils/filter/crlfflt.c: Likewise. * libmailutils/stream/fltstream.c (filter_read): Make sure mu_filter_lastbuf is always emitted prior to closing the filter. (filter_seek): Clear flag_eof. * libmailutils/tests/Makefile.am (noinst_PROGRAMS): Add dump and tocrlf. * libmailutils/tests/crlf.at: New test case. * libmailutils/tests/crlfdot.at: New test case. * libmailutils/tests/dump.c: New auxiliary program. * libmailutils/tests/tocrlf.c: Likewise. * libmailutils/tests/testsuite.at (MU_FILTER_TEST_NIBBLE) (MU_FILTER_TEST): New defines.
Diffstat (limited to 'imap4d')
-rw-r--r--imap4d/fetch.c33
-rw-r--r--imap4d/io.c8
2 files changed, 29 insertions, 12 deletions
diff --git a/imap4d/fetch.c b/imap4d/fetch.c
index 5efcda3a0..7a1912190 100644
--- a/imap4d/fetch.c
+++ b/imap4d/fetch.c
@@ -709,18 +709,11 @@ fetch_send_section_part (struct fetch_function_closure *ffc,
static int
fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
{
- mu_stream_t rfc = NULL;
-
- size_t n = 0;
-
- mu_filter_create (&rfc, stream, "CRLF", MU_FILTER_ENCODE,
- MU_STREAM_READ|MU_STREAM_SEEK);
-
if (start == 0 && size == (size_t) -1)
{
int rc;
- rc = mu_stream_seek (rfc, 0, MU_SEEK_SET, NULL);
+ rc = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
if (rc)
{
mu_error ("seek error: %s", mu_stream_strerror (stream, rc));
@@ -729,7 +722,7 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
if (max)
{
io_sendf (" {%lu}\n", (unsigned long) max);
- io_copy_out (rfc, max);
+ io_copy_out (stream, max);
/* FIXME: Make sure exactly max bytes were sent */
}
else
@@ -742,10 +735,12 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
}
else
{
+ mu_stream_t rfc = NULL;
int rc;
char *buffer, *p;
size_t total = 0;
-
+ size_t n = 0;
+
if (size > max)
size = max;
if (size + 2 < size) /* Check for integer overflow */
@@ -754,6 +749,9 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
return RESP_BAD;
}
+ mu_filter_create (&rfc, stream, "CRLF", MU_FILTER_ENCODE,
+ MU_STREAM_READ|MU_STREAM_SEEK);
+
p = buffer = mu_alloc (size + 1);
rc = mu_stream_seek (rfc, start, MU_SEEK_SET, NULL);
@@ -766,24 +764,35 @@ fetch_io (mu_stream_t stream, size_t start, size_t size, size_t max)
}
while (total < size
- && mu_stream_read (rfc, p, size - total, &n) == 0
+ && (rc = mu_stream_read (rfc, p, size - total, &n)) == 0
&& n > 0)
{
total += n;
p += n;
}
+
+ if (rc)
+ {
+ mu_error ("read error: %s", mu_stream_strerror (rfc, rc));
+ free (buffer);
+ mu_stream_destroy (&rfc);
+ return RESP_BAD;
+ }
+
*p = 0;
io_sendf ("<%lu>", (unsigned long) start);
if (total)
{
io_sendf (" {%lu}\n", (unsigned long) total);
+ io_enable_crlf (0);
io_send_bytes (buffer, total);
+ io_enable_crlf (1);
}
else
io_sendf (" \"\"");
free (buffer);
+ mu_stream_destroy (&rfc);
}
- mu_stream_destroy (&rfc);
return RESP_OK;
}
diff --git a/imap4d/io.c b/imap4d/io.c
index b1c1d7d04..9a2047419 100644
--- a/imap4d/io.c
+++ b/imap4d/io.c
@@ -727,3 +727,11 @@ imap4d_tokbuf_from_string (char *str)
return tok;
}
+void
+io_enable_crlf (int enable)
+{
+ enable = !enable;
+ mu_stream_ioctl (iostream, MU_IOCTL_FILTER,
+ MU_IOCTL_FILTER_SET_DISABLED,
+ &enable);
+}

Return to:

Send suggestions and report system problems to the System administrator.