Special handling of properties files (#432)

* Support for downloading properties files

* Show extra message when unzipping properties file

* Add logic to unzip method

* Move unzipped properties into CFG_DIR

* Better status message

* Cleanup

* Fix bugs
This commit is contained in:
Daniel Markstedt 2021-11-08 19:10:52 -08:00 committed by GitHub
parent 8aa7ab5401
commit 08e7531bb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 28 deletions

View File

@ -103,7 +103,7 @@ def list_images():
"size_mb": size_mb,
"detected_type": dtype,
"prop": prop,
"zip": zip_members,
"zip_members": zip_members,
})
return {"status": result.status, "msg": result.msg, "files": files}
@ -156,20 +156,46 @@ def delete_file(file_path):
return {"status": False, "msg": f"File to delete not found: {file_path}"}
def unzip_file(file_name, member=False):
def rename_file(file_path, target_path):
"""
Takes (str) file_name, optional (str) member
Takes (str) file_path and (str) target_path
Returns (dict) with (bool) status and (str) msg
"""
if os.path.exists(PurePath(target_path).parent):
os.rename(file_path, target_path)
return {"status": True, "msg": f"File moved to: {target_path}"}
return {"status": False, "msg": f"Unable to move to: {target_path}"}
def unzip_file(file_name, member=False, members=False):
"""
Takes (str) file_name, optional (str) member, optional (list) of (str) members
file_name is the name of the zip file to unzip
member is the full path to the particular file in the zip file to unzip
members contains all of the full paths to each of the zip archive members
Returns (dict) with (boolean) status and (list of str) msg
"""
from subprocess import run
from re import escape
server_info = get_server_info()
prop_flag = False
if not member:
unzip_proc = run(
["unzip", "-d", server_info["image_dir"], "-n", "-j", \
f"{server_info['image_dir']}/{file_name}"], capture_output=True
)
for path in members:
if path.endswith(PROPERTIES_SUFFIX):
name = PurePath(path).name
rename_file(f"{server_info['image_dir']}/{name}", f"{CFG_DIR}/{name}")
prop_flag = True
elif member.endswith(PROPERTIES_SUFFIX):
unzip_proc = run(
["unzip", "-d", CFG_DIR, "-n", "-j", \
f"{server_info['image_dir']}/{file_name}", escape(member)], capture_output=True
)
prop_flag = True
else:
unzip_proc = run(
["unzip", "-d", server_info["image_dir"], "-n", "-j", \
@ -185,7 +211,7 @@ def unzip_file(file_name, member=False):
"(?:inflating|extracting):(.+)\n",
unzip_proc.stdout.decode("utf-8")
)
return {"status": True, "msg": unzipped}
return {"status": True, "msg": unzipped, "prop_flag": prop_flag}
def download_file_to_iso(url):
@ -251,7 +277,7 @@ def write_config(file_name):
Returns (dict) with (bool) status and (str) msg
"""
from json import dump
file_name = CFG_DIR + file_name
file_name = f"{CFG_DIR}/{file_name}"
try:
with open(file_name, "w") as json_file:
version = get_server_info()["version"]
@ -297,7 +323,7 @@ def read_config(file_name):
Returns (dict) with (bool) status and (str) msg
"""
from json import load
file_name = CFG_DIR + file_name
file_name = f"{CFG_DIR}/{file_name}"
try:
with open(file_name) as json_file:
config = load(json_file)
@ -362,7 +388,7 @@ def write_drive_properties(file_name, conf):
Returns (dict) with (bool) status and (str) msg
"""
from json import dump
file_path = CFG_DIR + file_name
file_path = f"{CFG_DIR}/{file_name}"
try:
with open(file_path, "w") as json_file:
dump(conf, json_file, indent=4)

View File

@ -179,23 +179,27 @@
{% for key in file["prop"] %}
<li>{{ key }}: {{ file['prop'][key] }}</li>
{% endfor %}
<form action="/files/download" method="post">
<input name="file" type="hidden" value="{{ CFG_DIR }}/{{ file["name"].replace(base_dir, '') }}.{{ PROPERTIES_SUFFIX }}">
<input type="submit" value="Properties File &#8595;">
</form>
</ul>
</details>
</td>
{% elif file["zip"] %}
{% elif file["zip_members"] %}
<td>
<details>
<summary>
{{ file["name"] }}
</summary>
<ul>
{% for member in file["zip"] %}
{% for member in file["zip_members"] %}
</li>
<li>
<label for="member">{{ member }}</label>
<label for="zip_member">{{ member }}</label>
<form action="/files/unzip" method="post">
<input name="image" type="hidden" value="{{ file['name'] }}">
<input name="member" type="hidden" value="{{ member }}">
<input name="zip_file" type="hidden" value="{{ file['name'] }}">
<input name="zip_member" type="hidden" value="{{ member }}">
<input type="submit" value="Unzip">
</form>
</li>
@ -208,8 +212,8 @@
{% endif %}
<td style="text-align:center">
<form action="/files/download" method="post">
<input name="image" type="hidden" value="{{ file['name'] }}">
<input type="submit" value="{{ file["size_mb"] }} MB &#8595;">
<input name="file" type="hidden" value="{{ base_dir }}/{{ file['name'] }}">
<input type="submit" value="{{ file["size_mb"] }} MB &#8595;">
</form>
</td>
<td>
@ -218,9 +222,10 @@
Attached!
</center>
{% else %}
{% if file["name"].lower().endswith(archive_file_suffix) %}
{% if file["name"].lower().endswith(ARCHIVE_FILE_SUFFIX) %}
<form action="/files/unzip" method="post">
<input name="image" type="hidden" value="{{ file['name'] }}">
<input name="zip_file" type="hidden" value="{{ file['name'] }}">
<input name="zip_members" type="hidden" value="{{ file['zip_members'] }}">
<input type="submit" value="Unzip All">
</form>
{% else %}

View File

@ -137,7 +137,8 @@ def index():
cdrom_file_suffix=tuple(server_info["sccd"]),
removable_file_suffix=tuple(server_info["scrm"]),
mo_file_suffix=tuple(server_info["scmo"]),
archive_file_suffix=ARCHIVE_FILE_SUFFIX,
ARCHIVE_FILE_SUFFIX=ARCHIVE_FILE_SUFFIX,
PROPERTIES_SUFFIX=PROPERTIES_SUFFIX,
REMOVABLE_DEVICE_TYPES=REMOVABLE_DEVICE_TYPES,
)
@ -308,7 +309,7 @@ def config_load():
flash(process['msg'], "error")
return redirect(url_for("index"))
elif "delete" in request.form:
process = delete_file(CFG_DIR + file_name)
process = delete_file(f"{CFG_DIR}/{file_name}")
if process["status"]:
flash(process["msg"])
return redirect(url_for("index"))
@ -429,7 +430,7 @@ def attach():
# Attempt to load the device properties file:
# same file name with PROPERTIES_SUFFIX appended
drive_properties = f"{CFG_DIR}{file_name}.{PROPERTIES_SUFFIX}"
drive_properties = f"{CFG_DIR}/{file_name}.{PROPERTIES_SUFFIX}"
if Path(drive_properties).is_file():
process = read_drive_properties(drive_properties)
if not process["status"]:
@ -745,9 +746,8 @@ def download():
"""
Downloads a file from the Pi to the local computer
"""
image = request.form.get("image")
server_info = get_server_info()
return send_file(f"{server_info['image_dir']}/{image}", as_attachment=True)
image = request.form.get("file")
return send_file(image, as_attachment=True)
@APP.route("/files/delete", methods=["POST"])
@ -765,7 +765,7 @@ def delete():
return redirect(url_for("index"))
# Delete the drive properties file, if it exists
prop_file_path = f"{CFG_DIR}{file_name}.{PROPERTIES_SUFFIX}"
prop_file_path = f"{CFG_DIR}/{file_name}.{PROPERTIES_SUFFIX}"
if Path(prop_file_path).is_file():
process = delete_file(prop_file_path)
if process["status"]:
@ -783,10 +783,15 @@ def unzip():
"""
Unzips a specified zip file
"""
image = request.form.get("image")
member = request.form.get("member") or False
zip_file = request.form.get("zip_file")
zip_member = request.form.get("zip_member") or False
zip_members = request.form.get("zip_members") or False
process = unzip_file(image, member)
from ast import literal_eval
if zip_members:
zip_members = literal_eval(zip_members)
process = unzip_file(zip_file, zip_member, zip_members)
if process["status"]:
if not process["msg"]:
flash("Aborted unzip: File(s) with the same name already exists.", "error")
@ -794,9 +799,11 @@ def unzip():
flash("Unzipped the following files:")
for msg in process["msg"]:
flash(msg)
if process["prop_flag"]:
flash(f"Properties file(s) have been moved to {CFG_DIR}")
return redirect(url_for("index"))
flash("Failed to unzip " + image, "error")
flash("Failed to unzip " + zip_file, "error")
flash(process["msg"], "error")
return redirect(url_for("index"))
@ -807,7 +814,7 @@ if __name__ == "__main__":
APP.config["MAX_CONTENT_LENGTH"] = int(MAX_FILE_SIZE)
# Load the default configuration file, if found
if Path(CFG_DIR + DEFAULT_CONFIG).is_file():
if Path(f"{CFG_DIR}/{DEFAULT_CONFIG}").is_file():
read_config(DEFAULT_CONFIG)
import bjoern