bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen#include "lib.h"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen#include "str.h"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen#include "istream.h"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen#include "message-size.h"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen#include "message-header-parser.h"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen#include "test-common.h"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen#define TEST1_MSG_BODY_LEN 5
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenstatic const char *test1_msg =
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen "h1: v1\n"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen "h2:\n"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen " v2\r\n"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen "h3: \r\n"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen "\tv3\n"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen "\tw3\r\n"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen "\n"
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen " body";
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenstatic void
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainentest_message_header_parser_one(struct message_header_parser_ctx *parser,
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen enum message_header_parser_flags hdr_flags)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct message_header_line *hdr;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen bool use_full_value;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen use_full_value = hdr_flags != 0;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_offset == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP) == 0)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->full_value_offset == 4);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen else
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->full_value_offset == 5);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h1") == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP) == 0) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->middle_len == 2 && memcmp(hdr->middle, ": ", 2) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->value_len == 3 && memcmp(hdr->value, " v1", 3) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen } else {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->middle_len == 3 && memcmp(hdr->middle, ": ", 3) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->value_len == 2 && memcmp(hdr->value, "v1", 2) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(!hdr->continues && !hdr->continued && !hdr->eoh &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen !hdr->no_newline && !hdr->crlf_newline);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_offset == 8 && hdr->full_value_offset == 11);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h2") == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->middle_len == 1 && memcmp(hdr->middle, ":", 1) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->value_len == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->continues && !hdr->continued && !hdr->eoh &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen !hdr->no_newline && !hdr->crlf_newline);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (use_full_value) hdr->use_full_value = TRUE;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_offset == 8 && hdr->full_value_offset == 11);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h2") == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->middle_len == 1 && memcmp(hdr->middle, ":", 1) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->value_len == 3 && memcmp(hdr->value, " v2", 3) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(!hdr->continues && hdr->continued && !hdr->eoh &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen !hdr->no_newline && hdr->crlf_newline);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE) != 0) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->full_value_len == 3 &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen memcmp(hdr->full_value, " v2", 3) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen } else if (use_full_value) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->full_value_len == 4 &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen memcmp(hdr->full_value, "\n v2", 4) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_offset == 17 && hdr->full_value_offset == 21);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h3") == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->middle_len == 2 && memcmp(hdr->middle, ": ", 2) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->value_len == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->continues && !hdr->continued && !hdr->eoh &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen !hdr->no_newline && hdr->crlf_newline);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (use_full_value) hdr->use_full_value = TRUE;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_offset == 17 && hdr->full_value_offset == 21);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h3") == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->middle_len == 2 && memcmp(hdr->middle, ": ", 2) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->value_len == 3 && memcmp(hdr->value, "\tv3", 3) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->continues && hdr->continued && !hdr->eoh &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen !hdr->no_newline && !hdr->crlf_newline);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (use_full_value) hdr->use_full_value = TRUE;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE) != 0) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->full_value_len == 3 &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen memcmp(hdr->full_value, " v3", 3) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen } else if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_DROP_CR) != 0) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->full_value_len == 4 &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen memcmp(hdr->full_value, "\n\tv3", 4) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen } else if (use_full_value) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->full_value_len == 5 &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen memcmp(hdr->full_value, "\r\n\tv3", 5) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_offset == 17 && hdr->full_value_offset == 21);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_len == 2 && strcmp(hdr->name, "h3") == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->middle_len == 2 && memcmp(hdr->middle, ": ", 2) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->value_len == 3 && memcmp(hdr->value, "\tw3", 3) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(!hdr->continues && hdr->continued && !hdr->eoh &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen !hdr->no_newline && hdr->crlf_newline);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE) != 0) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->full_value_len == 6 &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen memcmp(hdr->full_value, " v3 w3", 6) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen } else if ((hdr_flags & MESSAGE_HEADER_PARSER_FLAG_DROP_CR) != 0) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->full_value_len == 8 &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen memcmp(hdr->full_value, "\n\tv3\n\tw3", 8) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen } else if (use_full_value) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->full_value_len == 9 &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen memcmp(hdr->full_value, "\r\n\tv3\n\tw3", 9) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_offset == 32 && hdr->full_value_offset == 32);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr->name_len == 0 && hdr->middle_len == 0 && hdr->value_len == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(!hdr->continues && !hdr->continued && hdr->eoh &&
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen !hdr->no_newline && !hdr->crlf_newline);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) < 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenstatic void test_message_header_parser(void)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen static enum message_header_parser_flags max_hdr_flags =
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP |
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen MESSAGE_HEADER_PARSER_FLAG_DROP_CR |
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen enum message_header_parser_flags hdr_flags;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct message_header_parser_ctx *parser;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct message_size hdr_size;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct istream *input;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_begin("message header parser");
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen input = test_istream_create(test1_msg);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen for (hdr_flags = 0; hdr_flags <= max_hdr_flags; hdr_flags++) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen i_stream_seek(input, 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen parser = message_parse_header_init(input, &hdr_size, hdr_flags);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_message_header_parser_one(parser, hdr_flags);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen message_parse_header_deinit(&parser);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr_size.physical_size == strlen(test1_msg)-TEST1_MSG_BODY_LEN);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(hdr_size.virtual_size == strlen(test1_msg) - TEST1_MSG_BODY_LEN + 4);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen i_stream_unref(&input);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_end();
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenstatic void hdr_write(string_t *str, struct message_header_line *hdr)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (!hdr->continued) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen str_append(str, hdr->name);
d4488f314d0c799c5f5b8a7890e17eef868f7a2cMartti Rannanjärvi if (hdr->middle_len > 0)
d4488f314d0c799c5f5b8a7890e17eef868f7a2cMartti Rannanjärvi str_append_n(str, hdr->middle, hdr->middle_len);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen str_append_n(str, hdr->value, hdr->value_len);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (!hdr->no_newline) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen if (hdr->crlf_newline)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen str_append_c(str, '\r');
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen str_append_c(str, '\n');
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenstatic void test_message_header_parser_partial(void)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct message_header_parser_ctx *parser;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct message_header_line *hdr;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen struct istream *input;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen unsigned int i, max = (strlen(test1_msg)-TEST1_MSG_BODY_LEN)*2;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen string_t *str;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen int ret;
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_begin("message header parser partial");
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen input = test_istream_create(test1_msg);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_istream_set_allow_eof(input, FALSE);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen str = t_str_new(max);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen parser = message_parse_header_init(input, NULL, 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen for (i = 0; i <= max; i++) {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_istream_set_size(input, i/2);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen while ((ret = message_parse_header_next(parser, &hdr)) > 0)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen hdr_write(str, hdr);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert((ret == 0 && i < max) ||
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen (ret < 0 && i == max));
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen }
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen message_parse_header_deinit(&parser);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen str_append(str, " body");
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_assert(strcmp(str_c(str), test1_msg) == 0);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen i_stream_unref(&input);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_end();
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainenstatic void
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainentest_message_header_parser_long_lines_str(const char *str,
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen unsigned int buffer_size,
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen struct message_size *size_r)
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen{
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen struct message_header_parser_ctx *parser;
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen struct message_header_line *hdr;
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen struct istream *input;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen unsigned int i;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t len = strlen(str);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen input = test_istream_create(str);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen test_istream_set_max_buffer_size(input, buffer_size);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen parser = message_parse_header_init(input, size_r, 0);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen for (i = 1; i <= len; i++) {
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen test_istream_set_size(input, i);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen while (message_parse_header_next(parser, &hdr) > 0) ;
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen }
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen message_parse_header_deinit(&parser);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen i_stream_unref(&input);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen}
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainenstatic void test_message_header_parser_long_lines(void)
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen{
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen static const char *lf_str = "1234567890: 345\n\n";
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen static const char *crlf_str = "1234567890: 345\r\n\r\n";
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen struct message_size hdr_size;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t i, len;
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen test_begin("message header parser long lines");
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen len = strlen(lf_str);
ad4cd18ba6c43fe94987408f81ed6547b29132d6Timo Sirainen for (i = 2; i < len; i++) {
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen test_message_header_parser_long_lines_str(lf_str, i, &hdr_size);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen test_assert(hdr_size.physical_size == len);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen test_assert(hdr_size.virtual_size == len + 2);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen }
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen len = strlen(crlf_str);
01ca85e6e763cfa0d146166fdd60654f04f51199Timo Sirainen for (i = 3; i < len; i++) {
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen test_message_header_parser_long_lines_str(crlf_str, i, &hdr_size);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen test_assert(hdr_size.physical_size == len);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen test_assert(hdr_size.virtual_size == len);
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen }
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen test_end();
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen}
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainenstatic void test_message_header_parser_extra_cr_in_eoh(void)
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen{
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen static const char *str = "a:b\n\r\r\n";
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen struct message_header_parser_ctx *parser;
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen struct message_header_line *hdr;
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen struct istream *input;
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen test_begin("message header parser extra CR in EOH");
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen input = test_istream_create(str);
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen parser = message_parse_header_init(input, NULL, 0);
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0 &&
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen strcmp(hdr->name, "a") == 0);
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0 &&
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen strcmp(hdr->name, "\r") == 0 && hdr->middle_len == 0 &&
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen hdr->value_len == 0 && !hdr->eoh);
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) < 0);
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen message_parse_header_deinit(&parser);
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen test_assert(input->stream_errno == 0);
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen i_stream_unref(&input);
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen test_end();
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen}
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainenstatic void test_message_header_parser_no_eoh(void)
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen{
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen static const char *str = "a:b\n";
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen struct message_header_parser_ctx *parser;
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen struct message_header_line *hdr;
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen struct istream *input;
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen test_begin("message header parser no EOH");
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen input = test_istream_create(str);
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen parser = message_parse_header_init(input, NULL, 0);
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) > 0 &&
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen strcmp(hdr->name, "a") == 0);
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen test_assert(message_parse_header_next(parser, &hdr) < 0);
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen message_parse_header_deinit(&parser);
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen test_assert(input->stream_errno == 0);
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen i_stream_unref(&input);
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen test_end();
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen}
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainenint main(void)
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen{
baf3e87e186453fda13bd21f7cbcb2efc8492e8bTimo Sirainen static void (*const test_functions[])(void) = {
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_message_header_parser,
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen test_message_header_parser_partial,
f16712057c1b82c6d2a3a4267c4521d357cd4b4cTimo Sirainen test_message_header_parser_long_lines,
bca734e149473b13bb4d454865e9e23d7a05ca10Timo Sirainen test_message_header_parser_extra_cr_in_eoh,
4b994089fc7e6f7f42f1d7932e893c2b13ed1451Timo Sirainen test_message_header_parser_no_eoh,
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen NULL
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen };
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen return test_run(test_functions);
cf29b7d24ada0c23d9c2ad2fee75b164583572f5Timo Sirainen}