From: Daniel Carl Date: Wed, 13 Jun 2018 22:29:24 +0000 (+0200) Subject: Do not damage utf8 string on escape. X-Git-Url: https://git.owens.tech///git?a=commitdiff_plain;h=c8eb577660d2849a9289720dcd9c012f7a85a15a;p=vimb.git Do not damage utf8 string on escape. This fixes #492. --- diff --git a/src/input.c b/src/input.c index c02f185..220cbb1 100644 --- a/src/input.c +++ b/src/input.c @@ -211,7 +211,7 @@ static void resume_editor(GPid pid, int status, EditorData *data) text = util_get_file_contents(data->file, NULL); if (text) { - escaped = g_strescape(text, NULL); + escaped = util_strescape(text, NULL); /* put the text back into the element */ if (data->element_id && strlen(data->element_id) > 0) { diff --git a/src/util.c b/src/util.c index bef3800..7c94dcc 100644 --- a/src/util.c +++ b/src/util.c @@ -796,6 +796,52 @@ char *util_str_replace(const char *search, const char *replace, const char *stri return ret; } +/** + * Escapes some special characters in the source string by inserting a '\' + * before them. Acts like g_strescape() but does not demage utf8 chars. + * Returns a newly allocated string. + */ +char *util_strescape(const char *source, const char *exceptions) +{ + GString *result = g_string_new(NULL); + while (TRUE) { + char c = *source++; + if ('\0' == c) { + goto done; + } + if (exceptions && !strchr(exceptions, c)) { + continue; + } + switch (c) { + case '\n': + g_string_append(result, "\\n"); + break; + case '\"': + g_string_append(result, "\\\""); + break; + case '\\': + g_string_append(result, "\\\\"); + break; + case '\b': + g_string_append(result, "\\b"); + break; + case '\f': + g_string_append(result, "\\f"); + break; + case '\r': + g_string_append(result, "\\r"); + break; + case '\t': + g_string_append(result, "\\t"); + break; + default: + g_string_append_c(result, c); + } + } +done: + return g_string_free(result, FALSE); +} + static void create_dir_if_not_exists(const char *dirpath) { if (!g_file_test(dirpath, G_FILE_TEST_IS_DIR)) { diff --git a/src/util.h b/src/util.h index 14dc3bb..5c6aba9 100644 --- a/src/util.h +++ b/src/util.h @@ -56,6 +56,7 @@ char *util_sanitize_filename(char *filename); char *util_sanitize_uri(const char *uri_str); char *util_strcasestr(const char *haystack, const char *needle); char *util_str_replace(const char* search, const char* replace, const char* string); +char *util_strescape(const char *source, const char *exceptions); gboolean util_wildmatch(const char *pattern, const char *subject); #endif /* end of include guard: _UTIL_H */ diff --git a/tests/test-util.c b/tests/test-util.c index d03ac57..ad3f1cb 100644 --- a/tests/test-util.c +++ b/tests/test-util.c @@ -262,6 +262,35 @@ static void test_wildmatch_multi(void) g_assert_false(util_wildmatch("foo,?", "fo")); } +static void test_strescape(void) +{ + unsigned int i; + char *value; + struct { + char *in; + char *expected; + char *excludes; + } data[] = { + {"", "", NULL}, + {"foo", "foo", NULL}, + {"a\nb\nc", "a\\nb\\nc", NULL}, + {"foo\"bar", "foo\\bar", NULL}, + {"s\\t", "s\\\\t", NULL}, + {"u\bv", "u\\bv", NULL}, + {"w\fx", "w\\fx", NULL}, + {"y\rz", "y\\rz", NULL}, + {"tab\tdi\t", "tab\\tdi\\t", NULL}, + {"❧äüö\n@foo\t\"bar\"", "❧äüö\\n@foo\\t\\\"bar\\\"", NULL}, + {"❧äüö\n@foo\t\"bar\"", "❧äüö\\n@foo\\t\"bar\"", "\""}, + {"❧äüö\n@foo\t\"bar\"", "❧äüö\n@foo\t\\\"bar\\\"", "\n\t"}, + }; + for (i = 0; i < LENGTH(data); i++) { + value = util_strescape(data->in, data->excludes); + g_assert_cmpstr(value, ==, data->expected); + g_free(value); + } +} + int main(int argc, char *argv[]) { g_test_init(&argc, &argv, NULL); @@ -279,6 +308,7 @@ int main(int argc, char *argv[]) g_test_add_func("/test-util/wildmatch-curlybraces", test_wildmatch_curlybraces); g_test_add_func("/test-util/wildmatch-complete", test_wildmatch_complete); g_test_add_func("/test-util/wildmatch-multi", test_wildmatch_multi); + g_test_add_func("/test-util/strescape", test_strescape); return g_test_run(); }