diff options
author | lovetox <philipp@hoerist.com> | 2020-12-20 18:30:20 +0300 |
---|---|---|
committer | lovetox <philipp@hoerist.com> | 2020-12-20 18:35:11 +0300 |
commit | a290db02c14bc62b2148d49e6070600ea1987dcf (patch) | |
tree | 30bd336cfe8cf1d53d1bdbbee0674b8d056d2264 /gajim/common/modules/httpupload.py | |
parent | d54f28f938af2d655cf659ef942e5346ab5cc2f5 (diff) |
HTTPUpload: Separate transfer from sending message
Diffstat (limited to 'gajim/common/modules/httpupload.py')
-rw-r--r-- | gajim/common/modules/httpupload.py | 118 |
1 files changed, 56 insertions, 62 deletions
diff --git a/gajim/common/modules/httpupload.py b/gajim/common/modules/httpupload.py index 0b2783061..0d29d3012 100644 --- a/gajim/common/modules/httpupload.py +++ b/gajim/common/modules/httpupload.py @@ -35,8 +35,7 @@ from gajim.common.helpers import get_user_proxy from gajim.common.const import FTState from gajim.common.filetransfer import FileTransfer from gajim.common.modules.base import BaseModule -from gajim.common.structs import OutgoingMessage -from gajim.common.connection_handlers_events import InformationEvent +from gajim.common.exceptions import FileError class HTTPUpload(BaseModule): @@ -87,10 +86,9 @@ class HTTPUpload(BaseModule): for ctrl in app.interface.msg_win_mgr.get_controls(acct=self._account): ctrl.update_actions() - def check_file_before_transfer(self, path, encryption, contact, - groupchat=False): + def make_transfer(self, path, encryption, contact, groupchat=False): if not path or not os.path.exists(path): - return + return None invalid_file = False stat = os.stat(path) @@ -112,47 +110,41 @@ class HTTPUpload(BaseModule): 'maximum allowed file size is: %s') % size if invalid_file: - self._raise_information_event('open-file-error2', msg) - return + raise FileError('file-error', msg) mime = mimetypes.MimeTypes().guess_type(path)[0] if not mime: mime = 'application/octet-stream' # fallback mime type self._log.info("Detected MIME type of file: %s", mime) - try: - transfer = HTTPFileTransfer(self._account, - self._cancel_upload, - path, - contact, - mime, - encryption, - groupchat) - app.interface.show_httpupload_progress(transfer) - except Exception as error: - self._log.exception('Error while loading file') - self._raise_information_event('open-file-error2', str(error)) - return - - if encryption is not None: - app.interface.encrypt_file(transfer, - self._account, - self._request_slot) - else: - self._request_slot(transfer) + return HTTPFileTransfer(self._account, + path, + contact, + mime, + encryption, + groupchat) - def _cancel_upload(self, transfer): + def cancel_transfer(self, transfer): + transfer.set_cancelled() message = self._queued_messages.get(id(transfer)) if message is None: return + self._session.cancel_message(message, Soup.Status.CANCELLED) - @staticmethod - def _raise_information_event(dialog_name, args=None): - app.nec.push_incoming_event(InformationEvent( - None, dialog_name=dialog_name, args=args)) + def start_transfer(self, transfer): + if transfer.encryption is not None and not transfer.is_encrypted: + transfer.set_encrypting() + plugin = app.plugin_manager.encryption_plugins[transfer.encryption] + if hasattr(plugin, 'encrypt_file'): + plugin.encrypt_file(transfer, + self._account, + self.start_transfer) + else: + transfer.set_error('encryption-not-available') + + return - def _request_slot(self, transfer): transfer.set_preparing() self._log.info('Sending request for slot') self._nbxmpp('HTTPUpload').request_slot( @@ -172,8 +164,6 @@ class HTTPUpload(BaseModule): HTTPUploadStanzaError, MalformedStanzaError) as error: - transfer.set_error() - if error.app_condition == 'file-too-large': size_text = GLib.format_size_full( error.get_max_file_size(), @@ -181,20 +171,18 @@ class HTTPUpload(BaseModule): error_text = _('File is too large, ' 'maximum allowed file size is: %s' % size_text) + transfer.set_error('file-too-large', error_text) + else: - error_text = str(error) - self._log.warning(error) + transfer.set_error('misc', str(error)) - self._raise_information_event('request-upload-slot-error', - error_text) return transfer.process_result(result) if (urlparse(transfer.put_uri).scheme != 'https' or urlparse(transfer.get_uri).scheme != 'https'): - transfer.set_error() - self._raise_information_event('unsecure-error') + transfer.set_error('unsecure') return self._log.info('Uploading file to %s', transfer.put_uri) @@ -206,7 +194,7 @@ class HTTPUpload(BaseModule): transfer.set_started() message = Soup.Message.new('PUT', transfer.put_uri) - message.connect('starting', self._check_certificate) + message.connect('starting', self._check_certificate, transfer) # Set CAN_REBUILD so chunks get discarded after they have been # written to the network @@ -227,10 +215,11 @@ class HTTPUpload(BaseModule): self._set_proxy_if_available() self._session.queue_message(message, self._on_finish, transfer) - def _check_certificate(self, message): + def _check_certificate(self, message, transfer): https_used, tls_certificate, tls_errors = message.get_https_status() if not https_used: self._log.warning('HTTPS was not used for upload') + transfer.set_error('unsecure') self._session.cancel_message(message, Soup.Status.CANCELLED) return @@ -241,12 +230,12 @@ class HTTPUpload(BaseModule): for error in tls_errors: phrase = get_tls_error_phrase(error) self._log.warning('TLS verification failed: %s', phrase) + + transfer.set_error('tls-verification-failed', phrase) self._session.cancel_message(message, Soup.Status.CANCELLED) - self._raise_information_event('httpupload-error', phrase) def _on_finish(self, _session, message, transfer): self._queued_messages.pop(id(transfer), None) - transfer.set_finished() if message.props.status_code == Soup.Status.CANCELLED: self._log.info('Upload cancelled') @@ -254,25 +243,14 @@ class HTTPUpload(BaseModule): if message.props.status_code in (Soup.Status.OK, Soup.Status.CREATED): self._log.info('Upload completed successfully') - uri = transfer.get_transformed_uri() + transfer.set_finished() - type_ = 'chat' - if transfer.is_groupchat: - type_ = 'groupchat' - - message = OutgoingMessage(account=self._account, - contact=transfer.contact, - message=uri, - type_=type_, - oob_url=uri) - - self._con.send_message(message) else: phrase = Soup.Status.get_phrase(message.props.status_code) self._log.error('Got unexpected http upload response code: %s', phrase) - self._raise_information_event('httpupload-response-error', phrase) + transfer.set_error('http-response', phrase) def _on_wrote_chunk(self, message, transfer): transfer.update_progress() @@ -303,15 +281,21 @@ class HTTPFileTransfer(FileTransfer): FTState.STARTED: _('Uploading via HTTP File Upload…'), } + _errors = { + 'unsecure': _('The server returned an insecure transport (HTTP).'), + 'encryption-not-available': _('There is no encryption method available ' + 'for the chosen encryption.') + } + def __init__(self, account, - cancel_func, path, contact, mime, encryption, groupchat): - FileTransfer.__init__(self, account, cancel_func=cancel_func) + + FileTransfer.__init__(self, account) self._path = path self._encryption = encryption @@ -328,6 +312,8 @@ class HTTPFileTransfer(FileTransfer): self._data = None self._headers = {} + self._is_encrypted = False + @property def mime(self): return self._mime @@ -352,6 +338,10 @@ class HTTPFileTransfer(FileTransfer): def path(self): return self._path + @property + def is_encrypted(self): + return self._is_encrypted + def get_transformed_uri(self): if self._uri_transform_func is not None: return self._uri_transform_func(self.get_uri) @@ -364,9 +354,12 @@ class HTTPFileTransfer(FileTransfer): def filename(self): return os.path.basename(self._path) - def set_error(self, text=''): + def set_error(self, domain, text=''): + if not text: + text = self._errors[domain] + self._close() - super().set_error(text) + super().set_error(domain, text) def set_finished(self): self._close() @@ -374,6 +367,7 @@ class HTTPFileTransfer(FileTransfer): def set_encrypted_data(self, data): self._data = data + self._is_encrypted = True def _close(self): if self._stream is not None: |