summaryrefslogtreecommitdiffstats
path: root/quicksearch.js
diff options
context:
space:
mode:
authorlpsolit%gmail.com <>2005-08-22 03:16:40 +0200
committerlpsolit%gmail.com <>2005-08-22 03:16:40 +0200
commitf4966aeb0e7a655c986aeb285c1a220274ddbfd9 (patch)
tree70fc81865b58b54e97da10c8cc824ae9fb641672 /quicksearch.js
parentd055246d2010e546bbad8c65d99496d53eee0bff (diff)
downloadbugzilla-f4966aeb0e7a655c986aeb285c1a220274ddbfd9.tar.gz
bugzilla-f4966aeb0e7a655c986aeb285c1a220274ddbfd9.tar.xz
Bug 70907: QuickSearch: port the JS code to perl (make it server-side) - Patch by Marc Schumann <wurblzap@gmail.com> r=wicked a=myk
Diffstat (limited to 'quicksearch.js')
-rw-r--r--quicksearch.js740
1 files changed, 0 insertions, 740 deletions
diff --git a/quicksearch.js b/quicksearch.js
deleted file mode 100644
index 29ab6eb6b..000000000
--- 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 <afranke@mathweb.org>
-//
-// Contributors:
-// Stephen Lee <slee@uk.bnsmc.com>
-
-
-// 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<l.length-1; i++) {
- l[i] = l[i+1];
- }
- l.length = l.length - 1;
- return l0;
-}
-
-function go_to (url) {
- // XXX specifying "sidebar" here indicates you want to use a
- // function to do the actual loading instead of using the specified
- // url directly. bug 236025 covers clarifying this. Pages that specify
- // sidebar=1 *must* specify a load_absolute_url function meanwhile.
- if ( typeof sidebar != "undefined" && sidebar == 1 ) {
- load_absolute_url(url);
- } else {
- document.location.href = url;
- }
-}
-
-function map(l, f) {
- var l1 = new Array();
- for (var i=0; i<l.length; i++) {
- l1[i] = f(l[i]);
- }
- return l1;
-}
-
-function isPrefix(s1, s2) {
- return (s1.length <= s2.length) &&
- (s1 == s2.substring(0,s1.length))
-}
-
-function member(s, l) {
- for (var i=0; i<l.length; i++) {
- if (l[i] == s) return true;
- }
- return false;
-}
-
-function add(s, l) {
- if (! member(s, l)) {
- do_unshift(l,s);
- }
-}
-
-function addAll(l1, l2) {
- for (var i=0; i<l1.length; i++) {
- add(l1[i],l2);
- }
-}
-
-function isSubset (l1, l2) {
- return (l1.length == 0)
- || (member(l1[0],l2) && subset(l1.slice(1),l2));
-}
-
-// fields
-
-var f1 = new Array();
-var f2 = new Array();
-
-function add_mapping(from,to) {
- f1[f1.length] = from;
- f2[f2.length] = to;
-}
-
-// Status, Resolution, Platform, OS, Priority, Severity
-add_mapping("status", "bug_status");
-add_mapping("resolution", "resolution"); // no change
-add_mapping("platform", "rep_platform");
-add_mapping("os", "op_sys");
-add_mapping("opsys", "op_sys");
-add_mapping("priority", "priority"); // no change
-add_mapping("pri", "priority");
-add_mapping("severity", "bug_severity");
-add_mapping("sev", "bug_severity");
-// People: AssignedTo, Reporter, QA Contact, CC, Added comment (?)
-add_mapping("owner", "assigned_to");
-add_mapping("assignee", "assigned_to");
-add_mapping("assignedto", "assigned_to");
-add_mapping("reporter", "reporter"); // no change
-add_mapping("rep", "reporter");
-add_mapping("qa", "qa_contact");
-add_mapping("qacontact", "qa_contact");
-add_mapping("cc", "cc"); // no change
-// Product, Version, Component, Target Milestone
-add_mapping("product", "product"); // no change
-add_mapping("prod", "product");
-add_mapping("version", "version"); // no change
-add_mapping("ver", "version");
-add_mapping("component", "component"); // no change
-add_mapping("comp", "component");
-add_mapping("milestone", "target_milestone");
-add_mapping("target", "target_milestone");
-add_mapping("targetmilestone", "target_milestone");
-// Summary, Description, URL, Status whiteboard, Keywords
-add_mapping("summary", "short_desc");
-add_mapping("shortdesc", "short_desc");
-add_mapping("desc", "longdesc");
-add_mapping("description", "longdesc");
-//add_mapping("comment", "longdesc"); // ???
- // reserve "comment" for "added comment" email search?
-add_mapping("longdesc", "longdesc");
-add_mapping("url", "bug_file_loc");
-add_mapping("whiteboard", "status_whiteboard");
-add_mapping("statuswhiteboard", "status_whiteboard");
-add_mapping("sw", "status_whiteboard");
-add_mapping("keywords", "keywords"); // no change
-add_mapping("kw", "keywords");
-// Attachments
-add_mapping("attachment", "attachments.description");
-add_mapping("attachmentdesc", "attachments.description");
-add_mapping("attachdesc", "attachments.description");
-add_mapping("attachmentdata", "attachments.thedata");
-add_mapping("attachdata", "attachments.thedata");
-add_mapping("attachmentmimetype", "attachments.mimetype");
-add_mapping("attachmimetype", "attachments.mimetype");
-
-// disabled because of bug 30823:
-// "BugsThisDependsOn" --> "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<array.length; i++)
- if (array[i] == value) return i;
- return -1;
-}
-
-function mapField(fieldname) {
- var i = findIndex(f1,fieldname);
- if (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 += "<tr>" +
- "<td><tt>" + expr + "</tt></td>" +
- "<td><tt>" + field + "</tt></td>" +
- "<td><tt>" + type + "</tt></td>" +
- "<td><tt>" + value + "</tt></td>" +
- "</tr>";
- 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<comparelist.length; i++) {
- if (isPrefix(prefix,comparelist[i])) {
- foundMatch = true;
- add(comparelist[i],resultlist);
- }
- }
- return foundMatch;
-}
-
-function prefixesNotFoundError(prefixes,statusValues,resolutionValues) {
- var txt;
- if (prefixes.length == 1) {
- txt = "is not a prefix ";
- } else {
- txt = "are not prefixes ";
- }
- alert(prefixes + "\n" + txt +
- "of one of these status or resolution values:\n" +
- statusValues + "\n" + resolutionValues + "\n");
-}
-
-function make_query_URL(url, input, searchLong) {
-
- status_and_resolution = "";
- charts = "";
-
- // declare all variables used in this function
-
- var searchURL = url; // bugzilla + "buglist.cgi" (or "query.cgi")
- var abort = false; // global flag, checked upon return
-
- var i,j,k,l; // index counters used in 'for' loops
- var parts,input2; // escape "quoted" parts of input
-
- var word; // array of words
- // (space-separated parts of input2)
- var alternative; // array of parts of an element of 'word'
- // (separated by '|', sometimes by comma)
- var comma_separated_words; // array of parts of an element of 'alternative'
- var w; // current element of one of these arrays:
- // word, alternative, comma_separated_words
-
- var w0; // first element of 'word'
- var prefixes; // comma-separated parts of w0
- // (prefixes of status/resolution values)
-
- var expr; // used for 'priority' support
- var n,separator; // used for 'votes' support
-
- var colon_separated_parts, fields,values,field;
- // used for generic fields:values notation
-
- var chart,and,or; // counters used in add_chart
- var negation; // boolean flag used in add_chart
-
- // `statuses_open' and `statuses_resolved' are defined externally
- var statusOpen = statuses_open;
- var statusResolved = statuses_resolved;
- var statusAll = statusOpen.concat(statusResolved);
-
- // `resolutions' is defined externally
- var bug_status = statusOpen.slice().reverse(); //reverse is just cosmetic
- var resolution = new Array();
-
- // escape everything between quotes: "foo bar" --> "foo%20bar"
- parts = input.split('"');
- if ((parts.length % 2) != 1) {
- alert('Unterminated quote');
- abort = true;
- return no_result;
- }
- for (i=1; i<parts.length; i+=2) {
- parts[i] = escape(parts[i]);
- }
- input2 = parts.join('"');
-
- // abort if there are still brackets
- if (input2.match(/[(]|[\)]/)) {
- alert('Brackets (...) are not supported.\n' +
- 'Use quotes "..." for values that contain special characters.');
- abort = true;
- return no_result;
- }
-
- // translate " AND "," OR "," NOT " to space,comma,dash
- input2 = input2.replace(/[\s]+AND[\s]+/g," ");
- input2 = input2.replace(/[\s]+OR[\s]+/g,"|");
- input2 = input2.replace(/[\s]+NOT[\s]+/g," -");
-
- // now split into words at space positions
- word = input2.split(/[\s]+/);
-
- // determine bug_status and resolution
- // the first word may contain relevant info
-
- // This function matches the given prefixes against the given statuses and
- // resolutions. Matched statuses are added to bug_status, matched
- // resolutions are added to resolution. Returns true if and only if
- // some matches were found for at least one of the given prefixes.
- function matchPrefixes(prefixes,statuses,resolutions) {
- var failedPrefixes = new Array();
- var foundMatch = false;
- for (var j=0; j<prefixes.length; j++) {
- var ok1 = addPrefixMatches(prefixes[j],statuses,bug_status);
- var ok2 = addPrefixMatches(prefixes[j],resolutions,resolution);
- if ((! ok1) && (! ok2)) {
- add(prefixes[j],failedPrefixes);
- } else {
- foundMatch = true;
- }
- }
- //report an error if some (but not all) prefixes didn't match anything
- if (foundMatch && (failedPrefixes.length > 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: <tt>'+bug_status+'</tt>';
-
- if (resolution.length > 0) {
- resolution = map(resolution,escape);
- searchURL += "&resolution=" + resolution.join("&resolution=");
- status_and_resolution += '<br>'+'Resolution: <tt>'+resolution+'</tt>';
- }
-
- // 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; i<parts.length; i+=2) {
- parts[i] = unescape(parts[i]);
- }
- var value2 = parts.join('');
-
- // negate type if negation is set
- var type2 = type;
- if (negation) {
- type2 = negate_comparison_type(type2);
- }
- searchURL += make_chart(chart+"-"+and+"-"+or,field,type2,value2);
- or++;
- if (negation) {
- and++;
- or=0;
- }
- }
-
- for (i=0; i<word.length; i++, chart++) {
-
- w = word[i];
-
- negation = false;
- if (w.charAt(0) == "-") {
- negation = true;
- w = w.substring(1);
- }
-
- switch (w.charAt(0)) {
- case "+":
- alternative = w.substring(1).split(/[|,]/);
- for (j=0; j<alternative.length; j++)
- add_chart("short_desc","substring",alternative[j]);
- break;
- case "#":
- alternative = w.substring(1).replace(/[|,]/g," ");
- add_chart("short_desc","anywords",alternative);
- if (searchLong)
- add_chart("longdesc","anywords",alternative);
- break;
- case ":":
- alternative = w.substring(1).split(",");
- for (j=0; j<alternative.length; j++) {
- add_chart("product","substring",alternative[j]);
- add_chart("component","substring",alternative[j]);
- }
- break;
- case "@":
- alternative = w.substring(1).split(",");
- for (j=0; j<alternative.length; j++)
- add_chart("assigned_to","substring",alternative[j]);
- break;
- case "[":
- add_chart("short_desc","substring",w);
- add_chart("status_whiteboard","substring",w);
- break;
- case "!":
- add_chart("keywords","anywords",w.substring(1));
- break;
- default:
- alternative=w.split("|");
- for (j=0; j<alternative.length; j++) {
-
- w=alternative[j];
-
- // votes:xx ("at least xx votes")
- if (w.match("^votes[:][0-9]+$")) {
- n = w.split(/[:]/)[1];
- add_chart("votes","greaterthan",String(n-1));
- continue;
- }
- // generic field1,field2,field3:value1,value2 notation
- if (w.match("^[^:]+[:][^:\/][^:]*$")) {
- colon_separated_parts = w.split(":");
- fields = colon_separated_parts[0].split(/[,]+/);
- values = colon_separated_parts[1].split(/[,]+/);
- for (k=0; k<fields.length; k++) {
- field = mapField(fields[k]);
- if (field == no_result) {
- alert("`"+fields[k]+"'"+
- " is not a valid field name.");
- abort = true;
- return no_result;
- } else {
- for (l=0; l<values.length; l++) {
- add_chart(field,"substring",values[l]);
- }
- }
- }
- continue;
- }
- comma_separated_words=w.split(/[,]+/);
- for (k=0; k<comma_separated_words.length; k++) {
- w=comma_separated_words[k];
-
- // platform
- if (is_platform(w)) {
- add_chart("rep_platform","substring",w);
- continue;
- }
- // priority
- if (w.match("^[pP][1-5](,[pP]?[1-5])*$")) {
- expr = "["+w.replace(/[p,]/g,"")+"]";
- add_chart("priority","regexp",expr);
- continue;
- }
- if (w.match("^[pP][1-5]-[1-5]$")) {
- expr = "["+w.substring(1)+"]";
- add_chart("priority","regexp",expr);
- continue;
- }
- // severity
- if (is_severity(w)) {
- add_chart("bug_severity","substring",w);
- continue;
- }
- // votes>xx
- 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 = "<table border=1>" +
- "<thead>" +
- "<tr>" +
- "<th>Chart-And-Or</th>" +
- "<th>Field</th>" +
- "<th>Type</th>" +
- "<th>Value</th>" +
- "</tr>" +
- "</thead>" +
- "<tbody>" + charts + "</tbody>" +
- "</table>";
- var html = '<html>' +
- '<head>' +
- '<title>' + input + '</title>' +
- '</head>' +
- '<body>' +
- '<a href="' + searchURL + '">' +
- 'Submit Query' +
- '</a>' +
- '<p>' + status_and_resolution +
- '<p>' + table +
- '<pre>' +
- pieces.replace(/[\n]/g,"<br>") +
- '</pre>' +
- '</body>' +
- '</html>';
- 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;
-}
-