vendor/pimcore/pimcore/bundles/CoreBundle/Controller/PublicServicesController.php line 228

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Commercial License (PCL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  13.  */
  14. namespace Pimcore\Bundle\CoreBundle\Controller;
  15. use function date;
  16. use Pimcore\Config;
  17. use Pimcore\Controller\Controller;
  18. use Pimcore\File;
  19. use Pimcore\Logger;
  20. use Pimcore\Model\Asset;
  21. use Pimcore\Model\Site;
  22. use Pimcore\Model\Tool\TmpStore;
  23. use Pimcore\Tool\Storage;
  24. use Symfony\Component\HttpFoundation\Cookie;
  25. use Symfony\Component\HttpFoundation\RedirectResponse;
  26. use Symfony\Component\HttpFoundation\Request;
  27. use Symfony\Component\HttpFoundation\Response;
  28. use Symfony\Component\HttpFoundation\StreamedResponse;
  29. use Symfony\Component\HttpKernel\EventListener\AbstractSessionListener;
  30. use function time;
  31. /**
  32.  * @internal
  33.  */
  34. class PublicServicesController extends Controller
  35. {
  36.     /**
  37.      * @param Request $request
  38.      *
  39.      * @return RedirectResponse|StreamedResponse
  40.      */
  41.     public function thumbnailAction(Request $request)
  42.     {
  43.         $storage Storage::get('thumbnail');
  44.         $assetId = (int) $request->get('assetId');
  45.         $thumbnailName $request->get('thumbnailName');
  46.         $thumbnailType $request->get('type');
  47.         $filename $request->get('filename');
  48.         $requestedFileExtension strtolower(File::getFileExtension($filename));
  49.         $asset Asset::getById($assetId);
  50.         if ($asset) {
  51.             $prefix preg_replace('@^cache-buster\-[\d]+\/@'''$request->get('prefix'));
  52.             $prefix preg_replace('@' $asset->getId() . '/$@'''$prefix);
  53.             if ($asset->getPath() === ('/' $prefix)) {
  54.                 // we need to check the path as well, this is important in the case you have restricted the public access to
  55.                 // assets via rewrite rules
  56.                 try {
  57.                     $thumbnail null;
  58.                     $thumbnailStream null;
  59.                     // just check if the thumbnail exists -> throws exception otherwise
  60.                     $thumbnailConfigClass 'Pimcore\\Model\\Asset\\' ucfirst($thumbnailType) . '\\Thumbnail\Config';
  61.                     $thumbnailConfig $thumbnailConfigClass::getByName($thumbnailName);
  62.                     if (!$thumbnailConfig) {
  63.                         // check if there's an item in the TmpStore
  64.                         // remove an eventually existing cache-buster prefix first (eg. when using with a CDN)
  65.                         $pathInfo preg_replace('@^/cache-buster\-[\d]+@'''$request->getPathInfo());
  66.                         $deferredConfigId 'thumb_' $assetId '__' md5(urldecode($pathInfo));
  67.                         if ($thumbnailConfigItem TmpStore::get($deferredConfigId)) {
  68.                             $thumbnailConfig $thumbnailConfigItem->getData();
  69.                             TmpStore::delete($deferredConfigId);
  70.                             if (!$thumbnailConfig instanceof $thumbnailConfigClass) {
  71.                                 throw new \Exception('Deferred thumbnail config file doesn\'t contain a valid '.$thumbnailConfigClass.' object');
  72.                             }
  73.                         } elseif ($this->getParameter('pimcore.config')['assets'][$thumbnailType]['thumbnails']['status_cache']) {
  74.                             // Delete Thumbnail Name from Cache so the next call can generate a new TmpStore entry
  75.                             $asset->getDao()->deleteFromThumbnailCache($thumbnailName);
  76.                         }
  77.                     }
  78.                     if (!$thumbnailConfig) {
  79.                         throw $this->createNotFoundException("Thumbnail '" $thumbnailName "' file doesn't exist");
  80.                     }
  81.                     if ($thumbnailType == 'image' && strcasecmp($thumbnailConfig->getFormat(), 'SOURCE') === 0) {
  82.                         $formatOverride $requestedFileExtension;
  83.                         if (in_array($requestedFileExtension, ['jpg''jpeg'])) {
  84.                             $formatOverride 'pjpeg';
  85.                         }
  86.                         $thumbnailConfig->setFormat($formatOverride);
  87.                     }
  88.                     if ($asset instanceof Asset\Video) {
  89.                         if ($thumbnailType == 'video') {
  90.                             $thumbnail $asset->getThumbnail($thumbnailName, [$requestedFileExtension]);
  91.                             $storagePath urldecode($thumbnail['formats'][$requestedFileExtension]);
  92.                             if ($storage->fileExists($storagePath)) {
  93.                                 $thumbnailStream $storage->readStream($storagePath);
  94.                             }
  95.                         } else {
  96.                             $time 1;
  97.                             if (preg_match("|~\-~time\-(\d+)\.|"$filename$matchesThumbs)) {
  98.                                 $time = (int)$matchesThumbs[1];
  99.                             }
  100.                             $thumbnail $asset->getImageThumbnail($thumbnailConfig$time);
  101.                             $thumbnailStream $thumbnail->getStream();
  102.                         }
  103.                     } elseif ($asset instanceof Asset\Document) {
  104.                         $page 1;
  105.                         if (preg_match("|~\-~page\-(\d+)(@[0-9.]+x)?\.|"$filename$matchesThumbs)) {
  106.                             $page = (int)$matchesThumbs[1];
  107.                         }
  108.                         $thumbnailConfig->setName(preg_replace("/\-[\d]+/"''$thumbnailConfig->getName()));
  109.                         $thumbnailConfig->setName(str_replace('document_'''$thumbnailConfig->getName()));
  110.                         $thumbnail $asset->getImageThumbnail($thumbnailConfig$page);
  111.                         $thumbnailStream $thumbnail->getStream();
  112.                     } elseif ($asset instanceof Asset\Image) {
  113.                         //check if high res image is called
  114.                         preg_match("@([^\@]+)(\@[0-9.]+x)?\.([a-zA-Z]{2,5})@"$filename$matches);
  115.                         if (empty($matches) || !isset($matches[1])) {
  116.                             throw $this->createNotFoundException('Requested asset does not exist');
  117.                         }
  118.                         if (array_key_exists(2$matches) && $matches[2]) {
  119.                             $highResFactor = (float)str_replace(['@''x'], ''$matches[2]);
  120.                             $thumbnailConfig->setHighResolution($highResFactor);
  121.                         }
  122.                         // check if a media query thumbnail was requested
  123.                         if (preg_match("#~\-~media\-\-(.*)\-\-query#"$matches[1], $mediaQueryResult)) {
  124.                             $thumbnailConfig->selectMedia($mediaQueryResult[1]);
  125.                         }
  126.                         $thumbnail $asset->getThumbnail($thumbnailConfig);
  127.                         $thumbnailStream $thumbnail->getStream();
  128.                     }
  129.                     if ($thumbnail && $thumbnailStream) {
  130.                         if ($thumbnailType == 'image') {
  131.                             $mime $thumbnail->getMimeType();
  132.                             $fileSize $thumbnail->getFileSize();
  133.                             $pathReference $thumbnail->getPathReference();
  134.                             $actualFileExtension File::getFileExtension($pathReference['src']);
  135.                             if ($actualFileExtension !== $requestedFileExtension) {
  136.                                 // create a copy/symlink to the file with the original file extension
  137.                                 // this can be e.g. the case when the thumbnail is called as foo.png but the thumbnail config
  138.                                 // is set to auto-optimized format so the resulting thumbnail can be jpeg
  139.                                 $requestedFile preg_replace('/\.' $actualFileExtension '$/''.' $requestedFileExtension$pathReference['src']);
  140.                                 //Only copy the file if not exists yet
  141.                                 if (!$storage->fileExists($requestedFile)) {
  142.                                     $storage->writeStream($requestedFile$thumbnailStream);
  143.                                 }
  144.                                 //Stream can be closed by writeStream and needs to be reloaded.
  145.                                 $thumbnailStream $storage->readStream($requestedFile);
  146.                             }
  147.                         } elseif ($thumbnailType =='video' && isset($storagePath)) {
  148.                             $mime $storage->mimeType($storagePath);
  149.                             $fileSize $storage->fileSize($storagePath);
  150.                         } else {
  151.                             throw new \Exception('Cannot determine mime type and file size of '.$thumbnailType.' thumbnail, see logs for details.');
  152.                         }
  153.                         // set appropriate caching headers
  154.                         // see also: https://github.com/pimcore/pimcore/blob/1931860f0aea27de57e79313b2eb212dcf69ef13/.htaccess#L86-L86
  155.                         $lifetime 86400 7// 1 week lifetime, same as direct delivery in .htaccess
  156.                         $headers = [
  157.                             'Cache-Control' => 'public, max-age=' $lifetime,
  158.                             'Expires' => date('D, d M Y H:i:s T'time() + $lifetime),
  159.                             'Content-Type' => $mime,
  160.                             'Content-Length' => $fileSize,
  161.                         ];
  162.                         $headers[AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER] = true;
  163.                         return new StreamedResponse(function () use ($thumbnailStream) {
  164.                             fpassthru($thumbnailStream);
  165.                         }, 200$headers);
  166.                     }
  167.                     throw new \Exception('Unable to generate '.$thumbnailType.' thumbnail, see logs for details.');
  168.                 } catch (\Exception $e) {
  169.                     Logger::error($e->getMessage());
  170.                     return new RedirectResponse('/bundles/pimcoreadmin/img/filetype-not-supported.svg');
  171.                 }
  172.             }
  173.         }
  174.         throw $this->createNotFoundException('Asset not found');
  175.     }
  176.     /**
  177.      * @param Request $request
  178.      *
  179.      * @return Response
  180.      */
  181.     public function robotsTxtAction(Request $request)
  182.     {
  183.         // check for site
  184.         $domain \Pimcore\Tool::getHostname();
  185.         $site Site::getByDomain($domain);
  186.         $config Config::getRobotsConfig()->toArray();
  187.         $siteId 'default';
  188.         if ($site instanceof Site) {
  189.             $siteId $site->getId();
  190.         }
  191.         // send correct headers
  192.         header('Content-Type: text/plain; charset=utf8');
  193.         while (@ob_end_flush()) ;
  194.         // check for configured robots.txt in pimcore
  195.         $content '';
  196.         if (array_key_exists($siteId$config)) {
  197.             $content $config[$siteId];
  198.         }
  199.         if (empty($content)) {
  200.             // default behavior, allow robots to index everything
  201.             $content "User-agent: *\nDisallow:";
  202.         }
  203.         return new Response($contentResponse::HTTP_OK, [
  204.             'Content-Type' => 'text/plain',
  205.         ]);
  206.     }
  207.     /**
  208.      * @param Request $request
  209.      *
  210.      * @return Response
  211.      */
  212.     public function commonFilesAction(Request $request)
  213.     {
  214.         return new Response("HTTP/1.1 404 Not Found\nFiltered by common files filter"404);
  215.     }
  216.     /**
  217.      * @param Request $request
  218.      *
  219.      * @return RedirectResponse
  220.      */
  221.     public function customAdminEntryPointAction(Request $request)
  222.     {
  223.         $params $request->query->all();
  224.         $url = match (true) {
  225.             isset($params['token'])    => $this->generateUrl('pimcore_admin_login_check'$params),
  226.             isset($params['deeplink']) => $this->generateUrl('pimcore_admin_login_deeplink'$params),
  227.             default                    => $this->generateUrl('pimcore_admin_login'$params)
  228.         };
  229.         $redirect = new RedirectResponse($url);
  230.         $customAdminPathIdentifier $this->getParameter('pimcore_admin.custom_admin_path_identifier');
  231.         if (!empty($customAdminPathIdentifier) && $request->cookies->get('pimcore_custom_admin') != $customAdminPathIdentifier) {
  232.             $redirect->headers->setCookie(new Cookie('pimcore_custom_admin'$customAdminPathIdentifierstrtotime('+1 year')));
  233.         }
  234.         return $redirect;
  235.     }
  236. }