diff --git a/composer.json b/composer.json index afc5753b3f952297303a97142d7017039f6dbbe6..63245129bfbc2535b65485b3f1e2abc10242a3c5 100644 --- a/composer.json +++ b/composer.json @@ -87,6 +87,7 @@ "symfony/messenger": "^6.2", "symfony/mime": "^6.2", "symfony/options-resolver": "^6.2", + "symfony/polyfill-intl-normalizer": "^1.27", "symfony/property-access": "^6.2", "symfony/property-info": "^6.2.11", "symfony/rate-limiter": "^6.2", diff --git a/composer.lock b/composer.lock index 5263cc7e860a7c55507dfd366bab44eab3ea9854..032e3a252b48e4a822c502ecd3be1dfc3a323ccc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e692c4b3082cbc8207fa2e0897d31ca9", + "content-hash": "7396b099be92db1ca53986a033f316ff", "packages": [ { "name": "bacon/bacon-qr-code", diff --git a/typo3/sysext/core/Classes/Http/UploadedFile.php b/typo3/sysext/core/Classes/Http/UploadedFile.php index 6f1da82864f4cbd04d646326ab0551fd2845ab70..99f3b5013c8433c61e6a68de0bf830177f9e6425 100644 --- a/typo3/sysext/core/Classes/Http/UploadedFile.php +++ b/typo3/sysext/core/Classes/Http/UploadedFile.php @@ -74,7 +74,10 @@ class UploadedFile implements UploadedFileInterface } $this->error = $errorStatus; - $this->clientFilename = $clientFilename; + if ($clientFilename !== null) { + $clientFilename = \Normalizer::normalize($clientFilename); + } + $this->clientFilename = is_string($clientFilename) ? $clientFilename : null; $this->clientMediaType = $clientMediaType; } diff --git a/typo3/sysext/core/Classes/Resource/ResourceStorage.php b/typo3/sysext/core/Classes/Resource/ResourceStorage.php index 8c6879412b2ff5dc37c7c6d8f88bb9227eb87fd0..bdfcafa4829579b5105ea484a7bd2cb0cf115c3f 100644 --- a/typo3/sysext/core/Classes/Resource/ResourceStorage.php +++ b/typo3/sysext/core/Classes/Resource/ResourceStorage.php @@ -2098,7 +2098,7 @@ class ResourceStorage implements ResourceStorageInterface } else { $localFilePath = $uploadedFileData['tmp_name']; if ($targetFileName === null) { - $targetFileName = $uploadedFileData['name']; + $targetFileName = \Normalizer::normalize($uploadedFileData['name']); } $size = $uploadedFileData['size']; } diff --git a/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php b/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php index 8291fa248930b05beb3192da50c2fa92ca120846..ea30d53b89d7cb87182f5cabc84fe71079fe4327 100644 --- a/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php +++ b/typo3/sysext/core/Classes/Utility/File/ExtendedFileUtility.php @@ -1049,6 +1049,7 @@ class ExtendedFileUtility extends BasicFileUtility 'size' => [$uploadedFileData['size']], ]; } + $uploadedFileData['name'] = array_map(\Normalizer::normalize(...), $uploadedFileData['name']); $resultObjects = []; $numberOfUploadedFilesForPosition = count($uploadedFileData['name']); // Loop through all uploaded files diff --git a/typo3/sysext/core/Tests/Unit/Http/UploadedFileTest.php b/typo3/sysext/core/Tests/Unit/Http/UploadedFileTest.php index c24c399381bc763b99f8ba477c025deba3f69267..517eebaa70ab64517b033f27ee9fee1c4f7f9afc 100644 --- a/typo3/sysext/core/Tests/Unit/Http/UploadedFileTest.php +++ b/typo3/sysext/core/Tests/Unit/Http/UploadedFileTest.php @@ -180,4 +180,15 @@ final class UploadedFileTest extends UnitTestCase $this->expectExceptionCode(1436717306); $upload->getStream(); } + + /** + * see https://en.wikipedia.org/wiki/Unicode_equivalence#Normalization, "NFD" + * @test + */ + public function nfdFileNameIsNormalized(): void + { + $clientFileName = hex2bin('6fcc88') . '.png'; + $subject = new UploadedFile(fopen('php://temp', 'wb+'), 0, 0, $clientFileName); + self::assertSame(hex2bin('c3b6') . '.png', $subject->getClientFilename()); + } } diff --git a/typo3/sysext/core/composer.json b/typo3/sysext/core/composer.json index a60489d9509885aa23dcf66b4fc4ee0298bca13f..294a0358f623da383424815cc78467a4be63f87c 100644 --- a/typo3/sysext/core/composer.json +++ b/typo3/sysext/core/composer.json @@ -66,6 +66,7 @@ "symfony/messenger": "^6.2", "symfony/mime": "^6.2", "symfony/options-resolver": "^6.2", + "symfony/polyfill-intl-normalizer": "^1.27", "symfony/rate-limiter": "^6.2", "symfony/routing": "^6.2", "symfony/uid": "^6.2",