test-istream-header-filter.c revision 270c7cd669b1ad4b69edb366dc5f22262948bfed
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2007-2016 Dovecot authors, see the included COPYING file */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "lib.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "str.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "istream.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "message-header-parser.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "istream-header-filter.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "test-common.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainentest_istream_run(struct istream *test_istream, struct istream *filter,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen unsigned int input_len, const char *output)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen unsigned int i, output_len = strlen(output);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const unsigned char *data;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen size_t size;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen for (i = 1; i < input_len; i++) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_istream_set_size(test_istream, i);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(i_stream_read(filter) >= 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_istream_set_size(test_istream, input_len);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(i_stream_read(filter) > 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(i_stream_read(filter) == -1);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen data = i_stream_get_data(filter, &size);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(size == output_len && memcmp(data, output, size) == 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* run again to make sure it's still correct the second time */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_skip(filter, size);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_stream_seek(filter, 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen while (i_stream_read(filter) > 0) ;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen data = i_stream_get_data(filter, &size);
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen test_assert(size == output_len && memcmp(data, output, size) == 0);
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen}
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainenstatic void ATTR_NULL(3)
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainenfilter_callback(struct header_filter_istream *input ATTR_UNUSED,
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen struct message_header_line *hdr,
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen bool *matched, void *context ATTR_UNUSED)
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen{
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen if (hdr != NULL && (hdr->name_offset == 0 ||
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen strcmp(hdr->name, "X-Drop") == 0)) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* drop 1) first header, 2) X-Drop header */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *matched = TRUE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainenstatic void test_istream_filter(void)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen static const char *exclude_headers[] = { "Subject", "To" };
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *input = "From: foo\nFrom: abc\nTo: bar\nSubject: plop\nX-Drop: 1\n\nhello world\n";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *output = "From: abc\n\nhello world\n";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct istream *istream, *filter, *filter2;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen unsigned int i, input_len = strlen(input);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen unsigned int output_len = strlen(output);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const unsigned char *data;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen size_t size;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_begin("i_stream_create_header_filter(exclude)");
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen istream = test_istream_create(input);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen filter = i_stream_create_header_filter(istream,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen HEADER_FILTER_EXCLUDE |
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen HEADER_FILTER_NO_CR,
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen exclude_headers,
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen N_ELEMENTS(exclude_headers),
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen filter_callback, (void *)NULL);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen filter2 = i_stream_create_header_filter(filter,
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen HEADER_FILTER_EXCLUDE |
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen HEADER_FILTER_NO_CR,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen exclude_headers,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen N_ELEMENTS(exclude_headers),
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen *null_header_filter_callback,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen (void *)NULL);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&filter);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen filter = filter2;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen for (i = 1; i < input_len; i++) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_istream_set_size(istream, i);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(i_stream_read(filter) >= 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_istream_set_size(istream, input_len);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(i_stream_read(filter) > 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(i_stream_read(filter) == -1);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c72d5f1aa95544dbfbc66d72bfa3205f8876d91cTimo Sirainen data = i_stream_get_data(filter, &size);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(size == output_len && memcmp(data, output, size) == 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_stream_skip(filter, size);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_seek(filter, 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen while (i_stream_read(filter) > 0) ;
ab8cf8fb93579981a687942e53bdb361b3b61bafTimo Sirainen data = i_stream_get_data(filter, &size);
ab8cf8fb93579981a687942e53bdb361b3b61bafTimo Sirainen test_assert(size == output_len && memcmp(data, output, size) == 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&filter);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&istream);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_end();
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void add_random_text(string_t *dest, unsigned int count)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen unsigned int i;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen for (i = 0; i < count; i++)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_append_c(dest, rand() % ('z'-'a'+1) + 'a');
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void ATTR_NULL(3)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenfilter2_callback(struct header_filter_istream *input ATTR_UNUSED,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct message_header_line *hdr,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen bool *matched, void *context ATTR_UNUSED)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (hdr != NULL && strcmp(hdr->name, "To") == 0)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen *matched = TRUE;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void test_istream_filter_large_buffer(void)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen string_t *input, *output;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct istream *istream, *filter;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const unsigned char *data;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen size_t size, prefix_len;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *p;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen unsigned int i;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_begin("i_stream_create_header_filter(large buffer)");
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen input = str_new(default_pool, 1024*128);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen output = str_new(default_pool, 1024*128);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_append(input, "From: ");
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen add_random_text(input, 1024*31);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_append(input, "\nTo: ");
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen add_random_text(input, 1024*32);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_append(input, "\nSubject: ");
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen add_random_text(input, 1024*34);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen str_append(input, "\n\nbody\n");
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen istream = test_istream_create_data(str_data(input), str_len(input));
b42697a5749b85659a24316d97f1c208d469e4e8Timo Sirainen test_istream_set_max_buffer_size(istream, 8192);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
9e9f0cf3cc3ce546e8a433990c92dd9be6665df6Timo Sirainen filter = i_stream_create_header_filter(istream,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen HEADER_FILTER_EXCLUDE |
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen HEADER_FILTER_NO_CR,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen NULL, 0,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen filter2_callback,
b42697a5749b85659a24316d97f1c208d469e4e8Timo Sirainen (void *)NULL);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen for (i = 0; i < 2; i++) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen for (;;) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ssize_t ret = i_stream_read(filter);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(ret != 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (ret == -1)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen break;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (ret == -2) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen data = i_stream_get_data(filter, &size);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_append_n(output, data, size);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_skip(filter, size);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen data = i_stream_get_data(filter, &size);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(size <= 8192);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_append_n(output, data, size);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen p = strstr(str_c(input), "To: ");
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_assert(p != NULL);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen prefix_len = p - str_c(input);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(strncmp(str_c(input), str_c(output), prefix_len) == 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen p = strchr(p, '\n');
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_assert(p != NULL);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(strcmp(p+1, str_c(output) + prefix_len) == 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* seek back and retry once with caching and different
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen buffer size */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_seek(filter, 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_truncate(output, 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_istream_set_max_buffer_size(istream, 4096);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_free(&input);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_free(&output);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&filter);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&istream);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_end();
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenfilter3_callback(struct header_filter_istream *input ATTR_UNUSED,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct message_header_line *hdr,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen bool *matched ATTR_UNUSED, string_t *dest)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (hdr != NULL)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen message_header_line_write(dest, hdr);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void test_istream_callbacks(void)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen string_t *input, *output;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct istream *istream, *filter;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen unsigned int i;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_begin("i_stream_create_header_filter(callbacks)");
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen input = str_new(default_pool, 1024*128);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen output = str_new(default_pool, 1024*128);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_append(input, "From: first line\n ");
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen add_random_text(input, 1024*31);
71c4ac143fefd57aeec6298489c4559b6f13c67bTimo Sirainen str_append(input, "\nTo: first line\n\tsecond line\n\t");
71c4ac143fefd57aeec6298489c4559b6f13c67bTimo Sirainen add_random_text(input, 1024*32);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_append(input, "\n last line\nSubject: ");
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen add_random_text(input, 1024*34);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_append(input, "\n");
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen istream = test_istream_create_data(str_data(input), str_len(input));
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_istream_set_max_buffer_size(istream, 8192);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen filter = i_stream_create_header_filter(istream,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen HEADER_FILTER_EXCLUDE |
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen HEADER_FILTER_NO_CR,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen NULL, 0,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen filter3_callback,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen output);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* callback should be called exactly once for all the header input */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen for (i = 0; i < 2; i++) {
4321f6c969e7b8f6b243ff5bb6b8d297921676f6Timo Sirainen while (i_stream_read(filter) != -1)
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_stream_skip(filter, i_stream_get_data_size(filter));
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(strcmp(str_c(output), str_c(input)) == 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_free(&input);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_free(&output);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&filter);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&istream);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_end();
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void ATTR_NULL(3)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenedit_callback(struct header_filter_istream *input,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct message_header_line *hdr,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen bool *matched, void *context ATTR_UNUSED)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (hdr != NULL && strcasecmp(hdr->name, "To") == 0) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* modify To header */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *new_to = "To: 123\n";
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen *matched = TRUE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_stream_header_filter_add(input, new_to, strlen(new_to));
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void test_istream_edit(void)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen const char *input = "From: foo\nTo: bar\n\nhello world\n";
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen const char *output = "From: foo\nTo: 123\n\nhello world\n";
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct istream *istream, *filter;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_begin("i_stream_create_header_filter(edit)");
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen istream = test_istream_create(input);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen filter = i_stream_create_header_filter(istream,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen HEADER_FILTER_EXCLUDE |
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen HEADER_FILTER_NO_CR,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen NULL, 0,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen edit_callback, (void *)NULL);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_istream_run(istream, filter, strlen(input), output);
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen i_stream_unref(&filter);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&istream);
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen test_end();
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainenstatic void test_istream_end_body_with_lf(void)
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *input = "From: foo\n\nhello world";
7230352f1177a8ed2b924c6992e751fd2ab9bc27Timo Sirainen const char *output = "From: foo\n\nhello world\n";
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct istream *istream, *filter;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen unsigned int i, input_len = strlen(input);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen unsigned int output_len = strlen(output);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const unsigned char *data;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen string_t *str = t_str_new(64);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen size_t size;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_begin("i_stream_create_header_filter(end_body_with_lf)");
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen istream = test_istream_create(input);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen filter = i_stream_create_header_filter(istream,
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainen HEADER_FILTER_EXCLUDE |
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen HEADER_FILTER_NO_CR |
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainen HEADER_FILTER_END_BODY_WITH_LF,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen NULL, 0,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen *null_header_filter_callback,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen (void *)NULL);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen for (i = 1; i < input_len; i++) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_istream_set_size(istream, i);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(i_stream_read(filter) >= 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_istream_set_size(istream, input_len);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(i_stream_read(filter) > 0);
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen test_assert(i_stream_read(filter) > 0);
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen test_assert(i_stream_read(filter) == -1);
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen data = i_stream_get_data(filter, &size);
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen test_assert(size == output_len && memcmp(data, output, size) == 0);
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen i_stream_skip(filter, size);
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen i_stream_seek(filter, 0);
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen for (i = 1; i < input_len; i++) {
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen test_istream_set_size(istream, i);
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen test_assert(i_stream_read(filter) >= 0);
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen data = i_stream_get_data(filter, &size);
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen str_append_n(str, data, size);
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen i_stream_skip(filter, size);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c2ced58969b446666ab1067c6bfdf495367ed621Timo Sirainen test_istream_set_size(istream, input_len);
c2ced58969b446666ab1067c6bfdf495367ed621Timo Sirainen test_assert(i_stream_read(filter) == 1);
c2ced58969b446666ab1067c6bfdf495367ed621Timo Sirainen test_assert(i_stream_read(filter) == 1);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(i_stream_read(filter) == -1);
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainen
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainen data = i_stream_get_data(filter, &size);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_append_n(str, data, size);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_assert(strcmp(str_c(str), output) == 0);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&filter);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&istream);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_end();
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void ATTR_NULL(3)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstrip_eoh_callback(struct header_filter_istream *input ATTR_UNUSED,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct message_header_line *hdr,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen bool *matched, void *context ATTR_UNUSED)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (hdr != NULL && hdr->eoh)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *matched = FALSE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic void test_istream_strip_eoh(void)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *input = "From: foo\nTo: bar\n\nhello world\n";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *output = "From: foo\nTo: bar\nhello world\n";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct istream *istream, *filter;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_begin("i_stream_create_header_filter(edit)");
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen istream = test_istream_create(input);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen filter = i_stream_create_header_filter(istream,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen HEADER_FILTER_EXCLUDE | HEADER_FILTER_NO_CR, NULL, 0,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen strip_eoh_callback, (void *)NULL);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_istream_run(istream, filter, strlen(input), output);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&filter);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen i_stream_unref(&istream);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_end();
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint main(void)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
a2a08c191a33bfaa758f9c68cafec2521b9a4472Timo Sirainen static void (*test_functions[])(void) = {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_istream_filter,
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen test_istream_filter_large_buffer,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_istream_callbacks,
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen test_istream_edit,
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen test_istream_end_body_with_lf,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen test_istream_strip_eoh,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen NULL
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen };
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return test_run(test_functions);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen