Mercurial > dovecot > core-2.2
changeset 18488:aa8786771490
lib-mail: Fixed modifying headers with i_stream_header_filter_add()
If the stream was read twice, the second time the callback wasn't called and
the header wasn't modified.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 28 Apr 2015 14:20:39 +0200 |
parents | 86f535375750 |
children | e00f9e93a9a3 |
files | src/lib-mail/istream-header-filter.c src/lib-mail/test-istream-header-filter.c |
diffstat | 2 files changed, 62 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-mail/istream-header-filter.c Tue Apr 28 11:27:04 2015 +0200 +++ b/src/lib-mail/istream-header-filter.c Tue Apr 28 14:20:39 2015 +0200 @@ -31,6 +31,7 @@ unsigned int header_read:1; unsigned int seen_eoh:1; unsigned int header_parsed:1; + unsigned int headers_edited:1; unsigned int exclude:1; unsigned int crlf:1; unsigned int crlf_preserve:1; @@ -209,14 +210,17 @@ bsearch_strcasecmp) != NULL; if (mstream->callback == NULL) { /* nothing gets excluded */ - } else if (mstream->cur_line > mstream->parsed_lines) { - /* first time in this line */ + } else if (mstream->cur_line > mstream->parsed_lines || + mstream->headers_edited) { + /* first time in this line or we have actually modified + the header so we always want to call the callbacks */ bool orig_matched = matched; mstream->parsed_lines = mstream->cur_line; mstream->callback(mstream, hdr, &matched, mstream->context); - if (matched != orig_matched) { + if (matched != orig_matched && + !mstream->headers_edited) { i_array_init(&mstream->match_change_lines, 8); array_append(&mstream->match_change_lines, &mstream->cur_line, 1); @@ -583,4 +587,5 @@ const void *data, size_t size) { buffer_append(input->hdr_buf, data, size); + input->headers_edited = TRUE; }
--- a/src/lib-mail/test-istream-header-filter.c Tue Apr 28 11:27:04 2015 +0200 +++ b/src/lib-mail/test-istream-header-filter.c Tue Apr 28 14:20:39 2015 +0200 @@ -68,6 +68,59 @@ test_end(); } +static void ATTR_NULL(3) +edit_callback(struct header_filter_istream *input, + struct message_header_line *hdr, + bool *matched, void *context ATTR_UNUSED) +{ + if (hdr != NULL && strcasecmp(hdr->name, "To") == 0) { + /* modify To header */ + const char *new_to = "To: 123\n"; + *matched = TRUE; + i_stream_header_filter_add(input, new_to, strlen(new_to)); + } +} + +static void test_istream_edit(void) +{ + const char *input = "From: foo\nTo: bar\n\nhello world\n"; + const char *output = "From: foo\nTo: 123\n\nhello world\n"; + struct istream *istream, *filter; + unsigned int i, input_len = strlen(input); + unsigned int output_len = strlen(output); + const unsigned char *data; + size_t size; + + test_begin("i_stream_create_header_filter(edit)"); + istream = test_istream_create(input); + filter = i_stream_create_header_filter(istream, + HEADER_FILTER_EXCLUDE | + HEADER_FILTER_NO_CR, + NULL, 0, + edit_callback, (void *)NULL); + for (i = 1; i < input_len; i++) { + test_istream_set_size(istream, i); + test_assert(i_stream_read(filter) >= 0); + } + test_istream_set_size(istream, input_len); + test_assert(i_stream_read(filter) > 0); + test_assert(i_stream_read(filter) == -1); + + data = i_stream_get_data(filter, &size); + test_assert(size == output_len && memcmp(data, output, size) == 0); + + i_stream_skip(filter, size); + i_stream_seek(filter, 0); + while (i_stream_read(filter) > 0) ; + data = i_stream_get_data(filter, &size); + test_assert(size == output_len && memcmp(data, output, size) == 0); + + i_stream_unref(&filter); + i_stream_unref(&istream); + + test_end(); +} + static void test_istream_end_body_with_lf(void) { static const char *empty_strarray[] = { NULL }; @@ -131,6 +184,7 @@ { static void (*test_functions[])(void) = { test_istream_filter, + test_istream_edit, test_istream_end_body_with_lf, NULL };