Download and store a remote GIF/clip for discussion within an existing DB transaction.
(conn, msg_id: int, gif_url: str)
| 12553 | chunk = request.files.get("chunk") |
| 12554 | if not re.fullmatch(r"[A-Za-z0-9_-]{20,128}", upload_id or "") or chunk is None: return jsonify({"ok": False, "error": "bad_request"}), 400 |
| 12555 | meta_path = _upload_meta_path(upload_id) |
| 12556 | with UPLOAD_LOCK: |
| 12557 | try: meta = json.loads(open(meta_path, "r", encoding="utf-8").read()) |
| 12558 | except Exception: return jsonify({"ok": False, "error": "not_found"}), 404 |
| 12559 | if meta.get("u") != current_user(): return jsonify({"ok": False, "error": "forbidden"}), 403 |
| 12560 | if total != int(meta.get("total_chunks") or 0) or idx != int(meta.get("received") or 0): return jsonify({"ok": False, "error": "out_of_order", "expected": int(meta.get("received") or 0)}), 409 |
| 12561 | tmp_path = _upload_tmp_path(upload_id); mode = "ab" if os.path.exists(tmp_path) else "wb" |
| 12562 | with open(tmp_path, mode) as out: shutil.copyfileobj(chunk.stream, out, length=8 * 1024 * 1024) |
| 12563 | written = os.path.getsize(tmp_path) |
| 12564 | if written > int(meta.get("total_size") or 0) or written > FILES_MAX_BYTES or not _disk_allows_upload(os.path.dirname(meta["destination"]), int(meta["total_size"]), written): |
| 12565 | for fp in (tmp_path, meta_path): |
| 12566 | try: os.remove(fp) |
| 12567 | except Exception: pass |
| 12568 | return jsonify({"ok": False, "error": "storage_or_size"}), 507 |
| 12569 | meta["received"] = idx + 1 |
| 12570 | temp_meta = meta_path + ".tmp" |
| 12571 | with open(temp_meta, "w", encoding="utf-8") as fh: json.dump(meta, fh) |
| 12572 | os.replace(temp_meta, meta_path) |
| 12573 | done = meta["received"] >= total |
| 12574 | if done: |
| 12575 | if written != int(meta.get("total_size") or 0): return jsonify({"ok": False, "error": "size_mismatch"}), 400 |
| 12576 | destination = meta["destination"] |
| 12577 | if os.path.exists(destination) and not meta.get("replace"): |
| 12578 | destination = _unique_destination(os.path.dirname(destination), os.path.basename(destination)) |
| 12579 | os.replace(tmp_path, destination); os.remove(meta_path) |
| 12580 | item_rel = os.path.relpath(destination, user_root(current_user())).replace(os.sep, "/") |
| 12581 | _log_file_activity(current_user(), "file_uploaded", item_rel, human_size(written)) |
| 12582 | return jsonify({"ok": True, "done": done, "received": meta["received"], "total": total}) |
| 12583 | |
| 12584 | |
| 12585 | @app.route("/files/rename", methods=["GET", "POST"]) |
| 12586 | @login_required |
| 12587 | def file_rename(): |
| 12588 | rel = request.values.get("p", "") or "" |
| 12589 | try: |
| 12590 | rel = safe_relpath(rel); source = abs_user_path(current_user(), rel) |
| 12591 | if not rel or not os.path.exists(source): raise ValueError |
| 12592 | except Exception: abort(404) |
| 12593 | parent = "/".join(rel.split("/")[:-1]) |
| 12594 | if request.method == "POST": |
| 12595 | try: |
| 12596 | new_name = _validate_entry_name(request.form.get("new_name", "")); destination = os.path.join(os.path.dirname(source), new_name) |
| 12597 | if os.path.exists(destination): raise FileExistsError |
| 12598 | os.rename(source, destination); new_rel = safe_relpath(f"{parent}/{new_name}" if parent else new_name); _remap_file_metadata(current_user(), rel, new_rel); _log_file_activity(current_user(), "entry_renamed", new_rel, f"from /{rel}"); flash("Entry renamed."); return redirect(url_for("files", p=parent)) |
| 12599 | except FileExistsError: flash("An entry with that name already exists.") |
| 12600 | except Exception: flash("Rename failed.") |
| 12601 | return render_template("file_rename.html", relpath=rel, parent_relpath=parent, name=os.path.basename(source)) |
| 12602 | |
| 12603 | |
| 12604 | @app.route("/files/move", methods=["GET", "POST"]) |
| 12605 | @login_required |
| 12606 | def file_move(): |
| 12607 | rel = request.values.get("p", "") or "" |
| 12608 | try: |
| 12609 | rel = safe_relpath(rel); source = abs_user_path(current_user(), rel) |
| 12610 | if not rel or not os.path.exists(source): raise ValueError |
| 12611 | except Exception: abort(404) |
| 12612 | parent = "/".join(rel.split("/")[:-1]) |
no test coverage detected