diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib-mail/test-message-header-encode.c | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/src/lib-mail/test-message-header-encode.c b/src/lib-mail/test-message-header-encode.c new file mode 100644 index 0000000..b1c5645 --- /dev/null +++ b/src/lib-mail/test-message-header-encode.c @@ -0,0 +1,295 @@ +/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "base64.h" +#include "buffer.h" +#include "str.h" +#include "message-header-encode.h" +#include "test-common.h" + +static bool verify_q(const char *str, unsigned int i, bool starts_with_a) +{ + unsigned int line_start = i, char_count = 0; + + if (str_begins(str+i, "\n\t")) { + i += 2; + line_start = i - 1; + } + + for (;;) { + if (!str_begins(str+i, "=?utf-8?q?")) + return FALSE; + i += 10; + + if (starts_with_a) { + if (str[i] != 'a') + return FALSE; + starts_with_a = FALSE; + i++; + } + while (!str_begins(str+i, "?=")) { + if (!str_begins(str+i, "=C3=A4")) + return FALSE; + i += 6; + char_count++; + } + i += 2; + if (i - line_start > 76) + return FALSE; + + if (str[i] == '\0') + break; + if (!str_begins(str+i, "\n\t")) + return FALSE; + i += 2; + line_start = i - 1; + } + return char_count == 40; +} + +static void test_message_header_encode_q(void) +{ + string_t *input = t_str_new(100); + string_t *str = t_str_new(512); + unsigned int i, j, skip; + + test_begin("message header encode q"); + + str_append_c(input, 'a'); + for (i = 0; i < 40; i++) + str_append(input, "\xC3\xA4"); + for (i = 0; i < 80; i++) { + for (skip = 0; skip < 2; skip++) { + str_truncate(str, 0); + for (j = 1; j < i; j++) + str_append_c(str, 'X'); + if (i != 0) + str_append_c(str, ' '); + + message_header_encode_q(str_data(input) + skip, + str_len(input) - skip, str, + i == 0 ? 0 : i+1); + test_assert(verify_q(str_c(str), i, skip == 0)); + } + } + test_end(); +} + +static bool verify_b(const char *str, unsigned int i, bool starts_with_a) +{ + unsigned int line_start = i, start, j, char_count = 0; + char bufdata[1000]; + buffer_t buf; + + buffer_create_from_data(&buf, bufdata, sizeof(bufdata)); + if (str_begins(str+i, "\n\t")) { + i += 2; + line_start = i - 1; + } + + for (;;) { + if (!str_begins(str+i, "=?utf-8?b?")) + return FALSE; + i += 10; + + start = i; + for (; str[i] != '?'; i++) { + if (str[i] == '\0') + return FALSE; + } + buffer_set_used_size(&buf, 0); + if (base64_decode(str+start, i-start, NULL, &buf) < 0) + return FALSE; + i++; + + if (!starts_with_a) + j = 0; + else { + if (bufdata[0] != 'a') + return FALSE; + starts_with_a = FALSE; + j = 1; + } + for (; j < buf.used; j += 2) { + if (bufdata[j] != '\xc3' || bufdata[j+1] != '\xa4') + return FALSE; + char_count++; + } + if (j != buf.used) + return FALSE; + + if (str[i++] != '=') + return FALSE; + + if (i - line_start > 76) + return FALSE; + + if (str[i] == '\0') + break; + if (!str_begins(str+i, "\n\t")) + return FALSE; + i += 2; + line_start = i - 1; + } + return char_count == 40; +} + +static void test_message_header_encode_b(void) +{ + string_t *input = t_str_new(100); + string_t *str = t_str_new(512); + unsigned int i, j, skip; + + test_begin("message header encode b"); + + str_append_c(input, 'a'); + for (i = 0; i < 40; i++) + str_append(input, "\xC3\xA4"); + for (i = 0; i < 80; i++) { + for (skip = 0; skip < 2; skip++) { + str_truncate(str, 0); + for (j = 1; j < i; j++) + str_append_c(str, 'X'); + if (i != 0) + str_append_c(str, ' '); + + message_header_encode_b(str_data(input) + skip, + str_len(input) - skip, str, + i == 0 ? 0 : i+1); + test_assert(verify_b(str_c(str), i, skip == 0)); + } + } + test_end(); +} + +static void test_message_header_encode(void) +{ + const char *data[] = { + "a b", "a b", + "a bc\xC3\xA4""de f", "a =?utf-8?q?bc=C3=A4de?= f", + "a \xC3\xA4\xC3\xA4 \xC3\xA4 b", "a =?utf-8?b?w6TDpCDDpA==?= b", + "\xC3\xA4 a \xC3\xA4", "=?utf-8?q?=C3=A4_a_=C3=A4?=", + "\xC3\xA4\xC3\xA4 a \xC3\xA4", "=?utf-8?b?w6TDpCBhIMOk?=", + "=", "=", + "?", "?", + "a=?", "a=?", + "=?", "=?utf-8?q?=3D=3F?=", + "=?x", "=?utf-8?q?=3D=3Fx?=", + "a\n=?", "a\n\t=?utf-8?q?=3D=3F?=", + "a\t=?", "a\t=?utf-8?q?=3D=3F?=", + "a =?", "a =?utf-8?q?=3D=3F?=", + "foo\001bar", "=?utf-8?q?foo=01bar?=", + "\x01\x02\x03\x04\x05\x06\x07\x08", "=?utf-8?b?AQIDBAUGBwg=?=", +#define TEXT30 "123456789012345678901234567890" + TEXT30 " \xc3\xa4 " TEXT30 "\xc3\xa4 stuff", + TEXT30 " =?utf-8?q?=C3=A4_12345678901234567890123456?=\n" + "\t=?utf-8?q?7890=C3=A4?= stuff", + + "a\r\n b", "a\r\n b", + "a\r\n\tb", "a\r\n\tb", + "a\r\nb", "a\r\n\tb", + "a\n b", "a\n b", + "a\n b", "a\n b", + "a\nb", "a\n\tb", + "a\r\n", "a", + "a\n", "a", + "foo\n \001bar", "foo\n =?utf-8?q?=01bar?=", + "foo\001\n bar", "=?utf-8?q?foo=01?=\n bar", + "\xC3\xA4\xC3\xA4\xC3\xA4\xC3\xA4\xC3\xA4\xC3\xA4\xC3\xA4" + "\xC3\xA4\xC3\xA4\xC3\xA4\xC3\xA4\xC3\xA4\xC3\xA4\xC3\xA4", + "=?utf-8?b?w6TDpMOkw6TDpMOkw6TDpMOkw6TDpMOkw6TDpA==?=", + /* Bad UTF-8 */ + "foofoo-\x80\x80\x80\x80\x80\x80\x80-barbar", + "=?utf-8?q?foofoo-=EF=BF=BD-barbar?=", + "foobarfoobar-\x80\x80\x80\x80\x80\x80\x80", + "=?utf-8?q?foobarfoobar-=EF=BF=BD?=", + "\x80\x80\x80\x80\x80\x80\x80-foobarfoobar", + "=?utf-8?q?=EF=BF=BD-foobarfoobar?=", + "foofoo-\x80\x80\x80\x80\x80\x80\x80-barbarbarbar-" + "\x81\x82\x83\x84\x85\x86\x87-bazbaz", + "=?utf-8?q?foofoo-=EF=BF=BD-barbarbarbar-" + "=EF=BF=BD-bazbaz?=", + "foobarfoobarfoobar-\x80\x80\x80\x80\x80\x80\x80-" + "\x81\x82\x83\x84\x85\x86\x87-bazbaz", + "=?utf-8?q?foobarfoobarfoobar-=EF=BF=BD-" + "=EF=BF=BD-bazbaz?=", + "\x80\x80\x80\x80\x80\x80\x80-foobarfoobarfoobar-" + "\x81\x82\x83\x84\x85\x86\x87-bazbaz", + "=?utf-8?q?=EF=BF=BD-foobarfoobarfoobar-" + "=EF=BF=BD-bazbaz?=", + "foofoo-\xC3-barbar", + "=?utf-8?q?foofoo-=EF=BF=BD-barbar?=", + "foobarfoobar-\xC3", + "=?utf-8?q?foobarfoobar-=EF=BF=BD?=", + "\xC3-foobarfoobar", + "=?utf-8?q?=EF=BF=BD-foobarfoobar?=", + "f-\x80\x80\x80\x80\x80\x80\x80-b", "=?utf-8?b?Zi3vv70tYg==?=", + "fb-\x80\x80\x80\x80\x80\x80\x80", "=?utf-8?b?ZmIt77+9?=", + "\x80\x80\x80\x80\x80\x80\x80-fb", "=?utf-8?b?77+9LWZi?=", + "ff-\x80\x80\x80\x80\x80\x80\x80-bb-" + "\x81\x82\x83\x84\x85\x86\x87-zz", + "=?utf-8?b?ZmYt77+9LWJiLe+/vS16eg==?=", + "fbfb-\x80\x80\x80\x80\x80\x80\x80-" + "\x81\x82\x83\x84\x85\x86\x87-zz", + "=?utf-8?b?ZmJmYi3vv70t77+9LXp6?=", + "\x80\x80\x80\x80\x80\x80\x80-ff-" + "\x81\x82\x83\x84\x85\x86\x87-zz", + "=?utf-8?b?77+9LWZmLe+/vS16eg==?=", + "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80", + "=?utf-8?b?77+9?=", + "-\xC3-\xC3-\xC3-\xC3-\xC3-\xC3-", + "=?utf-8?q?-=EF=BF=BD-=EF=BF=BD-" + "=EF=BF=BD-=EF=BF=BD-=EF=BF=BD-=EF=BF=BD-?=", + "\xC3--\xC3-\xC3-\xC3-\xC3--\xC3", + "=?utf-8?q?=EF=BF=BD--=EF=BF=BD-" + "=EF=BF=BD-=EF=BF=BD-=EF=BF=BD--=EF=BF=BD?=", + "-\xC3\xC3-\xC3\xC3-\xC3\xC3-\xC3\xC3-\xC3\xC3-\xC3\xC3-", + "=?utf-8?b?Le+/vS3vv70t77+9Le+/vS3vv70t77+9LQ==?=", + "-\xC3\xC3\xC3-\xC3\xC3\xC3-\xC3\xC3\xC3-" + "\xC3\xC3\xC3-\xC3\xC3\xC3-\xC3\xC3\xC3-", + "=?utf-8?b?Le+/vS3vv70t77+9Le+/vS3vv70t77+9LQ==?=", + "\xC3\xC3\xC3\xC3\xC3\xC3\xC3\xC3\xC3\xC3\xC3\xC3\xC3\xC3", + "=?utf-8?b?77+9?=", + "-\xC3\xA4\xC3\xC3-\xC3\xC3\xA4\xC3-\xC3\xC3\xC3\xA4-" + "\xC3\xC3\xC3\xA4-\xC3\xC3\xA4\xC3-\xC3\xA4\xC3\xC3-", + "=?utf-8?b?LcOk77+9Le+/vcOk77+9Le+/" + "vcOkLe+/vcOkLe+/vcOk77+9LcOk77+9LQ==?=", + }; + string_t *str = t_str_new(128); + unsigned int i; + + test_begin("message header encode"); + for (i = 0; i < N_ELEMENTS(data); i += 2) { + str_truncate(str, 0); + message_header_encode(data[i], str); + test_assert_strcmp(str_c(str), data[i+1]); + } + test_end(); +} + +static void test_message_header_encode_data(void) +{ + string_t *str = t_str_new(128); + static unsigned char nuls[10] = { 0, }; + + test_begin("message header encode data"); + message_header_encode_data(nuls, 1, str); + test_assert_strcmp(str_c(str), "=?utf-8?q?=00?="); + + str_truncate(str, 0); + message_header_encode_data(nuls, sizeof(nuls), str); + test_assert_strcmp(str_c(str), "=?utf-8?b?AAAAAAAAAAAAAA==?="); + test_end(); +} + +int main(void) +{ + static void (*const test_functions[])(void) = { + test_message_header_encode_q, + test_message_header_encode_b, + test_message_header_encode, + test_message_header_encode_data, + NULL + }; + return test_run(test_functions); +} |