| 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); |
| } |