Files
NetMesh/electron/bridges/terminalBridge/pathValidation.cjs

88 lines
3.4 KiB
JavaScript
Raw Normal View History

/* eslint-disable no-undef */
function createPathValidationApi(ctx) {
with (ctx) {
function getDefaultShell() {
return getDefaultLocalShell();
}
/**
* Validate a path - check if it exists and whether it's a file or directory
* @param {object} event - IPC event
* @param {object} payload - Contains { path: string, type?: 'file' | 'directory' | 'any' }
* @returns {{ exists: boolean, isFile: boolean, isDirectory: boolean, isExecutable: boolean }}
*
* `isExecutable` mirrors isExecutableFile(): POSIX requires the file mode
* to have an execute bit; Win32 treats any regular file as executable
* (NTFS lacks POSIX bits extension/PATHEXT decides at spawn time).
* Existing callers ignore the new field; consumers that need exec
* semantics (e.g. Mosh client path) read it explicitly.
*/
function statIsExecutable(stat) {
if (!stat || !stat.isFile()) return false;
if (process.platform === "win32") return true;
return (stat.mode & 0o111) !== 0;
}
function validatePath(event, payload) {
const targetPath = payload?.path;
const type = payload?.type || 'any';
if (!targetPath) {
return { exists: false, isFile: false, isDirectory: false, isExecutable: false };
}
try {
// Resolve path (handle ~, etc.)
let resolvedPath = expandHomePath(targetPath);
resolvedPath = path.resolve(resolvedPath);
if (fs.existsSync(resolvedPath)) {
const stat = fs.statSync(resolvedPath);
return {
exists: true,
isFile: stat.isFile(),
isDirectory: stat.isDirectory(),
isExecutable: statIsExecutable(stat),
};
}
// If type is 'file' and path doesn't exist, try to resolve via PATH (for executables like cmd.exe, powershell.exe)
if (type === 'file') {
const resolvedExecutable = findExecutable(targetPath);
// findExecutable returns the original name if not found, so check if it actually resolves to a real path
if (resolvedExecutable !== targetPath && fs.existsSync(resolvedExecutable)) {
const stat = fs.statSync(resolvedExecutable);
return {
exists: true,
isFile: stat.isFile(),
isDirectory: stat.isDirectory(),
isExecutable: statIsExecutable(stat),
};
}
// Also try with .exe extension on Windows if not already present
if (process.platform === 'win32' && !targetPath.toLowerCase().endsWith('.exe')) {
const withExe = findExecutable(targetPath + '.exe');
if (withExe !== targetPath + '.exe' && fs.existsSync(withExe)) {
const stat = fs.statSync(withExe);
return {
exists: true,
isFile: stat.isFile(),
isDirectory: stat.isDirectory(),
isExecutable: statIsExecutable(stat),
};
}
}
}
return { exists: false, isFile: false, isDirectory: false, isExecutable: false };
} catch (err) {
console.warn(`[Terminal] Error validating path "${targetPath}":`, err.message);
return { exists: false, isFile: false, isDirectory: false, isExecutable: false };
}
}
return { getDefaultShell, validatePath };
}
}
module.exports = { createPathValidationApi };