Store a regular DM attachment (plaintext on disk).
(dm_id: int, file_storage)
| 12473 | return redirect(url_for("files", p=rel)) |
| 12474 | |
| 12475 | |
| 12476 | UPLOAD_LOCK = threading.RLock() |
| 12477 | |
| 12478 | def _upload_meta_path(upload_id: str) -> str: return os.path.join(TMP_UPLOAD_DIR, f"{upload_id}.json") |
| 12479 | def _upload_tmp_path(upload_id: str) -> str: return os.path.join(TMP_UPLOAD_DIR, f"{upload_id}.part") |
| 12480 | |
| 12481 | def _cleanup_stale_file_uploads(max_age: int = 24 * 60 * 60) -> None: |
| 12482 | cutoff = time.time() - max_age |
| 12483 | os.makedirs(TMP_UPLOAD_DIR, exist_ok=True) |
| 12484 | for name in os.listdir(TMP_UPLOAD_DIR): |
| 12485 | if not (name.endswith(".part") or name.endswith(".json") or name.startswith("vault-download-")): continue |
| 12486 | path = os.path.join(TMP_UPLOAD_DIR, name) |
| 12487 | try: |
| 12488 | if os.path.getmtime(path) < cutoff: os.remove(path) |
| 12489 | except Exception: pass |
| 12490 | |
| 12491 | |
| 12492 | @app.route("/api/upload/init", methods=["POST"]) |
| 12493 | @login_required |
| 12494 | def api_upload_init(): |
| 12495 | _cleanup_stale_file_uploads() |
| 12496 | data = request.get_json(silent=True) or {} |
| 12497 | try: |
| 12498 | rel = safe_relpath(data.get("p", "") or ""); filename = _validate_vault_upload_filename((data.get("filename") or "").strip()); total = int(data.get("total_chunks") or 0); total_size = int(data.get("total_size") or 0) |
| 12499 | except Exception: return jsonify({"ok": False, "error": "bad_request"}), 400 |
| 12500 | conflict = (data.get("conflict") or "keep").lower() |
| 12501 | if conflict not in ("keep", "replace", "cancel"): conflict = "keep" |
| 12502 | expected = max(1, (total_size + FILE_UPLOAD_CHUNK_BYTES - 1) // FILE_UPLOAD_CHUNK_BYTES) |
| 12503 | if not filename or total != expected or total > 5000 or total_size < 0: return jsonify({"ok": False, "error": "bad_request"}), 400 |
| 12504 | if total_size > FILES_MAX_BYTES: return jsonify({"ok": False, "error": "too_large", "max": FILES_MAX_BYTES}), 413 |
| 12505 | dest_dir = abs_user_path(current_user(), rel); os.makedirs(dest_dir, exist_ok=True) |
| 12506 | original = os.path.join(dest_dir, filename) |
| 12507 | if os.path.exists(original): |
| 12508 | if conflict == "cancel": return jsonify({"ok": False, "error": "exists"}), 409 |
| 12509 | destination = original if conflict == "replace" else _unique_destination(dest_dir, filename) |
| 12510 | else: destination = original |
nothing calls this directly
no test coverage detected