]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-dict: Added dict_[un]escape_string().
authorTimo Sirainen <tss@iki.fi>
Fri, 5 Feb 2010 17:23:42 +0000 (19:23 +0200)
committerTimo Sirainen <tss@iki.fi>
Fri, 5 Feb 2010 17:23:42 +0000 (19:23 +0200)
--HG--
branch : HEAD

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

index 3ab68d0dd2c4d4cc9c475012c136205aa4d2a945..a20a1ea37bf12e401b0ceb88cf9c5358eada0d34 100644 (file)
@@ -5,6 +5,7 @@ dict_drivers = @dict_drivers@
 
 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 @@ DISTFILES = $(DIST_COMMON) $(base_sources) $(backend_sources) $(HEADERS) $(TEXIN
 
 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
index 50fbfa784ebd1270c694e1e31b7dfa4a01939b0b..7e955e95352a6bec735504619df4c0366c2d593f 100644 (file)
@@ -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 @@ void dict_atomic_inc(struct dict_transaction_context *ctx,
                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);
+}
index 540658175b37df9634a63b580be6a824514735ba..8f15ae979421bb1bcdb6a4916d5d075c3e342f8e 100644 (file)
@@ -81,4 +81,9 @@ void dict_unset(struct dict_transaction_context *ctx,
 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
diff --git a/src/lib-dict/test-dict.c b/src/lib-dict/test-dict.c
new file mode 100644 (file)
index 0000000..65998b4
--- /dev/null
@@ -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);
+}