You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-11-29 22:48:10 +02:00
This commit is contained in:
38
packages/lib/utils/resolvePathWithinDir.test.ts
Normal file
38
packages/lib/utils/resolvePathWithinDir.test.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import resolvePathWithinDir from './resolvePathWithinDir';
|
||||
|
||||
describe('resolvePathWithinDir', () => {
|
||||
test('should return correct values for Unix-style paths', () => {
|
||||
const testCases = [
|
||||
// Absolute paths
|
||||
{ baseDir: '/a/test/path/', path: '/a/test/path/test.txt', expected: '/a/test/path/test.txt' },
|
||||
{ baseDir: '/a/test/path/', path: '/a/test/path/..test.txt', expected: '/a/test/path/..test.txt' },
|
||||
{ baseDir: '/a/test/path/', path: '/a/test/path/.test.txt', expected: '/a/test/path/.test.txt' },
|
||||
{ baseDir: '/a/test/path', path: '/a/test/path/.test.txt', expected: '/a/test/path/.test.txt' },
|
||||
{ baseDir: '/a/test/path', path: '/a/test/path', expected: '/a/test/path' },
|
||||
{ baseDir: '/a/test/path', path: '/a/', expected: null },
|
||||
{ baseDir: '/a/test/path', path: '/a/test/', expected: null },
|
||||
{ baseDir: '/a/test/path', path: '/a/test/pa', expected: null },
|
||||
{ baseDir: '/a/test/path', path: '/a/test/path2', expected: null },
|
||||
{ baseDir: '/a/test/path', path: '/a/test/path\\//subdir', expected: null },
|
||||
|
||||
// Relative paths
|
||||
{ baseDir: '/a/test/path', path: './test', expected: '/a/test/path/test' },
|
||||
{ baseDir: '/a/test/path', path: '../path/test/2', expected: '/a/test/path/test/2' },
|
||||
{ baseDir: '/a/test/path', path: '../path/test/../../../2', expected: null },
|
||||
{ baseDir: '/a/test/path', path: '../test', expected: null },
|
||||
];
|
||||
|
||||
for (const testCase of testCases) {
|
||||
expect(resolvePathWithinDir(testCase.baseDir, testCase.path, false)).toBe(testCase.expected);
|
||||
}
|
||||
});
|
||||
|
||||
test('should return correct values for Windows-style paths', () => {
|
||||
expect(resolvePathWithinDir('C:\\a\\test\\path', 'C:\\a\\test\\path\\2', true)).toBe('C:\\a\\test\\path\\2');
|
||||
expect(resolvePathWithinDir('C:\\\\a\\test\\path', '.\\path\\2', true)).toBe('C:\\a\\test\\path\\path\\2');
|
||||
expect(resolvePathWithinDir('C:\\a\\test\\path', '..\\path\\2', true)).toBe('C:\\a\\test\\path\\2');
|
||||
expect(resolvePathWithinDir('C:\\a\\test\\path', '..\\2', true)).toBe(null);
|
||||
expect(resolvePathWithinDir('D:\\a\\test\\path', 'C:\\a\\test\\path\\2', true)).toBe(null);
|
||||
expect(resolvePathWithinDir('\\a\\test\\path', 'D:\\a\\test\\path\\2', true)).toBe(null);
|
||||
});
|
||||
});
|
||||
45
packages/lib/utils/resolvePathWithinDir.ts
Normal file
45
packages/lib/utils/resolvePathWithinDir.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
import * as path from 'path';
|
||||
|
||||
// Returns `null` if `relativePath` is not within `baseDir` and `relativePath`
|
||||
// resolved to an absolute path otherwise.
|
||||
//
|
||||
// `relativePath` can be either relative or absolute.
|
||||
// If relative, it is assumed to be relative to `baseDir`.
|
||||
//
|
||||
// It is expected that baseDir is a safe path (not user-provided).
|
||||
const resolvePathWithinDir = (
|
||||
baseDir: string, relativePath: string,
|
||||
|
||||
// For testing
|
||||
forceWin32Paths?: boolean,
|
||||
) => {
|
||||
let pathModule = path;
|
||||
if (forceWin32Paths === true) {
|
||||
pathModule = path.win32;
|
||||
}
|
||||
|
||||
let resolvedBaseDir = pathModule.resolve(baseDir);
|
||||
const resolvedPath = pathModule.resolve(baseDir, relativePath);
|
||||
|
||||
// Handles the case where resolvedBaseDir doesn't end with a
|
||||
// path separator. For example, if
|
||||
// resolvedBaseDir="/foo/bar"
|
||||
// then we could have
|
||||
// resolvedPath="/foo/bar2"
|
||||
// which is not within the "/foo/bar" directory.
|
||||
//
|
||||
// We can't do this if the two paths are already equal as (as this would cause
|
||||
// resolvedPath to no longer start with resolvedBaseDir).
|
||||
if (!resolvedBaseDir.endsWith(pathModule.sep) && resolvedBaseDir !== resolvedPath) {
|
||||
resolvedBaseDir += pathModule.sep;
|
||||
}
|
||||
|
||||
if (!resolvedPath.startsWith(resolvedBaseDir)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return resolvedPath;
|
||||
};
|
||||
|
||||
export default resolvePathWithinDir;
|
||||
Reference in New Issue
Block a user