53 lines
1.6 KiB
TypeScript
53 lines
1.6 KiB
TypeScript
/**
|
|
* Normalizes file paths for browser/ Obsidian environment
|
|
* Replaces multiple slashes with single slash and handles forward/backward slashes
|
|
*/
|
|
export function normalizePath(path: string): string {
|
|
// Replace multiple slashes with single slash
|
|
let normalized = path.replace(/[\\\/]+/g, '/');
|
|
|
|
// Remove trailing slash unless it's the root
|
|
if (normalized.length > 1 && normalized.endsWith('/')) {
|
|
normalized = normalized.slice(0, -1);
|
|
}
|
|
|
|
return normalized;
|
|
}
|
|
|
|
/**
|
|
* Validates a path string for safety (no traversal, no absolute paths, no invalid chars)
|
|
*/
|
|
export function validatePath(path: string): { valid: boolean; error?: string } {
|
|
const normalized = normalizePath(path);
|
|
|
|
// Check for path traversal by looking for .. as a path segment (not just substring in filenames)
|
|
const segments = normalized.split('/');
|
|
if (segments.includes('..')) {
|
|
return { valid: false, error: 'Path traversal not allowed' };
|
|
}
|
|
|
|
// Check if absolute path
|
|
if (normalized.startsWith('/') || normalized.startsWith('\\')) {
|
|
return { valid: false, error: 'Absolute paths not allowed' };
|
|
}
|
|
|
|
// Check for windows drive letters
|
|
if (/^[a-zA-Z]:/.test(normalized)) {
|
|
return { valid: false, error: 'Absolute paths not allowed' };
|
|
}
|
|
|
|
// Check for invalid characters
|
|
const invalidChars = /[\<\>\:\"\|\\\?\*~]/;
|
|
if (invalidChars.test(path)) {
|
|
return { valid: false, error: 'Path contains illegal characters' };
|
|
}
|
|
|
|
// Check path length
|
|
const MAX_PATH_LENGTH = 200;
|
|
if (path.length > MAX_PATH_LENGTH) {
|
|
return { valid: false, error: 'Path too long' };
|
|
}
|
|
|
|
return { valid: true };
|
|
}
|