import { resolve, sep } from "node:path";
/**
 * Validate that a user-supplied name is safe for use as a filename.
 * Rejects path traversal, path separators, and OS-reserved characters.
 */
export function validateFilename(name) {
    if (!name || name.trim().length === 0) {
        throw new Error("Filename must not be empty");
    }
    if (name.includes("..")) {
        throw new Error("Filename must not contain '..'");
    }
    if (/[/\\]/.test(name)) {
        throw new Error("Filename must not contain path separators (/ or \\)");
    }
    // Windows reserved characters: < > : " | ? *
    if (/[<>:"|?*]/.test(name)) {
        throw new Error("Filename contains invalid characters");
    }
    // Windows reserved names
    const reserved = /^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])(\.|$)/i;
    if (reserved.test(name)) {
        throw new Error(`Filename uses reserved name: ${name}`);
    }
}
/**
 * Validate that a name is a valid Enforce Script identifier.
 * Must start with a letter or underscore, followed by letters, digits, or underscores.
 */
export function validateEnforceIdentifier(name) {
    if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
        throw new Error("Must be a valid Enforce identifier (letters, digits, underscores only, must start with a letter or underscore)");
    }
}
/**
 * Check that resolved is equal to or contained within normalizedBase.
 * Uses trailing separator to prevent prefix collisions (e.g., C:\Proj vs C:\ProjEvil).
 */
function isContained(normalizedBase, resolved) {
    return resolved === normalizedBase || resolved.startsWith(normalizedBase + sep);
}
/**
 * Validate that a resolved path stays within the base directory.
 * Combines validateFilename + traversal check.
 */
export function safePath(basePath, ...segments) {
    for (const seg of segments) {
        validateFilename(seg);
    }
    const normalizedBase = resolve(basePath);
    const resolved = resolve(normalizedBase, ...segments);
    if (!isContained(normalizedBase, resolved)) {
        throw new Error("Path traversal not allowed: resolved path is outside project");
    }
    return resolved;
}
/**
 * Validate a relative sub-path (which may contain slashes) stays within the base directory.
 * Used by project_read / project_write / project_browse for user-supplied relative paths.
 */
export function validateProjectPath(basePath, subPath) {
    if (subPath.includes("..")) {
        throw new Error("Path traversal not allowed: '..' segments are blocked");
    }
    const normalizedBase = resolve(basePath);
    const resolved = resolve(normalizedBase, subPath);
    if (!isContained(normalizedBase, resolved)) {
        throw new Error("Path traversal not allowed: resolved path is outside project");
    }
    return resolved;
}
//# sourceMappingURL=safe-path.js.map