]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added str_append_tabunescaped(). str_tabescape*() now escapes also CR. Added unit...
authorTimo Sirainen <tss@iki.fi>
Tue, 16 Jun 2009 17:49:18 +0000 (13:49 -0400)
committerTimo Sirainen <tss@iki.fi>
Tue, 16 Jun 2009 17:49:18 +0000 (13:49 -0400)
--HG--
branch : HEAD

src/lib/Makefile.am
src/lib/strescape.c
src/lib/strescape.h
src/lib/test-lib.c
src/lib/test-lib.h
src/lib/test-strescape.c [new file with mode: 0644]

index 57f3e2f2b268665b7589a33c003d15a418411a35..9e0655d084c2a6cfd24be9381d1ce21c48283b84 100644 (file)
@@ -221,6 +221,7 @@ test_lib_SOURCES = \
        test-primes.c \
        test-priorityq.c \
        test-seq-range-array.c \
+       test-strescape.c \
        test-str-find.c \
        test-str-sanitize.c \
        test-utc-mktime.c
index 4d08a105f7705f659df064ceaf4b73c18124d473..aa8c154f77a797eb568b030c4f27afbb791968e8 100644 (file)
@@ -65,8 +65,11 @@ char *str_unescape(char *str)
        }
 
        for (dest = str; *str != '\0'; str++) {
-               if (*str == '\\' && str[1] != '\0')
+               if (*str == '\\') {
                        str++;
+                       if (*str == '\0')
+                               break;
+               }
 
                *dest++ = *str;
        }
@@ -87,6 +90,10 @@ void str_tabescape_write(string_t *dest, const char *src)
                        str_append_c(dest, '\001');
                        str_append_c(dest, 't');
                        break;
+               case '\r':
+                       str_append_c(dest, '\001');
+                       str_append_c(dest, 'r');
+                       break;
                case '\n':
                        str_append_c(dest, '\001');
                        str_append_c(dest, 'n');
