final fix for telegram

This commit is contained in:
lelo 2025-06-03 22:54:17 +02:00
parent f96f4a40a5
commit cb3d8efd72
3 changed files with 43 additions and 27 deletions

36
app.py
View File

@ -346,9 +346,16 @@ def api_browse(subpath):
def serve_file(subpath): def serve_file(subpath):
# 1) Locate the real file on disk # 1) Locate the real file on disk
root, *relative_parts = subpath.split('/') root, *relative_parts = subpath.split('/')
base_path = session['folders'].get(root)
full_path = os.path.join(base_path or '', *relative_parts) dltoken = request.args.get('dltoken')
if dltoken:
as_attachment = True
full_path = auth.decode_token(dltoken)['filename']
else:
as_attachment = False
base_path = session['folders'].get(root)
full_path = os.path.join(base_path or '', *relative_parts)
try: try:
full_path = check_path(full_path) full_path = check_path(full_path)
except (ValueError, PermissionError) as e: except (ValueError, PermissionError) as e:
@ -463,9 +470,6 @@ def serve_file(subpath):
# 6) Build response for non-image # 6) Build response for non-image
filesize = os.path.getsize(file_path) filesize = os.path.getsize(file_path)
# Figure out download flag and filename
ask_download = request.args.get('download') == 'true'
filename = os.path.basename(full_path) filename = os.path.basename(full_path)
# Single send_file call with proper attachment handling # Single send_file call with proper attachment handling
@ -473,10 +477,10 @@ def serve_file(subpath):
file_path, file_path,
mimetype=mime, mimetype=mime,
conditional=True, conditional=True,
as_attachment=ask_download, as_attachment=as_attachment,
download_name=filename if ask_download else None download_name=filename if as_attachment else None
) )
if not ask_download: if not as_attachment:
response.headers['Content-Disposition'] = 'inline' response.headers['Content-Disposition'] = 'inline'
response.headers['Cache-Control'] = 'public, max-age=86400' response.headers['Cache-Control'] = 'public, max-age=86400'
@ -562,12 +566,11 @@ def create_token(subpath):
) )
@app.route("/create_dl_token/<path:subpath>") @app.route("/create_dltoken/<path:subpath>")
@auth.require_secret @auth.require_secret
def create_dl_token(subpath): def create_dltoken(subpath):
scheme = request.scheme # current scheme (http or https) scheme = request.scheme # current scheme (http or https)
host = request.host host = request.host
print(f"Creating download token for subpath: {subpath}")
# 1) Locate the real file on disk # 1) Locate the real file on disk
root, *relative_parts = subpath.split('/') root, *relative_parts = subpath.split('/')
base_path = session['folders'].get(root) base_path = session['folders'].get(root)
@ -575,7 +578,6 @@ def create_dl_token(subpath):
try: try:
full_path = check_path(full_path) full_path = check_path(full_path)
print(f"Full path after check: {full_path}")
except (ValueError, PermissionError) as e: except (ValueError, PermissionError) as e:
return jsonify({'Unauthorized': str(e)}), 403 return jsonify({'Unauthorized': str(e)}), 403
@ -583,16 +585,14 @@ def create_dl_token(subpath):
app.logger.error(f"File not found: {full_path}") app.logger.error(f"File not found: {full_path}")
return "File not found", 404 return "File not found", 404
validity_date = (datetime.now() + timedelta(days=1)).strftime('%d.%m.%Y') validity_date = datetime.now().strftime('%d.%m.%Y')
data = { data = {
"validity": validity_date, "validity": validity_date,
"filename": full_path "filename": str(full_path)
} }
token = auth.generate_token(data) token = auth.generate_token(data)
url = f"{scheme}://{host}/media/{subpath}?dltoken={token}"
url = f"{scheme}://{host}?dl_token={token}"
return url return url

View File

@ -73,6 +73,12 @@ def require_secret(f):
# 1) Get secretand token from query params (if any) # 1) Get secretand token from query params (if any)
args_secret = request.args.get('secret') args_secret = request.args.get('secret')
args_token = request.args.get('token') args_token = request.args.get('token')
args_dltoken = request.args.get('dltoken')
# 1b) immediately return if dltoken is provided
if args_dltoken:
if is_valid_token(args_dltoken):
return f(*args, **kwargs)
# 2) Initialize 'valid_secrets' in the session if missing # 2) Initialize 'valid_secrets' in the session if missing
if 'valid_secrets' not in session: if 'valid_secrets' not in session:

View File

@ -139,20 +139,30 @@ class SimpleAudioPlayer {
} }
async fileDownload() { async fileDownload() {
const src = this.audio.currentSrc || this.audio.src; const src = this.audio.currentSrc || this.audio.src;
if (!src) return; if (!src) return;
// Build the URL with your download flag + cachebuster // Extract the subpath from the src
const downloadUrl = new URL(src, window.location.href); const urlObj = new URL(src, window.location.href);
downloadUrl.searchParams.set('download', 'true'); let subpath = urlObj.pathname;
downloadUrl.searchParams.set('_', Date.now()); subpath = subpath.slice('/media'.length);
// Create a “real” link to that URL and click it // Fetch the tokenized URL from your backend
let tokenizedUrl;
try {
const resp = await fetch(`/create_dltoken${subpath}`);
if (!resp.ok) return;
tokenizedUrl = await resp.text();
} catch {
return;
}
// Build the URL with cache-buster
const downloadUrl = new URL(tokenizedUrl, window.location.href);
// Create a link and click it
const a = document.createElement('a'); const a = document.createElement('a');
a.href = downloadUrl.toString(); a.href = downloadUrl.toString();
a.download = ''; // tell Safari “this is a download”
a.target = '_blank'; // force a real navigation on iOS
// NOTE: do NOT set a.download here we want the server's Content-Disposition to drive it
document.body.appendChild(a); document.body.appendChild(a);
a.click(); a.click();
document.body.removeChild(a); document.body.removeChild(a);