hdlAPI.py :  » Network » Grail-Internet-Browser » grail-0.6 » protocols » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Grail Internet Browser 
Grail Internet Browser » grail 0.6 » protocols » hdlAPI.py
"""CNRI handle protocol extension.

This module glues the backend CNRI handle client resolution module in
hdllib.py to the Grail URI protocol API.  Currently we are only
interested in URL type handles, so we can get away semantically with
returning an HTTP-style relocation error to the browser for the
resolved handle (if the handle resolves to a single URL), or to
generating a piece of HTML which lets the user choose one (if it
resolves to multiple URLs).

XXX Remaining problems:

           Issuing a 302 relocate isn't the proper thing to do in the
           long term, because it forces the user back into URL space.
           So, for example, the user will naturally keep the resolved
           URL on her bookmarks, instead of the original handle.
           However, for backward compatibility with relative links, we
           need to define relative-handle semantics.  We're working
           with the CNRI handle group to define this and we'll be
           experimenting with solutions in the future.  This should be
           good enough for now.

           Handle resolution is done synchronously, thereby defeating
           the intended asynchronous API.  This should be fixed by
           adding an asynchronous interface to hdllib.py.

"""

import sys
import string
import urllib
import hdllib
import nullAPI
import grailutil


# We are currently only concerned with URL type handles.
HANDLE_TYPES = [hdllib.HDL_TYPE_URL]


# HTML boilerplate for response on handle with multiple URLs
HTML_HEADER = """<HTML>

<HEAD>
<TITLE>%(title)s</TITLE>
</HEAD>

<BODY>

<H1>%(title)s</H1>

%(error)s

The handle you have selected resolves to multiple data items or to an
unknown data type.<P>

Please select one from the following list:

<UL>
"""

HTML_TRAILER = """
</UL>

</BODY>

</HTML>
"""



def parse_handle(hdl):
    """Parse off options from handle.

    E.g. 'auth.subauth/path;type=url' will return
    ('auth.subauth.path', {'type': 'url'}).

    This also interprets % quoting in the non-option part.

    """
    hdl, attrs = urllib.splitattr(hdl)
    d = {}
    if attrs:
        for attr in attrs:
            i = string.find(attr, '=')
            if i < 0:
                key, value = attr, None
            else:
                key, value = attr[:i], urllib.unquote(attr[i+1:])
            d[string.lower(key)] = value
    return urllib.unquote(hdl), d

def escape(s):
    """Replace special characters '&', '<' and '>' by SGML entities."""
    # From cgi.py
    import regsub
    s = regsub.gsub("&", "&amp;", s)    # Must be done first!
    s = regsub.gsub("<", "&lt;", s)
    s = regsub.gsub(">", "&gt;", s)
    return s

class hdl_access(nullAPI.null_access):

    _types = HANDLE_TYPES

    try:
        #print "Fetching global hash table"
        _global_hashtable = hdllib.fetch_global_hash_table()
    except hdllib.Error, inst:
        raise IOError, inst, sys.exc_traceback

    _hashtable = _global_hashtable

    _local_hashtables = {}

    def get_local_hash_table(self, hdl):
        key = hdllib.get_authority(hdl)
        if not self._local_hashtables.has_key(key):
            #print "Fetching local hash table for", key
            self._local_hashtables[key] = hdllib.fetch_local_hash_table(
                key, self._global_hashtable)
        return self._local_hashtables[key]

    def __init__(self, hdl, method, params):
        self._msgattrs = {"title": "Ambiguous handle resolution",
                          "error": ""}
        nullAPI.null_access.__init__(self, hdl, method, params)

        self._hdl, self._attrs = parse_handle(hdl)
        self.app = grailutil.get_grailapp()

        if self._attrs.has_key('type'):
            t = string.lower(self._attrs['type'])
            mname = "hdl_type_" + t
            tname = string.upper(mname)
            try:
                m = self.app.get_loader('protocols').find_module(mname)
                if not m:
                    self._msgattrs["title"] = (
                        "hdlAPI: Could not load %s data type handler" % mname)
                    self._msgattrs["error"] = sys.exc_value + "<p>"
                    raise ImportError, mname
                types = m.handle_types
                formatter = m.data_formatter
            except (ImportError, AttributeError), msg:
                if hdllib.data_map.has_key(tname):
                    self._types = [hdllib.data_map[tname]]
                else:
                    try:
                        n = string.atoi(t)
                    except ValueError:
                        self._types = [] # Request all types
                    else:
                        self._types = [n]
            else:
                self._types = types
                if formatter:
                    self._formatter = formatter

        if self._attrs.has_key('server'):
            self._hashtable = hdllib.HashTable(server=self._attrs['server'])

    def pollmeta(self):
        nullAPI.null_access.pollmeta(self)
        try:
            replyflags, self._items = self._hashtable.get_data(
                self._hdl, self._types)
        except hdllib.Error, inst:
            if inst.err == hdllib.HP_HANDLE_NOT_FOUND:
                #print "Retry using a local handle server"
                try:
                    self._hashtable = self.get_local_hash_table(
                        self._hdl)
                    replyflags, self._items = self._hashtable.get_data(
                        self._hdl, self._types)
                except hdllib.Error, inst:
                    # (Same comment as below)
                    raise IOError, inst, sys.exc_traceback
                else:
                    return 'Ready', 1
            # Catch all errors and raise an IOError.  The Grail
            # protocol extension defines this as the only error we're
            # allowed to raise.
            # Because the hdllib.Error instance is passed, no
            # information is lost.
            raise IOError, inst, sys.exc_traceback
        else:
            return 'Ready', 1

    def getmeta(self):
        nullAPI.null_access.getmeta(self)
        self._data = ""
        self._pos = 0
        return self._formatter(self)

    def formatter(self, alterego=None):
        if len(self._items) == 1 and self._items[0][0] == hdllib.HDL_TYPE_URL:
            return 302, 'Moved', {'location': self._items[0][1]}
        if len(self._items) == 0:
            self._data = "Handle not resolved to anything\n"
            return 404, 'Handle not resolved to anything', {}
        data = HTML_HEADER % self._msgattrs
        for type, uri in self._items:
            if type == hdllib.HDL_TYPE_URL:
                uri = escape(uri)
                text = '<LI><A HREF="%s">%s</A>\n' % (uri, uri)
            else:
                if type in (hdllib.HDL_TYPE_SERVICE_POINTER,
                            hdllib.HDL_TYPE_SERVICE_HANDLE):
                    uri = hdllib.hexstr(uri)
                else:
                    uri = escape(`uri`)
                if hdllib.data_map.has_key(type):
                    type = hdllib.data_map[type][9:]
                else:
                    type = str(type)
                text = '<LI>type=%s, value=%s\n' % (type, uri)
            data = data + text
        data = data + HTML_TRAILER
        self._data = data
        return 200, 'OK', {'content-type': 'text/html'}

    _formatter = formatter

    # polldata() is inherited from nullAPI

    def getdata(self, maxbytes):
        end = self._pos + maxbytes
        data = self._data[self._pos:end]
        if not data:
            return nullAPI.null_access.getdata(self, maxbytes)
        self._pos = end
        return data


# Here are some test handles:
#
# hdl:CNRI/19970131120001
# hdl:nlm.hdl_test/96053804
# hdl:cnri.dlib/december95
# hdl:cnri.dlib/november95
# hdl:nonreg.guido/python-home-page
# hdl:nonreg.guido/python-ftp-dir
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.