From: Timo Sirainen Date: Tue, 3 May 2016 14:25:07 +0000 (+0300) Subject: lib-mail: istream-header-filter HEADER_FILTER_ADD_MISSING_EOH fixes X-Git-Tag: 2.3.0.rc1~3857 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=10d2dbb8343d9f7a294519224e5e08e1c13e7453;p=thirdparty%2Fdovecot%2Fcore.git lib-mail: istream-header-filter HEADER_FILTER_ADD_MISSING_EOH fixes When using HEADER_FILTER_CRLF_PRESERVE, add CR to the EOH if the previous header line ended with CRLF. When header ends to a header without newline, add two newlines so we can get the actual EOH added. --- diff --git a/src/lib-mail/istream-header-filter.c b/src/lib-mail/istream-header-filter.c index 0a6c9a2fe1..400180d20f 100644 --- a/src/lib-mail/istream-header-filter.c +++ b/src/lib-mail/istream-header-filter.c @@ -38,6 +38,8 @@ struct header_filter_istream { unsigned int add_missing_eoh:1; unsigned int end_body_with_lf:1; unsigned int last_lf_added:1; + unsigned int last_orig_crlf:1; + unsigned int last_added_newline:1; unsigned int eoh_not_matched:1; unsigned int prev_matched:1; }; @@ -133,6 +135,8 @@ static void add_eol(struct header_filter_istream *mstream, bool orig_crlf) buffer_append(mstream->hdr_buf, "\r\n", 2); else buffer_append_c(mstream->hdr_buf, '\n'); + mstream->last_orig_crlf = orig_crlf; + mstream->last_added_newline = TRUE; } static ssize_t hdr_stream_update_pos(struct header_filter_istream *mstream) @@ -284,6 +288,11 @@ static ssize_t read_header(struct header_filter_istream *mstream) if (mstream->hdr_buf->used >= mstream->istream.max_buffer_size) break; } + if (mstream->hdr_buf->used > 0) { + const unsigned char *data = mstream->hdr_buf->data; + mstream->last_added_newline = + data[mstream->hdr_buf->used-1] == '\n'; + } if (hdr_ret < 0) { if (mstream->istream.parent->stream_errno != 0) { @@ -295,7 +304,9 @@ static ssize_t read_header(struct header_filter_istream *mstream) } if (!mstream->seen_eoh && mstream->add_missing_eoh) { mstream->seen_eoh = TRUE; - add_eol(mstream, FALSE); + if (!mstream->last_added_newline) + add_eol(mstream, mstream->last_orig_crlf); + add_eol(mstream, mstream->last_orig_crlf); } } diff --git a/src/lib-mail/test-istream-header-filter.c b/src/lib-mail/test-istream-header-filter.c index 6c1357c524..0f92ecbfd1 100644 --- a/src/lib-mail/test-istream-header-filter.c +++ b/src/lib-mail/test-istream-header-filter.c @@ -349,6 +349,42 @@ static void test_istream_end_body_with_lf(void) test_end(); } +static void test_istream_add_missing_eoh(void) +{ + struct { + const char *input; + const char *output; + unsigned int extra; + } tests[] = { + { "From: foo", "From: foo\n\n", 1 }, + { "From: foo\n", "From: foo\n\n", 1 }, + { "From: foo\n\n", "From: foo\n\n", 1 }, + { "From: foo\n\nbar", "From: foo\n\nbar", 0 }, + { "From: foo\r\n", "From: foo\r\n\r\n", 1 }, + { "From: foo\r\n\r\n", "From: foo\r\n\r\n", 0 }, + { "From: foo\r\n\r\nbar", "From: foo\r\n\r\nbar", 0 } + }; + struct istream *istream, *filter; + unsigned int i; + + test_begin("i_stream_create_header_filter(add_missing_eoh)"); + for (i = 0; i < N_ELEMENTS(tests); i++) { + istream = test_istream_create(tests[i].input); + filter = i_stream_create_header_filter(istream, + HEADER_FILTER_EXCLUDE | + HEADER_FILTER_CRLF_PRESERVE | + HEADER_FILTER_ADD_MISSING_EOH, + NULL, 0, + *null_header_filter_callback, (void *)NULL); + test_istream_run(istream, filter, + strlen(tests[i].input) + tests[i].extra, + tests[i].output); + i_stream_unref(&filter); + i_stream_unref(&istream); + } + test_end(); +} + static void ATTR_NULL(3) strip_eoh_callback(struct header_filter_istream *input ATTR_UNUSED, struct message_header_line *hdr, @@ -383,6 +419,7 @@ int main(void) test_istream_filter_large_buffer, test_istream_callbacks, test_istream_edit, + test_istream_add_missing_eoh, test_istream_end_body_with_lf, test_istream_strip_eoh, NULL