SàT: multi-profile, plugins updated

- core: 2 new convenient methods: getJidNStream and getClient
- new param in plugin info: "handler" to know if there is a handler to plug on profiles clients
- plugins with handler now use an other class which is returned to profile client with the new method "getHandler" and pluged when connecting
This commit is contained in:
Goffi 2010-01-30 16:17:33 +11:00
commit 656bea30dd

View file

@ -22,7 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from logging import debug, info, error
from twisted.words.xish import domish
from twisted.internet import protocol
from twisted.words.protocols.jabber import client, jid, xmlstream
from twisted.words.protocols.jabber import client, jid
from twisted.words.protocols.jabber import error as jab_error
import os.path
from twisted.internet import reactor #FIXME best way ???
@ -48,29 +48,22 @@ PLUGIN_INFO = {
"protocols": ["XEP-0096"],
"dependencies": ["XEP_0065"],
"main": "XEP_0096",
"handler": "yes",
"description": """Implementation of SI File Transfert"""
}
class XEP_0096(XMPPHandler):
implements(iwokkel.IDisco)
class XEP_0096():
def __init__(self, host):
info("Plugin XEP_0096 initialization")
self.host = host
self._waiting_for_approval = {}
host.bridge.addMethod("sendFile", ".communication", in_sign='ss', out_sign='s', method=self.sendFile)
host.bridge.addMethod("sendFile", ".communication", in_sign='sss', out_sign='s', method=self.sendFile)
def connectionInitialized(self):
self.xmlstream.addObserver(SI_REQUEST, self.xep_96)
def getHandler(self):
return XEP_0096_handler(self)
def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
return [disco.DiscoFeature(NS_SI)]
def getDiscoItems(self, requestor, target, nodeIdentifier=''):
return []
def xep_96(self, IQ):
def xep_96(self, IQ, profile):
info ("XEP-0096 management")
IQ.handled=True
SI_elem = IQ.firstChildElement()
@ -84,7 +77,7 @@ class XEP_0096(XMPPHandler):
file_size = element["size"]
elif element.name == "feature":
from_jid = IQ["from"]
self._waiting_for_approval[IQ["id"]] = (element, from_jid, file_size)
self._waiting_for_approval[IQ["id"]] = (element, from_jid, file_size, profile)
data={ "filename":filename, "from":from_jid, "size":file_size }
self.host.askConfirmation(IQ["id"], "FILE_TRANSFERT", data, self.confirmationCB)
@ -106,13 +99,15 @@ class XEP_0096(XMPPHandler):
error ("Approved unknow id !")
#TODO: manage this (maybe approved by several frontends)
else:
element, from_id, size = self._waiting_for_approval[id]
element, from_id, size, profile = self._waiting_for_approval[id]
del(self._waiting_for_approval[id])
self.negociate(element, id, from_id)
self.negociate(element, id, from_id, profile)
def negociate(self, feat_elem, id, to_jid):
def negociate(self, feat_elem, id, to_jid, profile):
#TODO: put this in a plugin
#FIXME: over ultra mega ugly, need to be generic
client = self.host.getClient(profile)
assert(client)
info ("Feature negociation")
data = feat_elem.firstChildElement()
field = data.firstChildElement()
@ -134,40 +129,41 @@ class XEP_0096(XMPPHandler):
field['var'] = 'stream-method'
value = field.addElement('value')
value.addContent('http://jabber.org/protocol/bytestreams')
self.host.xmlstream.send(result)
client.xmlstream.send(result)
def fileCB(self, answer):
def fileCB(self, answer, xmlstream, current_jid):
if answer['type']=="result": #FIXME FIXME FIXME ugly ugly ugly ! and temp FIXME FIXME FIXME
info("SENDING UGLY ANSWER")
offer=client.IQ(self.host.xmlstream,'set')
offer["from"]=self.host.me.full()
offer=client.IQ(xmlstream,'set')
offer["from"]=current_jid.full()
offer["to"]=answer['from']
query=offer.addElement('query', 'http://jabber.org/protocol/bytestreams')
query['mode']='tcp'
streamhost=query.addElement('streamhost')
streamhost['host']=self.host.memory.getParamA("IP", "File Transfert")
streamhost['port']=self.host.memory.getParamA("Port", "File Transfert")
streamhost['jid']=self.host.me.full()
streamhost['jid']=current_jid.full()
offer.send()
def sendFile(self, to, filepath):
def sendFile(self, to, filepath, profile_key='@DEFAULT@'):
"""send a file using XEP-0096
Return an unique id to identify the transfert
"""
current_jid, xmlstream = self.host.getJidNStream(profile_key)
if not xmlstream:
error ('Asking profile for an non-existant or not connected profile')
return ""
debug ("sendfile (%s) to %s", filepath, to )
print type(filepath), type(to)
statinfo = os.stat(filepath)
offer=client.IQ(self.host.xmlstream,'set')
offer=client.IQ(xmlstream,'set')
debug ("Transfert ID: %s", offer["id"])
self.host.plugins["XEP_0065"].sendFile(offer["id"], filepath, str(statinfo.st_size))
offer["from"]=self.host.me.full()
offer["from"]=current_jid.full()
offer["to"]=jid.JID(to).full()
si=offer.addElement('si','http://jabber.org/protocol/si')
si["mime-type"]='text/plain'
@ -190,7 +186,23 @@ class XEP_0096(XMPPHandler):
option = field.addElement('option')
value = option.addElement('value', content='http://jabber.org/protocol/bytestreams')
offer.addCallback(self.fileCB)
offer.addCallback(self.fileCB, current_jid = current_jid, xmlstream = xmlstream)
offer.send()
return offer["id"] #XXX: using IQ id as file transfert id seems OK as IQ id are required
class XEP_0096_handler(XMPPHandler):
implements(iwokkel.IDisco)
def __init__(self, plugin_parent):
self.plugin_parent = plugin_parent
self.host = plugin_parent.host
def connectionInitialized(self):
self.xmlstream.addObserver(SI_REQUEST, self.plugin_parent.xep_96, profile = self.parent.profile)
def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
return [disco.DiscoFeature(NS_SI)]
def getDiscoItems(self, requestor, target, nodeIdentifier=''):
return []