From 66500ef5fb6793aabae57d9738dde28a475a7518 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Thu, 8 Mar 2018 03:38:59 +0100 Subject: [PATCH] Add an HTTP File Upload plugin. --- slixmpp/plugins/xep_0363/__init__.py | 14 +++++ slixmpp/plugins/xep_0363/http_upload.py | 77 +++++++++++++++++++++++++ slixmpp/plugins/xep_0363/stanza.py | 38 ++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 slixmpp/plugins/xep_0363/__init__.py create mode 100644 slixmpp/plugins/xep_0363/http_upload.py create mode 100644 slixmpp/plugins/xep_0363/stanza.py diff --git a/slixmpp/plugins/xep_0363/__init__.py b/slixmpp/plugins/xep_0363/__init__.py new file mode 100644 index 00000000..d40bee4e --- /dev/null +++ b/slixmpp/plugins/xep_0363/__init__.py @@ -0,0 +1,14 @@ +""" + slixmpp: The Slick XMPP Library + Copyright (C) 2018 Emmanuel Gil Peyrot + This file is part of slixmpp. + + See the file LICENSE for copying permission. +""" + +from slixmpp.plugins.base import register_plugin + +from slixmpp.plugins.xep_0363.stanza import Request, Slot, Put, Get, Header +from slixmpp.plugins.xep_0363.http_upload import XEP_0363 + +register_plugin(XEP_0363) diff --git a/slixmpp/plugins/xep_0363/http_upload.py b/slixmpp/plugins/xep_0363/http_upload.py new file mode 100644 index 00000000..3026a8c9 --- /dev/null +++ b/slixmpp/plugins/xep_0363/http_upload.py @@ -0,0 +1,77 @@ +""" + slixmpp: The Slick XMPP Library + Copyright (C) 2018 Emmanuel Gil Peyrot + This file is part of slixmpp. + + See the file LICENSE for copying permission. +""" + +import asyncio +import logging + +from slixmpp import Iq +from slixmpp.plugins import BasePlugin +from slixmpp.xmlstream import register_stanza_plugin +from slixmpp.xmlstream.handler import Callback +from slixmpp.xmlstream.matcher import StanzaPath +from slixmpp.plugins.xep_0363 import stanza, Request, Slot, Put, Get, Header + +log = logging.getLogger(__name__) + +class XEP_0363(BasePlugin): + + name = 'xep_0363' + description = 'XEP-0363: HTTP File Upload' + dependencies = {'xep_0030'} + stanza = stanza + + def plugin_init(self): + register_stanza_plugin(Iq, Request) + register_stanza_plugin(Iq, Slot) + register_stanza_plugin(Slot, Put) + register_stanza_plugin(Slot, Get) + register_stanza_plugin(Put, Header) + + self.xmpp.register_handler( + Callback('HTTP Upload Request', + StanzaPath('iq@type=get/http_upload_request'), + self._handle_request)) + + def plugin_end(self): + self.xmpp.remove_handler('HTTP Upload Request') + self.xmpp.remove_handler('HTTP Upload Slot') + self.xmpp['xep_0030'].del_feature(feature=Request.namespace) + + def session_bind(self, jid): + self.xmpp.plugin['xep_0030'].add_feature(Request.namespace) + + def _handle_request(self, iq): + self.xmpp.event('http_upload_request', iq) + + @asyncio.coroutine + def find_upload_service(self, ifrom=None, timeout=None, callback=None, + timeout_callback=None): + infos = [self.xmpp['xep_0030'].get_info(self.xmpp.boundjid.domain)] + iq_items = yield from self.xmpp['xep_0030'].get_items( + self.xmpp.boundjid.domain, timeout=timeout) + items = iq_items['disco_items']['items'] + infos += [self.xmpp['xep_0030'].get_info(item[0]) for item in items] + info_futures, _ = yield from asyncio.wait(infos, timeout=timeout) + for future in info_futures: + info = future.result() + for identity in info['disco_info']['identities']: + if identity[0] == 'store' and identity[1] == 'file': + return info + + def request_slot(self, jid, filename, size, content_type=None, ifrom=None, + timeout=None, callback=None, timeout_callback=None): + iq = self.xmpp.Iq() + iq['to'] = jid + iq['from'] = ifrom + iq['type'] = 'get' + request = iq['http_upload_request'] + request['filename'] = filename + request['size'] = str(size) + request['content-type'] = content_type + return iq.send(timeout=timeout, callback=callback, + timeout_callback=timeout_callback) diff --git a/slixmpp/plugins/xep_0363/stanza.py b/slixmpp/plugins/xep_0363/stanza.py new file mode 100644 index 00000000..4795f96d --- /dev/null +++ b/slixmpp/plugins/xep_0363/stanza.py @@ -0,0 +1,38 @@ +""" + slixmpp: The Slick XMPP Library + Copyright (C) 2018 Emmanuel Gil Peyrot + This file is part of slixmpp. + + See the file LICENSE for copying permission. +""" + +from slixmpp.xmlstream import ElementBase + +class Request(ElementBase): + plugin_attrib = 'http_upload_request' + name = 'request' + namespace = 'urn:xmpp:http:upload:0' + interfaces = {'filename', 'size', 'content-type'} + +class Slot(ElementBase): + plugin_attrib = 'http_upload_slot' + name = 'slot' + namespace = 'urn:xmpp:http:upload:0' + +class Put(ElementBase): + plugin_attrib = 'put' + name = 'put' + namespace = 'urn:xmpp:http:upload:0' + interfaces = {'url'} + +class Get(ElementBase): + plugin_attrib = 'get' + name = 'get' + namespace = 'urn:xmpp:http:upload:0' + interfaces = {'url'} + +class Header(ElementBase): + plugin_attrib = 'header' + name = 'header' + namespace = 'urn:xmpp:http:upload:0' + interfaces = {'name', 'value'}