* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 * @author Icinga Development Team */ // {{{ICINGA_LICENSE_HEADER}}} namespace Icinga\Web\Controller; use \Icinga\Authentication\Manager as AuthManager; use \Icinga\Application\Benchmark; use \Icinga\Exception; use \Icinga\Application\Config; use \Icinga\Web\Notification; use \Zend_Layout as ZfLayout; use \Zend_Controller_Action as ZfController; use \Zend_Controller_Request_Abstract as ZfRequest; use \Zend_Controller_Response_Abstract as ZfResponse; use \Zend_Controller_Action_HelperBroker as ZfActionHelper; /* * @TODO(el): There was a note from tg that the following line is temporary. Ask him why. */ use Icinga\File\Pdf; /** * Base class for all core action controllers * * All Icinga Web core controllers should extend this class * * @copyright Copyright (c) 2013 Icinga-Web Team * @author Icinga-Web Team * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License */ class ActionController extends ZfController { /** * The Icinga Config object is available in all controllers. This is the * modules config for module action controllers. * @var Config */ protected $config; protected $replaceLayout = false; /** * The current module name. TODO: Find out whether this shall be null for * non-module actions * * @var string */ protected $module_name; /** * The current controller name * * @var string */ protected $controller_name; /** * The current action name * * @var string */ protected $action_name; // @TODO(el): Should be true, is/was disabled for testing purpose protected $handlesAuthentication = false; protected $modifiesSession = false; private $allowAccess = false; /** * The constructor starts benchmarking, loads the configuration and sets * other useful controller properties * * @param ZfRequest $request * @param ZfResponse $response * @param array $invokeArgs Any additional invocation arguments */ public function __construct( ZfRequest $request, ZfResponse $response, array $invokeArgs = array() ) { Benchmark::measure('Action::__construct()'); $this->module_name = $request->getModuleName(); $this->controller_name = $request->getControllerName(); $this->action_name = $request->getActionName(); $this->loadConfig(); $this->setRequest($request) ->setResponse($response) ->_setInvokeArgs($invokeArgs); $this->_helper = new ZfActionHelper($this); if ($this->handlesAuthentication() || AuthManager::getInstance( null, array( 'writeSession' => $this->modifiesSession ) )->isAuthenticated() ) { $this->allowAccess = true; $this->init(); } } /** * This is where the configuration is going to be loaded * * @return void */ protected function loadConfig() { $this->config = Config::app(); } /** * Translates the given string with the global translation catalog * * @param string $string The string that should be translated * * @return string */ public function translate($string) { return t($string); } /** * Whether the current user has the given permission * * TODO: This has not been implemented yet * * @param string $permission Permission name * @param string $object No idea what this should have been :-) * * @return bool */ final protected function hasPermission($uri, $permission = 'read') { return true; } /** * Assert the current user has the given permission * * TODO: This has not been implemented yet * * @param string $permission Permission name * @param string $object No idea what this should have been :-) * * @return self */ final protected function assertPermission($permission, $object = null) { if (! $this->hasPermission($permission, $object)) { // TODO: Log violation, create dedicated Exception class throw new \Exception('Permission denied'); } return $this; } protected function preserve($key, $value = null) { if ($value === null) { $value = $this->_getParam($key); } if ($value !== null) { if (! isset($this->view->preserve)) { $this->view->preserve = array(); } $this->view->preserve[$key] = $value; } return $this; } /** * Our benchmark wants to know when we started our dispatch loop * * @return void */ public function preDispatch() { Benchmark::measure('Action::preDispatch()'); if (! $this->allowAccess) { $this->_request->setModuleName('default') ->setControllerName('authentication') ->setActionName('login') ->setDispatched(false); return; } $this->view->action_name = $this->action_name; $this->view->controller_name = $this->controller_name; $this->view->module_name = $this->module_name; // TODO(el): What is this, why do we need that here? $this->view->compact = $this->_request->getParam('view') === 'compact'; Benchmark::measure( sprintf( 'Action::preDispatched(): %s / %s / %s', $this->module_name, $this->controller_name, $this->action_name ) ); //$this->quickRedirect('/authentication/login?a=e'); } public function redirectNow($url, array $params = array()) { if ($url instanceof Url) { $url = $url->getRelativeUrl(); } $this->_helper->Redirector->gotoUrlAndExit($url); } public function handlesAuthentication() { return $this->handlesAuthentication; } /** * Render our benchmark * * @return string */ protected function renderBenchmark() { return '
'
             . Benchmark::renderToHtml()
             . '
'; } /** * After dispatch happend we are going to do some automagic stuff * * - Benchmark is completed and rendered * - Notifications will be collected here * - Layout is disabled for XHR requests * - TODO: Headers with required JS and other things will be created * for XHR requests * * @return void */ public function postDispatch() { Benchmark::measure('Action::postDispatch()'); // TODO: Move this elsewhere, this is just an ugly test: if ($this->_request->getParam('filetype') === 'pdf') { // Snippet stolen from less compiler in public/css.php: require_once 'vendor/lessphp/lessc.inc.php'; $less = new \lessc; $cssdir = dirname(ICINGA_LIBDIR) . '/public/css'; // TODO: We need a way to retrieve public dir, even if located elsewhere $css = $less->compileFile($cssdir . '/pdfprint.less'); $this->render( null, $this->_helper->viewRenderer->getResponseSegment(), $this->_helper->viewRenderer->getNoController() ); $html = (string) $this->getResponse(); if ($this->module_name !== null) { $html = '
' . "\n" . $html . '
'; } $html = '' . $html; $pdf = new Pdf(); $pdf->AddPage(); $pdf->setFontSubsetting(false); $pdf->writeHTML($html); //0, 0, '', '', $html, 0, 1, 0, true, '', true); $pdf->Output('docs.pdf', 'I'); exit; } // END of PDF test if ($this->_request->isXmlHttpRequest()) { if ($this->replaceLayout || $this->_getParam('_render') === 'body') { $this->_helper->layout()->setLayout('just-the-body'); header('X-Icinga-Target: body'); } else { $this->_helper->layout()->setLayout('inline'); } } $notification = Notification::getInstance(); if ($notification->hasMessages()) { $nhtml = '
    '; foreach ($notification->getMessages() as $msg) { $nhtml .= '
  • [' . $msg->type . '] ' . htmlspecialchars($msg->message); } $nhtml .= '
'; $this->getResponse()->append('notification', $nhtml); } if (AuthManager::getInstance()->getSession()->get('show_benchmark')) { Benchmark::measure('Response ready'); $this->_helper->layout()->benchmark = $this->renderBenchmark(); } } }