blob: df93763388a5f4b7527cbd021cefd14d47d9e8e1 [file] [log] [blame]
diff --git a/tools/dbus-send.c b/tools/dbus-send.c
--- a/tools/dbus-send.c
+++ b/tools/dbus-send.c
@@ -149,17 +149,79 @@ append_arg (DBusMessageIter *iter, int type, const char *value)
}
}
+// Note: buffer must be pre-allocated and at least as big as str.
+static int
+get_next_token (const char *str, int loc, char *buffer)
+{
+ int str_index, buffer_index = 0;
+
+ enum State {START, ESCAPE};
+ enum State state = START;
+
+ for (str_index = loc; str[str_index] != '\0'; str_index++)
+ {
+ if (state == START)
+ {
+ switch (str[str_index])
+ {
+ case '\\':
+ state = ESCAPE;
+ continue;
+
+ // If we hit a , in the start state, we should treat it as
+ // an argument separator since it's not escaped.
+ case ',':
+ buffer[buffer_index] = '\0';
+ return str_index + 1;
+ }
+ }
+ else if (state == ESCAPE)
+ {
+ // If the \ doesn't immediately precede a , or another \, then
+ // it's not being used as an escape character.
+ // Similarly, if we have a string of multiple \s as the last
+ // characters, then they're also not being used as escape characters.
+ if ((str[str_index] != ',' && str[str_index] != '\\') ||
+ (str[str_index] == '\\' && str[str_index + 1] == '\0'))
+ {
+ buffer[buffer_index] = '\\';
+ buffer_index++;
+ }
+
+ state = START;
+ }
+
+ buffer[buffer_index] = str[str_index];
+ buffer_index++;
+ }
+
+ // If we end on a single \, then it's not being used as an escape character.
+ // Note the earlier check will only catch if we end on a string of multiple
+ // \s.
+ if (state == ESCAPE)
+ {
+ buffer[buffer_index] = '\\';
+ buffer_index++;
+ }
+ buffer[buffer_index] = '\0';
+
+ return -1;
+}
+
static void
append_array (DBusMessageIter *iter, int type, const char *value)
{
- const char *val;
- char *dupval = strdup (value);
+ char *buffer = strdup (value);
- val = strtok (dupval, ",");
- while (val != NULL)
+ int loc = 0;
+ while (loc >= 0)
{
- append_arg (iter, type, val);
- val = strtok (NULL, ",");
+ loc = get_next_token (value, loc, buffer);
+
+ // We don't want to include empty strings, even if there are
+ // several commas directly beside each other.
+ if (buffer[0] != '\0')
+ append_arg (iter, type, buffer);
}
- free (dupval);
+ free (buffer);
}