Mercurial > dovecot > core-2.2
changeset 10637:2cfe01556d6c HEAD
lib-dict: Added dict_[un]escape_string().
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 05 Feb 2010 19:23:42 +0200 |
parents | 7ebf82401e7a |
children | 05ae3f2e079e |
files | src/lib-dict/Makefile.am src/lib-dict/dict.c src/lib-dict/dict.h src/lib-dict/test-dict.c |
diffstat | 4 files changed, 138 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-dict/Makefile.am Fri Feb 05 18:04:16 2010 +0200 +++ b/src/lib-dict/Makefile.am Fri Feb 05 19:23:42 2010 +0200 @@ -5,6 +5,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib-test \ -I$(top_srcdir)/src/lib-sql \ -I$(top_srcdir)/src/lib-settings \ $(SQL_CFLAGS) @@ -72,3 +73,22 @@ distclean-generic: rm -f Makefile dict-drivers-register.c + +test_programs = \ + test-dict + +noinst_PROGRAMS = $(test_programs) + +test_libs = \ + ../lib-test/libtest.la \ + ../lib/liblib.la + +test_dict_SOURCES = test-dict.c +test_dict_LDADD = dict.lo $(test_libs) +test_dict_DEPENDENCIES = dict.lo $(test_libs) + +check: check-am check-test +check-test: all-am + for bin in $(test_programs); do \ + if ! ./$$bin; then exit 1; fi; \ + done
--- a/src/lib-dict/dict.c Fri Feb 05 18:04:16 2010 +0200 +++ b/src/lib-dict/dict.c Fri Feb 05 19:23:42 2010 +0200 @@ -2,6 +2,7 @@ #include "lib.h" #include "array.h" +#include "str.h" #include "dict-sql.h" #include "dict-private.h" @@ -194,3 +195,72 @@ ctx->changed = TRUE; } } + +const char *dict_escape_string(const char *str) +{ + const char *p; + string_t *ret; + + /* see if we need to escape it */ + for (p = str; *p != '\0'; p++) { + if (*p == '/' || *p == '\\') + break; + } + + if (*p == '\0') + return str; + + /* escape */ + ret = t_str_new((size_t) (p - str) + 128); + str_append_n(ret, str, (size_t) (p - str)); + + for (; *p != '\0'; p++) { + switch (*p) { + case '/': + str_append_c(ret, '\\'); + str_append_c(ret, '|'); + break; + case '\\': + str_append_c(ret, '\\'); + str_append_c(ret, '\\'); + break; + default: + str_append_c(ret, *p); + break; + } + } + return str_c(ret); +} + +const char *dict_unescape_string(const char *str) +{ + const char *p; + string_t *ret; + + /* see if we need to unescape it */ + for (p = str; *p != '\0'; p++) { + if (*p == '\\') + break; + } + + if (*p == '\0') + return str; + + /* unescape */ + ret = t_str_new((size_t) (p - str) + strlen(p) + 1); + str_append_n(ret, str, (size_t) (p - str)); + + for (; *p != '\0'; p++) { + if (*p != '\\') + str_append_c(ret, *p); + else { + if (*++p == '|') + str_append_c(ret, '/'); + else if (*p == '\0') + break; + else + str_append_c(ret, *p); + } + } + return str_c(ret); +}
--- a/src/lib-dict/dict.h Fri Feb 05 18:04:16 2010 +0200 +++ b/src/lib-dict/dict.h Fri Feb 05 19:23:42 2010 +0200 @@ -81,4 +81,9 @@ void dict_atomic_inc(struct dict_transaction_context *ctx, const char *key, long long diff); +/* Escape/unescape '/' characters in a string, so that it can be safely added + into path components in dict keys. */ +const char *dict_escape_string(const char *str); +const char *dict_unescape_string(const char *str); + #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-dict/test-dict.c Fri Feb 05 19:23:42 2010 +0200 @@ -0,0 +1,43 @@ +/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "dict-private.h" +#include "test-common.h" + +struct dict dict_driver_client; +struct dict dict_driver_file; + +static void test_dict_escape(void) +{ + static const char *input[] = { + "", "", + "foo", "foo", + "foo\\", "foo\\\\", + "foo\\bar", "foo\\\\bar", + "\\bar", "\\\\bar", + "foo/", "foo\\|", + "foo/bar", "foo\\|bar", + "/bar", "\\|bar", + "////", "\\|\\|\\|\\|", + "/", "\\|" + }; + unsigned int i; + + test_begin("dict escape"); + for (i = 0; i < N_ELEMENTS(input); i += 2) { + test_assert(strcmp(dict_escape_string(input[i]), input[i+1]) == 0); + test_assert(strcmp(dict_unescape_string(input[i+1]), input[i]) == 0); + } + test_assert(strcmp(dict_unescape_string("x\\"), "x") == 0); + test_assert(strcmp(dict_unescape_string("\\"), "") == 0); + test_end(); +} + +int main(void) +{ + static void (*test_functions[])(void) = { + test_dict_escape, + NULL + }; + return test_run(test_functions); +}