source: wokkel/generic.py @ 116:66d9a0b47016

Last change on this file since 116:66d9a0b47016 was 30:68535ae85c8d, checked in by Ralph Meijer <ralphm@…>, 14 years ago

Add support for pubsub collections.

File size: 3.2 KB
RevLine 
[20]1# -*- test-case-name: wokkel.test.test_generic -*-
2#
3# Copyright (c) 2003-2008 Ralph Meijer
[1]4# See LICENSE for details.
5
6"""
7Generic XMPP protocol helpers.
8"""
9
10from zope.interface import implements
11
12from twisted.internet import defer
[2]13from twisted.words.protocols.jabber import error
[20]14from twisted.words.protocols.jabber.xmlstream import toResponse
[24]15from twisted.words.xish import domish
[1]16
17from wokkel import disco
18from wokkel.iwokkel import IDisco
19from wokkel.subprotocols import XMPPHandler
20
21IQ_GET = '/iq[@type="get"]'
22IQ_SET = '/iq[@type="set"]'
23
24NS_VERSION = 'jabber:iq:version'
25VERSION = IQ_GET + '/query[@xmlns="' + NS_VERSION + '"]'
26
[24]27def parseXml(string):
28    """
29    Parse serialized XML into a DOM structure.
30
31    @param string: The serialized XML to be parsed, UTF-8 encoded.
32    @type string: C{str}.
33    @return: The DOM structure, or C{None} on empty or incomplete input.
34    @rtype: L{domish.Element}
35    """
36    roots = []
37    results = []
38    elementStream = domish.elementStream()
39    elementStream.DocumentStartEvent = roots.append
40    elementStream.ElementEvent = lambda elem: roots[0].addChild(elem)
41    elementStream.DocumentEndEvent = lambda: results.append(roots[0])
42    elementStream.parse(string)
43    return results and results[0] or None
44
45
46
[30]47def stripNamespace(rootElement):
48    namespace = rootElement.uri
49
50    def strip(element):
51        if element.uri == namespace:
52            element.uri = None
53            if element.defaultUri == namespace:
54                element.defaultUri = None
55            for child in element.elements():
56                strip(child)
57
58    if namespace is not None:
59        strip(rootElement)
60
61    return rootElement
62
63
64
[1]65class FallbackHandler(XMPPHandler):
66    """
67    XMPP subprotocol handler that catches unhandled iq requests.
68
69    Unhandled iq requests are replied to with a service-unavailable stanza
70    error.
71    """
72
73    def connectionInitialized(self):
74        self.xmlstream.addObserver(IQ_SET, self.iqFallback, -1)
75        self.xmlstream.addObserver(IQ_GET, self.iqFallback, -1)
76
77    def iqFallback(self, iq):
78        if iq.handled == True:
79            return
80
81        reply = error.StanzaError('service-unavailable')
82        self.xmlstream.send(reply.toResponse(iq))
83
84
[20]85
[1]86class VersionHandler(XMPPHandler):
87    """
88    XMPP subprotocol handler for XMPP Software Version.
89
90    This protocol is described in
91    U{XEP-0092<http://www.xmpp.org/extensions/xep-0092.html>}.
92    """
93
94    implements(IDisco)
95
96    def __init__(self, name, version):
97        self.name = name
98        self.version = version
99
100    def connectionInitialized(self):
101        self.xmlstream.addObserver(VERSION, self.onVersion)
102
103    def onVersion(self, iq):
[20]104        response = toResponse(iq, "result")
[1]105
[20]106        query = response.addElement((NS_VERSION, "query"))
[1]107        name = query.addElement("name", content=self.name)
[20]108        version = query.addElement("version", content=self.version)
109        self.send(response)
[1]110
111        iq.handled = True
112
[6]113    def getDiscoInfo(self, requestor, target, node):
[11]114        info = set()
115
[1]116        if not node:
[11]117            info.add(disco.DiscoFeature(NS_VERSION))
118
119        return defer.succeed(info)
[1]120
[6]121    def getDiscoItems(self, requestor, target, node):
[1]122        return defer.succeed([])
Note: See TracBrowser for help on using the repository browser.