summaryrefslogtreecommitdiffstats
path: root/src/lib-imap/test-imap-utf7.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 17:36:47 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 17:36:47 +0000
commit0441d265f2bb9da249c7abf333f0f771fadb4ab5 (patch)
tree3f3789daa2f6db22da6e55e92bee0062a7d613fe /src/lib-imap/test-imap-utf7.c
parentInitial commit. (diff)
downloaddovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.tar.xz
dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.zip
Adding upstream version 1:2.3.21+dfsg1.upstream/1%2.3.21+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib-imap/test-imap-utf7.c')
-rw-r--r--src/lib-imap/test-imap-utf7.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/src/lib-imap/test-imap-utf7.c b/src/lib-imap/test-imap-utf7.c
new file mode 100644
index 0000000..216eebf
--- /dev/null
+++ b/src/lib-imap/test-imap-utf7.c
@@ -0,0 +1,216 @@
+/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "unichar.h"
+#include "imap-utf7.h"
+#include "test-common.h"
+
+static void test_imap_utf7_by_example(void)
+{
+ static const struct test {
+ const char *utf8;
+ const char *mutf7;
+ } tests[] = {
+ { "&&x&&", "&-&-x&-&-" },
+ { "~peter/mail/\xe5\x8f\xb0\xe5\x8c\x97/\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e",
+ "~peter/mail/&U,BTFw-/&ZeVnLIqe-" },
+ { "tiet\xc3\xa4&j\xc3\xa4&", "tiet&AOQ-&-j&AOQ-&-" }, /* & is always encoded as &- */
+ { "p\xe4\xe4", NULL },
+ { NULL, "&" },
+ { NULL, "&Jjo" },
+ { NULL, "&Jjo!" },
+ { NULL, "&U,BTFw-&ZeVnLIqe-" } /* unnecessary shift */
+ };
+ string_t *dest, *dest2;
+ unsigned int i;
+
+ dest = t_str_new(256);
+ dest2 = t_str_new(256);
+
+ test_begin("imap mutf7 examples");
+ for (i = 0; i < N_ELEMENTS(tests); i++) {
+ str_truncate(dest, 0);
+ if (tests[i].utf8 != NULL) {
+ if (imap_utf8_to_utf7(tests[i].utf8, dest) < 0)
+ test_assert_idx(tests[i].mutf7 == NULL, i);
+ else
+ test_assert_idx(null_strcmp(tests[i].mutf7, str_c(dest)) == 0, i);
+ } else {
+ /* invalid mUTF-7 - test that escaping works */
+ str_truncate(dest2, 0);
+ imap_utf7_to_utf8_escaped(tests[i].mutf7, "%", dest);
+ imap_escaped_utf8_to_utf7(str_c(dest), '%', dest2);
+ test_assert_idx(strcmp(tests[i].mutf7, str_c(dest2)) == 0, i);
+ }
+ if (tests[i].mutf7 != NULL) {
+ str_truncate(dest, 0);
+ if (imap_utf7_to_utf8(tests[i].mutf7, dest) < 0)
+ test_assert_idx(tests[i].utf8 == NULL, i);
+ else
+ test_assert_idx(null_strcmp(tests[i].utf8, str_c(dest)) == 0, i);
+ test_assert_idx(imap_utf7_is_valid(tests[i].mutf7) != (tests[i].utf8 == NULL), i);
+ }
+ }
+
+ str_truncate(dest, 0);
+ imap_utf7_to_utf8_escaped(".foo%", "%.", dest);
+ test_assert_strcmp(str_c(dest), "%2efoo%25");
+
+ str_truncate(dest, 0);
+ test_assert(imap_escaped_utf8_to_utf7("%foo%2ebar", '%', dest) == 0);
+ test_assert_strcmp(str_c(dest), "%foo.bar");
+
+ test_end();
+}
+
+static void test_imap_utf7_ucs4_cases(void)
+{
+ string_t *src, *dest;
+ const char *orig_src;
+ unsigned int i, j;
+ unichar_t chr;
+
+ src = t_str_new(256);
+ dest = t_str_new(256);
+
+ test_begin("imap mutf7 ucs4 cases");
+ for (chr = 0xffff; chr <= 0x10010; chr++) T_BEGIN {
+ for (i = 1; i <= 10; i++) {
+ str_truncate(src, 0);
+ str_truncate(dest, 0);
+ for (j = 0; j < i; j++) {
+ if (j % 3 == 0)
+ str_append_c(src, 'x');
+ if (j % 5 == 0)
+ str_append_c(src, '&');
+ uni_ucs4_to_utf8_c(chr, src);
+ }
+
+ orig_src = t_strdup(str_c(src));
+ str_truncate(src, 0);
+
+ test_assert_idx(imap_utf8_to_utf7(orig_src, dest) == 0, chr*100+i);
+ test_assert_idx(imap_utf7_to_utf8(str_c(dest), src) == 0, chr*100+i);
+ test_assert_idx(strcmp(str_c(src), orig_src) == 0, chr+100+i);
+ }
+ } T_END;
+ test_end();
+}
+
+static const char mb64[64]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
+static void test_imap_utf7_non_utf16(void)
+{
+ string_t *dest, *dest2;
+ unsigned int i;
+
+ test_begin("imap mutf7 non-utf16");
+ dest = t_str_new(32);
+ dest2 = t_str_new(32);
+ for (i = 0; i <= 255; ++i) {
+ /* Invalid, code a single 8-bit octet */
+ const char csrc[] = {
+ '&',
+ mb64[i >> 2],
+ mb64[(i & 3) << 4],
+ '-',
+ '\0'
+ };
+ test_assert_idx(!imap_utf7_is_valid(csrc), i);
+
+ /* escaping can reverse the original string */
+ str_truncate(dest, 0);
+ str_truncate(dest2, 0);
+ imap_utf7_to_utf8_escaped(csrc, "%", dest);
+ imap_escaped_utf8_to_utf7(str_c(dest), '%', dest2);
+ test_assert_idx(strcmp(csrc, str_c(dest2)) == 0, i);
+ }
+ for (i = 0; i <= 255; ++i) {
+ /* Invalid, U+00E4 followed by a single octet */
+ const char csrc[] = {
+ '&',
+ mb64[ (0x00 >> 2)],
+ mb64[((0x00 & 0x03) << 4) | (0xe4 >> 4)],
+ mb64[((0xe4 & 0x0f) << 2) | ( i >> 6)],
+ mb64[ i & 0x3f ],
+ '-',
+ '\0'
+ };
+ test_assert_idx(!imap_utf7_is_valid(csrc), i);
+
+ /* escaping can reverse the original string */
+ str_truncate(dest, 0);
+ str_truncate(dest2, 0);
+ imap_utf7_to_utf8_escaped(csrc, "%", dest);
+ imap_escaped_utf8_to_utf7(str_c(dest), '%', dest2);
+ test_assert_idx(strcmp(csrc, str_c(dest2)) == 0, i);
+ }
+ test_end();
+}
+
+static void test_imap_utf7_bad_ascii(void)
+{
+ string_t *dest;
+ char csrc[1+1];
+ unsigned int i;
+
+ dest = t_str_new(256);
+
+ test_begin("imap mutf7 bad ascii");
+ for (i = 1; i <= 0x7f; ++i) {
+ if (i == ' ')
+ i = 0x7f;
+ csrc[0] = i;
+ csrc[1] = '\0';
+ test_assert_idx(!imap_utf7_is_valid(csrc), i);
+ str_truncate(dest, 0);
+ test_assert_idx(imap_utf7_to_utf8(csrc, dest) < 0, i);
+ }
+ test_end();
+}
+
+static void test_imap_utf7_unnecessary(void)
+{
+ string_t *dest;
+ char csrc[1+3+1+1];
+ unsigned int i;
+
+ dest = t_str_new(256);
+
+ test_begin("imap mutf7 unnecessary");
+ for (i = 0x20; i < 0x7f; ++i) {
+ /* Create an invalid escaped encoding of a simple char or '&' */
+ csrc[0] = '&';
+ csrc[1] = mb64[ (0x00 >> 2)];
+ csrc[2] = mb64[((0x00 & 0x03) << 4) | ( i >> 4)];
+ csrc[3] = mb64[(( i & 0x0f) << 2) | 0 ];
+ csrc[4] = '-';
+ csrc[5] = '\0';
+ test_assert_idx(!imap_utf7_is_valid(csrc), i);
+ str_truncate(dest, 0);
+ test_assert_idx(imap_utf7_to_utf8(csrc, dest) < 0, i);
+
+ /* All self-coding characters must self-code */
+ if (i == '&')
+ continue;
+ csrc[0] = i;
+ csrc[1] = '\0';
+ str_truncate(dest, 0);
+ test_assert_idx(imap_utf8_to_utf7(csrc, dest) >= 0, i);
+ test_assert_idx(strcmp(csrc, str_c(dest)) == 0, i);
+ }
+ test_end();
+}
+
+int main(void)
+{
+ static void (*const test_functions[])(void) = {
+ test_imap_utf7_by_example,
+ test_imap_utf7_ucs4_cases,
+ test_imap_utf7_non_utf16,
+ test_imap_utf7_bad_ascii,
+ test_imap_utf7_unnecessary,
+ NULL
+ };
+ return test_run(test_functions);
+}