setRequest($request) ->setResponse($response) ->_setInvokeArgs($invokeArgs); $this->prepareViewRenderer(); $this->_helper = new ZfHelperBroker($this); $this->handlerBrowserWindows(); $this->initializeTranslator(); $this->initializeLayout(); $this->view->compact = $request->getParam('view') === 'compact'; $url = $this->url(); $this->params = $url->getParams(); if ($url->shift('showCompact')) { $this->view->compact = true; } $this->checkPermissionBasics(); Benchmark::measure('Ready to initialize the controller'); $this->prepareInit(); $this->init(); } protected function initializeLayout() { $url = $this->url(); $layout = $this->layout = $this->_helper->layout(); $layout->isIframe = $url->shift('isIframe'); $layout->showFullscreen = $url->shift('showFullscreen'); $layout->moduleName = $this->getModuleName(); if ($this->rerenderLayout = $url->shift('renderLayout')) { $this->xhrLayout = $this->innerLayout; } if ($url->shift('_disableLayout')) { $this->layout->disableLayout(); } } /** * Prepare controller initialization * * As it should not be required for controllers to call the parent's init() method, * base controllers should use prepareInit() in order to prepare the controller * initialization. * * @see \Zend_Controller_Action::init() For the controller initialization method. */ protected function prepareInit() { } /** * Return the current module's name * * @return string */ public function getModuleName() { if ($this->moduleName === null) { $this->moduleName = $this->getRequest()->getModuleName(); } return $this->moduleName; } protected function setModuleName($name) { $this->moduleName = $name; return $this; } /** * Return this controller's module * * @return Module * @codingStandardsIgnoreStart */ public function Module() { // @codingStandardsIgnoreEnd if ($this->module === null) { try { $this->module = Icinga::app()->getModuleManager()->getModule($this->getModuleName()); } catch (ProgrammingError $e) { throw new RuntimeException($e->getMessage(), $e->getCode(), $e); } } return $this->module; } /** * @return Window * @codingStandardsIgnoreStart */ public function Window() { // @codingStandardsIgnoreEnd if ($this->window === null) { $this->window = new Window( $this->getRequestHeader('X-Icinga-WindowId', Window::UNDEFINED) ); } return $this->window; } protected function handlerBrowserWindows() { if ($this->isXhr()) { $id = $this->getRequestHeader('X-Icinga-WindowId', Window::UNDEFINED); if ($id === Window::UNDEFINED) { $this->window = new Window($id); $this->_response->setHeader('X-Icinga-WindowId', Window::generateId()); } } } /** * @return ServerRequestInterface */ protected function getServerRequest() { return ServerRequest::fromGlobals(); } protected function getRequestHeader($key, $default = null) { try { $value = $this->getRequest()->getHeader($key); } catch (\Zend_Controller_Request_Exception $e) { throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); } if ($value === null) { return $default; } else { return $value; } } /** * @throws SecurityException */ protected function checkPermissionBasics() { $request = $this->getRequest(); // $auth->authenticate($request, $response, $this->requiresLogin()); if ($this->requiresLogin()) { if (! $request->isXmlHttpRequest() && $request->isApiRequest()) { Auth::getInstance()->challengeHttp(); } $this->redirectToLogin(Url::fromRequest()); } if (($this->Auth()->isAuthenticated() || $this->requiresLogin()) && $this->getFrontController()->getDefaultModule() !== $this->getModuleName()) { $this->assertPermission(Manager::MODULE_PERMISSION_NS . $this->getModuleName()); } } protected function initializeTranslator() { $moduleName = $this->getModuleName(); $domain = $moduleName !== 'default' ? $moduleName : 'icinga'; $this->view->translationDomain = $domain; StaticTranslator::set(new Translator($domain)); } public function init() { // Hint: we intentionally do not call our parent's init() method } /** * Get the authentication manager * * @return Auth * @codingStandardsIgnoreStart */ public function Auth() { // @codingStandardsIgnoreEnd if ($this->auth === null) { $this->auth = Auth::getInstance(); } return $this->auth; } /** * Whether the current user has the given permission * * @param string $permission Name of the permission * * @return bool */ public function hasPermission($permission) { return $this->Auth()->hasPermission($permission); } /** * Assert that the current user has the given permission * * @param string $permission Name of the permission * * @throws SecurityException If the current user lacks the given permission */ public function assertPermission($permission) { if (! $this->Auth()->hasPermission($permission)) { throw new SecurityException('No permission for %s', $permission); } } /** * Return restriction information for an eventually authenticated user * * @param string $name Restriction name * * @return array */ public function getRestrictions($name) { return $this->Auth()->getRestrictions($name); } /** * Check whether the controller requires a login. That is when the controller requires authentication and the * user is currently not authenticated * * @return bool */ protected function requiresLogin() { if (! $this->requiresAuthentication) { return false; } return ! $this->Auth()->isAuthenticated(); } public function prepareViewRenderer() { $this->viewRenderer = new SimpleViewRenderer(); $this->viewRenderer->replaceZendViewRenderer(); $this->view = $this->viewRenderer->view; } /** * @return SimpleViewRenderer */ public function getViewRenderer() { return $this->viewRenderer; } protected function redirectXhr($url) { if (! $url instanceof WebUrl) { $url = Url::fromPath($url); } if ($this->rerenderLayout) { $this->getResponse()->setHeader('X-Icinga-Rerender-Layout', 'yes'); } if ($this->reloadCss) { $this->getResponse()->setHeader('X-Icinga-Reload-Css', 'now'); } $this->shutdownSession(); $this->getResponse() ->setHeader('X-Icinga-Redirect', rawurlencode($url->getAbsoluteUrl())) ->sendHeaders(); exit; } /** * Detect whether the current request requires changes in the layout and apply them before rendering * * @see Zend_Controller_Action::postDispatch() */ public function postDispatch() { Benchmark::measure('Action::postDispatch()'); $layout = $this->layout; $req = $this->getRequest(); $layout->innerLayout = $this->innerLayout; /** @var User $user */ if ($user = $req->getUser()) { if ((bool) $user->getPreferences()->getValue('icingaweb', 'show_benchmark', false)) { if ($layout->isEnabled()) { $layout->benchmark = $this->renderBenchmark(); } } if (! (bool) $user->getPreferences()->getValue('icingaweb', 'auto_refresh', true)) { $this->disableAutoRefresh(); } } if ($req->getParam('format') === 'pdf') { $this->shutdownSession(); $this->sendAsPdf(); return; } if ($this->isXhr()) { $this->postDispatchXhr(); } $this->shutdownSession(); } public function postDispatchXhr() { $this->layout->setLayout($this->xhrLayout); $resp = $this->getResponse(); $notifications = Notification::getInstance(); if ($notifications->hasMessages()) { $notificationList = array(); foreach ($notifications->popMessages() as $m) { $notificationList[] = rawurlencode($m->type . ' ' . $m->message); } $resp->setHeader('X-Icinga-Notification', implode('&', $notificationList), true); } if ($this->reloadCss) { $resp->setHeader('X-Icinga-CssReload', 'now', true); } if ($this->title) { if (preg_match('~[\r\n]~', $this->title)) { // TODO: Innocent exception and error log for hack attempts throw new InvalidArgumentException('No newlines allowed in page title'); } $resp->setHeader( 'X-Icinga-Title', // TODO: Config rawurlencode($this->title . ' :: ' . $this->applicationName), true ); } else { // TODO: config $resp->setHeader('X-Icinga-Title', rawurlencode($this->applicationName), true); } if ($this->rerenderLayout) { $this->getResponse()->setHeader('X-Icinga-Container', 'layout', true); } if (isset($this->autorefreshInterval)) { $resp->setHeader('X-Icinga-Refresh', $this->autorefreshInterval, true); } if ($name = $this->getModuleName()) { $this->getResponse()->setHeader('X-Icinga-Module', $name, true); } } /** * Redirect to login * * XHR will always redirect to __SELF__ if an URL to redirect to after successful login is set. __SELF__ instructs * JavaScript to redirect to the current window's URL if it's an auto-refresh request or to redirect to the URL * which required login if it's not an auto-refreshing one. * * XHR will respond with HTTP status code 403 Forbidden. * * @param Url|string $redirect URL to redirect to after successful login */ protected function redirectToLogin($redirect = null) { $login = Url::fromPath('authentication/login'); if ($this->isXhr()) { if ($redirect !== null) { $login->setParam('redirect', '__SELF__'); } $this->_response->setHttpResponseCode(403); } elseif ($redirect !== null) { if (! $redirect instanceof Url) { $redirect = Url::fromPath($redirect); } if (($relativeUrl = $redirect->getRelativeUrl())) { $login->setParam('redirect', $relativeUrl); } } $this->rerenderLayout()->redirectNow($login); } protected function sendAsPdf() { $pdf = new Pdf(); $pdf->renderControllerAction($this); } /** * Render the benchmark * * @return string Benchmark HTML */ protected function renderBenchmark() { $this->viewRenderer->postDispatch(); Benchmark::measure('Response ready'); return Benchmark::renderToHtml()/* . '
' . print_r(get_included_files(), 1) . ''*/; } public function isXhr() { return $this->getRequest()->isXmlHttpRequest(); } protected function redirectHttp($url) { if (! $url instanceof Url) { $url = Url::fromPath($url); } $this->shutdownSession(); $this->_helper->Redirector->gotoUrlAndExit($url->getRelativeUrl()); } /** * Redirect to a specific url, updating the browsers URL field * * @param Url|string $url The target to redirect to **/ public function redirectNow($url) { if ($this->isXhr()) { $this->redirectXhr($url); } else { $this->redirectHttp($url); } } protected function shutdownSession() { $session = Session::getSession(); if ($session->hasChanged()) { $session->write(); } } protected function rerenderLayout() { $this->rerenderLayout = true; $this->xhrLayout = 'layout'; return $this; } protected function reloadCss() { $this->reloadCss = true; return $this; } }