Download a file with proper security checks
()
| 1216 | |
| 1217 | @app.route("/download-file") |
| 1218 | def download_file(): |
| 1219 | """Download a file with proper security checks""" |
| 1220 | # Don't allow file downloads in static mode - skip freezing |
| 1221 | if STATIC_MODE: |
| 1222 | return redirect(url_for("index")) |
| 1223 | |
| 1224 | file_path = request.args.get("path") |
| 1225 | |
| 1226 | if not file_path: |
| 1227 | return jsonify({"success": False, "error": "No file path provided"}), 400 |
| 1228 | |
| 1229 | try: |
| 1230 | # Convert to Path object |
| 1231 | file_path_obj = Path(file_path) |
| 1232 | |
| 1233 | # Security check: ensure the file exists |
| 1234 | if not file_path_obj.exists(): |
| 1235 | return jsonify({"success": False, "error": "File does not exist"}), 404 |
| 1236 | |
| 1237 | # Security check: ensure the file is not a directory |
| 1238 | if not file_path_obj.is_file(): |
| 1239 | return jsonify({"success": False, "error": "Path is not a file"}), 400 |
| 1240 | |
| 1241 | # Security check: ensure the path is within our expected logs directory |
| 1242 | try: |
| 1243 | file_path_obj.relative_to(LOG_BASE_DIR) |
| 1244 | except ValueError: |
| 1245 | return jsonify({"success": False, "error": "Invalid file path"}), 403 |
| 1246 | |
| 1247 | # Send the file as an attachment |
| 1248 | return send_file(file_path_obj, as_attachment=True, download_name=file_path_obj.name) |
| 1249 | |
| 1250 | except Exception as e: |
| 1251 | return jsonify({"success": False, "error": str(e)}), 500 |
| 1252 | |
| 1253 | |
| 1254 | @app.route("/load-log") |