summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shared/nm-utils/nm-shared-utils.c27
-rw-r--r--shared/nm-utils/nm-shared-utils.h27
2 files changed, 53 insertions, 1 deletions
diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c
index c21f0f66ec..1a86778e81 100644
--- a/shared/nm-utils/nm-shared-utils.c
+++ b/shared/nm-utils/nm-shared-utils.c
@@ -1027,7 +1027,8 @@ nm_utils_strsplit_set_full (const char *str,
const char *c_str;
char *s;
guint8 ch_lookup[256];
- const gboolean f_allow_escaping = NM_FLAGS_HAS (flags, NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING);
+ const gboolean f_escaped = NM_FLAGS_HAS (flags, NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED);
+ const gboolean f_allow_escaping = f_escaped || NM_FLAGS_HAS (flags, NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING);
const gboolean f_preserve_empty = NM_FLAGS_HAS (flags, NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY);
const gboolean f_strstrip = NM_FLAGS_HAS (flags, NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP);
@@ -1188,6 +1189,30 @@ done2:
ptr[i_token] = NULL;
}
+ if (f_escaped) {
+ gsize i, j;
+
+ /* We no longer need ch_lookup for its original purpose. Modify it, so it
+ * can detect the delimiters, '\\', and (optionally) whitespaces. */
+ ch_lookup[((guint8) '\\')] = 1;
+ if (f_strstrip) {
+ for (i = 0; NM_ASCII_SPACES[i]; i++)
+ ch_lookup[((guint8) (NM_ASCII_SPACES[i]))] = 1;
+ }
+
+ for (i_token = 0; ptr[i_token]; i_token++) {
+ s = (char *) ptr[i_token];
+ j = 0;
+ for (i = 0; s[i] != '\0'; ) {
+ if ( s[i] == '\\'
+ && _char_lookup_has (ch_lookup, s[i + 1]))
+ i++;
+ s[j++] = s[i++];
+ }
+ s[j] = '\0';
+ }
+ }
+
return ptr;
}
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
index 0beb75ff10..25e77b9b8b 100644
--- a/shared/nm-utils/nm-shared-utils.h
+++ b/shared/nm-utils/nm-shared-utils.h
@@ -347,6 +347,33 @@ typedef enum {
* - when combined with %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING,
* trailing whitespace escaped by backslash are not stripped. */
NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP = (1u << 2),
+
+ /* This implies %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING.
+ *
+ * This will do a final run over all tokens and remove all backslash
+ * escape characters that
+ * - precede a delimiter.
+ * - precede a backslash.
+ * - preceed a whitespace (with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP).
+ *
+ * Note that with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, it is only
+ * necessary to escape the very last whitespace (if the delimiters
+ * are not whitespace themself). So, technically, it would be sufficient
+ * to only unescape a backslash before the last whitespace and the user
+ * still could express everything. However, such a rule would be complicated
+ * to understand, so when using backslash escaping with nm_utils_strsplit_set_full(),
+ * then all characters (including backslash) are treated verbatim, except:
+ *
+ * - "\\$DELIMITER" (escaped delimiter)
+ * - "\\\\" (escaped backslash)
+ * - "\\$SPACE" (escaped space) (with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP).
+ *
+ * Note that all other escapes like "\\n" or "\\001" are left alone.
+ * That makes the escaping/unescaping rules simple. Also, for the most part
+ * a text is just taken as-is, with little additional rules. Only backslashes
+ * need extra care, and then only if they proceed one of the relevant characters.
+ */
+ NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED = (1u << 3),
} NMUtilsStrsplitSetFlags;
const char **nm_utils_strsplit_set_full (const char *str,