FragmentListener.php

Namespace

Symfony\Component\HttpKernel\EventListener

File

drupal/core/vendor/symfony/http-kernel/Symfony/Component/HttpKernel/EventListener/FragmentListener.php
View source
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\IpUtils;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\UriSigner;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Handles content fragments represented by special URIs.
 *
 * All URL paths starting with /_fragment are handled as
 * content fragments by this listener.
 *
 * If the request does not come from a trusted IP, it throws an
 * AccessDeniedHttpException exception.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FragmentListener implements EventSubscriberInterface {
  private $signer;
  private $fragmentPath;

  /**
   * Constructor.
   *
   * @param UriSigner $signer       A UriSigner instance
   * @param string    $fragmentPath The path that triggers this listener
   */
  public function __construct(UriSigner $signer, $fragmentPath = '/_fragment') {
    $this->signer = $signer;
    $this->fragmentPath = $fragmentPath;
  }

  /**
   * Fixes request attributes when the path is '/_fragment'.
   *
   * @param GetResponseEvent $event A GetResponseEvent instance
   *
   * @throws AccessDeniedHttpException if the request does not come from a trusted IP.
   */
  public function onKernelRequest(GetResponseEvent $event) {
    $request = $event
      ->getRequest();
    if ($this->fragmentPath !== rawurldecode($request
      ->getPathInfo())) {
      return;
    }
    $this
      ->validateRequest($request);
    parse_str($request->query
      ->get('_path', ''), $attributes);
    $request->attributes
      ->add($attributes);
    $request->attributes
      ->set('_route_params', array_replace($request->attributes
      ->get('_route_params', array()), $attributes));
    $request->query
      ->remove('_path');
  }
  protected function validateRequest(Request $request) {

    // is the Request safe?
    if (!$request
      ->isMethodSafe()) {
      throw new AccessDeniedHttpException();
    }

    // does the Request come from a trusted IP?
    $trustedIps = array_merge($this
      ->getLocalIpAddresses(), $request
      ->getTrustedProxies());
    $remoteAddress = $request->server
      ->get('REMOTE_ADDR');
    if (IpUtils::checkIp($remoteAddress, $trustedIps)) {
      return;
    }

    // is the Request signed?
    // we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering)
    if ($this->signer
      ->check($request
      ->getSchemeAndHttpHost() . $request
      ->getBaseUrl() . $request
      ->getPathInfo() . (null !== ($qs = $request->server
      ->get('QUERY_STRING')) ? '?' . $qs : ''))) {
      return;
    }
    throw new AccessDeniedHttpException();
  }
  protected function getLocalIpAddresses() {
    return array(
      '127.0.0.1',
      'fe80::1',
      '::1',
    );
  }
  public static function getSubscribedEvents() {
    return array(
      KernelEvents::REQUEST => array(
        array(
          'onKernelRequest',
          48,
        ),
      ),
    );
  }

}

Classes

Namesort descending Description
FragmentListener Handles content fragments represented by special URIs.