summaryrefslogtreecommitdiffstats
path: root/src/lib-mail/test-message-header-encode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib-mail/test-message-header-encode.c')
-rw-r--r--src/lib-mail/test-message-header-encode.c295
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);
+}