""" Slixmpp: The Slick XMPP Library Copyright (C) 2012 Nathanael C. Fritz, Emmanuel Gil Peyrot This file is part of Slixmpp. See the file LICENSE for copying permission. """ import logging import hashlib from slixmpp import future_wrapper from slixmpp.stanza import Iq, Message, Presence from slixmpp.exceptions import XMPPError from slixmpp.xmlstream.handler import Callback from slixmpp.xmlstream.matcher import StanzaPath from slixmpp.xmlstream import register_stanza_plugin from slixmpp.plugins.base import BasePlugin from slixmpp.plugins.xep_0231 import stanza, BitsOfBinary log = logging.getLogger(__name__) class XEP_0231(BasePlugin): """ XEP-0231 Bits of Binary """ name = 'xep_0231' description = 'XEP-0231: Bits of Binary' dependencies = {'xep_0030'} def plugin_init(self): self._cids = {} register_stanza_plugin(Iq, BitsOfBinary) register_stanza_plugin(Message, BitsOfBinary) register_stanza_plugin(Presence, BitsOfBinary) self.xmpp.register_handler( Callback('Bits of Binary - Iq', StanzaPath('iq/bob'), self._handle_bob_iq)) self.xmpp.register_handler( Callback('Bits of Binary - Message', StanzaPath('message/bob'), self._handle_bob)) self.xmpp.register_handler( Callback('Bits of Binary - Presence', StanzaPath('presence/bob'), self._handle_bob)) self.api.register(self._get_bob, 'get_bob', default=True) self.api.register(self._set_bob, 'set_bob', default=True) self.api.register(self._del_bob, 'del_bob', default=True) def plugin_end(self): self.xmpp['xep_0030'].del_feature(feature='urn:xmpp:bob') self.xmpp.remove_handler('Bits of Binary - Iq') self.xmpp.remove_handler('Bits of Binary - Message') self.xmpp.remove_handler('Bits of Binary - Presence') def session_bind(self, jid): self.xmpp['xep_0030'].add_feature('urn:xmpp:bob') def set_bob(self, data, mtype, cid=None, max_age=None): if cid is None: cid = 'sha1+%s@bob.xmpp.org' % hashlib.sha1(data).hexdigest() bob = BitsOfBinary() bob['data'] = data bob['type'] = mtype bob['cid'] = cid bob['max_age'] = max_age self.api['set_bob'](args=bob) return cid @future_wrapper def get_bob(self, jid=None, cid=None, cached=True, ifrom=None, timeout=None, callback=None): if cached: data = self.api['get_bob'](None, None, ifrom, args=cid) if data is not None: if not isinstance(data, Iq): iq = self.xmpp.Iq() iq.append(data) return iq return data iq = self.xmpp.Iq() iq['to'] = jid iq['from'] = ifrom iq['type'] = 'get' iq['bob']['cid'] = cid return iq.send(timeout=timeout, callback=callback) def del_bob(self, cid): self.api['del_bob'](args=cid) def _handle_bob_iq(self, iq): cid = iq['bob']['cid'] if iq['type'] == 'result': self.api['set_bob'](iq['from'], None, iq['to'], args=iq['bob']) self.xmpp.event('bob', iq) elif iq['type'] == 'get': data = self.api['get_bob'](iq['to'], None, iq['from'], args=cid) if isinstance(data, Iq): data['id'] = iq['id'] data.send() return iq = iq.reply() iq.append(data) iq.send() def _handle_bob(self, stanza): self.api['set_bob'](stanza['from'], None, stanza['to'], args=stanza['bob']) self.xmpp.event('bob', stanza) # ================================================================= def _set_bob(self, jid, node, ifrom, bob): self._cids[bob['cid']] = bob def _get_bob(self, jid, node, ifrom, cid): if cid in self._cids: return self._cids[cid] raise XMPPError('item-not-found') def _del_bob(self, jid, node, ifrom, cid): if cid in self._cids: del self._cids[cid]