diff --git a/.github/workflows/codeception.yml b/.github/workflows/codeception.yml index 5e178ab..270f50e 100644 --- a/.github/workflows/codeception.yml +++ b/.github/workflows/codeception.yml @@ -40,9 +40,9 @@ jobs: matrix: php: [ 8.3 ] symfony: [ ^6.4 ] - pimcore: [ ~11.4.0 ] + pimcore: [ ~11.5.0 ] include: - - pimcore: ~11.4.0 + - pimcore: ~11.5.0 template_tag: 2024.3 steps: - uses: nanasess/setup-chromedriver@v2 diff --git a/.github/workflows/php-stan.yml b/.github/workflows/php-stan.yml index 479075f..5ba0724 100644 --- a/.github/workflows/php-stan.yml +++ b/.github/workflows/php-stan.yml @@ -39,9 +39,9 @@ jobs: matrix: php: [ 8.3 ] symfony: [ ^6.4 ] - pimcore: [ ~11.4.0 ] + pimcore: [ ~11.5.0 ] include: - - pimcore: ~11.4.0 + - pimcore: ~11.5.0 template_tag: 2024.3 steps: - uses: actions/checkout@v4 diff --git a/UPGRADE.md b/UPGRADE.md index ebeb684..a623267 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,8 @@ # Upgrade Notes +## 5.1.3 +- **[BUGFIX]**: Assert correct video context in chunked video streaming + ## 5.1.2 - **[BUGFIX]**: Fix interface compatibility [#216](https://github.com/dachcom-digital/pimcore-members/issues/216) - **[IMPROVEMENT]**: Account check before password reset diff --git a/src/Controller/RequestController.php b/src/Controller/RequestController.php index a702a7d..172da4a 100644 --- a/src/Controller/RequestController.php +++ b/src/Controller/RequestController.php @@ -71,14 +71,24 @@ public function serveProtectedAssetPathAction(Request $request, int $id, string $decodedPath = $this->restrictionUri->decodePublicAssetUrl($id, $path, $extension); if ($decodedPath === null) { - return new BinaryFileResponse(PIMCORE_PATH . '/bundles/AdminBundle/Resources/public/img/filetype-not-supported.svg'); + return new BinaryFileResponse(PIMCORE_WEB_ROOT . '/bundles/pimcoreadmin/img/filetype-not-supported.svg'); } - return $this->servePath($decodedPath, $request); + return $this->servePath($decodedPath, $id, $request); } - private function servePath(string $path, Request $request): Response + private function servePath(string $path, int $id, Request $request): Response { + $asset = Model\Asset::getById($id); + + if ($asset instanceof Model\Asset\Video) { + try { + return $this->serveVideoAsset($asset, $path, $request); + } catch (\Throwable $e) { + return new BinaryFileResponse(PIMCORE_WEB_ROOT . '/bundles/pimcoreadmin/img/filetype-not-supported.svg'); + } + } + $response = Model\Asset\Service::getStreamedResponseByUri($path); if ($response instanceof StreamedResponse) { @@ -86,16 +96,8 @@ private function servePath(string $path, Request $request): Response } // no thumbnail path found, check if the original file has been requested - - $asset = Model\Asset::getByPath($path); - if ($asset instanceof Model\Asset) { - // Handle response differently for video assets. - if ($asset instanceof Model\Asset\Video) { - return $this->serveVideoAsset($asset, $request); - } - $stream = $asset->getStream(); return new StreamedResponse(function () use ($stream) { @@ -109,15 +111,32 @@ private function servePath(string $path, Request $request): Response return throw $this->createNotFoundException(); } - private function serveVideoAsset(Model\Asset\Video $asset, Request $request): Response + private function serveVideoAsset(Model\Asset\Video $asset, string $path, Request $request): Response { - $fileSize = $asset->getFileSize(); + $regExpression = sprintf('/(%s)(%s)-thumb__(%s)__(%s)\/(%s)/', + '.*', + 'video|image', + '\d+', + '[a-zA-Z0-9_\-]+', + '.*' + ); + + if (preg_match($regExpression, $path, $matches)) { + $storage = $this->storage->get('thumbnail'); + } else { + $storage = $this->storage->get('asset'); + } + + if (!$storage->fileExists($path)) { + throw new \InvalidArgumentException('File does not exist'); + } + + $fileSize = $storage->fileSize($path); + $start = 0; $end = $fileSize - 1; $statusCode = Response::HTTP_OK; - $absolutePath = sprintf('%s/public/var/assets%s', PIMCORE_PROJECT_ROOT, $asset->getRealFullPath()); - if ($range = $request->headers->get('Range')) { if (preg_match('/bytes=(\d*)-(\d*)/', $range, $matches)) { if ($matches[1] !== '') { @@ -138,22 +157,25 @@ private function serveVideoAsset(Model\Asset\Video $asset, Request $request): Re $length = $end - $start + 1; - $response = new StreamedResponse(function () use ($absolutePath, $start, $length) { - $handle = fopen($absolutePath, 'rb'); + $response = new StreamedResponse(function () use ($storage, $path, $start, $length) { + + $handle = $storage->readStream($path); + fseek($handle, $start); $bytesLeft = $length; $chunkSize = 8192; while ($bytesLeft > 0 && !feof($handle)) { - $readSize = ($bytesLeft > $chunkSize) ? $chunkSize : $bytesLeft; + $readSize = min($chunkSize, $bytesLeft); echo fread($handle, $readSize); flush(); $bytesLeft -= $readSize; } + fclose($handle); }, $statusCode); - $response->headers->set('Content-Type', $asset->getMimeType()); + $response->headers->set('Content-Type', $storage->mimeType($path)); $response->headers->set('Accept-Ranges', 'bytes'); $response->headers->set('Content-Length', $length);