3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-11-17 09:29:30 +01:00

Fix split_line() quoting to be more sh-like

E.g.:

<pragma-> show testcargs
   <PBot> [global] testcargs: /code c11 printf("/say args: " ); while (*++argv) printf("[%s] " , *argv);
<pragma-> testcargs 'hello''world' 'how are 'you today
   <PBot> args: [helloworld] [how are you] [today]

Previously, adjacent 'foo''bar' would end up as 2 args like [foo] [bar]. Now
they are properly concatenated into one [foobar] argument.

This also fixes the cases of whitespace being inserted after quoted arguments.
This commit is contained in:
Pragmatic Software 2024-10-29 10:19:46 -07:00
parent 4a025801a2
commit 4287cb9fa2
No known key found for this signature in database
GPG Key ID: CC916B6E3C84ECCE
4 changed files with 17 additions and 29 deletions

View File

@ -101,11 +101,9 @@ sub execute {
return ($exitval, $stdout, $stderr); return ($exitval, $stdout, $stderr);
} }
# splits line into quoted arguments while preserving quotes. # splits line into arguments separated by unquoted whitespace.
# a string is considered quoted only if they are surrounded by # handles unbalanced quotes by treating them as part of the
# whitespace or json separators. # argument they were found within.
# handles unbalanced quotes gracefully by treating them as
# part of the argument they were found within.
sub split_line { sub split_line {
my ($self, $line, %opts) = @_; my ($self, $line, %opts) = @_;
@ -170,12 +168,10 @@ sub split_line {
} }
if (defined $quote) { if (defined $quote) {
if ($ch eq $quote and (not defined $next_ch or $next_ch =~ /[\s,:;})\].+=]/)) { if ($ch eq $quote) {
# closing quote # closing quote
$token .= $ch unless $opts{strip_quotes}; $token .= $ch unless $opts{strip_quotes};
push @args, $token;
$quote = undef; $quote = undef;
$token = '';
} else { } else {
# still within quoted argument # still within quoted argument
$token .= $ch; $token .= $ch;
@ -183,7 +179,7 @@ sub split_line {
next; next;
} }
if (($last_ch =~ /[\s:{(\[.+=]/) and not defined $quote and ($ch eq "'" or $ch eq '"')) { if (not defined $quote and ($ch eq "'" or $ch eq '"')) {
if ($ignore_quote) { if ($ignore_quote) {
# treat unbalanced quote as part of this argument # treat unbalanced quote as part of this argument
$token .= $ch; $token .= $ch;

View File

@ -13,11 +13,9 @@ no warnings 'experimental::signatures';
use parent qw(Exporter); use parent qw(Exporter);
our @EXPORT = qw(split_line); our @EXPORT = qw(split_line);
# splits line into quoted arguments while preserving quotes. # splits line into arguments separated by unquoted whitespace.
# a string is considered quoted only if they are surrounded by # handles unbalanced quotes by treating them as part of the
# whitespace or json separators. # argument they were found within.
# handles unbalanced quotes gracefully by treating them as
# part of the argument they were found within.
sub split_line ($line, %opts) { sub split_line ($line, %opts) {
my %default_opts = ( my %default_opts = (
strip_quotes => 0, strip_quotes => 0,
@ -82,12 +80,10 @@ sub split_line ($line, %opts) {
} }
if (defined $quote) { if (defined $quote) {
if ($ch eq $quote and (not defined $next_ch or $next_ch =~ /[\s,:;})\[\].+=]/)) { if ($ch eq $quote) {
# closing quote # closing quote
$token .= $ch unless $opts{strip_quotes}; $token .= $ch unless $opts{strip_quotes};
push @args, $token;
$quote = undef; $quote = undef;
$token = '';
} else { } else {
# still within quoted argument # still within quoted argument
$token .= $ch; $token .= $ch;
@ -95,7 +91,7 @@ sub split_line ($line, %opts) {
next; next;
} }
if (($last_ch =~ /[\s:{(\[.+=]/) and not defined $quote and ($ch eq "'" or $ch eq '"')) { if (not defined $quote and ($ch eq "'" or $ch eq '"')) {
if ($ignore_quote) { if ($ignore_quote) {
# treat unbalanced quote as part of this argument # treat unbalanced quote as part of this argument
$token .= $ch; $token .= $ch;

View File

@ -1180,11 +1180,9 @@ sub extract_bracketed($self, $string, $open_bracket = '{', $close_bracket = '}',
return ($result, $rest); return ($result, $rest);
} }
# splits line into quoted arguments while preserving quotes. # splits line into arguments separated by unquoted whitespace.
# a string is considered quoted only if they are surrounded by # handles unbalanced quotes by treating them as part of the
# whitespace or json separators. # argument they were found within.
# handles unbalanced quotes gracefully by treating them as
# part of the argument they were found within.
sub split_line($self, $line, %opts) { sub split_line($self, $line, %opts) {
my %default_opts = ( my %default_opts = (
strip_quotes => 0, strip_quotes => 0,
@ -1252,12 +1250,10 @@ sub split_line($self, $line, %opts) {
} }
if (defined $quote) { if (defined $quote) {
if ($ch eq $quote and (not defined $next_ch or $next_ch =~ /[\s,:;})\].+=]/)) { if ($ch eq $quote) {
# closing quote # closing quote
$token .= $ch unless $opts{strip_quotes}; $token .= $ch unless $opts{strip_quotes};
push @args, $token;
$quote = undef; $quote = undef;
$token = '';
} else { } else {
# still within quoted argument # still within quoted argument
$token .= $ch; $token .= $ch;
@ -1265,7 +1261,7 @@ sub split_line($self, $line, %opts) {
next; next;
} }
if (($last_ch =~ /[\s:{(\[.+=,]/) and not defined $quote and ($ch eq "'" or $ch eq '"')) { if (not defined $quote and ($ch eq "'" or $ch eq '"')) {
if ($ignore_quote) { if ($ignore_quote) {
# treat unbalanced quote as part of this argument # treat unbalanced quote as part of this argument
$token .= $ch; $token .= $ch;

View File

@ -25,8 +25,8 @@ use PBot::Imports;
# These are set by the /misc/update_version script # These are set by the /misc/update_version script
use constant { use constant {
BUILD_NAME => "PBot", BUILD_NAME => "PBot",
BUILD_REVISION => 4814, BUILD_REVISION => 4815,
BUILD_DATE => "2024-10-27", BUILD_DATE => "2024-10-29",
}; };
sub initialize {} sub initialize {}