Skip to content

Commit 7e47231

Browse files
authored
Merge pull request from GHSA-mwvh-p3hx-x4gg
1 parent 8ef0e70 commit 7e47231

File tree

12 files changed

+134
-34
lines changed

12 files changed

+134
-34
lines changed

eZ/Publish/Core/FieldType/BinaryBase/BinaryBaseStorage.php

+23-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
*/
77
namespace eZ\Publish\Core\FieldType\BinaryBase;
88

9+
use eZ\Publish\Core\Base\Exceptions\ContentFieldValidationException;
10+
use eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator;
911
use eZ\Publish\Core\IO\IOServiceInterface;
1012
use eZ\Publish\SPI\FieldType\BinaryBase\PathGenerator;
1113
use eZ\Publish\SPI\FieldType\BinaryBase\RouteAwarePathGenerator;
@@ -39,24 +41,21 @@ class BinaryBaseStorage extends GatewayBasedStorage
3941
/** @var \eZ\Publish\Core\FieldType\BinaryBase\BinaryBaseStorage\Gateway */
4042
protected $gateway;
4143

42-
/**
43-
* Construct from gateways.
44-
*
45-
* @param \eZ\Publish\SPI\FieldType\StorageGateway $gateway
46-
* @param \eZ\Publish\Core\IO\IOServiceInterface $ioService
47-
* @param \eZ\Publish\SPI\FieldType\BinaryBase\PathGenerator $pathGenerator
48-
* @param \eZ\Publish\SPI\IO\MimeTypeDetector $mimeTypeDetector
49-
*/
44+
/** @var \eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator */
45+
protected $fileExtensionBlackListValidator;
46+
5047
public function __construct(
5148
StorageGateway $gateway,
5249
IOServiceInterface $ioService,
5350
PathGenerator $pathGenerator,
54-
MimeTypeDetector $mimeTypeDetector
51+
MimeTypeDetector $mimeTypeDetector,
52+
FileExtensionBlackListValidator $fileExtensionBlackListValidator
5553
) {
5654
parent::__construct($gateway);
5755
$this->ioService = $ioService;
5856
$this->pathGenerator = $pathGenerator;
5957
$this->mimeTypeDetector = $mimeTypeDetector;
58+
$this->fileExtensionBlackListValidator = $fileExtensionBlackListValidator;
6059
}
6160

6261
/**
@@ -67,6 +66,10 @@ public function setDownloadUrlGenerator(PathGenerator $downloadUrlGenerator)
6766
$this->downloadUrlGenerator = $downloadUrlGenerator;
6867
}
6968

69+
/**
70+
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
71+
* @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
72+
*/
7073
public function storeFieldData(VersionInfo $versionInfo, Field $field, array $context)
7174
{
7275
if ($field->value->externalData === null) {
@@ -76,6 +79,17 @@ public function storeFieldData(VersionInfo $versionInfo, Field $field, array $co
7679
}
7780

7881
if (isset($field->value->externalData['inputUri'])) {
82+
$this->fileExtensionBlackListValidator->validateFileExtension($field->value->externalData['fileName']);
83+
if (!empty($errors = $this->fileExtensionBlackListValidator->getErrors())) {
84+
$preparedErrors = [];
85+
$preparedErrors[$field->fieldDefinitionId][$field->languageCode] = $errors;
86+
87+
throw ContentFieldValidationException::createNewWithMultiline(
88+
$preparedErrors,
89+
$versionInfo->contentInfo->name
90+
);
91+
}
92+
7993
$field->value->externalData['mimeType'] = $this->mimeTypeDetector->getFromPath($field->value->externalData['inputUri']);
8094
$createStruct = $this->ioService->newBinaryCreateStructFromLocalFile($field->value->externalData['inputUri']);
8195
$createStruct->id = $this->pathGenerator->getStoragePathForField($field, $versionInfo);

eZ/Publish/Core/FieldType/Image/ImageStorage.php

+25-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
*/
77
namespace eZ\Publish\Core\FieldType\Image;
88

9+
use eZ\Publish\Core\Base\Exceptions\ContentFieldValidationException;
910
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
1011
use eZ\Publish\Core\Base\Utils\DeprecationWarnerInterface as DeprecationWarner;
12+
use eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator;
1113
use eZ\Publish\Core\IO\FilePathNormalizerInterface;
1214
use eZ\Publish\Core\IO\IOServiceInterface;
1315
use eZ\Publish\Core\IO\MetadataHandler;
@@ -42,14 +44,18 @@ class ImageStorage extends GatewayBasedStorage
4244
/** @var \eZ\Publish\Core\IO\FilePathNormalizerInterface */
4345
protected $filePathNormalizer;
4446

47+
/** @var \eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator */
48+
protected $fileExtensionBlackListValidator;
49+
4550
public function __construct(
4651
StorageGateway $gateway,
4752
IOServiceInterface $ioService,
4853
PathGenerator $pathGenerator,
4954
MetadataHandler $imageSizeMetadataHandler,
5055
DeprecationWarner $deprecationWarner,
5156
AliasCleanerInterface $aliasCleaner,
52-
FilePathNormalizerInterface $filePathNormalizer
57+
FilePathNormalizerInterface $filePathNormalizer,
58+
FileExtensionBlackListValidator $fileExtensionBlackListValidator
5359
) {
5460
parent::__construct($gateway);
5561
$this->ioService = $ioService;
@@ -58,8 +64,15 @@ public function __construct(
5864
$this->deprecationWarner = $deprecationWarner;
5965
$this->aliasCleaner = $aliasCleaner;
6066
$this->filePathNormalizer = $filePathNormalizer;
67+
$this->fileExtensionBlackListValidator = $fileExtensionBlackListValidator;
6168
}
6269

70+
/**
71+
* @throws \eZ\Publish\Core\Base\Exceptions\NotFoundException
72+
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue
73+
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException
74+
* @throws \eZ\Publish\Core\Base\Exceptions\ContentFieldValidationException
75+
*/
6376
public function storeFieldData(VersionInfo $versionInfo, Field $field, array $context)
6477
{
6578
$contentMetaData = [
@@ -70,6 +83,17 @@ public function storeFieldData(VersionInfo $versionInfo, Field $field, array $co
7083

7184
// new image
7285
if (isset($field->value->externalData)) {
86+
$this->fileExtensionBlackListValidator->validateFileExtension($field->value->externalData['fileName']);
87+
if (!empty($errors = $this->fileExtensionBlackListValidator->getErrors())) {
88+
$preparedErrors = [];
89+
$preparedErrors[$field->fieldDefinitionId][$field->languageCode] = $errors;
90+
91+
throw ContentFieldValidationException::createNewWithMultiline(
92+
$preparedErrors,
93+
$versionInfo->contentInfo->name
94+
);
95+
}
96+
7397
$targetPath = sprintf(
7498
'%s/%s',
7599
$this->pathGenerator->getStoragePathForField(

eZ/Publish/Core/FieldType/Tests/BinaryFileTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ public function provideInvalidDataForValidate()
595595
),
596596
[
597597
new ValidationError(
598-
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
598+
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
599599
null,
600600
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
601601
'fileExtensionBlackList'
@@ -623,7 +623,7 @@ public function provideInvalidDataForValidate()
623623
),
624624
[
625625
new ValidationError(
626-
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
626+
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
627627
null,
628628
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
629629
'fileExtensionBlackList'

eZ/Publish/Core/FieldType/Tests/ImageTest.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ public function provideInvalidDataForValidate()
711711
),
712712
[
713713
new ValidationError(
714-
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
714+
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
715715
null,
716716
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
717717
'fileExtensionBlackList'
@@ -743,7 +743,7 @@ public function provideInvalidDataForValidate()
743743
),
744744
[
745745
new ValidationError(
746-
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
746+
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
747747
null,
748748
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
749749
'fileExtensionBlackList'
@@ -778,7 +778,7 @@ public function provideInvalidDataForValidate()
778778
),
779779
[
780780
new ValidationError(
781-
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
781+
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
782782
null,
783783
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
784784
'fileExtensionBlackList'
@@ -810,7 +810,7 @@ public function provideInvalidDataForValidate()
810810
),
811811
[
812812
new ValidationError(
813-
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
813+
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
814814
null,
815815
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
816816
'fileExtensionBlackList'

eZ/Publish/Core/FieldType/Tests/Integration/BinaryBase/BinaryBaseStorage/BinaryBaseStorageTest.php

+8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use eZ\Publish\Core\FieldType\BinaryBase\BinaryBaseStorage\Gateway;
1414
use eZ\Publish\Core\FieldType\BinaryFile\BinaryFileStorage\Gateway\DoctrineStorage;
1515
use eZ\Publish\Core\FieldType\Tests\Integration\BaseCoreFieldTypeIntegrationTest;
16+
use eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator;
1617
use eZ\Publish\Core\IO\IOServiceInterface;
1718
use eZ\Publish\Core\IO\Values\BinaryFile;
1819
use eZ\Publish\Core\IO\Values\BinaryFileCreateStruct;
@@ -36,13 +37,19 @@ class BinaryBaseStorageTest extends BaseCoreFieldTypeIntegrationTest
3637
/** @var \eZ\Publish\Core\FieldType\BinaryBase\BinaryBaseStorage|\PHPUnit\Framework\MockObject\MockObject */
3738
protected $storage;
3839

40+
/** @var \eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator&\PHPUnit\Framework\MockObject\MockObject */
41+
protected $fileExtensionBlackListValidatorMock;
42+
3943
protected function setUp(): void
4044
{
4145
parent::setUp();
4246

4347
$this->gateway = $this->getStorageGateway();
4448
$this->pathGeneratorMock = $this->createMock(PathGenerator::class);
4549
$this->ioServiceMock = $this->createMock(IOServiceInterface::class);
50+
$this->fileExtensionBlackListValidatorMock = $this->createMock(
51+
FileExtensionBlackListValidator::class
52+
);
4653
$this->storage = $this->getMockBuilder(BinaryBaseStorage::class)
4754
->onlyMethods([])
4855
->setConstructorArgs(
@@ -51,6 +58,7 @@ protected function setUp(): void
5158
$this->ioServiceMock,
5259
$this->pathGeneratorMock,
5360
$this->createMock(MimeTypeDetector::class),
61+
$this->fileExtensionBlackListValidatorMock,
5462
]
5563
)
5664
->getMock();

eZ/Publish/Core/FieldType/Tests/MediaTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ public function provideInvalidDataForValidate()
761761
),
762762
[
763763
new ValidationError(
764-
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
764+
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
765765
null,
766766
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
767767
'fileExtensionBlackList'

eZ/Publish/Core/FieldType/Validator/FileExtensionBlackListValidator.php

+23-6
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,40 @@ public function validateConstraints($constraints)
4646
* {@inheritdoc}
4747
*/
4848
public function validate(BaseValue $value)
49+
{
50+
$this->errors = [];
51+
52+
$this->validateFileExtension($value->fileName);
53+
54+
return empty($this->errors);
55+
}
56+
57+
public function validateFileExtension(string $fileName): void
4958
{
5059
if (
51-
pathinfo($value->fileName, PATHINFO_BASENAME) !== $value->fileName ||
52-
in_array(strtolower(pathinfo($value->fileName, PATHINFO_EXTENSION)), $this->constraints['extensionsBlackList'], true)
60+
pathinfo($fileName, PATHINFO_BASENAME) !== $fileName
61+
|| in_array(
62+
strtolower(pathinfo($fileName, PATHINFO_EXTENSION)),
63+
$this->constraints['extensionsBlackList'],
64+
true
65+
)
5366
) {
5467
$this->errors[] = new ValidationError(
55-
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
68+
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
5669
null,
5770
[
5871
'%extensionsBlackList%' => implode(', ', $this->constraints['extensionsBlackList']),
5972
],
6073
'fileExtensionBlackList'
6174
);
62-
63-
return false;
6475
}
76+
}
6577

66-
return true;
78+
/**
79+
* @return array<\eZ\Publish\SPI\FieldType\ValidationError>
80+
*/
81+
public function getErrors(): array
82+
{
83+
return $this->errors;
6784
}
6885
}

eZ/Publish/Core/settings/fieldtype_external_storages.yml

+11-8
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ services:
22
ezpublish.fieldType.ezbinaryfile.externalStorage:
33
class: eZ\Publish\Core\FieldType\BinaryFile\BinaryFileStorage
44
arguments:
5-
- "@ezpublish.fieldType.ezbinaryfile.storage_gateway"
6-
- "@ezpublish.fieldType.ezbinaryfile.io_service"
7-
- "@ezpublish.fieldType.ezbinaryfile.pathGenerator"
8-
- "@ezpublish.core.io.mimeTypeDetector"
5+
$gateway: '@ezpublish.fieldType.ezbinaryfile.storage_gateway'
6+
$ioService: '@ezpublish.fieldType.ezbinaryfile.io_service'
7+
$pathGenerator: '@ezpublish.fieldType.ezbinaryfile.pathGenerator'
8+
$mimeTypeDetector: '@ezpublish.core.io.mimeTypeDetector'
9+
$fileExtensionBlackListValidator: '@ezpublish.fieldType.validator.black_list'
910
tags:
1011
- {name: ezplatform.field_type.external_storage_handler, alias: ezbinaryfile}
1112

@@ -19,6 +20,7 @@ services:
1920
$deprecationWarner: '@ezpublish.utils.deprecation_warner'
2021
$aliasCleaner: '@eZ\Publish\Core\FieldType\Image\AliasCleanerInterface'
2122
$filePathNormalizer: '@eZ\Publish\Core\IO\FilePathNormalizerInterface'
23+
$fileExtensionBlackListValidator: '@ezpublish.fieldType.validator.black_list'
2224
tags:
2325
- {name: ezplatform.field_type.external_storage_handler, alias: ezimage}
2426

@@ -31,10 +33,11 @@ services:
3133
ezpublish.fieldType.ezmedia.externalStorage:
3234
class: eZ\Publish\Core\FieldType\Media\MediaStorage
3335
arguments:
34-
- "@ezpublish.fieldType.ezmedia.storage_gateway"
35-
- "@ezpublish.fieldType.ezbinaryfile.io_service"
36-
- "@ezpublish.fieldType.ezbinaryfile.pathGenerator"
37-
- "@ezpublish.core.io.mimeTypeDetector"
36+
$gateway: '@ezpublish.fieldType.ezmedia.storage_gateway'
37+
$ioService: '@ezpublish.fieldType.ezbinaryfile.io_service'
38+
$pathGenerator: '@ezpublish.fieldType.ezbinaryfile.pathGenerator'
39+
$mimeTypeDetector: '@ezpublish.core.io.mimeTypeDetector'
40+
$fileExtensionBlackListValidator: '@ezpublish.fieldType.validator.black_list'
3841
tags:
3942
- {name: ezplatform.field_type.external_storage_handler, alias: ezmedia}
4043

eZ/Publish/SPI/Tests/FieldType/BinaryFileIntegrationTest.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace eZ\Publish\SPI\Tests\FieldType;
88

99
use eZ\Publish\Core\FieldType;
10+
use eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator;
1011
use eZ\Publish\Core\IO\MimeTypeDetector\FileInfo;
1112
use eZ\Publish\Core\Persistence\Legacy;
1213
use eZ\Publish\SPI\Persistence\Content;
@@ -38,6 +39,9 @@
3839
*/
3940
class BinaryFileIntegrationTest extends FileBaseIntegrationTest
4041
{
42+
/** @var \eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator&\PHPUnit\Framework\MockObject\MockObject */
43+
private $fileExtensionBlackListValidator;
44+
4145
/**
4246
* Returns the storage identifier prefix used by the file service.
4347
*
@@ -71,6 +75,7 @@ public function getCustomHandler()
7175
$fieldType->setTransformationProcessor($this->getTransformationProcessor());
7276

7377
$this->ioService = self::$container->get('ezpublish.fieldType.ezbinaryfile.io_service');
78+
$this->fileExtensionBlackListValidator = $this->createMock(FileExtensionBlackListValidator::class);
7479

7580
return $this->getHandler(
7681
'ezbinaryfile',
@@ -80,7 +85,8 @@ public function getCustomHandler()
8085
new FieldType\BinaryFile\BinaryFileStorage\Gateway\DoctrineStorage($this->getDatabaseConnection()),
8186
$this->ioService,
8287
new FieldType\BinaryBase\PathGenerator\LegacyPathGenerator(),
83-
new FileInfo()
88+
new FileInfo(),
89+
$this->fileExtensionBlackListValidator
8490
)
8591
);
8692
}

0 commit comments

Comments
 (0)