Mercurial > libervia-backend
diff src/plugins/plugin_xep_0096.py @ 538:2c4016921403
core, frontends, bridgen plugins: fixed methods which were unproperly managing multi-profiles
- added profile argument to askConfirmation, actionResult, actionResultExt, entityDataUpdated, confirmationAnswer, getProgress
- core, frontends: fixed calls/signals according to new bridge API
- user of proper profile namespace for progression indicators and dialogs
- memory: getParam* now return bool when param type is bool
- memory: added getStringParam* to return string instead of typed value
- core, memory, storage, quick_frontend: getHistory now manage properly multi-profiles
- plugins XEP-0047, XEP-0054, XEP-0065, XEP-0077, XEP-0096; multi-profiles proper handling
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 10 Nov 2012 16:38:16 +0100 |
parents | a31abb97310d |
children | 47e45a577ab7 |
line wrap: on
line diff
--- a/src/plugins/plugin_xep_0096.py Sun Nov 04 23:53:26 2012 +0100 +++ b/src/plugins/plugin_xep_0096.py Sat Nov 10 16:38:16 2012 +0100 @@ -21,16 +21,14 @@ from logging import debug, info, warning, error from twisted.words.xish import domish -from twisted.internet import protocol -from twisted.words.protocols.jabber import client, jid +from twisted.words.protocols.jabber import jid from twisted.words.protocols.jabber import error as jab_error import os, os.path from twisted.internet import reactor -import pdb +from sat.core.exceptions import ProfileNotInCacheError -from zope.interface import implements -from wokkel import disco, iwokkel, data_form +from wokkel import data_form IQ_SET = '/iq[@type="set"]' PROFILE_NAME = "file-transfer" @@ -52,19 +50,23 @@ def __init__(self, host): info(_("Plugin XEP_0096 initialization")) self.host = host - self._waiting_for_approval = {} #key = id, value = [transfer data, IdelayedCall Reactor timeout, - # current stream method, [failed stream methods], profile] - self.managed_stream_m = [self.host.plugins["XEP-0065"].NAMESPACE, + self.managed_stream_m = [#self.host.plugins["XEP-0065"].NAMESPACE, self.host.plugins["XEP-0047"].NAMESPACE] #Stream methods managed self.host.plugins["XEP-0095"].registerSIProfile(PROFILE_NAME, self.transferRequest) host.bridge.addMethod("sendFile", ".plugin", in_sign='ssa{ss}s', out_sign='s', method=self.sendFile) - def _kill_id(self, approval_id): + def profileConnected(self, profile): + client = self.host.getClient(profile) + client._xep_0096_waiting_for_approval = {} #key = id, value = [transfer data, IdelayedCall Reactor timeout, + # current stream method, [failed stream methods], profile] + + def _kill_id(self, approval_id, profile): """Delete a waiting_for_approval id, called after timeout - @param approval_id: id of _waiting_for_approval""" + @param approval_id: id of _xep_0096_waiting_for_approval""" info(_("SI File Transfer: TimeOut reached for id %s") % approval_id); try: - del self._waiting_for_approval[approval_id] + client = self.host.getClient(profile) + del client._xep_0096_waiting_for_approval[approval_id] except KeyError: warning(_("kill id called on a non existant approval id")) @@ -78,6 +80,9 @@ @param profile: %(doc_profile)s""" info (_("XEP-0096 file transfer requested")) debug(si_el.toXml()) + client = self.host.getClient(profile) + if not client: + raise ProfileNotInCacheError filename = "" file_size = "" file_date = None @@ -124,9 +129,9 @@ #if we are here, the transfer can start, we just need user's agreement data={ "filename":filename, "id": iq_id, "from":from_jid, "size":file_size, "date":file_date, "hash":file_hash, "desc":file_desc, "can_range": str(can_range) } - self._waiting_for_approval[si_id] = [data, reactor.callLater(300, self._kill_id, si_id), stream_method, [], profile] + client._xep_0096_waiting_for_approval[si_id] = [data, reactor.callLater(300, self._kill_id, si_id, profile), stream_method, []] - self.host.askConfirmation(si_id, "FILE_TRANSFER", data, self.confirmationCB) + self.host.askConfirmation(si_id, "FILE_TRANSFER", data, self.confirmationCB, profile) def _getFileObject(self, dest_path, can_range = False): @@ -136,12 +141,15 @@ @return: File Object""" return open(dest_path, "ab" if can_range else "wb") - def confirmationCB(self, sid, accepted, frontend_data): + def confirmationCB(self, sid, accepted, frontend_data, profile): """Called on confirmation answer @param sid: file transfer session id @param accepted: True if file transfer is accepted @param frontend_data: data sent by frontend""" - data, timeout, stream_method, failed_methods, profile = self._waiting_for_approval[sid] + client = self.host.getClient(profile) + if not client: + raise ProfileNotInCacheError + data, timeout, stream_method, failed_methods = client._xep_0096_waiting_for_approval[sid] can_range = data['can_range'] == "True" range_offset = 0 if accepted: @@ -151,19 +159,19 @@ dest_path = frontend_data['dest_path'] except KeyError: error(_('dest path not found in frontend_data')) - del(self._waiting_for_approval[sid]) + del(client._xep_0096_waiting_for_approval[sid]) return if stream_method == self.host.plugins["XEP-0065"].NAMESPACE: file_obj = self._getFileObject(dest_path, can_range) range_offset = file_obj.tell() - self.host.plugins["XEP-0065"].prepareToReceive(jid.JID(data['from']), sid, file_obj, int(data["size"]), self._transferSucceeded, self._transferFailed) + self.host.plugins["XEP-0065"].prepareToReceive(jid.JID(data['from']), sid, file_obj, int(data["size"]), self._transferSucceeded, self._transferFailed, profile) elif stream_method == self.host.plugins["XEP-0047"].NAMESPACE: file_obj = self._getFileObject(dest_path, can_range) range_offset = file_obj.tell() - self.host.plugins["XEP-0047"].prepareToReceive(jid.JID(data['from']), sid, file_obj, int(data["size"]), self._transferSucceeded, self._transferFailed) + self.host.plugins["XEP-0047"].prepareToReceive(jid.JID(data['from']), sid, file_obj, int(data["size"]), self._transferSucceeded, self._transferFailed, profile) else: error(_("Unknown stream method, this should not happen at this stage, cancelling transfer")) - del(self._waiting_for_approval[sid]) + del(client._xep_0096_waiting_for_approval[sid]) return #we can send the iq result @@ -179,30 +187,37 @@ else: debug (_("Transfer [%s] refused"), sid) self.host.plugins["XEP-0095"].sendRejectedError (data["id"], data['from'], profile=profile) - del(self._waiting_for_approval[sid]) + del(client._xep_0096_waiting_for_approval[sid]) - def _transferSucceeded(self, sid, file_obj, stream_method): + def _transferSucceeded(self, sid, file_obj, stream_method, profile): """Called by the stream method when transfer successfuly finished @param id: stream id""" + client = self.host.getClient(profile) + if not client: + raise ProfileNotInCacheError file_obj.close() info(_('Transfer %s successfuly finished') % sid) - del(self._waiting_for_approval[sid]) + del(client._xep_0096_waiting_for_approval[sid]) - def _transferFailed(self, sid, file_obj, stream_method, reason): + def _transferFailed(self, sid, file_obj, stream_method, reason, profile): """Called when something went wrong with the transfer @param id: stream id @param reason: can be TIMEOUT, IO_ERROR, PROTOCOL_ERROR""" - data, timeout, stream_method, failed_methods, profile = self._waiting_for_approval[sid] - warning(_('Transfer %(id)s failed with stream method %(s_method)s') % { 'id': sid, - 's_method': stream_method }) + client = self.host.getClient(profile) + if not client: + raise ProfileNotInCacheError + data, timeout, stream_method, failed_methods = client._xep_0096_waiting_for_approval[sid] + warning(_('Transfer %(id)s failed with stream method %(s_method)s: %(reason)s') % { 'id': sid, + 's_method': stream_method, + 'reason': reason}) filepath = file_obj.name file_obj.close() os.remove(filepath) #TODO: session remenber (within a time limit) when a stream method fail, and avoid that stream method with full jid for the rest of the session warning(_("All stream methods failed, can't transfer the file")) - del(self._waiting_for_approval[sid]) + del(client._xep_0096_waiting_for_approval[sid]) - def fileCb(self, profile, filepath, sid, size, IQ): + def fileCb(self, filepath, sid, size, profile, IQ): if IQ['type'] == "error": stanza_err = jab_error.exceptionFromStanza(IQ) if stanza_err.code == '403' and stanza_err.condition == 'forbidden': @@ -252,7 +267,7 @@ else: warning(_("Invalid stream method received")) - def sendFile(self, to_jid, filepath, data={}, profile_key='@DEFAULT@'): + def sendFile(self, to_jid, filepath, data={}, profile_key='@NONE@'): """send a file using XEP-0096 @to_jid: recipient @filepath: absolute path to the file to send @@ -278,13 +293,13 @@ file_transfer_elts.append(domish.Element((None,'range'))) sid, offer = self.host.plugins["XEP-0095"].proposeStream(jid.JID(to_jid), PROFILE, feature_elt, file_transfer_elts, profile_key = profile) - offer.addCallback(self.fileCb, profile, filepath, sid, size) + offer.addCallback(self.fileCb, filepath, sid, size, profile) return sid - def sendSuccessCb(self, sid, file_obj, stream_method): - info(_('Transfer %s successfuly finished') % sid) + def sendSuccessCb(self, sid, file_obj, stream_method, profile): + info(_('Transfer %s successfuly finished [%s]') % (sid, profile)) file_obj.close() - def sendFailureCb(self, sid, file_obj, stream_method, reason): + def sendFailureCb(self, sid, file_obj, stream_method, reason, profile): file_obj.close() - warning(_('Transfer %(id)s failed with stream method %(s_method)s') % { 'id': sid, "s_method": stream_method }) + warning(_('Transfer %(id)s failed with stream method %(s_method)s: %(reason)s [%(profile)s') % { 'id': sid, "s_method": stream_method, 'reason': reason, 'profile': profile })