| import path from "node:path"; |
| import { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js"; |
|
|
| export const DEFAULT_BROWSER_TMP_DIR = resolvePreferredOpenClawTmpDir(); |
| export const DEFAULT_TRACE_DIR = DEFAULT_BROWSER_TMP_DIR; |
| export const DEFAULT_DOWNLOAD_DIR = path.join(DEFAULT_BROWSER_TMP_DIR, "downloads"); |
| export const DEFAULT_UPLOAD_DIR = path.join(DEFAULT_BROWSER_TMP_DIR, "uploads"); |
|
|
| export function resolvePathWithinRoot(params: { |
| rootDir: string; |
| requestedPath: string; |
| scopeLabel: string; |
| defaultFileName?: string; |
| }): { ok: true; path: string } | { ok: false; error: string } { |
| const root = path.resolve(params.rootDir); |
| const raw = params.requestedPath.trim(); |
| if (!raw) { |
| if (!params.defaultFileName) { |
| return { ok: false, error: "path is required" }; |
| } |
| return { ok: true, path: path.join(root, params.defaultFileName) }; |
| } |
| const resolved = path.resolve(root, raw); |
| const rel = path.relative(root, resolved); |
| if (!rel || rel.startsWith("..") || path.isAbsolute(rel)) { |
| return { ok: false, error: `Invalid path: must stay within ${params.scopeLabel}` }; |
| } |
| return { ok: true, path: resolved }; |
| } |
|
|
| export function resolvePathsWithinRoot(params: { |
| rootDir: string; |
| requestedPaths: string[]; |
| scopeLabel: string; |
| }): { ok: true; paths: string[] } | { ok: false; error: string } { |
| const resolvedPaths: string[] = []; |
| for (const raw of params.requestedPaths) { |
| const pathResult = resolvePathWithinRoot({ |
| rootDir: params.rootDir, |
| requestedPath: raw, |
| scopeLabel: params.scopeLabel, |
| }); |
| if (!pathResult.ok) { |
| return { ok: false, error: pathResult.error }; |
| } |
| resolvedPaths.push(pathResult.path); |
| } |
| return { ok: true, paths: resolvedPaths }; |
| } |
|
|