shared: support stripping whitespace from nm_utils_buf_utf8safe_unescape()
When parsing user input if is often convenient to allow stripping whitespace. Especially with escaped strings, the user could still escape the whitespace, if the space should be taken literally. Add support for that to nm_utils_buf_utf8safe_unescape(). Note that this is not the same as calling g_strstrip() before/after unescape. That is, because nm_utils_buf_utf8safe_unescape() correctly preserves escaped whitespace. If you call g_strstrip() before/after the unescape, you don't know whether the whitespace is escaped.
This commit is contained in:
@@ -2186,7 +2186,7 @@ nm_ip_routing_rule_get_xifname_bin (const NMIPRoutingRule *self,
|
||||
if (!xifname)
|
||||
return FALSE;
|
||||
|
||||
bin = nm_utils_buf_utf8safe_unescape (xifname, &len, &bin_to_free);
|
||||
bin = nm_utils_buf_utf8safe_unescape (xifname, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &len, &bin_to_free);
|
||||
|
||||
strncpy (out_xifname, bin, 16 /* IFNAMSIZ */);
|
||||
out_xifname[15] = '\0';
|
||||
|
@@ -4673,7 +4673,7 @@ nm_utils_is_valid_iface_name_utf8safe (const char *utf8safe_name)
|
||||
|
||||
g_return_val_if_fail (utf8safe_name, FALSE);
|
||||
|
||||
bin = nm_utils_buf_utf8safe_unescape (utf8safe_name, &len, &bin_to_free);
|
||||
bin = nm_utils_buf_utf8safe_unescape (utf8safe_name, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &len, &bin_to_free);
|
||||
|
||||
if (bin_to_free) {
|
||||
/* some unescaping happened... */
|
||||
|
@@ -7815,7 +7815,7 @@ _do_test_utils_str_utf8safe_unescape (const char *str, const char *expected, gsi
|
||||
gs_free gpointer buf_free_1 = NULL;
|
||||
gs_free char *str_free_1 = NULL;
|
||||
|
||||
s = nm_utils_buf_utf8safe_unescape (str, &l, &buf_free_1);
|
||||
s = nm_utils_buf_utf8safe_unescape (str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &l, &buf_free_1);
|
||||
g_assert_cmpint (expected_len, ==, l);
|
||||
g_assert_cmpstr (s, ==, expected);
|
||||
|
||||
@@ -7839,7 +7839,7 @@ _do_test_utils_str_utf8safe_unescape (const char *str, const char *expected, gsi
|
||||
if ( expected
|
||||
&& l == strlen (expected)) {
|
||||
/* there are no embeeded NULs. Check that nm_utils_str_utf8safe_unescape() yields the same result. */
|
||||
s = nm_utils_str_utf8safe_unescape (str, &str_free_1);
|
||||
s = nm_utils_str_utf8safe_unescape (str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_1);
|
||||
g_assert_cmpstr (s, ==, expected);
|
||||
if (strchr (str, '\\')) {
|
||||
g_assert (str_free_1 != str);
|
||||
@@ -7908,10 +7908,10 @@ _do_test_utils_str_utf8safe (const char *str, gsize str_len, const char *expecte
|
||||
g_assert (g_utf8_validate (str, -1, NULL));
|
||||
}
|
||||
|
||||
g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, &str_free_4));
|
||||
g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_4));
|
||||
g_assert (!str_free_4);
|
||||
|
||||
str_free_5 = nm_utils_str_utf8safe_unescape_cp (str_safe);
|
||||
str_free_5 = nm_utils_str_utf8safe_unescape_cp (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
if (str) {
|
||||
g_assert (str_free_5 != str);
|
||||
g_assert_cmpstr (str_free_5, ==, str);
|
||||
@@ -7935,11 +7935,11 @@ _do_test_utils_str_utf8safe (const char *str, gsize str_len, const char *expecte
|
||||
str_free_6 = g_strcompress (str_safe);
|
||||
g_assert_cmpstr (str, ==, str_free_6);
|
||||
|
||||
str_free_7 = nm_utils_str_utf8safe_unescape_cp (str_safe);
|
||||
str_free_7 = nm_utils_str_utf8safe_unescape_cp (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
g_assert (str_free_7 != str);
|
||||
g_assert_cmpstr (str_free_7, ==, str);
|
||||
|
||||
s = nm_utils_str_utf8safe_unescape (str_safe, &str_free_8);
|
||||
s = nm_utils_str_utf8safe_unescape (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_8);
|
||||
g_assert (str_free_8 != str);
|
||||
g_assert (s == str_free_8);
|
||||
g_assert_cmpstr (str_free_8, ==, str);
|
||||
|
@@ -139,7 +139,7 @@ _fixup_string (const char *desc,
|
||||
return NULL;
|
||||
|
||||
/* restore original non-UTF-8-safe text. */
|
||||
desc_full = nm_utils_str_utf8safe_unescape_cp (desc);
|
||||
desc_full = nm_utils_str_utf8safe_unescape_cp (desc, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
|
||||
/* replace all invalid UTF-8 bytes with space. */
|
||||
p = desc_full;
|
||||
|
@@ -2456,11 +2456,12 @@ _str_buf_append_c_escape_octal (NMStrBuf *strbuf,
|
||||
}
|
||||
|
||||
gconstpointer
|
||||
nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_free)
|
||||
nm_utils_buf_utf8safe_unescape (const char *str, NMUtilsStrUtf8SafeFlags flags, gsize *out_len, gpointer *to_free)
|
||||
{
|
||||
gboolean strip_spaces = NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES);
|
||||
NMStrBuf strbuf;
|
||||
gsize len;
|
||||
const char *s;
|
||||
gsize len;
|
||||
|
||||
g_return_val_if_fail (to_free, NULL);
|
||||
g_return_val_if_fail (out_len, NULL);
|
||||
@@ -2471,10 +2472,23 @@ nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_fr
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strip_spaces)
|
||||
str = nm_str_skip_leading_spaces (str);
|
||||
|
||||
len = strlen (str);
|
||||
|
||||
s = memchr (str, '\\', len);
|
||||
if (!s) {
|
||||
if ( strip_spaces
|
||||
&& len > 0
|
||||
&& g_ascii_isspace (str[len - 1])) {
|
||||
len--;
|
||||
while ( len > 0
|
||||
&& g_ascii_isspace (str[len - 1]))
|
||||
len--;
|
||||
*out_len = len;
|
||||
return (*to_free = g_strndup (str, len));
|
||||
}
|
||||
*out_len = len;
|
||||
*to_free = NULL;
|
||||
return str;
|
||||
@@ -2494,7 +2508,7 @@ nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_fr
|
||||
ch = (++str)[0];
|
||||
|
||||
if (ch == '\0') {
|
||||
// error. Trailing '\\'
|
||||
/* error. Trailing '\\' */
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2533,7 +2547,14 @@ nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_fr
|
||||
|
||||
s = strchr (str, '\\');
|
||||
if (!s) {
|
||||
nm_str_buf_append (&strbuf, str);
|
||||
gsize l = strlen (str);
|
||||
|
||||
if (strip_spaces) {
|
||||
while ( l > 0
|
||||
&& g_ascii_isspace (str[l - 1]))
|
||||
l--;
|
||||
}
|
||||
nm_str_buf_append_len (&strbuf, str, l);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2678,14 +2699,14 @@ nm_utils_buf_utf8safe_escape_bytes (GBytes *bytes, NMUtilsStrUtf8SafeFlags flags
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *
|
||||
nm_utils_str_utf8safe_unescape (const char *str, char **to_free)
|
||||
nm_utils_str_utf8safe_unescape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free)
|
||||
{
|
||||
const char *res;
|
||||
gsize len;
|
||||
|
||||
g_return_val_if_fail (to_free, NULL);
|
||||
|
||||
res = nm_utils_buf_utf8safe_unescape (str, &len, (gpointer *) to_free);
|
||||
res = nm_utils_buf_utf8safe_unescape (str, flags, &len, (gpointer *) to_free);
|
||||
|
||||
nm_assert ( (!res && len == 0)
|
||||
|| (strlen (res) <= len));
|
||||
@@ -2748,11 +2769,11 @@ nm_utils_str_utf8safe_escape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags)
|
||||
}
|
||||
|
||||
char *
|
||||
nm_utils_str_utf8safe_unescape_cp (const char *str)
|
||||
nm_utils_str_utf8safe_unescape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags)
|
||||
{
|
||||
char *s;
|
||||
|
||||
str = nm_utils_str_utf8safe_unescape (str, &s);
|
||||
str = nm_utils_str_utf8safe_unescape (str, flags, &s);
|
||||
return s ?: g_strdup (str);
|
||||
}
|
||||
|
||||
|
@@ -1197,17 +1197,25 @@ typedef enum {
|
||||
* reallocation happens. Thus, unescape always avoids leaking
|
||||
* secrets already. */
|
||||
NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET = 0x0004,
|
||||
|
||||
/* This flag only has an effect during unescaping. It means
|
||||
* that non-escaped whitespaces (g_ascii_isspace()) will be
|
||||
* stripped from the front and end of the string. Note that
|
||||
* this flag is only useful for gracefully accepting user input
|
||||
* with spaces. With this flag, escape and unescape may no longer
|
||||
* yield the original input. */
|
||||
NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES = 0x0008,
|
||||
} NMUtilsStrUtf8SafeFlags;
|
||||
|
||||
const char *nm_utils_buf_utf8safe_escape (gconstpointer buf, gssize buflen, NMUtilsStrUtf8SafeFlags flags, char **to_free);
|
||||
const char *nm_utils_buf_utf8safe_escape_bytes (GBytes *bytes, NMUtilsStrUtf8SafeFlags flags, char **to_free);
|
||||
gconstpointer nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_free);
|
||||
gconstpointer nm_utils_buf_utf8safe_unescape (const char *str, NMUtilsStrUtf8SafeFlags flags, gsize *out_len, gpointer *to_free);
|
||||
|
||||
const char *nm_utils_str_utf8safe_escape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
|
||||
const char *nm_utils_str_utf8safe_unescape (const char *str, char **to_free);
|
||||
const char *nm_utils_str_utf8safe_unescape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
|
||||
|
||||
char *nm_utils_str_utf8safe_escape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags);
|
||||
char *nm_utils_str_utf8safe_unescape_cp (const char *str);
|
||||
char *nm_utils_str_utf8safe_unescape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags);
|
||||
|
||||
char *nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags);
|
||||
|
||||
|
@@ -344,7 +344,7 @@ no_auto_default_from_file (const char *no_auto_default_file)
|
||||
|
||||
if (list) {
|
||||
for (i = 0; list[i]; i++)
|
||||
list[i] = nm_utils_str_utf8safe_unescape_cp (list[i]);
|
||||
list[i] = nm_utils_str_utf8safe_unescape_cp (list[i], NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
||||
}
|
||||
|
||||
/* The returned buffer here is not at all compact. That means, it has additional
|
||||
|
Reference in New Issue
Block a user