test-message-parser.c revision 7a12331c6360968b141a0888e0bf04dd24145f23
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2007-2016 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "str.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "istream.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "message-parser.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "test-common.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainenstatic const char test_msg[] =
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen"Return-Path: <test@example.org>\n"
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen"Subject: Hello world\n"
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen"From: Test User <test@example.org>\n"
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen"To: Another User <test2@example.org>\n"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen"Message-Id: <1.2.3.4@example>\n"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen"Mime-Version: 1.0\n"
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen"Date: Sun, 23 May 2007 04:58:08 +0300\n"
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen"Content-Type: multipart/signed; micalg=pgp-sha1;\n"
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen" protocol=\"application/pgp-signature\";\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen" boundary=\"=-GNQXLhuj24Pl1aCkk4/d\"\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"--=-GNQXLhuj24Pl1aCkk4/d\n"
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen"Content-Type: text/plain\n"
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen"Content-Transfer-Encoding: quoted-printable\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"\n"
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen"There was a day=20\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"a happy=20day\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"--=-GNQXLhuj24Pl1aCkk4/d\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"Content-Type: application/pgp-signature; name=signature.asc\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"-----BEGIN PGP SIGNATURE-----\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"Version: GnuPG v1.2.4 (GNU/Linux)\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"invalid\n"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen"-----END PGP SIGNATURE-----\n"
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen"\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"--=-GNQXLhuj24Pl1aCkk4/d--\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"\n"
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen"\n";
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen#define TEST_MSG_LEN (sizeof(test_msg)-1)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenstatic bool msg_parts_cmp(struct message_part *p1, struct message_part *p2)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen while (p1 != NULL || p2 != NULL) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if ((p1 != NULL) != (p2 != NULL))
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return FALSE;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if ((p1->children != NULL) != (p2->children != NULL))
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (p1->children) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!msg_parts_cmp(p1->children, p2->children))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (p1->physical_pos != p2->physical_pos ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->header_size.physical_size != p2->header_size.physical_size ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->header_size.virtual_size != p2->header_size.virtual_size ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->header_size.lines != p2->header_size.lines ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->body_size.physical_size != p2->body_size.physical_size ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->body_size.virtual_size != p2->body_size.virtual_size ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->body_size.lines != p2->body_size.lines ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->flags != p2->flags)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1 = p1->next;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen p2 = p2->next;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return TRUE;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void test_message_parser_small_blocks(void)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct message_parser_ctx *parser;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct istream *input;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct message_part *parts, *parts2;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct message_block block;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int i, end_of_headers_idx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen string_t *output;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool_t pool;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen int ret;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen test_begin("message parser in small blocks");
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool = pool_alloconly_create("message parser", 10240);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen input = test_istream_create(test_msg);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen output = t_str_new(128);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* full parsing */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen parser = message_parser_init(pool, input, 0,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS |
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen while ((ret = message_parser_parse_next_block(parser, &block)) > 0) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (block.hdr != NULL)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen message_header_line_write(output, block.hdr);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen else
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen str_append_n(output, block.data, block.size);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen test_assert(ret < 0);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen test_assert(message_parser_deinit(&parser, &parts) == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(strcmp(test_msg, str_c(output)) == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen /* parsing in small blocks */
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen i_stream_seek(input, 0);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen test_istream_set_allow_eof(input, FALSE);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen parser = message_parser_init(pool, input, 0, 0);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (i = 1; i <= TEST_MSG_LEN*2+1; i++) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen test_istream_set_size(input, i/2);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen if (i > TEST_MSG_LEN*2)
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen test_istream_set_allow_eof(input, TRUE);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen while ((ret = message_parser_parse_next_block(parser,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen &block)) > 0) ;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert((ret == 0 && i <= TEST_MSG_LEN*2) ||
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen (ret < 0 && i > TEST_MSG_LEN*2));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen test_assert(message_parser_deinit(&parser, &parts2) == 0);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen test_assert(msg_parts_cmp(parts, parts2));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* parsing in small blocks from preparsed parts */
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen i_stream_seek(input, 0);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen test_istream_set_allow_eof(input, FALSE);
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen end_of_headers_idx = (strstr(test_msg, "\n-----") - test_msg);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen parser = message_parser_init_from_parts(parts, input, 0,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen for (i = 1; i <= TEST_MSG_LEN*2+1; i++) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen test_istream_set_size(input, i/2);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (i > TEST_MSG_LEN*2)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen test_istream_set_allow_eof(input, TRUE);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen while ((ret = message_parser_parse_next_block(parser,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen &block)) > 0) ;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen test_assert((ret == 0 && i/2 <= end_of_headers_idx) ||
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen (ret < 0 && i/2 > end_of_headers_idx));
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(message_parser_deinit(&parser, &parts2) == 0);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen test_assert(msg_parts_cmp(parts, parts2));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_stream_unref(&input);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen pool_unref(&pool);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_end();
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic void test_message_parser_truncated_mime_headers(void)
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic const char input_msg[] =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen"Content-Type: multipart/mixed; boundary=\":foo\"\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"--:foo\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"--:foo\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"Content-Type: text/plain\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"--:foo\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"Content-Type: text/plain\r\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"--:foo\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"Content-Type: text/html\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"--:foo--\n";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct message_parser_ctx *parser;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct istream *input;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct message_part *parts, *part;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct message_block block;
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen pool_t pool;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen int ret;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_begin("message parser truncated mime headers");
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen pool = pool_alloconly_create("message parser", 10240);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen input = test_istream_create(input_msg);
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen parser = message_parser_init(pool, input, 0, 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(ret < 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(message_parser_deinit(&parser, &parts) == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert((parts->flags & MESSAGE_PART_FLAG_MULTIPART) != 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->body_size.lines == 8);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->body_size.physical_size == 112);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen test_assert(parts->body_size.virtual_size == 112+7);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->children->header_size.physical_size == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->children->body_size.physical_size == 0);
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen test_assert(parts->children->body_size.lines == 0);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->header_size.physical_size == 24);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->header_size.virtual_size == 24);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->header_size.lines == 0);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->next->header_size.physical_size == 24);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->next->header_size.virtual_size == 24);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->next->header_size.lines == 0);
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen test_assert(parts->children->next->next->next->header_size.physical_size == 23);
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen test_assert(parts->children->next->next->next->header_size.virtual_size == 23);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->children->next->next->next->header_size.lines == 0);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen for (part = parts->children; part != NULL; part = part->next) {
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen test_assert(part->body_size.physical_size == 0);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen test_assert(part->body_size.virtual_size == 0);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->children->next->next->next->next == NULL);
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen i_stream_unref(&input);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen pool_unref(&pool);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen test_end();
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen}
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic void test_message_parser_duplicate_mime_boundary(void)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic const char input_msg[] =
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen"Content-Type: multipart/mixed; boundary=\"a\"\n"
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen"\n"
9abf5be0962538e1f6f5c73c838ff677341da0c9Timo Sirainen"--a\n"
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen"Content-Type: multipart/mixed; boundary=\"a\"\n"
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen"\n"
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen"--a\n"
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen"Content-Type: text/plain\n"
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen"\n"
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen"body\n";
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen struct message_parser_ctx *parser;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen struct istream *input;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen struct message_part *parts;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen struct message_block block;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen pool_t pool;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen int ret;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen test_begin("message parser duplicate mime boundary");
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen pool = pool_alloconly_create("message parser", 10240);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen input = test_istream_create(input_msg);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen parser = message_parser_init(pool, input, 0, 0);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(ret < 0);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(message_parser_deinit(&parser, &parts) == 0);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->header_size.lines == 2);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->header_size.physical_size == 45);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->header_size.virtual_size == 45+2);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->body_size.lines == 7);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->body_size.physical_size == 84);
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen test_assert(parts->body_size.virtual_size == 84+7);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->physical_pos == 49);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->header_size.lines == 2);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->header_size.physical_size == 45);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->header_size.virtual_size == 45+2);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->body_size.lines == 4);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->body_size.physical_size == 35);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->body_size.virtual_size == 35+4);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME));
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->physical_pos == 98);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->header_size.lines == 2);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->header_size.physical_size == 26);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->header_size.virtual_size == 26+2);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen test_assert(parts->children->children->body_size.lines == 1);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->body_size.physical_size == 5);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->body_size.virtual_size == 5+1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen i_stream_unref(&input);
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen pool_unref(&pool);
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen test_end();
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic void test_message_parser_continuing_mime_boundary(void)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic const char input_msg[] =
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen"Content-Type: multipart/mixed; boundary=\"a\"\n"
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen"\n"
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen"--a\n"
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen"Content-Type: multipart/mixed; boundary=\"ab\"\n"
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen"\n"
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen"--ab\n"
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen"Content-Type: text/plain\n"
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen"\n"
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen"body\n";
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen struct message_parser_ctx *parser;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen struct istream *input;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen struct message_part *parts;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct message_block block;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen pool_t pool;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen int ret;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen test_begin("message parser continuing mime boundary");
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen pool = pool_alloconly_create("message parser", 10240);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen input = test_istream_create(input_msg);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen parser = message_parser_init(pool, input, 0, 0);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(ret < 0);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(message_parser_deinit(&parser, &parts) == 0);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->header_size.lines == 2);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->header_size.physical_size == 45);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->header_size.virtual_size == 45+2);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->body_size.lines == 7);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->body_size.physical_size == 86);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->body_size.virtual_size == 86+7);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->physical_pos == 49);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->header_size.lines == 2);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->children->header_size.physical_size == 46);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->header_size.virtual_size == 46+2);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->body_size.lines == 4);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->body_size.physical_size == 36);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->body_size.virtual_size == 36+4);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME));
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->physical_pos == 100);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->header_size.lines == 2);
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen test_assert(parts->children->children->header_size.physical_size == 26);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->header_size.virtual_size == 26+2);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->body_size.lines == 1);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->body_size.physical_size == 5);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->body_size.virtual_size == 5+1);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen i_stream_unref(&input);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen pool_unref(&pool);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen test_end();
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic void test_message_parser_no_eoh(void)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen{
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen static const char input_msg[] = "a:b\n";
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct message_parser_ctx *parser;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct istream *input;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct message_part *parts;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct message_block block;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen pool_t pool;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen test_begin("message parser no EOH");
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen pool = pool_alloconly_create("message parser", 10240);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen input = test_istream_create(input_msg);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen parser = message_parser_init(pool, input, 0, 0);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen test_assert(message_parser_parse_next_block(parser, &block) > 0 &&
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen block.hdr != NULL && strcmp(block.hdr->name, "a") == 0 &&
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen block.hdr->value_len == 1 && block.hdr->value[0] == 'b');
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen test_assert(message_parser_parse_next_block(parser, &block) > 0 &&
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen block.hdr == NULL && block.size == 0);
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen test_assert(message_parser_parse_next_block(parser, &block) < 0);
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen test_assert(message_parser_deinit(&parser, &parts) == 0);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen i_stream_unref(&input);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen pool_unref(&pool);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen test_end();
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenint main(void)
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen{
4a514fb20e04df397842cde11cc9ea92abfe9728Timo Sirainen static void (*test_functions[])(void) = {
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen test_message_parser_small_blocks,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen test_message_parser_truncated_mime_headers,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen test_message_parser_duplicate_mime_boundary,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen test_message_parser_continuing_mime_boundary,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen test_message_parser_no_eoh,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen NULL
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen };
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return test_run(test_functions);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen