Skip to content

Commit

Permalink
Merge pull request from GHSA-mwvh-p3hx-x4gg
Browse files Browse the repository at this point in the history
  • Loading branch information
barw4 authored Mar 20, 2024
1 parent 8ef0e70 commit 7e47231
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 34 deletions.
32 changes: 23 additions & 9 deletions eZ/Publish/Core/FieldType/BinaryBase/BinaryBaseStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*/
namespace eZ\Publish\Core\FieldType\BinaryBase;

use eZ\Publish\Core\Base\Exceptions\ContentFieldValidationException;
use eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator;
use eZ\Publish\Core\IO\IOServiceInterface;
use eZ\Publish\SPI\FieldType\BinaryBase\PathGenerator;
use eZ\Publish\SPI\FieldType\BinaryBase\RouteAwarePathGenerator;
Expand Down Expand Up @@ -39,24 +41,21 @@ class BinaryBaseStorage extends GatewayBasedStorage
/** @var \eZ\Publish\Core\FieldType\BinaryBase\BinaryBaseStorage\Gateway */
protected $gateway;

/**
* Construct from gateways.
*
* @param \eZ\Publish\SPI\FieldType\StorageGateway $gateway
* @param \eZ\Publish\Core\IO\IOServiceInterface $ioService
* @param \eZ\Publish\SPI\FieldType\BinaryBase\PathGenerator $pathGenerator
* @param \eZ\Publish\SPI\IO\MimeTypeDetector $mimeTypeDetector
*/
/** @var \eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator */
protected $fileExtensionBlackListValidator;

public function __construct(
StorageGateway $gateway,
IOServiceInterface $ioService,
PathGenerator $pathGenerator,
MimeTypeDetector $mimeTypeDetector
MimeTypeDetector $mimeTypeDetector,
FileExtensionBlackListValidator $fileExtensionBlackListValidator
) {
parent::__construct($gateway);
$this->ioService = $ioService;
$this->pathGenerator = $pathGenerator;
$this->mimeTypeDetector = $mimeTypeDetector;
$this->fileExtensionBlackListValidator = $fileExtensionBlackListValidator;
}

/**
Expand All @@ -67,6 +66,10 @@ public function setDownloadUrlGenerator(PathGenerator $downloadUrlGenerator)
$this->downloadUrlGenerator = $downloadUrlGenerator;
}

/**
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
* @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
*/
public function storeFieldData(VersionInfo $versionInfo, Field $field, array $context)
{
if ($field->value->externalData === null) {
Expand All @@ -76,6 +79,17 @@ public function storeFieldData(VersionInfo $versionInfo, Field $field, array $co
}

if (isset($field->value->externalData['inputUri'])) {
$this->fileExtensionBlackListValidator->validateFileExtension($field->value->externalData['fileName']);
if (!empty($errors = $this->fileExtensionBlackListValidator->getErrors())) {
$preparedErrors = [];
$preparedErrors[$field->fieldDefinitionId][$field->languageCode] = $errors;

throw ContentFieldValidationException::createNewWithMultiline(
$preparedErrors,
$versionInfo->contentInfo->name
);
}

$field->value->externalData['mimeType'] = $this->mimeTypeDetector->getFromPath($field->value->externalData['inputUri']);
$createStruct = $this->ioService->newBinaryCreateStructFromLocalFile($field->value->externalData['inputUri']);
$createStruct->id = $this->pathGenerator->getStoragePathForField($field, $versionInfo);
Expand Down
26 changes: 25 additions & 1 deletion eZ/Publish/Core/FieldType/Image/ImageStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
*/
namespace eZ\Publish\Core\FieldType\Image;

use eZ\Publish\Core\Base\Exceptions\ContentFieldValidationException;
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
use eZ\Publish\Core\Base\Utils\DeprecationWarnerInterface as DeprecationWarner;
use eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator;
use eZ\Publish\Core\IO\FilePathNormalizerInterface;
use eZ\Publish\Core\IO\IOServiceInterface;
use eZ\Publish\Core\IO\MetadataHandler;
Expand Down Expand Up @@ -42,14 +44,18 @@ class ImageStorage extends GatewayBasedStorage
/** @var \eZ\Publish\Core\IO\FilePathNormalizerInterface */
protected $filePathNormalizer;

/** @var \eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator */
protected $fileExtensionBlackListValidator;

public function __construct(
StorageGateway $gateway,
IOServiceInterface $ioService,
PathGenerator $pathGenerator,
MetadataHandler $imageSizeMetadataHandler,
DeprecationWarner $deprecationWarner,
AliasCleanerInterface $aliasCleaner,
FilePathNormalizerInterface $filePathNormalizer
FilePathNormalizerInterface $filePathNormalizer,
FileExtensionBlackListValidator $fileExtensionBlackListValidator
) {
parent::__construct($gateway);
$this->ioService = $ioService;
Expand All @@ -58,8 +64,15 @@ public function __construct(
$this->deprecationWarner = $deprecationWarner;
$this->aliasCleaner = $aliasCleaner;
$this->filePathNormalizer = $filePathNormalizer;
$this->fileExtensionBlackListValidator = $fileExtensionBlackListValidator;
}

/**
* @throws \eZ\Publish\Core\Base\Exceptions\NotFoundException
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentValue
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentException
* @throws \eZ\Publish\Core\Base\Exceptions\ContentFieldValidationException
*/
public function storeFieldData(VersionInfo $versionInfo, Field $field, array $context)
{
$contentMetaData = [
Expand All @@ -70,6 +83,17 @@ public function storeFieldData(VersionInfo $versionInfo, Field $field, array $co

// new image
if (isset($field->value->externalData)) {
$this->fileExtensionBlackListValidator->validateFileExtension($field->value->externalData['fileName']);
if (!empty($errors = $this->fileExtensionBlackListValidator->getErrors())) {
$preparedErrors = [];
$preparedErrors[$field->fieldDefinitionId][$field->languageCode] = $errors;

throw ContentFieldValidationException::createNewWithMultiline(
$preparedErrors,
$versionInfo->contentInfo->name
);
}

$targetPath = sprintf(
'%s/%s',
$this->pathGenerator->getStoragePathForField(
Expand Down
4 changes: 2 additions & 2 deletions eZ/Publish/Core/FieldType/Tests/BinaryFileTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ public function provideInvalidDataForValidate()
),
[
new ValidationError(
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
null,
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
'fileExtensionBlackList'
Expand Down Expand Up @@ -623,7 +623,7 @@ public function provideInvalidDataForValidate()
),
[
new ValidationError(
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
null,
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
'fileExtensionBlackList'
Expand Down
8 changes: 4 additions & 4 deletions eZ/Publish/Core/FieldType/Tests/ImageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ public function provideInvalidDataForValidate()
),
[
new ValidationError(
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
null,
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
'fileExtensionBlackList'
Expand Down Expand Up @@ -743,7 +743,7 @@ public function provideInvalidDataForValidate()
),
[
new ValidationError(
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
null,
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
'fileExtensionBlackList'
Expand Down Expand Up @@ -778,7 +778,7 @@ public function provideInvalidDataForValidate()
),
[
new ValidationError(
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
null,
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
'fileExtensionBlackList'
Expand Down Expand Up @@ -810,7 +810,7 @@ public function provideInvalidDataForValidate()
),
[
new ValidationError(
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
null,
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
'fileExtensionBlackList'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use eZ\Publish\Core\FieldType\BinaryBase\BinaryBaseStorage\Gateway;
use eZ\Publish\Core\FieldType\BinaryFile\BinaryFileStorage\Gateway\DoctrineStorage;
use eZ\Publish\Core\FieldType\Tests\Integration\BaseCoreFieldTypeIntegrationTest;
use eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator;
use eZ\Publish\Core\IO\IOServiceInterface;
use eZ\Publish\Core\IO\Values\BinaryFile;
use eZ\Publish\Core\IO\Values\BinaryFileCreateStruct;
Expand All @@ -36,13 +37,19 @@ class BinaryBaseStorageTest extends BaseCoreFieldTypeIntegrationTest
/** @var \eZ\Publish\Core\FieldType\BinaryBase\BinaryBaseStorage|\PHPUnit\Framework\MockObject\MockObject */
protected $storage;

/** @var \eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator&\PHPUnit\Framework\MockObject\MockObject */
protected $fileExtensionBlackListValidatorMock;

protected function setUp(): void
{
parent::setUp();

$this->gateway = $this->getStorageGateway();
$this->pathGeneratorMock = $this->createMock(PathGenerator::class);
$this->ioServiceMock = $this->createMock(IOServiceInterface::class);
$this->fileExtensionBlackListValidatorMock = $this->createMock(
FileExtensionBlackListValidator::class
);
$this->storage = $this->getMockBuilder(BinaryBaseStorage::class)
->onlyMethods([])
->setConstructorArgs(
Expand All @@ -51,6 +58,7 @@ protected function setUp(): void
$this->ioServiceMock,
$this->pathGeneratorMock,
$this->createMock(MimeTypeDetector::class),
$this->fileExtensionBlackListValidatorMock,
]
)
->getMock();
Expand Down
2 changes: 1 addition & 1 deletion eZ/Publish/Core/FieldType/Tests/MediaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ public function provideInvalidDataForValidate()
),
[
new ValidationError(
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
null,
['%extensionsBlackList%' => implode(', ', $this->blackListedExtensions)],
'fileExtensionBlackList'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,40 @@ public function validateConstraints($constraints)
* {@inheritdoc}
*/
public function validate(BaseValue $value)
{
$this->errors = [];

$this->validateFileExtension($value->fileName);

return empty($this->errors);
}

public function validateFileExtension(string $fileName): void
{
if (
pathinfo($value->fileName, PATHINFO_BASENAME) !== $value->fileName ||
in_array(strtolower(pathinfo($value->fileName, PATHINFO_EXTENSION)), $this->constraints['extensionsBlackList'], true)
pathinfo($fileName, PATHINFO_BASENAME) !== $fileName
|| in_array(
strtolower(pathinfo($fileName, PATHINFO_EXTENSION)),
$this->constraints['extensionsBlackList'],
true
)
) {
$this->errors[] = new ValidationError(
'A valid file is required. Following file extensions are on the blacklist: %extensionsBlackList%',
'A valid file is required. The following file extensions are not allowed: %extensionsBlackList%',
null,
[
'%extensionsBlackList%' => implode(', ', $this->constraints['extensionsBlackList']),
],
'fileExtensionBlackList'
);

return false;
}
}

return true;
/**
* @return array<\eZ\Publish\SPI\FieldType\ValidationError>
*/
public function getErrors(): array
{
return $this->errors;
}
}
19 changes: 11 additions & 8 deletions eZ/Publish/Core/settings/fieldtype_external_storages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ services:
ezpublish.fieldType.ezbinaryfile.externalStorage:
class: eZ\Publish\Core\FieldType\BinaryFile\BinaryFileStorage
arguments:
- "@ezpublish.fieldType.ezbinaryfile.storage_gateway"
- "@ezpublish.fieldType.ezbinaryfile.io_service"
- "@ezpublish.fieldType.ezbinaryfile.pathGenerator"
- "@ezpublish.core.io.mimeTypeDetector"
$gateway: '@ezpublish.fieldType.ezbinaryfile.storage_gateway'
$ioService: '@ezpublish.fieldType.ezbinaryfile.io_service'
$pathGenerator: '@ezpublish.fieldType.ezbinaryfile.pathGenerator'
$mimeTypeDetector: '@ezpublish.core.io.mimeTypeDetector'
$fileExtensionBlackListValidator: '@ezpublish.fieldType.validator.black_list'
tags:
- {name: ezplatform.field_type.external_storage_handler, alias: ezbinaryfile}

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

Expand All @@ -31,10 +33,11 @@ services:
ezpublish.fieldType.ezmedia.externalStorage:
class: eZ\Publish\Core\FieldType\Media\MediaStorage
arguments:
- "@ezpublish.fieldType.ezmedia.storage_gateway"
- "@ezpublish.fieldType.ezbinaryfile.io_service"
- "@ezpublish.fieldType.ezbinaryfile.pathGenerator"
- "@ezpublish.core.io.mimeTypeDetector"
$gateway: '@ezpublish.fieldType.ezmedia.storage_gateway'
$ioService: '@ezpublish.fieldType.ezbinaryfile.io_service'
$pathGenerator: '@ezpublish.fieldType.ezbinaryfile.pathGenerator'
$mimeTypeDetector: '@ezpublish.core.io.mimeTypeDetector'
$fileExtensionBlackListValidator: '@ezpublish.fieldType.validator.black_list'
tags:
- {name: ezplatform.field_type.external_storage_handler, alias: ezmedia}

Expand Down
8 changes: 7 additions & 1 deletion eZ/Publish/SPI/Tests/FieldType/BinaryFileIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace eZ\Publish\SPI\Tests\FieldType;

use eZ\Publish\Core\FieldType;
use eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator;
use eZ\Publish\Core\IO\MimeTypeDetector\FileInfo;
use eZ\Publish\Core\Persistence\Legacy;
use eZ\Publish\SPI\Persistence\Content;
Expand Down Expand Up @@ -38,6 +39,9 @@
*/
class BinaryFileIntegrationTest extends FileBaseIntegrationTest
{
/** @var \eZ\Publish\Core\FieldType\Validator\FileExtensionBlackListValidator&\PHPUnit\Framework\MockObject\MockObject */
private $fileExtensionBlackListValidator;

/**
* Returns the storage identifier prefix used by the file service.
*
Expand Down Expand Up @@ -71,6 +75,7 @@ public function getCustomHandler()
$fieldType->setTransformationProcessor($this->getTransformationProcessor());

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

return $this->getHandler(
'ezbinaryfile',
Expand All @@ -80,7 +85,8 @@ public function getCustomHandler()
new FieldType\BinaryFile\BinaryFileStorage\Gateway\DoctrineStorage($this->getDatabaseConnection()),
$this->ioService,
new FieldType\BinaryBase\PathGenerator\LegacyPathGenerator(),
new FileInfo()
new FileInfo(),
$this->fileExtensionBlackListValidator
)
);
}
Expand Down
Loading

0 comments on commit 7e47231

Please sign in to comment.