From: lpsolit%gmail.com <> Date: Mon, 22 Aug 2005 01:16:40 +0000 (+0000) Subject: Bug 70907: QuickSearch: port the JS code to perl (make it server-side) - Patch by... X-Git-Tag: bugzilla-2.21.1~103 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f4966aeb0e7a655c986aeb285c1a220274ddbfd9;p=thirdparty%2Fbugzilla.git Bug 70907: QuickSearch: port the JS code to perl (make it server-side) - Patch by Marc Schumann r=wicked a=myk --- diff --git a/Bugzilla/Search/Quicksearch.pm b/Bugzilla/Search/Quicksearch.pm new file mode 100644 index 0000000000..9f67245072 --- /dev/null +++ b/Bugzilla/Search/Quicksearch.pm @@ -0,0 +1,499 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# Contributor(s): C. Begle +# Jesse Ruderman +# Andreas Franke +# Stephen Lee +# Marc Schumann + +package Bugzilla::Search::Quicksearch; + +# Make it harder for us to do dangerous things in Perl. +use strict; + +use Bugzilla; +use Bugzilla::Config; +use Bugzilla::Error; + +use base qw(Exporter); +@Bugzilla::Search::Quicksearch::EXPORT = qw(quicksearch); + +my $cgi = Bugzilla->cgi; + +# Word renamings +my %mappings = (# Status, Resolution, Platform, OS, Priority, Severity + "status" => "bug_status", + "resolution" => "resolution", # no change + "platform" => "rep_platform", + "os" => "op_sys", + "opsys" => "op_sys", + "priority" => "priority", # no change + "pri" => "priority", + "severity" => "bug_severity", + "sev" => "bug_severity", + # People: AssignedTo, Reporter, QA Contact, CC, Added comment (?) + "owner" => "assigned_to", # deprecated since bug 76507 + "assignee" => "assigned_to", + "assignedto" => "assigned_to", + "reporter" => "reporter", # no change + "rep" => "reporter", + "qa" => "qa_contact", + "qacontact" => "qa_contact", + "cc" => "cc", # no change + # Product, Version, Component, Target Milestone + "product" => "product", # no change + "prod" => "product", + "version" => "version", # no change + "ver" => "version", + "component" => "component", # no change + "comp" => "component", + "milestone" => "target_milestone", + "target" => "target_milestone", + "targetmilestone" => "target_milestone", + # Summary, Description, URL, Status whiteboard, Keywords + "summary" => "short_desc", + "shortdesc" => "short_desc", + "desc" => "longdesc", + "description" => "longdesc", + #"comment" => "longdesc", # ??? + # reserve "comment" for "added comment" email search? + "longdesc" => "longdesc", + "url" => "bug_file_loc", + "whiteboard" => "status_whiteboard", + "statuswhiteboard" => "status_whiteboard", + "sw" => "status_whiteboard", + "keywords" => "keywords", # no change + "kw" => "keywords", + # Attachments + "attachment" => "attachments.description", + "attachmentdesc" => "attachments.description", + "attachdesc" => "attachments.description", + "attachmentdata" => "attachments.thedata", + "attachdata" => "attachments.thedata", + "attachmentmimetype" => "attachments.mimetype", + "attachmimetype" => "attachments.mimetype"); + +# We might want to put this into localconfig or somewhere +my @platforms = ('pc', 'sun', 'macintosh', 'mac'); +my @productExceptions = ('row' # [Browser] + # ^^^ + ,'new' # [MailNews] + # ^^^ + ); +my @componentExceptions = ('hang' # [Bugzilla: Component/Keyword Changes] + # ^^^^ + ); + +# Quicksearch-wide globals for boolean charts. +my $chart = 0; +my $and = 0; +my $or = 0; + +sub quicksearch { + my ($searchstring) = (@_); + + # Remove leading and trailing commas and whitespace. + $searchstring =~ s/(^[\s,]+|[\s,]+$)//g; + ThrowUserError('buglist_parameters_required') unless ($searchstring); + + if ($searchstring =~ m/^[0-9,\s]*$/) { + # Bug number(s) only. + + # Allow separation by comma or whitespace. + $searchstring =~ s/[,\s]+/,/g; + + if (index($searchstring, ',') < $[) { + # Single bug number; shortcut to show_bug.cgi. + print $cgi->redirect(-uri => Param('urlbase') . + "show_bug.cgi?id=$searchstring"); + exit; + } + else { + # List of bug numbers. + $cgi->param('bug_id', $searchstring); + $cgi->param('order', 'bugs.bug_id'); + $cgi->param('bugidtype', 'include'); + } + } + else { + # It's not just a bug number or a list of bug numbers. + # Maybe it's an alias? + if ($searchstring =~ /^([^,\s]+)$/) { + if (Bugzilla->dbh->selectrow_array(q{SELECT COUNT(*) + FROM bugs + WHERE alias = ?}, + undef, + $1)) { + print $cgi->redirect(-uri => Param('urlbase') . + "show_bug.cgi?id=$1"); + exit; + } + } + + # It's no alias either, so it's a more complex query. + + &::GetVersionTable(); + + # Globally translate " AND ", " OR ", " NOT " to space, pipe, dash. + $searchstring =~ s/\s+AND\s+/ /g; + $searchstring =~ s/\s+OR\s+/|/g; + $searchstring =~ s/\s+NOT\s+/ -/g; + + my @words = splitString($searchstring); + my $searchComments = $#words < Param('quicksearch_comment_cutoff'); + my @openStates = &::OpenStates(); + my @closedStates; + my (%states, %resolutions); + + foreach (@::legal_bug_status) { + push(@closedStates, $_) unless &::IsOpenedState($_); + } + foreach (@openStates) { $states{$_} = 1 } + if ($words[0] eq 'ALL') { + foreach (@::legal_bug_status) { $states{$_} = 1 } + shift @words; + } + elsif ($words[0] eq 'OPEN') { + shift @words; + } + elsif ($words[0] =~ /^\+[A-Z]+(,[A-Z]+)*$/) { + # e.g. +DUP,FIX + if (matchPrefixes(\%states, + \%resolutions, + [split(/,/, substr($words[0], 1))], + \@closedStates, + \@::legal_resolution)) { + shift @words; + # Allowing additional resolutions means we need to keep + # the "no resolution" resolution. + $resolutions{'---'} = 1; + } + else { + # Carry on if no match found. + } + } + elsif ($words[0] =~ /^[A-Z]+(,[A-Z]+)*$/) { + # e.g. NEW,ASSI,REOP,FIX + undef %states; + if (matchPrefixes(\%states, + \%resolutions, + [split(/,/, $words[0])], + \@::legal_bug_status, + \@::legal_resolution)) { + shift @words; + } + else { + # Carry on if no match found + foreach (@openStates) { $states{$_} = 1 } + } + } + else { + # Default: search for unresolved bugs only. + # Put custom code here if you would like to change this behaviour. + } + + # If we have wanted resolutions, allow closed states + if (keys(%resolutions)) { + foreach (@closedStates) { $states{$_} = 1 } + } + + $cgi->param('bug_status', keys(%states)); + $cgi->param('resolution', keys(%resolutions)); + + # Loop over all main-level QuickSearch words. + foreach my $qsword (@words) { + my $negate = substr($qsword, 0, 1) eq '-'; + if ($negate) { + $qsword = substr($qsword, 1); + } + + my $firstChar = substr($qsword, 0, 1); + my $baseWord = substr($qsword, 1); + my @subWords = split(/[\|,]/, $baseWord); + if ($firstChar eq '+') { + foreach (@subWords) { + addChart('short_desc', 'substring', $qsword, $negate); + } + } + elsif ($firstChar eq '#') { + addChart('short_desc', 'anywords', $baseWord, $negate); + if ($searchComments) { + addChart('longdesc', 'anywords', $baseWord, $negate); + } + } + elsif ($firstChar eq ':') { + foreach (@subWords) { + addChart('product', 'substring', $_, $negate); + addChart('component', 'substring', $_, $negate); + } + } + elsif ($firstChar eq '@') { + foreach (@subWords) { + addChart('assigned_to', 'substring', $_, $negate); + } + } + elsif ($firstChar eq '[') { + addChart('short_desc', 'substring', $baseWord, $negate); + addChart('status_whiteboard', 'substring', $baseWord, $negate); + } + elsif ($firstChar eq '!') { + addChart('keywords', 'anywords', $baseWord, $negate); + + } + else { # No special first char + + # Split by '|' to get all operands for a boolean OR. + foreach my $or_operand (split(/\|/, $qsword)) { + if ($or_operand =~ /^votes:([0-9]+)$/) { + # votes:xx ("at least xx votes") + addChart('votes', 'greaterthan', $1, $negate); + } + elsif ($or_operand =~ /^([^:]+):([^:]+)$/) { + # generic field1,field2,field3:value1,value2 notation + my @fields = split(/,/, $1); + my @values = split(/,/, $2); + foreach my $field (@fields) { + # Be tolerant about unknown fields + next unless defined($mappings{$field}); + $field = $mappings{$field}; + foreach (@values) { + addChart($field, 'substring', $_, $negate); + } + } + + } + else { + + # Having ruled out the special cases, we may now split + # by comma, which is another legal boolean OR indicator. + foreach my $word (split(/,/, $or_operand)) { + # Platform + if (grep({lc($word) eq $_} @platforms)) { + addChart('rep_platform', 'substring', + $word, $negate); + } + # Priority + elsif ($word =~ m/^[pP]([1-5](-[1-5])?)$/) { + addChart('priority', 'regexp', + "[$1]", $negate); + } + # Severity + elsif (grep({lc($word) eq substr($_, 0, 3)} + @::legal_severity)) { + addChart('bug_severity', 'substring', + $word, $negate); + } + # Votes (votes>xx) + elsif ($word =~ m/^votes>([0-9]+)$/) { + addChart('votes', 'greaterthan', + $1, $negate); + } + # Votes (votes>=xx, votes=>xx) + elsif ($word =~ m/^votes(>=|=>)([0-9]+)$/) { + addChart('votes', 'greaterthan', + $2-1, $negate); + + } + else { # Default QuickSearch word + + if (!grep({lc($word) eq $_} + @productExceptions) && + length($word)>2 + ) { + addChart('product', 'substring', + $word, $negate); + } + if (!grep({lc($word) eq $_} + @componentExceptions) && + length($word)>2 + ) { + addChart('component', 'substring', + $word, $negate); + } + if (grep({lc($word) eq $_} + @::legal_keywords)) { + addChart('keywords', 'substring', + $word, $negate); + if (length($word)>2) { + addChart('short_desc', 'substring', + $word, $negate); + addChart('status_whiteboard', + 'substring', + $word, $negate); + } + + } + else { + + addChart('short_desc', 'substring', + $word, $negate); + addChart('status_whiteboard', 'substring', + $word, $negate); + } + if ($searchComments) { + addChart('longdesc', 'substring', + $word, $negate); + } + } + # URL field (for IP addrs, host.names, + # scheme://urls) + if ($word =~ m/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ + || $word =~ /^[A-Za-z]+(\.[A-Za-z]+)+/ + || $word =~ /:[\\\/][\\\/]/ + || $word =~ /localhost/ + || $word =~ /mailto[:]?/ + # || $word =~ /[A-Za-z]+[:][0-9]+/ #host:port + ) { + addChart('bug_file_loc', 'substring', + $word, $negate); + } + } # foreach my $word (split(/,/, $qsword)) + } # votes and generic field detection + } # foreach (split(/\|/, $_)) + } # "switch" $firstChar + $chart++; + $and = 0; + $or = 0; + } # foreach (@words) + + # We've been very tolerant about invalid queries, so all that's left + # may be an empty query. + scalar($cgi->param())>0 || ThrowUserError("buglist_parameters_required"); + } + + # List of quicksearch-specific CGI parameters to get rid of. + my @params_to_strip = ('quicksearch', 'load', 'run'); + my $modified_query_string = $cgi->canonicalise_query(@params_to_strip); + + if ($cgi->param('load')) { + # Param 'load' asks us to display the query in the advanced search form. + print $cgi->redirect(-uri => Param('urlbase') . "query.cgi?" . + "format=advanced&" . + $modified_query_string); + } + + # Otherwise, pass the modified query string to the caller. + # We modified $cgi->params, so the caller can choose to look at that, too, + # and disregard the return value. + $cgi->delete(@params_to_strip); + return $modified_query_string; +} + +########################################################################### +# Helpers +########################################################################### + +# Split string on whitespace, retaining quoted strings as one +sub splitString { + my $string = shift; + my @quoteparts; + my @parts; + my $i = 0; + + # Escape backslashes + $string =~ s/\\/\\\//g; + + # Now split on quote sign; be tolerant about unclosed quotes + @quoteparts = split(/"/, $string); + foreach (@quoteparts) { + # After every odd quote, escape whitespace + s/(\s)/\\$1/g if $i++ % 2; + } + # Join again + $string = join('"', @quoteparts); + + # Now split on unescaped whitespace + @parts = split(/(?param("field$expr", $field); + $cgi->param("type$expr", $type); + $cgi->param("value$expr", $value); +} + +1; diff --git a/QUICKSTART b/QUICKSTART index 3f26f06d1a..54ebfa4cf1 100644 --- a/QUICKSTART +++ b/QUICKSTART @@ -30,10 +30,6 @@ of the Bugzilla Guide in the docs/ directory. If you want to change platforms, operating systems, severities and priorities, this can also be done in localconfig at this time. - You should also update localconfig.js to reflect these changes. This - includes setting the URL you chose in step 1 as the 'bugzilla' JS - variable. - 5. Using the name you provided as $db_name above, create a MySQL database for Bugzilla. You should also create a user permission for the name supplied as $db_user with read/write access to that database. diff --git a/buglist.cgi b/buglist.cgi index 904df703db..63ab55951f 100755 --- a/buglist.cgi +++ b/buglist.cgi @@ -38,6 +38,7 @@ use vars qw($template $vars); use Bugzilla; use Bugzilla::Search; +use Bugzilla::Search::Quicksearch; use Bugzilla::Constants; use Bugzilla::User; @@ -65,6 +66,15 @@ if (length($buffer) == 0) { ThrowUserError("buglist_parameters_required"); } +# Determine whether this is a quicksearch query. +my $searchstring = $cgi->param('quicksearch'); +if (defined($searchstring)) { + $buffer = quicksearch($searchstring); + # Quicksearch may do a redirect, in which case it does not return. + # If it does return, it has modified $cgi->params so we can use them here + # as if this had been a normal query from the beginning. +} + ################################################################################ # Data and Security Validation ################################################################################ diff --git a/checksetup.pl b/checksetup.pl index f20d1dcb2b..b2bb97162f 100755 --- a/checksetup.pl +++ b/checksetup.pl @@ -1015,9 +1015,6 @@ if ($my_create_htaccess) { deny from all - - allow from all - END close HTACCESS; chmod $fileperm, ".htaccess"; @@ -1033,11 +1030,6 @@ END print "Repairing .htaccess...\n"; open HTACCESS, '>', '.htaccess'; print HTACCESS $oldaccess; - print HTACCESS <<'END'; - - allow from all - -END close HTACCESS; } diff --git a/defparams.pl b/defparams.pl index 598d0711f3..ffb9c68d93 100644 --- a/defparams.pl +++ b/defparams.pl @@ -1424,6 +1424,17 @@ Reason: %reason% default => 1, }, + { + name => 'quicksearch_comment_cutoff', + desc => q{The maximum number of search terms for a QuickSearch to search + comments. + If the QuickSearch query contains more terms than this value, + QuickSearch will not search comments.}, + type => 't', + default => '4', + checker => \&check_numeric + }, + # Added for Patch Viewer stuff (attachment.cgi?action=diff) { name => 'cvsroot', diff --git a/docs/xml/security.xml b/docs/xml/security.xml index a638ae26a9..e68577b4ce 100644 --- a/docs/xml/security.xml +++ b/docs/xml/security.xml @@ -1,5 +1,5 @@ - + Bugzilla Security @@ -207,14 +207,6 @@ skip-networking - - But allow: - - localconfig.js - localconfig.rdf - - - diff --git a/docs/xml/using.xml b/docs/xml/using.xml index 720f461e9d..5a11730ccc 100644 --- a/docs/xml/using.xml +++ b/docs/xml/using.xml @@ -725,11 +725,12 @@ summary and status whiteboard of a bug; adding ":BazProduct" would search only in that product. + You can use it to find a bug by its number or its alias, too. - You'll find the Quicksearch box on Bugzilla's - front page, along with a - Help + You'll find the Quicksearch box in Bugzilla's footer area. + On Bugzilla's front page, there is an additional + Help link which details how to use it. diff --git a/localconfig.js b/localconfig.js deleted file mode 100644 index 2cbe6f24f7..0000000000 --- a/localconfig.js +++ /dev/null @@ -1,75 +0,0 @@ -// -// This file contains the installation specific values for QuickSearch. -// See quicksearch.js for more details. -// - -// the global bugzilla url - -var bugzilla = ""; -//var bugzilla = "http://bugzilla.mozilla.org/"; - -// Status and Resolution -// --------------------- - -var statuses_open = new Array("UNCONFIRMED","NEW","ASSIGNED","REOPENED"); -var statuses_resolved = new Array("RESOLVED","VERIFIED","CLOSED"); -var resolutions = new Array("FIXED","INVALID","WONTFIX","LATER", - "REMIND","DUPLICATE","WORKSFORME","MOVED"); - -// Keywords -// -------- -// -// Enumerate all your keywords here. This is necessary to avoid -// "foo is not a legal keyword" errors. This makes it possible -// to include the keywords field in the search by default. - -var keywords = new Array( -// "foo", "bar", "baz" -); - -// Platforms -// --------- -// -// A list of words (substrings of platform values) -// that will automatically be translated to "platform:" -// E.g. if "mac" is defined as a platform, then searching -// for it will find all bugs with platform="Macintosh", -// but no other bugs with e.g. "mac" in the summary. - -var platforms = new Array( -"pc","sun","macintosh","mac" //shortcut added -//,"dec","hp","sgi" -//,"all" //this is a legal value for OpSys, too :( -//,"other" -); - -// Severities -// ---------- -// -// A list of words (substrings of severity values) -// that will automatically be translated to "severity:" -// E.g with this default set of severities, searching for -// "blo,cri,maj" will find all severe bugs. - -var severities = new Array("blo","cri","maj","nor","min","tri","enh"); - -// Products and Components -// ----------------------- -// -// It is not necessary to list all products and components here. -// Instead, you can define a "blacklist" for some commonly used -// words or word fragments that occur in a product or component name -// but should _not_ trigger product/component search. - -var product_exceptions = new Array( -"row" // [Browser] - // ^^^ -,"new" // [MailNews] - // ^^^ -); - -var component_exceptions = new Array( -"hang" // [mozilla.org] Bugzilla: Component/Keyword Changes - // ^^^^ -); - diff --git a/quicksearch.html b/quicksearch.html deleted file mode 100644 index 1b1ecb1a67..0000000000 --- a/quicksearch.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - Bugzilla QuickSearch - - - - -

