I've been thinking about this problem since out IRC discussion, and while the above solution goes some way towards making sense, it doesn't quite get there. I originally coded the escapes the way I did to "defend" certain escapes, such as \n, which I thought might be required later.
After some experimentation, I'm now convinced they are. if you are to write a string, for example, that matches a field value that contains a newline, you
have to expand \n to chr(10) in the parser. It's not enough to pass it on to the operator to deal with, because the operator doesn;t know the string value came from a constant. A consistent scheme for handling all these escapes in constant strings is required. So here's my counter-patch:
Index: UnitTestContrib/test/unit/QueryTests.pm
===================================================================
--- UnitTestContrib/test/unit/QueryTests.pm (revision 6928)
+++ UnitTestContrib/test/unit/QueryTests.pm (working copy)
@@ -74,6 +74,9 @@
$meta->putKeyed( 'FIELD',
{ name => "string", title => "String", value => "String" } );
$meta->putKeyed( 'FIELD',
+ { name => "StringWithChars", title => "StringWithChars",
+ value => "n\nn t\tt s\\s q'q o#o h#h X~X \\b \\a \\e \\f \\r \\cX" } );
+ $meta->putKeyed( 'FIELD',
{ name => "boolean", title => "Boolean", value => "1" } );
$meta->putKeyed( 'FIELD',
{ name => "macro", value => "%RED%" } );
@@ -235,6 +238,13 @@
$this->check( "number=98 OR string='Spring'", 0 );
}
+sub test_constant_strings {
+ my $this = shift;
+ my $in = 'n\nn t\tt s\\\\s q\\\'q o\\043o h\\x23h X\\x{7e}X \\b \\a \\e \\f \\r \\cX';
+
+ $this->check( "'$in'=StringWithChars", 1 );
+}
+
sub conjoin {
my ( $this, $last, $A, $B, $a, $b, $c, $r ) = @_;
Index: core/lib/Foswiki/Infix/Parser.pm
===================================================================
--- core/lib/Foswiki/Infix/Parser.pm (revision 6928)
+++ core/lib/Foswiki/Infix/Parser.pm (working copy)
@@ -227,11 +227,13 @@
push( @opers, $op );
}
elsif ( $$input =~ s/^\s*(['"])(|.*?[^\\])\1// ) {
- print STDERR "Tok: qs '$1'\n" if MONITOR_PARSER;
+ my $q = $1;
my $val = $2;
+ print STDERR "Tok: qs '$q'\n" if MONITOR_PARSER;
- # Handle escaped characters in the string
- $val =~ s/(?<!\\)\\(.)/$1/g;
+ # Handle escaped characters in the string. This is where
+ # expansions such as \n are handled
+ $val =~ s/(?<!\\)\\(0[0-7]{2}|x[a-fA-F0-9]{2}|x{[a-fA-F0-9]+}|n|t|\\|$q)/eval('"\\'.$1.'"')/ge;
push( @opands,
$this->{client_class}
->newLeaf( $val, $Foswiki::Infix::Node::STRING ) );
--
CrawfordCurrie - 26 Mar 2010
Hm, not sure we should allow these special chars everywhere. Before an
\n
in all other (non-regex) operators was a
\
and a
n
(actually an
n
only, but that's part of the found bug). With your above patch,
all operators now understand a certain subset of special chars.
--
MichaelDaum - 26 Mar 2010