From 28de92a00cba51bd665d7afabcc3f27356a177c1 Mon Sep 17 00:00:00 2001 From: Daniel Markstedt Date: Tue, 26 Oct 2021 13:05:15 -0700 Subject: [PATCH] Enable unzipping of individual archive members (#385) * Enable unzipping of individual archive members * Add code comments --- src/web/file_cmds.py | 35 ++++++++++++++++++++++++++++++----- src/web/templates/index.html | 20 +++++++++++++++++++- src/web/web.py | 3 ++- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/web/file_cmds.py b/src/web/file_cmds.py index 82183119..9e66e693 100644 --- a/src/web/file_cmds.py +++ b/src/web/file_cmds.py @@ -65,6 +65,8 @@ def list_images(): prop_data = list_files(PROPERTIES_SUFFIX, cfg_dir) prop_files = [PurePath(x[0]).stem for x in prop_data] + from zipfile import ZipFile, is_zipfile + server_info = get_server_info() files = [] for f in result.image_files_info.image_files: # Add properties meta data for the image, if applicable @@ -73,6 +75,22 @@ def list_images(): prop = process["conf"] else: prop = False + if f.name.lower().endswith(".zip"): + zip_path = f"{server_info['image_dir']}/{f.name}" + if is_zipfile(zip_path): + zip = ZipFile(zip_path) + # Get a list of str containing all zipfile members + zip_members = zip.namelist() + # Strip out directories from the list + zip_members = [x for x in zip_members if not x.endswith("/")] + # Reduce members to file names only (strip out full path) + zip_members = [PurePath(x).name for x in zip_members] + else: + logging.warning(f"{zip_path} is an invalid zip file") + zip_members = False + else: + zip_members = False + size_mb = "{:,.1f}".format(f.size / 1024 / 1024) dtype = proto.PbDeviceType.Name(f.type) files.append( @@ -82,6 +100,7 @@ def list_images(): "size_mb": size_mb, "detected_type": dtype, "prop": prop, + "zip": zip_members, } ) @@ -136,18 +155,24 @@ def delete_file(file_path): return {"status": False, "msg": "Could not delete file"} -def unzip_file(file_name): +def unzip_file(file_name, member=False): """ - Takes (str) file_name + Takes (str) file_name, optional (str) member Returns dict with (boolean) status and (list of str) msg """ from subprocess import run server_info = get_server_info() - unzip_proc = run( - ["unzip", "-d", server_info["image_dir"], "-n", "-j", \ + if member == False: + unzip_proc = run( + ["unzip", "-d", server_info["image_dir"], "-n", "-j", \ f"{server_info['image_dir']}/{file_name}"], capture_output=True - ) + ) + else: + unzip_proc = run( + ["unzip", "-d", server_info["image_dir"], "-n", "-j", \ + f"{server_info['image_dir']}/{file_name}", member], capture_output=True + ) if unzip_proc.returncode != 0: stderr = unzip_proc.stderr.decode("utf-8") logging.warning(f"Unzipping failed: {stderr}") diff --git a/src/web/templates/index.html b/src/web/templates/index.html index 610df49e..bee0172d 100644 --- a/src/web/templates/index.html +++ b/src/web/templates/index.html @@ -140,6 +140,24 @@ + {% elif file["zip"] %} + +
+ {{file["name"]}} + +
+ {% else %} {{file["name"]}} {% endif %} @@ -156,7 +174,7 @@ {% if file["name"].lower().endswith(archive_file_suffix) %}
- +
{% else %}
diff --git a/src/web/web.py b/src/web/web.py index 64362f5d..31dc99c4 100644 --- a/src/web/web.py +++ b/src/web/web.py @@ -645,8 +645,9 @@ def delete(): @app.route("/files/unzip", methods=["POST"]) def unzip(): image = request.form.get("image") + member = request.form.get("member") or False - process = unzip_file(image) + process = unzip_file(image, member) if process["status"]: if len(process["msg"]) < 1: flash("Aborted unzip: File(s) with the same name already exists.", "error")