2 namespace wcf\system\request
;
3 use wcf\system\application\ApplicationHandler
;
4 use wcf\system\exception\AJAXException
;
5 use wcf\system\exception\IllegalLinkException
;
6 use wcf\system\exception\NamedUserException
;
7 use wcf\system\exception\SystemException
;
8 use wcf\system\menu\page\PageMenu
;
9 use wcf\system\SingletonFactory
;
11 use wcf\util\FileUtil
;
12 use wcf\util\HeaderUtil
;
15 * Handles http requests.
18 * @copyright 2001-2015 WoltLab GmbH
19 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
20 * @package com.woltlab.wcf
21 * @subpackage system.request
22 * @category Community Framework
24 class RequestHandler
extends SingletonFactory
{
26 * active request object
29 protected $activeRequest;
32 * true, if current domain mismatch any known domain
35 protected $inRescueMode = false;
38 * indicates if the request is an acp request
41 protected $isACPRequest = false;
44 * @see \wcf\system\SingletonFactory::init()
46 protected function init() {
47 $this->isACPRequest
= class_exists('wcf\system\WCFACP', false);
51 * Handles a http request.
53 * @param string $application
54 * @param boolean $isACPRequest
55 * @throws AJAXException
56 * @throws IllegalLinkException
57 * @throws SystemException
59 public function handle($application = 'wcf', $isACPRequest = false) {
61 $this->isACPRequest
= $isACPRequest;
63 if (!RouteHandler
::getInstance()->matches()) {
64 if (ENABLE_DEBUG_MODE
) {
65 throw new SystemException("Cannot handle request, no valid route provided.");
68 throw new IllegalLinkException();
73 $this->buildRequest($application);
75 // handle offline mode
76 if (!$isACPRequest && defined('OFFLINE') && OFFLINE
) {
77 if (!WCF
::getSession()->getPermission('admin.general.canViewPageDuringOfflineMode') && !$this->activeRequest
->isAvailableDuringOfflineMode()) {
78 if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')) {
79 throw new AJAXException(WCF
::getLanguage()->get('wcf.ajax.error.permissionDenied'), AJAXException
::INSUFFICIENT_PERMISSIONS
);
82 @header
('HTTP/1.1 503 Service Unavailable');
83 WCF
::getTPL()->assign(array(
84 'templateName' => 'offline',
85 'templateNameApplication' => 'wcf'
87 WCF
::getTPL()->display('offline');
95 $this->activeRequest
->execute();
97 catch (NamedUserException
$e) {
104 * Builds a new request.
106 * @param string $application
107 * @throws IllegalLinkException
109 protected function buildRequest($application) {
111 $routeData = RouteHandler
::getInstance()->getRouteData();
113 // handle landing page for frontend requests
114 if (!$this->isACPRequest()) {
115 $this->handleDefaultController($application, $routeData);
117 // check if accessing from the wrong domain (e.g. "www." omitted but domain was configured with)
118 if (!defined('WCF_RUN_MODE') || WCF_RUN_MODE
!== 'embedded') {
119 $applicationObject = ApplicationHandler
::getInstance()->getApplication($application);
120 if ($applicationObject->domainName
!= $_SERVER['HTTP_HOST']) {
121 // build URL, e.g. http://example.net/forum/
122 $url = FileUtil
::addTrailingSlash(RouteHandler
::getProtocol() . $applicationObject->domainName
. RouteHandler
::getPath());
124 // query string, e.g. ?foo=bar
125 if (!empty($_SERVER['QUERY_STRING'])) {
126 $url .= '?' . $_SERVER['QUERY_STRING'];
129 HeaderUtil
::redirect($url, true);
134 else if (empty($routeData['controller'])) {
135 $routeData['controller'] = 'index';
138 $controller = $routeData['controller'];
140 if (isset($routeData['className'])) {
142 'className' => $routeData['className'],
143 'controller' => $routeData['controller'],
144 'pageType' => $routeData['pageType']
147 unset($routeData['className']);
148 unset($routeData['controller']);
149 unset($routeData['pageType']);
152 $classData = ControllerMap
::getInstance()->resolve($application, $controller, $this->isACPRequest());
153 if (is_string($classData)) {
154 $this->redirect($routeData, $application, $classData);
158 // handle CMS page meta data
160 if (isset($routeData['cmsPageID'])) {
162 'pageID' => $routeData['cmsPageID'],
163 'languageID' => $routeData['cmsPageLanguageID']
166 unset($routeData['cmsPageID']);
167 unset($routeData['cmsPageLanguageID']);
170 $this->activeRequest
= new Request($classData['className'], $classData['controller'], $classData['pageType'], $metaData);
172 catch (SystemException
$e) {
173 throw new IllegalLinkException();
178 * Redirects to the actual URL, e.g. controller has been aliased or mistyped (boardlist instead of board-list).
180 * @param string[] $routeData
181 * @param string $application
182 * @param string $controller
184 protected function redirect(array $routeData, $application, $controller = null) {
185 $routeData['application'] = $application;
186 if ($controller !== null) $routeData['controller'] = $controller;
188 // append the remaining query parameters
189 foreach ($_GET as $key => $value) {
190 if (!empty($value) && $key != 'controller') {
191 $routeData[$key] = $value;
195 $redirectURL = LinkHandler
::getInstance()->getLink($routeData['controller'], $routeData);
196 HeaderUtil
::redirect($redirectURL, true);
201 * Checks page access for possible mandatory redirects.
203 * @param string $application
204 * @param string[] $routeData
206 protected function handleDefaultController($application, array &$routeData) {
207 if (!RouteHandler
::getInstance()->isDefaultController()) {
211 $data = ControllerMap
::getInstance()->lookupDefaultController($application);
212 if ($data === null) {
213 // handle WCF which does not have a default controller
214 throw new IllegalLinkException();
216 else if (!empty($data['redirect'])) {
218 HeaderUtil
::redirect($data['redirect'], true);
222 foreach ($data as $key => $value) {
223 $routeData[$key] = $value;
228 * Returns the active request object.
232 public function getActiveRequest() {
233 return $this->activeRequest
;
237 * Returns true if the request is an acp request.
241 public function isACPRequest() {
242 return $this->isACPRequest
;
246 * Returns true, if current host mismatches any known domain.
250 public function inRescueMode() {
251 return $this->inRescueMode
;