diff options
author | Tomasz Melcer <liori@exroot.org> | 2006-07-15 17:27:57 +0400 |
---|---|---|
committer | Tomasz Melcer <liori@exroot.org> | 2006-07-15 17:27:57 +0400 |
commit | 477f33b6b9546dd10c4c97309cead970da49891f (patch) | |
tree | de22fec99f81543c29b54cad8275b7448c77f186 | |
parent | 76c7831c496340fa00ac56ade53f94ea6b8a6f54 (diff) |
Generic support for exposing commands (untested).
-rw-r--r-- | src/common/connection_handlers.py | 159 |
1 files changed, 147 insertions, 12 deletions
diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index e2e6cfef5..f52104e68 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -655,6 +655,10 @@ class ConnectionDisco: feature = common.xmpp.Node('feature') feature.setAttr('var', common.xmpp.NS_FILE) query.addChild(node=feature) + # exposing adhoc commands + feature = common.xmpp.Node('feature') + feature.setAttr('var', common.xmpp.NS_COMMANDS) + query.addChild(node=feature) self.connection.send(iq) raise common.xmpp.NodeProcessed @@ -692,19 +696,33 @@ class ConnectionDisco: else: self.dispatch('AGENT_INFO_ITEMS', (jid, node, items)) + def _DiscoverItemsGetCB(self, con, iq_obj): + gajim.log.debug('DiscoverItemsGetCB') + node = iq_obj.getTagAttr('query', 'node') + if node==common.xmpp.NS_COMMANDS: + self.commandListQuery(con, iq_obj) + raise common.xmpp.NodeProcessed + def _DiscoverInfoGetCB(self, con, iq_obj): gajim.log.debug('DiscoverInfoGetCB') - iq = iq_obj.buildReply('result') - q = iq.getTag('query') - q.addChild('identity', attrs = {'type': 'pc', - 'category': 'client', - 'name': 'Gajim'}) - q.addChild('feature', attrs = {'var': common.xmpp.NS_BYTESTREAM}) - q.addChild('feature', attrs = {'var': common.xmpp.NS_SI}) - q.addChild('feature', attrs = {'var': common.xmpp.NS_FILE}) - q.addChild('feature', attrs = {'var': common.xmpp.NS_MUC}) - self.connection.send(iq) - raise common.xmpp.NodeProcessed + q = iq_obj.getTag('query') + node = q.getAttr('node') + + if self.commandQuery(con, iq_obj): + raise NodeProcessed + + elif node is None: + iq = iq_obj.buildReply('result') + q = iq.getTag('query') + q.addChild('identity', attrs = {'type': 'pc', + 'category': 'client', + 'name': 'Gajim'}) + q.addChild('feature', attrs = {'var': common.xmpp.NS_BYTESTREAM}) + q.addChild('feature', attrs = {'var': common.xmpp.NS_SI}) + q.addChild('feature', attrs = {'var': common.xmpp.NS_FILE}) + q.addChild('feature', attrs = {'var': common.xmpp.NS_MUC}) + self.connection.send(iq) + raise common.xmpp.NodeProcessed def _DiscoverInfoErrorCB(self, con, iq_obj): gajim.log.debug('DiscoverInfoErrorCB') @@ -1036,11 +1054,124 @@ class ConnectionVcard: else: self.dispatch('VCARD', vcard) +class AdHocCommand: + commandnode = 'command' + commandname = 'The Command' + commandfeatures = (common.xmpp.NS_DATA,) + + @staticmethod + def isVisibleFor(jid): return True -class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco): +class ChangeStatusCommand(AdHocCommand): + commandnode = 'change-status' + commandname = 'Change status information' + def __init__(self, sessiondata): + pass + +class ConnectionCommands: + def __init__(self): + # a list of all commands exposed + self.__commands = {} + for cmdobj in (ChangeStatusCommand,): + self.__commands[cmdobj.commandnode] = cmdobj + + # a list of sessions; keys are tuples (jid, sessionid, node) + self.__sessions = {} + + def commandListQuery(self, con, iq_obj): + iq = iq_obj.buildReply('result') + jid = helpers.get_full_jid_from_iq(iq_obj) + q = iq.getTag('query') + + for node, cmd in self.__commands.iter_items(): + if cmd.isVisibleFor(jid): + q.addChild('item', { + 'jid': 'our-jid', + 'node': node, + 'name': cmd.commandname}) + + self.connection.send(iq) + + def commandQuery(self, con, iq_obj): + ''' Send disco result for query for command (JEP-0050, example 6.). + Return True if the result was sent, False if not. ''' + jid = helpers.get_full_jid_from_iq(iq_obj) + node = iq_obj.getTagAttr('query', 'node') + + if node not in self.__commands: return False + + cmd = self.__commands[node] + if cmd.isVisibleFor(jid): + iq = iq_obj.buildReply('result') + q = iq.getTag('query') + q.addChild('identity', attrs = {'type': 'command-node', + 'category': 'automation', + 'name': cmd.commandname}) + q.addChild('feature', attrs = {'var': common.xmpp.NS_COMMANDS}) + for feature in cmd.commandfeatures: + q.addChild('feature', attrs = {'var': feature}) + + self.connection.send(iq) + return True + + return False + + def _CommandExecuteCB(self, con, iq_obj): + jid = helpers.get_full_jid_from_iq(iq_obj) + + cmd = iq_obj.getTag('command') + if cmd is None: return + + node = cmd.getAttr('node') + if node is None: return + + sessionid = cmd.getAttr('sessionid') + if sessionid is None: + # we start a new command session... only if we are visible for the jid + newcmd = self.__commands[node] + if not newcmd.isVisibleFor(jid): + return + + # generate new sessionid + sessionid = self.connection.getAnID() + + # create new instance and run it + obj = newcmd(jid=jid, sessionid=sessionid) + rc = obj.execute() + if rc: + self.__sessions[(jid, sessionid, node)] = obj + raise NodeProcessed + else: + # the command is already running, check for it + magictuple = (jid, sessionid, node) + if magictuple not in self.__sessions: + # we don't have this session... ha! + return + + action = cmd.getAttr('action') + obj = self.__sessions[magictuple] + + if action == 'cancel': rc = obj.cancel(iq_obj) + elif action == 'prev': rc = obj.prev(iq_obj) + elif action == 'next': rc = obj.next(iq_obj) + elif action == 'execute': rc = obj.execute(iq_obj) + elif action == 'complete': rc = obj.complete(iq_obj) + else: + # action is wrong. stop the session, send error + del self.__sessions[magictuple] + return + + # delete the session if rc is False + if not rc: + del self.__sessions[magictuple] + + raise NodeProcessed + +class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, ConnectionCommands): def __init__(self): ConnectionVcard.__init__(self) ConnectionBytestream.__init__(self) + ConnectionCommands.__init__(self) # List of IDs we are waiting answers for {id: (type_of_request, data), } self.awaiting_answers = {} # List of IDs that will produce a timeout is answer doesn't arrive @@ -1785,12 +1916,16 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco) common.xmpp.NS_PRIVATE) con.RegisterHandler('iq', self._HttpAuthCB, 'get', common.xmpp.NS_HTTP_AUTH) + con.RegisterHandler('iq', self._CommandExecuteCB, 'set', + common.xmpp.NS_COMMANDS) con.RegisterHandler('iq', self._gMailNewMailCB, 'set', common.xmpp.NS_GMAILNOTIFY) con.RegisterHandler('iq', self._gMailQueryCB, 'result', common.xmpp.NS_GMAILNOTIFY) con.RegisterHandler('iq', self._DiscoverInfoGetCB, 'get', common.xmpp.NS_DISCO_INFO) + con.RegisterHandler('iq', self._DiscoverItemsGetCB, 'get', + common.xmpp.NS_DISCO_ITEMS) con.RegisterHandler('iq', self._ErrorCB, 'error') con.RegisterHandler('iq', self._IqCB) con.RegisterHandler('iq', self._StanzaArrivedCB) |