From c16dd25fc90f27ab44ad63676105a1314e97a120 Mon Sep 17 00:00:00 2001 From: Goffi Date: Wed, 26 Feb 2020 15:54:43 +0100 Subject: [PATCH] plugin download, aesgcm: fixed handling of HTTP errors --- sat/core/exceptions.py | 4 ++++ sat/plugins/plugin_misc_download.py | 19 +++++++++++++++++-- sat/plugins/plugin_sec_aesgcm.py | 20 ++++++++++++-------- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/sat/core/exceptions.py b/sat/core/exceptions.py index 371e7647..c0e506fb 100644 --- a/sat/core/exceptions.py +++ b/sat/core/exceptions.py @@ -123,6 +123,10 @@ class NotReady(Exception): pass +class NetworkError(Exception): + """Something is wrong with a request (e.g. HTTP(S))""" + + class InvalidCertificate(Exception): """A TLS certificate is not valid""" pass diff --git a/sat/plugins/plugin_misc_download.py b/sat/plugins/plugin_misc_download.py index 9fba5724..ecfbbfe9 100644 --- a/sat/plugins/plugin_misc_download.py +++ b/sat/plugins/plugin_misc_download.py @@ -169,6 +169,17 @@ class DownloadPlugin(object): except KeyError: raise exceptions.NotFound(f"No callback registered for scheme {scheme!r}") + def errbackDownload(self, file_obj, download_d, resp): + """Set file_obj and download deferred appropriatly after a network error + + @param file_obj(SatFile): file where the download must be done + @param download_d(Deferred): deffered which must be fired on complete download + @param resp(treq.response.IResponse): treq response + """ + msg = f"HTTP error ({resp.code}): {resp.phrase.decode()}" + file_obj.close(error=msg) + download_d.errback(exceptions.NetworkError(msg)) + async def downloadHTTP(self, client, uri_parsed, dest_path, options): url = uri_parsed.geturl() @@ -189,6 +200,10 @@ class DownloadPlugin(object): progress_id = file_obj.uid resp = await treq.get(url, unbuffered=True) - d = treq.collect(resp, file_obj.write) - d.addBoth(lambda _: file_obj.close()) + if resp.code == 200: + d = treq.collect(resp, file_obj.write) + d.addBoth(lambda _: file_obj.close()) + else: + d = defer.Deferred() + self.errbackDownload(file_obj, d, resp) return progress_id, d diff --git a/sat/plugins/plugin_sec_aesgcm.py b/sat/plugins/plugin_sec_aesgcm.py index 0ea9c0e0..f5a833c7 100644 --- a/sat/plugins/plugin_sec_aesgcm.py +++ b/sat/plugins/plugin_sec_aesgcm.py @@ -19,15 +19,15 @@ import re from textwrap import dedent from functools import partial -from urllib.parse import urlparse +from urllib import parse import mimetypes import secrets from cryptography.hazmat.primitives import ciphers from cryptography.hazmat.primitives.ciphers import modes from cryptography.hazmat import backends from cryptography.exceptions import AlreadyFinalized -from urllib import parse import treq +from twisted.internet import defer from sat.core.i18n import _ from sat.core.constants import Const as C from sat.core import exceptions @@ -108,11 +108,15 @@ class AESGCM(object): progress_id = file_obj.uid resp = await treq.get(download_url, unbuffered=True) - d = treq.collect(resp, partial( - self.onDataDownload, - client=client, - file_obj=file_obj, - decryptor=decryptor)) + if resp.code == 200: + d = treq.collect(resp, partial( + self.onDataDownload, + client=client, + file_obj=file_obj, + decryptor=decryptor)) + else: + d = defer.Deferred() + self.host.plugins["DOWNLOAD"].errbackDownload(file_obj, d, resp) return progress_id, d def onDataDownload(self, data, client, file_obj, decryptor): @@ -226,7 +230,7 @@ class AESGCM(object): mess_encrypted = client.encryption.isEncrypted(data) attachments = data['extra'].setdefault(C.MESS_KEY_ATTACHMENTS, []) for link in links: - path = urlparse(link).path + path = parse.urlparse(link).path attachment = { "url": link, }