Bugfix: Properly handle workspace names with double quotes (+test) (Thanks kvapen)
This commit is contained in:
parent
ed2bcc15e3
commit
2f8d3d3390
@ -294,10 +294,36 @@ void handle_button(xcb_button_press_event_t *event) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t len = strlen(cur_ws->name) + strlen("workspace \"\"") + 1;
|
/* To properly handle workspace names with double quotes in them, we need
|
||||||
char buffer[len];
|
* to escape the double quotes. Unfortunately, that’s rather ugly in C: We
|
||||||
snprintf(buffer, len, "workspace \"%s\"", cur_ws->name);
|
* first count the number of double quotes, then we allocate a large enough
|
||||||
|
* buffer, then we copy character by character. */
|
||||||
|
int num_quotes = 0;
|
||||||
|
size_t namelen = 0;
|
||||||
|
for (char *walk = cur_ws->name; *walk != '\0'; walk++) {
|
||||||
|
if (*walk == '"')
|
||||||
|
num_quotes++;
|
||||||
|
/* While we’re looping through the name anyway, we can save one
|
||||||
|
* strlen(). */
|
||||||
|
namelen++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t len = namelen + strlen("workspace \"\"") + 1;
|
||||||
|
char *buffer = scalloc(len+num_quotes);
|
||||||
|
strncpy(buffer, "workspace \"", strlen("workspace \""));
|
||||||
|
int inpos, outpos;
|
||||||
|
for (inpos = 0, outpos = strlen("workspace \"");
|
||||||
|
inpos < namelen;
|
||||||
|
inpos++, outpos++) {
|
||||||
|
if (cur_ws->name[inpos] == '"') {
|
||||||
|
buffer[outpos] = '\\';
|
||||||
|
outpos++;
|
||||||
|
}
|
||||||
|
buffer[outpos] = cur_ws->name[inpos];
|
||||||
|
}
|
||||||
|
buffer[++outpos] = '"';
|
||||||
i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, buffer);
|
i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, buffer);
|
||||||
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -274,7 +274,18 @@ char *parse_command(const char *input) {
|
|||||||
}
|
}
|
||||||
if (walk != beginning) {
|
if (walk != beginning) {
|
||||||
char *str = scalloc(walk-beginning + 1);
|
char *str = scalloc(walk-beginning + 1);
|
||||||
strncpy(str, beginning, walk-beginning);
|
/* We copy manually to handle escaping of characters. */
|
||||||
|
int inpos, outpos;
|
||||||
|
for (inpos = 0, outpos = 0;
|
||||||
|
inpos < (walk-beginning);
|
||||||
|
inpos++, outpos++) {
|
||||||
|
/* We only handle escaped double quotes to not break
|
||||||
|
* backwards compatibility with people using \w in
|
||||||
|
* regular expressions etc. */
|
||||||
|
if (beginning[inpos] == '\\' && beginning[inpos+1] == '"')
|
||||||
|
inpos++;
|
||||||
|
str[outpos] = beginning[inpos];
|
||||||
|
}
|
||||||
if (token->identifier)
|
if (token->identifier)
|
||||||
push_string(token->identifier, str);
|
push_string(token->identifier, str);
|
||||||
DLOG("str is \"%s\"\n", str);
|
DLOG("str is \"%s\"\n", str);
|
||||||
|
@ -157,4 +157,16 @@ is(parser_calls('move something to somewhere'),
|
|||||||
" ^^^^^^^^^^^^^^^^^^^^^^",
|
" ^^^^^^^^^^^^^^^^^^^^^^",
|
||||||
'error for unknown literal ok');
|
'error for unknown literal ok');
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# 3: Verify that escaping of double quotes works correctly
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
is(parser_calls('workspace "foo"'),
|
||||||
|
'cmd_workspace_name(foo)',
|
||||||
|
'Command with simple double quotes ok');
|
||||||
|
|
||||||
|
is(parser_calls('workspace "foo \"bar"'),
|
||||||
|
'cmd_workspace_name(foo "bar)',
|
||||||
|
'Command with escaped double quotes ok');
|
||||||
|
|
||||||
done_testing;
|
done_testing;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user