-If you are already familiar with the original -Bugzilla Query Form, -you may prefer this form. - -

- - - - -

Bugzilla QuickSearch

- -

-Type in one or more words (or word fragments) to search for: -

- -
- - - - - - -
-
- - - -

Getting Started

- -
    -
  • This is case-insensitive search. -
      -
    •  table ,  Table  - and  TABLE  are all the same.
    • -
    -
  • -
  • This is all words as substrings search.
    - Therefore you should use stems to get better results: -
      -
    • Use localiz instead of localize or - localization.
    • -
    • Use bookmark instead of bookmarks or - bookmarking.
    • -
    -
  • -
- -

Features

- -
    -
  • Boolean operations: ``-foo''(NOT), ``foo bar''(AND), - ``foo|bar''(OR). -
      -
    • NOT: Use  -foo  to exclude bugs - with  foo  in the summary.
    • -
    • AND: Space-separated words are treated as a conjunction.
    • -
    • OR: Within a word, "|"-separated parts denote alternatives.
    • -
    • Besides "|", a comma can be used to separate alternatives.
    • -
    • OR has higher precedence than AND; AND is the top level operation
    • -
    - Example:  url,location bar,field -focus  - means - (url OR location) AND (bar OR field) AND (NOT focus) -

    -

  • -
  • Use  +foo  to search for bugs where the summary contains  foo  as a substring.
    - Use  #foo  to search for bugs where the summary contains the word  foo  -
      -
    •  +brow  does not find all bugs in the  Browser  product
    • -
    •  #title  does not find bugs bugs with  titlebar  or  titled 
    • -
    - Phrases with special chars (space, comma, +, -, #, ...) can be quoted: -
      -
    •  "lock icon" 
    • -
    -

    -

  • -
  • Open vs. Resolved Bugs:
    - By default, only open (i.e. unresolved) bugs are shown. - Use  +DUP  as first word in your query - to include duplicate bugs in your search, -  FIXED  to search for fixed bugs only, - or  ALL  to search all bugs, - regardless of status or resolution. Searching for duplicates is - recommended if you can't find an open bug directly. -
      -
    •  +DUP,FIXED table border 
    • -
    •  ALL mouse wheel 
    • -
    -

  • -
  • Focus the Search with Products & Components:
    - To search for bugs in product "Foo Bar" only, add -  :foo  or  :bar  or both - to your query. - You can do this with any substring of a - product or component - to focus the search. -
  • -
- -

More Tips

- -
    -
  • You can also use this tool to lookup a bug by its number. -
      -
    •  12345 
    • -
    -
  • -
  • A comma-separated list of bug numbers gives you a list of these bugs. -
      -
    •  12345,23456,34567 
    • -
    -
  • -
- -

-By default, the following fields are searched: Summary, Keywords, Product, -Component, Status Whiteboard. If a word looks like a part of a URL, that field -is included in the search, too. -

- -
- -

-Use the powerful -Bugzilla Query Form -for advanced queries. -

- - - diff --git a/quicksearch.js b/quicksearch.js deleted file mode 100644 index 29ab6eb6b3..0000000000 --- a/quicksearch.js +++ /dev/null @@ -1,740 +0,0 @@ -// -// This is the main JS file for QuickSearch. -// -// Derived from: -// -// * C. Begle's SimpleSearch tool: -// http://www.mozilla.org/quality/help/simplesearch.html -// http://www.mozilla.org/quality/help/bugreport.js -// -// * Jesse Ruderman's bugzilla search page: -// http://www.cs.hmc.edu/~jruderma/s/bugz.html -// -// Created by -// Andreas Franke -// -// Contributors: -// Stephen Lee - - -// Use no_result variable to avoid problems with "undefined" on some browsers - -var no_result="---"; - -// do_unshift(l, s) is equivalent to l.unshift(s), but some browsers do not -// support the built-in function. - -function do_unshift(l, s) { - l.length = l.length + 1; - for (var i=l.length-1; i>0; i--) { - l[i] = l[i-1]; - } - l[0] = s; - return l.length; -} - -// do_shift(l) is equivalent to l.shift(s), but some browsers do not -// support the built-in function. - -function do_shift(l) { - var l0=l[0]; - for (var i=0; i "dependson" -// "OtherBugsDependingOnThis"--> "blocked" -//add_mapping("dependson", "dependson"); -//add_mapping("blocked", "blocked"); - -// Substring search doesn't make much sense for the following fields: -// "Attachment is patch" --> "attachments.ispatch" -// "Last changed date" --> "delta_ts" -// "Days since bug changed" --> "(to_days(now()) - to_days(bugs.delta_ts))" -//"groupset" -//"everconfirmed" -//"bug","bugid","bugno" --> "bug_id" -// "votes" --> "votes" -// "votes>5", "votes>=5", "votes=>5" works now, see below -// "votes:5" is interpreted as "votes>=5" - -function findIndex(array,value) { - for (var i=0; i= 0) return f2[i]; - return no_result; -} - -// `keywords' is defined externally - -function is_keyword(s) { - return member(s, keywords); -} - -// `platforms' is defined externally - -function is_platform(str) { - return member (str.toLowerCase(),platforms); -} - -// `severities' is defined externally - -function is_severity(str) { - return member(str.toLowerCase(),severities); -} - -// `product_exceptions' is defined externally - -function match_product(str) { - var s = str.toLowerCase(); - return (s.length > 2) && (! member(s,product_exceptions)); -} - -// `component_exceptions are defined externally - -function match_component(str) { - var s = str.toLowerCase(); - return (s.length > 2) && (! member(s,component_exceptions)); -} - -var status_and_resolution = ""; // for pretty debug output only; these vars -var charts = ""; // always hold the data from the last query - -// derived from http://www.mozilla.org/quality/help/bugreport.js - -function make_chart(expr, field, type, value) { - charts += "" + - "" + expr + "" + - "" + field + "" + - "" + type + "" + - "" + value + "" + - ""; - return "&field" + expr + "=" + field + - "&type" + expr + "=" + type + - "&value" + expr + "=" + escape(value).replace(/[+]/g,"%2B"); -} - -// returns true if at least one of comparelist had the prefix, false otherwise -function addPrefixMatches(prefix, comparelist, resultlist) { - var foundMatch = false; - for (var i=0; i "foo%20bar" - parts = input.split('"'); - if ((parts.length % 2) != 1) { - alert('Unterminated quote'); - abort = true; - return no_result; - } - for (i=1; i 0)) { - prefixesNotFoundError(failedPrefixes,statuses,resolutions); - abort = true; - } - return foundMatch; - } - - if (word[0] == "ALL") { - // special case: search for bugs regardless of status - addAll(statusResolved,bug_status); - do_shift(word); - } else if (word[0] == "OPEN") { - // special case: search for open bugs only - do_shift(word); - } else if (word[0].match("^[+][A-Z]+(,[A-Z]+)*$")) { - // e.g. +DUP,FIX - w0 = do_shift(word); - prefixes = w0.substring(1).split(","); - if (! matchPrefixes(prefixes,statusResolved,resolutions)) { - do_unshift(word,w0); - } - } else if (word[0].match("^[A-Z]+(,[A-Z]+)*$")) { - // e.g. NEW,ASSI,REOP,FIX - bug_status = new Array(); // reset - w0 = do_shift(word); - prefixes = w0.split(","); - if (! matchPrefixes(prefixes,statusAll,resolutions)) { - do_unshift(word,w0); - bug_status = statusOpen.reverse(); //reset to default bug_status - } - } else { - // default case: - // search for unresolved bugs only - // uncomment this to include duplicate bugs in the search - // add("DUPLICATE",resolution); - } - if (resolution.length > 0) { - resolution = resolution.reverse(); - do_unshift(resolution,"---"); - addAll(statusResolved,bug_status); - } - bug_status = bug_status.reverse(); - bug_status = map(bug_status,escape); - searchURL += "?bug_status=" + bug_status.join("&bug_status="); - status_and_resolution += 'Status: '+bug_status+''; - - if (resolution.length > 0) { - resolution = map(resolution,escape); - searchURL += "&resolution=" + resolution.join("&resolution="); - status_and_resolution += '
'+'Resolution: '+resolution+''; - } - - // end of bug_status & resolution stuff - - chart = 0; - and = 0; - or = 0; - - negation = false; - - function negate_comparison_type(type) { - switch(type) { - case "substring": return "notsubstring"; - case "anywords": return "nowords"; - case "regexp": return "notregexp"; - default: - // e.g. "greaterthan" - alert("Can't negate comparison type: `" + type + "'"); - abort = true; - return "dummy"; - } - } - - function add_chart(field,type,value) { - // undo escaping for value: '"foo%20bar"' --> 'foo bar' - var parts = value.split('"'); - if ((parts.length % 2) != 1) { - alert('Internal error: unescaping failure'); - abort = true; - } - for (var i=1; ixx - if (w.match("^votes>[0-9]+$")) { - n = w.split(">")[1]; - add_chart("votes","greaterthan",n); - continue; - } - // votes>=xx, votes=>xx - if (w.match("^votes(>=|=>)[0-9]+$")) { - separator = w.match("^votes(>=|=>)[0-9]+$")[1]; - n = w.split(separator)[1]; - add_chart("votes","greaterthan",String(n-1)); - continue; - } - // really default case - if (match_product(w)) { - add_chart("product","substring",w); - } - if (match_component(w)) { - add_chart("component","substring",w); - } - if (is_keyword(w)) { - add_chart("keywords","substring",w); - if (w.length > 2) { - add_chart("short_desc","substring",w); - add_chart("status_whiteboard","substring",w); - } - } else { - add_chart("short_desc","substring",w); - add_chart("status_whiteboard","substring",w); - } - if (searchLong) - add_chart("longdesc","substring",w); - - // URL field (for IP addrs, host.names, scheme://urls) - if (w.match(/[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+/) - || w.match(/^[A-Za-z]+([.][A-Za-z]+)+/) - || w.match(/[:][\/][\/]/) - || w.match(/localhost/) - || w.match(/mailto[:]?/) - // || w.match(/[A-Za-z]+[:][0-9]+/) //host:port - ) - add_chart("bug_file_loc","substring",w); - } - } - } - and = 0; - or = 0; - } - - //searchURL += "&cmdtype=doit"; - - if (abort == false) { - return searchURL; - } else { - return no_result; - } -} - -function unique_id () { - return (new Date()).getTime(); -} - -function ShowURL(mode,input) { - var searchURL = make_query_URL(bugzilla+"buglist.cgi", input, false); - if (searchURL != no_result) { - var pieces = searchURL.replace(/[\?]/g,"\n?").replace(/[\&]/g,"\n&"); - if (mode == "alert") { - alert(pieces); - } else { - var table = "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + charts + "" + - "
Chart-And-OrFieldTypeValue
"; - var html = '' + - '' + - '' + input + '' + - '' + - '' + - '' + - 'Submit Query' + - '' + - '

' + status_and_resolution + - '

' + table + - '

' +
-                             pieces.replace(/[\n]/g,"
") + - '
' + - '' + - ''; - var w = window.open("","preview_"+unique_id()); - w.document.write(html); - w.document.close(); - } - } -} - -// -// new interface: -// searchLong is a boolean now (not a checkbox/radiobutton) -// -function Search(url, input, searchLong) { - var inputstring = new String(input); - var word = inputstring.split(/[\s]+/); - - // Check for empty input - if ( word.length == 1 && word[0] == "" ) - return; - - // Check for potential Bugzilla-busting intensive queries - if ((searchLong!=false) && word.length > 4) { - var message = "Searching Descriptions for more than four words " + - "will take a very long time indeed. Please choose " + - "no more than four keywords for your query."; - alert(message); - return; - } - var searchURL = make_query_URL(url, inputstring, searchLong); - if (searchURL != no_result) { - go_to(searchURL); - //window.open(searchURL, "other" ); - } else { - return; - } -} - -// -// original interface, untested -// -//function SearchForBugs (input, searchRadio) { -// if (searchRadio[0].checked) { -// return Search(bugzilla + "buglist.cgi", input, false); -// } else { -// return Search(bugzilla + "buglist.cgi", input, true); -// } -//} - -// derived from http://www.cs.hmc.edu/~jruderma/s/bugz.html - -// QuickSearch combines lookup-by-bug-number and search -// in a single textbox. -// -// type nothing: -// --> go to bugzilla front page -// type a number: -// --> go to that bug number -// type several numbers, separated by commas: -// --> go to a buglist of just those bug numbers -// type anything else: -// --> search summary, product, component, keywords, status whiteboard -// (and URL if it's an IP address, a host.name, or an absolute://URL) - -function QuickSearch (input) -{ - //remove leading and trailing whitespace - input = input.replace(/^[\s]+/,"").replace(/[\s]+$/,""); - - if (input == "") - { - //once this _is_ on http://bugzilla.mozilla.org, it should just return; - go_to(bugzilla); - } - else if (input.match(/^[0-9, ]*$/)) - { - if (input.indexOf(",") == -1) { - // only _one_ bug number --> show_bug - go_to(bugzilla+"show_bug.cgi?id="+escape(input)); - } else { - // comma-separated bug numbers --> buglist - go_to(bugzilla+"buglist.cgi?bug_id="+escape(input) - + "&bugidtype=include&order=bugs.bug_id"); - } - } - else - { - Search(bugzilla+"buglist.cgi",input,false); - } - return; -} - -function LoadQuery(input) { - //remove leading and trailing whitespace - input = input.replace(/^[\s]+/,"").replace(/[\s]+$/,""); - - Search(bugzilla+"query.cgi",input,false); - return; -} - diff --git a/quicksearchhack.html b/quicksearchhack.html deleted file mode 100644 index d514082f83..0000000000 --- a/quicksearchhack.html +++ /dev/null @@ -1,357 +0,0 @@ - - - - - Bugzilla QuickSearch (for Hackers) - - - - - - - -

Bugzilla QuickSearch (for Hackers)

- -

-Type in one or more words (or word fragments) to search for: -

- -
- - - - - - -
-
-
- - - -

-This is a case-insensitive ``all words as substrings'' search; -words are separated by spaces. -By default, the following fields are relevant: Summary, Keywords, -Product, Component, Status Whiteboard. If a word looks like a part of a -URL, that field is included in the search, too. -

-

-The generic format for a ``word'' is - field1,...,fieldN:value1,...,valueM . -A bug qualifies if at least one of the values occurs as a substring in -at least one of the fields. -For example,  assignee,reporter,qa:ibm,sun  -will give you bugs where the assignee, reporter, or qa contact -has an email address that contains - ibm  or  sun . -If only  value1,...,valueM  is given, -the prefix (roughly) defaults to  summary,keywords,product,component,statuswhiteboard:  as noted above. -You can use  -word  to express the logical negation -of  word.  -

-

-Here is a complete listing of available fields (the Shortcut column is just -for access speed): -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Searched by defaultShortcutField NameAliasesDescription
 UNCO,NEW,...,CLOS,
FIX,DUP,...(as first word)
status Status - ("bug_status") -
 resolution Resolution
 as-isplatform Platform ("rep_platform")
  osopsysOS ("op_sys")
 p1,p2 or p1-2prioritypriPriority
 blo,cri,...,enhseveritysevSeverity ("bug_severity")
 @assigneeassignedtoassignee, ownerAssignee ("assigned_to")
  reporterrepReporter (email)
  qaqacontactQA Contact (email) ("qa_contact")
  cc CC (email)
yes:areaproductprodProduct (enum)
yescomponentcompComponent
  versionverVersion (enum)
  milestonetarget, targetmilestoneTarget Milestone ("target_milestone")
yes summaryshortdescBug Summary (short text)("short_desc")
  descriptiondesc, longdescBug Description / Comments (long text)
depends url URL ("bug_file_loc")
yes statuswhiteboardsw, whiteboardStatus Whiteboard ("status_whiteboard")
yes!keywordkeywordskwKeywords
  attachmentdescattachdescAttachment Description ("attachments.description")
  attachmentdataattachdataAttachment Data ("attachments.thedata")
  attachmentmimetypeattachmimetypeAttachment mime-type ("attachments.mimetype")
- -

-Examples for some useful abbreviations: -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SyntaxSemantics and Examples
:areaproduct,component:area
sevseverity:sev
blo,cri,majsevere bugs
enhenhancement requests
plevelpriority:level
p1very high-priority bugs
p1-2high-priority bugs
@assigneeassignedto:assignee
!keywordkeywords:keyword
- -

-More information can be found in the -"Features" section -on the introductory page. -

- - - - diff --git a/skins/standard/global.css b/skins/standard/global.css index 4c265df1e3..ea95e74602 100644 --- a/skins/standard/global.css +++ b/skins/standard/global.css @@ -176,13 +176,14 @@ body margin-top: 5px; width: 100%; font-family: sans-serif; + background: #edf2f2; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; } #footer form { - background: #edf2f2; - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; + display: inline; } #footer span diff --git a/template/en/default/config.js.tmpl b/template/en/default/config.js.tmpl index a74c5d34d6..e3ec91435a 100644 --- a/template/en/default/config.js.tmpl +++ b/template/en/default/config.js.tmpl @@ -19,8 +19,7 @@ # Contributor(s): Myk Melez #%] // -// This file contains the installation specific values for QuickSearch -// and other Bugzilla clients. See quicksearch.js for more details. +// This file contains installation specific values for third-party clients. // // Note: this interface is experimental and under development. // We may and probably will make breaking changes to it in the future. diff --git a/template/en/default/global/useful-links.html.tmpl b/template/en/default/global/useful-links.html.tmpl index 38b193cf57..5a01a5703d 100644 --- a/template/en/default/global/useful-links.html.tmpl +++ b/template/en/default/global/useful-links.html.tmpl @@ -25,7 +25,6 @@ [% PROCESS global/variables.none.tmpl %] -