plugin upload, XEP-0363: splitted fileUpload in fileUpload + upload:
fileUpload is used by external frontends, while upload can be used by frontends. upload return in addition to the progress_id a download_d Deferred which fire with URI when file is uploaded.
changed option ignore-tls-errors to ignore_tls_errors.
This commit is contained in:
parent
333a43e824
commit
94ec775019
2 changed files with 58 additions and 25 deletions
|
|
@ -41,7 +41,7 @@ PLUGIN_INFO = {
|
|||
|
||||
UPLOADING = D_(u'Please select a file to upload')
|
||||
UPLOADING_TITLE = D_(u'File upload')
|
||||
BOOL_OPTIONS = ('ignore-tls-errors',)
|
||||
BOOL_OPTIONS = ('ignore_tls_errors',)
|
||||
|
||||
|
||||
class UploadPlugin(object):
|
||||
|
|
@ -54,6 +54,7 @@ class UploadPlugin(object):
|
|||
self._upload_callbacks = []
|
||||
|
||||
def _fileUpload(self, filepath, filename, upload_jid_s='', options=None, profile=C.PROF_KEY_NONE):
|
||||
client = self.host.getClient(profile)
|
||||
upload_jid = jid.JID(upload_jid_s) if upload_jid_s else None
|
||||
if options is None:
|
||||
options = {}
|
||||
|
|
@ -64,10 +65,31 @@ class UploadPlugin(object):
|
|||
except KeyError:
|
||||
pass
|
||||
|
||||
return self.fileUpload(filepath, filename or None, upload_jid, options or None, profile)
|
||||
return self.fileUpload(client, filepath, filename or None, upload_jid, options or None)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def fileUpload(self, filepath, filename, upload_jid, options, profile=C.PROF_KEY_NONE):
|
||||
def fileUpload(self, client, filepath, filename, upload_jid, options):
|
||||
"""Send a file using best available method
|
||||
|
||||
parameters are the same as for [upload]
|
||||
@return (dict): action dictionary, with progress id in case of success, else xmlui message
|
||||
"""
|
||||
def uploadCb(data):
|
||||
progress_id, dummy = data
|
||||
return {'progress': progress_id}
|
||||
|
||||
def uploadEb(fail):
|
||||
msg = unicode(fail)
|
||||
log.warning(msg)
|
||||
return {'xmlui': xml_tools.note(u"Can't upload file", msg, C.XMLUI_DATA_LVL_WARNING).toXml()}
|
||||
|
||||
d = self.upload(filepath, filename, upload_jid, options, client.profile)
|
||||
d.addCallback(uploadCb)
|
||||
d.addErrback(uploadEb)
|
||||
return d
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def upload(self, client, filepath, filename=None, upload_jid=None, options=None):
|
||||
"""Send a file using best available method
|
||||
|
||||
@param filepath(str): absolute path to the file
|
||||
|
|
@ -76,26 +98,28 @@ class UploadPlugin(object):
|
|||
@param upload_jid(jid.JID, None): upload capable entity jid,
|
||||
or None to use autodetected, if possible
|
||||
@param options(dict): option to use for the upload, may be:
|
||||
- ignore-tls-errors(bool): True to ignore SSL/TLS certificate verification
|
||||
- ignore_tls_errors(bool): True to ignore SSL/TLS certificate verification
|
||||
used only if HTTPS transport is needed
|
||||
@param profile: %(doc_profile)s
|
||||
@return (dict): action dictionary, with progress id in case of success, else xmlui message
|
||||
@return (tuple[unicode,D(unicode)]): progress_id and a Deferred which fire download URL
|
||||
when upload is finished
|
||||
"""
|
||||
if options is None:
|
||||
options = {}
|
||||
if not os.path.isfile(filepath):
|
||||
raise exceptions.DataError(u"The given path doesn't link to a file")
|
||||
for method_name, available_cb, upload_cb, priority in self._upload_callbacks:
|
||||
try:
|
||||
upload_jid = yield available_cb(upload_jid, profile)
|
||||
upload_jid = yield available_cb(upload_jid, client.profile)
|
||||
except exceptions.NotFound:
|
||||
continue # no entity managing this extension found
|
||||
log.info(u"{name} method will be used to upload the file".format(name=method_name))
|
||||
progress_id = yield defer.maybeDeferred(upload_cb, filepath, filename, upload_jid, options, profile)
|
||||
defer.returnValue({'progress': progress_id})
|
||||
|
||||
# if we reach this point, no entity handling any known upload method has been found
|
||||
msg = u"Can't find any method to upload a file"
|
||||
log.warning(msg)
|
||||
defer.returnValue({'xmlui': xml_tools.note(u"Can't upload file", msg, C.XMLUI_DATA_LVL_WARNING).toXml()})
|
||||
log.info(u"{name} method will be used to upload the file".format(name=method_name))
|
||||
progress_id_d, download_d = yield defer.maybeDeferred(upload_cb, filepath, filename, upload_jid, options, client.profile)
|
||||
progress_id = yield progress_id_d
|
||||
defer.returnValue((progress_id, download_d))
|
||||
|
||||
raise exceptions.NotFound(u"Can't find any method to upload a file")
|
||||
|
||||
def register(self, method_name, available_cb, upload_cb, priority=0):
|
||||
"""Register a fileUploading method
|
||||
|
|
@ -105,7 +129,10 @@ class UploadPlugin(object):
|
|||
the callback must take two arguments: upload_jid (can be None) and profile
|
||||
the callback must return the first entity found (being upload_jid or one of its components)
|
||||
exceptions.NotFound must be raised if no entity has been found
|
||||
@param upload_cb(callable): method to upload a file (must have the same signature as [fileUpload])
|
||||
@param upload_cb(callable): method to upload a file
|
||||
must have the same signature as [fileUpload]
|
||||
must return a tuple with progress_id and a Deferred which fire download URL when
|
||||
upload is finished
|
||||
@param priority(int): pririoty of this method, the higher available will be used
|
||||
"""
|
||||
assert method_name
|
||||
|
|
@ -113,7 +140,7 @@ class UploadPlugin(object):
|
|||
if method_name == data[0]:
|
||||
raise exceptions.ConflictError(u'A method with this name is already registered')
|
||||
self._upload_callbacks.append((method_name, available_cb, upload_cb, priority))
|
||||
self._upload_callbacks.sort(key=lambda data: data[2], reverse=True)
|
||||
self._upload_callbacks.sort(key=lambda data: data[3], reverse=True)
|
||||
|
||||
def unregister(self, method_name):
|
||||
for idx, data in enumerate(self._upload_callbacks):
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ class XEP_0363(object):
|
|||
|
||||
def _fileHTTPUpload(self, filepath, filename='', upload_jid='', ignore_tls_errors=False, profile=C.PROF_KEY_NONE):
|
||||
assert os.path.isabs(filepath) and os.path.isfile(filepath)
|
||||
return self.fileHTTPUpload(filepath, filename or None, jid.JID(upload_jid) if upload_jid else None, {'ignore-tls-errors': ignore_tls_errors}, profile)
|
||||
progress_id_d, dummy = self.fileHTTPUpload(filepath, filename or None, jid.JID(upload_jid) if upload_jid else None, {'ignore_tls_errors': ignore_tls_errors}, profile)
|
||||
return progress_id_d
|
||||
|
||||
def fileHTTPUpload(self, filepath, filename=None, upload_jid=None, options=None, profile=C.PROF_KEY_NONE):
|
||||
"""upload a file through HTTP
|
||||
|
|
@ -136,29 +137,32 @@ class XEP_0363(object):
|
|||
@param options(dict): options where key can be:
|
||||
- ignore_tls_errors(bool): if True, SSL certificate will not be checked
|
||||
@param profile: %(doc_profile)s
|
||||
@return (D(unicode)): progress id
|
||||
@return (D(tuple[D(unicode), D(unicode)])): progress id and Deferred which fire download URL
|
||||
"""
|
||||
if options is None:
|
||||
options = {}
|
||||
ignore_tls_errors = options.get('ignore-tls-errors', False)
|
||||
ignore_tls_errors = options.get('ignore_tls_errors', False)
|
||||
client = self.host.getClient(profile)
|
||||
filename = filename or os.path.basename(filepath)
|
||||
size = os.path.getsize(filepath)
|
||||
progress_id_d = defer.Deferred()
|
||||
download_d = defer.Deferred()
|
||||
d = self.getSlot(client, filename, size, upload_jid=upload_jid)
|
||||
d.addCallbacks(self._getSlotCb, self._getSlotEb, (client, progress_id_d, filepath, size, ignore_tls_errors), None, (client, progress_id_d))
|
||||
return progress_id_d
|
||||
d.addCallbacks(self._getSlotCb, self._getSlotEb, (client, progress_id_d, download_d, filepath, size, ignore_tls_errors), None, (client, progress_id_d, download_d))
|
||||
return progress_id_d, download_d
|
||||
|
||||
def _getSlotEb(self, fail, client, progress_id_d):
|
||||
def _getSlotEb(self, fail, client, progress_id_d, download_d):
|
||||
"""an error happened while trying to get slot"""
|
||||
log.warning(u"Can't get upload slot: {reason}".format(reason=fail.value))
|
||||
progress_id_d.errback(fail)
|
||||
download_d.errback(fail)
|
||||
|
||||
def _getSlotCb(self, slot, client, progress_id_d, path, size, ignore_tls_errors=False):
|
||||
def _getSlotCb(self, slot, client, progress_id_d, download_d, path, size, ignore_tls_errors=False):
|
||||
"""Called when slot is received, try to do the upload
|
||||
|
||||
@param slot(Slot): slot instance with the get and put urls
|
||||
@param progress_id_d(defer.Deferred): Deferred to call when progress_id is known
|
||||
@param progress_id_d(defer.Deferred): Deferred to call with URL when upload is done
|
||||
@param path(str): path to the file to upload
|
||||
@param size(int): size of the file to upload
|
||||
@param ignore_tls_errors(bool): ignore TLS certificate is True
|
||||
|
|
@ -173,10 +177,10 @@ class XEP_0363(object):
|
|||
else:
|
||||
agent = http_client.Agent(reactor)
|
||||
d = agent.request('PUT', slot.put.encode('utf-8'), http_headers.Headers({'User-Agent': [C.APP_NAME.encode('utf-8')]}), file_producer)
|
||||
d.addCallbacks(self._uploadCb, self._uploadEb, (sat_file, slot), None, (sat_file,))
|
||||
d.addCallbacks(self._uploadCb, self._uploadEb, (sat_file, slot, download_d), None, (sat_file, download_d))
|
||||
return d
|
||||
|
||||
def _uploadCb(self, dummy, sat_file, slot):
|
||||
def _uploadCb(self, dummy, sat_file, slot, download_d):
|
||||
"""Called once file is successfully uploaded
|
||||
|
||||
@param sat_file(SatFile): file used for the upload
|
||||
|
|
@ -185,13 +189,15 @@ class XEP_0363(object):
|
|||
"""
|
||||
log.info(u"HTTP upload finished")
|
||||
sat_file.progressFinished({'url': slot.get})
|
||||
download_d.callback(slot.get)
|
||||
|
||||
def _uploadEb(self, fail, sat_file):
|
||||
def _uploadEb(self, fail, sat_file, download_d):
|
||||
"""Called on unsuccessful upload
|
||||
|
||||
@param sat_file(SatFile): file used for the upload
|
||||
should be closed, be is needed to send the progressError signal
|
||||
"""
|
||||
download_d.errback(fail)
|
||||
try:
|
||||
wrapped_fail = fail.value.reasons[0]
|
||||
except (AttributeError, IndexError):
|
||||
|
|
|
|||
Loading…
Reference in a new issue