Mercurial > libervia-backend
diff sat_frontends/jp/cmd_file.py @ 3094:c3cb18236bdf
jp (file): new `get` command + encryption with upload:
- new file/get command let download a file from URL. It handles `aesgcm:` scheme by
thanks to backend decryption on the fly.
- new `--encrypt` option for upload. When used, the file will be encrypted using AES-GCM
algorithm, and the `aesgcm:` URL will be returned
- for both commands, the XMLUI note is displayed in case of error
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 20 Dec 2019 12:28:04 +0100 |
parents | e75024e41f81 |
children | 040ca99e25fe |
line wrap: on
line diff
--- a/sat_frontends/jp/cmd_file.py Fri Dec 20 12:28:04 2019 +0100 +++ b/sat_frontends/jp/cmd_file.py Fri Dec 20 12:28:04 2019 +0100 @@ -19,6 +19,7 @@ from . import base +from . import xmlui_manager import sys import os import os.path @@ -29,6 +30,8 @@ from sat_frontends.jp import common from sat_frontends.tools import jid from sat.tools.common.ansi import ANSI as A +from urllib.parse import urlparse +from pathlib import Path import tempfile import xml.etree.ElementTree as ET # FIXME: used temporarily to manage XMLUI import json @@ -254,7 +257,8 @@ path = os.path.abspath(self.filename) if os.path.exists(path) and not self.args.force: - message = _(f"File {path} already exists! Do you want to overwrite?") + message = _("File {path} already exists! Do you want to overwrite?").format( + path = path) await self.host.confirmOrQuit(message, _("file request cancelled")) self.full_dest_jid = await self.host.get_full_jid(self.args.jid) @@ -413,6 +417,77 @@ await self.start_answering() +class Get(base.CommandBase): + + def __init__(self, host): + super(Get, self).__init__( + host, "get", use_progress=True, use_verbose=True, + help=_("download a file from URI") + ) + + def add_parser_options(self): + self.parser.add_argument( + '-o', '--dest_file', type=str, default='', + help=_("destination file (DEFAULT: filename from URL)") + ) + self.parser.add_argument( + "-f", + "--force", + action="store_true", + help=_("overwrite existing file without confirmation"), + ) + self.parser.add_argument("uri", type=str, help=_("URI of the file to retrieve")) + + async def onProgressStarted(self, metadata): + self.disp(_("File download started"), 2) + + async def onProgressFinished(self, metadata): + self.disp(_("File downloaded successfully"), 2) + + async def onProgressError(self, error_msg): + self.disp(_("Error while downloading file: {}").format(error_msg), error=True) + + async def gotId(self, data): + """Called when a progress id has been received""" + try: + await self.set_progress_id(data["progress"]) + except KeyError: + if 'xmlui' in data: + ui = xmlui_manager.create(self.host, data['xmlui']) + await ui.show() + else: + self.disp(_("Can't download file"), error=True) + self.host.quit(C.EXIT_ERROR) + + async def start(self): + uri = self.args.uri + dest_file = self.args.dest_file + if not dest_file: + parsed_uri = urlparse(uri) + dest_file = Path(parsed_uri.path).name.strip() or "downloaded_file" + + dest_file = Path(dest_file).expanduser().resolve() + if dest_file.exists() and not self.args.force: + message = _("File {path} already exists! Do you want to overwrite?").format( + path = dest_file) + await self.host.confirmOrQuit(message, _("file download cancelled")) + + options = {} + + try: + download_data = await self.host.bridge.fileDownload( + uri, + str(dest_file), + data_format.serialise(options), + self.profile, + ) + except Exception as e: + self.disp(f"error while trying to download a file: {e}", error=True) + self.host.quit(C.EXIT_BRIDGE_ERRBACK) + else: + await self.gotId(download_data) + + class Upload(base.CommandBase): def __init__(self, host): super(Upload, self).__init__( @@ -420,6 +495,12 @@ ) def add_parser_options(self): + self.parser.add_argument( + "-e", + "--encrypt", + action="store_true", + help=_("encrypt file using AES-GCM"), + ) self.parser.add_argument("file", type=str, help=_("file to upload")) self.parser.add_argument( "jid", @@ -429,7 +510,7 @@ self.parser.add_argument( "--ignore-tls-errors", action="store_true", - help=_("ignore invalide TLS certificate"), + help=_(r"ignore invalide TLS certificate (/!\ Dangerous /!\)"), ) async def onProgressStarted(self, metadata): @@ -443,7 +524,7 @@ self.disp("download URL not found in metadata") else: self.disp(_("URL to retrieve the file:"), 1) - # XXX: url is display alone on a line to make parsing easier + # XXX: url is displayed alone on a line to make parsing easier self.disp(url) async def onProgressError(self, error_msg): @@ -458,8 +539,11 @@ try: await self.set_progress_id(data["progress"]) except KeyError: - # TODO: if 'xmlui' key is present, manage xmlui message display - self.disp(_("Can't upload file"), error=True) + if 'xmlui' in data: + ui = xmlui_manager.create(self.host, data['xmlui']) + await ui.show() + else: + self.disp(_("Can't upload file"), error=True) self.host.quit(C.EXIT_ERROR) async def start(self): @@ -479,6 +563,8 @@ options = {} if self.args.ignore_tls_errors: options["ignore_tls_errors"] = True + if self.args.encrypt: + options["encryption"] = C.ENC_AES_GCM path = os.path.abspath(file_) try: @@ -490,7 +576,7 @@ self.profile, ) except Exception as e: - self.disp(f"can't while trying to upload a file: {e}", error=True) + self.disp(f"error while trying to upload a file: {e}", error=True) self.host.quit(C.EXIT_BRIDGE_ERRBACK) else: await self.gotId(upload_data, file_) @@ -727,7 +813,7 @@ class File(base.CommandBase): - subcommands = (Send, Request, Receive, Upload, Share) + subcommands = (Send, Request, Receive, Get, Upload, Share) def __init__(self, host): super(File, self).__init__(