import { NOTEBOOK_ROOT } from "./chunk-74TMTGBG.js"; // shared/errors/index.ts var AppError = class extends Error { constructor(code, message, statusCode = 500, details) { super(message); this.code = code; this.name = "AppError"; this.statusCode = statusCode; this.details = details; } statusCode; details; toJSON() { return { name: this.name, code: this.code, message: this.message, statusCode: this.statusCode, details: this.details }; } }; var ValidationError = class extends AppError { constructor(message, details) { super("VALIDATION_ERROR", message, 400, details); this.name = "ValidationError"; } }; var NotFoundError = class extends AppError { constructor(message = "Resource not found", details) { super("NOT_FOUND", message, 404, details); this.name = "NotFoundError"; } }; var AccessDeniedError = class extends AppError { constructor(message = "Access denied", details) { super("ACCESS_DENIED", message, 403, details); this.name = "AccessDeniedError"; } }; var BadRequestError = class extends AppError { constructor(message, details) { super("BAD_REQUEST", message, 400, details); this.name = "BadRequestError"; } }; var NotADirectoryError = class extends AppError { constructor(message = "\u4E0D\u662F\u76EE\u5F55", details) { super("NOT_A_DIRECTORY", message, 400, details); this.name = "NotADirectoryError"; } }; var AlreadyExistsError = class extends AppError { constructor(message = "Resource already exists", details) { super("ALREADY_EXISTS", message, 409, details); this.name = "AlreadyExistsError"; } }; var ForbiddenError = class extends AppError { constructor(message = "\u7981\u6B62\u8BBF\u95EE", details) { super("FORBIDDEN", message, 403, details); this.name = "ForbiddenError"; } }; var UnsupportedMediaTypeError = class extends AppError { constructor(message = "\u4E0D\u652F\u6301\u7684\u5A92\u4F53\u7C7B\u578B", details) { super("UNSUPPORTED_MEDIA_TYPE", message, 415, details); this.name = "UnsupportedMediaTypeError"; } }; var ResourceLockedError = class extends AppError { constructor(message = "\u8D44\u6E90\u5DF2\u9501\u5B9A", details) { super("RESOURCE_LOCKED", message, 423, details); this.name = "ResourceLockedError"; } }; var InternalError = class extends AppError { constructor(message = "\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF", details) { super("INTERNAL_ERROR", message, 500, details); this.name = "InternalError"; } }; function isAppError(error) { return error instanceof AppError; } function isNodeError(error) { return error instanceof Error && "code" in error; } // api/utils/pathSafety.ts import path from "path"; var DANGEROUS_PATTERNS = [ /\.\./, /\0/, /%2e%2e[%/]/i, /%252e%252e[%/]/i, /\.\.%2f/i, /\.\.%5c/i, /%c0%ae/i, /%c1%9c/i, /%c0%ae%c0%ae/i, /%c1%9c%c1%9c/i, /\.\.%c0%af/i, /\.\.%c1%9c/i, /%252e/i, /%uff0e/i, /%u002e/i ]; var DOUBLE_ENCODE_PATTERNS = [ /%25[0-9a-fA-F]{2}/, /%[0-9a-fA-F]{2}%[0-9a-fA-F]{2}/ ]; var normalizeRelPath = (input) => { const trimmed = input.replace(/\0/g, "").trim(); return trimmed.replace(/^[/\\]+/, ""); }; var containsPathTraversal = (input) => { const decoded = decodeURIComponentSafe(input); return DANGEROUS_PATTERNS.some((pattern) => pattern.test(input) || pattern.test(decoded)); }; var containsDoubleEncoding = (input) => { return DOUBLE_ENCODE_PATTERNS.some((pattern) => pattern.test(input)); }; var hasPathSecurityIssues = (input) => { return containsPathTraversal(input) || containsDoubleEncoding(input); }; var decodeURIComponentSafe = (input) => { try { return decodeURIComponent(input); } catch { return input; } }; var resolveNotebookPath = (relPath) => { if (hasPathSecurityIssues(relPath)) { throw new AccessDeniedError("Path traversal detected"); } const safeRelPath = normalizeRelPath(relPath); const notebookRoot = path.resolve(NOTEBOOK_ROOT); const fullPath = path.resolve(notebookRoot, safeRelPath); if (!fullPath.startsWith(notebookRoot)) { throw new AccessDeniedError("Access denied"); } return { safeRelPath, fullPath }; }; export { ValidationError, NotFoundError, BadRequestError, NotADirectoryError, AlreadyExistsError, ForbiddenError, UnsupportedMediaTypeError, ResourceLockedError, InternalError, isAppError, isNodeError, resolveNotebookPath };