From 086bf89d699c88ab89ad1e1975d6022335ca5c04 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Sun, 3 Jul 2011 00:35:36 -0700 Subject: Added XEP-0066: Out-of-Band Data --- sleekxmpp/plugins/xep_0066/__init__.py | 11 +++++ sleekxmpp/plugins/xep_0066/oob.py | 89 ++++++++++++++++++++++++++++++++++ sleekxmpp/plugins/xep_0066/stanza.py | 33 +++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 sleekxmpp/plugins/xep_0066/__init__.py create mode 100644 sleekxmpp/plugins/xep_0066/oob.py create mode 100644 sleekxmpp/plugins/xep_0066/stanza.py (limited to 'sleekxmpp/plugins/xep_0066') diff --git a/sleekxmpp/plugins/xep_0066/__init__.py b/sleekxmpp/plugins/xep_0066/__init__.py new file mode 100644 index 00000000..ebfbd0c2 --- /dev/null +++ b/sleekxmpp/plugins/xep_0066/__init__.py @@ -0,0 +1,11 @@ +""" + SleekXMPP: The Sleek XMPP Library + Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout + This file is part of SleekXMPP. + + See the file LICENSE for copying permission. +""" + +from sleekxmpp.plugins.xep_0066 import stanza +from sleekxmpp.plugins.xep_0066.stanza import OOB, OOBTransfer +from sleekxmpp.plugins.xep_0066.oob import xep_0066 diff --git a/sleekxmpp/plugins/xep_0066/oob.py b/sleekxmpp/plugins/xep_0066/oob.py new file mode 100644 index 00000000..b4322351 --- /dev/null +++ b/sleekxmpp/plugins/xep_0066/oob.py @@ -0,0 +1,89 @@ +""" + SleekXMPP: The Sleek XMPP Library + Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout + This file is part of SleekXMPP. + + See the file LICENSE for copying permission. +""" + + +from sleekxmpp.stanza import Message, Presence, Iq +from sleekxmpp.xmlstream import register_stanza_plugin +from sleekxmpp.xmlstream.handler import Callback +from sleekxmpp.xmlstream.matcher import StanzaPath +from sleekxmpp.plugins.base import base_plugin +from sleekxmpp.plugins.xep_0066 import stanza + + +class xep_0066(base_plugin): + + """ + XEP-0066: Out-of-Band Data + + Out-of-Band Data is a basic method for transferring files between + XMPP agents. The URL of the resource in question is sent to the receiving + entity, which then downloads the resource before responding to the OOB + request. OOB is also used as a generic means to transmit URLs in other + stanzas to indicate where to find additional information. + + Also see . + + Events: + oob_transfer -- Raised when a request to download a resource + has been received. + + Methods: + send_oob -- Send a request to another entity to download a file + or other addressable resource. + """ + + def plugin_init(self): + """Start the XEP-0066 plugin.""" + self.xep = '0066' + self.description = 'Out-of-Band Transfer' + self.stanza = stanza + + register_stanza_plugin(Iq, stanza.OOBTransfer) + register_stanza_plugin(Message, stanza.OOB) + register_stanza_plugin(Presence, stanza.OOB) + + self.xmpp.register_handler( + Callback('OOB Transfer', + StanzaPath('iq@type=set/oob_transfer'), + self._handle_transfer)) + + def post_init(self): + """Handle cross-plugin dependencies.""" + base_plugin.post_init(self) + self.xmpp['xep_0030'].add_feature(stanza.OOBTransfer.namespace) + self.xmpp['xep_0030'].add_feature(stanza.OOB.namespace) + + def send_oob(self, to, url, desc=None, ifrom=None, **iqargs): + """ + Initiate a basic file transfer by sending the URL of + a file or other resource. + + Arguments: + url -- The URL of the resource to transfer. + desc -- An optional human readable description of the item + that is to be transferred. + ifrom -- Specifiy the sender's JID. + block -- If true, block and wait for the stanzas' reply. + timeout -- The time in seconds to block while waiting for + a reply. If None, then wait indefinitely. + callback -- Optional callback to execute when a reply is + received instead of blocking and waiting for + the reply. + """ + iq = self.xmpp.Iq() + iq['type'] = 'set' + iq['to'] = to + if ifrom: + iq['from'] = ifrom + iq['oob_transfer']['url'] = url + iq['oob_transfer']['desc'] = desc + return iq.send(**iqargs) + + def _handle_transfer(self, iq): + """Handle receiving an out-of-band transfer request.""" + self.xmpp.event('oob_transfer', iq) diff --git a/sleekxmpp/plugins/xep_0066/stanza.py b/sleekxmpp/plugins/xep_0066/stanza.py new file mode 100644 index 00000000..21387485 --- /dev/null +++ b/sleekxmpp/plugins/xep_0066/stanza.py @@ -0,0 +1,33 @@ +""" + SleekXMPP: The Sleek XMPP Library + Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout + This file is part of SleekXMPP. + + See the file LICENSE for copying permission. +""" + +from sleekxmpp.xmlstream import ElementBase + + +class OOBTransfer(ElementBase): + + """ + """ + + name = 'query' + namespace = 'jabber:iq:oob' + plugin_attrib = 'oob_transfer' + interfaces = set(('url', 'desc', 'sid')) + sub_interfaces = set(('url', 'desc')) + + +class OOB(ElementBase): + + """ + """ + + name = 'x' + namespace = 'jabber:x:oob' + plugin_attrib = 'oob' + interfaces = set(('url', 'desc')) + sub_interfaces = interfaces -- cgit v1.2.3 From cccccdcc0aae2be9a00012c872ab1fad60b2b971 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Sun, 3 Jul 2011 20:39:03 -0700 Subject: Add logging to XEP-0066. --- sleekxmpp/plugins/xep_0066/oob.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sleekxmpp/plugins/xep_0066') diff --git a/sleekxmpp/plugins/xep_0066/oob.py b/sleekxmpp/plugins/xep_0066/oob.py index b4322351..1f79492d 100644 --- a/sleekxmpp/plugins/xep_0066/oob.py +++ b/sleekxmpp/plugins/xep_0066/oob.py @@ -6,6 +6,7 @@ See the file LICENSE for copying permission. """ +import logging from sleekxmpp.stanza import Message, Presence, Iq from sleekxmpp.xmlstream import register_stanza_plugin @@ -15,6 +16,9 @@ from sleekxmpp.plugins.base import base_plugin from sleekxmpp.plugins.xep_0066 import stanza +log = logging.getLogger(__name__) + + class xep_0066(base_plugin): """ @@ -86,4 +90,6 @@ class xep_0066(base_plugin): def _handle_transfer(self, iq): """Handle receiving an out-of-band transfer request.""" + log.debug('Received out-of-band data request for %s from %s:' % ( + iq['oob_transfer']['url'], iq['from'])) self.xmpp.event('oob_transfer', iq) -- cgit v1.2.3 From 1d22a0472193a543129875ac9a412de4d11fb8b0 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Tue, 5 Jul 2011 09:22:17 -0700 Subject: Added support for custom OOB transfer handlers. Accepting download requests can be done using: self['xep_0066'].register_url_handler(handler=self.oob_download) # Add jid=... to specify a handler for a particular JID for a # componenent. def oob_download(self, iq): if iq['from'] not in self.custom_oob_whitelist: raise XMPPError('not-authorized') try: data = urllib2.urlopen(iq['oob_transfer']['url']) file = open('oob_download', 'w+') file.write(data.read()) file.close() data.close() except: raise XMPPError('item-not-found') --- sleekxmpp/plugins/xep_0066/oob.py | 63 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) (limited to 'sleekxmpp/plugins/xep_0066') diff --git a/sleekxmpp/plugins/xep_0066/oob.py b/sleekxmpp/plugins/xep_0066/oob.py index 1f79492d..98cb81cd 100644 --- a/sleekxmpp/plugins/xep_0066/oob.py +++ b/sleekxmpp/plugins/xep_0066/oob.py @@ -9,6 +9,7 @@ import logging from sleekxmpp.stanza import Message, Presence, Iq +from sleekxmpp.exceptions import XMPPError from sleekxmpp.xmlstream import register_stanza_plugin from sleekxmpp.xmlstream.handler import Callback from sleekxmpp.xmlstream.matcher import StanzaPath @@ -47,6 +48,9 @@ class xep_0066(base_plugin): self.description = 'Out-of-Band Transfer' self.stanza = stanza + self.url_handlers = {'global': self._default_handler, + 'jid': {}} + register_stanza_plugin(Iq, stanza.OOBTransfer) register_stanza_plugin(Message, stanza.OOB) register_stanza_plugin(Presence, stanza.OOB) @@ -62,6 +66,28 @@ class xep_0066(base_plugin): self.xmpp['xep_0030'].add_feature(stanza.OOBTransfer.namespace) self.xmpp['xep_0030'].add_feature(stanza.OOB.namespace) + def register_url_handler(self, jid=None, handler=None): + """ + Register a handler to process download requests, either for all + JIDs or a single JID. + + Arguments: + jid -- If None, then set the handler as a global default. + handler -- If None, then remove the existing handler for the + given JID, or reset the global handler if the JID + is None. + """ + if jid is None: + if handler is not None: + self.url_handlers['global'] = handler + else: + self.url_handlers['global'] = self._default_handler + else: + if handler is not None: + self.url_handlers['jid'][jid] = handler + else: + del self.url_handlers['jid'][jid] + def send_oob(self, to, url, desc=None, ifrom=None, **iqargs): """ Initiate a basic file transfer by sending the URL of @@ -88,8 +114,41 @@ class xep_0066(base_plugin): iq['oob_transfer']['desc'] = desc return iq.send(**iqargs) + def _run_url_handler(self, iq): + """ + Execute the appropriate handler for a transfer request. + + Arguments: + iq -- The Iq stanza containing the OOB transfer request. + """ + if iq['to'] in self.url_handlers['jid']: + return self.url_handlers['jid'][jid](iq) + else: + if self.url_handlers['global']: + self.url_handlers['global'](iq) + else: + raise XMPPError('service-unavailable') + + def _default_handler(self, iq): + """ + As a safe default, don't actually download files. + + Register a new handler using self.register_url_handler to + screen requests and download files. + + Arguments: + iq -- The Iq stanza containing the OOB transfer request. + """ + raise XMPPError('service-unavailable') + def _handle_transfer(self, iq): - """Handle receiving an out-of-band transfer request.""" + """ + Handle receiving an out-of-band transfer request. + + Arguments: + iq -- An Iq stanza containing an OOB transfer request. + """ log.debug('Received out-of-band data request for %s from %s:' % ( iq['oob_transfer']['url'], iq['from'])) - self.xmpp.event('oob_transfer', iq) + self._run_url_handler(iq) + iq.reply().send() -- cgit v1.2.3