Skip to content

Commit

Permalink
Merge pull request from GHSA-946c-f9w6-2c25
Browse files Browse the repository at this point in the history
  • Loading branch information
glye committed Nov 3, 2023
1 parent 0f4d6ab commit affa252
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 13 deletions.
Expand Up @@ -37,7 +37,7 @@ ez_content_download:

ez_content_download_field_id:
path: /content/download/{contentId}/{fieldId}
defaults: { _controller: ezpublish.controller.content.download_redirection:redirectToContentDownloadAction }
defaults: { _controller: ezpublish.controller.content.download:downloadBinaryFileByIdAction }
requirements:
contentId: '\d+'
fieldId: '\d+'
Expand Up @@ -8,12 +8,13 @@

use eZ\Bundle\EzPublishIOBundle\BinaryStreamResponse;
use eZ\Publish\API\Repository\ContentService;
use eZ\Publish\API\Repository\Values\Content\Content;
use eZ\Publish\API\Repository\Values\Content\Field;
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
use eZ\Publish\Core\Base\Exceptions\NotFoundException;
use eZ\Publish\Core\Helper\TranslationHelper;
use eZ\Publish\Core\IO\IOServiceInterface;
use eZ\Publish\Core\MVC\Symfony\Controller\Controller;
use InvalidArgumentException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

Expand All @@ -36,18 +37,51 @@ public function __construct(ContentService $contentService, IOServiceInterface $
}

/**
* @param mixed $contentId ID of a valid Content
* @param string $fieldIdentifier Field Definition identifier of the Field the file must be downloaded from
* @param string $filename
* @param \Symfony\Component\HttpFoundation\Request $request
* Download binary file identified by field ID.
*
* @return \eZ\Bundle\EzPublishIOBundle\BinaryStreamResponse
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the field $fieldId can't be found, or the translation can't be found.
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If the content is trashed, or can't be found.
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the user has no access to read content and in case of un-published content: read versions.
*/
public function downloadBinaryFileByIdAction(Request $request, int $contentId, int $fieldId): BinaryStreamResponse
{
$content = $this->contentService->loadContent($contentId);
try {
$field = $this->findFieldInContent($fieldId, $content);
} catch (InvalidArgumentException $e) {
throw new NotFoundException('File', $fieldId);
}

return $this->downloadBinaryFileAction($contentId, $field->fieldDefIdentifier, $field->value->fileName, $request);
}

/**
* Finds the field with id $fieldId in $content.
*
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the field $fieldId can't be found, or the translation can't be found.
*/
protected function findFieldInContent(int $fieldId, Content $content): Field
{
foreach ($content->getFields() as $field) {
if ($field->getId() === $fieldId) {
return $field;
}
}

throw new InvalidArgumentException(
'$fieldId',
"Field with id $fieldId not found in Content with id {$content->id}"
);
}

/**
* Download binary file identified by field identifier.
*
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the field $fieldIdentifier can't be found, or the translation can't be found.
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If the content is trashed, or can't be found.
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the user has no access to read content and in case of un-published content: read versions.
*/
public function downloadBinaryFileAction($contentId, $fieldIdentifier, $filename, Request $request)
public function downloadBinaryFileAction(int $contentId, string $fieldIdentifier, string $filename, Request $request): BinaryStreamResponse
{
if ($request->query->has('version')) {
$version = (int) $request->query->get('version');
Expand All @@ -70,14 +104,15 @@ public function downloadBinaryFileAction($contentId, $fieldIdentifier, $filename
);
if (!$field instanceof Field) {
throw new InvalidArgumentException(
"'{$fieldIdentifier}' Field does not exist in Content item {$content->contentInfo->id} '{$content->contentInfo->name}'"
'$fieldIdentifier',
"'{$fieldIdentifier}' field not present on content #{$content->contentInfo->id} '{$content->contentInfo->name}'"
);
}

$response = new BinaryStreamResponse($this->ioService->loadBinaryFile($field->value->id), $this->ioService);
$response->setContentDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
$filename,
$field->value->fileName,
bin2hex(random_bytes(8))
);

Expand Down

0 comments on commit affa252

Please sign in to comment.