diff options
Diffstat (limited to 'Bugzilla/Search/Quicksearch.pm')
-rw-r--r-- | Bugzilla/Search/Quicksearch.pm | 71 |
1 files changed, 56 insertions, 15 deletions
diff --git a/Bugzilla/Search/Quicksearch.pm b/Bugzilla/Search/Quicksearch.pm index fd9d796d1..bc25bb4c0 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) @@ -161,6 +161,8 @@ sub quicksearch { ThrowUserError('quicksearch_invalid_query') if ($words[0] =~ /^(?:AND|OR)$/ || $words[$#words] =~ /^(?:AND|OR|NOT)$/); + $fulltext = Bugzilla->user->setting('quicksearch_fulltext') eq 'on' ? 1 : 0; + my (@qswords, @or_group); while (scalar @words) { my $word = shift @words; @@ -187,6 +189,10 @@ sub quicksearch { } unshift(@words, "-$word"); } + # --comment and ++comment disable or enable fulltext searching + elsif ($word =~ /^(--|\+\+)comments?$/i) { + $fulltext = $1 eq '--' ? 0 : 1; + } else { # OR groups words together, as OR has higher precedence than AND. push(@or_group, $word); @@ -203,12 +209,12 @@ sub quicksearch { shift(@qswords) if $bug_status_set; my (@unknownFields, %ambiguous_fields); - $fulltext = Bugzilla->user->setting('quicksearch_fulltext') eq 'on' ? 1 : 0; # 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 '-'; if ($negate) { $term = substr($term, 1); @@ -221,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); @@ -273,6 +279,29 @@ sub quicksearch { # Parts of quicksearch() # ########################## +sub _parse_line { + my ($delim, $keep, $line) = @_; + return () unless defined $line; + + # parse_line always treats ' as a quote character, making it impossible + # to sanely search for contractions. 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/'/ if defined $word; + } + return @words; +} + sub _bug_numbers_only { my $searchstring = shift; my $cgi = Bugzilla->cgi; @@ -339,6 +368,7 @@ sub _handle_status_and_resolution { sub _handle_special_first_chars { my ($qsword, $negate) = @_; + return 0 if !defined $qsword || length($qsword) <= 1; my $firstChar = substr($qsword, 0, 1); my $baseWord = substr($qsword, 1); @@ -377,23 +407,26 @@ sub _handle_field_names { # Flag and requestee shortcut if ($or_operand =~ /^(?:flag:)?([^\?]+\?)([^\?]*)$/) { - my ($flagtype, $requestee) = ($1, $2); - addChart('flagtypes.name', 'substring', $flagtype, $negate); - if ($requestee) { - # AND - $chart++; - $and = $or = 0; - addChart('requestees.login_name', 'substring', $requestee, $negate); + # BMO: Do not treat custom fields as flags if value is ? + if ($1 !~ /^cf_/) { + my ($flagtype, $requestee) = ($1, $2); + addChart('flagtypes.name', 'substring', $flagtype, $negate); + if ($requestee) { + # AND + $chart++; + $and = $or = 0; + addChart('requestees.login_name', 'substring', $requestee, $negate); + } + return 1; } - return 1; } # 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 @@ -410,6 +443,7 @@ sub _handle_field_names { $bug_status_set = 1; } foreach my $value (@values) { + next unless defined $value; my $operator = FIELD_OPERATOR->{$translated} || 'substring'; # If the string was quoted to protect some special # characters such as commas and colons, we need @@ -482,6 +516,7 @@ sub _translate_field_name { sub _special_field_syntax { my ($word, $negate) = @_; + return unless defined($word); # P1-5 Syntax if ($word =~ m/^P(\d+)(?:-(\d+))?$/i) { @@ -517,6 +552,7 @@ sub _special_field_syntax { sub _default_quicksearch_word { my ($word, $negate) = @_; + return unless defined($word); if (!grep { lc($word) eq $_ } PRODUCT_EXCEPTIONS and length($word) > 2) { addChart('product', 'substring', $word, $negate); @@ -535,10 +571,15 @@ sub _default_quicksearch_word { addChart('short_desc', 'substring', $word, $negate); addChart('status_whiteboard', 'substring', $word, $negate); addChart('content', 'matches', _matches_phrase($word), $negate) if $fulltext; + + # BMO Bug 664124 - Include the crash signature (sig:) field in default quicksearches + addChart('cf_crash_signature', 'substring', $word, $negate); } sub _handle_urls { my ($word, $negate) = @_; + return unless defined($word); + # URL field (for IP addrs, host.names, # scheme://urls) if ($word =~ m/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ |