Learn more  » Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

vistahigherlearning / punjab   python

Repository URL to install this package:

/ punjab / httpb.py

"""
 http binding interface
"""
from twisted.python import components
from twisted.web import server, resource
from twisted.internet import defer, task
from twisted.python import log

from zope.interface import Interface, implements

try:
    from twisted.words.xish import domish
except ImportError:
    from twisted.xish import domish

import hashlib, time
import error
from session import make_session
import punjab
from punjab.xmpp import ns


NS_BIND = 'http://jabber.org/protocol/httpbind'
NS_FEATURES = 'http://etherx.jabber.org/streams'
NS_XMPP = 'urn:xmpp:xbosh'

class DummyElement:
    """
    dummy element for a quicker parse
    """
    # currently not used
    def __init__(self, *args, **kwargs):

        self.children = []



class HttpbElementStream(domish.ExpatElementStream):
    """
    add rawXml to the elements
    """

    def __init__(self, prefixes=None):
        domish.ExpatElementStream.__init__(self)
        self.prefixes = {}
        if prefixes:
            self.prefixes.update(prefixes)
        self.prefixes.update(domish.G_PREFIXES)
        self.prefixStack = [domish.G_PREFIXES.values()]
        self.prefixCounter = 0


    def getPrefix(self, uri):
        if not self.prefixes.has_key(uri):
            self.prefixes[uri] = "xn%d" % (self.prefixCounter)
            self.prefixCounter = self.prefixCounter + 1
        return self.prefixes[uri]

    def prefixInScope(self, prefix):
        stack = self.prefixStack
        for i in range(-1, (len(self.prefixStack)+1) * -1, -1):
            if prefix in stack[i]:
                return True
        return False

    def _onStartElement(self, name, attrs):
        # Generate a qname tuple from the provided name
        attr_str   = ''
        defaultUri = None
        uri        = None
        qname = name.split(" ")
        if len(qname) == 1:
            qname = ('', name)
            currentUri = None
        else:
            currentUri = qname[0]
        if self.currElem:
            defaultUri = self.currElem.defaultUri
            uri = self.currElem.uri

        if not defaultUri and currentUri in self.defaultNsStack:
            defaultUri = self.defaultNsStack[1]

        if defaultUri and currentUri != defaultUri:

            raw_xml = u"""<%s xmlns='%s'%s""" % (qname[1], qname[0], '%s')

        else:
            raw_xml = u"""<%s%s""" % (qname[1], '%s')


        # Process attributes

        for k, v in attrs.items():
            if k.find(" ") != -1:
                aqname = k.split(" ")
                attrs[(aqname[0], aqname[1])] = v

                attr_prefix = self.getPrefix(aqname[0])
                if not self.prefixInScope(attr_prefix):
                    attr_str = attr_str + " xmlns:%s='%s'" % (attr_prefix,
                                                              aqname[0])
                    self.prefixStack[-1].append(attr_prefix)
                attr_str = attr_str + " %s:%s='%s'" % (attr_prefix,
                                                       aqname[1],
                                                       domish.escapeToXml(v,
                                                                          True))
                del attrs[k]
            else:
                v = domish.escapeToXml(v, True)
                attr_str = attr_str + " " + k + "='" + v + "'"

        raw_xml = raw_xml % (attr_str,)

        # Construct the new element
        e = domish.Element(qname, self.defaultNsStack[-1], attrs, self.localPrefixes)
        self.localPrefixes = {}

        # Document already started
        if self.documentStarted == 1:
            if self.currElem != None:
                if len(self.currElem.children)==0 or isinstance(self.currElem.children[-1], domish.Element):
                    if self.currRawElem[-1] != ">":
                        self.currRawElem = self.currRawElem +">"

                self.currElem.children.append(e)
                e.parent = self.currElem

            self.currRawElem = self.currRawElem + raw_xml
            self.currElem = e
        # New document
        else:
            self.currRawElem = u''
            self.documentStarted = 1
            self.DocumentStartEvent(e)

    def _onEndElement(self, _):
        # Check for null current elem; end of doc
        if self.currElem is None:
            self.DocumentEndEvent()

        # Check for parent that is None; that's
        # the top of the stack
        elif self.currElem.parent is None:
            if len(self.currElem.children)>0:
                self.currRawElem = self.currRawElem + "</"+ self.currElem.name+">"
            else:
                self.currRawElem = self.currRawElem + "/>"
            self.ElementEvent(self.currElem, self.currRawElem)
            self.currElem = None
            self.currRawElem = u''
        # Anything else is just some element in the current
        # packet wrapping up
        else:
            if len(self.currElem.children)==0:
                self.currRawElem = self.currRawElem + "/>"
            else:
                self.currRawElem = self.currRawElem + "</"+ self.currElem.name+">"
            self.currElem = self.currElem.parent

    def _onCdata(self, data):
        if self.currElem != None:
            if len(self.currElem.children)==0:
                self.currRawElem = self.currRawElem + ">" + domish.escapeToXml(data)
                #self.currRawElem = self.currRawElem + ">" + data
            else:
                self.currRawElem = self.currRawElem  + domish.escapeToXml(data)
                #self.currRawElem = self.currRawElem  + data

            self.currElem.addContent(data)

    def _onStartNamespace(self, prefix, uri):
        # If this is the default namespace, put
        # it on the stack
        if prefix is None:
            self.defaultNsStack.append(uri)
        else:
            self.localPrefixes[prefix] = uri

    def _onEndNamespace(self, prefix):
        # Remove last element on the stack
        if prefix is None:
            self.defaultNsStack.pop()

