Mercurial > dovecot > core-2.2
changeset 9484:5a6fe52a0cfc HEAD
Added str_append_tabunescaped(). str_tabescape*() now escapes also CR. Added unit tests.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 16 Jun 2009 13:49:18 -0400 |
parents | 464116e1d0ae |
children | acbbd522be43 |
files | 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 |
diffstat | 6 files changed, 127 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/Makefile.am Tue Jun 16 13:39:40 2009 -0400 +++ b/src/lib/Makefile.am Tue Jun 16 13:49:18 2009 -0400 @@ -221,6 +221,7 @@ 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
--- a/src/lib/strescape.c Tue Jun 16 13:39:40 2009 -0400 +++ b/src/lib/strescape.c Tue Jun 16 13:49:18 2009 -0400 @@ -65,8 +65,11 @@ } for (dest = str; *str != '\0'; str++) { - if (*str == '\\' && str[1] != '\0') + if (*str == '\\') { str++; + if (*str == '\0') + break; + } *dest++ = *str; } @@ -87,6 +90,10 @@ 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 *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 @@ } 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; + } +}
--- a/src/lib/strescape.h Tue Jun 16 13:39:40 2009 -0400 +++ b/src/lib/strescape.h Tue Jun 16 13:49:18 2009 -0400 @@ -12,9 +12,10 @@ /* 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
--- a/src/lib/test-lib.c Tue Jun 16 13:39:40 2009 -0400 +++ b/src/lib/test-lib.c Tue Jun 16 13:49:18 2009 -0400 @@ -16,6 +16,7 @@ test_primes, test_priorityq, test_seq_range_array, + test_strescape, test_str_find, test_str_sanitize, test_utc_mktime,
--- a/src/lib/test-lib.h Tue Jun 16 13:39:40 2009 -0400 +++ b/src/lib/test-lib.h Tue Jun 16 13:49:18 2009 -0400 @@ -15,6 +15,7 @@ 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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/test-strescape.c Tue Jun 16 13:49:18 2009 -0400 @@ -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(); +}