changeset 1:4cc41776b7d7

Initial revision
author Ralph Meijer <ralphm@ik.nu>
date Wed, 23 Jun 2004 14:31:49 +0000
parents 1b68bdae21eb
children 9701df89c534
files idavoll/__init__.py idavoll/backend.py idavoll/idavoll.py idavoll/plugins.tml idavoll/pubsub.py idavoll/tap.py idavoll/xmpp_error.py
diffstat 6 files changed, 236 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/idavoll/backend.py	Wed Jun 23 14:31:49 2004 +0000
@@ -0,0 +1,62 @@
+from twisted.application import service
+from twisted.python import components, failure
+from twisted.internet import defer, reactor
+
+class IBackendService(components.Interface):
+	""" Interface to a backend service of a pubsub service """
+
+class BackendException(Exception):
+	def __init__(self, msg = ''):
+		self.msg = msg
+
+	def __str__(self):
+		return self.msg
+	
+class NodeNotFound(BackendException):
+	#def __init__(self, msg = 'Node not found'):
+	#	BackendException.__init__(self, msg)
+	pass
+
+class NotAuthorized(BackendException):
+	pass
+
+class MemoryBackendService(service.Service):
+
+	__implements__ = IBackendService,
+
+	def __init__(self):
+		self.nodes = {"ralphm/test": 'test'}
+		self.subscribers = {"ralphm/test": ["ralphm@ik.nu", "intosi@ik.nu"] }
+		self.affiliations = {"ralphm/test": { "ralphm@ik.nu": "owner", "ralphm@se-135.se.wtb.tue.nl": 'publisher' } }
+
+	def do_publish(self, node, publisher, item):
+		try:
+			try:
+				result = self.nodes[node]
+			except KeyError:
+				raise NodeNotFound
+
+			try:
+				affiliation = self.affiliations[node][publisher]
+				if affiliation not in ['owner', 'publisher']:
+					raise NotAuthorized
+			except KeyError:
+				raise NotAuthorized()
+			print "publish by %s to %s" % (publisher, node)
+			return defer.succeed(result)
+		except:
+			f = failure.Failure()
+			return defer.fail(f)
+
+	def get_subscribers(self, node):
+		d = defer.Deferred()
+		try:
+			result = self.subscribers[node]
+		except:
+			f = failure.Failure()
+			reactor.callLater(0, d.errback, f)
+		else:
+			reactor.callLater(0, d.callback, result)
+
+		return d
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/idavoll/idavoll.py	Wed Jun 23 14:31:49 2004 +0000
@@ -0,0 +1,56 @@
+from twisted.protocols.jabber import component
+from twisted.application import service
+import backend
+import pubsub
+import xmpp_error
+
+import sys
+
+IQ_GET = '/iq[@type="get"]'
+IQ_SET = '/iq[@type="set"]'
+VERSION = IQ_GET + '/query[@xmlns="jabber:iq:version"]'
+
+class IdavollService(component.Service):
+
+	def componentConnected(self, xmlstream):
+		self.xmlstream = xmlstream
+		xmlstream.addObserver(VERSION, self.onVersion, 1)
+		xmlstream.addObserver(IQ_GET, self.iqFallback, -1)
+		xmlstream.addObserver(IQ_SET, self.iqFallback, -1)
+	
+	def onVersion(self, iq):
+		print "version?"
+		iq.swapAttributeValues("to", "from")
+		iq["type"] = "result"
+		name = iq.addElement("name", None, 'Idavoll')
+		version = iq.addElement("version", None, '0.1')
+		self.send(iq)
+		iq.handled = True
+
+	def iqFallback(self, iq):
+		if iq.handled == True:
+			return
+
+		self.send(xmpp_error.error_from_iq(iq, 'feature-not-implemented'))
+
+def makeService(config):
+	serviceCollection = service.MultiService()
+
+	pss = backend.MemoryBackendService()
+
+	# set up Jabber Component
+	c = component.buildServiceManager(config["jid"], config["secret"],
+			("tcp:%s:%s" % (config["rhost"], config["rport"])))
+
+	s = component.IService(pss)
+	s.jid = config["jid"]
+	s.setServiceParent(c)
+
+	s = IdavollService()
+	s.setServiceParent(c)
+
+	c.setServiceParent(serviceCollection)
+
+	# other stuff
+
+	return c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/idavoll/plugins.tml	Wed Jun 23 14:31:49 2004 +0000
@@ -0,0 +1,3 @@
+register("Idavoll", "idavoll.tap",
+         description="Jabber Publish Subscribe Component",
+         type='tap', tapname='idavoll')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/idavoll/pubsub.py	Wed Jun 23 14:31:49 2004 +0000
@@ -0,0 +1,73 @@
+from twisted.protocols.jabber import component,jid
+from twisted.xish import utility
+from twisted.python import components
+import backend
+import xmpp_error
+
+IQ_GET = '/iq[@type="get"]'
+IQ_SET = '/iq[@type="set"]'
+PUBSUB_GET = IQ_GET + '/pubsub[@xmlns="http://jabber.org/protocol/pubsub"]'
+PUBSUB_SET = IQ_SET + '/pubsub[@xmlns="http://jabber.org/protocol/pubsub"]'
+
+PUBSUB_CREATE = PUBSUB_SET + '/create'
+PUBSUB_PUBLISH = PUBSUB_SET + '/publish'
+
+class ComponentServiceFromBackend(component.Service, utility.EventDispatcher):
+
+	def __init__(self, backend):
+		utility.EventDispatcher.__init__(self)
+		self.backend = backend
+		self.addObserver(PUBSUB_PUBLISH, self.onPublish)
+
+	def componentConnected(self, xmlstream):
+		xmlstream.addObserver(PUBSUB_SET, self.onPubSub)
+		xmlstream.addObserver(PUBSUB_GET, self.onPubSub)
+
+	def error(self, failure, iq):
+		r = failure.trap(backend.NotAuthorized, backend.NodeNotFound)
+
+		if r == backend.NotAuthorized:
+			xmpp_error.error_from_iq(iq, 'not-authorized', failure.value.msg)
+
+		if r == backend.NodeNotFound:
+			xmpp_error.error_from_iq(iq, 'item-not-found', failure.value.msg)
+
+		return iq
+	
+	def success(self, result, iq):
+		iq.swapAttributeValues("to", "from")
+		iq["type"] = 'result'
+		iq.children = []
+		return iq
+
+	def onPubSub(self, iq):
+		self.dispatch(iq)
+		iq.handled = True
+
+	def onPublish(self, iq):
+		node = iq.pubsub.publish["node"]
+
+		d = self.backend.do_publish(node, jid.JID(iq["from"]).userhost(), iq.pubsub.publish.item)
+		d.addCallback(self.success, iq)
+		d.addErrback(self.error, iq)
+		d.addCallback(self.send)
+
+
+"""
+	def onCreateSet(self, iq):
+		node = iq.pubsub.create["node"]
+		owner = jid.JID(iq["from"]).userhost()
+
+		try:
+			node = self.backend.create_node(node, owner)
+
+			if iq.pubsub.create["node"] == None:
+				# also show node name
+		except:
+			pass
+
+		iq.handled = True
+"""
+
+components.registerAdapter(ComponentServiceFromBackend, backend.IBackendService, component.IService)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/idavoll/tap.py	Wed Jun 23 14:31:49 2004 +0000
@@ -0,0 +1,15 @@
+from twisted.application import internet, service
+from twisted.internet import interfaces
+from twisted.python import usage
+import idavoll
+
+class Options(usage.Options):
+	optParameters = [
+		('jid', None, 'pubsub'),
+		('secret', None, None),
+		('rhost', None, '127.0.0.1'),
+		('rport', None, '6000')
+	]
+
+def makeService(config):
+	return idavoll.makeService(config)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/idavoll/xmpp_error.py	Wed Jun 23 14:31:49 2004 +0000
@@ -0,0 +1,27 @@
+conditions = {
+	'not-authorized':			{'code': '401', 'type': 'cancel'},
+	'item-not-found':			{'code': '404', 'type': 'cancel'},
+	'feature-not-implemented':	{'code': '501', 'type': 'cancel'},
+}
+
+def error_from_iq(iq, condition, text = '', type = None):
+	iq.swapAttributeValues("to", "from")
+	iq["type"] = 'error'
+	e = iq.addElement("error")
+
+	c = e.addElement(condition)
+	c["xmlns"] = "urn:ietf:params:xml:ns:xmpp-stanzas"
+
+	if type == None:
+		type = conditions[condition]['type']
+
+	code = conditions[condition]['code']
+
+	e["code"] = code
+	e["type"] = type
+
+	if text:
+		t = e.addElement("text", None, text)
+		t["xmlns"] = "urn:ietf:params:xml:ns:xmpp-stanzas"
+
+	return iq