From 3b7cec365af342697017796eac63bff7fb56e1c6 Mon Sep 17 00:00:00 2001 From: Jean-Michel Picod Date: Wed, 18 Oct 2023 10:27:12 +0200 Subject: [PATCH] Support double-quoted arguments in CLI When a quoted command argument is seen, it will take all characters until the next double-quote (no supported escape sequence here for simplicity). All white spaces (space, tab, etc.) are then removed from the argument. This means that the following command should behave the same: ``` pm3> wiegand encode --fc 101 --cn 1337 pm3> wiegand encode --fc "1 0 1" --cn "1 3 3 7" ``` Or a more useful example, when copy/pasting hex formatted values: ``` pm3> hf iclass calcnewkey --old 1122334455667788 --new 2233445566778899 pm3> hf iclass calcnewkey --old "11 22 33 44 55 66 77 88" --new "22 33 44 55 66 77 88 99" ``` --- client/deps/cliparser/cliparser.c | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index e5e8f946c..c11863ab6 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -147,6 +147,7 @@ enum ParserState { PS_FIRST, PS_ARGUMENT, PS_OPTION, + PS_QUOTE, }; #define isSpace(c)(c == ' ' || c == '\t') @@ -195,6 +196,10 @@ int CLIParserParseStringEx(CLIParserContext *ctx, const char *str, void *vargtab case PS_ARGUMENT: if (state == PS_FIRST) state = PS_ARGUMENT; + if (str[i] == '"') { + state = PS_QUOTE; + break; + } if (isSpace(str[i])) { spaceptr = bufptr; state = PS_FIRST; @@ -215,6 +220,35 @@ int CLIParserParseStringEx(CLIParserContext *ctx, const char *str, void *vargtab *bufptr = str[i]; bufptr++; break; + case PS_QUOTE: + if (str[i] == '"') { + // Now let's compact the argument by removing spaces + if (spaceptr != NULL) { + // We've seen at least 1 space + char *cur_ptr = spaceptr; + while (spaceptr < bufptr) { + if (isSpace(*spaceptr) == false) { + *cur_ptr = *spaceptr; + cur_ptr++; + } + spaceptr++; + } + *cur_ptr = 0; + // Rollback bufptr + bufptr = cur_ptr; + spaceptr = NULL; + } + *bufptr = 0x00; + state = PS_FIRST; + } else { + if (isSpace(str[i]) && spaceptr == NULL) { + // Store first encountered space for later + spaceptr = bufptr; + } + *bufptr = str[i]; + } + bufptr++; + break; } if (bufptr > bufptrend) { PrintAndLogEx(ERR, "ERROR: Line too long\n");