diff src/plugins/plugin_misc_upload.py @ 1824:a19161bb3ff7

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.
author Goffi <goffi@goffi.org>
date Fri, 22 Jan 2016 20:24:17 +0100
parents d17772b0fe22
children ff603003d40a
line wrap: on
line diff
--- a/src/plugins/plugin_misc_upload.py	Fri Jan 22 20:24:17 2016 +0100
+++ b/src/plugins/plugin_misc_upload.py	Fri Jan 22 20:24:17 2016 +0100
@@ -41,7 +41,7 @@
 
 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 @@
         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 @@
             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 @@
         @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 @@
            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 @@
             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):