def elementStream():
    """ Preferred method to construct an ElementStream

    Uses Expat-based stream if available, and falls back to Sux if necessary.
    """
    try:
        es = HttpbElementStream()
        return es
    except ImportError:
        if domish.SuxElementStream is None:
            raise Exception("No parsers available :(")
        es = domish.SuxElementStream()
        return es

# make httpb body class, similar to xmlrpclib
#
class HttpbParse:
    """
    An xml parser for parsing the body elements.
    """
    def __init__(self, use_t=False):
        """
        Call reset to initialize object
        """
        self.use_t = use_t # use domish element stream
        self._reset()


    def parse(self, buf):
        """
        Parse incoming xml and return the body and its children in a list
        """
        self.stream.parse(buf)

        # return the doc element and its children in a list
        return self.body, self.xmpp_elements

    def serialize(self, obj):
        """
        Turn object into a string type
        """
        if isinstance(obj, domish.Element):
            obj = obj.toXml()
        return obj

    def onDocumentStart(self, rootelem):
        """
        The body document has started.

        This should be a body.
        """
        if rootelem.name == 'body':
            self.body = rootelem

    def onElement(self, element, raw_element = None):
        """
        A child element has been found.
        """
        if isinstance(element, domish.Element):
            if raw_element:
                self.xmpp_elements.append(raw_element)
            else:
                self.xmpp_elements.append(element)
        else:
            pass

    def _reset(self):
        """
        Setup the parser
        """
        if not self.use_t:
            self.stream = elementStream()
        else:
            self.stream = domish.elementStream()

        self.stream.DocumentStartEvent = self.onDocumentStart
        self.stream.ElementEvent = self.onElement
        self.stream.DocumentEndEvent = self.onDocumentEnd
        self.body = ""
        self.xmpp_elements = []


    def onDocumentEnd(self):
        """
        Body End
        """
        pass

class IHttpbService(Interface):
    """
    Interface for http binding class
    """
    def __init__(self, verbose):
        """ """

    def startSession(self, body):
        """ Start a punjab jabber session """

    def endSession(self, session):
        """ end a punjab jabber session """

    def onExpire(self, session_id):
        """ preform actions based on when the jabber connection expires """

    def parseBody(self, body):
        """ parse a body element """


    def error(self, error):
        """ send a body error element """


    def inSession(self, body):
        """ """

    def getXmppElements(self, body, session):
        """ """



class IHttpbFactory(Interface):
    """
    Factory class for generating binding sessions.
    """
    def startSession(self):
        """ Start a punjab jabber session """

    def endSession(self, session):
        """ end a punjab jabber session """

    def parseBody(self, body):
        """ parse an body element """

    def buildProtocol(self, addr):
        """Return a protocol """



class Httpb(resource.Resource):
    """
    Http resource to handle BOSH requests.
    """
    isLeaf = True
    def __init__(self, service, v = 0):
        """Initialize.
        """
        resource.Resource.__init__(self)
        self.service  = service
        self.hp       = None
        self.children = {}
        self.client   = 0
        self.verbose  = v

        self.polling = self.service.polling or 15

    def render_OPTIONS(self, request):
        request.setHeader('Access-Control-Allow-Origin', '*')
        request.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        request.setHeader('Access-Control-Allow-Headers', 'Content-Type')
        request.setHeader('Access-Control-Max-Age', '86400')
        return ""
Loading ...