vendor/nelmio/security-bundle/src/EventListener/ClickjackingListener.php line 45

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of the Nelmio SecurityBundle.
  5.  *
  6.  * (c) Nelmio <[email protected]>
  7.  *
  8.  * For the full copyright and license information, please view the LICENSE
  9.  * file that was distributed with this source code.
  10.  */
  11. namespace Nelmio\SecurityBundle\EventListener;
  12. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  13. use Symfony\Component\HttpKernel\KernelEvents;
  14. final class ClickjackingListener extends AbstractContentTypeRestrictableListener
  15. {
  16.     /**
  17.      * @var array<string, array<string, string>>
  18.      */
  19.     private array $paths;
  20.     private ?string $hosts;
  21.     /**
  22.      * @param array<string, array<string, string>> $paths
  23.      * @param list<string>                         $contentTypes
  24.      * @param list<string>                         $hosts
  25.      */
  26.     public function __construct(array $paths, array $contentTypes = [], array $hosts = [])
  27.     {
  28.         parent::__construct($contentTypes);
  29.         $this->paths $paths;
  30.         $this->hosts = [] !== $hosts '('.implode('|'$hosts).')' null;
  31.     }
  32.     public static function getSubscribedEvents(): array
  33.     {
  34.         return [KernelEvents::RESPONSE => 'onKernelResponse'];
  35.     }
  36.     public function onKernelResponse(ResponseEvent $e): void
  37.     {
  38.         if (!$e->isMainRequest()) {
  39.             return;
  40.         }
  41.         if (!$this->isContentTypeValid($e->getResponse())) {
  42.             return;
  43.         }
  44.         $response $e->getResponse();
  45.         if ($response->isRedirection()) {
  46.             return;
  47.         }
  48.         if ($response->headers->has('X-Frame-Options')) {
  49.             // Do not overwrite an existing header
  50.             return;
  51.         }
  52.         $request $e->getRequest();
  53.         $host '' === $request->getHost() ? '/' $request->getHost();
  54.         // skip non-listed hosts
  55.         if (null !== $this->hosts && !== preg_match('{'.$this->hosts.'}i'$host)) {
  56.             return;
  57.         }
  58.         $currentPath '' === $request->getRequestUri() ? '/' $request->getRequestUri();
  59.         foreach ($this->paths as $path => $options) {
  60.             if (=== preg_match('{'.$path.'}i'$currentPath)) {
  61.                 if ('ALLOW' === $options['header']) {
  62.                     $response->headers->remove('X-Frame-Options');
  63.                 } else {
  64.                     $response->headers->set('X-Frame-Options'$options['header']);
  65.                 }
  66.                 return;
  67.             }
  68.         }
  69.     }
  70. }