[kupfer] google: Use OpenSearch search engines



commit 9e0cec0226d3b997f09f00822494a658c22cabb7
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date:   Mon Aug 24 22:54:47 2009 +0200

    google: Use OpenSearch search engines
    
    This plugin is the Web search plugin, not the google plugin. It can
    now use firefox' OpenSearch search engines as was intended.

 kupfer/plugin/google.py |  109 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 103 insertions(+), 6 deletions(-)
---
diff --git a/kupfer/plugin/google.py b/kupfer/plugin/google.py
index 261f9b2..e716501 100644
--- a/kupfer/plugin/google.py
+++ b/kupfer/plugin/google.py
@@ -1,18 +1,34 @@
-import gobject
+import os
+import urllib
+import xml.sax
 
-from kupfer.objects import Action, Source
+from kupfer.objects import Action, Source, Leaf
 from kupfer.objects import TextLeaf
-from kupfer import utils
+from kupfer import utils, config
 
+from kupfer.plugin import firefox_support, xml_support
 
 __kupfer_name__ = _("Search the Web")
-__kupfer_sources__ = ()
+__kupfer_sources__ = ("OpenSearchSource", )
 __kupfer_text_sources__ = ()
-__kupfer_actions__ = ("GoogleSearch", )
-__description__ = _("Send search queries to Google")
+__kupfer_actions__ = (
+		"GoogleSearch",
+		"SearchWithEngine",
+	)
+__description__ = _("Search the web with OpenSearch search engines")
 __version__ = ""
 __author__ = "Ulrik Sverdrup <ulrik sverdrup gmail com>"
 
+class OpenSearchHandler (xml_support.XMLEntryHandler):
+	def startElement(self, sName, attributes):
+		if sName in ("Url", "os:Url"):
+			if not attributes["type"] == "text/html":
+				return
+			self.element_content = attributes["template"]
+			self.is_wanted_element = True
+		else:
+			xml_support.XMLEntryHandler.startElement(self, sName, attributes)
+
 class GoogleSearch (Action):
 	def __init__(self):
 		Action.__init__(self, _("Search with Google"))
@@ -30,3 +46,84 @@ class GoogleSearch (Action):
 	def item_types(self):
 		yield TextLeaf
 
+def _urlencode(word):
+	"""Urlencode a single string of bytes @word"""
+	return urllib.urlencode({"q": word})[2:]
+
+def _do_search_engine(terms, search_url, encoding="UTF-8"):
+	search_url = search_url.encode(encoding, "strict")
+	terms_enc = terms.encode(encoding, "ignore")
+	query_url = search_url.replace("{searchTerms}", _urlencode(terms_enc))
+	utils.show_url(query_url)
+
+class SearchWithEngine (Action):
+	def __init__(self):
+		Action.__init__(self, _("Search with..."))
+
+	def activate(self, leaf, iobj):
+		coding = iobj.object.get("InputEncoding")
+		url = iobj.object["Url"]
+		_do_search_engine(leaf.object, url, encoding=coding)
+		# will encode search=text, where `text` is escaped
+		#query_url = search_url + urlencode({"q": leaf.object, "ie": "utf-8"})
+		#utils.show_url(query_url)
+
+	def item_types(self):
+		yield TextLeaf
+
+	def requires_object(self):
+		return True
+	def object_types(self):
+		yield SearchEngine
+
+	def get_description(self):
+		return _("Search the web with OpenSearch search engines")
+	def get_icon_name(self):
+		return "gtk-find"
+
+class SearchEngine (Leaf):
+	def get_description(self):
+		desc = self.object.get("Url")
+		return desc if desc != unicode(self) else None
+
+class OpenSearchSource (Source):
+	def __init__(self):
+		Source.__init__(self, _("OpenSearch Search Engines"))
+
+	@classmethod
+	def _parse_opensearch(cls, filepaths):
+		searches = []
+		parser = xml.sax.make_parser()
+		simplekeys = ["Description", "Url", "ShortName", "InputEncoding"]
+		keys = simplekeys[:]
+		keys += ["os:" + k for k in simplekeys]
+		handler = OpenSearchHandler(searches, "SearchPlugin", {}, keys)
+		parser.setContentHandler(handler)
+		for filepath in filepaths:
+			parser.parse(filepath)
+
+		# normalize to unnamespaced values and sanitize
+		for s in searches:
+			for key, val in s.items():
+				skey = key.replace("os:", "", 1)
+				del s[key]
+				s[skey] = val.strip()
+
+		# remove those missing keys
+		searches = [s for s in searches if all((k in s) for k in simplekeys)]
+		return searches
+
+	def get_items(self):
+		plugin_dirs = []
+		home_plugins = firefox_support.get_firefox_home_file("searchplugins")
+		if home_plugins:
+			plugin_dirs.append(home_plugins)
+		# accept in kupfer data dirs
+		plugin_dirs.extend(config.get_data_dirs("searchplugins"))
+
+		for dirname, dirs, files in os.walk(home_plugins):
+			break
+		searches = self._parse_opensearch((os.path.join(dirname, f) for f in files))
+		for s in searches:
+			yield SearchEngine(s, s.get("ShortName"))
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]