test-message-header-parser.c revision d4488f314d0c799c5f5b8a7890e17eef868f7a2c
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2007-2016 Dovecot authors, see the included COPYING file */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "lib.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "str.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "istream.h"
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen#include "message-size.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "message-header-parser.h"
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen#include "test-common.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#define TEST1_MSG_BODY_LEN 5
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic const char *test1_msg =
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "h1: v1\n"
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen "h2:\n"
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen " v2\r\n"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "h3: \r\n"
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen "\tv3\n"
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen "\tw3\r\n"
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen "\n"
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen " body";
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstatic void
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainentest_message_header_parser_one(struct message_header_parser_ctx *parser,
373492be949e159fda651807b3acda2c5c077027Timo Sirainen enum message_header_parser_flags hdr_flags)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen{
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen struct message_header_line *hdr;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen bool use_full_value;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen use_full_value = hdr_flags != 0;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
373492be949e159fda651807b3acda2c5c077027Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
373492be949e159fda651807b3acda2c5c077027Timo Sirainen test_assert(hdr->name_offset == 0);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP) == 0)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(hdr->full_value_offset == 4);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen else
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(hdr->full_value_offset == 5);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h1") == 0);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP) == 0) {
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(hdr->middle_len == 2 && memcmp(hdr->middle, ": ", 2) == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->value_len == 3 && memcmp(hdr->value, " v1", 3) == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen } else {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->middle_len == 3 && memcmp(hdr->middle, ": ", 3) == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->value_len == 2 && memcmp(hdr->value, "v1", 2) == 0);
635df5b4cbcd7b24c825e01d9dd66d3a4274c4c7Timo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(!hdr->continues && !hdr->continued && !hdr->eoh &&
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen !hdr->no_newline && !hdr->crlf_newline);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->name_offset == 8 && hdr->full_value_offset == 11);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h2") == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->middle_len == 1 && memcmp(hdr->middle, ":", 1) == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->value_len == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->continues && !hdr->continued && !hdr->eoh &&
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen !hdr->no_newline && !hdr->crlf_newline);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (use_full_value) hdr->use_full_value = TRUE;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->name_offset == 8 && hdr->full_value_offset == 11);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h2") == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->middle_len == 1 && memcmp(hdr->middle, ":", 1) == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->value_len == 3 && memcmp(hdr->value, " v2", 3) == 0);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(!hdr->continues && hdr->continued && !hdr->eoh &&
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen !hdr->no_newline && hdr->crlf_newline);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE) != 0) {
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(hdr->full_value_len == 3 &&
635df5b4cbcd7b24c825e01d9dd66d3a4274c4c7Timo Sirainen memcmp(hdr->full_value, " v2", 3) == 0);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen } else if (use_full_value) {
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(hdr->full_value_len == 4 &&
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen memcmp(hdr->full_value, "\n v2", 4) == 0);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen }
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(hdr->name_offset == 17 && hdr->full_value_offset == 21);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h3") == 0);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(hdr->middle_len == 2 && memcmp(hdr->middle, ": ", 2) == 0);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(hdr->value_len == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->continues && !hdr->continued && !hdr->eoh &&
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen !hdr->no_newline && hdr->crlf_newline);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (use_full_value) hdr->use_full_value = TRUE;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->name_offset == 17 && hdr->full_value_offset == 21);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h3") == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->middle_len == 2 && memcmp(hdr->middle, ": ", 2) == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->value_len == 3 && memcmp(hdr->value, "\tv3", 3) == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->continues && hdr->continued && !hdr->eoh &&
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen !hdr->no_newline && !hdr->crlf_newline);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (use_full_value) hdr->use_full_value = TRUE;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE) != 0) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->full_value_len == 3 &&
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen memcmp(hdr->full_value, " v3", 3) == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen } else if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_DROP_CR) != 0) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->full_value_len == 4 &&
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen memcmp(hdr->full_value, "\n\tv3", 4) == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen } else if (use_full_value) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr->full_value_len == 5 &&
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen memcmp(hdr->full_value, "\r\n\tv3", 5) == 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_assert(hdr->name_offset == 17 && hdr->full_value_offset == 21);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h3") == 0);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_assert(hdr->middle_len == 2 && memcmp(hdr->middle, ": ", 2) == 0);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_assert(hdr->value_len == 3 && memcmp(hdr->value, "\tw3", 3) == 0);
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen test_assert(!hdr->continues && hdr->continued && !hdr->eoh &&
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen !hdr->no_newline && hdr->crlf_newline);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE) != 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_assert(hdr->full_value_len == 6 &&
380dbb60ae291cbe39d1f710284562ca9167150bTimo Sirainen memcmp(hdr->full_value, " v3 w3", 6) == 0);
380dbb60ae291cbe39d1f710284562ca9167150bTimo Sirainen } else if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_DROP_CR) != 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_assert(hdr->full_value_len == 8 &&
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen memcmp(hdr->full_value, "\n\tv3\n\tw3", 8) == 0);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else if (use_full_value) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_assert(hdr->full_value_len == 9 &&
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen memcmp(hdr->full_value, "\r\n\tv3\n\tw3", 9) == 0);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen }
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen test_assert(hdr->name_offset == 32 && hdr->full_value_offset == 32);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen test_assert(hdr->name_len == 0 && hdr->middle_len == 0 && hdr->value_len == 0);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen test_assert(!hdr->continues && !hdr->continued && hdr->eoh &&
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen !hdr->no_newline && !hdr->crlf_newline);
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(message_parse_header_next(parser, &hdr) < 0);
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainenstatic void test_message_header_parser(void)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen static enum message_header_parser_flags max_hdr_flags =
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP |
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen MESSAGE_HEADER_PARSER_FLAG_DROP_CR |
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE;
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen enum message_header_parser_flags hdr_flags;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct message_header_parser_ctx *parser;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct message_size hdr_size;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct istream *input;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_begin("message header parser");
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen input = test_istream_create(test1_msg);
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen for (hdr_flags = 0; hdr_flags <= max_hdr_flags; hdr_flags++) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_stream_seek(input, 0);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen parser = message_parse_header_init(input, &hdr_size, hdr_flags);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_message_header_parser_one(parser, hdr_flags);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen message_parse_header_deinit(&parser);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen test_assert(hdr_size.physical_size == strlen(test1_msg)-TEST1_MSG_BODY_LEN);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen test_assert(hdr_size.virtual_size == strlen(test1_msg) - TEST1_MSG_BODY_LEN + 4);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen i_stream_unref(&input);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen test_end();
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen}
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainenstatic void hdr_write(string_t *str, struct message_header_line *hdr)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen if (!hdr->continued) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen str_append(str, hdr->name);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (hdr->middle_len > 0)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen str_append_n(str, hdr->middle, hdr->middle_len);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen }
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen str_append_n(str, hdr->value, hdr->value_len);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen if (!hdr->no_newline) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (hdr->crlf_newline)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen str_append_c(str, '\r');
57d2429fae575e96ca276355af675deb66b76d00Timo Sirainen str_append_c(str, '\n');
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
57d2429fae575e96ca276355af675deb66b76d00Timo Sirainenstatic void test_message_header_parser_partial(void)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct message_header_parser_ctx *parser;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct message_header_line *hdr;
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen struct istream *input;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen unsigned int i, max = (strlen(test1_msg)-TEST1_MSG_BODY_LEN)*2;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen string_t *str;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen int ret;
61618d4c58080570f689614fec204ae14e90cef2Timo Sirainen
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen test_begin("message header parser partial");
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen input = test_istream_create(test1_msg);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_istream_set_allow_eof(input, FALSE);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen str = t_str_new(max);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen parser = message_parse_header_init(input, NULL, 0);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen for (i = 0; i <= max; i++) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_istream_set_size(input, i/2);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen while ((ret = message_parse_header_next(parser, &hdr)) > 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen hdr_write(str, hdr);
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen test_assert((ret == 0 && i < max) ||
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen (ret < 0 && i == max));
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen message_parse_header_deinit(&parser);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
c6f894e1522f7b0b6068c228900914073c145175Timo Sirainen str_append(str, " body");
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_assert(strcmp(str_c(str), test1_msg) == 0);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_stream_unref(&input);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_end();
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic void
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainentest_message_header_parser_long_lines_str(const char *str,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen unsigned int buffer_size,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct message_size *size_r)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct message_header_parser_ctx *parser;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct message_header_line *hdr;
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen struct istream *input;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen unsigned int i, len = strlen(str);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen input = test_istream_create(str);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_istream_set_max_buffer_size(input, buffer_size);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen parser = message_parse_header_init(input, size_r, 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen for (i = 1; i <= len; i++) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_istream_set_size(input, i);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen while (message_parse_header_next(parser, &hdr) > 0) ;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen message_parse_header_deinit(&parser);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_stream_unref(&input);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen}
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenstatic void test_message_header_parser_long_lines(void)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen{
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen static const char *lf_str = "1234567890: 345\n\n";
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen static const char *crlf_str = "1234567890: 345\r\n\r\n";
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen struct message_size hdr_size;
c6f894e1522f7b0b6068c228900914073c145175Timo Sirainen unsigned int i, len;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_begin("message header parser long lines");
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen len = strlen(lf_str);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen for (i = 2; i < len; i++) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_message_header_parser_long_lines_str(lf_str, i, &hdr_size);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr_size.physical_size == len);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr_size.virtual_size == len + 2);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen len = strlen(crlf_str);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen for (i = 3; i < len; i++) {
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen test_message_header_parser_long_lines_str(crlf_str, i, &hdr_size);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr_size.physical_size == len);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen test_assert(hdr_size.virtual_size == len);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen test_end();
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen}
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainenstatic void test_message_header_parser_extra_cr_in_eoh(void)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen{
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen static const char *str = "a:b\n\r\r\n";
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen struct message_header_parser_ctx *parser;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct message_header_line *hdr;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct istream *input;
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen test_begin("message header parser extra CR in EOH");
2024157e8de36edd31f5fd72f5ea7364a0955fa7Timo Sirainen
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen input = test_istream_create(str);
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen parser = message_parse_header_init(input, NULL, 0);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0 &&
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen strcmp(hdr->name, "a") == 0);
15f526e5ac611b4532568d131fcd0abf664abe41Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0 &&
15f526e5ac611b4532568d131fcd0abf664abe41Timo Sirainen strcmp(hdr->name, "\r") == 0 && hdr->middle_len == 0 &&
15f526e5ac611b4532568d131fcd0abf664abe41Timo Sirainen hdr->value_len == 0 && !hdr->eoh);
15f526e5ac611b4532568d131fcd0abf664abe41Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) < 0);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen message_parse_header_deinit(&parser);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen test_assert(input->stream_errno == 0);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen i_stream_unref(&input);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen test_end();
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen}
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen
0f62889d833767acf9c2ad010c3269806b4cfae3Timo Sirainenstatic void test_message_header_parser_no_eoh(void)
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen{
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen static const char *str = "a:b\n";
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen struct message_header_parser_ctx *parser;
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen struct message_header_line *hdr;
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen struct istream *input;
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen test_begin("message header parser no EOH");
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen input = test_istream_create(str);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen parser = message_parse_header_init(input, NULL, 0);
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0 &&
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen strcmp(hdr->name, "a") == 0);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) < 0);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen message_parse_header_deinit(&parser);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen test_assert(input->stream_errno == 0);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen i_stream_unref(&input);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen test_end();
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen}
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainenint main(void)
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen{
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen static void (*test_functions[])(void) = {
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen test_message_header_parser,
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen test_message_header_parser_partial,
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen test_message_header_parser_long_lines,
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen test_message_header_parser_extra_cr_in_eoh,
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen test_message_header_parser_no_eoh,
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen NULL
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen };
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen return test_run(test_functions);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen}
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen