openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit f1f2297b4205ae9f6d86c41f82b009b6e297e243
parent 457a14d60abbec47e56ad6c696a426777f57fa49
Author: Jan Dankert <devnull@localhost>
Date:   Sat, 30 Dec 2017 21:16:34 +0100

Refactoring des Dispatchers, Aufteilen der Logik in mehrere Methoden. So ist es schöner.

Diffstat:
modules/cms-core/Dispatcher.class.php | 271++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
modules/cms-ui/UI.class.php | 4++++
2 files changed, 163 insertions(+), 112 deletions(-)

diff --git a/modules/cms-core/Dispatcher.class.php b/modules/cms-core/Dispatcher.class.php @@ -6,6 +6,7 @@ namespace cms; use BadMethodCallException; +use cms\action\Action; use Configuration; use DomainException; use Http; @@ -21,17 +22,25 @@ $conf = array(); $SESS = array(); $FILES = array(); +/** + * Dispatcher for all cms actions. + * + * @package cms + */ class Dispatcher { public $action; public $subaction; /** - * @return array + * @return array data for the client */ public function doAction() { - // Jetzt erst die Sitzung starten (nachdem alle Klassen zur Verfügung stehen). + define('PRODUCTION', config('production')); + define('DEVELOPMENT', !PRODUCTION); + + // Start the session. All classes should have been loaded up to now. session_start(); global $SESS; @@ -40,10 +49,147 @@ class Dispatcher global $FILES; $FILES = &$_FILES; + $this->checkConfiguration(); + // Vorhandene Konfiguration aus der Sitzung lesen. global $conf; $conf = Session::getConfig(); + // Nachdem die Konfiguration gelesen wurde, kann nun der Logger benutzt werden. + require_once(OR_MODULES_DIR . "logger/require." . PHP_EXT); + $this->initializeLogger(); + + + if (!empty($conf['security']['umask'])) + umask(octdec($conf['security']['umask'])); + + if (!empty($conf['interface']['timeout'])) + set_time_limit(intval($conf['interface']['timeout'])); + + $this->checkPostToken(); + + define('FILE_SEP', $conf['interface']['file_separator']); + + define('TEMPLATE_DIR', OR_THEMES_DIR . $conf['interface']['theme'] . '/templates'); + define('CSS_DIR', OR_THEMES_DIR . $conf['interface']['theme'] . '/css'); + define('IMAGE_DIR', OR_THEMES_DIR . $conf['interface']['theme'] . '/images'); + + + $this->startDatabaseTransaction(); + + $result = $this->callActionMethod(); + + Logger::trace('Output' . "\n" . print_r($result, true)); + + // Weitere Variablen anreichern. + $result['session'] = array('name' => session_name(), 'id' => session_id(), 'token' => token()); + $result['version'] = OR_VERSION; + $result['api'] = '2'; + + $this->commitDatabaseTransaction(); + + Session::close(); + + // Ablaufzeit für den Inhalt auf aktuelle Zeit setzen. + header('Expires: ' . substr(date('r', time() - date('Z')), 0, -5) . 'GMT', false); + + return $result; + } + + /** + * Prüft, ob die Actionklasse aufgerufen werden darf. + * + * @param $do Action + * @throws SecurityException falls der Aufruf nicht erlaubt ist. + */ + private function checkAccess($do) + { + switch (@$do->security) { + case SECURITY_GUEST: + // Ok. + break; + case SECURITY_USER: + if (!is_object($do->currentUser)) + throw new SecurityException('No user logged in, but this action requires a valid user'); + break; + case SECURITY_ADMIN: + if (!is_object($do->currentUser) || !$do->currentUser->isAdmin) + throw new SecurityException('This action requires administration privileges, but user ' . $do->currentUser->name . ' is not an admin'); + break; + default: + } + + } + + /** + * Startet die Verbindung zur Datenbank und eröffnet eine Transaktion. + */ + private function startDatabaseTransaction() + { + // Verbindung zur Datenbank + // + $db = Session::getDatabase(); + if (is_object($db)) { + $ok = $db->connect(); + if (!$ok) + throw new DomainException('Database is not available: ' . $db->error); + + Session::setDatabase($db); + $db->start(); + } + + } + + private function checkPostToken() + { + global $REQ; + if (config('security', 'use_post_token') && $_SERVER['REQUEST_METHOD'] == 'POST' && @$REQ[REQ_PARAM_TOKEN] != token()) { + Logger::error('Token mismatch: Needed ' . token() . ' but got ' . @$REQ[REQ_PARAM_TOKEN] . '. Maybe an attacker?'); + Http::notAuthorized("Token mismatch", "Token mismatch"); + } + } + + /** + * Logger initialisieren. + */ + private function initializeLogger() + { + $logConfig = config('log'); + + Logger::$messageFormat = $logConfig['format']; + Logger::$filename = $logConfig['file']; + Logger::$dateFormat = $logConfig['date_format']; + Logger::$nsLookup = $logConfig['ns_lookup']; + + $cname = 'LOGGER_LOG_' . strtoupper($logConfig['level']); + if (defined($cname)) + Logger::$level = constant($cname); + + + Logger::$messageCallback = function () { + $action = Session::get('action'); + if (empty($action)) + $action = '-'; + + $action = Session::get('action'); + if (empty($action)) + $action = '-'; + + $user = Session::getUser(); + if (is_object($user)) + $username = $user->name; + else + $username = '-'; + + return array('user' => $username, 'action' => $action); + }; + Logger::init(); + } + + private function checkConfiguration() + { + $conf = Session::getConfig(); + // Konfiguration lesen. // Wenn Konfiguration noch nicht in Session vorhanden oder die Konfiguration geändert wurde (erkennbar anhand des Datei-Datums) // dann die Konfiguration neu einlesen. @@ -106,77 +252,14 @@ class Dispatcher Session::setConfig($conf); } + } -// Nachdem die Konfiguration gelesen wurde, kann nun der Logger benutzt werden. - require_once(OR_MODULES_DIR . "logger/require." . PHP_EXT); - -// Logger initialisieren - Logger::$messageFormat = $conf['log']['format']; - Logger::$filename = $conf['log']['file']; - Logger::$dateFormat = $conf['log']['date_format']; - Logger::$nsLookup = $conf['log']['ns_lookup']; - - $cname = 'LOGGER_LOG_' . strtoupper($conf['log']['level']); - if (defined($cname)) - Logger::$level = constant($cname); - - - Logger::$messageCallback = function () { - $action = Session::get('action'); - if (empty($action)) - $action = '-'; - - $action = Session::get('action'); - if (empty($action)) - $action = '-'; - - $user = Session::getUser(); - if (is_object($user)) - $username = $user->name; - else - $username = '-'; - - return array('user' => $username, 'action' => $action); - }; - Logger::init(); - - - if (!empty($conf['security']['umask'])) - umask(octdec($conf['security']['umask'])); - - if (!empty($conf['interface']['timeout'])) - set_time_limit(intval($conf['interface']['timeout'])); - + /** + * @return array + */ + private function callActionMethod() + { global $REQ; - if (config('security', 'use_post_token') && $_SERVER['REQUEST_METHOD'] == 'POST' && @$REQ[REQ_PARAM_TOKEN] != token()) { - Logger::error('Token mismatch: Needed ' . token() . ' but got ' . @$REQ[REQ_PARAM_TOKEN] . '. Maybe an attacker?'); - Http::notAuthorized("Token mismatch", "Token mismatch"); - } - - - - define('FILE_SEP', $conf['interface']['file_separator']); - - define('TEMPLATE_DIR', OR_THEMES_DIR . $conf['interface']['theme'] . '/templates'); - define('CSS_DIR', OR_THEMES_DIR . $conf['interface']['theme'] . '/css'); - define('IMAGE_DIR', OR_THEMES_DIR . $conf['interface']['theme'] . '/images'); - - define('PRODUCTION', $conf['production']); - define('DEVELOPMENT', !PRODUCTION); - - // Verbindung zur Datenbank - // - $db = Session::getDatabase(); - if (is_object($db)) { - $ok = $db->connect(); - if (!$ok) - throw new DomainException('Database is not available: ' . $db->error); - - Session::setDatabase($db); - $db->start(); - } - - $actionClassName = ucfirst($this->action) . 'Action'; $actionClassNameWithNamespace = 'cms\\action\\' . $actionClassName; @@ -203,21 +286,7 @@ class Dispatcher $do->init(); - - switch (@$do->security) { - case SECURITY_GUEST: - // Ok. - break; - case SECURITY_USER: - if (!is_object($do->currentUser)) - throw new SecurityException('No user logged in, but this action requires a valid user'); - break; - case SECURITY_ADMIN: - if (!is_object($do->currentUser) || !$do->currentUser->isAdmin) - throw new SecurityException('This action requires administration privileges, but user ' . $do->currentUser->name . ' is not an admin'); - break; - default: - } + $this->checkAccess($do); $isAction = $_SERVER['REQUEST_METHOD'] == 'POST'; @@ -238,43 +307,21 @@ class Dispatcher if (!method_exists($do, $subactionMethodName)) throw new BadMethodCallException("Method '$subactionMethodName' does not exist"); - $result = $do->$subactionMethodName(); // <== Executing the Action + $do->$subactionMethodName(); // <== Executing the Action // The action is able to change its method name. $this->subaction = $do->subActionName; - Logger::trace('Output' . "\n" . print_r($result, true)); - - // Weitere Variablen anreichern. - $result['session'] = array('name' => session_name(), 'id' => session_id(), 'token' => token()); - $result['version'] = OR_VERSION; - $result['api'] = '2'; - - $do->handleResult($result); - - $this->cleanup(); - - return $do->getOutputData(); + $result = $do->getOutputData(); + return $result; } - private function cleanup() + private function commitDatabaseTransaction() { - - Session::close(); - global $conf; - $db = db_connection(); if (is_object($db)) $db->commit(); - - // Ablaufzeit für den Inhalt auf aktuelle Zeit setzen. - header('Expires: ' . substr(date('r', time() - date('Z')), 0, -5) . 'GMT', false); - - if ($conf['security']['content-security-policy']) - header('X-Content-Security-Policy: ' . 'allow \'self\'; img-src: *; script-src \'self\'; options inline-script'); - - } } \ No newline at end of file diff --git a/modules/cms-ui/UI.class.php b/modules/cms-ui/UI.class.php @@ -47,6 +47,7 @@ class UI $data = $dispatcher->doAction(); + // The action is able to change its method name. $subaction = $dispatcher->subaction; @@ -54,6 +55,9 @@ class UI $tplName = $action . '/' . $subaction; + if (config('security','content-security-policy')) + header('X-Content-Security-Policy: ' . 'allow \'self\'; img-src: *; script-src \'self\'; options inline-script'); + UI::outputTemplate($tplName,$data['output']); } catch (BadMethodCallException $e) { // Action-Method does not exist.