Upgraded drupal core with security updates
[yaffs-website] / web / core / lib / Drupal / Core / Path / PathValidator.php
1 <?php
2
3 namespace Drupal\Core\Path;
4
5 use Drupal\Component\Utility\UrlHelper;
6 use Drupal\Core\ParamConverter\ParamNotConvertedException;
7 use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
8 use Drupal\Core\Routing\AccessAwareRouterInterface;
9 use Drupal\Core\Routing\RequestContext;
10 use Drupal\Core\Session\AccountInterface;
11 use Drupal\Core\Url;
12 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
13 use Symfony\Component\HttpFoundation\Request;
14 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
15 use Symfony\Component\Routing\Exception\MethodNotAllowedException;
16 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
17 use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
18
19 /**
20  * Provides a default path validator and access checker.
21  */
22 class PathValidator implements PathValidatorInterface {
23
24   /**
25    * The access aware router.
26    *
27    * @var \Drupal\Core\Routing\AccessAwareRouterInterface
28    */
29   protected $accessAwareRouter;
30
31   /**
32    * A router implementation which does not check access.
33    *
34    * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface
35    */
36   protected $accessUnawareRouter;
37
38   /**
39    * The current user.
40    *
41    * @var \Drupal\Core\Session\AccountInterface
42    */
43   protected $account;
44
45   /**
46    * The path processor.
47    *
48    * @var \Drupal\Core\PathProcessor\InboundPathProcessorInterface
49    */
50   protected $pathProcessor;
51
52   /**
53    * Creates a new PathValidator.
54    *
55    * @param \Drupal\Core\Routing\AccessAwareRouterInterface $access_aware_router
56    *   The access aware router.
57    * @param \Symfony\Component\Routing\Matcher\UrlMatcherInterface $access_unaware_router
58    *   A router implementation which does not check access.
59    * @param \Drupal\Core\Session\AccountInterface $account
60    *   The current user.
61    * @param \Drupal\Core\PathProcessor\InboundPathProcessorInterface $path_processor
62    *   The path processor;
63    */
64   public function __construct(AccessAwareRouterInterface $access_aware_router, UrlMatcherInterface $access_unaware_router, AccountInterface $account, InboundPathProcessorInterface $path_processor) {
65     $this->accessAwareRouter = $access_aware_router;
66     $this->accessUnawareRouter = $access_unaware_router;
67     $this->account = $account;
68     $this->pathProcessor = $path_processor;
69   }
70
71   /**
72    * {@inheritdoc}
73    */
74   public function isValid($path) {
75     return (bool) $this->getUrlIfValid($path);
76   }
77
78   /**
79    * {@inheritdoc}
80    */
81   public function getUrlIfValid($path) {
82     return $this->getUrl($path, TRUE);
83   }
84
85   /**
86    * {@inheritdoc}
87    */
88   public function getUrlIfValidWithoutAccessCheck($path) {
89     return $this->getUrl($path, FALSE);
90   }
91
92   /**
93    * Helper for getUrlIfValid() and getUrlIfValidWithoutAccessCheck().
94    */
95   protected function getUrl($path, $access_check) {
96     $path = ltrim($path, '/');
97
98     $parsed_url = UrlHelper::parse($path);
99
100     $options = [];
101     if (!empty($parsed_url['query'])) {
102       $options['query'] = $parsed_url['query'];
103     }
104     if (!empty($parsed_url['fragment'])) {
105       $options['fragment'] = $parsed_url['fragment'];
106     }
107
108     if ($parsed_url['path'] == '<front>') {
109       return new Url('<front>', [], $options);
110     }
111     elseif ($parsed_url['path'] == '<none>') {
112       return new Url('<none>', [], $options);
113     }
114     elseif (UrlHelper::isExternal($path) && UrlHelper::isValid($path)) {
115       if (empty($parsed_url['path'])) {
116         return FALSE;
117       }
118       return Url::fromUri($path);
119     }
120
121     $request = Request::create('/' . $path);
122     $attributes = $this->getPathAttributes($path, $request, $access_check);
123
124     if (!$attributes) {
125       return FALSE;
126     }
127
128     $route_name = $attributes[RouteObjectInterface::ROUTE_NAME];
129     $route_parameters = $attributes['_raw_variables']->all();
130
131     return new Url($route_name, $route_parameters, $options + ['query' => $request->query->all()]);
132   }
133
134   /**
135    * Gets the matched attributes for a given path.
136    *
137    * @param string $path
138    *   The path to check.
139    * @param \Symfony\Component\HttpFoundation\Request $request
140    *   A request object with the given path.
141    * @param bool $access_check
142    *   If FALSE then skip access check and check only whether the path is
143    *   valid.
144    *
145    * @return array|bool
146    *   An array of request attributes of FALSE if an exception was thrown.
147    */
148   protected function getPathAttributes($path, Request $request, $access_check) {
149     if (!$access_check || $this->account->hasPermission('link to any page')) {
150       $router = $this->accessUnawareRouter;
151     }
152     else {
153       $router = $this->accessAwareRouter;
154     }
155
156     $initial_request_context = $router->getContext() ? $router->getContext() : new RequestContext();
157     $path = $this->pathProcessor->processInbound('/' . $path, $request);
158
159     try {
160       $request_context = new RequestContext();
161       $request_context->fromRequest($request);
162       $router->setContext($request_context);
163       $result = $router->match($path);
164     }
165     catch (ResourceNotFoundException $e) {
166       $result = FALSE;
167     }
168     catch (ParamNotConvertedException $e) {
169       $result = FALSE;
170     }
171     catch (AccessDeniedHttpException $e) {
172       $result = FALSE;
173     }
174     catch (MethodNotAllowedException $e) {
175       $result = FALSE;
176     }
177
178     $router->setContext($initial_request_context);
179     return $result;
180   }
181
182 }