@@ -104,7 +111,7 @@ const char *str_tabescape(const char *str)
        const char *p;
 
        for (p = str; *p != '\0'; p++) {
-               if (*p <= '\n') {
+               if (*p <= '\r') {
                        tmp = t_str_new(128);
                        str_append_n(tmp, str, p-str);
                        str_tabescape_write(tmp, p);
@@ -113,3 +120,44 @@ const char *str_tabescape(const char *str)
        }
        return str;
 }
+
+void str_append_tabunescaped(string_t *dest, const void *src, size_t src_size)
+{
+       const unsigned char *src_c = src;
+       size_t start = 0, i = 0;
+
+       while (i < src_size) {
+               start = i;
+               for (; i < src_size; i++) {
+                       if (src_c[i] == '\001')
+                               break;
+               }
+
+               str_append_n(dest, src_c + start, i-start);
+
+               if (i < src_size) {
+                       i++;
+                       if (i < src_size) {
+                               switch (src_c[i]) {
+                               case '1':
+                                       str_append_c(dest, '\001');
+                                       break;
+                               case 't':
+                                       str_append_c(dest, '\t');
+                                       break;
+                               case 'r':
+                                       str_append_c(dest, '\r');
+                                       break;
+                               case 'n':
+                                       str_append_c(dest, '\n');
+                                       break;
+                               default:
+                                       str_append_c(dest, src_c[i]);
+                                       break;
+                               }
+                               i++;
+                       }
+               }
+               start = i;
+       }
+}
index 0918b65bf9d6f1627ee134d8d128d82a66735f1d..c9d6ee159ba8f66bb0429cd1a06b1145245ea95f 100644 (file)
@@ -12,9 +12,10 @@ void str_append_unescaped(string_t *dest, const void *src, size_t src_size);
 /* remove all '\' characters */
 char *str_unescape(char *str);
 
-/* For Dovecot's internal protocols: Escape \001, \t and \n characters
+/* For Dovecot's internal protocols: Escape \001, \t, \r and \n characters
    using \001. */
 const char *str_tabescape(const char *str);
 void str_tabescape_write(string_t *dest, const char *src);
+void str_append_tabunescaped(string_t *dest, const void *src, size_t src_size);
 
 #endif
index 21cd0bbb78cae4b1b45064e22d96ce6809181558..fa6befdfb8bfceb2d3ea2ec6c86616b854297a33 100644 (file)
@@ -16,6 +16,7 @@ int main(void)
                test_primes,
                test_priorityq,
                test_seq_range_array,
+               test_strescape,
                test_str_find,
                test_str_sanitize,
                test_utc_mktime,
index 97c1b9686a99a4cfc66f90456ae417db530e9930..84ca1d5a99256f19d7cdb6ebcc36b8fcacda4c82 100644 (file)
@@ -15,6 +15,7 @@ void test_network(void);
 void test_primes(void);
 void test_priorityq(void);
 void test_seq_range_array(void);
+void test_strescape(void);
 void test_str_find(void);
 void test_str_sanitize(void);
 void test_utc_mktime(void);
diff --git a/src/lib/test-strescape.c b/src/lib/test-strescape.c
new file mode 100644 (file)
index 0000000..165b0a9
--- /dev/null
@@ -0,0 +1,72 @@
+/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
+
+#include "test-lib.h"
+#include "str.h"
+#include "strescape.h"
+
+struct strinput {
+       const char *input;
+       const char *output;
+};
+
+void test_strescape(void)
+{
+       static struct strinput unesc[] = {
+               { "foo", "foo" },
+               { "\\\\\\\\\\\"\\\"\\\'\\\'", "\\\\\"\"\'\'" },
+               { "\\a\\n\\r\\", "anr" }
+       };
+       static struct strinput tabesc[] = {
+               { "foo", "foo" },
+               { "\001", "\0011" },
+               { "\t", "\001t" },
+               { "\r", "\001r" },
+               { "\n", "\001n" },
+               { "\001\001\t\t\r\r\n\n", "\0011\0011\001t\001t\001r\001r\001n\001n" }
+       };
+       unsigned char buf[1 << CHAR_BIT];
+       const char *escaped;
+       string_t *str;
+       unsigned int i;
+
+       test_begin("str_escape");
+       for (i = 1; i < sizeof(buf); i++)
+               buf[i-1] = i;
+       buf[i-1] = '\0';
+
+       escaped = str_escape((char *)buf);
+       test_assert(strlen(escaped) == (1 << CHAR_BIT) - 1 + 3);
+       test_assert(escaped['\"'-1] == '\\'); /* 34 */
+       test_assert(escaped['\"'] == '\"');
+       test_assert(escaped['\''+1-1] == '\\'); /* 39 */
+       test_assert(escaped['\''+1] == '\'');
+       test_assert(escaped['\\'+2-1] == '\\'); /* 92 */
+       test_assert(escaped['\\'+2] == '\\');
+       test_assert(strcmp(str_escape("\\\\\"\"\'\'"),
+                          "\\\\\\\\\\\"\\\"\\\'\\\'") == 0);
+       test_end();
+
+       str = t_str_new(256);
+       test_begin("str_unescape");
+       for (i = 0; i < N_ELEMENTS(unesc); i++) {
+               test_assert(strcmp(str_unescape(t_strdup_noconst(unesc[i].input)),
+                                  unesc[i].output) == 0);
+               str_truncate(str, 0);
+               str_append_unescaped(str, unesc[i].input, strlen(unesc[i].input));
+               test_assert(strcmp(str_c(str), unesc[i].output) == 0);
+       }
+       test_end();
+
+       test_begin("str_tabescape");
+       for (i = 0; i < N_ELEMENTS(tabesc); i++) {
+               test_assert(strcmp(str_tabescape(tabesc[i].input),
+                                  tabesc[i].output) == 0);
+               str_truncate(str, 0);
+               str_append_tabunescaped(str, tabesc[i].output, strlen(tabesc[i].output));
+               test_assert(strcmp(str_c(str), tabesc[i].input) == 0);
+       }
+       str_truncate(str, 0);
+       str_append_tabunescaped(str, "\0012\001l\001", strlen("\0012\001l\001"));
+       test_assert(strcmp(str_c(str), "2l") == 0);
+       test_end();
+}