From 36d7b30e10cc479630f51bcb76f47479086dda45 Mon Sep 17 00:00:00 2001 From: Jeremy Maitin-Shepard Date: Mon, 14 Apr 2008 03:08:06 -0400 Subject: [PATCH] Add webjump integration with OpenSearch search engines This provides support for search suggestion completions. --- modules/history.js | 22 +----- modules/minibuffer-completion.js | 84 ++++++++++++--------- modules/minibuffer-read.js | 73 ++++++++++++++---- modules/minibuffer.js | 10 ++- modules/search-engine.js | 109 ++++++++++++++++++++++++++- modules/webjump.js | 142 ++++++++++++++++++++++++------------ search-engines/amazondotcom.xml | 13 ++++ search-engines/answers.xml | 13 ++++ search-engines/creativecommons.xml | 11 +++ search-engines/eBay.xml | 17 +++++ search-engines/google.xml | 15 ++++ search-engines/mozilla-bugzilla.xml | 8 ++ search-engines/wikipedia.xml | 15 ++++ search-engines/yahoo.xml | 14 ++++ 14 files changed, 424 insertions(+), 122 deletions(-) create mode 100644 search-engines/amazondotcom.xml create mode 100644 search-engines/answers.xml create mode 100644 search-engines/creativecommons.xml create mode 100644 search-engines/eBay.xml create mode 100644 search-engines/google.xml create mode 100644 search-engines/mozilla-bugzilla.xml create mode 100644 search-engines/wikipedia.xml create mode 100644 search-engines/yahoo.xml diff --git a/modules/history.js b/modules/history.js index 5e18635..9d78296 100644 --- a/modules/history.js +++ b/modules/history.js @@ -21,30 +21,14 @@ function history_completer() { root.containerOpen = true; var history_count = root.childCount; return {count: history_count, - get_string: function (i) { - return root.getChild(i).uri; - }, - get_description: function (i) { - return root.getChild(i).title; - }, - apply: function (i, m) { - apply_completion_string(root.getChild(i).uri, m); - }, + get_string: function (i) root.getChild(i).uri, + get_description: function (i) root.getChild(i).title, + get_input_state: function (i) [root.getChild(i).uri], destroy: function () { root.containerOpen = false; } }; } } -function webjump_completer() { - return prefix_completer( - $completions = function(visitor) { - for (var i in webjumps) - visitor([i,webjumps[i]]); - }, - $get_string = function (x) x[0] + " ", - $get_description = function (x) ""); -} - function url_completer() { keywords(arguments); var use_webjumps = arguments.$use_webjumps; diff --git a/modules/minibuffer-completion.js b/modules/minibuffer-completion.js index 0f26c7b..f19714d 100644 --- a/modules/minibuffer-completion.js +++ b/modules/minibuffer-completion.js @@ -1,11 +1,5 @@ require("minibuffer.js"); - -function apply_completion_string(str, m) { - m._set_selection(); - m._input_text = str; -} - /** * Completions is either a visit function or an array. */ @@ -42,7 +36,7 @@ function all_word_completer() index_of: function (x) data.indexOf(x), get_string: function (i) get_string(data[i]), get_description : function (i) get_description(data[i]), - apply : function (i, m) apply_completion_string(get_string(data[i]), m), + get_input_state: function (i) [get_string(data[i])], get_value : function(i) (get_value ? get_value(data[i]) : data[i]) }; } @@ -61,17 +55,16 @@ function get_common_prefix_length(a, b, len) { return i; } -function apply_partial_completion(x, prefix_end, suffix_begin, orig_str, m) { +function get_partial_completion_input_state(x, prefix_end, suffix_begin, orig_str) { if (suffix_begin < orig_str.length) { if (orig_str[suffix_begin] == " ") suffix_begin++; - m._input_text = orig_str.substring(0, prefix_end) + x + " " + orig_str.substring(suffix_begin); let sel = x.length + prefix_end + 1; - m._set_selection(sel, sel); + return [orig_str.substring(0, prefix_end) + x + " " + orig_str.substring(suffix_begin), + sel, sel]; } else { - m._input_text = orig_str.substring(0, prefix_end) + x; let sel = x.length + prefix_end; - m._set_selection(sel, sel); + return [orig_str.substring(0, prefix_end) + x, sel, sel]; } } @@ -139,10 +132,11 @@ function prefix_completer() index_of: function (x) data.indexOf(x), get_string: function (i) get_string(data[i]), get_description : function (i) get_description(data[i]), - apply : function (i, m) apply_partial_completion(get_string(data[i]), 0, pos, input, m), + get_input_state : function (i) get_partial_completion_input_state(get_string(data[i]), 0, pos, input), get_value : function(i) get_value(data[i]), - apply_common_prefix: (common_prefix && - function (m) apply_partial_completion(common_prefix, 0, pos, input, m)), + get common_prefix_input_state () { + return common_prefix && get_partial_completion_input_state(common_prefix, 0, pos, input); + }, default_completion: default_completion }; } @@ -244,9 +238,10 @@ function javascript_completer(buffer) { return {count:data.length, get_string: function (i) data[i][0], get_description: function (i) data[i][1], - apply: function (i,m) apply_partial_completion(data[i][0], offset, pos, input, m), - apply_common_prefix: (common_prefix && - function (m) apply_partial_completion(common_prefix, offset, pos, input, m)) + get_input_state: function (i) get_partial_completion_input_state(data[i][0], offset, pos, input), + get common_prefix_input_state () { + return common_prefix && get_partial_completion_input_state(common_prefix, offset, pos, input); + } }; } } @@ -258,21 +253,19 @@ function merge_completers(completers) { return function (input, pos, conservative) { var results = []; var count = 0; - var results = completers.map(function(c) { - var r = c(input, pos, conservative); - if(r != null) { - count += r.count; - } - return r; - }); - + for (let i = 0; i < completers.length; ++i) { + let r = yield completers[i](input, pos, conservative); + if (r != null && r.count > 0) { + results.push(r); + count += r.count; + } + } function forward(name) { return function() { var args = Array.prototype.slice.call(arguments); var i = args.shift(); for(var j=0; j < results.length; j++) { var r = results[j]; - if(r == null) continue; if(i < r.count) { args.unshift(i); return r[name].apply(this, args); @@ -282,11 +275,36 @@ function merge_completers(completers) { return null; } } - return {count: count, - get_string: forward('get_string'), - get_description: forward('get_description'), - apply: forward('apply'), - destroy: forward('destroy') - }; + yield co_return({count: count, + get_string: forward('get_string'), + get_description: forward('get_description'), + get_input_state: forward('get_input_state'), + destroy: forward('destroy') + }); + }; +} + +function nest_completions(completions, prefix, suffix) { + if (prefix == null) + prefix = ""; + if (suffix == null) + suffix = ""; + function nest(x) { + let [s, a, b] = x; + if (a == null) + a = s.length; + if (b == null) + b = s.length; + return [prefix + s + suffix, a + prefix.length, b + prefix.length]; + } + return { + __proto__: completions, + get_input_state: function (i) nest(completions.get_input_state(i)), + get common_prefix_input_state () { + let x = completions.common_prefix_input_state; + if (x) + return nest(x); + return null; + } }; } diff --git a/modules/minibuffer-read.js b/modules/minibuffer-read.js index dc4d2b6..2de54b4 100644 --- a/modules/minibuffer-read.js +++ b/modules/minibuffer-read.js @@ -173,6 +173,11 @@ text_entry_minibuffer_state.prototype = { destroy : function (window) { if (this.completions != null && this.completions.destroy) this.completions.destroy(); + delete this.completions; + if (this.completions_cont) + this.completions_cont.throw(abort()); + delete this.completions_cont; + var el = this.completions_display_element; if (el) { @@ -198,14 +203,12 @@ text_entry_minibuffer_state.prototype = { this.completions_timer_ID = this.window.setTimeout( function () { s.completions_timer_ID = null; - s.update_completions(true /* auto */); - s.update_completions_display(); + s.update_completions(true /* auto */, true /* update completions display */); }, this.auto_complete_delay); return; } - s.update_completions(true /* auto */); - s.update_completions_display(); + s.update_completions(true /* auto */, true /* update completions display */); }, ran_minibuffer_command : function () { @@ -233,8 +236,7 @@ text_entry_minibuffer_state.prototype = { /* If auto is true, this update is due to auto completion, rather * than specifically requested. */ - update_completions : function (auto) { - + update_completions : function (auto, update_display) { if (this.completions_timer_ID != null) { this.window.clearTimeout(this.completions_timer_ID); @@ -243,14 +245,47 @@ text_entry_minibuffer_state.prototype = { let m = this.window.minibuffer; + if (this.completions_cont) { + this.completions_cont.throw(abort()); + this.completions_cont = null; + } + + let c = this.completer(m._input_text, m._selection_start, + auto && this.auto_complete_conservative); + + if (is_coroutine(c)) { + let s = this; + let already_done = false; + this.completions_cont = co_call(function () { + var x; + try { + x = yield c; + } finally { + s.completions_cont = null; + already_done = true; + } + s.update_completions_done(x, update_display); + }()); + + // In case the completer actually already finished + if (already_done) + this.completions_cont = null; + return; + } else + this.update_completions_done(c, update_display); + }, + + update_completions_done : function update_completions_done(c, update_display) { + /* The completer should return undefined if completion was not * attempted due to auto being true. Otherwise, it can return * null to indicate no completions. */ if (this.completions != null && this.completions.destroy) this.completions.destroy(); - let c = this.completions = this.completer(m._input_text, m._selection_start, - auto && this.auto_complete_conservative); + + this.completions = c; this.completions_valid = true; + this.applied_common_prefix = false; let i = -1; if (c && c.count > 0) { @@ -264,6 +299,9 @@ text_entry_minibuffer_state.prototype = { } this.selected_completion_index = i; } + + if (update_display) + this.update_completions_display(); }, select_completion : function (i) { @@ -286,7 +324,7 @@ text_entry_minibuffer_state.prototype = { if (this.completions_valid && c && !this.match_required && i >= 0 && i < c.count) { - c.apply(i, m); + m.set_input_state(c.get_input_state(i)); } } }; @@ -303,8 +341,11 @@ function minibuffer_complete(window, count) if (!s.completions_valid || s.completions === undefined) { if (s.completions_timer_ID == null) just_completed_manually = true; - s.update_completions(false /* not auto */); - s.update_completions_display(); + s.update_completions(false /* not auto */, true /* update completions display */); + + // If the completer is a coroutine, nothing we can do here + if (!s.completions_valid) + return; } var c = s.completions; @@ -315,10 +356,12 @@ function minibuffer_complete(window, count) var e = s.completions_display_element; var new_index = -1; - if (count == 1 && c.apply_common_prefix) + let common_prefix; + + if (count == 1 && !s.applied_common_prefix && (common_prefix = c.common_prefix_input_state)) { - c.apply_common_prefix(m); - c.apply_common_prefix = null; + m.set_input_state(common_prefix); + s.applied_common_prefix = true; } else if (!just_completed_manually) { if (e.currentIndex != -1) { @@ -354,7 +397,7 @@ function exit_minibuffer(window) if (s.completer && s.match_required) { if (!s.completions_valid || s.completions === undefined) - s.update_completions(false); + s.update_completions(false /* not conservative */, false /* don't update */); let c = s.completions; let i = s.selected_completion_index; diff --git a/modules/minibuffer.js b/modules/minibuffer.js index 7a79d92..fdedf43 100644 --- a/modules/minibuffer.js +++ b/modules/minibuffer.js @@ -30,9 +30,8 @@ define_builtin_commands( m.ignore_input_events = false; } var s = m.current_state; - let x = s.ran_minibuffer_command; - if (x) - x(command); + if (s.ran_minibuffer_command) + s.ran_minibuffer_command(command); } } catch (e) { @@ -179,6 +178,11 @@ minibuffer.prototype = { get prompt () { return this.input_prompt_element.value; }, set prompt (s) { this.input_prompt_element.value = s; }, + set_input_state : function(x) { + this._input_text = x[0]; + this._set_selection(x[1], x[2]); + }, + _set_selection : function (start, end) { if (start == null) start = this._input_text.length; diff --git a/modules/search-engine.js b/modules/search-engine.js index b3f4100..cf35bce 100644 --- a/modules/search-engine.js +++ b/modules/search-engine.js @@ -153,6 +153,10 @@ function parse_search_engine_from_dom_node(node) { return eng; } +search_engine.prototype.supports_response_type = function (type) { + return this.urls.contains(type); +}; + /** * Returns null if the result mime_type isn't supported. The string * search_terms will be escaped by this function. @@ -199,15 +203,89 @@ search_engine.prototype.get_query_load_spec = function search_engine__get_query_ url_string += "&"; url_string += data; } - return load_spec({uri: uri_string}); + return load_spec({uri: url_string}); } else { - var string_stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream); - string_stream.data = data; - return load_spec({uri: uri_string, raw_post_data: data, + return load_spec({uri: url_string, raw_post_data: data, request_mime_type: "application/x-www-form-urlencoded"}); } } +search_engine.prototype.__defineGetter__("completer", function () { + const response_type_json = "application/x-suggestions+json"; + const response_type_xml = "application/x-suggestions+xml"; + + var eng = this; + if (this.supports_response_type(response_type_xml)) { + return function (input, pos, conservative) { + if (pos == 0 && conservative) + yield co_return(undefined); + let str = input.substring(0,pos); + try { + let lspec = eng.get_query_load_spec(str, response_type_xml, + $override_mime_type = "application/xml"); + let result = yield send_http_request(lspec); + let doc = result.responseXML; + let data = []; + if (doc) { + let elems = doc.getElementsByTagName("CompleteSuggestion"); + for (let i = 0; i < elems.length; ++i) { + let node = elems[i]; + let name = node.firstChild.getAttribute("data"); + let desc = node.lastChild.getAttribute("int"); + if (name && desc) + data.push([name,desc]); + } + delete doc; + delete elem; + delete result; + delete lspec; + let c = { count: data.length, + get_string: function (i) data[i][0], + get_description: function (i) data[i][1] + " results", + get_input_state: function (i) [data[i][0]] + }; + yield co_return(c); + } + } catch (e) { + yield co_return(null); + } + }; + } else if (this.supports_response_type(response_type_json)) { + return function (input, pos, conservative) { + if (pos == 0 && conservative) + yield co_return(undefined); + let str = input.substring(0,pos); + try { + let lspec = eng.get_query_load_spec(str, response_type_json); + let result = yield send_http_request(lspec); + let data = JSON.decode(result.responseText); + delete result; + delete lspec; + + if (!(data instanceof Array && + data.length >= 2 && + typeof(data[0]) == "string" && + data[0] == str && + data[1] instanceof Array && + (data[2] == null || (data[2] instanceof Array)))) + yield co_return(null); + if (data[2].length != data[1].length) + data[2] = null; + let c = { count: data[1].length, + get_string: function (i) String(data[1][i]), + get_description: (data[2] != null) && (function (i) String(data[2][i])), + get_input_state: function (i) [String(data[1][i])] + }; + yield co_return(c); + } catch (e) { + yield co_return(null); + } + }; + } else { + return null; + } +}); + // Load search engines from default directories { let dir = file_locator.get("CurProcD", Ci.nsIFile); @@ -220,3 +298,26 @@ search_engine.prototype.get_query_load_spec = function search_engine__get_query_ if (dir.exists() && dir.isDirectory()) load_search_engines_in_directory(dir); } + +function define_search_engine_webjump(search_engine_name, key) { + var eng = search_engines.get(search_engine_name); + + if (key == null) + key = search_engine_name; + + define_webjump(key, + function (arg) { + return eng.get_query_load_spec(arg); + }, + $description = eng.description, + $completer = eng.completer); +} + +define_search_engine_webjump("google.xml", "google"); +define_search_engine_webjump("mozilla-bugzilla.xml", "bugzilla"); +define_search_engine_webjump("amazondotcom.xml", "amazon"); +define_search_engine_webjump("wikipedia.xml", "wikipedia"); +define_search_engine_webjump("answers.xml", "answers"); +define_search_engine_webjump("yahoo.xml", "yahoo"); +define_search_engine_webjump("creativecommons.xml", "creativecommons"); +define_search_engine_webjump("eBay.xml", "ebay"); diff --git a/modules/webjump.js b/modules/webjump.js index 16128ea..c60ab67 100644 --- a/modules/webjump.js +++ b/modules/webjump.js @@ -1,12 +1,34 @@ //// web jump stuff -var webjumps = {}; -function add_webjump(key, loc) -{ - webjumps[key] = loc; +var webjumps = new string_hashmap(); + +define_keywords("$completer", "$description", "$no_argument"); +function define_webjump(key, handler) { + keywords(arguments); + + if (typeof(handler) == "string") { + let template = handler; + handler = function (arg) { + var b = template.indexOf('%s'); + var a = b + 2; + // Just return the same string if it doesn't contain a %s + if (b == -1) + return template; + else + return template.substr(0,b) + encodeURIComponent(arg) + template.substring(a); + }; + } + webjumps.put(key, + {key: key, + handler: handler, completer: arguments.$completer, + description: arguments.$description, + no_argument: arguments.$no_argument}); } +// Compatibility +var add_webjump = define_webjump; + function add_delicious_webjumps (username) { add_webjump("delicious", " http://del.icio.us/" + username); @@ -15,22 +37,20 @@ function add_delicious_webjumps (username) add_webjump("sadelicious", " http://del.icio.us/search/all?search=%s"); } -function webjumps_clear() +function clear_webjumps() { webjumps = {}; } // Some built in web jumps -function webjumps_add_defaults() +function define_default_webjumps() { add_webjump("conkerorwiki", "http://conkeror.org/?action=fullsearch&context=60&value=%s&fullsearch=Text"); - add_webjump("google", "http://www.google.com/search?q=%s"); add_webjump("lucky", "http://www.google.com/search?q=%s&btnI=I'm Feeling Lucky"); add_webjump("maps", "http://maps.google.com/?q=%s"); add_webjump("scholar", "http://scholar.google.com/scholar?q=%s"); add_webjump("clusty", "http://www.clusty.com/search?query=%s"); - add_webjump("wikipedia", "http://en.wikipedia.org/wiki/Special:Search?search=%s"); add_webjump("slang", "http://www.urbandictionary.com/define.php?term=%s"); add_webjump("dictionary", "http://dictionary.reference.com/search?q=%s"); add_webjump("xulplanet", "http://www.google.com/custom?q=%s&cof=S%3A"+ @@ -39,7 +59,6 @@ function webjumps_add_defaults() "xulplanet.png%3BALC%3Ablue%3BLW%3A215%3BAWFID%3A0979f384d5"+ "181409%3B&domains=xulplanet.com&sitesearch=xulplanet.com&sa=Go"); add_webjump("image", "http://images.google.com/images?q=%s"); - add_webjump("bugzilla", "https://bugzilla.mozilla.org/show_bug.cgi?id=%s"); add_webjump("clhs", "http://www.xach.com/clhs?q=%s"); add_webjump("emacswiki", "http://www.emacswiki.org/cgi-bin/wiki?search=%s"); add_webjump("cliki", "http://www.cliki.net/admin/search?words=%s"); @@ -53,60 +72,87 @@ function webjumps_add_defaults() add_webjump("sheldonbrown", "http://www.google.com/search?q=site:sheldonbrown.com %s"); } -function webjump_build_url(template, subs) -{ - var b = template.indexOf('%s'); - var a = b + 2; - // Just return the same string if it doesn't contain a %s - if (b == -1) - return template; - else - return template.substr(0,b) + encodeURIComponent(subs) + template.substring(a); -} +function match_webjump(str) { + var sp = str.indexOf(' '); -function get_partial_match(hash, part) -{ - var matches = []; - for (x in hash) { - if (part == x.substr(0, part.length)) - matches.push(x); + var key, arg; + if (sp == -1) { + key = str; + arg = null; + } else { + key = str.substring(0, sp); + arg = str.substring(sp + 1); } - if (matches.length == 1) - return matches[0]; - else - return null; + + // Look for an exact match + var match = webjumps.get(key); + + // Look for a partial match + if (!match) { + for (let [k,v] in webjumps.iterator()) { + if (k.substring(0, key.length) == key) { + if (match) { + // key is not a unique prefix, as there are multiple partial matches + return null; + } + match = v; + } + } + } + + if (match) { + if (!arg && !match.no_argument) { + // This webjump requires an argument, but none was given + return null; + } + return [match, key, arg]; + } + return null; } + function getWebJump(value) { - try { - var start = value.indexOf(' '); - var jump; - if (start == -1) - jump = webjumps[value]; - else - jump = webjumps[value.substr(0,start)]; - // Try to find a web jump match - if (!jump) { - var match = get_partial_match(webjumps, value.substr(0,start)); - if (match) - jump = webjumps[match]; - else - return null; - } - return webjump_build_url(jump, value.substring(start + 1)); - } catch(e) {/* FIXME: figure out why we need this */ dump_error(e); return null;} + var res = match_webjump(value); + if (!res) + return null; + let [match,key,arg] = res; + return match.handler(arg); } function get_url_or_webjump(input) { var url = getWebJump(input); - if (url) { + if (url != null) { return url; } else { return input; } } -webjumps_add_defaults (); +define_default_webjumps(); + +function webjump_completer() +{ + let base_completer = prefix_completer( + $completions = [ v for ([k,v] in webjumps.iterator()) ], + $get_string = function (x) x.key + (x.no_argument ? "" : " "), + $get_description = function (x) x.description || ""); + + return function(input, pos, conservative) { + let str = input.substring(0,pos); + let res = match_webjump(str); + if (res) { + let [match, key, arg] = res; + if (arg != null) { // If there is no argument yet, we use the base completer + if (match.completer) { + let c = yield match.completer.call(null, arg, pos - key.length - 1, conservative); + yield co_return(nest_completions(c, match.key + " ")); + } + yield co_return(null); + } + } + yield co_return(base_completer(input, pos, conservative)); + } +} diff --git a/search-engines/amazondotcom.xml b/search-engines/amazondotcom.xml new file mode 100644 index 0000000..b5e42dd --- /dev/null +++ b/search-engines/amazondotcom.xml @@ -0,0 +1,13 @@ + +Amazon.com +Amazon.com Search +ISO-8859-1 +data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHgSURBVHjalFM9TNtQEP4cB7PwM1RITUXIgsRaYEEVEyKZwhiyZAQyd0BhpFOlIjoBqhjSqVQMoVMLLAjEwECCQJkSkBqJYDOAFOMKFSf28d7DTUxiUDnp/Pzeu/vuu7t3ICKF6SLTMv2/lB0fRWKfjwDm4JJisYh0Oo3fpZLYT0SjSCQS8JAFMADNDZ3NZsnf1taiqVTKi4nGASruk5lkkmTmMB6JUKFQqO+DfX1eABWeQoVR6f7HSdM0obqu48Yw8G1tDT82NsRd1TSbU9BbGPCog8PDj+jLzurFoAVgMh4XxoNDQ6SqKi0tL9eBvAB8zZwymYxYY7EYAoEA8vm82BNTg6XUIs0MeGTZoR1mhXSnwNl4pmAbjU7mcjkKhkL1ynMnntZ4OEw3VyrV8utk7s5TdW++0QXz+1i3P7IK36t+PCfVn1OQOoOA0gXr5DPak+cPXbBK+/T3S69AtY3LJ98vZ1or/iLr+pTuvr59/A6s003UdqZFJF/PCKQ3o5CUznoBST2AfbEF/9iqYEDaIfwj73VJPEfgNTe0tWNYR0uwy9uOW0OkrgHI7z5ADo2C7v48nLV3XHKAT+x/1m1sX58xsBxg8rZJrDYD8DHHp4aJj/MK09sXjPOt46PcCzAACXY8/u34wN0AAAAASUVORK5CYII= + + + + + + +http://www.amazon.com/ + diff --git a/search-engines/answers.xml b/search-engines/answers.xml new file mode 100644 index 0000000..a2a139b --- /dev/null +++ b/search-engines/answers.xml @@ -0,0 +1,13 @@ + +Answers.com +Dictionary Search on Answers.com +UTF-8 +data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAABMLAAATCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////K////4f////E////5f///+n////P////mv///0EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8E////fv///+//////////////////////7NnP/+LFtv/////+////of///xYAAAAAAAAAAAAAAAD///8D////lf////////////j0//bi1v/OlXf/tGU9/6FCEv/OmH3////////////////D////FgAAAAAAAAAA////avPm4P/evaz/8NbI//7r3//23M3/xYRi/5kzAP/Df1z//u/l//749P/v4dn/+PPw/////6j///8B////GP///+W/f1//smM7//bczf/+69///uvf/9ytlP+ZMwD/5se3/+/f1//AgmP/nj0N/927qv/////+////QP///2z/////8NvQ/8WCYP/+69///uvf//7r3/+7ckz/pUkb/9m1ov+ePQ3/okUW/8+fh//38O3//////////5r///+t//////7y6v/Cflv/58Cr//DRwP/mwKv/okQU/8ODYv/cuqj/yZN4//Tq5f/+9e///vDn///////////Q////yf/////+7+b/05yA/65ZLv+9dVD/sF40/5kzAP/kvKb//vTu//Tr5v/7+Pb//vfz//707f//////////6f///8X//////vDm/+K4ov/KjGz//ure/8uNbf+jRBX/+OTX/+3b0v+jSBr/pk0h/717Wv/Wrpr//Pn4/////+b///+i//////7z7f/02Mj/wn5b//vl2P+uWS7/vXhU//v49//48u//1q6a/717Wv+oUSb/tWxH//jz8P/////K////V///////+/j//ure/8aFZP/fs5v/oEAQ/9q1o/+zaEL/1ayX//718P/+9/P/+PHu//jz8P//////////h////wr////O///////38v/YpYr/tGQ7/6ZLHf/06eX/s2dB/549Df/x49z//vDn//7x6f//////////8////yoAAAAA////R/////v/////7dXI/5kzAP+7cUv//vHp/+vYzv+bNwX/vHlY//38/P///////////////30AAAAAAAAAAAAAAAD///9n////+/z5+P++e1n/3LGc//7w5//++PT/0KKL/8OIa//9/Pv//////////5X///8GAAAAAAAAAAAAAAAAAAAAAP///0n////K///////////////////////////+/v7/////5v///2z///8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////Cv///1f///+g////xP///8n///+r////bP///xoAAAAAAAAAAAAAAAAAAAAA+B////AH///AA///wAH//4AB//+AAP//AAD//wAA//8AAP//AAD//4AA//+AAf//wAP//+AD///wD////D///w== + + + + + +http://www.answers.com/ + diff --git a/search-engines/creativecommons.xml b/search-engines/creativecommons.xml new file mode 100644 index 0000000..7baf3b0 --- /dev/null +++ b/search-engines/creativecommons.xml @@ -0,0 +1,11 @@ + +Creative Commons +Find photos, movies, music, and text to rip, sample, mash, and share. +utf-8 +data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAJUSURBVDiNjZO9S1thGMXPvTfJFbnkipNkLLS0ksFg0M0lf4CboNCEgIIg/RiKtEOn0qGWTtbVoBYcIji10I9J0ApWCjp0kRaXdhHjTW4+uGnur4NJ8GOwZ3nf4TnnfZ5z3scAdBGGYdyVdN+yrGHTNNOtVqsVhuG+pO+S3gE/LtV3BIxzPDJNc8FxHGN0dNRKpVIGoJ2dndr+/r5Vr9cl6bmkN0AoSQIEyHXdj5KYnZ3F932uolKpkM/nK5KQ9FmSCZwLOI7zQBLr6+vXiFdRLBaDtsiTTve3YrFYkM/nbyR3MDU1dSKpLumO+vr6Xruui+d5AFSrVVZWVtjY2KDRaABwdHTE4uIie3t7AJTLZaLRaFXSCyUSid1MJgOA53n09/eTTqdJJpPMzc2xurqKbduMj48Tj8fZ3d0FYHBw8FjSezmOU56fnwdgeXkZ27ap1WpUKhWazSZjY2Nks1kASqVSd4zp6eljSX/MtiHdRDpnEATyfb+bkiSVSqXu3TCM8xgHBga+dkY4OzvDdV2GhoZIJBLMzMxQKBSIRqNkMhlisRhbW1sAJJPJn5I+KB6Pv7poou/7rK2tsbm5SRAEXROXlpY4ODgAoFarYdu2J+llN8ZcLvffMeZyud+SGpLuCVBPT89jSRQKhRvJxWKxISmU9JTOT5Rk9Pb2fpHE5OQkJycn14inp6dMTEx4bdM/SbKAy8sk6WEkElmwLCuSSqUYGRmxgHB7e7t+eHgYazabgaRnkt7SeZnr63xbUtYwjGHTNNNhGP4F9iR9a6/zr4v1/wDE1D9XlC4rrAAAAABJRU5ErkJggg== + + + + +http://search.creativecommons.org/ + diff --git a/search-engines/eBay.xml b/search-engines/eBay.xml new file mode 100644 index 0000000..1612e30 --- /dev/null +++ b/search-engines/eBay.xml @@ -0,0 +1,17 @@ + +eBay +eBay - Online actions +ISO-8859-1 +data:image/x-icon;base64,AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAADAAAAA/wAAAABAAABAQAAAgEAAAMBAAAD/QAAAAIAAAECAAACAgAAAwIAAAP+AAAAAwAAAQMAAAIDAAADAwAAA/8AAAAD/AABA/wAAgP8AAMD/AAD//wAAAABAAEAAQACAAEAAwABAAP8AQAAAQEAAQEBAAIBAQADAQEAA/0BAAACAQABAgEAAgIBAAMCAQAD/gEAAAMBAAEDAQACAwEAAwMBAAP/AQAAA/0AAQP9AAID/QADA/0AA//9AAAAAgABAAIAAgACAAMAAgAD/AIAAAECAAEBAgACAQIAAwECAAP9AgAAAgIAAQICAAICAgADAgIAA/4CAAADAgABAwIAAgMCAAMDAgAD/wIAAAP+AAED/gACA/4AAwP+AAP//gAAAAMAAQADAAIAAwADAAMAA/wDAAABAwABAQMAAgEDAAMBAwAD/QMAAAIDAAECAwACAgMAAwIDAAP+AwAAAwMAAQMDAAIDAwADAwMAA/8DAAAD/wABA/8AAgP/AAMD/wAD//8AAAAD/AEAA/wCAAP8AwAD/AP8A/wAAQP8AQED/AIBA/wDAQP8A/0D/AACA/wBAgP8AgID/AMCA/wD/gP8AAMD/AEDA/wCAwP8AwMD/AP/A/wAA//8AQP//AID//wDA//8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8fHx8fHx8fHx8fHx8AAB8cGRkUFAcHBx8fBUKfAAAfFBkfHxNHF4cb29vCnwAAHxkZFBQUBx8HG98bwp8fAB8ZGR8UGQcXhxvb28KFXx8fHZkZGRNHBwcfG8jCgoQfAB8fHx8HBx8b29vCnwPCnwAAAB8fBwcfHx8EBB8Dwp8AAAAAHx8fHwAfHx8AHx8fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD//wAA//8AAP//AACAAwAAAAMAAAADAAAAAQAAAAAAAAAAAACAAAAA4AAAAPCIAAD//wAA//8AAP//AAA= + + + + + + + + + + +http://search.ebay.com/ + diff --git a/search-engines/google.xml b/search-engines/google.xml new file mode 100644 index 0000000..cb2d782 --- /dev/null +++ b/search-engines/google.xml @@ -0,0 +1,15 @@ + +Google +Google Search +UTF-8 +data:image/x-icon;base64,R0lGODlhEAAQAPfLAAATVikwdA8SnxUfgAsWpAAilholjxw4jBc7kwAlvQQ2sRMsoBUqqhMzuhY/vxw4tSgmiyM1mSUztiQ6sTE3sQ4qyxMxxRoyxiAuxR1CtBxJsBxasSJuuTFguBte0Rlf2xVc9h9W9xVjzxVr0gdj6BRh4R1o5yBcyiZbyydT1i9b2Ddb1iFY6CJg2Vpor1dzvEJu20Z0yi23QDy1REi2OUy0O1WzOVC4PU+tVUe5Sk2xQU2zRUO4UE21Ula2SmKEqWWF2HyPx2+a6X6e6Xqk1m+s78sUDs4UGdEQB9YfDdwaANEfHd0YEscjAM4mAM0qANIoD9IkGdslGswuItYgL4aP0ImP2YGZ36Opzaq2wq/S+rzX/7/e8MrS1MLO/sTb48rT8snX/83c89PZ+crq+cH1/9Dl/9Ln/93r/9fy/+Hf7P/42eDm/O7u/+T29uX2/eT2/+f4/+f5/+j/9u//8+3/9u7/9ur5/+j//+n//+v//u3//+7//e7//+////b66/T/6vX/6/f/7f/07fj/4fv/4Pj/5v/45v7/4/r+7/3/6fDw+Pfx//D/9/X/8fT/8/f/8ff/8/D///H///L8/fL///P///X7//b6/ff/+/T///b9//f///v19//w9v/09P/29v/x+f/y///z///1+v/1///2///3//j79P/58/z/8/z99/z/9v7/9P7/9vn7//v6//j9//n9//j///n///v//vv////4+v/5+//6+P/4///6/P/6/v/6///7///9+P/8+v/9+v7/+Pz////8/f/9/f79///8///9//7//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAMsALAAAAAAQABAAAAj/AEn4oIFjBw8bOnrMuJGjhowZM1T8UdYJUZ5ZcNRYWjSrVK5QU0DMmtUnzRAXEy4o6FCEy6NDTkQIq1MmRgM0eZTlCXMgQJtRSE4gmgUkwh1EiZTNUiamy6NUUExcuoJgDCdDjQg9KgVL2SNFT1hwEvKglLBWuixZ+jSrlSBdRlL04bBBkTBdpZTpIqWsFaBcTEr0QaEhl6dWlswKW6poDRUPlmAUQKWMkTJLc76QMQNGUZMWgIgkCFJnlq5WXigwkFClVZQQyuRgELAlk7JBymCZGYAF0ZEPrQixgUDAihxVdPpoAZAFUZIRfThxgvPCwAILDipk+OFG2ZIVoxApERtPfvwlvZ+kQFzPvv0MJQEBADs= + + + + + + + + +http://www.google.com/firefox + diff --git a/search-engines/mozilla-bugzilla.xml b/search-engines/mozilla-bugzilla.xml new file mode 100644 index 0000000..da6bd79 --- /dev/null +++ b/search-engines/mozilla-bugzilla.xml @@ -0,0 +1,8 @@ + + +Bugzilla@Mozilla +Bugzilla@Mozilla Quick Search +UTF-8 +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAABGdBTUEAAK%2FINwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz%2F%2Fz8DJQAggJiQOe%2Ffv2fv7Oz8rays%2FN%2BVkfG%2FiYnJfyD%2F1%2BrVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw%2F8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi%2FG%2BQKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo%2BMXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia%2BCuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq%2FvLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg%2FkdypqCg4H8lUIACnQ%2FSOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD%2BaDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg%3D%3D + + \ No newline at end of file diff --git a/search-engines/wikipedia.xml b/search-engines/wikipedia.xml new file mode 100644 index 0000000..36b8ed4 --- /dev/null +++ b/search-engines/wikipedia.xml @@ -0,0 +1,15 @@ + +Wikipedia (en) +Wikipedia, the free encyclopedia +UTF-8 +data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAEAgQAhIOEAMjHyABIR0gA6ejpAGlqaQCpqKkAKCgoAPz9%2FAAZGBkAmJiYANjZ2ABXWFcAent6ALm6uQA8OjwAiIiIiIiIiIiIiI4oiL6IiIiIgzuIV4iIiIhndo53KIiIiB%2FWvXoYiIiIfEZfWBSIiIEGi%2FfoqoiIgzuL84i9iIjpGIoMiEHoiMkos3FojmiLlUipYliEWIF%2BiDe0GoRa7D6GPbjcu1yIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + + + + + + + + +http://en.wikipedia.org/wiki/Special:Search + diff --git a/search-engines/yahoo.xml b/search-engines/yahoo.xml new file mode 100644 index 0000000..94ac633 --- /dev/null +++ b/search-engines/yahoo.xml @@ -0,0 +1,14 @@ + +Yahoo +Yahoo Search +UTF-8 +data:image/x-icon;base64,R0lGODlhEAAQAJECAP8AAAAAAP///wAAACH5BAEAAAIALAAAAAAQABAAAAIplI+py+0NogQuyBDEnEd2kHkfFWUamEzmpZSfmaIHPHrRguUm/fT+UwAAOw== + + + + + + +http://search.yahoo.com/ + -- 2.11.4.GIT