You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	Windows: Fixes #10525: Prevent notes with titles that differ only in case from being overwritten when exporting (#10541)
This commit is contained in:
		| @@ -152,13 +152,21 @@ export default class FsDriverBase { | ||||
| 		} | ||||
| 		let counter = 1; | ||||
|  | ||||
| 		// On Windows, ./FiLe.md and ./file.md are equivalent file paths. | ||||
| 		// As such, to avoid overwriting reserved names, comparisons need to be | ||||
| 		// case-insensitive. | ||||
| 		reservedNames = reservedNames.map(name => name.toLowerCase()); | ||||
| 		const isReserved = (testName: string) => { | ||||
| 			return reservedNames.includes(testName.toLowerCase()); | ||||
| 		}; | ||||
|  | ||||
| 		const nameNoExt = filename(name, true); | ||||
| 		let extension = fileExtension(name); | ||||
| 		if (extension) extension = `.${extension}`; | ||||
| 		let nameToTry = nameNoExt + extension; | ||||
| 		while (true) { | ||||
| 			// Check if the filename does not exist in the filesystem and is not reserved | ||||
| 			const exists = await this.exists(nameToTry) || reservedNames.includes(nameToTry); | ||||
| 			const exists = await this.exists(nameToTry) || isReserved(nameToTry); | ||||
| 			if (!exists) return nameToTry; | ||||
| 			if (!markdownSafe) { | ||||
| 				nameToTry = `${nameNoExt} (${counter})${extension}`; | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| import { join } from 'path'; | ||||
| import FsDriverNode from './fs-driver-node'; | ||||
| import shim from './shim'; | ||||
| import { expectThrow } from './testing/test-utils'; | ||||
| import { expectThrow, supportDir } from './testing/test-utils'; | ||||
|  | ||||
| const windowsPartitionLetter = __filename[0]; | ||||
|  | ||||
| @@ -15,7 +16,6 @@ function platformPath(path: string) { | ||||
| } | ||||
|  | ||||
| describe('fsDriver', () => { | ||||
|  | ||||
| 	it('should resolveRelativePathWithinDir', async () => { | ||||
| 		const fsDriver = new FsDriverNode(); | ||||
| 		expect(fsDriver.resolveRelativePathWithinDir('/test/temp', './my/file.txt').toLowerCase()).toBe(platformPath('/test/temp/my/file.txt')); | ||||
| @@ -28,4 +28,18 @@ describe('fsDriver', () => { | ||||
| 		await expectThrow(() => fsDriver.resolveRelativePathWithinDir('/test/temp', '/var/local/no.txt')); | ||||
| 	}); | ||||
|  | ||||
| 	it('should compare reserved names in a case-insensitive way in findUniqueFilename', async () => { | ||||
| 		// Compare with filenames in the reserved list should be case insensitive | ||||
| 		expect( | ||||
| 			await shim.fsDriver().findUniqueFilename( | ||||
| 				join(supportDir, 'this-file-does-not-exist.txt'), | ||||
| 				[join(supportDir, 'THIS-file-does-not-exist.txt'), join(supportDir, 'THIS-file-DOES-not-exist (1).txt')], | ||||
| 			), | ||||
| 		).toBe(join(supportDir, 'this-file-does-not-exist (2).txt')); | ||||
|  | ||||
| 		// Should still not match reserved names that aren't equivalent. | ||||
| 		expect( | ||||
| 			await shim.fsDriver().findUniqueFilename(join(supportDir, 'this-file-does-not-exist.txt'), [join(supportDir, 'some-other-file.txt')]), | ||||
| 		).toBe(join(supportDir, 'this-file-does-not-exist.txt')); | ||||
| 	}); | ||||
| }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user