Upgraded drupal core with security updates
[yaffs-website] / web / core / lib / Drupal / Core / Access / RouteProcessorCsrf.php
1 <?php
2
3 namespace Drupal\Core\Access;
4
5 use Drupal\Component\Utility\Crypt;
6 use Drupal\Core\Render\BubbleableMetadata;
7 use Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface;
8 use Symfony\Component\Routing\Route;
9
10 /**
11  * Processes the outbound route to handle the CSRF token.
12  */
13 class RouteProcessorCsrf implements OutboundRouteProcessorInterface {
14
15   /**
16    * The CSRF token generator.
17    *
18    * @var \Drupal\Core\Access\CsrfTokenGenerator
19    */
20   protected $csrfToken;
21
22   /**
23    * Constructs a RouteProcessorCsrf object.
24    *
25    * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
26    *   The CSRF token generator.
27    */
28   public function __construct(CsrfTokenGenerator $csrf_token) {
29     $this->csrfToken = $csrf_token;
30   }
31
32   /**
33    * {@inheritdoc}
34    */
35   public function processOutbound($route_name, Route $route, array &$parameters, BubbleableMetadata $bubbleable_metadata = NULL) {
36     if ($route->hasRequirement('_csrf_token')) {
37       $path = ltrim($route->getPath(), '/');
38       // Replace the path parameters with values from the parameters array.
39       foreach ($parameters as $param => $value) {
40         $path = str_replace("{{$param}}", $value, $path);
41       }
42       // Adding this to the parameters means it will get merged into the query
43       // string when the route is compiled.
44       if (!$bubbleable_metadata) {
45         $parameters['token'] = $this->csrfToken->get($path);
46       }
47       else {
48         // Generate a placeholder and a render array to replace it.
49         $placeholder = Crypt::hashBase64($path);
50         $placeholder_render_array = [
51           '#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]],
52         ];
53
54         // Instead of setting an actual CSRF token as the query string, we set
55         // the placeholder, which will be replaced at the very last moment. This
56         // ensures links with CSRF tokens don't break cacheability.
57         $parameters['token'] = $placeholder;
58         $bubbleable_metadata->addAttachments(['placeholders' => [$placeholder => $placeholder_render_array]]);
59       }
60     }
61   }
62
63   /**
64    * #lazy_builder callback; gets a CSRF token for the given path.
65    *
66    * @param string $path
67    *   The path to get a CSRF token for.
68    *
69    * @return array
70    *   A renderable array representing the CSRF token.
71    */
72   public function renderPlaceholderCsrfToken($path) {
73     return [
74       '#markup' => $this->csrfToken->get($path),
75       // Tokens are per session.
76       '#cache' => [
77         'contexts' => [
78           'session',
79         ],
80       ],
81     ];
82   }
83
84 }