Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Melcer <liori@exroot.org>2006-07-15 17:27:57 +0400
committerTomasz Melcer <liori@exroot.org>2006-07-15 17:27:57 +0400
commit477f33b6b9546dd10c4c97309cead970da49891f (patch)
treede22fec99f81543c29b54cad8275b7448c77f186
parent76c7831c496340fa00ac56ade53f94ea6b8a6f54 (diff)
Generic support for exposing commands (untested).
-rw-r--r--src/common/connection_handlers.py159
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)