@@ -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