diff options
author | Byron Jones <bjones@mozilla.com> | 2013-09-18 10:00:08 +0200 |
---|---|---|
committer | Byron Jones <bjones@mozilla.com> | 2013-09-18 10:00:08 +0200 |
commit | 92d69ff51ac4234213f54fdc897369f7ccc40a76 (patch) | |
tree | 054ca8812d2dabbcab3dca3a052738013039f21a | |
parent | 45b7728b22f637b3b6d95bc540be05045ee4facf (diff) | |
download | bugzilla-92d69ff51ac4234213f54fdc897369f7ccc40a76.tar.gz bugzilla-92d69ff51ac4234213f54fdc897369f7ccc40a76.tar.xz |
Bug 877545: quicksearch shouldn't treat apostrophes as quote characters
-rw-r--r-- | Bugzilla/Search/Quicksearch.pm | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/Bugzilla/Search/Quicksearch.pm b/Bugzilla/Search/Quicksearch.pm index c3c11b728..561493ed8 100644 --- a/Bugzilla/Search/Quicksearch.pm +++ b/Bugzilla/Search/Quicksearch.pm @@ -151,7 +151,7 @@ sub quicksearch { # Retain backslashes and quotes, to know which strings are quoted, # and which ones are not. - my @words = parse_line('\s+', 1, $searchstring); + my @words = _parse_line('\s+', 1, $searchstring); # If parse_line() returns no data, this means strings are badly quoted. # Rather than trying to guess what the user wanted to do, we throw an error. scalar(@words) @@ -212,7 +212,7 @@ sub quicksearch { # Loop over all main-level QuickSearch words. foreach my $qsword (@qswords) { - my @or_operand = parse_line('\|', 1, $qsword); + my @or_operand = _parse_line('\|', 1, $qsword); foreach my $term (@or_operand) { next unless defined $term; my $negate = substr($term, 0, 1) eq '-'; @@ -227,7 +227,7 @@ sub quicksearch { # Having ruled out the special cases, we may now split # by comma, which is another legal boolean OR indicator. # Remove quotes from quoted words, if any. - @words = parse_line(',', 0, $term); + @words = _parse_line(',', 0, $term); foreach my $word (@words) { if (!_special_field_syntax($word, $negate)) { _default_quicksearch_word($word, $negate); @@ -279,6 +279,27 @@ sub quicksearch { # Parts of quicksearch() # ########################## +sub _parse_line { + my ($delim, $keep, $line) = @_; + # parse_line always treats ' as a quote character, making it impossible + # to sanely search for contradictions. As this behavour isn't + # configurable, we replace ' with a placeholder to hide it from the + # parser. + + # only treat ' at the start or end of words as quotes + # it's easier to do this in reverse with regexes + $line =~ s/(^|\s|:)'/$1\001/g; + $line =~ s/'($|\s)/\001$1/g; + $line =~ s/\\?'/\000/g; + $line =~ tr/\001/'/; + + my @words = parse_line($delim, $keep, $line); + foreach my $word (@words) { + $word =~ tr/\000/'/; + } + return @words; +} + sub _bug_numbers_only { my $searchstring = shift; my $cgi = Bugzilla->cgi; @@ -400,10 +421,10 @@ sub _handle_field_names { # Generic field1,field2,field3:value1,value2 notation. # We have to correctly ignore commas and colons in quotes. - my @field_values = parse_line(':', 1, $or_operand); + my @field_values = _parse_line(':', 1, $or_operand); if (scalar @field_values == 2) { - my @fields = parse_line(',', 1, $field_values[0]); - my @values = parse_line(',', 1, $field_values[1]); + my @fields = _parse_line(',', 1, $field_values[0]); + my @values = _parse_line(',', 1, $field_values[1]); foreach my $field (@fields) { my $translated = _translate_field_name($field); # Skip and record any unknown fields |