View source
<?php
namespace Drupal\Tests\system\Unit\Event;
use Drupal\Core\File\Event\FileUploadSanitizeNameEvent;
use Drupal\system\EventSubscriber\SecurityFileUploadEventSubscriber;
use Drupal\Tests\UnitTestCase;
class SecurityFileUploadEventSubscriberTest extends UnitTestCase {
public function testSanitizeName(string $filename, string $allowed_extensions, string $expected_filename, string $expected_filename_with_insecure_uploads = NULL) {
$config_factory = $this
->getConfigFactoryStub([
'system.file' => [
'allow_insecure_uploads' => FALSE,
],
]);
$subscriber = new SecurityFileUploadEventSubscriber($config_factory);
$event = new FileUploadSanitizeNameEvent($filename, $allowed_extensions);
$subscriber
->sanitizeName($event);
$this
->assertSame($expected_filename, $event
->getFilename());
$this
->assertSame($expected_filename !== $filename, $event
->isSecurityRename());
$config_factory = $this
->getConfigFactoryStub([
'system.file' => [
'allow_insecure_uploads' => TRUE,
],
]);
$subscriber = new SecurityFileUploadEventSubscriber($config_factory);
$event = new FileUploadSanitizeNameEvent($filename, $allowed_extensions);
$subscriber
->sanitizeName($event);
$expected_filename_with_insecure_uploads = $expected_filename_with_insecure_uploads ?? $expected_filename;
$this
->assertSame($expected_filename_with_insecure_uploads, $event
->getFilename());
$this
->assertSame($expected_filename_with_insecure_uploads !== $filename, $event
->isSecurityRename());
}
public function provideFilenames() {
return [
'All extensions allowed filename not munged' => [
'foo.txt',
'',
'foo.txt',
],
'All extensions allowed with .php file' => [
'foo.php',
'',
'foo.php_.txt',
'foo.php',
],
'All extensions allowed with .pHp file' => [
'foo.pHp',
'',
'foo.pHp_.txt',
'foo.pHp',
],
'All extensions allowed with .PHP file' => [
'foo.PHP',
'',
'foo.PHP_.txt',
'foo.PHP',
],
'.php extension allowed with .php file' => [
'foo.php',
'php',
'foo.php',
'foo.php',
],
'.PhP extension allowed with .php file' => [
'foo.php',
'PhP',
'foo.php',
'foo.php',
],
'.php, .txt extension allowed with .php file' => [
'foo.php',
'php txt',
'foo.php_.txt',
'foo.php',
],
'.PhP, .tXt extension allowed with .php file' => [
'foo.php',
'PhP tXt',
'foo.php_.txt',
'foo.php',
],
'no extension produces no errors' => [
'foo',
'',
'foo',
],
'filename is munged' => [
'foo.phar.png.php.jpg',
'jpg png',
'foo.phar_.png_.php_.jpg',
],
'filename is munged regardless of case' => [
'FOO.pHAR.PNG.PhP.jpg',
'jpg png',
'FOO.pHAR_.PNG_.PhP_.jpg',
],
'null bytes are removed' => [
'foo' . chr(0) . '.txt' . chr(0),
'',
'foo.txt',
],
'dot files are renamed' => [
'.htaccess',
'',
'htaccess',
],
];
}
public function testSanitizeNameNoMunge(string $filename, string $allowed_extensions) {
$config_factory = $this
->getConfigFactoryStub([
'system.file' => [
'allow_insecure_uploads' => FALSE,
],
]);
$subscriber = new SecurityFileUploadEventSubscriber($config_factory);
$event = new FileUploadSanitizeNameEvent($filename, $allowed_extensions);
$subscriber
->sanitizeName($event);
$this
->assertSame($filename, $event
->getFilename());
$this
->assertSame(FALSE, $event
->isSecurityRename());
$config_factory = $this
->getConfigFactoryStub([
'system.file' => [
'allow_insecure_uploads' => TRUE,
],
]);
$event = new FileUploadSanitizeNameEvent($filename, $allowed_extensions);
$subscriber = new SecurityFileUploadEventSubscriber($config_factory);
$subscriber
->sanitizeName($event);
$this
->assertSame($filename, $event
->getFilename());
$this
->assertSame(FALSE, $event
->isSecurityRename());
}
public function provideFilenamesNoMunge() {
return [
'.php is not munged when it would be rejected' => [
'foo.php.php',
'jpg',
],
'.php is not munged when it would be rejected and filename contains null byte character' => [
'foo.' . chr(0) . 'php.php',
'jpg',
],
'extension less files are not munged when they would be rejected' => [
'foo',
'jpg',
],
'dot files are not munged when they would be rejected' => [
'.htaccess',
'jpg png',
],
];
}
}