|
|
@@ -1,41 +1,41 @@
|
|
|
-/**
|
|
|
- * 小说上下文管理器 - 服务端专用工具函数
|
|
|
- * Novel Context Manager - Server-side Only Utility Functions
|
|
|
- *
|
|
|
- * 此文件仅在服务端(API 路由、Server Components)使用,
|
|
|
- * 不可在客户端组件或 hooks 中导入。
|
|
|
- */
|
|
|
-
|
|
|
-import { access } from 'fs/promises';
|
|
|
-import path from 'path';
|
|
|
-
|
|
|
-/**
|
|
|
- * 验证路径不包含目录遍历或注入模式。
|
|
|
- * 用于 projectPath(允许绝对路径)和 filePath(应为相对路径)的通用安全检查。
|
|
|
- */
|
|
|
-export function isPathSafe(inputPath: string): boolean {
|
|
|
- if (!inputPath || typeof inputPath !== 'string') return false;
|
|
|
- // Block directory traversal in Unix and Windows forms
|
|
|
- if (inputPath.includes('../') || inputPath.includes('..\\')) return false;
|
|
|
- // Block URL-encoded traversal
|
|
|
- if (/%2e%2e/i.test(inputPath)) return false;
|
|
|
- // Block absolute paths (path.join collapses them, bypassing prefix)
|
|
|
- if (inputPath.startsWith('/') || inputPath.startsWith('\\')) return false;
|
|
|
- // Block Windows drive letter absolute paths (e.g. C:\)
|
|
|
- if (/^[a-zA-Z]:[/\\]/.test(inputPath)) return false;
|
|
|
- // Block null bytes
|
|
|
- if (inputPath.includes('\0')) return false;
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 检测指定路径下是否存在 novel_project.json,判断是否为有效项目目录
|
|
|
- */
|
|
|
-export async function isValidProject(projectPath: string): Promise<boolean> {
|
|
|
- try {
|
|
|
- await access(path.join(projectPath, 'novel_project.json'));
|
|
|
- return true;
|
|
|
- } catch {
|
|
|
- return false;
|
|
|
- }
|
|
|
-}
|
|
|
+/**
|
|
|
+ * 小说上下文管理器 - 服务端专用工具函数
|
|
|
+ * Novel Context Manager - Server-side Only Utility Functions
|
|
|
+ *
|
|
|
+ * 此文件仅在服务端(API 路由、Server Components)使用,
|
|
|
+ * 不可在客户端组件或 hooks 中导入。
|
|
|
+ */
|
|
|
+
|
|
|
+import { access } from 'fs/promises';
|
|
|
+import path from 'path';
|
|
|
+
|
|
|
+/**
|
|
|
+ * 验证路径不包含目录遍历或注入模式。
|
|
|
+ * 用于 projectPath(允许绝对路径)和 filePath(应为相对路径)的通用安全检查。
|
|
|
+ */
|
|
|
+export function isPathSafe(inputPath: string): boolean {
|
|
|
+ if (!inputPath || typeof inputPath !== 'string') return false;
|
|
|
+ // Block directory traversal in Unix and Windows forms
|
|
|
+ if (inputPath.includes('../') || inputPath.includes('..\\')) return false;
|
|
|
+ // Block URL-encoded traversal
|
|
|
+ if (/%2e%2e/i.test(inputPath)) return false;
|
|
|
+ // Block absolute paths (path.join collapses them, bypassing prefix)
|
|
|
+ if (inputPath.startsWith('/') || inputPath.startsWith('\\')) return false;
|
|
|
+ // Block Windows drive letter absolute paths (e.g. C:\)
|
|
|
+ if (/^[a-zA-Z]:[/\\]/.test(inputPath)) return false;
|
|
|
+ // Block null bytes
|
|
|
+ if (inputPath.includes('\0')) return false;
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 检测指定路径下是否存在 novel_project.json,判断是否为有效项目目录
|
|
|
+ */
|
|
|
+export async function isValidProject(projectPath: string): Promise<boolean> {
|
|
|
+ try {
|
|
|
+ await access(path.join(projectPath, 'novel_project.json'));
|
|
|
+ return true;
|
|
|
+ } catch {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|