summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Bugzilla/Search/Quicksearch.pm33
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