avoid breaking out into filestructure
This commit is contained in:
parent
564d95a5c2
commit
a0f972f38a
34
app.py
34
app.py
@ -15,6 +15,7 @@ import geoip2.database
|
||||
from functools import lru_cache
|
||||
from urllib.parse import urlparse, unquote
|
||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
from pathlib import Path
|
||||
import re
|
||||
import qrcode
|
||||
import base64
|
||||
@ -24,6 +25,7 @@ import analytics as a
|
||||
import folder_secret_config_editor as fsce
|
||||
|
||||
app_config = auth.return_app_config()
|
||||
BASE_DIR = os.path.realpath(app_config['BASE_DIR'])
|
||||
|
||||
cache_audio = diskcache.Cache('./filecache_audio', size_limit= app_config['filecache_size_limit_audio'] * 1024**3)
|
||||
cache_image = diskcache.Cache('./filecache_image', size_limit= app_config['filecache_size_limit_image'] * 1024**3)
|
||||
@ -90,6 +92,27 @@ def get_cached_image(size):
|
||||
resized_img.save(img_byte_arr, format='PNG')
|
||||
return img_byte_arr.getvalue()
|
||||
|
||||
def check_path(access_path: str) -> Path:
|
||||
"""
|
||||
Take an absolute access_path, then ensure it lives inside BASE_DIR.
|
||||
Raises ValueError or PermissionError on failure.
|
||||
"""
|
||||
p = Path(access_path)
|
||||
if not p.is_absolute():
|
||||
raise ValueError(f"Path {access_path} is not a valid absolute path")
|
||||
|
||||
# Resolve symlinks & eliminate “..” components
|
||||
candidate = p.resolve()
|
||||
base = Path(BASE_DIR).resolve()
|
||||
|
||||
try:
|
||||
# Will raise ValueError if candidate is not under base
|
||||
candidate.relative_to(base)
|
||||
except ValueError:
|
||||
raise PermissionError(f"Access to {access_path} is forbidden")
|
||||
|
||||
return candidate
|
||||
|
||||
def list_directory_contents(directory, subpath):
|
||||
"""
|
||||
List only the immediate contents of the given directory.
|
||||
@ -236,6 +259,12 @@ def api_browse(subpath):
|
||||
directory = os.path.join(base_path, *relative_parts)
|
||||
|
||||
playfile = None
|
||||
|
||||
try:
|
||||
directory = check_path(directory)
|
||||
except (ValueError, PermissionError) as e:
|
||||
return jsonify({'error': str(e)}), 403
|
||||
|
||||
# Check if the constructed directory exists.
|
||||
if not os.path.isdir(directory):
|
||||
# Assume the last segment is a filename; remove it.
|
||||
@ -270,6 +299,11 @@ def serve_file(subpath):
|
||||
root, *relative_parts = subpath.split('/')
|
||||
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:
|
||||
return jsonify({'error': str(e)}), 403
|
||||
|
||||
if not os.path.isfile(full_path):
|
||||
app.logger.error(f"File not found: {full_path}")
|
||||
|
||||
@ -213,7 +213,12 @@ function loadDirectory(subpath) {
|
||||
.then(data => {
|
||||
clearTimeout(spinnerTimer);
|
||||
hideSpinner();
|
||||
renderContent(data);
|
||||
if (data.breadcrumbs) {
|
||||
renderContent(data);
|
||||
} else if (data.error) {
|
||||
document.getElementById('content').innerHTML = `<div class="alert alert-warning">${data.error}</div>`;
|
||||
return;
|
||||
}
|
||||
if (data.playfile) {
|
||||
const playFileLink = document.querySelector(`.play-file[data-url="${data.playfile}"]`);
|
||||
if (playFileLink) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user