aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libstrongswan/tests/suites/test_utils.c87
-rw-r--r--src/libstrongswan/utils/utils.c54
-rw-r--r--src/libstrongswan/utils/utils.h16
3 files changed, 155 insertions, 2 deletions
diff --git a/src/libstrongswan/tests/suites/test_utils.c b/src/libstrongswan/tests/suites/test_utils.c
index 3ca0412b4..2d290f81e 100644
--- a/src/libstrongswan/tests/suites/test_utils.c
+++ b/src/libstrongswan/tests/suites/test_utils.c
@@ -385,6 +385,89 @@ START_TEST(test_translate)
END_TEST
/*******************************************************************************
+ * strreplace
+ */
+
+static struct {
+ char *in;
+ char *out;
+ char *search;
+ char *replace;
+ bool allocated;
+} strreplace_data[] = {
+ /* invalid arguments */
+ {NULL, NULL, NULL, NULL, FALSE},
+ {"", "", NULL, NULL, FALSE},
+ {"", "", "", NULL, FALSE},
+ {"", "", NULL, "", FALSE},
+ {"", "", "", "", FALSE},
+ {"", "", "", "asdf", FALSE},
+ {"", "", "asdf", "", FALSE},
+ {"asdf", "asdf", NULL, NULL, FALSE},
+ {"asdf", "asdf", "", NULL, FALSE},
+ {"asdf", "asdf", NULL, "", FALSE},
+ {"asdf", "asdf", "", "", FALSE},
+ {"asdf", "asdf", "", "asdf", FALSE},
+ {"asdf", "asdf", "asdf", NULL, FALSE},
+ {"qwer", "qwer", "", "asdf", FALSE},
+ /* replacement shorter */
+ {"asdf", "", "asdf", "", TRUE},
+ {"asdfasdf", "", "asdf", "", TRUE},
+ {"asasdfdf", "asdf", "asdf", "", TRUE},
+ {"asdf", "df", "as", "", TRUE},
+ {"asdf", "as", "df", "", TRUE},
+ {"qwer", "qwer", "asdf", "", FALSE},
+ /* replacement same length */
+ {"a", "b", "a", "b", TRUE},
+ {"aaa", "bbb", "a", "b", TRUE},
+ {"aaa", "bbb", "aaa", "bbb", TRUE},
+ {"asdf", "asdf", "asdf", "asdf", TRUE},
+ {"qwer", "qwer", "asdf", "asdf", FALSE},
+ /* replacement longer */
+ {"asdf", "asdf", "", "asdf", FALSE},
+ {"asdf", "asdfasdf", "asdf", "asdfasdf", TRUE},
+ {"asdf", "asdfsdf", "a", "asdf", TRUE},
+ {"asdf", "asdasdf", "f", "asdf", TRUE},
+ {"aaa", "asdfasdfasdf", "a", "asdf", TRUE},
+ {"qwer", "qwer", "asdf", "asdfasdf", FALSE},
+ /* real examples */
+ {"http://x.org/no/spaces", "http://x.org/no/spaces", " ", "%20", FALSE},
+ {"http://x.org/end ", "http://x.org/end%20", " ", "%20", TRUE},
+ {" http://x.org/start", "%20http://x.org/start", " ", "%20", TRUE},
+ {" http://x.org/both ", "%20http://x.org/both%20", " ", "%20", TRUE},
+ {"http://x.org/ /slash", "http://x.org/%20/slash", " ", "%20", TRUE},
+ {"http://x.org/ /three", "http://x.org/%20%20%20/three", " ", "%20", TRUE},
+ {"http://x.org/ ", "http://x.org/%20%20%20%20%20%20", " ", "%20", TRUE},
+ {"http://x.org/%20/encoded", "http://x.org/%20/encoded", " ", "%20", FALSE},
+};
+
+START_TEST(test_strreplace)
+{
+ char *ret;
+
+ ret = strreplace(strreplace_data[_i].in, strreplace_data[_i].search,
+ strreplace_data[_i].replace);
+ if (ret && strreplace_data[_i].out)
+ {
+ ck_assert_str_eq(ret, strreplace_data[_i].out);
+ }
+ else
+ {
+ ck_assert(ret == strreplace_data[_i].out);
+ }
+ if (strreplace_data[_i].allocated)
+ {
+ ck_assert(ret != strreplace_data[_i].in);
+ free(ret);
+ }
+ else
+ {
+ ck_assert(ret == strreplace_data[_i].in);
+ }
+}
+END_TEST
+
+/*******************************************************************************
* time_printf_hook
*/
@@ -543,6 +626,10 @@ Suite *utils_suite_create()
tcase_add_loop_test(tc, test_translate, 0, countof(translate_data));
suite_add_tcase(s, tc);
+ tc = tcase_create("strreplace");
+ tcase_add_loop_test(tc, test_strreplace, 0, countof(strreplace_data));
+ suite_add_tcase(s, tc);
+
tc = tcase_create("printf_hooks");
tcase_add_loop_test(tc, test_time_printf_hook, 0, countof(time_data));
tcase_add_loop_test(tc, test_time_delta_printf_hook, 0, countof(time_delta_data));
diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c
index 4bacb5834..77d875445 100644
--- a/src/libstrongswan/utils/utils.c
+++ b/src/libstrongswan/utils/utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2008-2013 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -144,6 +144,58 @@ char* translate(char *str, const char *from, const char *to)
/**
* Described in header.
*/
+char* strreplace(const char *str, const char *search, const char *replace)
+{
+ size_t len, slen, rlen, count = 0;
+ char *res, *pos, *found, *dst;
+
+ if (!str || !*str || !search || !*search || !replace)
+ {
+ return (char*)str;
+ }
+ slen = strlen(search);
+ rlen = strlen(replace);
+ if (slen != rlen)
+ {
+ for (pos = (char*)str; (pos = strstr(pos, search)); pos += slen)
+ {
+ found = pos;
+ count++;
+ }
+ if (!count)
+ {
+ return (char*)str;
+ }
+ len = (found - str) + strlen(found) + count * (rlen - slen);
+ }
+ else
+ {
+ len = strlen(str);
+ }
+ found = strstr(str, search);
+ if (!found)
+ {
+ return (char*)str;
+ }
+ dst = res = malloc(len + 1);
+ pos = (char*)str;
+ do
+ {
+ len = found - pos;
+ memcpy(dst, pos, len);
+ dst += len;
+ memcpy(dst, replace, rlen);
+ dst += rlen;
+ pos = found + slen;
+ }
+ while ((found = strstr(pos, search)));
+ strcpy(dst, pos);
+ return res;
+}
+
+/**
+ * Described in header.
+ */
bool mkdir_p(const char *path, mode_t mode)
{
int len;
diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h
index cda7edf08..7e4bfb2de 100644
--- a/src/libstrongswan/utils/utils.h
+++ b/src/libstrongswan/utils/utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2008-2013 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -472,6 +472,20 @@ void *memstr(const void *haystack, const char *needle, size_t n);
char *translate(char *str, const char *from, const char *to);
/**
+ * Replaces all occurences of search in the given string with replace.
+ *
+ * Allocates memory only if anything is replaced in the string. The original
+ * string is also returned if any of the arguments are invalid (e.g. if search
+ * is empty or any of them are NULL).
+ *
+ * @param str original string
+ * @param search string to search for and replace
+ * @param replace string to replace found occurences with
+ * @return allocated string, if anything got replaced, str otherwise
+ */
+char *strreplace(const char *str, const char *search, const char *replace);
+
+/**
* Creates a directory and all required parent directories.
*
* @param path path to the new directory