Download and store a remote GIF using an existing DB connection/transaction.
(conn, dm_id: int, gif_url: str)
| 12738 | if is_encrypted_file(target): |
| 12739 | response = Response(aesgcm_decrypt_generator(target), mimetype=mime); response.headers["Content-Disposition"] = f'attachment; filename="{os.path.basename(target)}"' |
| 12740 | else: response = send_file(target, mimetype=mime, as_attachment=True, download_name=os.path.basename(target), conditional=True, max_age=0) |
| 12741 | response.headers["Cache-Control"] = "no-store"; return response |
| 12742 | except Exception as exc: |
| 12743 | if getattr(exc, "code", None) == 404: raise |
| 12744 | log.exception("Download failed: %s", exc); flash("Download failed."); return redirect(url_for("files")) |
| 12745 | |
| 12746 | |
| 12747 | @app.route("/files/details") |
| 12748 | @login_required |
| 12749 | def file_details(): |
| 12750 | rel = request.args.get("p", "") or "" |
| 12751 | try: |
| 12752 | rel = safe_relpath(rel); target = abs_user_path(current_user(), rel); st = os.stat(target) |
| 12753 | if not rel: raise ValueError |
| 12754 | except Exception: abort(404) |
| 12755 | is_dir = os.path.isdir(target); size = _folder_size(target) if is_dir else st.st_size; category = _file_category(target, is_dir) |
| 12756 | checksum = _sha256_file(target) if request.args.get("checksum") == "1" and not is_dir else "" |
| 12757 | conn = db_connect(); comments = conn.execute("SELECT id, author, body, created_at FROM file_comments WHERE owner=? AND relpath=? ORDER BY id DESC", (current_user(), rel)).fetchall(); shares_rows = conn.execute("SELECT id, token, pw_hash, expires_at FROM file_shares WHERE owner=? AND relpath=? AND revoked=0 ORDER BY id DESC", (current_user(), rel)).fetchall(); conn.close() |
| 12758 | now = datetime.now(timezone.utc) |
| 12759 | shares = [] |
| 12760 | for row in shares_rows: |
| 12761 | expired = False |
| 12762 | try: expired = bool(row["expires_at"] and datetime.fromisoformat(row["expires_at"].replace("Z", "+00:00")) <= now) |
| 12763 | except Exception: expired = False |
| 12764 | if not expired: shares.append(type("Obj", (), {"id": row["id"], "url": url_for("public_share", token=row["token"], _external=True), "protected": bool(row["pw_hash"]), "expires_at": row["expires_at"]})()) |
| 12765 | info = type("Obj", (), {"name": os.path.basename(target), "is_dir": is_dir, "kind": "Folder" if is_dir else "File", "category": _category_label(category), "mime": "inode/directory" if is_dir else guess_mime(target), "size": size, "size_h": human_size(size), "created": datetime.fromtimestamp(getattr(st, "st_birthtime", st.st_ctime)).isoformat(sep=" ", timespec="seconds"), "modified": datetime.fromtimestamp(st.st_mtime).isoformat(sep=" ", timespec="seconds")})() |
| 12766 | return render_template("file_details.html", relpath=rel, parent_relpath="/".join(rel.split("/")[:-1]), info=info, checksum=checksum, comments=comments, shares=shares) |
| 12767 | |
| 12768 | |
| 12769 | @app.route("/files/comments/add", methods=["POST"]) |
| 12770 | @login_required |
| 12771 | def file_comment_add(): |
| 12772 | rel = safe_relpath(request.form.get("p", "") or ""); body = (request.form.get("body") or "").strip() |
| 12773 | try: |
| 12774 | if not body or len(body) > 2000 or not os.path.exists(abs_user_path(current_user(), rel)): raise ValueError |
| 12775 | conn = db_connect(); conn.execute("INSERT INTO file_comments(owner, relpath, author, body, created_at) VALUES(?,?,?,?,?)", (current_user(), rel, current_user(), body, now_z())); conn.commit(); conn.close(); _log_file_activity(current_user(), "comment_added", rel); flash("Comment added.") |
| 12776 | except Exception: flash("Could not add comment.") |
| 12777 | return redirect(url_for("file_details", p=rel)) |
| 12778 | |
| 12779 | |
| 12780 | @app.route("/files/comments/<int:cid>/delete", methods=["POST"]) |
| 12781 | @login_required |
| 12782 | def file_comment_delete(cid: int): |
| 12783 | rel = safe_relpath(request.form.get("p", "") or ""); conn = db_connect(); conn.execute("DELETE FROM file_comments WHERE id=? AND owner=?", (cid, current_user())); conn.commit(); conn.close(); _log_file_activity(current_user(), "comment_deleted", rel); flash("Comment deleted."); return redirect(url_for("file_details", p=rel)) |
| 12784 | |
| 12785 | |
| 12786 | @app.route("/files/share/create", methods=["POST"]) |
| 12787 | @login_required |
| 12788 | def file_share_create(): |
| 12789 | rel = safe_relpath(request.form.get("p", "") or "") |
| 12790 | try: |
| 12791 | if not rel or not os.path.exists(abs_user_path(current_user(), rel)): raise ValueError |
| 12792 | hours = max(1, min(720, int(request.form.get("hours") or 24))); password = request.form.get("password") or ""; token = secrets.token_urlsafe(32); expires = (datetime.now(timezone.utc) + timedelta(hours=hours)).isoformat(timespec="seconds").replace("+00:00", "Z") |
| 12793 | conn = db_connect(); conn.execute("INSERT INTO file_shares(token, owner, relpath, pw_hash, expires_at, created_at, revoked) VALUES(?,?,?,?,?,?,0)", (token, current_user(), rel, generate_password_hash(password) if password else None, expires, now_z())); conn.commit(); conn.close(); _log_file_activity(current_user(), "share_created", rel, f"expires {expires}"); flash("Share link created.") |
| 12794 | except Exception: flash("Could not create share link.") |
| 12795 | return redirect(url_for("file_details", p=rel)) |
| 12796 | |
| 12797 |
no test coverage detected