Logo Search packages:      
Sourcecode: ubufox version File versions

plugin-finder.py

#!/usr/bin/python
#
# Copyright (C) 2007-2008  Canonical Ltd.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

import httplib

from cStringIO import StringIO
from mod_python import apache
from pysqlite2 import dbapi2 as sqlite
from xml.dom.xmlbuilder import *
from xml.dom.minidom import *
import os
import time
import thread
import threading
import sys
import plugindata

# TestURL: http://localhost/~asac/cgi-bin/PluginFinderService.php?mimetype=%PLUGIN_MIMETYPE%&appID=%APP_ID%&appVersion=%APP_VERSION%&clientOS=%CLIENT_OS%&chromeLocale=%CHROME_LOCALE%

counter=0
docroot=""
CACHE_TIME_SEC=3600
DB_DIR="/home/asac/pfsdb/"
ENABLE_MOZILLA_PFS_RESULTS=None

arch_map=dict()
cache_con_map=dict()

arch_map['x86_64']="amd64"
arch_map['i686']="i386"

def connect_db(docroot):
      apt_con = sqlite.connect(DB_DIR+"apt-plugins.sqlite")
      return apt_con

def get_db(req):
      apt_con = connect_db(req.document_root())
      return apt_con

def retrieve_proxied_result(req):
      builder = DOMBuilder()
      result_doc = None
      if ENABLE_MOZILLA_PFS_RESULTS:
            hc = httplib.HTTPSConnection("pfs.mozilla.org")
            hc.request("GET", "/plugins/PluginFinderService.php?" + req.args)
            res = hc.getresponse()
            source = DOMInputSource()
            source.byteStream = StringIO(res.read())
            result_doc = builder.parse(source)
      else:
            result_doc = Document()
            root = result_doc.createElement("RDF:RDF")
            root.setAttribute("xmlns:RDF", "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
            root.setAttribute("xmlns:pfs", "http://www.mozilla.org/2004/pfs-rdf#")
            result_doc.appendChild(root)

      return result_doc


def parse_http_parameters (req):
      parameters = dict()
      for parameterblock in req.args.split("&"):
            keyvaluepair = parameterblock.split("=")
            if len(keyvaluepair) < 2:
                  continue
            parameters[url_unquote(keyvaluepair[0])] = url_unquote(keyvaluepair[1])
      return parameters


def retrieve_filehint_name_map(req, parameters):
      res = ""
      apt_con = get_db(req)
      
        distribution = "7.10"
        if parameters.has_key('distributionID') and parameters['distributionID'] is not None:
            distribution = parameters['distributionID']
      cur = apt_con.cursor()
      cur.execute("SELECT distinct filehint, name FROM package " \
                  + "WHERE filehint!=\"\"") 
      for row in cur:
            res = res + "filehint: ";
            res = res + row[0];
            res = res + "\n";
            res = res + "name: ";
            res = res + row[1];
            res = res + "\n";
      return res

def retrieve_descriptions(req, parameters):
      ret = []
      apt_con = get_db(req)

      mimetype = parameters['mimetype']
      architecture = None
      if not parameters['clientOS'] is None:
            tmp = parameters['clientOS'].split(" ")
            architecture = arch_map[tmp[1]]
            if architecture is None:
                  architecture = tmp[1]
      else:
            return ret # nothing to do for no arch

        distribution = "7.10"
        if parameters.has_key('distributionID') and parameters['distributionID'] is not None:
            distribution = parameters['distributionID']

      appid = parameters['appID']

      cur = apt_con.cursor()
      cur.execute("SELECT name, mimetype, pkgname, description, section, filehint FROM package " \
                  + "WHERE mimetype=? AND architecture=? AND appid=? " \
                  + "AND distribution=? order by package.weight desc", (mimetype, architecture, appid, distribution))
      for row in cur:
            desc = plugindata.PluginDescription (           \
                        row[0],     \
                        row[1],     \
                        None,             \
                        None,       \
                        None,       \
                        "apt:" + row[2] + "?section=" + row[4],   \
                        None, \
                        None, \
                        None,       \
                        "false", \
                        row [5], \
                        row [3] )
            ret.append(desc)

      cur.close()

      return ret        

def retrieve_ubuntu_results(req, http_parameters):
      description_results = []
      description_results = retrieve_descriptions(req, http_parameters)
      return description_results

def url_unquote(s):
      res = s.split('%')
      for i in xrange(1, len(res)):
            item = res[i]
            try:
                  res[i] = unichr(int(item[:2], 16)) + item[2:]
            except KeyError:
                  res[i] = '%' + item
            except ValueError:
                  res[i] = '%' + item

      return "".join(res)

def get_cache_con():
      if not cache_con_map.has_key(threading._get_ident()):
            cache_con = sqlite.connect(":memory:")
            cur = cache_con.cursor()
            cur.execute("create table plugin_result_cache(url string, timestamp long, content string)")
            cur.close()
            cache_con_map[threading._get_ident()] = cache_con
      con = cache_con_map[threading._get_ident()]
      return con

def inject_ubuntu_descriptions_in_upstream_result (resxml, ubuntu_descriptions, mimetype):
      result_list = None

      node = resxml.documentElement.firstChild
      seq_r = None
      while not node is None:
            nextNode = node.nextSibling
            if node.nodeType == node.ELEMENT_NODE:
                  about = node.getAttribute("about")
                  if not about is None and about.rfind("urn:mozilla:plugin-results:") == 0:
                        item = node.getElementsByTagName("RDF:Seq").item(0)
                        seq_r = item
                        result_list = node
                        break
            node = nextNode

      if not result_list:
            result_list = resxml.createElement("RDF:Description")

      if seq_r is None:
            result_list.setAttribute("about", "urn:mozilla:plugin-results:"+mimetype)
            pluginsElement = resxml.createElement("pfs:plugins")
            result_list.appendChild(pluginsElement)
            seq_r = resxml.createElement("RDF:Seq")
            pluginsElement.appendChild(seq_r)
            resxml.documentElement.appendChild(result_list)

      for description in ubuntu_descriptions:
            result_list.setAttribute("about", "urn:mozilla:plugin-results:"+description.requestedMimetype)
            update_list = resxml.createElement("RDF:Description")
            update_list.setAttribute("about", "urn:mozilla:plugin:"+ description.guid)
            resxml.documentElement.appendChild(update_list)
            updatesElement = resxml.createElement("pfs:updates")
            update_list.appendChild(updatesElement)
            seq_u = resxml.createElement("RDF:Seq")
            updatesElement.appendChild(seq_u)

            main_element = description.to_element(resxml)
            resxml.documentElement.appendChild(main_element);
            li_r = resxml.createElement("RDF:li")
            li_u = resxml.createElement("RDF:li")
            li_r.setAttribute("resource", "urn:mozilla:plugin:" + description.guid)
            li_u.setAttribute("resource", description.id)
            seq_r.appendChild(li_r)
            seq_u.appendChild(li_u)

      node = seq_r.lastChild
      while not node is None:
            nextNode = node.previousSibling
            if node.nodeType == node.ELEMENT_NODE and node.getAttribute("resource") == "urn:mozilla:plugin:-1":
                  seq_r.removeChild(node)
            
            node = nextNode



def get_cached_and_cache(req, http_params):
      global counter
      counter= (counter + 1) % 2
      req.content_type = 'text/xml'

      if counter == 0:
            now = int(time.time() * 1000)
            low_time = now - CACHE_TIME_SEC * 1000
            cur = get_cache_con().cursor()
            cur.execute("delete from plugin_result_cache where timestamp <= ?", (low_time,))
            cur.close()

      key = req.args
      found = False
      result = None
      cur = get_cache_con().cursor()
      cur.execute("select timestamp, content from plugin_result_cache where url = ?", (key,))
      for row in cur:
            found = True
            result = row[1]

      cur.close()

      if found:
            print "found!"
            return result

      resxml = retrieve_proxied_result(req)
      ubuntu_descriptions = retrieve_ubuntu_results(req, http_params)

      inject_ubuntu_descriptions_in_upstream_result(resxml, ubuntu_descriptions, http_params['mimetype'])

      result_string = resxml.toxml()

      now = int(time.time() * 1000)
      cur = get_cache_con().cursor()
      cur.execute("insert into plugin_result_cache (timestamp, url, content) values (?, ?, ?)", (now, key, result_string))
      return result_string

def get_filehint_and_name(req, http_params):
      req.content_type = 'text/plain'
      res = retrieve_filehint_name_map( req, http_params)
      return res

apt_con_lock = thread.allocate_lock()
apt_plugin_db_updater=None
error_txt=""

def handler(req):
      global apt_plugin_db_updater
      pfsdbdir =  req.document_root() + "/pfsdb/"
      http_params = parse_http_parameters(req)
      op = None
      if http_params.has_key('op'):
            op = http_params['op']

      if op == "filehint2name":
            res = get_filehint_and_name (req, http_params)
      else: 
            res = get_cached_and_cache(req, http_params)
      req.write(res)
      return apache.OK


Generated by  Doxygen 1.6.0   Back to index