Skip to content

Commit 5a87003

Browse files
committed
restore: use request.stream instead of request.files
request.files uses /tmp for file uploads before file.save is even called /tmp is tmpfs and rather small on newer linux systems thus we need a solution to work-around this issue. this commit is a rather ugly work-around but it seems to work
1 parent b9f01e2 commit 5a87003

File tree

1 file changed

+39
-14
lines changed
  • src/modules/adsb-feeder/filesystem/root/opt/adsb/adsb-setup

1 file changed

+39
-14
lines changed

src/modules/adsb-feeder/filesystem/root/opt/adsb/adsb-setup/app.py

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,28 +1076,53 @@ def zip2fobj(fobj, include_graphs, include_heatmap):
10761076

10771077
def restore(self):
10781078
if request.method == "POST":
1079-
# check if the post request has the file part
1080-
if "file" not in request.files:
1079+
# read the post request as a stream
1080+
# request.files uses /tmp which can be too small
1081+
# thus we need to parse the POST request ourselves which is a bit of a pain
1082+
# read the first chunk and separate the POST header from the body
1083+
# we parse the header and store the first part of the body as chunk
1084+
chunk_size = 16 * 1024
1085+
chunk = request.stream.read(chunk_size)
1086+
split = chunk.split(b"\r\n\r\n", 1)
1087+
if len(split) != 2:
1088+
flash("POST header issue")
1089+
print_err("Restore: POST header issue")
1090+
return redirect(request.url)
1091+
header, chunk = split
1092+
header = str(header)
1093+
match = re.search("filename=\"([^\"]*)\"", header)
1094+
if not match:
10811095
flash("No file submitted")
1096+
print_err("Restore: No file submitted, header was: " + header)
10821097
return redirect(request.url)
1083-
file = request.files["file"]
1098+
filename = secure_filename(match.group(1))
10841099
# If the user does not select a file, the browser submits an
10851100
# empty file without a filename.
1086-
if file.filename == "":
1101+
if filename == "":
10871102
flash("No file selected")
1103+
print_err("Restore: No file selected, header was: " + header)
10881104
return redirect(request.url)
1089-
if file.filename and (file.filename.endswith(".zip") or file.filename.endswith(".backup")):
1090-
filename = secure_filename(file.filename)
1091-
restore_path = pathlib.Path(f"{get_adsb_base_dir()}/config/restore")
1092-
# clean up the restore path when saving a fresh zipfile
1093-
shutil.rmtree(restore_path, ignore_errors=True)
1094-
restore_path.mkdir(mode=0o644, exist_ok=True)
1095-
file.save(restore_path / filename)
1096-
print_err(f"saved restore file to {restore_path / filename}")
1097-
return redirect(url_for("executerestore", zipfile=filename))
1098-
else:
1105+
if not (filename.endswith(".zip") or filename.endswith(".backup")):
10991106
flash("Please only submit ADS-B Feeder Image backup files")
1107+
print_err("Restore: Incorrect filename, header was: " + header)
11001108
return redirect(request.url)
1109+
1110+
restore_path = pathlib.Path(f"{get_adsb_base_dir()}/config/restore")
1111+
# clean up the restore path when saving a fresh zipfile
1112+
shutil.rmtree(restore_path, ignore_errors=True)
1113+
restore_path.mkdir(mode=0o644, exist_ok=True)
1114+
1115+
with open(restore_path / filename, "bw") as f:
1116+
# this while loop looks backwards but it's not because we start with the first chunk
1117+
# we read further up in this function
1118+
while True:
1119+
if len(chunk) == 0:
1120+
break
1121+
f.write(chunk)
1122+
chunk = request.stream.read(chunk_size)
1123+
1124+
print_err(f"saved restore file to {restore_path / filename}")
1125+
return redirect(url_for("executerestore", zipfile=filename))
11011126
else:
11021127
return render_template("/restore.html")
11031128

0 commit comments

Comments
 (0)