new changes
This commit is contained in:
@@ -13,17 +13,25 @@ router = APIRouter(prefix="/files", tags=["files"])
|
||||
|
||||
|
||||
def _resolve_path(path: str) -> str:
|
||||
"""Resolve and validate path within allowed roots (cross-platform)"""
|
||||
"""
|
||||
Resolve API path to an OS path.
|
||||
|
||||
On Linux/macOS: path is an absolute POSIX path from filesystem root (/) so admins
|
||||
can browse the whole server (same expectation as BT/aaPanel-style panels).
|
||||
|
||||
On Windows (dev): paths stay sandboxed under www_root / setup_path.
|
||||
"""
|
||||
if ".." in path:
|
||||
raise HTTPException(status_code=400, detail="Path traversal not allowed")
|
||||
|
||||
raw = path.strip().replace("\\", "/")
|
||||
|
||||
if os.name == "nt":
|
||||
cfg = get_runtime_config()
|
||||
www_root = os.path.abspath(cfg["www_root"])
|
||||
setup_path = os.path.abspath(cfg["setup_path"])
|
||||
allowed = [www_root, setup_path]
|
||||
if os.name != "nt":
|
||||
allowed.append(os.path.abspath("/www"))
|
||||
if ".." in path:
|
||||
raise HTTPException(status_code=400, detail="Path traversal not allowed")
|
||||
norm_path = path.strip().replace("\\", "/").strip("/")
|
||||
# Root or www_root-style path
|
||||
norm_path = raw.strip("/")
|
||||
if not norm_path or norm_path in ("www", "www/wwwroot", "wwwroot"):
|
||||
full = www_root
|
||||
elif norm_path.startswith("www/wwwroot/"):
|
||||
@@ -37,6 +45,16 @@ def _resolve_path(path: str) -> str:
|
||||
raise HTTPException(status_code=403, detail="Path not allowed")
|
||||
return full
|
||||
|
||||
# POSIX: absolute paths from /
|
||||
if not raw or raw == "/":
|
||||
return "/"
|
||||
if not raw.startswith("/"):
|
||||
raw = "/" + raw
|
||||
full = os.path.normpath(raw)
|
||||
if not full.startswith("/"):
|
||||
raise HTTPException(status_code=400, detail="Invalid path")
|
||||
return full
|
||||
|
||||
|
||||
@router.get("/list")
|
||||
async def files_list(
|
||||
@@ -51,7 +69,15 @@ async def files_list(
|
||||
if not os.path.isdir(full):
|
||||
raise HTTPException(status_code=404, detail="Not a directory")
|
||||
items = []
|
||||
for name in os.listdir(full):
|
||||
try:
|
||||
names = os.listdir(full)
|
||||
except PermissionError:
|
||||
raise HTTPException(status_code=403, detail="Permission denied")
|
||||
except FileNotFoundError:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
except OSError as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
for name in names:
|
||||
item_path = os.path.join(full, name)
|
||||
try:
|
||||
stat = os.stat(item_path)
|
||||
@@ -62,7 +88,8 @@ async def files_list(
|
||||
})
|
||||
except OSError:
|
||||
pass
|
||||
return {"path": path, "items": items}
|
||||
display_path = full if full == "/" else full.rstrip("/")
|
||||
return {"path": display_path, "items": items}
|
||||
|
||||
|
||||
@router.get("/read")
|
||||
|
||||
@@ -58,7 +58,7 @@ export function FilesPage() {
|
||||
|
||||
const handleBack = () => {
|
||||
const parts = path.replace(/\/$/, '').split('/').filter(Boolean)
|
||||
if (parts.length <= 1) return
|
||||
if (parts.length === 0) return
|
||||
parts.pop()
|
||||
const newPath = parts.length === 0 ? '/' : '/' + parts.join('/')
|
||||
loadDir(newPath)
|
||||
@@ -147,8 +147,8 @@ export function FilesPage() {
|
||||
.catch((err) => setError(err.message))
|
||||
}
|
||||
|
||||
const breadcrumbs = path.split('/').filter(Boolean)
|
||||
const canGoBack = breadcrumbs.length > 0
|
||||
const pathSegments = path.replace(/\/$/, '').split('/').filter(Boolean)
|
||||
const canGoBack = pathSegments.length > 0
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -172,7 +172,7 @@ export function FilesPage() {
|
||||
)}
|
||||
Upload
|
||||
</AdminButton>
|
||||
<code className="small bg-body-secondary px-2 py-1 rounded ms-auto text-break">Path: {path}</code>
|
||||
<code className="small bg-body-secondary px-2 py-1 rounded ms-auto text-break">Path: {path || '/'}</code>
|
||||
</div>
|
||||
|
||||
<Modal show={showMkdir} onHide={() => { setShowMkdir(false); setMkdirName('') }} centered>
|
||||
|
||||
Reference in New Issue
Block a user