diff --git a/core/modules/file/file.module b/core/modules/file/file.module index fb2f3484b724a2fec63fc1ab22d744976d543668..ba2c6629601d0f590c7bb14323508ea09eec5e48 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -339,7 +339,14 @@ function file_validate_extensions(FileInterface $file, $extensions) { $errors = []; $regex = '/\.(' . preg_replace('/ +/', '|', preg_quote($extensions)) . ')$/i'; - if (!preg_match($regex, $file->getFilename())) { + // Filename may differ from the basename, for instance in case files migrated + // from D7 file entities. Because of that new files are saved temporarily with + // a generated file name, without the original extension, we will use the + // generated filename property for extension validation only in case of + // temporary files; and use the file system file name in case of permanent + // files. + $subject = $file->isTemporary() ? $file->getFilename() : $file->getFileUri(); + if (!preg_match($regex, $subject)) { $errors[] = t('Only files with the following extensions are allowed: %files-allowed.', ['%files-allowed' => $extensions]); } return $errors; diff --git a/core/modules/file/tests/src/Kernel/ValidatorTest.php b/core/modules/file/tests/src/Kernel/ValidatorTest.php index 1569230385c8eceb694a55831d1344e314496093..27ad4b9df155a212307489956dbc8686042b4905 100644 --- a/core/modules/file/tests/src/Kernel/ValidatorTest.php +++ b/core/modules/file/tests/src/Kernel/ValidatorTest.php @@ -52,6 +52,89 @@ public function testFileValidateExtensions() { $this->assertCount(1, $errors, 'Invalid extension blocked.'); } + /** + * Tests the file_validate_extensions() function. + * + * @param array $file_properties + * The properties of the file being validated. + * @param string[] $extensions + * An array of the allowed file extensions. + * @param string[] $expected_errors + * The expected error messages as string. + * + * @dataProvider providerTestFileValidateExtensionsOnUri + */ + public function testFileValidateExtensionsOnUri(array $file_properties, array $extensions, array $expected_errors) { + $file = File::create($file_properties); + $actual_errors = file_validate_extensions($file, implode(' ', $extensions)); + $actual_errors_as_string = array_map(function ($error_message) { + return (string) $error_message; + }, $actual_errors); + $this->assertEquals($expected_errors, $actual_errors_as_string); + } + + /** + * Data provider for ::testFileValidateExtensionsOnUri. + * + * @return array[][] + * The test cases. + */ + public function providerTestFileValidateExtensionsOnUri(): array { + $temporary_txt_file_properties = [ + 'filename' => 'asdf.txt', + 'uri' => 'temporary://asdf', + 'status' => 0, + ]; + $permanent_txt_file_properties = [ + 'filename' => 'asdf.txt', + 'uri' => 'public://asdf_0.txt', + 'status' => 1, + ]; + $permanent_png_file_properties = [ + 'filename' => 'The Druplicon', + 'uri' => 'public://druplicon.png', + 'status' => 1, + ]; + return [ + 'Temporary txt validated with "asdf", "txt", "pork"' => [ + 'File properties' => $temporary_txt_file_properties, + 'Allowed_extensions' => ['asdf', 'txt', 'pork'], + 'Expected errors' => [], + ], + 'Temporary txt validated with "exe" and "png"' => [ + 'File properties' => $temporary_txt_file_properties, + 'Allowed_extensions' => ['exe', 'png'], + 'Expected errors' => [ + 'Only files with the following extensions are allowed: <em class="placeholder">exe png</em>.', + ], + ], + 'Permanent txt validated with "asdf", "txt", "pork"' => [ + 'File properties' => $permanent_txt_file_properties, + 'Allowed_extensions' => ['asdf', 'txt', 'pork'], + 'Expected errors' => [], + ], + 'Permanent txt validated with "exe" and "png"' => [ + 'File properties' => $permanent_txt_file_properties, + 'Allowed_extensions' => ['exe', 'png'], + 'Expected errors' => [ + 'Only files with the following extensions are allowed: <em class="placeholder">exe png</em>.', + ], + ], + 'Permanent png validated with "png", "gif", "jpg", "jpeg"' => [ + 'File properties' => $permanent_png_file_properties, + 'Allowed_extensions' => ['png', 'gif', 'jpg', 'jpeg'], + 'Expected errors' => [], + ], + 'Permanent png validated with "exe" and "txt"' => [ + 'File properties' => $permanent_png_file_properties, + 'Allowed_extensions' => ['exe', 'txt'], + 'Expected errors' => [ + 'Only files with the following extensions are allowed: <em class="placeholder">exe txt</em>.', + ], + ], + ]; + } + /** * This ensures a specific file is actually an image. */