[network-manager-openvpn/th/utf8safe-bgo763039: 3/5] utils: add nmv_utils_str_utf8safe_escape()
- From: Thomas Haller <thaller src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-openvpn/th/utf8safe-bgo763039: 3/5] utils: add nmv_utils_str_utf8safe_escape()
- Date: Thu, 3 Mar 2016 12:20:10 +0000 (UTC)
commit 35d2c41ad96c71cacf4e63e8b8482fbcb034b81c
Author: Thomas Haller <thaller redhat com>
Date: Thu Mar 3 10:15:09 2016 +0100
utils: add nmv_utils_str_utf8safe_escape()
properties/tests/test-import-export.c | 78 +++++++++++++++++++++++
shared/utils.c | 110 +++++++++++++++++++++++++++++++++
shared/utils.h | 5 ++
3 files changed, 193 insertions(+), 0 deletions(-)
---
diff --git a/properties/tests/test-import-export.c b/properties/tests/test-import-export.c
index 763e785..612675a 100644
--- a/properties/tests/test-import-export.c
+++ b/properties/tests/test-import-export.c
@@ -31,6 +31,7 @@
#include "nm-openvpn.h"
#include "nm-openvpn-service-defines.h"
#include "import-export.h"
+#include "utils.h"
#include "nm-test-utils.h"
@@ -1302,6 +1303,81 @@ test_args_parse_line (void)
/*****************************************************************************/
+static void
+do_test_utils_str_utf8safe (const char *str, const char *expected)
+{
+ const char *str_safe, *s;
+ gs_free char *str2 = NULL;
+ gs_free char *str3 = NULL;
+
+ str_safe = nmv_utils_str_utf8safe_escape_c (str, &str2);
+
+ str3 = nmv_utils_str_utf8safe_escape (str);
+ g_assert_cmpstr (str3, ==, str_safe);
+ g_assert ((!str && !str3) || (str != str3));
+ g_clear_pointer (&str3, g_free);
+
+ if (expected == NULL) {
+ g_assert (str_safe == str);
+ g_assert (!str2);
+ if (str) {
+ g_assert (!strchr (str, '\\'));
+ g_assert (g_utf8_validate (str, -1, NULL));
+ }
+
+ g_assert (str == nmv_utils_str_utf8safe_unescape_c (str_safe, &str3));
+ g_assert (!str3);
+
+ str3 = nmv_utils_str_utf8safe_unescape (str_safe);
+ if (str) {
+ g_assert (str3 != str);
+ g_assert_cmpstr (str3, ==, str);
+ } else
+ g_assert (!str3);
+ g_clear_pointer (&str3, g_free);
+ return;
+ }
+
+ g_assert (str);
+ g_assert (str_safe != str);
+ g_assert (str_safe == str2);
+ g_assert (strchr (str, '\\') || !g_utf8_validate (str, -1, NULL));
+ g_assert (g_utf8_validate (str_safe, -1, NULL));
+
+ str3 = g_strcompress (str_safe);
+ g_assert_cmpstr (str, ==, str3);
+ g_clear_pointer (&str3, g_free);
+
+ str3 = nmv_utils_str_utf8safe_unescape (str_safe);
+ g_assert (str3 != str);
+ g_assert_cmpstr (str3, ==, str);
+ g_clear_pointer (&str3, g_free);
+
+ s = nmv_utils_str_utf8safe_unescape_c (str_safe, &str3);
+ g_assert (str3 != str);
+ g_assert (s == str3);
+ g_assert_cmpstr (str3, ==, str);
+ g_clear_pointer (&str3, g_free);
+
+ g_assert_cmpstr (str_safe, ==, expected);
+}
+
+static void
+test_utils_str_utf8safe (void)
+{
+ do_test_utils_str_utf8safe (NULL, NULL);
+ do_test_utils_str_utf8safe ("", NULL);
+ do_test_utils_str_utf8safe ("a", NULL);
+ do_test_utils_str_utf8safe ("ab", NULL);
+ do_test_utils_str_utf8safe ("abäb", NULL);
+ do_test_utils_str_utf8safe ("㈞abä㈞b", NULL);
+ do_test_utils_str_utf8safe ("Äab\\äb", "Äab\\\\äb");
+ do_test_utils_str_utf8safe ("ÄÄab\\äb", "ÄÄab\\\\äb");
+ do_test_utils_str_utf8safe ("Ä\304ab\\äb", "Ä\\304ab\\\\äb");
+}
+
+/*****************************************************************************/
+
NMTST_DEFINE ();
int main (int argc, char **argv)
@@ -1376,6 +1452,8 @@ int main (int argc, char **argv)
_add_test_func_simple (test_args_parse_line);
+ _add_test_func_simple (test_utils_str_utf8safe);
+
result = g_test_run ();
if (result != EXIT_SUCCESS)
return result;
diff --git a/shared/utils.c b/shared/utils.c
index b777d9f..0731aff 100644
--- a/shared/utils.c
+++ b/shared/utils.c
@@ -170,3 +170,113 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma
/*****************************************************************************/
+/**
+ * nmv_utils_str_utf8safe_escape:
+ * @str: NUL terminated input string, possibly in utf-8 encoding
+ *
+ * Does something similar like g_strescape(), where the operation
+ * can be reverted by g_strcompress(). However, the UTF-8 characters
+ * are not escaped at all (except the escape character '\\'). It only
+ * escapes non-UTF-8 characters. This way it is possible to transfer
+ * the string as UTF-8 via D-Bus.
+ * Also, it can be directly displayed to the user and will show as
+ * UTF-8, with exception of the escape character and characters in
+ * different encodings.
+ *
+ * Returns: the escaped input string in UTF-8 encoding. The returned
+ * value should be freed with g_free().
+ * The escaping can be reverted by g_strcompress().
+ **/
+char *
+nmv_utils_str_utf8safe_escape (const char *str)
+{
+ char *s = NULL;
+
+ nmv_utils_str_utf8safe_escape_c (str, &s);
+ return s ? : g_strdup (str);
+}
+
+/**
+ * nmv_utils_str_utf8safe_escape_c:
+ * @str: NUL terminated input string, possibly in utf-8 encoding
+ * @str_free: (out): return the pointer location of the string
+ * if a copying was necessary.
+ *
+ * Like nmv_utils_str_utf8safe_escape(), except that the string
+ * is only copied if it is actually necessary. In that case,
+ * @str_free will contain the allocated string which must be
+ * freed with g_free().
+ * Otherwise, @str_free is %NULL and the input string is returned.
+ *
+ * Returns: the escaped input string. If no escaping is necessary,
+ * it returns @str. Otherwise, an allocated string @str_free is
+ * returned.
+ * The escaping can be reverted by g_strcompress().
+ **/
+const char *
+nmv_utils_str_utf8safe_escape_c (const char *str, char **str_free)
+{
+ const char *p = NULL;
+ guchar ch;
+ GString *s;
+
+ g_return_val_if_fail (str_free, NULL);
+
+ *str_free = NULL;
+ if (!str || !str[0])
+ return str;
+
+ if (g_utf8_validate (str, -1, &p)) {
+ if (!strchr (str, '\\'))
+ return str;
+ }
+
+ s = g_string_sized_new (30);
+
+ do {
+ for (; str < p; str++) {
+ if (str[0] == '\\')
+ g_string_append (s, "\\\\");
+ else
+ g_string_append_c (s, str[0]);
+ }
+
+ ch = p[0];
+ if (ch == '\0')
+ break;
+ g_string_append_c (s, '\\');
+ g_string_append_c (s, '0' + ((ch >> 6) & 07));
+ g_string_append_c (s, '0' + ((ch >> 3) & 07));
+ g_string_append_c (s, '0' + ( ch & 07));
+
+ str = &p[1];
+ g_utf8_validate (str, -1, &p);
+ } while (TRUE);
+
+ *str_free = g_string_free (s, FALSE);
+ return *str_free;
+}
+
+char *
+nmv_utils_str_utf8safe_unescape (const char *str)
+{
+ if (!str)
+ return NULL;
+ return g_strcompress (str);
+}
+
+const char *
+nmv_utils_str_utf8safe_unescape_c (const char *str, char **str_free)
+{
+ g_return_val_if_fail (str_free, NULL);
+
+ if (!str || !strchr (str, '\\')) {
+ *str_free = NULL;
+ return str;
+ }
+ *str_free = g_strcompress (str);
+ return *str_free;
+}
+
+/*****************************************************************************/
+
diff --git a/shared/utils.h b/shared/utils.h
index 4571a77..3853c6c 100644
--- a/shared/utils.h
+++ b/shared/utils.h
@@ -30,5 +30,10 @@ gboolean is_encrypted (const char *filename);
gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
+char * nmv_utils_str_utf8safe_escape (const char *str);
+const char *nmv_utils_str_utf8safe_escape_c (const char *str, char **out_clone);
+char * nmv_utils_str_utf8safe_unescape (const char *str);
+const char *nmv_utils_str_utf8safe_unescape_c (const char *str, char **str_free);
+
#endif /* UTILS_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]