From cb3d8efd725d99a9b5af0156c3f2d35ab3b9bcd3 Mon Sep 17 00:00:00 2001 From: lelo Date: Tue, 3 Jun 2025 22:54:17 +0200 Subject: [PATCH] final fix for telegram --- app.py | 36 ++++++++++++++++++------------------ auth.py | 6 ++++++ static/audioplayer.js | 28 +++++++++++++++++++--------- 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/app.py b/app.py index e5a1879..a3fa187 100755 --- a/app.py +++ b/app.py @@ -346,9 +346,16 @@ def api_browse(subpath): def serve_file(subpath): # 1) Locate the real file on disk 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: full_path = check_path(full_path) except (ValueError, PermissionError) as e: @@ -463,9 +470,6 @@ def serve_file(subpath): # 6) Build response for non-image 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) # Single send_file call with proper attachment handling @@ -473,10 +477,10 @@ def serve_file(subpath): file_path, mimetype=mime, conditional=True, - as_attachment=ask_download, - download_name=filename if ask_download else None + as_attachment=as_attachment, + download_name=filename if as_attachment else None ) - if not ask_download: + if not as_attachment: response.headers['Content-Disposition'] = 'inline' response.headers['Cache-Control'] = 'public, max-age=86400' @@ -562,12 +566,11 @@ def create_token(subpath): ) -@app.route("/create_dl_token/") +@app.route("/create_dltoken/") @auth.require_secret -def create_dl_token(subpath): +def create_dltoken(subpath): scheme = request.scheme # current scheme (http or https) host = request.host - print(f"Creating download token for subpath: {subpath}") # 1) Locate the real file on disk root, *relative_parts = subpath.split('/') base_path = session['folders'].get(root) @@ -575,7 +578,6 @@ def create_dl_token(subpath): try: full_path = check_path(full_path) - print(f"Full path after check: {full_path}") except (ValueError, PermissionError) as e: return jsonify({'Unauthorized': str(e)}), 403 @@ -583,16 +585,14 @@ def create_dl_token(subpath): app.logger.error(f"File not found: {full_path}") 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 = { "validity": validity_date, - "filename": full_path + "filename": str(full_path) } token = auth.generate_token(data) - - url = f"{scheme}://{host}?dl_token={token}" - + url = f"{scheme}://{host}/media/{subpath}?dltoken={token}" return url diff --git a/auth.py b/auth.py index 1be5b34..15b9f17 100644 --- a/auth.py +++ b/auth.py @@ -73,6 +73,12 @@ def require_secret(f): # 1) Get secretand token from query params (if any) args_secret = request.args.get('secret') 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 if 'valid_secrets' not in session: diff --git a/static/audioplayer.js b/static/audioplayer.js index c0f25b8..3bebfdb 100644 --- a/static/audioplayer.js +++ b/static/audioplayer.js @@ -139,20 +139,30 @@ class SimpleAudioPlayer { } async fileDownload() { - const src = this.audio.currentSrc || this.audio.src; + const src = this.audio.currentSrc || this.audio.src; if (!src) return; - // Build the URL with your download flag + cache‑buster - const downloadUrl = new URL(src, window.location.href); - downloadUrl.searchParams.set('download', 'true'); - downloadUrl.searchParams.set('_', Date.now()); + // Extract the subpath from the src + const urlObj = new URL(src, window.location.href); + let subpath = urlObj.pathname; + 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'); 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); a.click(); document.body.removeChild(a);