2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-23 03:18:59 +00:00

Slightly improve bash completion arg parsing

This commit is contained in:
Jay Berkenbilt 2018-12-22 23:16:46 -05:00
parent 6b90f3db4d
commit 52a0b767c8
4 changed files with 75 additions and 12 deletions

View File

@ -1414,30 +1414,85 @@ void
ArgParser::handleBashArguments()
{
// Do a minimal job of parsing bash_line into arguments. This
// doesn't do everything the shell does, but it should be good
// enough for purposes of handling completion. We can't use
// new_argv because this has to interoperate with @file arguments.
// doesn't do everything the shell does (e.g. $(...), variable
// expansion, arithmetic, globs, etc.), but it should be good
// enough for purposes of handling completion. As we build up the
// new argv, we can't use this->new_argv because this code has to
// interoperate with @file arguments, so memory for both ways of
// fabricating argv has to be protected.
enum { st_top, st_quote } state = st_top;
bool last_was_backslash = false;
enum { st_top, st_squote, st_dquote } state = st_top;
std::string arg;
for (std::string::iterator iter = bash_line.begin();
iter != bash_line.end(); ++iter)
{
char ch = (*iter);
if ((state == st_top) && QUtil::is_space(ch) && (! arg.empty()))
if (last_was_backslash)
{
bash_argv.push_back(
PointerHolder<char>(
true, QUtil::copy_string(arg.c_str())));
arg.clear();
arg.append(1, ch);
last_was_backslash = false;
}
else if (ch == '\\')
{
last_was_backslash = true;
}
else
{
if (ch == '"')
bool append = false;
switch (state)
{
state = (state == st_top ? st_quote : st_top);
case st_top:
if (QUtil::is_space(ch))
{
if (! arg.empty())
{
bash_argv.push_back(
PointerHolder<char>(
true, QUtil::copy_string(arg.c_str())));
arg.clear();
}
}
else if (ch == '"')
{
state = st_dquote;
}
else if (ch == '\'')
{
state = st_squote;
}
else
{
append = true;
}
break;
case st_squote:
if (ch == '\'')
{
state = st_top;
}
else
{
append = true;
}
break;
case st_dquote:
if (ch == '"')
{
state = st_top;
}
else
{
append = true;
}
break;
}
if (append)
{
arg.append(1, ch);
}
arg.append(1, ch);
}
}
if (bash_argv.empty())

View File

@ -117,6 +117,12 @@ my @completion_tests = (
['qpdf --decode-lzzz', 15, 'decode-l'],
['qpdf --decode-level=', undef, 'decode-level'],
['qpdf --check -', undef, 'later-arg'],
['qpdf infile outfile oops --ch', undef, 'usage-empty'],
['qpdf --encrypt \'user " password\' ', undef, 'quoting'],
['qpdf --encrypt \'user password\' ', undef, 'quoting'],
['qpdf --encrypt "user password" ', undef, 'quoting'],
['qpdf --encrypt "user pass\'word" ', undef, 'quoting'],
['qpdf --encrypt user\ password ', undef, 'quoting'],
);
$n_tests += scalar(@completion_tests);
foreach my $c (@completion_tests)

View File

@ -0,0 +1 @@
owner-password

View File

@ -0,0 +1 @@
!--check