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:
parent
7b520ddc93
commit
656bea30dd
1 changed files with 175 additions and 109 deletions
|
|
@ -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 []
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue