/
DefaultDispatcher.php
130 lines (113 loc) · 4.24 KB
/
DefaultDispatcher.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?php
namespace Concrete\Core\Http;
use Concrete\Core\Application\Application;
use Concrete\Core\Routing\DispatcherRouteCallback;
use Concrete\Core\Routing\Redirect;
use Concrete\Core\Routing\RouterInterface;
use Concrete\Core\User\User;
use Concrete\Core\View\View;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Concrete\Core\Session\SessionValidator;
class DefaultDispatcher implements DispatcherInterface
{
/**
* @var \Concrete\Core\Application\Application
*/
private $app;
/**
* @var \Concrete\Core\Routing\RouterInterface
*/
private $router;
public function __construct(Application $app, RouterInterface $router)
{
$this->app = $app;
$this->router = $router;
}
/**
* @param \Symfony\Component\HttpFoundation\Request $request
*
* @return SymfonyResponse
*/
public function dispatch(SymfonyRequest $request)
{
$path = rawurldecode($request->getPathInfo());
if (substr($path, 0, 3) == '../' || substr($path, -3) == '/..' || strpos($path, '/../') ||
substr($path, 0, 3) == '..\\' || substr($path, -3) == '\\..' || strpos($path, '\\..\\')) {
throw new \RuntimeException(t('Invalid path traversal. Please make this request with a valid HTTP client.'));
}
$response = null;
if ($this->app->isInstalled()) {
$response = $this->getEarlyDispatchResponse();
}
if ($response === null) {
$response = $this->handleDispatch($request);
}
return $response;
}
private function getEarlyDispatchResponse()
{
$validator = $this->app->make(SessionValidator::class);
if ($validator->hasActiveSession()) {
$session = $this->app['session'];
if (!$session->has('uID')) {
User::verifyAuthTypeCookie();
}
// User may have been logged in, so lets check status again.
if ($session->has('uID') && $session->get('uID') > 0 && $response = $this->validateUser()) {
return $response;
}
}
}
private function validateUser()
{
// check to see if this is a valid user account
$user = new User();
if (!$user->checkLogin()) {
$isActive = $user->isActive();
$user->logout();
if ($user->isError()) {
switch ($user->getError()) {
case USER_SESSION_EXPIRED:
return Redirect::to('/login', 'session_invalidated')->send();
}
} elseif (!$isActive) {
return Redirect::to('/login', 'account_deactivated')->send();
} else {
$v = new View('/frontend/user_error');
$v->setViewTheme('concrete');
$contents = $v->render();
return $this->app->make(ResponseFactoryInterface::class)->forbidden($contents);
}
}
}
private function handleDispatch($request)
{
$collection = $this->router->getList();
$context = new RequestContext();
$context->fromRequest($request);
$matcher = new UrlMatcher($collection, $context);
$path = rtrim($request->getPathInfo(), '/') . '/';
$callDispatcher = false;
try {
$matched = $matcher->match($path);
$request->attributes->add($matched);
$route = $collection->get($matched['_route']);
$this->router->setRequest($request);
$response = $this->router->execute($route, $matched);
} catch (ResourceNotFoundException $e) {
$callDispatcher = true;
} catch (MethodNotAllowedException $e) {
$callDispatcher = true;
}
if ($callDispatcher) {
$callback = $this->app->make(DispatcherRouteCallback::class, ['dispatcher']);
$response = $callback->execute($request);
}
return $response;
}
}