Mercurial > libervia-backend
comparison 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 |
comparison
equal
deleted
inserted
replaced
1823:1424cc6f8e98 | 1824:a19161bb3ff7 |
---|---|
39 } | 39 } |
40 | 40 |
41 | 41 |
42 UPLOADING = D_(u'Please select a file to upload') | 42 UPLOADING = D_(u'Please select a file to upload') |
43 UPLOADING_TITLE = D_(u'File upload') | 43 UPLOADING_TITLE = D_(u'File upload') |
44 BOOL_OPTIONS = ('ignore-tls-errors',) | 44 BOOL_OPTIONS = ('ignore_tls_errors',) |
45 | 45 |
46 | 46 |
47 class UploadPlugin(object): | 47 class UploadPlugin(object): |
48 # TODO: plugin unload | 48 # TODO: plugin unload |
49 | 49 |
52 self.host = host | 52 self.host = host |
53 host.bridge.addMethod("fileUpload", ".plugin", in_sign='sssa{ss}s', out_sign='a{ss}', method=self._fileUpload, async=True) | 53 host.bridge.addMethod("fileUpload", ".plugin", in_sign='sssa{ss}s', out_sign='a{ss}', method=self._fileUpload, async=True) |
54 self._upload_callbacks = [] | 54 self._upload_callbacks = [] |
55 | 55 |
56 def _fileUpload(self, filepath, filename, upload_jid_s='', options=None, profile=C.PROF_KEY_NONE): | 56 def _fileUpload(self, filepath, filename, upload_jid_s='', options=None, profile=C.PROF_KEY_NONE): |
57 client = self.host.getClient(profile) | |
57 upload_jid = jid.JID(upload_jid_s) if upload_jid_s else None | 58 upload_jid = jid.JID(upload_jid_s) if upload_jid_s else None |
58 if options is None: | 59 if options is None: |
59 options = {} | 60 options = {} |
60 # we convert values that are well-known booleans | 61 # we convert values that are well-known booleans |
61 for bool_option in BOOL_OPTIONS: | 62 for bool_option in BOOL_OPTIONS: |
62 try: | 63 try: |
63 options[bool_option] = C.bool(options[bool_option]) | 64 options[bool_option] = C.bool(options[bool_option]) |
64 except KeyError: | 65 except KeyError: |
65 pass | 66 pass |
66 | 67 |
67 return self.fileUpload(filepath, filename or None, upload_jid, options or None, profile) | 68 return self.fileUpload(client, filepath, filename or None, upload_jid, options or None) |
68 | 69 |
69 @defer.inlineCallbacks | 70 @defer.inlineCallbacks |
70 def fileUpload(self, filepath, filename, upload_jid, options, profile=C.PROF_KEY_NONE): | 71 def fileUpload(self, client, filepath, filename, upload_jid, options): |
72 """Send a file using best available method | |
73 | |
74 parameters are the same as for [upload] | |
75 @return (dict): action dictionary, with progress id in case of success, else xmlui message | |
76 """ | |
77 def uploadCb(data): | |
78 progress_id, dummy = data | |
79 return {'progress': progress_id} | |
80 | |
81 def uploadEb(fail): | |
82 msg = unicode(fail) | |
83 log.warning(msg) | |
84 return {'xmlui': xml_tools.note(u"Can't upload file", msg, C.XMLUI_DATA_LVL_WARNING).toXml()} | |
85 | |
86 d = self.upload(filepath, filename, upload_jid, options, client.profile) | |
87 d.addCallback(uploadCb) | |
88 d.addErrback(uploadEb) | |
89 return d | |
90 | |
91 @defer.inlineCallbacks | |
92 def upload(self, client, filepath, filename=None, upload_jid=None, options=None): | |
71 """Send a file using best available method | 93 """Send a file using best available method |
72 | 94 |
73 @param filepath(str): absolute path to the file | 95 @param filepath(str): absolute path to the file |
74 @param filename(None, unicode): name to use for the upload | 96 @param filename(None, unicode): name to use for the upload |
75 None to use basename of the path | 97 None to use basename of the path |
76 @param upload_jid(jid.JID, None): upload capable entity jid, | 98 @param upload_jid(jid.JID, None): upload capable entity jid, |
77 or None to use autodetected, if possible | 99 or None to use autodetected, if possible |
78 @param options(dict): option to use for the upload, may be: | 100 @param options(dict): option to use for the upload, may be: |
79 - ignore-tls-errors(bool): True to ignore SSL/TLS certificate verification | 101 - ignore_tls_errors(bool): True to ignore SSL/TLS certificate verification |
80 used only if HTTPS transport is needed | 102 used only if HTTPS transport is needed |
81 @param profile: %(doc_profile)s | 103 @param profile: %(doc_profile)s |
82 @return (dict): action dictionary, with progress id in case of success, else xmlui message | 104 @return (tuple[unicode,D(unicode)]): progress_id and a Deferred which fire download URL |
105 when upload is finished | |
83 """ | 106 """ |
107 if options is None: | |
108 options = {} | |
84 if not os.path.isfile(filepath): | 109 if not os.path.isfile(filepath): |
85 raise exceptions.DataError(u"The given path doesn't link to a file") | 110 raise exceptions.DataError(u"The given path doesn't link to a file") |
86 for method_name, available_cb, upload_cb, priority in self._upload_callbacks: | 111 for method_name, available_cb, upload_cb, priority in self._upload_callbacks: |
87 try: | 112 try: |
88 upload_jid = yield available_cb(upload_jid, profile) | 113 upload_jid = yield available_cb(upload_jid, client.profile) |
89 except exceptions.NotFound: | 114 except exceptions.NotFound: |
90 continue # no entity managing this extension found | 115 continue # no entity managing this extension found |
116 | |
91 log.info(u"{name} method will be used to upload the file".format(name=method_name)) | 117 log.info(u"{name} method will be used to upload the file".format(name=method_name)) |
92 progress_id = yield defer.maybeDeferred(upload_cb, filepath, filename, upload_jid, options, profile) | 118 progress_id_d, download_d = yield defer.maybeDeferred(upload_cb, filepath, filename, upload_jid, options, client.profile) |
93 defer.returnValue({'progress': progress_id}) | 119 progress_id = yield progress_id_d |
120 defer.returnValue((progress_id, download_d)) | |
94 | 121 |
95 # if we reach this point, no entity handling any known upload method has been found | 122 raise exceptions.NotFound(u"Can't find any method to upload a file") |
96 msg = u"Can't find any method to upload a file" | |
97 log.warning(msg) | |
98 defer.returnValue({'xmlui': xml_tools.note(u"Can't upload file", msg, C.XMLUI_DATA_LVL_WARNING).toXml()}) | |
99 | 123 |
100 def register(self, method_name, available_cb, upload_cb, priority=0): | 124 def register(self, method_name, available_cb, upload_cb, priority=0): |
101 """Register a fileUploading method | 125 """Register a fileUploading method |
102 | 126 |
103 @param method_name(unicode): short name for the method, must be unique | 127 @param method_name(unicode): short name for the method, must be unique |
104 @param available_cb(callable): method to call to check if this method is usable | 128 @param available_cb(callable): method to call to check if this method is usable |
105 the callback must take two arguments: upload_jid (can be None) and profile | 129 the callback must take two arguments: upload_jid (can be None) and profile |
106 the callback must return the first entity found (being upload_jid or one of its components) | 130 the callback must return the first entity found (being upload_jid or one of its components) |
107 exceptions.NotFound must be raised if no entity has been found | 131 exceptions.NotFound must be raised if no entity has been found |
108 @param upload_cb(callable): method to upload a file (must have the same signature as [fileUpload]) | 132 @param upload_cb(callable): method to upload a file |
133 must have the same signature as [fileUpload] | |
134 must return a tuple with progress_id and a Deferred which fire download URL when | |
135 upload is finished | |
109 @param priority(int): pririoty of this method, the higher available will be used | 136 @param priority(int): pririoty of this method, the higher available will be used |
110 """ | 137 """ |
111 assert method_name | 138 assert method_name |
112 for data in self._upload_callbacks: | 139 for data in self._upload_callbacks: |
113 if method_name == data[0]: | 140 if method_name == data[0]: |
114 raise exceptions.ConflictError(u'A method with this name is already registered') | 141 raise exceptions.ConflictError(u'A method with this name is already registered') |
115 self._upload_callbacks.append((method_name, available_cb, upload_cb, priority)) | 142 self._upload_callbacks.append((method_name, available_cb, upload_cb, priority)) |
116 self._upload_callbacks.sort(key=lambda data: data[2], reverse=True) | 143 self._upload_callbacks.sort(key=lambda data: data[3], reverse=True) |
117 | 144 |
118 def unregister(self, method_name): | 145 def unregister(self, method_name): |
119 for idx, data in enumerate(self._upload_callbacks): | 146 for idx, data in enumerate(self._upload_callbacks): |
120 if data[0] == method_name: | 147 if data[0] == method_name: |
121 del [idx] | 148 del [idx] |