dovecot-2.0: lib-dict: Added dict_[un]escape_string().

dovecot at dovecot.org dovecot at dovecot.org
Fri Feb 5 19:23:46 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/2cfe01556d6c
changeset: 10637:2cfe01556d6c
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Feb 05 19:23:42 2010 +0200
description:
lib-dict: Added dict_[un]escape_string().

diffstat:

4 files changed, 138 insertions(+)
src/lib-dict/Makefile.am |   20 +++++++++++++
src/lib-dict/dict.c      |   70 ++++++++++++++++++++++++++++++++++++++++++++++
src/lib-dict/dict.h      |    5 +++
src/lib-dict/test-dict.c |   43 ++++++++++++++++++++++++++++

diffs (178 lines):

diff -r 7ebf82401e7a -r 2cfe01556d6c src/lib-dict/Makefile.am
--- 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 @@ 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_source
 
 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
diff -r 7ebf82401e7a -r 2cfe01556d6c src/lib-dict/dict.c
--- 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 @@ void dict_atomic_inc(struct dict_transac
 		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);
+}
diff -r 7ebf82401e7a -r 2cfe01556d6c src/lib-dict/dict.h
--- 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_transac
 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 -r 7ebf82401e7a -r 2cfe01556d6c src/lib-dict/test-dict.c
--- /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);
+}


More information about the dovecot-cvs mailing list