openrat-cms

# OpenRat Content Management System
git clone http://git.code.weiherhei.de/openrat-cms.git
Log | Files | Refs

commit 953e0c4399ae9a55116f8a6b6ddfbe81f22b0174
parent a09b09c8a618284def9100193970b39fdbfd9c37
Author: Jan Dankert <develop@jandankert.de>
Date:   Mon, 20 May 2019 00:34:19 +0200

Refactoring: Datenbankverbindung im Dispatcher erstellen. Bisher wurde in der Loginaction die DB-Verbindung aufgebaut, was dort falsch aufgehoben war.

Diffstat:
modules/cms-core/Dispatcher.class.php | 854+++++++++++++++++++++++++++++++++++++++++--------------------------------------
modules/cms-core/action/LoginAction.class.php | 3262++++++++++++++++++++++++++++++++++++-------------------------------------------
modules/cms-core/functions/common.inc.php | 352+++++++++++++++++++++++++++++++++++++++----------------------------------------
modules/cms-core/model/BaseObject.class.php | 8++------
modules/cms-core/model/Language.class.php | 432+++++++++++++++++++++++++++++++++++++++----------------------------------------
modules/cms-core/model/Project.class.php | 2050+++++++++++++++++++++++++++++++++++++++----------------------------------------
modules/cms-core/model/User.class.php | 27+++++----------------------
modules/cms-core/model/Value.class.php | 2+-
modules/cms-ui/action/TitleAction.class.php | 230++++++++++++++++++++++++++++++++++++++++----------------------------------------
modules/configuration/Configuration.class.php | 29+++++++++++++++++++++++++++++
modules/configuration/ConfigurationLoader.class.php | 2+-
modules/database/Database.class.php | 453+++++++++++++++++++++++++++++++++++++++----------------------------------------
modules/util/Http.class.php | 2+-
modules/util/Session.class.php | 40++++++++++++++++++++++++++++++----------
modules/util/config-default.php | 2--
15 files changed, 3757 insertions(+), 3988 deletions(-)

diff --git a/modules/cms-core/Dispatcher.class.php b/modules/cms-core/Dispatcher.class.php @@ -1,412 +1,444 @@ -<?php - -/* - * Loading and calling the action class (the "controller"). - */ -namespace cms; - -use BadMethodCallException; -use cms\action\Action; -use cms\action\RequestParams; -use ConfigurationLoader; -use DomainException; -use Http; -use http\Exception; -use language\Language; -use Logger; -use LogicException; -use ObjectNotFoundException; -use OpenRatException; -use SecurityException; -use Session; -use Spyc; - - -/** - * Dispatcher for all cms actions. - * - * @package cms - */ -class Dispatcher -{ - /** - * @var RequestParams - */ - public $request; - - /** - * Vollständige Abarbeitug einer Aktion. - * Führt die gesamte Abarbeitung einer Aktion durch, incl. Datenbank-Transaktionssteuerung. - * - * @return array data for the client - */ - public function doAction() - { - // Start the session. All classes should have been loaded up to now. - session_start(); - - $this->checkConfiguration(); - - // Vorhandene Konfiguration aus der Sitzung lesen. - global $conf; - $conf = Session::getConfig(); - - define('PRODUCTION', Conf()->is('production')); - define('DEVELOPMENT', !PRODUCTION); - - if( DEVELOPMENT) - { - ini_set('display_errors', 1); - ini_set('display_startup_errors', 1); - error_reporting(E_ALL); - }else { - ini_set('display_errors', 0); - ini_set('display_startup_errors', 0); - error_reporting(0); - } - - $this->setContentLanguageHeader(); - - // Nachdem die Konfiguration gelesen wurde, kann nun der Logger benutzt werden. - require_once(OR_MODULES_DIR . "logger/require." . PHP_EXT); - $this->initializeLogger(); - - // Sollte nur 1x pro Sitzung ausgeführt werden. Wie ermitteln wir das? - //if ( DEVELOPMENT ) - // Logger::debug( "Effective configuration:\n".Spyc::YAMLDump($conf) ); - - 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']); - - $this->connectToDatabase(); - $this->startDatabaseTransaction(); - - try{ - - $result = $this->callActionMethod(); - } - catch(Exception $e) - { - // In case of exception, rolling back the transaction - try - { - $this->rollbackDatabaseTransaction(); - } - catch(Exception $re) - { - Logger::warn("rollback failed:".$e->getMessage()); - } - - throw $e; - } - - $this->commitDatabaseTransaction(); - - if ( DEVELOPMENT ) - 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'; - - - // Yes, closing the session flushes the session data and unlocks other waiting requests. - // Now another request is able to be executed. - 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 Action::SECURITY_GUEST: - // Ok. - break; - case Action::SECURITY_USER: - if (!is_object($do->currentUser)) - throw new SecurityException('No user logged in, but this action requires a valid user'); - break; - case Action::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: - } - - } - - 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?'); - throw new SecurityException("Token mismatch"); - } - } - - /** - * Logger initialisieren. - */ - private function initializeLogger() - { - - $logConfig = config('log'); - - $logFile = $logConfig['file']; - - // Wenn Logfile relativ angegeben wurde, dann muss dies relativ zum Root der Anwendung sein. - if ( !empty($logFile) && $logFile[0] != '/' ) - $logFile = __DIR__.'/../../'.$logFile; - //$logFile = __DIR__.'/../../'.$logFile; - - Logger::$messageFormat = $logConfig['format']; - Logger::$filename = $logFile; - 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 = '-'; - - $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. - $configLoader = new ConfigurationLoader( __DIR__.'/../../config/config.yml' ); - - if (!is_array($conf) || $conf['config']['auto_reload'] && $configLoader->lastModificationTime() > $conf['config']['last_modification_time']) { - - // Da die Konfiguration neu eingelesen wird, sollten wir auch die Sitzung komplett leeren. - if (is_array($conf) && $conf['config']['session_destroy_on_config_reload']) - session_unset(); - - // Fest eingebaute Standard-Konfiguration laden. - require(OR_MODULES_DIR . 'util/config-default.php'); - $conf = createDefaultConfig(); - - $customConfig = $configLoader->load(); - $conf = array_replace_recursive($conf, $customConfig); - - // Sprache lesen - - if ($conf['i18n']['use_http']) - // Die vom Browser angeforderten Sprachen ermitteln - $languages = Http::getLanguages(); - else - // Nur Default-Sprache erlauben - $languages = array(); - - if (isset($_COOKIE['or_language'])) - $languages = array($_COOKIE['or_language']) + $languages; - - // Default-Sprache hinzufuegen. - // Wird dann verwendet, wenn die vom Browser angeforderten Sprachen - // nicht vorhanden sind - $languages[] = $conf['i18n']['default']; - $available = explode(',', $conf['i18n']['available']); - - foreach ($languages as $l) { - if (!in_array($l, $available)) - continue; // language is not configured as available. - - $isProduction = $conf['production']; - $language = new \language\Language(); - $lang = $language->getLanguage( $l,$isProduction); - $conf['language'] = $lang; - $conf['language']['language_code'] = $l; - break; - } - - - if (!isset($conf['language'])) - throw new \LogicException('no language found! (languages=' . implode(',', $languages) . ')'); - - // Schreibt die Konfiguration in die Sitzung. Diese wird anschliessend nicht - // mehr veraendert. - Session::setConfig($conf); - } - - } - - /** - * Aufruf der Action-Methode. - * Diese Methode muss public sein, da sie für Embedded-Actions aus dem UI direkt aufgerufen wird. - * - * @return array Vollständige Rückgabe aller Daten als assoziatives Array - */ - public function callActionMethod() - { - global $REQ; - $actionClassName = ucfirst($this->request->action) . 'Action'; - $actionClassNameWithNamespace = 'cms\\action\\' . $actionClassName; - - if (!class_exists($actionClassNameWithNamespace)) - { - // Laden der Action-Klasse. - $success = include_once(__DIR__. '/action/' . $actionClassName . '.class.php'); - - if ( !$success) - throw new LogicException("Action '$this->request->action' is not available"); - } - - // Erzeugen der Action-Klasse - /* @type $do \cms\action\Action */ - $do = new $actionClassNameWithNamespace; - - $do->request = $this->request; - $do->init(); - - if(!defined('OR_ID')) - //if (isset($REQ[REQ_PARAM_ID])) - define('OR_ID', $this->request->id); - //else - // define('OR_ID', ''); - - $this->checkAccess($do); - - // POST-Request => ...Post() wird aufgerufen. - // GET-Request => ...View() wird aufgerufen. - $methodSuffix = $this->request->isAction ? 'Post' : 'View'; - $subactionMethodName = $this->request->method . $methodSuffix; - - // Daten werden nur angezeigt, die Sitzung kann also schon geschlossen werden. - // Halt! In Index-Action können Benutzer-Logins gesetzt werden. - if ( ! $this->request->isAction && $this->request->action != 'index' ) - Session::close(); - - Logger::debug("Dispatcher executing {$this->request->action}/{$this->request->method}/" . @$REQ[REQ_PARAM_ID].' -> '.$actionClassName.'#'.$subactionMethodName.'() embed='.$this->request->isEmbedded); - - - try { - $method = new \ReflectionMethod($do,$subactionMethodName); - $declaredClassName = $method->getDeclaringClass()->getShortName(); - $declaredActionName = strtolower(substr($declaredClassName,0,strpos($declaredClassName,'Action'))); - - $method->invoke($do); // <== Executing the Action - } - catch (\ValidationException $ve) - { - $do->addValidationError( $ve->fieldName ); - } - catch (\ReflectionException $re) - { - throw new BadMethodCallException("Method '$subactionMethodName' does not exist",0,$re); - } - - // The action is able to change its method name. - $this->request = $do->request; - $this->request->action = $declaredActionName; - - $result = $do->getOutputData(); - - return $result; - } - - /** - * Startet die Verbindung zur Datenbank. - */ - private function connectToDatabase() - { - // Connect to database - // - $db = Session::getDatabase(); - - if (is_object($db)) { - - $db->connect(); // throws exception if error. - - Session::setDatabase($db); - } - - } - - - /** - * Eröffnet eine Transaktion. - */ - private function startDatabaseTransaction() - { - // Verbindung zur Datenbank - // - $db = Session::getDatabase(); - - if (is_object($db)) { - // Transactions are only needed for POST-Request - // GET-Request do only read from the database and have no need for transactions. - if ( $this->request->isAction ) - $db->start(); - } - - } - - - private function commitDatabaseTransaction() - { - $db = db_connection(); - - if (is_object($db)) - // Transactions were only started for POST-Request - if($this->request->isAction) - $db->commit(); - } - - - - private function rollbackDatabaseTransaction() - { - $db = db_connection(); - - if (is_object($db)) - // Transactions were only started for POST-Request - if($this->request->isAction) - $db->rollback(); - } - - - /** - * Sets the "Content-Language"-HTTP-Header with the user language. - */ - private function setContentLanguageHeader() - { - header('Content-Language: ' . Conf()->subset('language')->get('language_code') ); - } +<?php + +/* + * Loading and calling the action class (the "controller"). + */ +namespace cms; + +use BadMethodCallException; +use cms\action\Action; +use cms\action\RequestParams; +use ConfigurationLoader; +use database\Database; +use DomainException; +use Http; +use http\Exception; +use language\Language; +use Logger; +use LogicException; +use ObjectNotFoundException; +use OpenRatException; +use SecurityException; +use Session; +use Spyc; +use template_engine\components\ElseComponent; + + +/** + * Dispatcher for all cms actions. + * + * @package cms + */ +class Dispatcher +{ + /** + * @var RequestParams + */ + public $request; + + /** + * Vollständige Abarbeitug einer Aktion. + * Führt die gesamte Abarbeitung einer Aktion durch, incl. Datenbank-Transaktionssteuerung. + * + * @return array data for the client + */ + public function doAction() + { + // Start the session. All classes should have been loaded up to now. + session_start(); + + $this->checkConfiguration(); + + // Vorhandene Konfiguration aus der Sitzung lesen. + global $conf; + $conf = Session::getConfig(); + + define('PRODUCTION', Conf()->is('production')); + define('DEVELOPMENT', !PRODUCTION); + + if( DEVELOPMENT) + { + ini_set('display_errors', 1); + ini_set('display_startup_errors', 1); + error_reporting(E_ALL); + }else { + ini_set('display_errors', 0); + ini_set('display_startup_errors', 0); + error_reporting(0); + } + + $this->setContentLanguageHeader(); + + // Nachdem die Konfiguration gelesen wurde, kann nun der Logger benutzt werden. + require_once(OR_MODULES_DIR . "logger/require." . PHP_EXT); + $this->initializeLogger(); + + // Sollte nur 1x pro Sitzung ausgeführt werden. Wie ermitteln wir das? + //if ( DEVELOPMENT ) + // Logger::debug( "Effective configuration:\n".Spyc::YAMLDump($conf) ); + + 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']); + + $this->connectToDatabase(); + $this->startDatabaseTransaction(); + + try{ + + $result = $this->callActionMethod(); + } + catch(Exception $e) + { + // In case of exception, rolling back the transaction + try + { + $this->rollbackDatabaseTransaction(); + } + catch(Exception $re) + { + Logger::warn("rollback failed:".$e->getMessage()); + } + + throw $e; + } + + $this->commitDatabaseTransaction(); + + if ( DEVELOPMENT ) + 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'; + + + // Yes, closing the session flushes the session data and unlocks other waiting requests. + // Now another request is able to be executed. + 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 Action::SECURITY_GUEST: + // Ok. + break; + case Action::SECURITY_USER: + if (!is_object($do->currentUser)) + throw new SecurityException('No user logged in, but this action requires a valid user'); + break; + case Action::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: + } + + } + + 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?'); + throw new SecurityException("Token mismatch"); + } + } + + /** + * Logger initialisieren. + */ + private function initializeLogger() + { + + $logConfig = config('log'); + + $logFile = $logConfig['file']; + + // Wenn Logfile relativ angegeben wurde, dann muss dies relativ zum Root der Anwendung sein. + if ( !empty($logFile) && $logFile[0] != '/' ) + $logFile = __DIR__.'/../../'.$logFile; + //$logFile = __DIR__.'/../../'.$logFile; + + Logger::$messageFormat = $logConfig['format']; + Logger::$filename = $logFile; + 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 = '-'; + + $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. + $configLoader = new ConfigurationLoader( __DIR__.'/../../config/config.yml' ); + + if (!is_array($conf) || $conf['config']['auto_reload'] && $configLoader->lastModificationTime() > $conf['config']['last_modification_time']) { + + // Da die Konfiguration neu eingelesen wird, sollten wir auch die Sitzung komplett leeren. + if (is_array($conf) && $conf['config']['session_destroy_on_config_reload']) + session_unset(); + + // Fest eingebaute Standard-Konfiguration laden. + require(OR_MODULES_DIR . 'util/config-default.php'); + $conf = createDefaultConfig(); + + $customConfig = $configLoader->load(); + $conf = array_replace_recursive($conf, $customConfig); + + // Sprache lesen + + if ($conf['i18n']['use_http']) + // Die vom Browser angeforderten Sprachen ermitteln + $languages = Http::getLanguages(); + else + // Nur Default-Sprache erlauben + $languages = array(); + + if (isset($_COOKIE['or_language'])) + $languages = array($_COOKIE['or_language']) + $languages; + + // Default-Sprache hinzufuegen. + // Wird dann verwendet, wenn die vom Browser angeforderten Sprachen + // nicht vorhanden sind + $languages[] = $conf['i18n']['default']; + $available = explode(',', $conf['i18n']['available']); + + foreach ($languages as $l) { + if (!in_array($l, $available)) + continue; // language is not configured as available. + + $isProduction = $conf['production']; + $language = new \language\Language(); + $lang = $language->getLanguage( $l,$isProduction); + $conf['language'] = $lang; + $conf['language']['language_code'] = $l; + break; + } + + + if (!isset($conf['language'])) + throw new \LogicException('no language found! (languages=' . implode(',', $languages) . ')'); + + // Schreibt die Konfiguration in die Sitzung. Diese wird anschliessend nicht + // mehr veraendert. + Session::setConfig($conf); + } + + } + + /** + * Aufruf der Action-Methode. + * Diese Methode muss public sein, da sie für Embedded-Actions aus dem UI direkt aufgerufen wird. + * + * @return array Vollständige Rückgabe aller Daten als assoziatives Array + */ + public function callActionMethod() + { + global $REQ; + $actionClassName = ucfirst($this->request->action) . 'Action'; + $actionClassNameWithNamespace = 'cms\\action\\' . $actionClassName; + + if (!class_exists($actionClassNameWithNamespace)) + { + // Laden der Action-Klasse. + $success = include_once(__DIR__. '/action/' . $actionClassName . '.class.php'); + + if ( !$success) + throw new LogicException("Action '$this->request->action' is not available"); + } + + // Erzeugen der Action-Klasse + /* @type $do \cms\action\Action */ + $do = new $actionClassNameWithNamespace; + + $do->request = $this->request; + $do->init(); + + if(!defined('OR_ID')) + //if (isset($REQ[REQ_PARAM_ID])) + define('OR_ID', $this->request->id); + //else + // define('OR_ID', ''); + + $this->checkAccess($do); + + // POST-Request => ...Post() wird aufgerufen. + // GET-Request => ...View() wird aufgerufen. + $methodSuffix = $this->request->isAction ? 'Post' : 'View'; + $subactionMethodName = $this->request->method . $methodSuffix; + + // Daten werden nur angezeigt, die Sitzung kann also schon geschlossen werden. + // Halt! In Index-Action können Benutzer-Logins gesetzt werden. + if ( ! $this->request->isAction && $this->request->action != 'index' ) + Session::close(); + + Logger::debug("Dispatcher executing {$this->request->action}/{$this->request->method}/" . @$REQ[REQ_PARAM_ID].' -> '.$actionClassName.'#'.$subactionMethodName.'() embed='.$this->request->isEmbedded); + + + try { + $method = new \ReflectionMethod($do,$subactionMethodName); + $declaredClassName = $method->getDeclaringClass()->getShortName(); + $declaredActionName = strtolower(substr($declaredClassName,0,strpos($declaredClassName,'Action'))); + + $method->invoke($do); // <== Executing the Action + } + catch (\ValidationException $ve) + { + $do->addValidationError( $ve->fieldName ); + } + catch (\ReflectionException $re) + { + throw new BadMethodCallException("Method '$subactionMethodName' does not exist",0,$re); + } + + // The action is able to change its method name. + $this->request = $do->request; + $this->request->action = $declaredActionName; + + $result = $do->getOutputData(); + + return $result; + } + + /** + * Startet die Verbindung zur Datenbank. + */ + private function connectToDatabase() + { + if ( $this->request->hasRequestVar('dbid') ) + $dbid = $this->request->getRequestVar('dbid',OR_FILTER_ALPHANUM); + elseif ( !empty( Session::getDatabaseId())) + $dbid = Session::getDatabaseId(); + elseif ( isset($_COOKIE['or_dbid']) ) + $dbid = $_COOKIE['or_dbid']; + else { + //throw new LogicException('No DBID available'); + // some actions do not need a database + // f.e. the login dialog. + // so this is NOT an error. + return; + } + + + $dbConfig = config()->subset('database'); + + if ( ! $dbConfig->has( $dbid ) ) + throw new \LogicException( 'unknown DB-Id: '.$dbid ); + + $dbConfig = $dbConfig->subset($dbid ); + + try + { + $key = $this->request->isAction?'write':'read'; + + $db = new Database( $dbConfig->subset($key)->getConfig() + $dbConfig->getConfig() ); + $db->id = $dbid; + + Session::setDatabaseId( $dbid ); + Session::setDatabase( $db ); + }catch(\Exception $e) + { + throw new OpenRatException('DATABASE_ERROR_CONNECTION',$e->getMessage() ); + } + } + + + /** + * Eröffnet eine Transaktion. + */ + private function startDatabaseTransaction() + { + // Verbindung zur Datenbank + // + $db = Session::getDatabase(); + + if (is_object($db)) { + // Transactions are only needed for POST-Request + // GET-Request do only read from the database and have no need for transactions. + if ( $this->request->isAction ) + { + $db->start(); + + //register_shutdown_function( function() { + // $this->rollbackDatabaseTransaction(); + //}); + } + } + + } + + + private function commitDatabaseTransaction() + { + $db = Session::getDatabase(); + + if (is_object($db)) + // Transactions were only started for POST-Request + if($this->request->isAction) + $db->commit(); + } + + + + private function rollbackDatabaseTransaction() + { + $db = Session::getDatabase(); + + if (is_object($db)) + // Transactions were only started for POST-Request + if($this->request->isAction) + $db->rollback(); + } + + + /** + * Sets the "Content-Language"-HTTP-Header with the user language. + */ + private function setContentLanguageHeader() + { + header('Content-Language: ' . Conf()->subset('language')->get('language_code') ); + } } \ No newline at end of file diff --git a/modules/cms-core/action/LoginAction.class.php b/modules/cms-core/action/LoginAction.class.php @@ -1,1766 +1,1495 @@ -<?php - -namespace cms\action; - - -use cms\model\User; -use cms\model\Project; -use cms\model\Group; -use cms\model\Value; -use cms\model\Element; -use cms\model\Page; -use cms\model\BaseObject; -use cms\model\Language; -use cms\model\Model; - - -use \database\Database; -use \DB; -use \DbUpdate; -use \Exception; -use \Http; -use \InternalAuth; -use \Logger; -use \ObjectNotFoundException; -use \OpenRatException; -use \security\Password; -use \Session; -use \Html; -use \Mail; -use \Text; - - -// OpenRat Content Management System -// Copyright (C) 2002-2007 Jan Dankert, jandankert@jandankert.de -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; version 2. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - -define('PROJECTID_ADMIN',-1); - -/** - * Action-Klasse fuer die Start-Action - * @author $Author$ - * @version $Revision$ - * @package openrat.actions - */ - -class LoginAction extends Action -{ - public $security = Action::SECURITY_GUEST; - - - public function __construct() - { - parent::__construct(); - } - - /** - * Eine Datenbankverbindugn wird aufgebaut und initalisiert. - * - * @param $dbid Datenbank-Id - * @throws OpenRatException - */ - private function setDb( $dbid ) - { - global $conf; - - if ( !isset($conf['database'][$dbid] )) - throw new \LogicException( 'unknown DB-Id: '.$dbid ); - - try{ - - $db = db(); - - $db->rollback(); - $db->disconnect(); // Bäm. This seems to be necessary. WTF? - //$db = null; - //Session::setDatabase( null ); - } - catch( Exception $e) { - // happens if we have no db connection. - } - - try - { - $db = new Database( $conf['database'][$dbid] ); - $db->id = $dbid; - $db->start(); // Transaktion starten. - Session::setDatabase( $db ); - }catch(\Exception $e) - { - throw new OpenRatException('DATABASE_ERROR_CONNECTION',$e->getMessage() ); - } - } - - - /** - * Prueft, ob der Parameter 'dbid' übergeben wurde. - * @throws OpenRatException - */ - function checkForDb() - { - global $conf; - $dbid = $this->getRequestVar('dbid'); - - if ( $dbid != '' ) - $this->setDb( $dbid ); - } - - - /** - * @throws OpenRatException - */ - function setDefaultDb() - { - if ( $this->hasRequestVar(REQ_PARAM_DATABASE_ID) ) - { - $dbid = $this->getRequestVar(REQ_PARAM_DATABASE_ID); - } - else - { - global $conf; - - if ( !isset($conf['database']['default']) ) - throw new \LogicException('default-database not set'); - - $dbid = $conf['database']['default']; - } - - $this->setDb( $dbid ); - } - - - /** - * Führt ein Login durch. - * @param $name string Benutzername - * @param $pw string Password - * @param $pw1 string new Password - * @param $pw2 string new Password repeated - * @return bool - * @throws ObjectNotFoundException - */ - private function checkLogin($name, $pw, $pw1, $pw2 ) - { - Logger::debug( "Login user: '$name'.'" ); - - global $conf; - global $SESS; - - unset( $SESS['user'] ); - - - $db = db_connection(); - - if ( !is_object($db) ) - { - $this->addNotice('database','','DATABASE_CONNECTION_ERROR',OR_NOTICE_ERROR,array(),array('no connection')); - //$this->callSubAction('showlogin'); - return false; - } - - if ( !$db->available ) - { - $this->addNotice('database',$db->conf['description'],'DATABASE_CONNECTION_ERROR',OR_NOTICE_ERROR,array(),array('Database Error: '.$db->error)); - //$this->callSubAction('showlogin'); - return false; - } - - $ip = getenv("REMOTE_ADDR"); - - $user = new User(); - $user->name = $name; - - $ok = $user->checkPassword( $pw ); - - $mustChangePassword = $user->mustChangePassword; - - if ( $mustChangePassword ) - { - // Der Benutzer hat zwar ein richtiges Kennwort eingegeben, aber dieses ist abgelaufen. - // Wir versuchen hier, das neue zu setzen (sofern eingegeben). - if ( empty($pw1) ) - { - } - elseif ( $pw1 != $pw2 ) - { - $this->addValidationError('password1','PASSWORDS_DO_NOT_MATCH'); - $this->addValidationError('password2',''); - } - elseif ( strlen($pw2) < $conf['security']['password']['min_length'] ) - { - $this->addValidationError('password1','PASSWORD_MINLENGTH',array('minlength'=>$conf['security']['password']['min_length'])); - $this->addValidationError('password2',''); - } - else - { - // Kennw?rter identisch und lang genug. - $user->setPassword( $pw1,true ); - - // Das neue Kennwort ist gesetzt, die Anmeldung ist also doch noch gelungen. - $ok = true; - $mustChangePassword = false; - - $pw = $pw1; - } - } - - // Falls Login erfolgreich - if ( $ok ) - { - // Login war erfolgreich! - $user->load(); - $user->setCurrent(); - - if ($user->passwordAlgo != Password::bestAlgoAvailable() ) - // Re-Hash the password with a better hash algo. - $user->setPassword($pw); - - - Logger::info( "login successful for {$user->name} from IP $ip" ); - - return true; - } - else - { - Logger::info( "login failed for user {$user->name} from IP $ip" ); - - return false; - } - } - - - /** - * Anzeigen der Loginmaske. - * - * Es wird nur die Loginmaske angezeigt. - * @throws OpenRatException - */ - function loginView() - { - // Hier nie "304 not modified" setzen, da sonst keine - // Login-Fehlermeldung erscheinen kann. - global $conf; - - $sso = $conf['security']['sso']; - $ssl = $conf['security']['ssl']; - - $ssl_trust = false; - $ssl_user_var = ''; - extract( $ssl, EXTR_PREFIX_ALL, 'ssl' ); - - if ( $sso['enable'] ) - { - $authid = $this->getRequestVar( $sso['auth_param_name']); - - if ( empty( $authid) ) - throw new \SecurityException( 'no authorization data (no auth-id)'); - - if ( $sso['auth_param_serialized'] ) - $authid = unserialize( $authid ); - - $purl = parse_url($sso['url']); - // Verbindung zu URL herstellen. - $errno=0; $errstr=''; - $fp = fsockopen ($purl['host'],80, $errno, $errstr, 30); - if ( !$fp ) - { - echo "Connection failed: $errstr ($errno)"; - } - else - { - $http_get = $purl['path']; - if ( !empty($purl['query']) ) - $http_get .= '?'.$purl['query']; - - $header = array(); - - $header[] = "GET $http_get HTTP/1.0"; - $header[] ="Host: ".$purl['host']; - $header[] = "User-Agent: Mozilla/5.0 (OpenRat CMS Single Sign-on Check)"; - $header[] = "Connection: Close"; - - if ( $sso['cookie'] ) - { - $cookie = 'Cookie: '; - if ( is_array($authid)) - foreach( $authid as $cookiename=>$cookievalue) - $cookie .= $cookiename.'='.$cookievalue."; "; - else - $cookie .= $sso['cookie_name'].'='.$authid; - - $header[] = $cookie; - } - -// Html::debug($header); - fputs ($fp, implode("\r\n",$header)."\r\n\r\n"); - - $inhalt=array(); - while (!feof($fp)) { - $inhalt[] = fgets($fp,128); - } - fclose($fp); - - $html = implode('',$inhalt); -// Html::debug($html); - if ( !preg_match($sso['expect_regexp'],$html) ) - throw new \SecurityException('auth failed'); - $treffer=0; - if ( !preg_match($sso['username_regexp'],$html,$treffer) ) - throw new \SecurityException('auth failed'); - if ( !isset($treffer[1]) ) - throw new \SecurityException('authorization failed'); - - $username = $treffer[1]; - -// Html::debug( $treffer ); - $this->setDefaultDb(); - - $user = User::loadWithName( $username ); - - if ( ! $user->isValid( )) - throw new \SecurityException('authorization failed: user not found: '.$username); - - $user->setCurrent(); - - $this->callSubAction('show'); - } - } - - elseif ( $ssl_trust ) - { - if ( empty($ssl_user_var) ) - throw new \LogicException( 'please set environment variable name in ssl-configuration.' ); - - $username = getenv( $ssl_user_var ); - - if ( empty($username) ) - throw new \SecurityException( 'no username in client certificate ('.$ssl_user_var.') (or there is no client certificate...?)' ); - - $this->setDefaultDb(); - - $user = User::loadWithName( $username ); - - if ( !$user->isValid() ) - throw new \LogicException( 'unknown username: '.$username ); - - $user->setCurrent(); - - $this->callSubAction('show'); - } - - $dbids = array(); - - $databases = Conf()->get('database'); - - if ( !is_array($databases)) - throw new \LogicException("Corrupt configuration: Databases configuration must be an array."); - - - foreach( $databases as $dbid => $dbconf ) - { - if ( !is_array($dbconf)) - throw new \LogicException("Corrup configuration: Database configuration '".$dbid."' must be an array.'"); - - $dbconf += $conf['database-default']['defaults']; // Add Default-Values - - if ( is_array($dbconf) && $dbconf['enabled'] ) // Database-Connection is enabled - $dbids[$dbid] = array( - 'key' => $dbid, - 'value' => empty($dbconf['name']) ? $dbid : Text::maxLength($dbconf['name']), - 'title' => $dbconf['description'] - ); - } - - - if ( empty($dbids) ) - $this->addNotice('','','no_database_configuration',OR_NOTICE_WARN); - - if ( !isset($this->templateVars['login_name']) && isset($_COOKIE['or_username']) ) - $this->setTemplateVar('login_name',$_COOKIE['or_username']); - - if ( !isset($this->templateVars['login_name']) ) - $this->setTemplateVar('login_name',@$conf['security']['default']['username']); - - if ( @$this->templateVars['login_name']== @$conf['security']['default']['username']) - $this->setTemplateVar('login_password',@$conf['security']['default']['password']); - - $this->setTemplateVar( 'dbids',$dbids ); - - // Vorausgewählte Datenbank-Id ermiteln - $db = Session::getDatabase(); - if ( is_object($db) ) - // Datenbankverbindung ist noch in Sitzung, diese verwenden. - $this->setTemplateVar('dbid',$db->id); - elseif ( isset($_COOKIE['or_dbid']) && isset($dbids[$_COOKIE['or_dbid']]) ) - // DB-Id aus dem Cookie lesen. - $this->setTemplateVar('dbid',$_COOKIE['or_dbid'] ); - elseif ( ! empty($conf['database-default']['default-id']) && isset($dbids[$conf['database-default']['default-id']])) - // Default-Datenbankverbindung ist konfiguriert und vorhanden. - $this->setTemplateVar('dbid',$conf['database-default']['default-id']); - elseif ( count($dbids) > 0) - // Datenbankverbindungen sind vorhanden, wir nehmen die erste. - $this->setTemplateVar('dbid',array_keys($dbids)[0]); - else - // Keine Datenbankverbindung vorhanden. Fallback: - $this->setTemplateVar('dbid',''); - - - // Den Benutzernamen aus dem Client-Zertifikat lesen und in die Loginmaske eintragen. - $ssl_user_var = $conf['security']['ssl']['client_cert_dn_env']; - if ( !empty($ssl_user_var) ) - { - $username = getenv( $ssl_user_var ); - - if ( empty($username) ) - { - // Nothing to do. - // if user has no valid client cert he could not access this form. - } - else { - - // Benutzername ist in Eingabemaske unver�nderlich - $this->setTemplateVar('force_username',true); - $this->setTemplateVar('login_name' ,$username); - } - - } - - $this->setTemplateVar('objectid' ,$this->getRequestVar('objectid' ,OR_FILTER_NUMBER) ); - $this->setTemplateVar('projectid' ,$this->getRequestVar('projectid' ,OR_FILTER_NUMBER) ); - $this->setTemplateVar('modelid' ,$this->getRequestVar('modelid' ,OR_FILTER_NUMBER) ); - $this->setTemplateVar('languageid',$this->getRequestVar('languageid',OR_FILTER_NUMBER) ); - - $this->setTemplateVar('register' ,$conf['login' ]['register' ]); - $this->setTemplateVar('send_password',$conf['login' ]['send_password']); - - // Versuchen, einen Benutzernamen zu ermitteln, der im Eingabeformular vorausgewählt wird. - $modules = explode(',',$conf['security']['modules']['preselect']); - - $username = ''; - foreach( $modules as $module) - { - Logger::debug('Preselecting module: '.$module); - $moduleClass = $module.'Auth'; - /** @var \Auth $auth */ - $auth = new $moduleClass; - $username = $auth->username(); - - if ( !empty($username) ) - { - Logger::debug('Preselecting User '.$username); - break; // Benutzername gefunden. - } - } - - $this->setTemplateVar('login_name',$username); - } - - - - /** - * Anzeigen der Loginmaske. - * - * Es wird nur die Loginmaske angezeigt. - * Hier nie "304 not modified" setzen, da sonst keine - * Login-Fehlermeldung erscheinen kann - */ - function openidView() - { - global $conf; - - foreach( $conf['database'] as $dbname=>$dbconf ) - { - if ( is_array($dbconf) && $dbconf['enabled'] ) - $dbids[$dbname] = array('key' =>$dbname, - 'value'=>Text::maxLength($dbconf['description']), - 'title'=>$dbconf['description'].(isset($dbconf['host'])?' ('.$dbconf['host'].')':'') ); - } - - $openid_provider = array(); - foreach( explode(',',$conf['security']['openid']['provider']['name']) as $provider ) - $openid_provider[$provider] = config('security','openid','provider.'.$provider.'.name'); - $this->setTemplateVar('openid_providers',$openid_provider); - $this->setTemplateVar('openid_user_identity',config('security','openid','user_identity')); - //$this->setTemplateVar('openid_provider','identity'); - - - if ( empty($dbids) ) - $this->addNotice('','','no_database_configuration',OR_NOTICE_WARN); - - if ( !isset($_COOKIE['or_username']) ) - $this->setTemplateVar('login_name',$_COOKIE['or_username']); - else - $this->setTemplateVar('login_name',$conf['security']['default']['username']); - - $this->setTemplateVar( 'dbids',$dbids ); - - $db = Session::getDatabase(); - if ( is_object($db) ) - $this->setTemplateVar('actdbid',$db->id); - else - $this->setTemplateVar('actdbid',$conf['database']['default']); - - $this->setTemplateVar('objectid' ,$this->getRequestVar('objectid' ,OR_FILTER_NUMBER) ); - $this->setTemplateVar('projectid' ,$this->getRequestVar('projectid' ,OR_FILTER_NUMBER) ); - $this->setTemplateVar('modelid' ,$this->getRequestVar('modelid' ,OR_FILTER_NUMBER) ); - $this->setTemplateVar('languageid',$this->getRequestVar('languageid',OR_FILTER_NUMBER) ); - - } - - - - /** - * Erzeugt ein Projekt-Auswahlmenue. - */ - function projectmenu() - { - $user = Session::getUser(); - - if ( $user->mustChangePassword ) - { - $this->addNotice( 'user',$user->name,'PASSWORD_TIMEOUT','warn' ); - $this->callSubAction( 'changepassword' ); // Zwang, das Kennwort zu ?ndern. - } - - - // Diese Seite gilt pro Sitzung. - $this->lastModified( $user->loginDate ); - - // Projekte ermitteln - $projects = $user->projects; - - $list = array(); - - foreach( $projects as $id=>$name ) - { - $p = array(); - $p['url' ] = Html::url('index','project',$id); - $p['name'] = $name; - $p['id' ] = $id; - - $tmpProject = new Project( $id ); - $p['defaultmodelid' ] = $tmpProject->getDefaultModelId(); - $p['defaultlanguageid'] = $tmpProject->getDefaultLanguageId(); - $p['models' ] = $tmpProject->getModels(); - $p['languages' ] = $tmpProject->getLanguages(); - - $list[] = $p; - } - - $this->setTemplateVar('projects',$list); - - if ( empty($list) ) - { - // Kein Projekt vorhanden. Eine Hinweismeldung ausgeben. - if ( $this->userIsAdmin() ) - // Administratoren bekommen bescheid, dass sie ein Projekt anlegen sollen - $this->addNotice('','','ADMIN_NO_PROJECTS_AVAILABLE',OR_NOTICE_WARN); - else - // Normale Benutzer erhalten eine Meldung, dass kein Projekt zur Verf?gung steht - $this->addNotice('','','NO_PROJECTS_AVAILABLE',OR_NOTICE_WARN); - } - - } - - - - /** - * Erzeugt eine Anwendungsliste. - */ - function applications() - { - global $conf; - - // Diese Seite gilt pro Sitzung. - $user = Session::getUser(); - $userGroups = $user->getGroups(); - $this->lastModified( $user->loginDate ); - - // Applikationen ermitteln - $list = array(); - foreach( $conf['applications'] as $id=>$app ) - { - if ( !is_array($app) ) - continue; - - if ( isset($app['group']) ) - if ( !in_array($app['group'],$userGroups) ) - continue; // Keine Berechtigung, da Benutzer nicht in Gruppe vorhanden. - - $p = array(); - $p['url'] = $app['url']; - $p['description'] = @$app['description']; - if ( isset($app['param']) ) - { - $p['url'] .= strpos($p['url'],'?')!==false?'&':'?'; - $p['url'] .= $app['param'].'='.session_id(); - } - $p['name'] = $app['name']; - - $list[] = $p; - } - - - $this->setTemplateVar('applications',$list); - } - - - - - /** - * Open-Id Login, ?berpr?fen der Anmeldung.<br> - * Spezifikation: http://openid.net/specs/openid-authentication-1_1.html<br> - * Kapitel "4.4. check_authentication"<br> - * <br> - * Im 2. Schritt (Mode "id_res") erfolgte ein Redirect vom Open-Id Provider an OpenRat zur?ck.<br> - * Wir befinden uns nun im darauf folgenden Request des Browsers.<br> - * <br> - * Es muss noch beim OpenId-Provider die Best?tigung eingeholt werden, danach ist der - * Benutzer angemeldet.<br> - */ - public function openidloginView() - { - global $conf; - $openId = Session::get('openid'); - - if ( !$openId->checkAuthentication() ) - { - throw new \SecurityException('OpenId-Login failed' ); - } - - //Html::debug($openId); - - // Anmeldung wurde mit "is_valid:true" best?tigt. - // Der Benutzer ist jetzt eingeloggt. - $username = $openId->getUserFromIdentiy(); - - Logger::debug("OpenId-Login successful for $username"); - - if ( empty($username) ) - { - // Es konnte kein Benutzername ermittelt werden. - throw new \SecurityException('no username supplied by openid provider' ); - } - - $user = User::loadWithName( $username ); - - if ( $user->userid <=0) - { - // Benutzer ist (noch) nicht vorhanden. - if ( $conf['security']['openid']['add']) // Anlegen? - { - $user->name = $username; - $user->add(); - - $user->mail = @$openId->info['email']; - $user->fullname = @$openId->info['fullname']; - $user->save(); // Um E-Mail zu speichern (wird bei add() nicht gemacht) - } - else - { - Logger::debug("OpenId-Login failed for $username"); - // Benutzer ist nicht in Benutzertabelle vorhanden (und angelegt werden soll er auch nicht). - throw new \SecurityException('user',$username,'LOGIN_OPENID_FAILED','error',array('name'=>$username) ); - } - } - else - { - // Benutzer ist bereits vorhanden. - if ( @$conf['security']['openid']['update_user']) - { - $user->fullname = @$openId->info['fullname']; - $user->mail = @$openId->info['email']; - $user->save(); - } - } - - Logger::info("User login successful: ".$username); - $user->setCurrent(); // Benutzer ist jetzt in der Sitzung. - - $this->setStyle( $user->style ); - - $server = Http::getServer(); - Logger::debug("Redirecting to $server"); - header('Location: '.slashify($server) ); - exit(); - } - - - /** - * Login. - */ - function openidPost() - { - global $conf; - - $this->checkForDb(); - Session::setUser(''); - - if ( $conf['login']['nologin'] ) - throw new \SecurityException('login disabled'); - - $openid_user = $this->getRequestVar('openid_url' ); - $loginName = $this->getRequestVar('login_name' ,OR_FILTER_ALPHANUM); - $loginPassword = $this->getRequestVar('login_password',OR_FILTER_ALPHANUM); - $newPassword1 = $this->getRequestVar('password1' ,OR_FILTER_ALPHANUM); - $newPassword2 = $this->getRequestVar('password2' ,OR_FILTER_ALPHANUM); - - // Cookie setzen - $this->setCookie('or_username',$loginName ); - - // Login mit Open-Id. - if ( $this->hasRequestVar('openid_provider') && ($this->getRequestVar('openid_provider') != 'identity' || !empty($openid_user)) ) - { - $openId = new OpenId($this->getRequestVar('openid_provider'),$openid_user); - - if ( ! $openId->login() ) - { - $this->addNotice('user',$openid_user,'LOGIN_OPENID_FAILED','error',array('name'=>$openid_user),array($openId->error) ); - $this->addValidationError('openid_url',''); - $this->callSubAction('showlogin'); - return; - } - - Session::set('openid',$openId); - $this->redirect( $openId->getRedirectUrl() ); - return; - } - } - - - /** - * Synchronisiert die bisherigen Gruppen des Benutzers mit den Gruppen, die sich aus der Authentifzierung ergeben haben. - * - * @param $user User Benutzerobjekt - * @param $groups array $groups Einfaches Array von Gruppennamen. - */ - private function checkGroups($user, $groups) - { - if ( $groups == null ) - return; - - $oldGroups = $user->getGroups(); - - foreach( $oldGroups as $id=>$name) - { - if ( !in_array($name,$groups) ) - $user->delGroup($id); - } - - foreach( $groups as $name) - { - if ( ! in_array($name,$oldGroups)) - { - try - { - $group = Group::loadWithName( $name ); - $user->addGroup($group->groupid); - } - catch (ObjectNotFoundException $e) - { - // Gruppe fehlt. Anlegen? - if ( config('ldap','authorize','auto_add' ) ) - { - // Die Gruppe in der OpenRat-Datenbank hinzufuegen. - $g = new Group(); - $g->name = $group; - $g->add(); // Gruppe hinzufuegen - $user->addGroup($g->groupid); // Und Gruppe dem Benutzer hinzufuegen. - } - - } - } - } - } - - - /** - * Login. - * Zuerst wird die Datenbankverbindung aufgebaut und falls notwendig, aktualisiert. - */ - function loginPost() - { - global $conf; - - Logger::info("DBID: ".$this->getRequestVar('dbid')); - if ( $this->hasRequestVar('dbid')) - { - $dbid = $this->getRequestVar('dbid'); - - if ( !is_array($conf['database'][$dbid]) ) - $this->addValidationError('dbid'); - - $this->updateDatabase($dbid); // Updating... - } - - $this->checkForDb(); - - Session::setUser(''); // Altes Login entfernen. - - if ( $conf['login']['nologin'] ) - throw new \SecurityException('login disabled'); - - $loginName = $this->getRequestVar('login_name' ,OR_FILTER_ALPHANUM); - $loginPassword = $this->getRequestVar('login_password',OR_FILTER_ALPHANUM); - $newPassword1 = $this->getRequestVar('password1' ,OR_FILTER_ALPHANUM); - $newPassword2 = $this->getRequestVar('password2' ,OR_FILTER_ALPHANUM); - $token = $this->getRequestVar('user_token' ,OR_FILTER_ALPHANUM); - - // Der Benutzer hat zwar ein richtiges Kennwort eingegeben, aber dieses ist abgelaufen. - // Wir versuchen hier, das neue zu setzen (sofern eingegeben). - if ( empty($newPassword1) ) - { - // Kein neues Kennwort, - // nichts zu tun... - } - else - { - $auth = new InternalAuth(); - - if ( $auth->login($loginName, $loginPassword,$token) || $auth->mustChangePassword ) - { - if ( $newPassword1 != $newPassword2 ) - { - $this->addValidationError('password1','PASSWORDS_DO_NOT_MATCH'); - $this->addValidationError('password2',''); - return; - } - elseif ( strlen($newPassword1) < $conf['security']['password']['min_length'] ) - { - $this->addValidationError('password1','PASSWORD_MINLENGTH',array('minlength'=>$conf['security']['password']['min_length'])); - $this->addValidationError('password2',''); - return; - } - else - { - // Kennwoerter identisch und lang genug. - $user = User::loadWithName($loginName); - $user->setPassword( $newPassword1,true ); - - // Das neue gesetzte Kennwort für die weitere Authentifizierung benutzen. - $loginPassword = $newPassword1; - } - } - else - { - // Anmeldung gescheitert. - $this->addNotice('user',$loginName,'LOGIN_FAILED','error',array('name'=>$loginName) ); - $this->addValidationError('login_name' ,''); - $this->addValidationError('login_password',''); - return; - } - } - - // Cookie setzen - $this->setCookie('or_username',$loginName ); - $this->setCookie('or_dbid' ,$this->getRequestVar('dbid')); - - // Authentifzierungs-Module. - $modules = explode(',',$conf['security']['modules']['authenticate']); - - $loginOk = false; - $mustChangePassword = false; - $tokenFailed = false; - $groups = null; - $lastModule = null; - - // Jedes Authentifizierungsmodul durchlaufen, bis ein Login erfolgreich ist. - foreach( $modules as $module) - { - $moduleClass = $module.'Auth'; - $auth = new $moduleClass; - Logger::info('Trying to login with module '.$moduleClass); - $loginStatus = $auth->login( $loginName,$loginPassword, $token ); - $loginOk = $loginStatus === true || $loginStatus === OR_AUTH_STATUS_SUCCESS; - - if ( $loginStatus === OR_AUTH_STATUS_PW_EXPIRED ) - $mustChangePassword = true; - if ( $loginStatus === OR_AUTH_STATUS_TOKEN_NEEDED ) - $tokenFailed = true; - - if ( $loginOk ) - { - Logger::info('Login successful for '.$loginName); - $lastModule = $module; - - if ( isset($auth->groups ) ) - $groups = $auth->groups; - - break; // Login erfolgreich, erstes Modul gewinnt. - } - } - - /* - $loginOk = $this->checkLogin( $loginName, - $loginPassword, - $newPassword1, - $newPassword2 ); - */ - - - if ( $loginOk ) - { - - try - { - // Benutzer über den Benutzernamen laden. - $user = User::loadWithName($loginName); - $user->loginModuleName = $lastModule; -// Session::setUser($user); - $user->setCurrent(); - - if ($user->passwordAlgo != Password::bestAlgoAvailable() ) - // Re-Hash the password with a better hash algo. - $user->setPassword($loginPassword); - - } - catch( ObjectNotFoundException $ex ) - { - // Benutzer wurde zwar authentifiziert, ist aber in der - // internen Datenbank nicht vorhanden - if ( $conf['security']['newuser']['autoadd'] ) - { - // Neue Benutzer in die interne Datenbank uebernehmen. - $user = new User(); - $user->name = $loginName; - $user->fullname = $loginName; - $user->add(); - $user->save(); - } - else - { - // Benutzer soll nicht angelegt werden. - // Daher ist die Anmeldung hier gescheitert. - $loginOk = false; - } - } - } - - Password::delay(); - - $ip = getenv("REMOTE_ADDR"); - - if ( !$loginOk ) - { - // Anmeldung nicht erfolgreich - - Logger::debug("Login failed for user '$loginName' from IP $ip"); - - if ( $tokenFailed ) - { - // Token falsch. - $this->addNotice('user',$loginName,'LOGIN_FAILED_TOKEN_FAILED','error' ); - $this->addValidationError('user_token',''); - } - elseif ( $mustChangePassword ) - { - // Anmeldung gescheitert, Benutzer muss Kennwort ?ndern. - $this->addNotice('user',$loginName,'LOGIN_FAILED_MUSTCHANGEPASSWORD','error' ); - $this->addValidationError('password1',''); - $this->addValidationError('password2',''); - } - else - { - // Anmeldung gescheitert. - $this->addNotice('user',$loginName,'LOGIN_FAILED','error',array('name'=>$loginName) ); - $this->addValidationError('login_name' ,''); - $this->addValidationError('login_password',''); - } - - - //$this->callSubAction('login'); - return; - } - else - { - - Logger::debug("Login successful for user '$loginName' from IP $ip"); - - $this->checkGroups( $user, $groups ); - - if ( $this->hasRequestVar('remember') ) - { - // Cookie setzen - $this->setCookie('or_username',$user->name ); - $this->setCookie('or_token' ,$user->loginToken() ); - } - - // Anmeldung erfolgreich. - if ( config('security','renew_session_login') ) - $this->recreateSession(); - - $this->addNotice('user',$user->name,'LOGIN_OK',OR_NOTICE_OK,array('name'=>$user->fullname)); - - $this->setStyle( $user->style ); // Benutzer-Style setzen - - $config = Session::getConfig(); - $language = new \language\Language(); - $config['language'] = $language->getLanguage($user->language); - $config['language']['language_code'] = $user->language; - Session::setConfig( $config ); - - - - // Entscheiden, welche Perspektive als erstes angezeigt werden soll. - - $allProjects = Project::getAllProjects(); - } - - } - - - /** - * Benutzer meldet sich ab. - */ - function logoutPost() - { - global $conf; - - $user = Session::getUser(); - if ( is_object($user) ) - $this->setTemplateVar('login_username',$user->name); - - if ( config('security','renew_session_logout') ) - $this->recreateSession(); - - session_unset(); - - if ( @$conf['theme']['compiler']['compile_at_logout'] ) - { - foreach( $conf['action'] as $actionName => $actionConfig ) - { - foreach( $actionConfig as $subActionName=>$subaction ) - { - if ( is_array($subaction) && - !isset($subaction['goto' ]) && - !isset($subaction['direct']) && - !isset($subaction['action']) && - !isset($subaction['async' ]) && - !isset($subaction['alias' ]) && - $subActionName != 'menu' ) - { - $engine = new template_engine\TemplateEngine(); - $engine->compile( strtolower(str_replace('Action','',$actionName)).'/'.$subActionName); - } - } - } - } - - // Login-Token löschen: - // Wenn der Benutzer sich abmelden will, dann soll auch die automatische - // Anmeldung deaktiviert werden. - $this->setCookie('or_token' ,null ); - - // Umleiten auf eine definierte URL.s - $redirect_url = @$conf['security']['logout']['redirect_url']; - - if ( !empty($redirect_url) ) - { - $this->redirect($redirect_url); - } - - // Style zurücksetzen. - // Der Style des Benutzers koennte auch stehen bleiben. Aber dann gäbe es Rückschlüsse darauf, wer zuletzt angemeldet war (Sicherheit!). - $this->setStyle( config('interface','style','default') ); - } - - - - /** - * Benutzer meldet sich ab. - */ - function logoutView() - { - } - - - /** - * Ausgeben von maschinenlesbaren Benutzerinformationen. - * - * Diese Funktion dient dem Single-Signon f?r fremde Anwendungen, welche - * die Benutzerinformationen des angemeldeten Benutzers aus dieser - * Anwendung auslesen k?nnen. - */ - function userinfo() - { - $user = Session::getUser(); - $info = array('username' => $user->name, - 'fullname' => $user->fullname, - 'mail' => $user->mail, - 'telephone' => $user->tel, - 'style' => $user->style, - 'admin' => $user->isAdmin?'true':'false', - 'ldap' => $user->ldap_dn, - 'groups' => implode(',',$user->getGroups()), - 'description'=> $user->desc - ); - - // Wenn der HTTP-Parameter "xml" vorhanden ist, dann geben wir die - // Informationen per XML aus. - if ( $this->hasRequestVar('xml') ) - { - header('Content-Type: text/xml'); - echo '<userinfo>'; - foreach( $info as $n=>$i ) - echo '<'.$n.'>'.$i.'</'.$n.'>'."\n"; - echo '</userinfo>'; - - } - - // Sonst normale Textausgabe im INI-Datei-Format. - else - { - header('Content-Type: text/plain'); - foreach( $info as $n=>$i ) - echo $n.'="'.$i."\"\n"; - } - - exit; // Fertig. - } - - - function project() - { - $user = Session::getUser(); - if ( ! is_object($user) ) - { - $this->callSubAction('show'); - return; - } - - $this->evaluateRequestVars( array('projectid'=>$this->getRequestId()) ); - - Session::setUser( $user ); - } - - - function object() - { - $user = Session::getUser(); - if ( ! is_object($user) ) - { - $this->callSubAction('show'); - return; - } - - $this->evaluateRequestVars( array('objectid'=>$this->getRequestId()) ); - - Session::setUser( $user ); - } - - - function language() - { - $user = Session::getUser(); - if ( ! is_object($user) ) - { - $this->callSubAction('show'); - return; - } - - $this->evaluateRequestVars( array(REQ_PARAM_LANGUAGE_ID=>$this->getRequestId()) ); - } - - - function model() - { - $user = Session::getUser(); - if ( ! is_object($user) ) - { - $this->callSubAction('show'); - return; - } - - $this->evaluateRequestVars( array(REQ_PARAM_MODEL_ID=>$this->getRequestId()) ); - - $user = Session::getUser(); - } - - - /** - * Auswerten der Request-Variablen. - * - * @param Array $add - */ - function evaluateRequestVars( $add = array() ) - { - } - - - function showtree() - { - Session::set('showtree',true ); - } - - - function hidetree() - { - Session::set('showtree',false ); - } - - - function switchuser() - { - $user = Session::getUser(); - - if ( ! $user->isAdmin ) - throw new \SecurityException("Switching the user is only possible for admins."); - - $this->recreateSession(); - - $newUser = new User( $this->getRequestId() ); - $newUser->load(); - - $newUser->setCurrent(); - } - - - function show() - { - global $conf; - global $PHP_AUTH_USER; - global $PHP_AUTH_PW; - - $user = Session::getUser(); - // Gast-Login - if ( ! is_object($user) ) - { - if ( $conf['security']['guest']['enable'] ) - { - $this->setDefaultDb(); - $username = $conf['security']['guest']['user']; - $user = User::loadWithName($username); - if ( $user->userid > 0 ) - $user->setCurrent(); - else - { - Logger::warn('Guest login failed, user not found: '.$username); - $this->addNotice('user',$username,'LOGIN_FAILED',OR_NOTICE_WARN,array('name'=>$username) ); - $user = null; - } - } - } - - if ( ! is_object($user) ) - { - switch( $conf['security']['login']['type'] ) - { - - // Authorization ueber HTTP - // - case 'http': - $ok = false; - - if ( isset($_SERVER['PHP_AUTH_USER']) ) - { - $this->setDefaultDb(); - $ok = $this->checkLogin( $_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'] ); - } - - if ( ! $ok ) - { - header( 'WWW-Authenticate: Basic realm="'.OR_TITLE.' - '.lang('HTTP_REALM').'"' ); - header( 'HTTP/1.0 401 Unauthorized' ); - echo 'Authorization Required!'; - exit; - } - break; - - case 'form': - // Benutzer ist nicht angemeldet - $this->callSubAction( 'showlogin' ); // Anzeigen der Login-Maske - return; - break; - - default: - throw new \LogicException('Unknown auth-type: '.$conf['security']['login']['type'].'. Please check the configuration setting /security/login/type' ); - } - } - - if ( $user->mustChangePassword ) - { - $this->addNotice( 'user',$user->name,'PASSWORD_TIMEOUT','warn' ); - $this->callSubAction( 'changepassword' ); // Zwang, das Kennwort zu ?ndern. - } - - // Seite ?ndert sich nur 1x pro Session - $this->lastModified( $user->loginDate ); - - } - - - - function checkMenu( $name ) - { - global $conf; - - switch( $name ) - { - case 'applications': - // Men?punkt "Anwendungen" wird nur angezeigt, wenn weitere Anwendungen - // konfiguriert sind. - return count(@$conf['applications']) > 0; - - case 'register': // Registrierung - // Nur, wenn aktiviert und gegen eigene Datenbank authentisiert wird. - return @$conf['login']['register'] && @$conf['security']['auth']['type'] == 'database'; - - case 'password': // Kennwort vergessen - // Nur, wenn aktiviert und gegen eigene Datenbank authentisiert wird. - // Deaktiviert, falls LDAP-Lookup aktiviert ist. - return @$conf['login']['send_password'] && @$conf['security']['auth']['type'] == 'database' - && !@$conf['security']['auth']['userdn']; - - case 'administration': - // "Administration" nat?rlich nur f?r Administratoren. - return $this->userIsAdmin(); - - case 'login': - return !@$conf['login']['nologin']; - - case 'logout': - return true; - - case 'projectmenu': - return true; - - default: - return false; - } - } - - - /** - * Maske anzeigen, um Benutzer zu registrieren. - */ - public function registerView() - { - - } - - - /** - * Registriercode erzeugen und per E-Mail dem Benutzer mitteilen. - * Maske anzeigen, damit Benuter Registriercode anzeigen kann. - */ - public function registercodeView() - { - global $conf; - foreach( $conf['database'] as $dbname=>$dbconf ) - { - if ( is_array($dbconf) && $dbconf['enabled'] ) - $dbids[$dbname] = $dbconf['description']; - } - - $this->setTemplateVar( 'dbids',$dbids ); - - $db = Session::getDatabase(); - if ( is_object($db) ) - $this->setTemplateVar('actdbid',$db->id); - else - $this->setTemplateVar('actdbid',$conf['database']['default']); - - - - } - - - - public function registerPost() - { - global $conf; - - Session::set('registerMail',$this->getRequestVar('mail') ); - - srand ((double)microtime()*1000003); - $registerCode = rand(); - - Session::set('registerCode',$registerCode ); - - $email_address = $this->getRequestVar('mail',OR_FILTER_MAIL); - - if ( ! Mail::checkAddress($email_address) ) - { - $this->addValidationError('mail'); - return; - } - - // E-Mail and die eingegebene Adresse verschicken - $mail = new Mail($email_address, - 'register_commit_code','register_commit_code'); - $mail->setVar('code',$registerCode); // Registrierungscode als Text-Variable - - if ( $mail->send() ) - { - $this->addNotice('','','mail_sent',OR_NOTICE_OK); - } - else - { - $this->addNotice('','','mail_not_sent',OR_NOTICE_ERROR,array(),$mail->error); - return; - } - } - - - /** - * Benutzerregistierung. - * Benutzer hat Best?tigungscode erhalten und eingegeben. - */ - function registercodePost() - { - global $conf; - $this->checkForDb(); - - $origRegisterCode = Session::get('registerCode'); - $inputRegisterCode = $this->getRequestVar('code'); - - if ( $origRegisterCode != $inputRegisterCode ) - { - // Best?tigungscode stimmt nicht. - $this->addValidationError('code','code_not_match'); - return; - } - - // Best?tigungscode stimmt ?berein. - // Neuen Benutzer anlegen. - - if ( !$this->hasRequestVar('username') ) - { - $this->addValidationError('username'); - return; - } - - $user = User::loadWithName( $this->getRequestVar('username') ); - if ( $user->isValid() ) - { - $this->addValidationError('username','USER_ALREADY_IN_DATABASE'); - return; - } - - if ( strlen($this->getRequestVar('password')) < $conf['security']['password']['min_length'] ) - { - $this->addValidationError('password','password_minlength',array('minlength'=>$conf['security']['password']['min_length'])); - return; - } - - $newUser = new User(); - $newUser->name = $this->getRequestVar('username'); - $newUser->add(); - - $newUser->mail = Session::get('registerMail'); - $newUser->save(); - - $newUser->setPassword( $this->getRequestVar('password'),true ); - - $this->addNotice('user',$newUser->name,'user_added','ok'); - } - - - - /** - * Vergessenes Kennwort zusenden lassen. - */ - function passwordView() - { - // TODO: Attribut "Password" abfragen - foreach( config('database') as $dbname=>$dbconf ) - { - $dbconf = $dbconf + config('database-default','defaults'); - if ( $dbconf['enabled'] ) - $dbids[$dbname] = $dbconf['description']; - } - - $this->setTemplateVar( 'dbids',$dbids ); - - - $db = Session::getDatabase(); - - if ( is_object($db) ) - $this->setTemplateVar('actdbid',$db->id); - else - $this->setTemplateVar('actdbid',config('database-default','default-id')); - } - - - /* - function changepassword() - { - } - */ - - - /* - function setnewpassword() - { - $oldPw = $this->getRequestVar('password_old' ); - $newPw1 = $this->getRequestVar('password_new_1'); - $newPw2 = $this->getRequestVar('password_new_2'); - - if ( $newPw1 == $newPw2 ) - { - // Aktuellen Benutzer aus der Sitzung ermitteln - $user = $this->getUserFromSession(); - - // Altes Kennwort pr?fen. - $ok = $user->checkPassword( $oldPw ); - - if ( $ok ) // Altes Kennwort ist ok. - { - $user->setPassword( $newPw1 ); // Setze neues Kennwort - $user->mustChangePassword = false; - Session::setUser($user); - $this->addNotice('user',$user->name,'password_set','ok'); - } - else - { - // Altes Kennwort falsch. - $this->addNotice('user',$user->name,'password_error','error'); - } - } - else - { - // Beide neuen Kennw?rter stimmen nicht ?berein - $this->addNotice('user',$user->name,'passwords_not_match','error'); - } - } - */ - - - /** - * Einen Kennwort-Anforderungscode an den Benutzer senden. - */ - function passwordPost() - { - if ( !$this->hasRequestVar('username') ) - { - $this->addValidationError('username'); - return; - } - - $this->checkForDb(); - - $user = User::loadWithName( $this->getRequestVar("username") ); - // Html::debug($user); - Password::delay(); - if ( $user->isValid() ) - { - srand ((double)microtime()*1000003); - $code = rand(); - $this->setSessionVar("password_commit_code",$code); - - $eMail = new Mail( $user->mail,'password_commit_code' ); - $eMail->setVar('name',$user->getName()); - $eMail->setVar('code',$code); - if ( $eMail->send() ) - $this->addNotice('user',$user->getName(),'mail_sent',OR_NOTICE_OK); - else - $this->addNotice('user',$user->getName(),'mail_not_sent',OR_NOTICE_ERROR,array(),$eMail->error); - - } - else - { - //$this->addNotice('','user','username_not_found'); - // Trotzdem vort?uschen, eine E-Mail zu senden, damit die G?ltigkeit - // eines Benutzernamens nicht von au?en gepr?ft werden kann. - // - $this->addNotice('user',$this->getRequestVar("username"),'mail_sent'); - - } - - $this->setSessionVar("password_commit_name",$user->name); - } - - - - /** - * Anzeige Formular zum Eingeben des Kennwort-Codes. - * - */ - function passwordcodeView() - { - - } - - - /** - * Neues Kennwort erzeugen und dem Benutzer zusenden. - */ - function passwordcodePost() - { - $username = $this->getSessionVar("password_commit_name"); - - if ( $this->getRequestVar("code")=='' || - $this->getSessionVar("password_commit_code") != $this->getRequestVar("code") ) - { - $this->addValidationError('code','PASSWORDCODE_NOT_MATCH'); - return; - } - - $user = User::loadWithName( $username ); - - if ( !$user->isValid() ) - { - // Benutzer konnte nicht geladen werden. - $this->addNotice('user',$username,'error',OR_NOTICE_ERROR); - return; - } - - $newPw = User::createPassword(); // Neues Kennwort erzeugen. - - $eMail = new Mail( $user->mail,'password_new' ); - $eMail->setVar('name' ,$user->getName()); - $eMail->setVar('password',$newPw ); - - if ( $eMail->send() ) - { - $user->setPassword( $newPw, false ); // Kennwort muss beim n?. Login ge?ndert werden. - $this->addNotice('user',$username,'mail_sent',OR_NOTICE_OK); - } - else - { - // Sollte eigentlich nicht vorkommen, da der Benutzer ja auch schon den - // Code per E-Mail erhalten hat. - $this->addNotice('user',$username,'error',OR_NOTICE_ERROR,array(),$eMail->error); - } - } - - - /** - * Erzeugt eine neue Sitzung. - */ - function recreateSession() - { - - // PHP < 4.3.2 kennt die Funktion session_regenerate_id() nicht. - if ( version_compare(phpversion(),"4.3.2","<") ) - { - $randlen = 32; - $randval = "0123456789abcdefghijklmnopqrstuvwxyz"; - $newid = ""; - for ($i = 1; $i <= $randlen; $i++) - { - $newid .= substr($randval, rand(0,(strlen($randval) - 1)), 1); - } - session_id( $newid ); - } - elseif( version_compare(phpversion(),"4.3.2","==") ) - { - session_regenerate_id(); - - // Bug in PHP 4.3.2: Session-Cookie wird nicht neu gesetzt. - if ( ini_get("session.use_cookies") ) - $this->setCookie( session_name(),session_id() ); - } - elseif ( version_compare(phpversion(),"5.1.0",">") ) - { - session_regenerate_id(true); - } - else - { - // 5.1.0 > PHP >= 4.3.3 - } - } - - - function licenseView() - { - $software = array(); - - $software[] = array('name' =>'OpenRat Content Management System', - 'url' =>'http://www.openrat.de/', - 'license'=>'GPL v2'); - $software[] = array('name' =>'jQuery Core Javascript Framework', - 'url' =>'http://jquery.com/', - 'license'=>'MPL, GPL v2'); - $software[] = array('name' =>'jQuery UI Javascript Framework', - 'url' =>'http://jqueryui.com/', - 'license'=>'MPL, GPL v2'); - $software[] = array('name' =>'GeSHi - Generic Syntax Highlighter', - 'url' =>'http://qbnz.com/highlighter/', - 'license'=>'GPL v2'); - $software[] = array('name' =>'TAR file format', - 'url' =>'http://www.phpclasses.org/package/529', - 'license'=>'LGPL'); - $software[] = array('name' =>'JSON file format', - 'url' =>'http://pear.php.net/pepr/pepr-proposal-show.php?id=198', - 'license'=>'BSD'); - - $this->setTemplateVar('software',$software); - - - - $this->setTemplateVar('time' ,date('r') ); - $this->setTemplateVar('os' ,php_uname('s') ); - $this->setTemplateVar('release' ,php_uname('r') ); - $this->setTemplateVar('machine' ,php_uname('m') ); - $this->setTemplateVar('version' , phpversion() ); - - $this->setTemplateVar('cms_name' , Conf()->subset('application')->get('name' ) ); - $this->setTemplateVar('cms_version' , Conf()->subset('application')->get('version' ) ); - $this->setTemplateVar('cms_operator', Conf()->subset('application')->get('operator') ); - - $user = Session::getUser(); - if ( !empty($user) ) - { - $this->setTemplateVar('user_login' , $user->loginDate ); - $this->setTemplateVar('user_name' , $user->name ); - $this->setTemplateVar('user_fullname', $user->fullname ); - } - - } - - - function pingView() - { - echo "1"; - } - - /** - * Updating the database. - * - * @param $dbid integer - * @throws OpenRatException - */ - private function updateDatabase($dbid) - { - try { - $adminDbConfig = Conf()->subset('database')->subset($dbid); - - $adminDb = new Database( config('database',$dbid), true); - $adminDb->id = $dbid; - } catch (Exception $e) { - - throw new OpenRatException('DATABASE_ERROR_CONNECTION', $e->getMessage()); - } - - $updater = new DbUpdate(); - $updater->update($adminDb); - - // Try to close the PDO connection. PDO doc: - // To close the connection, you need to destroy the object by ensuring that all - // remaining references to it are deleted—you do this by assigning NULL to the variable that holds the object. - // If you don't do this explicitly, PHP will automatically close the connection when your script ends. - $adminDb = null; - unset($adminDb); - } - - - public function showView() { - $this->nextSubAction('login'); - } -} - - -?>- \ No newline at end of file +<?php + +namespace cms\action; + + +use cms\model\User; +use cms\model\Project; +use cms\model\Group; +use cms\model\Value; +use cms\model\Element; +use cms\model\Page; +use cms\model\BaseObject; +use cms\model\Language; +use cms\model\Model; + + +use \database\Database; +use \DB; +use \DbUpdate; +use \Exception; +use \Http; +use \InternalAuth; +use \Logger; +use \ObjectNotFoundException; +use \OpenRatException; +use \security\Password; +use \Session; +use \Html; +use \Mail; +use \Text; + + +// OpenRat Content Management System +// Copyright (C) 2002-2007 Jan Dankert, jandankert@jandankert.de +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +define('PROJECTID_ADMIN',-1); + +/** + * Action-Klasse fuer die Start-Action + * @author $Author$ + * @version $Revision$ + * @package openrat.actions + */ + +class LoginAction extends Action +{ + public $security = Action::SECURITY_GUEST; + + + public function __construct() + { + parent::__construct(); + } + + + + /** + * Führt ein Login durch. + * @param $name string Benutzername + * @param $pw string Password + * @param $pw1 string new Password + * @param $pw2 string new Password repeated + * @return bool + * @throws ObjectNotFoundException + */ + private function checkLogin($name, $pw, $pw1, $pw2 ) + { + Logger::debug( "Login user: '$name'.'" ); + + global $conf; + global $SESS; + + unset( $SESS['user'] ); + + + $db = db_connection(); + + if ( !is_object($db) ) + { + $this->addNotice('database','','DATABASE_CONNECTION_ERROR',OR_NOTICE_ERROR,array(),array('no connection')); + //$this->callSubAction('showlogin'); + return false; + } + + if ( !$db->available ) + { + $this->addNotice('database',$db->conf['description'],'DATABASE_CONNECTION_ERROR',OR_NOTICE_ERROR,array(),array('Database Error: '.$db->error)); + //$this->callSubAction('showlogin'); + return false; + } + + $ip = getenv("REMOTE_ADDR"); + + $user = new User(); + $user->name = $name; + + $ok = $user->checkPassword( $pw ); + + $mustChangePassword = $user->mustChangePassword; + + if ( $mustChangePassword ) + { + // Der Benutzer hat zwar ein richtiges Kennwort eingegeben, aber dieses ist abgelaufen. + // Wir versuchen hier, das neue zu setzen (sofern eingegeben). + if ( empty($pw1) ) + { + } + elseif ( $pw1 != $pw2 ) + { + $this->addValidationError('password1','PASSWORDS_DO_NOT_MATCH'); + $this->addValidationError('password2',''); + } + elseif ( strlen($pw2) < $conf['security']['password']['min_length'] ) + { + $this->addValidationError('password1','PASSWORD_MINLENGTH',array('minlength'=>$conf['security']['password']['min_length'])); + $this->addValidationError('password2',''); + } + else + { + // Kennw?rter identisch und lang genug. + $user->setPassword( $pw1,true ); + + // Das neue Kennwort ist gesetzt, die Anmeldung ist also doch noch gelungen. + $ok = true; + $mustChangePassword = false; + + $pw = $pw1; + } + } + + // Falls Login erfolgreich + if ( $ok ) + { + // Login war erfolgreich! + $user->load(); + $user->setCurrent(); + + if ($user->passwordAlgo != Password::bestAlgoAvailable() ) + // Re-Hash the password with a better hash algo. + $user->setPassword($pw); + + + Logger::info( "login successful for {$user->name} from IP $ip" ); + + return true; + } + else + { + Logger::info( "login failed for user {$user->name} from IP $ip" ); + + return false; + } + } + + + /** + * Anzeigen der Loginmaske. + * + * Es wird nur die Loginmaske angezeigt. + * @throws OpenRatException + */ + function loginView() + { + // Hier nie "304 not modified" setzen, da sonst keine + // Login-Fehlermeldung erscheinen kann. + global $conf; + + $sso = $conf['security']['sso']; + $ssl = $conf['security']['ssl']; + + $ssl_trust = false; + $ssl_user_var = ''; + extract( $ssl, EXTR_PREFIX_ALL, 'ssl' ); + + if ( $sso['enable'] ) + { + $authid = $this->getRequestVar( $sso['auth_param_name']); + + if ( empty( $authid) ) + throw new \SecurityException( 'no authorization data (no auth-id)'); + + if ( $sso['auth_param_serialized'] ) + $authid = unserialize( $authid ); + + $purl = parse_url($sso['url']); + // Verbindung zu URL herstellen. + $errno=0; $errstr=''; + $fp = fsockopen ($purl['host'],80, $errno, $errstr, 30); + if ( !$fp ) + { + echo "Connection failed: $errstr ($errno)"; + } + else + { + $http_get = $purl['path']; + if ( !empty($purl['query']) ) + $http_get .= '?'.$purl['query']; + + $header = array(); + + $header[] = "GET $http_get HTTP/1.0"; + $header[] ="Host: ".$purl['host']; + $header[] = "User-Agent: Mozilla/5.0 (OpenRat CMS Single Sign-on Check)"; + $header[] = "Connection: Close"; + + if ( $sso['cookie'] ) + { + $cookie = 'Cookie: '; + if ( is_array($authid)) + foreach( $authid as $cookiename=>$cookievalue) + $cookie .= $cookiename.'='.$cookievalue."; "; + else + $cookie .= $sso['cookie_name'].'='.$authid; + + $header[] = $cookie; + } + + fputs ($fp, implode("\r\n",$header)."\r\n\r\n"); + + $inhalt=array(); + while (!feof($fp)) { + $inhalt[] = fgets($fp,128); + } + fclose($fp); + + $html = implode('',$inhalt); + if ( !preg_match($sso['expect_regexp'],$html) ) + throw new \SecurityException('auth failed'); + $treffer=0; + if ( !preg_match($sso['username_regexp'],$html,$treffer) ) + throw new \SecurityException('auth failed'); + if ( !isset($treffer[1]) ) + throw new \SecurityException('authorization failed'); + + $username = $treffer[1]; + + $user = User::loadWithName( $username ); + + if ( ! $user->isValid( )) + throw new \SecurityException('authorization failed: user not found: '.$username); + + $user->setCurrent(); + + $this->callSubAction('show'); + } + } + + elseif ( $ssl_trust ) + { + if ( empty($ssl_user_var) ) + throw new \LogicException( 'please set environment variable name in ssl-configuration.' ); + + $username = getenv( $ssl_user_var ); + + if ( empty($username) ) + throw new \SecurityException( 'no username in client certificate ('.$ssl_user_var.') (or there is no client certificate...?)' ); + + $user = User::loadWithName( $username ); + + if ( !$user->isValid() ) + throw new \LogicException( 'unknown username: '.$username ); + + $user->setCurrent(); + + $this->callSubAction('show'); + } + + $dbids = array(); + + $databases = Conf()->get('database'); + + if ( !is_array($databases)) + throw new \LogicException("Corrupt configuration: Databases configuration must be an array."); + + + foreach( $databases as $dbid => $dbconf ) + { + if ( !is_array($dbconf)) + throw new \LogicException("Corrup configuration: Database configuration '".$dbid."' must be an array.'"); + + $dbconf += $conf['database-default']['defaults']; // Add Default-Values + + if ( is_array($dbconf) && $dbconf['enabled'] ) // Database-Connection is enabled + $dbids[$dbid] = array( + 'key' => $dbid, + 'value' => empty($dbconf['name']) ? $dbid : Text::maxLength($dbconf['name']), + 'title' => $dbconf['description'] + ); + } + + + if ( empty($dbids) ) + $this->addNotice('','','no_database_configuration',OR_NOTICE_WARN); + + if ( !isset($this->templateVars['login_name']) && isset($_COOKIE['or_username']) ) + $this->setTemplateVar('login_name',$_COOKIE['or_username']); + + if ( !isset($this->templateVars['login_name']) ) + $this->setTemplateVar('login_name',@$conf['security']['default']['username']); + + if ( @$this->templateVars['login_name']== @$conf['security']['default']['username']) + $this->setTemplateVar('login_password',@$conf['security']['default']['password']); + + $this->setTemplateVar( 'dbids',$dbids ); + + // Vorausgewählte Datenbank-Id ermiteln + $db = Session::getDatabase(); + if ( is_object($db) ) + // Datenbankverbindung ist noch in Sitzung, diese verwenden. + $this->setTemplateVar('dbid',$db->id); + elseif ( isset($_COOKIE['or_dbid']) && isset($dbids[$_COOKIE['or_dbid']]) ) + // DB-Id aus dem Cookie lesen. + $this->setTemplateVar('dbid',$_COOKIE['or_dbid'] ); + elseif ( ! empty($conf['database-default']['default-id']) && isset($dbids[$conf['database-default']['default-id']])) + // Default-Datenbankverbindung ist konfiguriert und vorhanden. + $this->setTemplateVar('dbid',$conf['database-default']['default-id']); + elseif ( count($dbids) > 0) + // Datenbankverbindungen sind vorhanden, wir nehmen die erste. + $this->setTemplateVar('dbid',array_keys($dbids)[0]); + else + // Keine Datenbankverbindung vorhanden. Fallback: + $this->setTemplateVar('dbid',''); + + + // Den Benutzernamen aus dem Client-Zertifikat lesen und in die Loginmaske eintragen. + $ssl_user_var = $conf['security']['ssl']['client_cert_dn_env']; + if ( !empty($ssl_user_var) ) + { + $username = getenv( $ssl_user_var ); + + if ( empty($username) ) + { + // Nothing to do. + // if user has no valid client cert he could not access this form. + } + else { + + // Benutzername ist in Eingabemaske unver�nderlich + $this->setTemplateVar('force_username',true); + $this->setTemplateVar('login_name' ,$username); + } + + } + + $this->setTemplateVar('objectid' ,$this->getRequestVar('objectid' ,OR_FILTER_NUMBER) ); + $this->setTemplateVar('projectid' ,$this->getRequestVar('projectid' ,OR_FILTER_NUMBER) ); + $this->setTemplateVar('modelid' ,$this->getRequestVar('modelid' ,OR_FILTER_NUMBER) ); + $this->setTemplateVar('languageid',$this->getRequestVar('languageid',OR_FILTER_NUMBER) ); + + $this->setTemplateVar('register' ,$conf['login' ]['register' ]); + $this->setTemplateVar('send_password',$conf['login' ]['send_password']); + + // Versuchen, einen Benutzernamen zu ermitteln, der im Eingabeformular vorausgewählt wird. + $modules = explode(',',$conf['security']['modules']['preselect']); + + $username = ''; + foreach( $modules as $module) + { + Logger::debug('Preselecting module: '.$module); + $moduleClass = $module.'Auth'; + /** @var \Auth $auth */ + $auth = new $moduleClass; + $username = $auth->username(); + + if ( !empty($username) ) + { + Logger::debug('Preselecting User '.$username); + break; // Benutzername gefunden. + } + } + + $this->setTemplateVar('login_name',$username); + } + + + + /** + * Anzeigen der Loginmaske. + * + * Es wird nur die Loginmaske angezeigt. + * Hier nie "304 not modified" setzen, da sonst keine + * Login-Fehlermeldung erscheinen kann + */ + function openidView() + { + global $conf; + + foreach( $conf['database'] as $dbname=>$dbconf ) + { + if ( is_array($dbconf) && $dbconf['enabled'] ) + $dbids[$dbname] = array('key' =>$dbname, + 'value'=>Text::maxLength($dbconf['description']), + 'title'=>$dbconf['description'].(isset($dbconf['host'])?' ('.$dbconf['host'].')':'') ); + } + + $openid_provider = array(); + foreach( explode(',',$conf['security']['openid']['provider']['name']) as $provider ) + $openid_provider[$provider] = config('security','openid','provider.'.$provider.'.name'); + $this->setTemplateVar('openid_providers',$openid_provider); + $this->setTemplateVar('openid_user_identity',config('security','openid','user_identity')); + //$this->setTemplateVar('openid_provider','identity'); + + + if ( empty($dbids) ) + $this->addNotice('','','no_database_configuration',OR_NOTICE_WARN); + + if ( !isset($_COOKIE['or_username']) ) + $this->setTemplateVar('login_name',$_COOKIE['or_username']); + else + $this->setTemplateVar('login_name',$conf['security']['default']['username']); + + $this->setTemplateVar( 'dbids',$dbids ); + + $db = db(); + if ( is_object($db) ) + $this->setTemplateVar('actdbid',$db->id); + else + $this->setTemplateVar('actdbid',$conf['database']['default']); + + $this->setTemplateVar('objectid' ,$this->getRequestVar('objectid' ,OR_FILTER_NUMBER) ); + $this->setTemplateVar('projectid' ,$this->getRequestVar('projectid' ,OR_FILTER_NUMBER) ); + $this->setTemplateVar('modelid' ,$this->getRequestVar('modelid' ,OR_FILTER_NUMBER) ); + $this->setTemplateVar('languageid',$this->getRequestVar('languageid',OR_FILTER_NUMBER) ); + + } + + + + /** + * Erzeugt eine Anwendungsliste. + * TODO: unused at the moment + */ + function applications() + { + global $conf; + + // Diese Seite gilt pro Sitzung. + $user = Session::getUser(); + $userGroups = $user->getGroups(); + $this->lastModified( $user->loginDate ); + + // Applikationen ermitteln + $list = array(); + foreach( $conf['applications'] as $id=>$app ) + { + if ( !is_array($app) ) + continue; + + if ( isset($app['group']) ) + if ( !in_array($app['group'],$userGroups) ) + continue; // Keine Berechtigung, da Benutzer nicht in Gruppe vorhanden. + + $p = array(); + $p['url'] = $app['url']; + $p['description'] = @$app['description']; + if ( isset($app['param']) ) + { + $p['url'] .= strpos($p['url'],'?')!==false?'&':'?'; + $p['url'] .= $app['param'].'='.session_id(); + } + $p['name'] = $app['name']; + + $list[] = $p; + } + + + $this->setTemplateVar('applications',$list); + } + + + + + /** + * Open-Id Login, ?berpr?fen der Anmeldung.<br> + * Spezifikation: http://openid.net/specs/openid-authentication-1_1.html<br> + * Kapitel "4.4. check_authentication"<br> + * <br> + * Im 2. Schritt (Mode "id_res") erfolgte ein Redirect vom Open-Id Provider an OpenRat zur?ck.<br> + * Wir befinden uns nun im darauf folgenden Request des Browsers.<br> + * <br> + * Es muss noch beim OpenId-Provider die Best?tigung eingeholt werden, danach ist der + * Benutzer angemeldet.<br> + */ + public function openidloginView() + { + global $conf; + $openId = Session::get('openid'); + + if ( !$openId->checkAuthentication() ) + { + throw new \SecurityException('OpenId-Login failed' ); + } + + //Html::debug($openId); + + // Anmeldung wurde mit "is_valid:true" best?tigt. + // Der Benutzer ist jetzt eingeloggt. + $username = $openId->getUserFromIdentiy(); + + Logger::debug("OpenId-Login successful for $username"); + + if ( empty($username) ) + { + // Es konnte kein Benutzername ermittelt werden. + throw new \SecurityException('no username supplied by openid provider' ); + } + + $user = User::loadWithName( $username ); + + if ( $user->userid <=0) + { + // Benutzer ist (noch) nicht vorhanden. + if ( $conf['security']['openid']['add']) // Anlegen? + { + $user->name = $username; + $user->add(); + + $user->mail = @$openId->info['email']; + $user->fullname = @$openId->info['fullname']; + $user->save(); // Um E-Mail zu speichern (wird bei add() nicht gemacht) + } + else + { + Logger::debug("OpenId-Login failed for $username"); + // Benutzer ist nicht in Benutzertabelle vorhanden (und angelegt werden soll er auch nicht). + throw new \SecurityException('user',$username,'LOGIN_OPENID_FAILED','error',array('name'=>$username) ); + } + } + else + { + // Benutzer ist bereits vorhanden. + if ( @$conf['security']['openid']['update_user']) + { + $user->fullname = @$openId->info['fullname']; + $user->mail = @$openId->info['email']; + $user->save(); + } + } + + Logger::info("User login successful: ".$username); + $user->setCurrent(); // Benutzer ist jetzt in der Sitzung. + + $this->setStyle( $user->style ); + + $server = Http::getServer(); + Logger::debug("Redirecting to $server"); + header('Location: '.slashify($server) ); + exit(); + } + + + /** + * Login. + */ + function openidPost() + { + global $conf; + + Session::setUser(''); + + if ( $conf['login']['nologin'] ) + throw new \SecurityException('login disabled'); + + $openid_user = $this->getRequestVar('openid_url' ); + $loginName = $this->getRequestVar('login_name' ,OR_FILTER_ALPHANUM); + $loginPassword = $this->getRequestVar('login_password',OR_FILTER_ALPHANUM); + $newPassword1 = $this->getRequestVar('password1' ,OR_FILTER_ALPHANUM); + $newPassword2 = $this->getRequestVar('password2' ,OR_FILTER_ALPHANUM); + + // Cookie setzen + $this->setCookie('or_username',$loginName ); + + // Login mit Open-Id. + if ( $this->hasRequestVar('openid_provider') && ($this->getRequestVar('openid_provider') != 'identity' || !empty($openid_user)) ) + { + $openId = new OpenId($this->getRequestVar('openid_provider'),$openid_user); + + if ( ! $openId->login() ) + { + $this->addNotice('user',$openid_user,'LOGIN_OPENID_FAILED','error',array('name'=>$openid_user),array($openId->error) ); + $this->addValidationError('openid_url',''); + $this->callSubAction('showlogin'); + return; + } + + Session::set('openid',$openId); + $this->redirect( $openId->getRedirectUrl() ); + return; + } + } + + + /** + * Synchronisiert die bisherigen Gruppen des Benutzers mit den Gruppen, die sich aus der Authentifzierung ergeben haben. + * + * @param $user User Benutzerobjekt + * @param $groups array $groups Einfaches Array von Gruppennamen. + */ + private function checkGroups($user, $groups) + { + if ( $groups == null ) + return; + + $oldGroups = $user->getGroups(); + + foreach( $oldGroups as $id=>$name) + { + if ( !in_array($name,$groups) ) + $user->delGroup($id); + } + + foreach( $groups as $name) + { + if ( ! in_array($name,$oldGroups)) + { + try + { + $group = Group::loadWithName( $name ); + $user->addGroup($group->groupid); + } + catch (ObjectNotFoundException $e) + { + // Gruppe fehlt. Anlegen? + if ( config('ldap','authorize','auto_add' ) ) + { + // Die Gruppe in der OpenRat-Datenbank hinzufuegen. + $g = new Group(); + $g->name = $group; + $g->add(); // Gruppe hinzufuegen + $user->addGroup($g->groupid); // Und Gruppe dem Benutzer hinzufuegen. + } + + } + } + } + } + + + /** + * Login. + * Zuerst wird die Datenbankverbindung aufgebaut und falls notwendig, aktualisiert. + */ + function loginPost() + { + global $conf; + + $db = db(); // throws Exception, if database is not available. + { + $dbid = $db->id; + + $this->updateDatabase($dbid); // Updating... + } + + Session::setUser(''); // Altes Login entfernen. + + if ( $conf['login']['nologin'] ) + throw new \SecurityException('login disabled'); + + $loginName = $this->getRequestVar('login_name' ,OR_FILTER_ALPHANUM); + $loginPassword = $this->getRequestVar('login_password',OR_FILTER_ALPHANUM); + $newPassword1 = $this->getRequestVar('password1' ,OR_FILTER_ALPHANUM); + $newPassword2 = $this->getRequestVar('password2' ,OR_FILTER_ALPHANUM); + $token = $this->getRequestVar('user_token' ,OR_FILTER_ALPHANUM); + + // Der Benutzer hat zwar ein richtiges Kennwort eingegeben, aber dieses ist abgelaufen. + // Wir versuchen hier, das neue zu setzen (sofern eingegeben). + if ( empty($newPassword1) ) + { + // Kein neues Kennwort, + // nichts zu tun... + } + else + { + $auth = new InternalAuth(); + + if ( $auth->login($loginName, $loginPassword,$token) || $auth->mustChangePassword ) + { + if ( $newPassword1 != $newPassword2 ) + { + $this->addValidationError('password1','PASSWORDS_DO_NOT_MATCH'); + $this->addValidationError('password2',''); + return; + } + elseif ( strlen($newPassword1) < $conf['security']['password']['min_length'] ) + { + $this->addValidationError('password1','PASSWORD_MINLENGTH',array('minlength'=>$conf['security']['password']['min_length'])); + $this->addValidationError('password2',''); + return; + } + else + { + // Kennwoerter identisch und lang genug. + $user = User::loadWithName($loginName); + $user->setPassword( $newPassword1,true ); + + // Das neue gesetzte Kennwort für die weitere Authentifizierung benutzen. + $loginPassword = $newPassword1; + } + } + else + { + // Anmeldung gescheitert. + $this->addNotice('user',$loginName,'LOGIN_FAILED','error',array('name'=>$loginName) ); + $this->addValidationError('login_name' ,''); + $this->addValidationError('login_password',''); + return; + } + } + + // Cookie setzen + $this->setCookie('or_username',$loginName ); + $this->setCookie('or_dbid' ,$this->getRequestVar('dbid')); + + // Authentifzierungs-Module. + $modules = explode(',',$conf['security']['modules']['authenticate']); + + $loginOk = false; + $mustChangePassword = false; + $tokenFailed = false; + $groups = null; + $lastModule = null; + + // Jedes Authentifizierungsmodul durchlaufen, bis ein Login erfolgreich ist. + foreach( $modules as $module) + { + $moduleClass = $module.'Auth'; + $auth = new $moduleClass; + Logger::info('Trying to login with module '.$moduleClass); + $loginStatus = $auth->login( $loginName,$loginPassword, $token ); + $loginOk = $loginStatus === true || $loginStatus === OR_AUTH_STATUS_SUCCESS; + + if ( $loginStatus === OR_AUTH_STATUS_PW_EXPIRED ) + $mustChangePassword = true; + if ( $loginStatus === OR_AUTH_STATUS_TOKEN_NEEDED ) + $tokenFailed = true; + + if ( $loginOk ) + { + Logger::info('Login successful for '.$loginName); + $lastModule = $module; + + if ( isset($auth->groups ) ) + $groups = $auth->groups; + + break; // Login erfolgreich, erstes Modul gewinnt. + } + } + + /* + $loginOk = $this->checkLogin( $loginName, + $loginPassword, + $newPassword1, + $newPassword2 ); + */ + + + if ( $loginOk ) + { + + try + { + // Benutzer über den Benutzernamen laden. + $user = User::loadWithName($loginName); + $user->loginModuleName = $lastModule; + $user->setCurrent(); + + if ($user->passwordAlgo != Password::bestAlgoAvailable() ) + // Re-Hash the password with a better hash algo. + $user->setPassword($loginPassword); + + } + catch( ObjectNotFoundException $ex ) + { + // Benutzer wurde zwar authentifiziert, ist aber in der + // internen Datenbank nicht vorhanden + if ( $conf['security']['newuser']['autoadd'] ) + { + // Neue Benutzer in die interne Datenbank uebernehmen. + $user = new User(); + $user->name = $loginName; + $user->fullname = $loginName; + $user->add(); + $user->save(); + } + else + { + // Benutzer soll nicht angelegt werden. + // Daher ist die Anmeldung hier gescheitert. + $loginOk = false; + } + } + } + + Password::delay(); + + $ip = getenv("REMOTE_ADDR"); + + if ( !$loginOk ) + { + // Anmeldung nicht erfolgreich + + Logger::debug("Login failed for user '$loginName' from IP $ip"); + + if ( $tokenFailed ) + { + // Token falsch. + $this->addNotice('user',$loginName,'LOGIN_FAILED_TOKEN_FAILED','error' ); + $this->addValidationError('user_token',''); + } + elseif ( $mustChangePassword ) + { + // Anmeldung gescheitert, Benutzer muss Kennwort ?ndern. + $this->addNotice('user',$loginName,'LOGIN_FAILED_MUSTCHANGEPASSWORD','error' ); + $this->addValidationError('password1',''); + $this->addValidationError('password2',''); + } + else + { + // Anmeldung gescheitert. + $this->addNotice('user',$loginName,'LOGIN_FAILED','error',array('name'=>$loginName) ); + $this->addValidationError('login_name' ,''); + $this->addValidationError('login_password',''); + } + + return; + } + else + { + + Logger::debug("Login successful for user '$loginName' from IP $ip"); + + $this->checkGroups( $user, $groups ); + + if ( $this->hasRequestVar('remember') ) + { + // Cookie setzen + $this->setCookie('or_username',$user->name ); + $this->setCookie('or_token' ,$user->loginToken() ); + } + + // Anmeldung erfolgreich. + if ( config()->subset('security')->is('renew_session_login',false) ) + $this->recreateSession(); + + $this->addNotice('user',$user->name,'LOGIN_OK',OR_NOTICE_OK,array('name'=>$user->fullname)); + + $this->setStyle( $user->style ); // Benutzer-Style setzen + + $config = Session::getConfig(); + $language = new \language\Language(); + $config['language'] = $language->getLanguage($user->language); + $config['language']['language_code'] = $user->language; + Session::setConfig( $config ); + } + + } + + + /** + * Benutzer meldet sich ab. + */ + function logoutPost() + { + global $conf; + + $user = Session::getUser(); + if ( is_object($user) ) + $this->setTemplateVar('login_username',$user->name); + + if ( config()->subset('security')->is('renew_session_logout',false) ) + $this->recreateSession(); + + session_unset(); + + if ( @$conf['theme']['compiler']['compile_at_logout'] ) + { + foreach( $conf['action'] as $actionName => $actionConfig ) + { + foreach( $actionConfig as $subActionName=>$subaction ) + { + if ( is_array($subaction) && + !isset($subaction['goto' ]) && + !isset($subaction['direct']) && + !isset($subaction['action']) && + !isset($subaction['async' ]) && + !isset($subaction['alias' ]) && + $subActionName != 'menu' ) + { + $engine = new template_engine\TemplateEngine(); + $engine->compile( strtolower(str_replace('Action','',$actionName)).'/'.$subActionName); + } + } + } + } + + // Login-Token löschen: + // Wenn der Benutzer sich abmelden will, dann soll auch die automatische + // Anmeldung deaktiviert werden. + $this->setCookie('or_token' ,null ); + + // Umleiten auf eine definierte URL.s + $redirect_url = @$conf['security']['logout']['redirect_url']; + + if ( !empty($redirect_url) ) + { + $this->redirect($redirect_url); + } + + // Style zurücksetzen. + // Der Style des Benutzers koennte auch stehen bleiben. Aber dann gäbe es Rückschlüsse darauf, wer zuletzt angemeldet war (Sicherheit!). + $this->setStyle( config('interface','style','default') ); + } + + + + /** + * Benutzer meldet sich ab. + */ + function logoutView() + { + } + + + /** + * Ausgeben von maschinenlesbaren Benutzerinformationen. + * + * Diese Funktion dient dem Single-Signon f?r fremde Anwendungen, welche + * die Benutzerinformationen des angemeldeten Benutzers aus dieser + * Anwendung auslesen k?nnen. + */ + function userinfo() + { + $user = Session::getUser(); + $info = array('username' => $user->name, + 'fullname' => $user->fullname, + 'mail' => $user->mail, + 'telephone' => $user->tel, + 'style' => $user->style, + 'admin' => $user->isAdmin?'true':'false', + 'ldap' => $user->ldap_dn, + 'groups' => implode(',',$user->getGroups()), + 'description'=> $user->desc + ); + + // Wenn der HTTP-Parameter "xml" vorhanden ist, dann geben wir die + // Informationen per XML aus. + if ( $this->hasRequestVar('xml') ) + { + header('Content-Type: text/xml'); + echo '<userinfo>'; + foreach( $info as $n=>$i ) + echo '<'.$n.'>'.$i.'</'.$n.'>'."\n"; + echo '</userinfo>'; + + } + + // Sonst normale Textausgabe im INI-Datei-Format. + else + { + header('Content-Type: text/plain'); + foreach( $info as $n=>$i ) + echo $n.'="'.$i."\"\n"; + } + + exit; // Fertig. + } + + + function project() + { + $user = Session::getUser(); + if ( ! is_object($user) ) + { + $this->callSubAction('show'); + return; + } + + $this->evaluateRequestVars( array('projectid'=>$this->getRequestId()) ); + + Session::setUser( $user ); + } + + + function object() + { + $user = Session::getUser(); + if ( ! is_object($user) ) + { + $this->callSubAction('show'); + return; + } + + $this->evaluateRequestVars( array('objectid'=>$this->getRequestId()) ); + + Session::setUser( $user ); + } + + + function language() + { + $user = Session::getUser(); + if ( ! is_object($user) ) + { + $this->callSubAction('show'); + return; + } + + $this->evaluateRequestVars( array(REQ_PARAM_LANGUAGE_ID=>$this->getRequestId()) ); + } + + + function model() + { + $user = Session::getUser(); + if ( ! is_object($user) ) + { + $this->callSubAction('show'); + return; + } + + $this->evaluateRequestVars( array(REQ_PARAM_MODEL_ID=>$this->getRequestId()) ); + + $user = Session::getUser(); + } + + + /** + * Auswerten der Request-Variablen. + * + * @param Array $add + */ + function evaluateRequestVars( $add = array() ) + { + } + + + function showtree() + { + Session::set('showtree',true ); + } + + + function hidetree() + { + Session::set('showtree',false ); + } + + + function switchuser() + { + $user = Session::getUser(); + + if ( ! $user->isAdmin ) + throw new \SecurityException("Switching the user is only possible for admins."); + + $this->recreateSession(); + + $newUser = new User( $this->getRequestId() ); + $newUser->load(); + + $newUser->setCurrent(); + } + + + function show() + { + global $conf; + global $PHP_AUTH_USER; + global $PHP_AUTH_PW; + + $user = Session::getUser(); + // Gast-Login + if ( ! is_object($user) ) + { + if ( $conf['security']['guest']['enable'] ) + { + $username = $conf['security']['guest']['user']; + $user = User::loadWithName($username); + if ( $user->userid > 0 ) + $user->setCurrent(); + else + { + Logger::warn('Guest login failed, user not found: '.$username); + $this->addNotice('user',$username,'LOGIN_FAILED',OR_NOTICE_WARN,array('name'=>$username) ); + $user = null; + } + } + } + + if ( ! is_object($user) ) + { + switch( $conf['security']['login']['type'] ) + { + + // Authorization ueber HTTP + // + case 'http': + $ok = false; + + if ( isset($_SERVER['PHP_AUTH_USER']) ) + { + $ok = $this->checkLogin( $_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'] ); + } + + if ( ! $ok ) + { + header( 'WWW-Authenticate: Basic realm="'.OR_TITLE.' - '.lang('HTTP_REALM').'"' ); + header( 'HTTP/1.0 401 Unauthorized' ); + echo 'Authorization Required!'; + exit; + } + break; + + case 'form': + // Benutzer ist nicht angemeldet + $this->callSubAction( 'showlogin' ); // Anzeigen der Login-Maske + return; + break; + + default: + throw new \LogicException('Unknown auth-type: '.$conf['security']['login']['type'].'. Please check the configuration setting /security/login/type' ); + } + } + + if ( $user->mustChangePassword ) + { + $this->addNotice( 'user',$user->name,'PASSWORD_TIMEOUT','warn' ); + $this->callSubAction( 'changepassword' ); // Zwang, das Kennwort zu ?ndern. + } + + // Seite ?ndert sich nur 1x pro Session + $this->lastModified( $user->loginDate ); + + } + + + + /** + * Maske anzeigen, um Benutzer zu registrieren. + */ + public function registerView() + { + + } + + + /** + * Registriercode erzeugen und per E-Mail dem Benutzer mitteilen. + * Maske anzeigen, damit Benuter Registriercode anzeigen kann. + */ + public function registercodeView() + { + global $conf; + foreach( $conf['database'] as $dbname=>$dbconf ) + { + if ( is_array($dbconf) && $dbconf['enabled'] ) + $dbids[$dbname] = $dbconf['description']; + } + + $this->setTemplateVar( 'dbids',$dbids ); + + $db = db(); + if ( is_object($db) ) + $this->setTemplateVar('actdbid',$db->id); + else + $this->setTemplateVar('actdbid',$conf['database-defaults']['default-id']); + + + + } + + + + public function registerPost() + { + global $conf; + + Session::set('registerMail',$this->getRequestVar('mail') ); + + srand ((double)microtime()*1000003); + $registerCode = rand(); + + Session::set('registerCode',$registerCode ); + + $email_address = $this->getRequestVar('mail',OR_FILTER_MAIL); + + if ( ! Mail::checkAddress($email_address) ) + { + $this->addValidationError('mail'); + return; + } + + // E-Mail and die eingegebene Adresse verschicken + $mail = new Mail($email_address, + 'register_commit_code','register_commit_code'); + $mail->setVar('code',$registerCode); // Registrierungscode als Text-Variable + + if ( $mail->send() ) + { + $this->addNotice('','','mail_sent',OR_NOTICE_OK); + } + else + { + $this->addNotice('','','mail_not_sent',OR_NOTICE_ERROR,array(),$mail->error); + return; + } + } + + + /** + * Benutzerregistierung. + * Benutzer hat Best?tigungscode erhalten und eingegeben. + */ + function registercodePost() + { + global $conf; + + $origRegisterCode = Session::get('registerCode'); + $inputRegisterCode = $this->getRequestVar('code'); + + if ( $origRegisterCode != $inputRegisterCode ) + { + // Best?tigungscode stimmt nicht. + $this->addValidationError('code','code_not_match'); + return; + } + + // Best?tigungscode stimmt ?berein. + // Neuen Benutzer anlegen. + + if ( !$this->hasRequestVar('username') ) + { + $this->addValidationError('username'); + return; + } + + $user = User::loadWithName( $this->getRequestVar('username') ); + if ( $user->isValid() ) + { + $this->addValidationError('username','USER_ALREADY_IN_DATABASE'); + return; + } + + if ( strlen($this->getRequestVar('password')) < $conf['security']['password']['min_length'] ) + { + $this->addValidationError('password','password_minlength',array('minlength'=>$conf['security']['password']['min_length'])); + return; + } + + $newUser = new User(); + $newUser->name = $this->getRequestVar('username'); + $newUser->add(); + + $newUser->mail = Session::get('registerMail'); + $newUser->save(); + + $newUser->setPassword( $this->getRequestVar('password'),true ); + + $this->addNotice('user',$newUser->name,'user_added','ok'); + } + + + + /** + * Vergessenes Kennwort zusenden lassen. + */ + function passwordView() + { + // TODO: Attribut "Password" abfragen + foreach( config('database') as $dbname=>$dbconf ) + { + $dbconf = $dbconf + config('database-default','defaults'); + if ( $dbconf['enabled'] ) + $dbids[$dbname] = $dbconf['description']; + } + + $this->setTemplateVar( 'dbids',$dbids ); + + + $db = db(); + + if ( is_object($db) ) + $this->setTemplateVar('actdbid',$db->id); + else + $this->setTemplateVar('actdbid',config('database-default','default-id')); + } + + + + /** + * Einen Kennwort-Anforderungscode an den Benutzer senden. + */ + function passwordPost() + { + if ( !$this->hasRequestVar('username') ) + { + $this->addValidationError('username'); + return; + } + + $user = User::loadWithName( $this->getRequestVar("username") ); + // Html::debug($user); + Password::delay(); + if ( $user->isValid() ) + { + srand ((double)microtime()*1000003); + $code = rand(); + $this->setSessionVar("password_commit_code",$code); + + $eMail = new Mail( $user->mail,'password_commit_code' ); + $eMail->setVar('name',$user->getName()); + $eMail->setVar('code',$code); + if ( $eMail->send() ) + $this->addNotice('user',$user->getName(),'mail_sent',OR_NOTICE_OK); + else + $this->addNotice('user',$user->getName(),'mail_not_sent',OR_NOTICE_ERROR,array(),$eMail->error); + + } + else + { + //$this->addNotice('','user','username_not_found'); + // Trotzdem vort?uschen, eine E-Mail zu senden, damit die G?ltigkeit + // eines Benutzernamens nicht von au?en gepr?ft werden kann. + // + $this->addNotice('user',$this->getRequestVar("username"),'mail_sent'); + + } + + $this->setSessionVar("password_commit_name",$user->name); + } + + + + /** + * Anzeige Formular zum Eingeben des Kennwort-Codes. + * + */ + function passwordcodeView() + { + + } + + + /** + * Neues Kennwort erzeugen und dem Benutzer zusenden. + */ + function passwordcodePost() + { + $username = $this->getSessionVar("password_commit_name"); + + if ( $this->getRequestVar("code")=='' || + $this->getSessionVar("password_commit_code") != $this->getRequestVar("code") ) + { + $this->addValidationError('code','PASSWORDCODE_NOT_MATCH'); + return; + } + + $user = User::loadWithName( $username ); + + if ( !$user->isValid() ) + { + // Benutzer konnte nicht geladen werden. + $this->addNotice('user',$username,'error',OR_NOTICE_ERROR); + return; + } + + $newPw = User::createPassword(); // Neues Kennwort erzeugen. + + $eMail = new Mail( $user->mail,'password_new' ); + $eMail->setVar('name' ,$user->getName()); + $eMail->setVar('password',$newPw ); + + if ( $eMail->send() ) + { + $user->setPassword( $newPw, false ); // Kennwort muss beim n?. Login ge?ndert werden. + $this->addNotice('user',$username,'mail_sent',OR_NOTICE_OK); + } + else + { + // Sollte eigentlich nicht vorkommen, da der Benutzer ja auch schon den + // Code per E-Mail erhalten hat. + $this->addNotice('user',$username,'error',OR_NOTICE_ERROR,array(),$eMail->error); + } + } + + + /** + * Erzeugt eine neue Sitzung. + */ + function recreateSession() + { + + session_regenerate_id(true); + } + + + function licenseView() + { + $software = array(); + + $software[] = array('name' =>'OpenRat Content Management System', + 'url' =>'http://www.openrat.de/', + 'license'=>'GPL v2'); + $software[] = array('name' =>'jQuery Core Javascript Framework', + 'url' =>'http://jquery.com/', + 'license'=>'MPL, GPL v2'); + $software[] = array('name' =>'jQuery UI Javascript Framework', + 'url' =>'http://jqueryui.com/', + 'license'=>'MPL, GPL v2'); + $software[] = array('name' =>'GeSHi - Generic Syntax Highlighter', + 'url' =>'http://qbnz.com/highlighter/', + 'license'=>'GPL v2'); + $software[] = array('name' =>'TAR file format', + 'url' =>'http://www.phpclasses.org/package/529', + 'license'=>'LGPL'); + $software[] = array('name' =>'JSON file format', + 'url' =>'http://pear.php.net/pepr/pepr-proposal-show.php?id=198', + 'license'=>'BSD'); + + $this->setTemplateVar('software',$software); + + + + $this->setTemplateVar('time' ,date('r') ); + $this->setTemplateVar('os' ,php_uname('s') ); + $this->setTemplateVar('release' ,php_uname('r') ); + $this->setTemplateVar('machine' ,php_uname('m') ); + $this->setTemplateVar('version' , phpversion() ); + + $this->setTemplateVar('cms_name' , Conf()->subset('application')->get('name' ) ); + $this->setTemplateVar('cms_version' , Conf()->subset('application')->get('version' ) ); + $this->setTemplateVar('cms_operator', Conf()->subset('application')->get('operator') ); + + $user = Session::getUser(); + if ( !empty($user) ) + { + $this->setTemplateVar('user_login' , $user->loginDate ); + $this->setTemplateVar('user_name' , $user->name ); + $this->setTemplateVar('user_fullname', $user->fullname ); + } + + } + + + + /** + * Updating the database. + * + * @param $dbid integer + * @throws OpenRatException + */ + private function updateDatabase($dbid) + { + try { + $dbConfig = Conf()->subset('database')->subset($dbid); + + if ( ! $dbConfig->is('check_version',false)) + return; // Check for DB version is disabled. + + $adminDb = new Database( $dbConfig->subset('admin')->getConfig() + $dbConfig->getConfig() ); + $adminDb->id = $dbid; + } catch (Exception $e) { + + throw new OpenRatException('DATABASE_ERROR_CONNECTION', $e->getMessage()); + } + + $updater = new DbUpdate(); + $updater->update($adminDb); + + // Try to close the PDO connection. PDO doc: + // To close the connection, you need to destroy the object by ensuring that all + // remaining references to it are deleted—you do this by assigning NULL to the variable that holds the object. + // If you don't do this explicitly, PHP will automatically close the connection when your script ends. + $adminDb = null; + unset($adminDb); + } + + +} + + diff --git a/modules/cms-core/functions/common.inc.php b/modules/cms-core/functions/common.inc.php @@ -1,178 +1,176 @@ -<?php - - -/** - * F�gt einen Slash ("/") an das Ende an, sofern nicht bereits vorhanden. - * - * @param String $pfad - * @return Pfad mit angeh�ngtem Slash. - */ -function slashify($pfad) -{ - if ( substr($pfad,-1,1) == '/') - return $pfad; - else - return $pfad.'/'; -} - -function convertToXmlAttribute( $value ) -{ - return utf8_encode( htmlspecialchars( $value ) ) ; -} - - -/** - * Ermittelt die aktuelle Systemzeit als Unix-Timestamp.<br> - * Unix-Timestamp ist immer bezogen auf GMT. - * - - * @return Unix-Timestamp der aktuellen Zeit - */ -function now() -{ - return time(); -} - - - -/** - * Erzeugt f�r eine Zahl eine Schreibweise mit Vorzeichen.<br> - * '-2' bleibt '-2'<br> - * '2' wird zu '+2'<br> - */ -function vorzeichen( $nr ) -{ - return intval($nr)<0 ? $nr : '+'.$nr; -} - - - -/** - * Stellt fest, ob das System in einem schreibgeschuetzten Zustand ist. - * - * @return boolean true, falls schreibgeschuetzt, sonst false - */ -function readonly() -{ - global $conf; - - // Gesamtes CMS ist readonly. - if ( config('security','readonly') ) - return true; - - // Aktuelle Datenbankverbindung ist readonly. - $db = Session::getDatabase(); - if ( isset($db->conf['readonly']) && $db->conf['readonly'] ) - return true; - - return false; -} - - - - - -/** - * Generiert aus der Session-Id einen Token. - * @return Token - */ -function token() -{ - return substr(session_id(),-10); -} - - -/** - * Ermittelt, ob der Wert 'true' oder 'false' entspricht. - * - * Anders als beim PHP-Cast auf boolean wird hier auch die - * Zeichenkette 'true' als wahr betrachtet. - * - * @param val mixed - * @return boolean - */ -function istrue( $val ) -{ - if ( is_bool($val) ) - return $val; - elseif( is_numeric($val) ) - return $val != 0; - elseif( is_string($val) ) - return $val == 'true' || $val == 'yes' || $val == '1'; - else - return false; -} - - - -/** - * Erzeugt einen Link auf die OpenRat-lokale CSS-Datei - * @param $name Name der Style-Konfiguration. Default: 'default'. - */ -function css_link( $name='default' ) -{ - global $conf; - - // Falls Style-Konfiguration unbekannt, dann Fallback auf default. - if ( ! isset($conf['style'][$name])) - $name = $conf['interface']['style']['default']; - - - return encode_array($conf['style'][$name]); -} - - -/** - * Encodiert ein Array für eine URL. - * - * @param $args URL-Parameter - */ -function encode_array( $args ) -{ - if ( !is_array($args) ) - return ''; - - $out = array(); - - foreach( $args as $name => $value ) - $out[] = $name.'='.urlencode($value); - - return implode('&',$out); -} - - -function not($var) { - return !$var; -} - -/** - * Liefert die Datenbankverbindung fuer die aktuelle Sitzung. - * - * @return \database\Database - * @deprecated use db() - */ -function db_connection() -{ - - return db(); -} - -/** - * Liefert die Datenbankverbindung fuer die aktuelle Sitzung. - * - * @return \database\Database - */ -function db() -{ - - $db = Session::getDatabase(); - - if ( ! is_object($db)) - throw new RuntimeException('no database available'); - - return $db; -} - - - - +<?php + + +/** + * F�gt einen Slash ("/") an das Ende an, sofern nicht bereits vorhanden. + * + * @param String $pfad + * @return Pfad mit angeh�ngtem Slash. + */ +function slashify($pfad) +{ + if ( substr($pfad,-1,1) == '/') + return $pfad; + else + return $pfad.'/'; +} + +function convertToXmlAttribute( $value ) +{ + return utf8_encode( htmlspecialchars( $value ) ) ; +} + + +/** + * Ermittelt die aktuelle Systemzeit als Unix-Timestamp.<br> + * Unix-Timestamp ist immer bezogen auf GMT. + * - + * @return Unix-Timestamp der aktuellen Zeit + */ +function now() +{ + return time(); +} + + + +/** + * Erzeugt f�r eine Zahl eine Schreibweise mit Vorzeichen.<br> + * '-2' bleibt '-2'<br> + * '2' wird zu '+2'<br> + */ +function vorzeichen( $nr ) +{ + return intval($nr)<0 ? $nr : '+'.$nr; +} + + + +/** + * Stellt fest, ob das System in einem schreibgeschuetzten Zustand ist. + * + * @return boolean true, falls schreibgeschuetzt, sonst false + */ +function readonly() +{ + // Gesamtes CMS ist readonly. + if ( config('security','readonly') ) + return true; + + // Aktuelle Datenbankverbindung ist readonly. + $db = db(); + if ( isset($db->conf['readonly']) && $db->conf['readonly'] ) + return true; + + return false; +} + + + + + +/** + * Generiert aus der Session-Id einen Token. + * @return Token + */ +function token() +{ + return substr(session_id(),-10); +} + + +/** + * Ermittelt, ob der Wert 'true' oder 'false' entspricht. + * + * Anders als beim PHP-Cast auf boolean wird hier auch die + * Zeichenkette 'true' als wahr betrachtet. + * + * @param val mixed + * @return boolean + */ +function istrue( $val ) +{ + if ( is_bool($val) ) + return $val; + elseif( is_numeric($val) ) + return $val != 0; + elseif( is_string($val) ) + return $val == 'true' || $val == 'yes' || $val == '1'; + else + return false; +} + + + +/** + * Erzeugt einen Link auf die OpenRat-lokale CSS-Datei + * @param $name Name der Style-Konfiguration. Default: 'default'. + */ +function css_link( $name='default' ) +{ + global $conf; + + // Falls Style-Konfiguration unbekannt, dann Fallback auf default. + if ( ! isset($conf['style'][$name])) + $name = $conf['interface']['style']['default']; + + + return encode_array($conf['style'][$name]); +} + + +/** + * Encodiert ein Array für eine URL. + * + * @param $args URL-Parameter + */ +function encode_array( $args ) +{ + if ( !is_array($args) ) + return ''; + + $out = array(); + + foreach( $args as $name => $value ) + $out[] = $name.'='.urlencode($value); + + return implode('&',$out); +} + + +function not($var) { + return !$var; +} + +/** + * Liefert die Datenbankverbindung fuer die aktuelle Sitzung. + * + * @return \database\Database + * @deprecated use db() + */ +function db_connection() +{ + + return db(); +} + +/** + * Liefert die Datenbankverbindung fuer die aktuelle Sitzung. + * + * @return \database\Database + */ +function db() +{ + + $db = Session::getDatabase(); + + if ( ! is_object($db)) + throw new RuntimeException('no database available'); + + return $db; +} + + + + ?> \ No newline at end of file diff --git a/modules/cms-core/model/BaseObject.class.php b/modules/cms-core/model/BaseObject.class.php @@ -1194,14 +1194,12 @@ SQL */ public function parentObjectFileNames( $with_root = false, $with_self = false ) { - $db = \Session::getDatabase(); - $foid = $this->id; $idCache = array(); while( intval($foid)!=0 ) { - $sql = $db->sql( <<<SQL + $sql = db()->sql( <<<SQL SELECT parentid,id,filename FROM {{object}} @@ -1230,14 +1228,12 @@ SQL public function parentObjectNames( $with_root = false, $with_self = false ) { - $db = \Session::getDatabase(); - $foid = $this->id; $idCache = array(); while( intval($foid)!=0 ) { - $sql = $db->sql( <<<SQL + $sql = db()->sql( <<<SQL SELECT {{object}}.parentid,{{object}}.id,{{object}}.filename,{{name}}.name FROM {{object}} LEFT JOIN {{name}} diff --git a/modules/cms-core/model/Language.class.php b/modules/cms-core/model/Language.class.php @@ -1,218 +1,216 @@ -<?php -namespace cms\model; -// OpenRat Content Management System -// Copyright (C) 2002-2012 Jan Dankert, cms@jandankert.de -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - -/** - * Darstellen einer Sprache. Jeder Seiteninhalt wird einer Sprache zugeordnet. - * - * @version $Revision$ - * @author $Author$ - * @package openrat.objects - */ -class Language -{ - public $languageid; - public $projectid; - - public $name; - public $isoCode; - public $isDefault = false; - - - // Konstruktor - function __construct( $languageid='' ) - { - if ( is_numeric($languageid) ) - $this->languageid = $languageid; - } - - - - /** - * Stellt fest, ob die angegebene Id existiert. - */ - function available( $id ) - { - $db = db_connection(); - - $sql = $db->sql('SELECT 1 FROM {{language}} '. - ' WHERE id={id}'); - $sql->setInt('id' ,$id ); - - return intval($sql->getOne()) == 1; - } - - - - /** - * Lesen aus der Datenbank. - * - */ - public function load() - { - $db = \Session::getDatabase(); - - $sql = $db->sql( 'SELECT * FROM {{language}}'. - ' WHERE id={languageid}' ); - $sql->setInt( 'languageid',$this->languageid ); - - $row = $sql->getRow(); - - if ( count($row) > 0 ) - { - $this->name = $row['name' ]; - $this->isoCode = $row['isocode' ]; - $this->projectid = intval( $row['projectid'] ); - - $this->isDefault = ( $row['is_default'] == '1' ); - } - } - - - /** - * Speichern der Sprache in der Datenbank - */ - public function save() - { - $db = db_connection(); - - // Gruppe speichern - $sql = $db->sql( 'UPDATE {{language}} '. - 'SET name = {name}, '. - ' isocode = {isocode} '. - 'WHERE id={languageid}' ); - $sql->setString( 'name' ,$this->name ); - $sql->setString( 'isocode' ,$this->isoCode ); - - $sql->setInt( 'languageid',$this->languageid ); - - // Datenbankabfrage ausfuehren - $sql->query(); - } - - - /** - * Ermitteln aller Eigenschaften dieser Sprache - * @return Array - */ - function getProperties() - { - return Array( 'name' =>$this->name, - 'isocode'=>$this->isoCode ); - } - - - /** - * Neue Sprache hinzuf?gen - */ - function add( $isocode='' ) - { - global $SESS; - global $iso; - $db = db_connection(); - - if ( $isocode != '' ) - { - // Kleiner Trick, damit "no" (Norwegen) in der .ini-Datei stehen kann - $isocode = str_replace('_','',$isocode); - - $this->isocode = $isocode; - $codes = \GlobalFunctions::getIsoCodes(); - $this->name = $codes[ $isocode ]; - } - - $sql = $db->sql('SELECT MAX(id) FROM {{language}}'); - $this->languageid = intval($sql->getOne())+1; - - // Sprache hinzuf?gen - $sql = $db->sql( 'INSERT INTO {{language}} '. - '(id,projectid,name,isocode,is_default) VALUES( {languageid},{projectid},{name},{isocode},0 )'); - $sql->setInt ('languageid',$this->languageid ); - $sql->setInt ('projectid' ,$this->projectid ); - $sql->setString('name' ,$this->name ); - $sql->setString('isocode' ,$this->isoCode ); - - // Datenbankbefehl ausfuehren - $sql->query(); - } - - - // Diese Sprache als 'default' markieren. - function setDefault() - { - global $SESS; - $db = db_connection(); - - // Zuerst alle auf nicht-Standard setzen - $sql = $db->sql( 'UPDATE {{language}} '. - ' SET is_default = 0 '. - ' WHERE projectid={projectid}' ); - $sql->setInt('projectid',$this->projectid ); - $sql->query(); - - // Jetzt die gew?nschte Sprachvariante auf Standard setzen - $sql = $db->sql( 'UPDATE {{language}} '. - ' SET is_default = 1 '. - ' WHERE id={languageid}' ); - $sql->setInt('languageid',$this->languageid ); - $sql->query(); - } - - - // Sprache entfernen - function delete() - { - $db = db_connection(); - - // Sprache l?schen -// $sql = $db->sql( 'SELECT COUNT(*) FROM {{language}} WHERE projectid={projectid}' ); -// $sql->setInt( 'projectid',$this->projectid ); -// $count = $sql->getOne( $sql ); -// -// // Nur l?schen, wenn es mindestens 2 Sprachen gibt -// if ( $count >= 2 ) -// { - // Inhalte mit dieser Sprache l?schen - $sql = $db->sql( 'DELETE FROM {{value}} WHERE languageid={languageid}' ); - $sql->setInt( 'languageid',$this->languageid ); - $sql->query(); - - // Inhalte mit dieser Sprache l?schen - $sql = $db->sql( 'DELETE FROM {{name}} WHERE languageid={languageid}' ); - $sql->setInt( 'languageid',$this->languageid ); - $sql->query(); - - // Sprache l?schen - $sql = $db->sql( 'DELETE FROM {{language}} WHERE id={languageid}' ); - $sql->setInt( 'languageid',$this->languageid ); - $sql->query(); - - // Andere Sprache auf "Default" setzen - $sql = $db->sql( 'SELECT id FROM {{language}} WHERE projectid={projectid}' ); - $sql->setInt( 'projectid',$this->projectid ); - $new_default_languageid = $sql->getOne(); - - $sql = $db->sql( 'UPDATE {{language}} SET is_default=1 WHERE id={languageid}' ); - $sql->setInt( 'languageid',$new_default_languageid ); - $sql->query(); -// } - } -} - +<?php +namespace cms\model; +// OpenRat Content Management System +// Copyright (C) 2002-2012 Jan Dankert, cms@jandankert.de +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +/** + * Darstellen einer Sprache. Jeder Seiteninhalt wird einer Sprache zugeordnet. + * + * @version $Revision$ + * @author $Author$ + * @package openrat.objects + */ +class Language +{ + public $languageid; + public $projectid; + + public $name; + public $isoCode; + public $isDefault = false; + + + // Konstruktor + function __construct( $languageid='' ) + { + if ( is_numeric($languageid) ) + $this->languageid = $languageid; + } + + + + /** + * Stellt fest, ob die angegebene Id existiert. + */ + function available( $id ) + { + $db = db_connection(); + + $sql = $db->sql('SELECT 1 FROM {{language}} '. + ' WHERE id={id}'); + $sql->setInt('id' ,$id ); + + return intval($sql->getOne()) == 1; + } + + + + /** + * Lesen aus der Datenbank. + * + */ + public function load() + { + $stmt = db()->sql( 'SELECT * FROM {{language}}'. + ' WHERE id={languageid}' ); + $stmt->setInt( 'languageid',$this->languageid ); + + $row = $stmt->getRow(); + + if ( count($row) > 0 ) + { + $this->name = $row['name' ]; + $this->isoCode = $row['isocode' ]; + $this->projectid = intval( $row['projectid'] ); + + $this->isDefault = ( $row['is_default'] == '1' ); + } + } + + + /** + * Speichern der Sprache in der Datenbank + */ + public function save() + { + $db = db_connection(); + + // Gruppe speichern + $sql = $db->sql( 'UPDATE {{language}} '. + 'SET name = {name}, '. + ' isocode = {isocode} '. + 'WHERE id={languageid}' ); + $sql->setString( 'name' ,$this->name ); + $sql->setString( 'isocode' ,$this->isoCode ); + + $sql->setInt( 'languageid',$this->languageid ); + + // Datenbankabfrage ausfuehren + $sql->query(); + } + + + /** + * Ermitteln aller Eigenschaften dieser Sprache + * @return Array + */ + function getProperties() + { + return Array( 'name' =>$this->name, + 'isocode'=>$this->isoCode ); + } + + + /** + * Neue Sprache hinzuf?gen + */ + function add( $isocode='' ) + { + global $SESS; + global $iso; + $db = db_connection(); + + if ( $isocode != '' ) + { + // Kleiner Trick, damit "no" (Norwegen) in der .ini-Datei stehen kann + $isocode = str_replace('_','',$isocode); + + $this->isocode = $isocode; + $codes = \GlobalFunctions::getIsoCodes(); + $this->name = $codes[ $isocode ]; + } + + $sql = $db->sql('SELECT MAX(id) FROM {{language}}'); + $this->languageid = intval($sql->getOne())+1; + + // Sprache hinzuf?gen + $sql = $db->sql( 'INSERT INTO {{language}} '. + '(id,projectid,name,isocode,is_default) VALUES( {languageid},{projectid},{name},{isocode},0 )'); + $sql->setInt ('languageid',$this->languageid ); + $sql->setInt ('projectid' ,$this->projectid ); + $sql->setString('name' ,$this->name ); + $sql->setString('isocode' ,$this->isoCode ); + + // Datenbankbefehl ausfuehren + $sql->query(); + } + + + // Diese Sprache als 'default' markieren. + function setDefault() + { + global $SESS; + $db = db_connection(); + + // Zuerst alle auf nicht-Standard setzen + $sql = $db->sql( 'UPDATE {{language}} '. + ' SET is_default = 0 '. + ' WHERE projectid={projectid}' ); + $sql->setInt('projectid',$this->projectid ); + $sql->query(); + + // Jetzt die gew?nschte Sprachvariante auf Standard setzen + $sql = $db->sql( 'UPDATE {{language}} '. + ' SET is_default = 1 '. + ' WHERE id={languageid}' ); + $sql->setInt('languageid',$this->languageid ); + $sql->query(); + } + + + // Sprache entfernen + function delete() + { + $db = db_connection(); + + // Sprache l?schen +// $sql = $db->sql( 'SELECT COUNT(*) FROM {{language}} WHERE projectid={projectid}' ); +// $sql->setInt( 'projectid',$this->projectid ); +// $count = $sql->getOne( $sql ); +// +// // Nur l?schen, wenn es mindestens 2 Sprachen gibt +// if ( $count >= 2 ) +// { + // Inhalte mit dieser Sprache l?schen + $sql = $db->sql( 'DELETE FROM {{value}} WHERE languageid={languageid}' ); + $sql->setInt( 'languageid',$this->languageid ); + $sql->query(); + + // Inhalte mit dieser Sprache l?schen + $sql = $db->sql( 'DELETE FROM {{name}} WHERE languageid={languageid}' ); + $sql->setInt( 'languageid',$this->languageid ); + $sql->query(); + + // Sprache l?schen + $sql = $db->sql( 'DELETE FROM {{language}} WHERE id={languageid}' ); + $sql->setInt( 'languageid',$this->languageid ); + $sql->query(); + + // Andere Sprache auf "Default" setzen + $sql = $db->sql( 'SELECT id FROM {{language}} WHERE projectid={projectid}' ); + $sql->setInt( 'projectid',$this->projectid ); + $new_default_languageid = $sql->getOne(); + + $sql = $db->sql( 'UPDATE {{language}} SET is_default=1 WHERE id={languageid}' ); + $sql->setInt( 'languageid',$new_default_languageid ); + $sql->query(); +// } + } +} + ?> \ No newline at end of file diff --git a/modules/cms-core/model/Project.class.php b/modules/cms-core/model/Project.class.php @@ -1,1029 +1,1023 @@ -<?php - -namespace cms\model; - -define('PROJECT_FLAG_CUT_INDEX',1); -define('PROJECT_FLAG_CONTENT_NEGOTIATION',2); -define('PROJECT_FLAG_PUBLISH_FILE_EXTENSION',4); -define('PROJECT_FLAG_PUBLISH_PAGE_EXTENSION',8); - -use database\Database; -use Session; - - -/** - * Darstellen eines Projektes - * - * @author Jan Dankert - * @package openrat.objects - */ -class Project extends ModelBase -{ - // Eigenschaften - public $projectid; - public $name; - public $target_dir; - public $ftp_url; - - /** - * Hostname - * @var string - */ - public $url; - - public $ftp_passive; - public $cmd_after_publish; - - - /** - * @var boolean - */ - public $content_negotiation = false; - - /** - * @var boolean - */ - public $cut_index = false; - - /** - * @var boolean - */ - public $publishFileExtension = true; - - /** - * @var boolean - */ - public $publishPageExtension = true; - - public $log = array(); - - - - // Konstruktor - public function __construct( $projectid='' ) - { - if ( intval($projectid) != 0 ) - $this->projectid = $projectid; - } - - - private static $cache = array(); - - /** - * @param $projectid - * @return Project - * @throws \ObjectNotFoundException - */ - public static function create($projectid) - { - if ( empty( Project::$cache[ $projectid ] ) ) - { - $project = new Project( $projectid ); - - Project::$cache[ $projectid ] = $project->load(); - } - return Project::$cache[ $projectid ]; - } - - - /** - * Stellt fest, ob die angegebene Projekt-Id existiert. - * @param $id int Projekt-Id - * @return boolean - * - */ - public function isAvailable($id ) - { - $db = db_connection(); - - $sql = $db->sql('SELECT 1 FROM {{project}} '. - ' WHERE id={id}'); - $sql->setInt('id' ,$id ); - - return intval($sql->getOne()) == 1; - } - - - /** - * Liefert alle verf?gbaren Projekte. - * @return array - */ - public static function getAllProjects() - { - $db = db_connection(); - $sql = $db->sql( 'SELECT id,name FROM {{project}} '. - ' ORDER BY name' ); - - return $sql->getAssoc(); - } - - - // Liefert alle verf?gbaren Projekt-Ids - public function getAllProjectIds() - { - $db = db_connection(); - $sql = $db->sql( 'SELECT id FROM {{project}} '. - ' ORDER BY name' ); - - return $sql->getCol(); - } - - - /** - * Liefert die Sprachen des Projektes. - * - * @return array Id->Name - */ - public function getLanguages() - { - $db = db_connection(); - - $sql = $db->sql( 'SELECT id,name FROM {{language}}'. - ' WHERE projectid={projectid} '. - ' ORDER BY name' ); - $sql->setInt ('projectid',$this->projectid); - - return $sql->getAssoc(); - } - - - public function getLanguageIds() - { - return array_keys( $this->getLanguages() ); - } - - - /** - * Liefert die Projektmodelle als Array mit ID->Name. - * - * @return array - */ - public function getModels() - { - $db = db_connection(); - - $sql = $db->sql( 'SELECT id,name FROM {{projectmodel}}'. - ' WHERE projectid= {projectid} '. - ' ORDER BY name' ); - $sql->setInt ('projectid',$this->projectid); - - return $sql->getAssoc(); - } - - - public function getModelIds() - { - return array_keys( $this->getModels() ); - } - - - public function getTemplateIds() - { - $db = db_connection(); - - $sql = $db->sql( 'SELECT id FROM {{template}}'. - ' WHERE projectid= {projectid} ' ); - $sql->setInt ('projectid',$this->projectid); - - return $sql->getCol(); - } - - - public function getTemplates() - { - $db = db_connection(); - - $sql = $db->sql( 'SELECT id,name FROM {{template}}'. - ' WHERE projectid= {projectid} ' ); - $sql->setInt ('projectid',$this->projectid); - - return $sql->getAssoc(); - } - - - /** - * Ermitteln des Wurzel-Ordners fuer dieses Projekt. - * - * Der Wurzelordner ist der einzige Ordnerhat in diesem - * Projekt, der kein Elternelement besitzt. - * - * @return Objekt-Id des Wurzelordners - */ - public function getRootObjectId() - { - $db = db_connection(); - - $sql = $db->sql('SELECT id FROM {{object}}'. - ' WHERE parentid IS NULL'. - ' AND projectid={projectid}' ); - - $sql->setInt('projectid',$this->projectid); - - return( $sql->getOne() ); - } - - - - // Laden - - /** - * @throws \ObjectNotFoundException - */ - public function load() - { - $sql = db()->sql( 'SELECT * FROM {{project}} '. - ' WHERE id={projectid}' ); - $sql->setInt( 'projectid',$this->projectid ); - - $row = $sql->getRow(); - - if ( empty($row) ) - throw new \ObjectNotFoundException('project '.$this->projectid.' not found'); - - $this->name = $row['name' ]; - $this->url = $row['url' ]; - $this->target_dir = $row['target_dir' ]; - $this->ftp_url = $row['ftp_url' ]; - $this->ftp_passive = $row['ftp_passive' ]; - $this->cmd_after_publish = $row['cmd_after_publish' ]; - $this->cut_index = $row['flags']&PROJECT_FLAG_CUT_INDEX; - $this->content_negotiation = $row['flags']&PROJECT_FLAG_CONTENT_NEGOTIATION; - $this->publishFileExtension = $row['flags']&PROJECT_FLAG_PUBLISH_FILE_EXTENSION; - $this->publishPageExtension = $row['flags']&PROJECT_FLAG_PUBLISH_PAGE_EXTENSION; - - return $this; - } - - - // Laden - public function loadByName() - { - $db = db_connection(); - - $sql = $db->sql( 'SELECT * FROM {{project}} '. - ' WHERE name={projectname}' ); - $sql->setString( 'projectname',$this->name ); - - $row = $sql->getRow(); - - $this->projectid = $row['id' ]; - $this->target_dir = $row['target_dir' ]; - $this->ftp_url = $row['ftp_url' ]; - $this->url = $row['url' ]; - $this->ftp_passive = $row['ftp_passive' ]; - $this->cmd_after_publish = $row['cmd_after_publish' ]; - $this->cut_index = $row['flags']&PROJECT_FLAG_CUT_INDEX; - $this->content_negotiation = $row['flags']&PROJECT_FLAG_CONTENT_NEGOTIATION; - $this->publishFileExtension = $row['flags']&PROJECT_FLAG_PUBLISH_FILE_EXTENSION; - $this->publishPageExtension = $row['flags']&PROJECT_FLAG_PUBLISH_PAGE_EXTENSION; - } - - - // Speichern - public function save() - { - $db = db_connection(); - - $sql = $db->sql( <<<SQL - UPDATE {{project}} - SET name = {name}, - target_dir = {target_dir}, - ftp_url = {ftp_url}, - ftp_passive = {ftp_passive}, - url = {url}, - flags = {flags}, - cmd_after_publish = {cmd_after_publish} - WHERE id= {projectid} -SQL -); - - $sql->setString('ftp_url' ,$this->ftp_url ); - $sql->setString('url' ,$this->url ); - $sql->setString('name' ,$this->name ); - $sql->setString('target_dir' ,$this->target_dir ); - $sql->setInt ('ftp_passive' ,$this->ftp_passive ); - $sql->setString('cmd_after_publish' ,$this->cmd_after_publish ); - - $flags = 0; - if( $this->cut_index) $flags |= PROJECT_FLAG_CUT_INDEX; - if( $this->content_negotiation) $flags |= PROJECT_FLAG_CONTENT_NEGOTIATION; - if( $this->publishFileExtension) $flags |= PROJECT_FLAG_PUBLISH_FILE_EXTENSION; - if( $this->publishPageExtension) $flags |= PROJECT_FLAG_PUBLISH_PAGE_EXTENSION; - - $sql->setInt ('flags' ,$flags ); - $sql->setInt ('projectid' ,$this->projectid ); - - $sql->query(); - - try - { - $rootFolder = new Folder( $this->getRootObjectId() ); - $rootFolder->load(); - $rootFolder->filename = $this->name; - $rootFolder->save(); - } - catch( \Exception $e ) - { - \Logger::warn('Project '.$this->projectid.' has not a root folder'."\n".$e->getTraceAsString()); - } - } - - - /** - * Liefert alle Eigenschaften des Projektes. - */ - public function getProperties() - { - return parent::getProperties(); - } - - - /** - * Add a project to the database. - */ - public function add() - { - $db = db_connection(); - - $sql = $db->sql('SELECT MAX(id) FROM {{project}}'); - $this->projectid = intval($sql->getOne())+1; - - - // Projekt hinzuf?gen - $sql = $db->sql( 'INSERT INTO {{project}} (id,name,target_dir,ftp_url,ftp_passive,cmd_after_publish,flags) '. - " VALUES( {projectid},{name},'','',0,'',0 ) " ); - $sql->setInt ('projectid',$this->projectid ); - $sql->setString('name' ,$this->name ); - - $sql->query(); - - // Modell anlegen - $model = new Model(); - $model->projectid = $this->projectid; - $model->name = 'html'; - $model->add(); - - // Sprache anlegen - $language = new Language(); - $language->projectid = $this->projectid; - $language->isoCode = 'en'; - $language->name = 'english'; - $language->add(); - - // Haupt-Ordner anlegen - $folder = new Folder(); - $folder->isRoot = true; - $folder->projectid = $this->projectid; - $folder->languageid = $language->languageid; - $folder->filename = $this->name; - $folder->name = $this->name; - $folder->isRoot = true; - $folder->add(); - - // Template anlegen - $template = new Template(); - $template->projectid = $this->projectid; - $template->name = ''; - $template->modelid = $model->modelid; - $template->languageid = $language->languageid; - $template->extension = 'html'; - $template->src = '<html><body><h1>Hello world</h1><hr><p>Hello, World.</p></body></html>'; - $template->add(); - $template->save(); - - // Beispiel-Seite anlegen - $page = new Page(); - $page->parentid = $folder->objectid; - $page->projectid = $this->projectid; - $page->languageid = $language->languageid; - $page->templateid = $template->templateid; - $page->filename = ''; - $page->name = 'OpenRat'; - $page->add(); - } - - - // Projekt aus Datenbank entfernen - public function delete() - { - $db = db_connection(); - - // Root-Ordner rekursiv samt Inhalten loeschen - $folder = new Folder( $this->getRootObjectId() ); - $folder->deleteAll(); - - - foreach( $this->getLanguageIds() as $languageid ) - { - $language = new Language( $languageid ); - $language->delete(); - } - - - foreach( $this->getTemplateIds() as $templateid ) - { - $template = new Template( $templateid ); - $template->delete(); - } - - - foreach( $this->getModelIds() as $modelid ) - { - $model = new Model( $modelid ); - $model->delete(); - } - - - // Deleting the project - $sql = $db->sql( 'DELETE FROM {{project}}'. - ' WHERE id= {projectid} ' ); - $sql->setInt( 'projectid',$this->projectid ); - $sql->query(); - } - - - /** - * Liefert die Standard-Sprach-Id. If there is no default language, the first language-id will be used. - * @return String - */ - public function getDefaultLanguageId() - { - $db = Session::getDatabase(); - - // ORDER BY deswegen, damit immer mind. eine Sprache - // gelesen wird - $sql = $db->sql( 'SELECT id FROM {{language}} '. - ' WHERE projectid={projectid}'. - ' ORDER BY is_default DESC, name ASC' ); - - $sql->setInt('projectid',$this->projectid ); - - return $sql->getOne(); - } - - - public function getDefaultModelId() - { - $db = Session::getDatabase(); - - // ORDER BY deswegen, damit immer mind. eine Sprache - // gelesen wird - $sql = $db->sql( 'SELECT id FROM {{projectmodel}} '. - ' WHERE projectid={projectid}'. - ' ORDER BY is_default DESC' ); - $sql->setInt('projectid',$this->projectid ); - - return $sql->getOne(); - } - - - - /** - * Entfernt nicht mehr notwendige Inhalte aus dem Archiv. - */ - public function checkLimit() - { - $root = new Folder( $this->getRootObjectId() ); - $root->projectid = $this->projectid; - - $pages = $this->getAllObjectIds( array('page') ); - $languages = $this->getLanguageIds(); - - foreach( $pages as $objectid ) - { - $page = new Page( $objectid ); - $page->load(); - foreach( $page->getElementIds() as $eid ) - { - foreach( $languages as $lid ) - { - $value = new Value(); - $value->element = new Element($eid); - $value->pageid = $page->pageid; - $value->languageid = $lid; - - $value->checkLimit(); - } - } - } - - } - - - - /** - * Testet die Integrität der Datenbank. - */ - public function checkLostFiles() - { - $this->log = array(); - - $db = Session::getDatabase(); - - // Ordnerstruktur prüfen. - $sql = $db->sql( <<<EOF -SELECT thistab.id FROM {{object}} AS thistab - LEFT JOIN {{object}} AS parenttab - ON parenttab.id = thistab.parentid - WHERE thistab.projectid={projectid} AND thistab.parentid IS NOT NULL AND parenttab.id IS NULL -EOF -); - $sql->setInt('projectid',$this->projectid); - - $idList = $sql->getCol(); - - if ( count( $idList ) > 0 ) - { - $lostAndFoundFolder = new Folder(); - $lostAndFoundFolder->projectid = $this->projectid; - $lostAndFoundFolder->languageid = $this->getDefaultLanguageId(); - $lostAndFoundFolder->filename = "lostandfound"; - $lostAndFoundFolder->name = 'Lost+found'; - $lostAndFoundFolder->parentid = $this->getRootObjectId(); - $lostAndFoundFolder->add(); - - foreach( $idList as $id ) - { - $this->log[] = 'Lost file! Moving '.$id.' to lost+found.'; - $obj = new BaseObject( $id ); - $obj->setParentId( $lostAndFoundFolder->objectid ); - } - } - - - // Prüfe, ob die Verbindung Projekt->Template->Templatemodell->Projectmodell->Projekt konsistent ist. - $sql = $db->sql( <<<EOF -SELECT DISTINCT projectid FROM {{projectmodel}} WHERE id IN (SELECT projectmodelid from {{templatemodel}} WHERE templateid in (SELECT id from {{template}} WHERE projectid={projectid})) -EOF -); - $sql->setInt('projectid',$this->projectid); - - $idList = $sql->getCol(); - - if ( count( $idList ) > 1 ) - { - \Logger::warn('Inconsistence found: Reference circle project<->template<->templatemodel<->projectmodel<->project is not consistent.'); - $this->log[] = 'Inconsistence found: Reference circle project<->template<->templatemodel<->projectmodel<->project is not consistent.'; - } - - } - - - /** - * Synchronisation des Projektinhaltes mit dem Dateisystem. - */ - public function sync() - { - global $conf; - $syncConf = $conf['sync']; - - if ( ! $syncConf['enabled'] ) - return; - - $syncDir = slashify($syncConf['directory']).$this->name; - - } - - /** - * Kopiert ein Projekt von einer Datenbank zu einer anderen.<br> - * <br> - * Alle Projektinhalte werden kopiert, die Fremdschluesselbeziehungen werden entsprechend angepasst.<br> - * <br> - * Alle Beziehungen zu Benutzern, z.B. "Zuletzt geaendert von", "angelegt von" sowie<br> - * alle Berechtigungsinformationen gehen verloren!<br> - * - * @param string $dbid_destination ID der Ziel-Datenbank - * @param string $name - */ - public function copy( $dbid_destination,$name='' ) - { - \Logger::debug( 'Copying project '.$this->name.' to database '.$dbid_destination ); - - global $conf; - $zeit = date('Y-m-d\TH:i:sO'); - - $db_src = db_connection(); - $db_dest = new Database( $conf['database'][$dbid_destination] ); - $db_dest->id = $dbid_destination; - $db_dest->start(); - - $sameDB = ( $db_dest->id == $db_src->id ); - - // ------------------------------------------------------- - $mapping = array(); - $ids = array('project' => array('foreign_keys'=>array(), - 'primary_key' =>'id', - 'unique_idx' =>'name', - 'erase' =>array() - ), - 'language' => array('foreign_keys'=>array('projectid'=>'project'), - 'primary_key' =>'id' - ), - 'projectmodel' => array('foreign_keys'=>array('projectid'=>'project'), - 'primary_key' =>'id' - ), - 'template' => array('foreign_keys'=>array('projectid'=>'project'), - 'primary_key' =>'id' - ), - 'object' => array('foreign_keys'=>array('projectid' =>'project' ), - 'self_key' =>'parentid', - 'primary_key' =>'id', - 'erase' =>array('create_userid','lastchange_userid') - ), - 'element' => array('foreign_keys'=>array('templateid' =>'template', - 'folderobjectid' =>'object', - 'default_objectid'=>'object' ), - 'primary_key' =>'id' - ), - 'templatemodel'=> array('foreign_keys'=>array('projectmodelid'=>'projectmodel', - 'templateid' =>'template' ), - 'primary_key' =>'id', - 'replace' =>array('text'=>'element') - ), - 'name' => array('foreign_keys'=>array('objectid' =>'object', - 'languageid'=>'language' ), - 'primary_key' =>'id' - ), - 'page' => array('foreign_keys'=>array('objectid' =>'object', - 'templateid'=>'template' ), - 'primary_key' =>'id' - ), - 'value' => array('foreign_keys'=>array('pageid' =>'page', - 'languageid'=>'language', - 'elementid'=>'element', - 'linkobjectid'=>'object' ), - 'erase' =>array('lastchange_userid'), - 'replace' =>array('text'=>'object'), - 'primary_key' =>'id' - ), - 'link' => array('foreign_keys'=>array('objectid' =>'object', - 'link_objectid'=>'object' ), - 'primary_key' =>'id' - ), - 'folder' => array('foreign_keys'=>array('objectid' =>'object' ), - 'primary_key' =>'id' - ), - 'file' => array('foreign_keys'=>array('objectid' =>'object' ), - 'primary_key' =>'id', - 'binary' =>'value' - ), - - ); - - if ( $sameDB ) - $ids['acl'] = array('foreign_keys'=>array('objectid' => 'object', - 'languageid' => 'language' ), - 'primary_key' =>'id' - ); - - foreach( $ids as $tabelle=>$data ) - { - \Logger::debug( 'Copying table '.$tabelle.' ...' ); - $mapping[$tabelle] = array(); - $idcolumn = $data['primary_key']; - - // Naechste freie Id in der Zieltabelle ermitteln. - $stmt = $db_dest->sql( 'SELECT MAX('.$idcolumn.') FROM {t_'.$tabelle.'}'); - $maxid = intval($stmt->getOne()); - $nextid = $maxid; - - // Zu �bertragende IDs ermitteln. - if ( count($data['foreign_keys'])==0 ) - { - $where = ' WHERE id='.$this->projectid; - } - else - { - foreach( $data['foreign_keys'] as $fkey_column=>$target_tabelle ) - { - $where = ' WHERE '.$fkey_column.' IN ('.join(array_keys($mapping[$target_tabelle]),',').')'; - break; - } - } - $stmt = $db_src->sql( 'SELECT '.$idcolumn.' FROM {t_'.$tabelle.'} '.$where); - - foreach( $stmt->getCol() as $srcid ) - { - \Logger::debug('Id '.$srcid.' of table '.$tabelle); - $mapping[$tabelle][$srcid] = ++$nextid; - - $stmt = $db_src->sql( 'SELECT * FROM {t_'.$tabelle.'} WHERE id={id}'); - $stmt->setInt('id',$srcid); - $row = $stmt->getRow(); - - // Wert des Prim�rschl�ssels �ndern. - $row[$idcolumn] = $mapping[$tabelle][$srcid]; - - // Fremdschl�sselbeziehungen auf neue IDn korrigieren. - foreach( $data['foreign_keys'] as $fkey_column=>$target_tabelle) - { - \Logger::debug($fkey_column.' '.$target_tabelle.' '.$row[$fkey_column]); - - if ( intval($row[$fkey_column]) != 0 ) - $row[$fkey_column] = $mapping[$target_tabelle][$row[$fkey_column]]; - } - - foreach( array_keys($row) as $key ) - { - if ( isset($data['unique_idx']) && $key == $data['unique_idx'] ) - { - // Nachschauen, ob es einen UNIQUE-Key in der Zieltabelle schon gibt. - $stmt = $db_dest->sql( 'SELECT 1 FROM {t_'.$tabelle.'} WHERE '.$key."='".$row[$key]."'"); - - if ( intval($stmt->getOne()) == 1 ) - $row[$key] = $row[$key].$zeit; - - } - - if ( !$sameDB && isset($data['erase']) && in_array($key,$data['erase']) ) - $row[$key] = null; - - if ( isset($data['self_key']) && $key == $data['self_key'] && intval($row[$key]) > 0 ) - $row[$key] = $row[$key]+$maxid; - } - - if ( isset($data['replace']) ) - { - foreach( $data['replace'] as $repl_column=>$repl_tabelle) - foreach( $mapping[$repl_tabelle] as $oldid=>$newid) - { - $row[$repl_column] = str_replace('{'.$oldid.'}','{'.$newid.'}' ,$row[$repl_column]); - $row[$repl_column] = str_replace('"'.$oldid.'"','"'.$newid.'"' ,$row[$repl_column]); - $row[$repl_column] = str_replace('->'.$oldid ,'->"'.$newid.'"',$row[$repl_column]); - } - } - - if ( isset($data['binary']) ) - { - if ( !$db_src->conf['base64'] && $db_dest->conf['base64'] ) - $row[$data['binary']] = base64_encode($row[$data['binary']]); - elseif ( $db_src->conf['base64'] && !$db_dest->conf['base64'] ) - $row[$data['binary']] = base64_decode($row[$data['binary']]); - } - - // Daten in Zieltabelle einf�gen. - $stmt = $db_dest->sql( 'INSERT INTO {t_'.$tabelle.'} ('.join(array_keys($row),',').') VALUES({'.join(array_keys($row),'},{').'})',$dbid_destination); - foreach( $row as $key=>$value ) - { - if ( !$sameDB && isset($data['erase']) && in_array($key,$data['erase']) ) - $stmt->setNull($key); - else - { - if(is_bool($value)) - $stmt->setBoolean($key,$value); - elseif(is_int($value)) - $stmt->setInt($key,$value); - elseif(is_string($value)) - $stmt->setString($key,$value); - } - } - //$sql = $db->sql( 'INSERT INTO {t_'.$tabelle.'} ('.join(array_keys($row),',').') VALUES('.join($row,',').')',$dbid_destination); - $stmt->query(); - } - - if ( isset($data['self_key']) ) - { - foreach( $mapping[$tabelle] as $oldid=>$newid ) - { - $stmt = $db_dest->sql( 'UPDATE {t_'.$tabelle.'} SET '.$data['self_key'].'='.$newid.' WHERE '.$data['self_key'].'='.($oldid+$maxid),$dbid_destination ); - $stmt->query(); - } - } - } - - \Logger::debug( 'Finished copying project' ); - - $db_dest->commit(); - } - - - - /** - * Ermittelt die Anzahl aller Objekte in diesem Projekt. - * @return int Anzahl - */ - public function countObjects() - { - $db = db_connection(); - $sql = $db->sql( 'SELECT COUNT(*) FROM {{object}} '. - ' WHERE projectid = {projectid}' ); - $sql->setInt( 'projectid', $this->projectid ); - - return $sql->getOne(); - - } - - - - /** - * Ermittelt die Gr��e aller Dateien in diesem Projekt. - * @return int Summe aller Dateigroessen - */ - public function size() - { - $db = db_connection(); - - $sql = $db->sql( <<<SQL - SELECT SUM(size) FROM {{file}} - LEFT JOIN {{object}} - ON {{file}}.objectid = {{object}}.id - WHERE projectid = {projectid} -SQL -); - $sql->setInt( 'projectid', $this->projectid ); - - return $sql->getOne(); - } - - - - /** - * Liefert alle verf?gbaren Projekt-Ids - */ - public function info() - { - $info = array(); - - $info['count_objects'] = $this->countObjects(); - $info['sum_filesize' ] = $this->size(); - - - return $info; - } - - - - - /** - * Ermittelt projektübergreifend die letzten Änderungen des angemeldeten Benutzers. - * - * @return array <string, unknown> - */ - public function getMyLastChanges() - { - - $db = db_connection(); - - - $sql = $db->sql( <<<SQL - SELECT {{object}}.id as objectid, - {{object}}.filename as filename, - {{object}}.typeid as typeid, - {{object}}.lastchange_date as lastchange_date, - {{name}}.name as name - FROM {{object}} - LEFT JOIN {{name}} - ON {{name}}.objectid = {{object}}.id - AND {{name}}.languageid = {languageid} - LEFT JOIN {{project}} - ON {{object}}.projectid = {{project}}.id - WHERE {{object}}.projectid = {projectid} - AND {{object}}.lastchange_userid = {userid} - ORDER BY {{object}}.lastchange_date DESC; -SQL - ); - - // Variablen setzen. - $sql->setInt( 'projectid', $this->projectid ); - - $sql->setInt( 'languageid', 0 ); - - $user = Session::getUser(); - $sql->setInt( 'userid', $user->userid ); - - return $sql->getAll(); - } - - - /** - * Ermittelt projektübergreifend die letzten Änderungen. - * - * @return array - */ - public static function getAllLastChanges() - { - $db = db_connection(); - - $sql = $db->sql( <<<SQL - SELECT {{object}}.id as objectid, - {{object}}.lastchange_date as lastchange_date, - {{object}}.filename as filename, - {{project}}.id as projectid, - {{project}}.name as projectname, - {{user}}.name as username, - {{user}}.id as userid, - {{user}}.mail as usermail, - {{user}}.fullname as userfullname - FROM {{object}} - LEFT JOIN {{project}} - ON {{object}}.projectid = {{project}}.id - LEFT JOIN {{user}} - ON {{user}}.id = {{object}}.lastchange_userid - ORDER BY {{object}}.lastchange_date DESC - LIMIT 50 -SQL - ); - - return $sql->getAll(); - } - - - - /** - * Ermittelt die letzten Änderung im Projekt. - * @return array - */ - public function getLastChanges() - { - - $db = db_connection(); - - $sql = $db->sql( <<<SQL - SELECT {{object}}.id as objectid, - {{object}}.lastchange_date as lastchange_date, - {{object}}.filename as filename, - {{object}}.typeid as typeid, - {{name}}.name as name, - {{user}}.name as username, - {{user}}.id as userid, - {{user}}.mail as usermail, - {{user}}.fullname as userfullname - FROM {{object}} - LEFT JOIN {{name}} - ON {{name}}.objectid = {{object}}.id - AND {{name}}.languageid = {languageid} - LEFT JOIN {{user}} - ON {{user}}.id = {{object}}.lastchange_userid - WHERE {{object}}.projectid = {projectid} - ORDER BY {{object}}.lastchange_date DESC -SQL - ); - - // Variablen setzen. - $sql->setInt( 'projectid', $this->projectid ); - - $languageid = $this->getDefaultLanguageId(); - $sql->setInt( 'languageid', $languageid ); - - return $sql->getAll(); - } - - /** - * Ermittelt alle Objekte vom gew�nschten Typ, die sic in - * diesem Projekt befinden. - * - * @see objectClasses/Object#getAllObjectIds() - * @param types Array - * @return Liste von Object-Ids - */ - public function getAllObjectIds( $types=array('folder','page','link','file','image','url','text') ) - { - $stmt = db()->sql( <<<SQL - SELECT id FROM {{object}} - WHERE projectid={projectid} - AND ( typeid ={is_folder} - OR typeid ={is_file} - OR typeid ={is_image} - OR typeid ={is_text} - OR typeid ={is_page} - OR typeid ={is_link} - OR typeid ={is_url} ) - ORDER BY orderid ASC -SQL - ); - - $stmt->setInt('projectid',$this->projectid ); - $stmt->setInt('is_folder',in_array('folder',$types)?BaseObject::TYPEID_FOLDER:0); - $stmt->setInt('is_file' ,in_array('file' ,$types)?BaseObject::TYPEID_FILE :0); - $stmt->setInt('is_image' ,in_array('image' ,$types)?BaseObject::TYPEID_IMAGE :0); - $stmt->setInt('is_text' ,in_array('text' ,$types)?BaseObject::TYPEID_TEXT :0); - $stmt->setInt('is_page' ,in_array('page' ,$types)?BaseObject::TYPEID_PAGE :0); - $stmt->setInt('is_link' ,in_array('link' ,$types)?BaseObject::TYPEID_LINK :0); - $stmt->setInt('is_url' ,in_array('url' ,$types)?BaseObject::TYPEID_URL :0); - - return( $stmt->getCol() ); - } - - - /** - * Liefert die Ids aller Ordner in diesem Projekt. - * - * @return array - */ - public function getAllFolders() - { - $db = db_connection(); - - $stmt = $db->sql('SELECT id FROM {{object}}'. - ' WHERE typeid='.BaseObject::TYPEID_FOLDER. - ' AND projectid={projectid}' ); - - $stmt->setInt( 'projectid',$this->projectid ); - - return( $stmt->getCol() ); - } - - -} - +<?php + +namespace cms\model; + +define('PROJECT_FLAG_CUT_INDEX',1); +define('PROJECT_FLAG_CONTENT_NEGOTIATION',2); +define('PROJECT_FLAG_PUBLISH_FILE_EXTENSION',4); +define('PROJECT_FLAG_PUBLISH_PAGE_EXTENSION',8); + +use database\Database; +use Session; + + +/** + * Darstellen eines Projektes + * + * @author Jan Dankert + * @package openrat.objects + */ +class Project extends ModelBase +{ + // Eigenschaften + public $projectid; + public $name; + public $target_dir; + public $ftp_url; + + /** + * Hostname + * @var string + */ + public $url; + + public $ftp_passive; + public $cmd_after_publish; + + + /** + * @var boolean + */ + public $content_negotiation = false; + + /** + * @var boolean + */ + public $cut_index = false; + + /** + * @var boolean + */ + public $publishFileExtension = true; + + /** + * @var boolean + */ + public $publishPageExtension = true; + + public $log = array(); + + + + // Konstruktor + public function __construct( $projectid='' ) + { + if ( intval($projectid) != 0 ) + $this->projectid = $projectid; + } + + + private static $cache = array(); + + /** + * @param $projectid + * @return Project + * @throws \ObjectNotFoundException + */ + public static function create($projectid) + { + if ( empty( Project::$cache[ $projectid ] ) ) + { + $project = new Project( $projectid ); + + Project::$cache[ $projectid ] = $project->load(); + } + return Project::$cache[ $projectid ]; + } + + + /** + * Stellt fest, ob die angegebene Projekt-Id existiert. + * @param $id int Projekt-Id + * @return boolean + * + */ + public function isAvailable($id ) + { + $db = db_connection(); + + $sql = $db->sql('SELECT 1 FROM {{project}} '. + ' WHERE id={id}'); + $sql->setInt('id' ,$id ); + + return intval($sql->getOne()) == 1; + } + + + /** + * Liefert alle verf?gbaren Projekte. + * @return array + */ + public static function getAllProjects() + { + $db = db_connection(); + $sql = $db->sql( 'SELECT id,name FROM {{project}} '. + ' ORDER BY name' ); + + return $sql->getAssoc(); + } + + + // Liefert alle verf?gbaren Projekt-Ids + public function getAllProjectIds() + { + $db = db_connection(); + $sql = $db->sql( 'SELECT id FROM {{project}} '. + ' ORDER BY name' ); + + return $sql->getCol(); + } + + + /** + * Liefert die Sprachen des Projektes. + * + * @return array Id->Name + */ + public function getLanguages() + { + $db = db_connection(); + + $sql = $db->sql( 'SELECT id,name FROM {{language}}'. + ' WHERE projectid={projectid} '. + ' ORDER BY name' ); + $sql->setInt ('projectid',$this->projectid); + + return $sql->getAssoc(); + } + + + public function getLanguageIds() + { + return array_keys( $this->getLanguages() ); + } + + + /** + * Liefert die Projektmodelle als Array mit ID->Name. + * + * @return array + */ + public function getModels() + { + $db = db_connection(); + + $sql = $db->sql( 'SELECT id,name FROM {{projectmodel}}'. + ' WHERE projectid= {projectid} '. + ' ORDER BY name' ); + $sql->setInt ('projectid',$this->projectid); + + return $sql->getAssoc(); + } + + + public function getModelIds() + { + return array_keys( $this->getModels() ); + } + + + public function getTemplateIds() + { + $db = db_connection(); + + $sql = $db->sql( 'SELECT id FROM {{template}}'. + ' WHERE projectid= {projectid} ' ); + $sql->setInt ('projectid',$this->projectid); + + return $sql->getCol(); + } + + + public function getTemplates() + { + $db = db_connection(); + + $sql = $db->sql( 'SELECT id,name FROM {{template}}'. + ' WHERE projectid= {projectid} ' ); + $sql->setInt ('projectid',$this->projectid); + + return $sql->getAssoc(); + } + + + /** + * Ermitteln des Wurzel-Ordners fuer dieses Projekt. + * + * Der Wurzelordner ist der einzige Ordnerhat in diesem + * Projekt, der kein Elternelement besitzt. + * + * @return Objekt-Id des Wurzelordners + */ + public function getRootObjectId() + { + $db = db_connection(); + + $sql = $db->sql('SELECT id FROM {{object}}'. + ' WHERE parentid IS NULL'. + ' AND projectid={projectid}' ); + + $sql->setInt('projectid',$this->projectid); + + return( $sql->getOne() ); + } + + + + // Laden + + /** + * @throws \ObjectNotFoundException + */ + public function load() + { + $sql = db()->sql( 'SELECT * FROM {{project}} '. + ' WHERE id={projectid}' ); + $sql->setInt( 'projectid',$this->projectid ); + + $row = $sql->getRow(); + + if ( empty($row) ) + throw new \ObjectNotFoundException('project '.$this->projectid.' not found'); + + $this->name = $row['name' ]; + $this->url = $row['url' ]; + $this->target_dir = $row['target_dir' ]; + $this->ftp_url = $row['ftp_url' ]; + $this->ftp_passive = $row['ftp_passive' ]; + $this->cmd_after_publish = $row['cmd_after_publish' ]; + $this->cut_index = $row['flags']&PROJECT_FLAG_CUT_INDEX; + $this->content_negotiation = $row['flags']&PROJECT_FLAG_CONTENT_NEGOTIATION; + $this->publishFileExtension = $row['flags']&PROJECT_FLAG_PUBLISH_FILE_EXTENSION; + $this->publishPageExtension = $row['flags']&PROJECT_FLAG_PUBLISH_PAGE_EXTENSION; + + return $this; + } + + + // Laden + public function loadByName() + { + $db = db_connection(); + + $sql = $db->sql( 'SELECT * FROM {{project}} '. + ' WHERE name={projectname}' ); + $sql->setString( 'projectname',$this->name ); + + $row = $sql->getRow(); + + $this->projectid = $row['id' ]; + $this->target_dir = $row['target_dir' ]; + $this->ftp_url = $row['ftp_url' ]; + $this->url = $row['url' ]; + $this->ftp_passive = $row['ftp_passive' ]; + $this->cmd_after_publish = $row['cmd_after_publish' ]; + $this->cut_index = $row['flags']&PROJECT_FLAG_CUT_INDEX; + $this->content_negotiation = $row['flags']&PROJECT_FLAG_CONTENT_NEGOTIATION; + $this->publishFileExtension = $row['flags']&PROJECT_FLAG_PUBLISH_FILE_EXTENSION; + $this->publishPageExtension = $row['flags']&PROJECT_FLAG_PUBLISH_PAGE_EXTENSION; + } + + + // Speichern + public function save() + { + $db = db_connection(); + + $sql = $db->sql( <<<SQL + UPDATE {{project}} + SET name = {name}, + target_dir = {target_dir}, + ftp_url = {ftp_url}, + ftp_passive = {ftp_passive}, + url = {url}, + flags = {flags}, + cmd_after_publish = {cmd_after_publish} + WHERE id= {projectid} +SQL +); + + $sql->setString('ftp_url' ,$this->ftp_url ); + $sql->setString('url' ,$this->url ); + $sql->setString('name' ,$this->name ); + $sql->setString('target_dir' ,$this->target_dir ); + $sql->setInt ('ftp_passive' ,$this->ftp_passive ); + $sql->setString('cmd_after_publish' ,$this->cmd_after_publish ); + + $flags = 0; + if( $this->cut_index) $flags |= PROJECT_FLAG_CUT_INDEX; + if( $this->content_negotiation) $flags |= PROJECT_FLAG_CONTENT_NEGOTIATION; + if( $this->publishFileExtension) $flags |= PROJECT_FLAG_PUBLISH_FILE_EXTENSION; + if( $this->publishPageExtension) $flags |= PROJECT_FLAG_PUBLISH_PAGE_EXTENSION; + + $sql->setInt ('flags' ,$flags ); + $sql->setInt ('projectid' ,$this->projectid ); + + $sql->query(); + + try + { + $rootFolder = new Folder( $this->getRootObjectId() ); + $rootFolder->load(); + $rootFolder->filename = $this->name; + $rootFolder->save(); + } + catch( \Exception $e ) + { + \Logger::warn('Project '.$this->projectid.' has not a root folder'."\n".$e->getTraceAsString()); + } + } + + + /** + * Liefert alle Eigenschaften des Projektes. + */ + public function getProperties() + { + return parent::getProperties(); + } + + + /** + * Add a project to the database. + */ + public function add() + { + $db = db_connection(); + + $sql = $db->sql('SELECT MAX(id) FROM {{project}}'); + $this->projectid = intval($sql->getOne())+1; + + + // Projekt hinzuf?gen + $sql = $db->sql( 'INSERT INTO {{project}} (id,name,target_dir,ftp_url,ftp_passive,cmd_after_publish,flags) '. + " VALUES( {projectid},{name},'','',0,'',0 ) " ); + $sql->setInt ('projectid',$this->projectid ); + $sql->setString('name' ,$this->name ); + + $sql->query(); + + // Modell anlegen + $model = new Model(); + $model->projectid = $this->projectid; + $model->name = 'html'; + $model->add(); + + // Sprache anlegen + $language = new Language(); + $language->projectid = $this->projectid; + $language->isoCode = 'en'; + $language->name = 'english'; + $language->add(); + + // Haupt-Ordner anlegen + $folder = new Folder(); + $folder->isRoot = true; + $folder->projectid = $this->projectid; + $folder->languageid = $language->languageid; + $folder->filename = $this->name; + $folder->name = $this->name; + $folder->isRoot = true; + $folder->add(); + + // Template anlegen + $template = new Template(); + $template->projectid = $this->projectid; + $template->name = ''; + $template->modelid = $model->modelid; + $template->languageid = $language->languageid; + $template->extension = 'html'; + $template->src = '<html><body><h1>Hello world</h1><hr><p>Hello, World.</p></body></html>'; + $template->add(); + $template->save(); + + // Beispiel-Seite anlegen + $page = new Page(); + $page->parentid = $folder->objectid; + $page->projectid = $this->projectid; + $page->languageid = $language->languageid; + $page->templateid = $template->templateid; + $page->filename = ''; + $page->name = 'OpenRat'; + $page->add(); + } + + + // Projekt aus Datenbank entfernen + public function delete() + { + $db = db_connection(); + + // Root-Ordner rekursiv samt Inhalten loeschen + $folder = new Folder( $this->getRootObjectId() ); + $folder->deleteAll(); + + + foreach( $this->getLanguageIds() as $languageid ) + { + $language = new Language( $languageid ); + $language->delete(); + } + + + foreach( $this->getTemplateIds() as $templateid ) + { + $template = new Template( $templateid ); + $template->delete(); + } + + + foreach( $this->getModelIds() as $modelid ) + { + $model = new Model( $modelid ); + $model->delete(); + } + + + // Deleting the project + $sql = $db->sql( 'DELETE FROM {{project}}'. + ' WHERE id= {projectid} ' ); + $sql->setInt( 'projectid',$this->projectid ); + $sql->query(); + } + + + /** + * Liefert die Standard-Sprach-Id. If there is no default language, the first language-id will be used. + * @return String + */ + public function getDefaultLanguageId() + { + // ORDER BY deswegen, damit immer mind. eine Sprache + // gelesen wird + $sql = db()->sql( 'SELECT id FROM {{language}} '. + ' WHERE projectid={projectid}'. + ' ORDER BY is_default DESC, name ASC' ); + + $sql->setInt('projectid',$this->projectid ); + + return $sql->getOne(); + } + + + public function getDefaultModelId() + { + // ORDER BY deswegen, damit immer mind. eine Sprache + // gelesen wird + $sql = db()->sql( 'SELECT id FROM {{projectmodel}} '. + ' WHERE projectid={projectid}'. + ' ORDER BY is_default DESC' ); + $sql->setInt('projectid',$this->projectid ); + + return $sql->getOne(); + } + + + + /** + * Entfernt nicht mehr notwendige Inhalte aus dem Archiv. + */ + public function checkLimit() + { + $root = new Folder( $this->getRootObjectId() ); + $root->projectid = $this->projectid; + + $pages = $this->getAllObjectIds( array('page') ); + $languages = $this->getLanguageIds(); + + foreach( $pages as $objectid ) + { + $page = new Page( $objectid ); + $page->load(); + foreach( $page->getElementIds() as $eid ) + { + foreach( $languages as $lid ) + { + $value = new Value(); + $value->element = new Element($eid); + $value->pageid = $page->pageid; + $value->languageid = $lid; + + $value->checkLimit(); + } + } + } + + } + + + + /** + * Testet die Integrität der Datenbank. + */ + public function checkLostFiles() + { + $this->log = array(); + + // Ordnerstruktur prüfen. + $stmt = db()->sql( <<<EOF +SELECT thistab.id FROM {{object}} AS thistab + LEFT JOIN {{object}} AS parenttab + ON parenttab.id = thistab.parentid + WHERE thistab.projectid={projectid} AND thistab.parentid IS NOT NULL AND parenttab.id IS NULL +EOF +); + $stmt->setInt('projectid',$this->projectid); + + $idList = $stmt->getCol(); + + if ( count( $idList ) > 0 ) + { + $lostAndFoundFolder = new Folder(); + $lostAndFoundFolder->projectid = $this->projectid; + $lostAndFoundFolder->languageid = $this->getDefaultLanguageId(); + $lostAndFoundFolder->filename = "lostandfound"; + $lostAndFoundFolder->name = 'Lost+found'; + $lostAndFoundFolder->parentid = $this->getRootObjectId(); + $lostAndFoundFolder->add(); + + foreach( $idList as $id ) + { + $this->log[] = 'Lost file! Moving '.$id.' to lost+found.'; + $obj = new BaseObject( $id ); + $obj->setParentId( $lostAndFoundFolder->objectid ); + } + } + + + // Prüfe, ob die Verbindung Projekt->Template->Templatemodell->Projectmodell->Projekt konsistent ist. + $stmt = db()->sql( <<<EOF +SELECT DISTINCT projectid FROM {{projectmodel}} WHERE id IN (SELECT projectmodelid from {{templatemodel}} WHERE templateid in (SELECT id from {{template}} WHERE projectid={projectid})) +EOF +); + $stmt->setInt('projectid',$this->projectid); + + $idList = $stmt->getCol(); + + if ( count( $idList ) > 1 ) + { + \Logger::warn('Inconsistence found: Reference circle project<->template<->templatemodel<->projectmodel<->project is not consistent.'); + $this->log[] = 'Inconsistence found: Reference circle project<->template<->templatemodel<->projectmodel<->project is not consistent.'; + } + + } + + + /** + * Synchronisation des Projektinhaltes mit dem Dateisystem. + */ + public function sync() + { + global $conf; + $syncConf = $conf['sync']; + + if ( ! $syncConf['enabled'] ) + return; + + $syncDir = slashify($syncConf['directory']).$this->name; + + } + + /** + * Kopiert ein Projekt von einer Datenbank zu einer anderen.<br> + * <br> + * Alle Projektinhalte werden kopiert, die Fremdschluesselbeziehungen werden entsprechend angepasst.<br> + * <br> + * Alle Beziehungen zu Benutzern, z.B. "Zuletzt geaendert von", "angelegt von" sowie<br> + * alle Berechtigungsinformationen gehen verloren!<br> + * + * @param string $dbid_destination ID der Ziel-Datenbank + * @param string $name + */ + public function copy( $dbid_destination,$name='' ) + { + \Logger::debug( 'Copying project '.$this->name.' to database '.$dbid_destination ); + + global $conf; + $zeit = date('Y-m-d\TH:i:sO'); + + $db_src = db_connection(); + $db_dest = new Database( $conf['database'][$dbid_destination] ); + $db_dest->id = $dbid_destination; + $db_dest->start(); + + $sameDB = ( $db_dest->id == $db_src->id ); + + // ------------------------------------------------------- + $mapping = array(); + $ids = array('project' => array('foreign_keys'=>array(), + 'primary_key' =>'id', + 'unique_idx' =>'name', + 'erase' =>array() + ), + 'language' => array('foreign_keys'=>array('projectid'=>'project'), + 'primary_key' =>'id' + ), + 'projectmodel' => array('foreign_keys'=>array('projectid'=>'project'), + 'primary_key' =>'id' + ), + 'template' => array('foreign_keys'=>array('projectid'=>'project'), + 'primary_key' =>'id' + ), + 'object' => array('foreign_keys'=>array('projectid' =>'project' ), + 'self_key' =>'parentid', + 'primary_key' =>'id', + 'erase' =>array('create_userid','lastchange_userid') + ), + 'element' => array('foreign_keys'=>array('templateid' =>'template', + 'folderobjectid' =>'object', + 'default_objectid'=>'object' ), + 'primary_key' =>'id' + ), + 'templatemodel'=> array('foreign_keys'=>array('projectmodelid'=>'projectmodel', + 'templateid' =>'template' ), + 'primary_key' =>'id', + 'replace' =>array('text'=>'element') + ), + 'name' => array('foreign_keys'=>array('objectid' =>'object', + 'languageid'=>'language' ), + 'primary_key' =>'id' + ), + 'page' => array('foreign_keys'=>array('objectid' =>'object', + 'templateid'=>'template' ), + 'primary_key' =>'id' + ), + 'value' => array('foreign_keys'=>array('pageid' =>'page', + 'languageid'=>'language', + 'elementid'=>'element', + 'linkobjectid'=>'object' ), + 'erase' =>array('lastchange_userid'), + 'replace' =>array('text'=>'object'), + 'primary_key' =>'id' + ), + 'link' => array('foreign_keys'=>array('objectid' =>'object', + 'link_objectid'=>'object' ), + 'primary_key' =>'id' + ), + 'folder' => array('foreign_keys'=>array('objectid' =>'object' ), + 'primary_key' =>'id' + ), + 'file' => array('foreign_keys'=>array('objectid' =>'object' ), + 'primary_key' =>'id', + 'binary' =>'value' + ), + + ); + + if ( $sameDB ) + $ids['acl'] = array('foreign_keys'=>array('objectid' => 'object', + 'languageid' => 'language' ), + 'primary_key' =>'id' + ); + + foreach( $ids as $tabelle=>$data ) + { + \Logger::debug( 'Copying table '.$tabelle.' ...' ); + $mapping[$tabelle] = array(); + $idcolumn = $data['primary_key']; + + // Naechste freie Id in der Zieltabelle ermitteln. + $stmt = $db_dest->sql( 'SELECT MAX('.$idcolumn.') FROM {t_'.$tabelle.'}'); + $maxid = intval($stmt->getOne()); + $nextid = $maxid; + + // Zu �bertragende IDs ermitteln. + if ( count($data['foreign_keys'])==0 ) + { + $where = ' WHERE id='.$this->projectid; + } + else + { + foreach( $data['foreign_keys'] as $fkey_column=>$target_tabelle ) + { + $where = ' WHERE '.$fkey_column.' IN ('.join(array_keys($mapping[$target_tabelle]),',').')'; + break; + } + } + $stmt = $db_src->sql( 'SELECT '.$idcolumn.' FROM {t_'.$tabelle.'} '.$where); + + foreach( $stmt->getCol() as $srcid ) + { + \Logger::debug('Id '.$srcid.' of table '.$tabelle); + $mapping[$tabelle][$srcid] = ++$nextid; + + $stmt = $db_src->sql( 'SELECT * FROM {t_'.$tabelle.'} WHERE id={id}'); + $stmt->setInt('id',$srcid); + $row = $stmt->getRow(); + + // Wert des Prim�rschl�ssels �ndern. + $row[$idcolumn] = $mapping[$tabelle][$srcid]; + + // Fremdschl�sselbeziehungen auf neue IDn korrigieren. + foreach( $data['foreign_keys'] as $fkey_column=>$target_tabelle) + { + \Logger::debug($fkey_column.' '.$target_tabelle.' '.$row[$fkey_column]); + + if ( intval($row[$fkey_column]) != 0 ) + $row[$fkey_column] = $mapping[$target_tabelle][$row[$fkey_column]]; + } + + foreach( array_keys($row) as $key ) + { + if ( isset($data['unique_idx']) && $key == $data['unique_idx'] ) + { + // Nachschauen, ob es einen UNIQUE-Key in der Zieltabelle schon gibt. + $stmt = $db_dest->sql( 'SELECT 1 FROM {t_'.$tabelle.'} WHERE '.$key."='".$row[$key]."'"); + + if ( intval($stmt->getOne()) == 1 ) + $row[$key] = $row[$key].$zeit; + + } + + if ( !$sameDB && isset($data['erase']) && in_array($key,$data['erase']) ) + $row[$key] = null; + + if ( isset($data['self_key']) && $key == $data['self_key'] && intval($row[$key]) > 0 ) + $row[$key] = $row[$key]+$maxid; + } + + if ( isset($data['replace']) ) + { + foreach( $data['replace'] as $repl_column=>$repl_tabelle) + foreach( $mapping[$repl_tabelle] as $oldid=>$newid) + { + $row[$repl_column] = str_replace('{'.$oldid.'}','{'.$newid.'}' ,$row[$repl_column]); + $row[$repl_column] = str_replace('"'.$oldid.'"','"'.$newid.'"' ,$row[$repl_column]); + $row[$repl_column] = str_replace('->'.$oldid ,'->"'.$newid.'"',$row[$repl_column]); + } + } + + if ( isset($data['binary']) ) + { + if ( !$db_src->conf['base64'] && $db_dest->conf['base64'] ) + $row[$data['binary']] = base64_encode($row[$data['binary']]); + elseif ( $db_src->conf['base64'] && !$db_dest->conf['base64'] ) + $row[$data['binary']] = base64_decode($row[$data['binary']]); + } + + // Daten in Zieltabelle einf�gen. + $stmt = $db_dest->sql( 'INSERT INTO {t_'.$tabelle.'} ('.join(array_keys($row),',').') VALUES({'.join(array_keys($row),'},{').'})',$dbid_destination); + foreach( $row as $key=>$value ) + { + if ( !$sameDB && isset($data['erase']) && in_array($key,$data['erase']) ) + $stmt->setNull($key); + else + { + if(is_bool($value)) + $stmt->setBoolean($key,$value); + elseif(is_int($value)) + $stmt->setInt($key,$value); + elseif(is_string($value)) + $stmt->setString($key,$value); + } + } + //$sql = $db->sql( 'INSERT INTO {t_'.$tabelle.'} ('.join(array_keys($row),',').') VALUES('.join($row,',').')',$dbid_destination); + $stmt->query(); + } + + if ( isset($data['self_key']) ) + { + foreach( $mapping[$tabelle] as $oldid=>$newid ) + { + $stmt = $db_dest->sql( 'UPDATE {t_'.$tabelle.'} SET '.$data['self_key'].'='.$newid.' WHERE '.$data['self_key'].'='.($oldid+$maxid),$dbid_destination ); + $stmt->query(); + } + } + } + + \Logger::debug( 'Finished copying project' ); + + $db_dest->commit(); + } + + + + /** + * Ermittelt die Anzahl aller Objekte in diesem Projekt. + * @return int Anzahl + */ + public function countObjects() + { + $db = db_connection(); + $sql = $db->sql( 'SELECT COUNT(*) FROM {{object}} '. + ' WHERE projectid = {projectid}' ); + $sql->setInt( 'projectid', $this->projectid ); + + return $sql->getOne(); + + } + + + + /** + * Ermittelt die Gr��e aller Dateien in diesem Projekt. + * @return int Summe aller Dateigroessen + */ + public function size() + { + $db = db_connection(); + + $sql = $db->sql( <<<SQL + SELECT SUM(size) FROM {{file}} + LEFT JOIN {{object}} + ON {{file}}.objectid = {{object}}.id + WHERE projectid = {projectid} +SQL +); + $sql->setInt( 'projectid', $this->projectid ); + + return $sql->getOne(); + } + + + + /** + * Liefert alle verf?gbaren Projekt-Ids + */ + public function info() + { + $info = array(); + + $info['count_objects'] = $this->countObjects(); + $info['sum_filesize' ] = $this->size(); + + + return $info; + } + + + + + /** + * Ermittelt projektübergreifend die letzten Änderungen des angemeldeten Benutzers. + * + * @return array <string, unknown> + */ + public function getMyLastChanges() + { + + $db = db_connection(); + + + $sql = $db->sql( <<<SQL + SELECT {{object}}.id as objectid, + {{object}}.filename as filename, + {{object}}.typeid as typeid, + {{object}}.lastchange_date as lastchange_date, + {{name}}.name as name + FROM {{object}} + LEFT JOIN {{name}} + ON {{name}}.objectid = {{object}}.id + AND {{name}}.languageid = {languageid} + LEFT JOIN {{project}} + ON {{object}}.projectid = {{project}}.id + WHERE {{object}}.projectid = {projectid} + AND {{object}}.lastchange_userid = {userid} + ORDER BY {{object}}.lastchange_date DESC; +SQL + ); + + // Variablen setzen. + $sql->setInt( 'projectid', $this->projectid ); + + $sql->setInt( 'languageid', 0 ); + + $user = Session::getUser(); + $sql->setInt( 'userid', $user->userid ); + + return $sql->getAll(); + } + + + /** + * Ermittelt projektübergreifend die letzten Änderungen. + * + * @return array + */ + public static function getAllLastChanges() + { + $db = db_connection(); + + $sql = $db->sql( <<<SQL + SELECT {{object}}.id as objectid, + {{object}}.lastchange_date as lastchange_date, + {{object}}.filename as filename, + {{project}}.id as projectid, + {{project}}.name as projectname, + {{user}}.name as username, + {{user}}.id as userid, + {{user}}.mail as usermail, + {{user}}.fullname as userfullname + FROM {{object}} + LEFT JOIN {{project}} + ON {{object}}.projectid = {{project}}.id + LEFT JOIN {{user}} + ON {{user}}.id = {{object}}.lastchange_userid + ORDER BY {{object}}.lastchange_date DESC + LIMIT 50 +SQL + ); + + return $sql->getAll(); + } + + + + /** + * Ermittelt die letzten Änderung im Projekt. + * @return array + */ + public function getLastChanges() + { + + $db = db_connection(); + + $sql = $db->sql( <<<SQL + SELECT {{object}}.id as objectid, + {{object}}.lastchange_date as lastchange_date, + {{object}}.filename as filename, + {{object}}.typeid as typeid, + {{name}}.name as name, + {{user}}.name as username, + {{user}}.id as userid, + {{user}}.mail as usermail, + {{user}}.fullname as userfullname + FROM {{object}} + LEFT JOIN {{name}} + ON {{name}}.objectid = {{object}}.id + AND {{name}}.languageid = {languageid} + LEFT JOIN {{user}} + ON {{user}}.id = {{object}}.lastchange_userid + WHERE {{object}}.projectid = {projectid} + ORDER BY {{object}}.lastchange_date DESC +SQL + ); + + // Variablen setzen. + $sql->setInt( 'projectid', $this->projectid ); + + $languageid = $this->getDefaultLanguageId(); + $sql->setInt( 'languageid', $languageid ); + + return $sql->getAll(); + } + + /** + * Ermittelt alle Objekte vom gew�nschten Typ, die sic in + * diesem Projekt befinden. + * + * @see objectClasses/Object#getAllObjectIds() + * @param types Array + * @return Liste von Object-Ids + */ + public function getAllObjectIds( $types=array('folder','page','link','file','image','url','text') ) + { + $stmt = db()->sql( <<<SQL + SELECT id FROM {{object}} + WHERE projectid={projectid} + AND ( typeid ={is_folder} + OR typeid ={is_file} + OR typeid ={is_image} + OR typeid ={is_text} + OR typeid ={is_page} + OR typeid ={is_link} + OR typeid ={is_url} ) + ORDER BY orderid ASC +SQL + ); + + $stmt->setInt('projectid',$this->projectid ); + $stmt->setInt('is_folder',in_array('folder',$types)?BaseObject::TYPEID_FOLDER:0); + $stmt->setInt('is_file' ,in_array('file' ,$types)?BaseObject::TYPEID_FILE :0); + $stmt->setInt('is_image' ,in_array('image' ,$types)?BaseObject::TYPEID_IMAGE :0); + $stmt->setInt('is_text' ,in_array('text' ,$types)?BaseObject::TYPEID_TEXT :0); + $stmt->setInt('is_page' ,in_array('page' ,$types)?BaseObject::TYPEID_PAGE :0); + $stmt->setInt('is_link' ,in_array('link' ,$types)?BaseObject::TYPEID_LINK :0); + $stmt->setInt('is_url' ,in_array('url' ,$types)?BaseObject::TYPEID_URL :0); + + return( $stmt->getCol() ); + } + + + /** + * Liefert die Ids aller Ordner in diesem Projekt. + * + * @return array + */ + public function getAllFolders() + { + $db = db_connection(); + + $stmt = $db->sql('SELECT id FROM {{object}}'. + ' WHERE typeid='.BaseObject::TYPEID_FOLDER. + ' AND projectid={projectid}' ); + + $stmt->setInt( 'projectid',$this->projectid ); + + return( $stmt->getCol() ); + } + + +} + ?> \ No newline at end of file diff --git a/modules/cms-core/model/User.class.php b/modules/cms-core/model/User.class.php @@ -39,7 +39,6 @@ class User extends ModelBase var $desc; var $style; var $isAdmin; - var $projects = array(); var $rights; var $loginDate = 0; @@ -112,24 +111,21 @@ class User extends ModelBase */ public function setCurrent() { - $this->loadProjects(); $this->loginDate = time(); \Session::setUser( $this ); - $db = db_connection(); - - $sql = $db->sql( <<<SQL + $stmt = db()->sql( <<<SQL UPDATE {{user}} SET last_login={time} WHERE id={userid} SQL ); - $sql->setInt( 'time' ,time() ); - $sql->setInt( 'userid',$this->userid ); + $stmt->setInt( 'time' ,time() ); + $stmt->setInt( 'userid',$this->userid ); // Datenbankabfrage ausfuehren - $sql->query(); + $stmt->query(); } @@ -202,16 +198,6 @@ SQL } - /** - * Lädt die Liste alle Projekte, fuer die der Benutzer berechtigt ist und - * speichert diese in diesem Benutzerobjekt. - */ - function loadProjects() - { - $this->projects = $this->getReadableProjects(); - } - - /** * Ermittelt zu diesem Benutzer den Login-Token. @@ -260,11 +246,8 @@ SQL */ public static function loadWithName( $name ) { - global $conf; - $db = db_connection(); - // Benutzer �ber Namen suchen - $sql = $db->sql( 'SELECT id FROM {{user}}'. + $sql = db()->sql( 'SELECT id FROM {{user}}'. ' WHERE name={name}' ); //Html::debug($sql); $sql->setString( 'name',$name ); diff --git a/modules/cms-core/model/Value.class.php b/modules/cms-core/model/Value.class.php @@ -1466,7 +1466,7 @@ SQL if ( substr($inhalt,-4) == 'api/' ) $inhalt = substr($inhalt,0,-4); - $db = \Session::getDatabase(); + $db = db(); $params = array('dbid' =>$db->id, 'objectid' =>$this->page->objectid, 'modelid' =>$this->page->modelid, diff --git a/modules/cms-ui/action/TitleAction.class.php b/modules/cms-ui/action/TitleAction.class.php @@ -1,116 +1,116 @@ -<?php - -namespace cms\action; - -use cms\model\Project; -use cms\model\BaseObject; -use cms\model\Language; -use cms\model\Model; - -use Session; -use \Html; -// OpenRat Content Management System -// Copyright (C) 2002-2009 Jan Dankert, jandankert@jandankert.de -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - -/** - * Actionklasse zum Anzeigen der Titelleiste. - * - * @author Jan Dankert - * @package openrat.actions - */ -class TitleAction extends Action -{ - public $security = Action::SECURITY_GUEST; - - /** - * Fuellen der Variablen und Anzeigen der Titelleiste - */ - public function showView() - { - $this->setTemplateVar('buildinfo',OR_TITLE.' '.OR_VERSION.' - build '.config('build','build') ); - - $user = Session::getUser(); - - if ( !is_object($user) ) - { - $this->setTemplateVar('isLoggedIn' ,false ); - $this->setTemplateVar('userfullname',lang('NOT_LOGGED_IN') ); - return; // Kein Benutzer angemeldet. - } - - $this->setTemplateVar('isLoggedIn',true ); - - $db = Session::getDatabase(); - $this->setTemplateVar('dbname',$db->conf['name'].(readonly()?' ('.lang('readonly').')':'')); - $this->setTemplateVar('dbid' ,$db->id); - - $databases = array(); - - $this->setTemplateVar('username' ,$user->name ); - $this->setTemplateVar('userfullname',$user->fullname); - - // Urls zum Benutzerprofil und zum Abmelden - //$this->setTemplateVar('profile_url',Html::url( 'profile' )); - //$this->setTemplateVar('logout_url' ,Html::url( 'index','logout' )); - $this->setTemplateVar('isAdmin',$this->userIsAdmin() ); - - if ( config('interface','session','auto_extend') ) - { - $this->setTemplateVar('ping_url' ,Html::url('title','ping') ); - $this->setTemplateVar('ping_timeout',ini_get('session.gc_maxlifetime')-60 ); - } - } - - - public function pingView() - { - $this->setTemplateVar('ping',true ); - $this->setTemplateVar('time',date('r') ); - } - - - public function historyView() - { - $resultList = array(); - - $history = Session::get('history'); - - if ( is_array($history) ) - { - foreach( array_reverse($history) as $objectid ) - { - $o = new BaseObject( $objectid ); - $o->load(); - $resultList[$objectid] = array(); - $resultList[$objectid]['url'] = Html::url($o->getType(),'',$objectid); - $resultList[$objectid]['type'] = $o->getType(); - $resultList[$objectid]['name'] = $o->name; - $resultList[$objectid]['lastchange_date'] = $o->lastchangeDate; - - if ( $o->desc != '' ) - $resultList[$objectid]['desc'] = $o->desc; - else - $resultList[$objectid]['desc'] = lang('NO_DESCRIPTION_AVAILABLE'); - } - } - - $this->setTemplateVar( 'history',$resultList ); - } -} - +<?php + +namespace cms\action; + +use cms\model\Project; +use cms\model\BaseObject; +use cms\model\Language; +use cms\model\Model; + +use Session; +use \Html; +// OpenRat Content Management System +// Copyright (C) 2002-2009 Jan Dankert, jandankert@jandankert.de +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +/** + * Actionklasse zum Anzeigen der Titelleiste. + * + * @author Jan Dankert + * @package openrat.actions + */ +class TitleAction extends Action +{ + public $security = Action::SECURITY_GUEST; + + /** + * Fuellen der Variablen und Anzeigen der Titelleiste + */ + public function showView() + { + $this->setTemplateVar('buildinfo',OR_TITLE.' '.OR_VERSION.' - build '.config('build','build') ); + + $user = Session::getUser(); + + if ( !is_object($user) ) + { + $this->setTemplateVar('isLoggedIn' ,false ); + $this->setTemplateVar('userfullname',lang('NOT_LOGGED_IN') ); + return; // Kein Benutzer angemeldet. + } + + $this->setTemplateVar('isLoggedIn',true ); + + $db = db(); + $this->setTemplateVar('dbname',$db->conf['name'].(readonly()?' ('.lang('readonly').')':'')); + $this->setTemplateVar('dbid' ,$db->id); + + $databases = array(); + + $this->setTemplateVar('username' ,$user->name ); + $this->setTemplateVar('userfullname',$user->fullname); + + // Urls zum Benutzerprofil und zum Abmelden + //$this->setTemplateVar('profile_url',Html::url( 'profile' )); + //$this->setTemplateVar('logout_url' ,Html::url( 'index','logout' )); + $this->setTemplateVar('isAdmin',$this->userIsAdmin() ); + + if ( config('interface','session','auto_extend') ) + { + $this->setTemplateVar('ping_url' ,Html::url('title','ping') ); + $this->setTemplateVar('ping_timeout',ini_get('session.gc_maxlifetime')-60 ); + } + } + + + public function pingView() + { + $this->setTemplateVar('ping',true ); + $this->setTemplateVar('time',date('r') ); + } + + + public function historyView() + { + $resultList = array(); + + $history = Session::get('history'); + + if ( is_array($history) ) + { + foreach( array_reverse($history) as $objectid ) + { + $o = new BaseObject( $objectid ); + $o->load(); + $resultList[$objectid] = array(); + $resultList[$objectid]['url'] = Html::url($o->getType(),'',$objectid); + $resultList[$objectid]['type'] = $o->getType(); + $resultList[$objectid]['name'] = $o->name; + $resultList[$objectid]['lastchange_date'] = $o->lastchangeDate; + + if ( $o->desc != '' ) + $resultList[$objectid]['desc'] = $o->desc; + else + $resultList[$objectid]['desc'] = lang('NO_DESCRIPTION_AVAILABLE'); + } + } + + $this->setTemplateVar( 'history',$resultList ); + } +} + ?> \ No newline at end of file diff --git a/modules/configuration/Configuration.class.php b/modules/configuration/Configuration.class.php @@ -78,6 +78,11 @@ class Config } + /** + * @param $name + * @param null $default + * @return mixed|null + */ public function get( $name, $default = null ) { if ( isset( $this->config[ $name ] ) ) @@ -96,6 +101,21 @@ class Config } + /** + * @param $name + * @return bool + */ + public function has( $name ) + { + return isset( $this->config[ $name ] ); + } + + + /** + * @param $name + * @param bool $default + * @return bool + */ public function is( $name, $default = false ) { if ( isset( $this->config[ $name ] ) ) @@ -105,4 +125,13 @@ class Config } + /** + * @return array + */ + public function getConfig() { + + return $this->config; + } + + } \ No newline at end of file diff --git a/modules/configuration/ConfigurationLoader.class.php b/modules/configuration/ConfigurationLoader.class.php @@ -86,7 +86,7 @@ class ConfigurationLoader // Load include files. foreach ($customConfig['include'] as $key => $file) { - if ( $file[0] == '/') + if ( $file[0] == '/') // File begins with '?' ; // File has an absolute path - do not change. else // Prepend file path with our config directory. diff --git a/modules/database/Database.class.php b/modules/database/Database.class.php @@ -1,231 +1,224 @@ -<?php -// OpenRat Content Management System -// Copyright (C) 2002-2006 Jan Dankert, jandankert@jandankert.de -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -namespace database; -use database\driver\PDODriver; -use Logger; -use RuntimeException; - -/** - * Darstellung einer Datenbank-Verbindung. - * - * Fuer die echten DB-Aufrufe werden die entsprechenden - * Methoden des passenden Clients aufgerufen. - * - * Diese Klasse stammt urspruenglich aus dem PHP-Pear-DB-Projekt, wurde hier aber intensiv veraendert. - * - * @author Jan Dankert - * @package openrat.database - */ -class Database -{ - /** - * Datenbank-Id. - * - * @var String - */ - var $id; - - /** - * Konfiguration der Datenbank-Verbindung - * - * @var array - */ - var $conf; - - /** - * Kennzeichen, ob die Datenbank verf�gbar ist. - * - * @var Boolean - */ - var $available; - - /** - * Enth�lt eine Fehlermeldung (sofern verf�gbar). - * - * @var String - */ - var $error; - - /** - * Client. - * - * @var PDODriver - */ - var $client; - - /** - * Schalter, ob eine Transaktion begonnen wurde. - * @var boolean - */ - var $transactionInProgress = false; - - - /** - * Kontruktor. - * Erwartet die Datenbank-Konfiguration als Parameter. - * - * @param array Konfiguration der Verbindung - * @param boolean admin Wenn es eine Admin-DB-Verbindung werden soll, die auch DDL ausfuehren darf - */ - public function __construct( $dbconf,$admin=false ) - { - global $conf; - - $this->conf = $dbconf + $conf['database-default']['defaults']; // linksstehender Operator hat Priorität! - - if ( $admin ) - { - // Bevorzugung der Unter-Konfiguration 'update' - if ( isset($this->conf['update']) ) - $this->conf = $this->conf['update'] + $this->conf; // linksstehender Operator hat Priorität! - } - - $this->connect(); - } - - - /** - * Verbindung zur Datenbank aufbauen. - * - * @return bool Status - */ - public function connect() - { - // Ausfuehren des Systemkommandos vor Verbindungsaufbau - if (!empty($this->conf['cmd'])) - $this->executeSystemCommand( $this->conf['cmd'] ); - - // Client instanziieren - $this->client = new PDODriver(); - - // Verbindung aufbauen - $this->client->connect( $this->conf ); - - // SQL nach Verbindungsaufbau ausfuehren. - if ( ! empty($this->conf['connection_sql']) ) - { - $cmd = $this->conf['connection_sql']; - - $stmt = $this->sql($cmd); - - $ok = $stmt->execute(); - - if ( ! $ok ) - { - throw new RuntimeException( "Could not execute connection-query '".$cmd."'"); - } - } - - // Setting isolation level to "read committed". - // if another session is committing data, we want to read that immediatly - if ( $this->conf['persistent']) - { -// $sql = $this->sql('ROLLBACK'); -// $sql->execute(); -// $sql = $this->sql('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); -// $sql->execute(); - } - - - Logger::debug('Database connection established'); - - $this->available = true; - } - - /** - * Startet eine Transaktion. - * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts. - */ - public function start() - { - Logger::debug("Starting database transaction!"); - $this->transactionInProgress = true; - $this->client->start(); - } - - - /** - * Beendet und bestaetigt eine Transaktion. - * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts. - */ - public function commit() - { - if ( $this->transactionInProgress ) - { - Logger::debug("Committing database transaction!"); - $this->client->commit(); - $this->transactionInProgress = false; - } else { - Logger::warn("No Transaction in progress, ignoring commit request."); - } - } - - - - /** - * Setzt eine Transaktion zurueck. - * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts. - */ - public function rollback() - { - if ( $this->transactionInProgress ) - { - Logger::debug("Rolling back database transaction!"); - $this->client->rollback(); - $this->transactionInProgress = false; - } else { - Logger::warn("No Transaction in progress, ignoring rollback request."); - } - } - - - public function disconnect() - { - $this->client->disconnect(); - } - /** - * @param $sql string das SQL - * @return Statement - */ - public function sql($sql ) - { - return new Statement( $sql,$this->client,$this->conf); - } - - - private function executeSystemCommand( $cmd ) - { - $ausgabe = array(); - $rc = false; - - Logger::debug("Database command executing: " . $this->conf['cmd']); - exec($cmd, $ausgabe, $rc); - - foreach ($ausgabe as $zeile) - Logger::debug("Database command output: " . $zeile); - - if ($rc != 0) { - throw new RuntimeException('Command failed: ' . implode("", $ausgabe)); - } - } - -} - - +<?php +// OpenRat Content Management System +// Copyright (C) 2002-2006 Jan Dankert, jandankert@jandankert.de +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +namespace database; +use database\driver\PDODriver; +use Logger; +use RuntimeException; + +/** + * Darstellung einer Datenbank-Verbindung. + * + * Fuer die echten DB-Aufrufe werden die entsprechenden + * Methoden des passenden Clients aufgerufen. + * + * Diese Klasse stammt urspruenglich aus dem PHP-Pear-DB-Projekt, wurde hier aber intensiv veraendert. + * + * @author Jan Dankert + * @package openrat.database + */ +class Database +{ + /** + * Datenbank-Id. + * + * @var String + */ + var $id; + + /** + * Konfiguration der Datenbank-Verbindung + * + * @var array + */ + var $conf; + + /** + * Kennzeichen, ob die Datenbank verf�gbar ist. + * + * @var Boolean + */ + var $available; + + /** + * Enth�lt eine Fehlermeldung (sofern verf�gbar). + * + * @var String + */ + var $error; + + /** + * Client. + * + * @var PDODriver + */ + var $client; + + /** + * Schalter, ob eine Transaktion begonnen wurde. + * @var boolean + */ + var $transactionInProgress = false; + + + /** + * Kontruktor. + * Erwartet die Datenbank-Konfiguration als Parameter. + * + * @param array Konfiguration der Verbindung + * @param boolean admin Wenn es eine Admin-DB-Verbindung werden soll, die auch DDL ausfuehren darf + */ + public function __construct( $dbconf ) + { + global $conf; + + $this->conf = $dbconf + $conf['database-default']['defaults']; // linksstehender Operator hat Priorität! + + $this->connect(); + } + + + /** + * Verbindung zur Datenbank aufbauen. + * + * @return bool Status + */ + public function connect() + { + // Ausfuehren des Systemkommandos vor Verbindungsaufbau + if (!empty($this->conf['cmd'])) + $this->executeSystemCommand( $this->conf['cmd'] ); + + // Client instanziieren + $this->client = new PDODriver(); + + // Verbindung aufbauen + $this->client->connect( $this->conf ); + + // SQL nach Verbindungsaufbau ausfuehren. + if ( ! empty($this->conf['connection_sql']) ) + { + $cmd = $this->conf['connection_sql']; + + $stmt = $this->sql($cmd); + + $ok = $stmt->execute(); + + if ( ! $ok ) + { + throw new RuntimeException( "Could not execute connection-query '".$cmd."'"); + } + } + + // Setting isolation level to "read committed". + // if another session is committing data, we want to read that immediatly + if ( $this->conf['persistent']) + { +// $sql = $this->sql('ROLLBACK'); +// $sql->execute(); +// $sql = $this->sql('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); +// $sql->execute(); + } + + + Logger::debug('Database connection established'); + + $this->available = true; + } + + /** + * Startet eine Transaktion. + * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts. + */ + public function start() + { + Logger::debug("Starting database transaction!"); + $this->transactionInProgress = true; + $this->client->start(); + } + + + /** + * Beendet und bestaetigt eine Transaktion. + * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts. + */ + public function commit() + { + if ( $this->transactionInProgress ) + { + Logger::debug("Committing database transaction!"); + $this->client->commit(); + $this->transactionInProgress = false; + } else { + Logger::warn("No Transaction in progress, ignoring commit request."); + } + } + + + + /** + * Setzt eine Transaktion zurueck. + * Falls der Schalter 'transaction' nicht gesetzt ist, passiert nichts. + */ + public function rollback() + { + if ( $this->transactionInProgress ) + { + Logger::debug("Rolling back database transaction!"); + $this->client->rollback(); + $this->transactionInProgress = false; + } else { + Logger::warn("No Transaction in progress, ignoring rollback request."); + } + } + + + public function disconnect() + { + $this->client->disconnect(); + } + /** + * @param $sql string das SQL + * @return Statement + */ + public function sql($sql ) + { + return new Statement( $sql,$this->client,$this->conf); + } + + + private function executeSystemCommand( $cmd ) + { + $ausgabe = array(); + $rc = false; + + Logger::debug("Database command executing: " . $this->conf['cmd']); + exec($cmd, $ausgabe, $rc); + + foreach ($ausgabe as $zeile) + Logger::debug("Database command output: " . $zeile); + + if ($rc != 0) { + throw new RuntimeException('Command failed: ' . implode("", $ausgabe)); + } + } + +} + + ?> \ No newline at end of file diff --git a/modules/util/Http.class.php b/modules/util/Http.class.php @@ -426,7 +426,7 @@ class Http { if ( class_exists('Session')) { - $db = Session::getDatabase(); + $db = db(); if ( is_object( $db ) ) $db->rollback(); } diff --git a/modules/util/Session.class.php b/modules/util/Session.class.php @@ -21,12 +21,18 @@ use cms\model\User; class Session { + const KEY_DBID = 'dbid'; + const KEY_DB = 'database'; + const KEY_USER = 'userObject'; + const KEY_CONFIG = 'config'; + const PRAEFIX = 'ors_'; + public static function get( $var ) { $SESS = &$_SESSION; - if ( isset($SESS['ors_'.$var]) ) - return $SESS['ors_'.$var]; + if ( isset($SESS[self::PRAEFIX.$var]) ) + return $SESS[self::PRAEFIX.$var]; else return ''; } @@ -34,7 +40,7 @@ class Session public static function set( $var,$value ) { $SESS = &$_SESSION; - $SESS[ 'ors_'.$var ] = $value; + $SESS[ self::PRAEFIX.$var ] = $value; } @@ -43,12 +49,12 @@ class Session */ public static function getConfig() { - return Session::get('config'); + return Session::get(self::KEY_CONFIG); } public static function setConfig( $var ) { - Session::set('config',$var); + Session::set(self::KEY_CONFIG,$var); } @@ -59,12 +65,12 @@ class Session */ public static function getUser() { - return Session::get('userObject'); + return Session::get(self::KEY_USER); } public static function setUser( $var ) { - Session::set('userObject',$var); + Session::set(self::KEY_USER,$var); } @@ -73,12 +79,26 @@ class Session */ public static function getDatabase() { - return Session::get('database'); + return Session::get(self::KEY_DB); } public static function setDatabase( $var ) { - Session::set('database',$var); + Session::set(self::KEY_DB,$var); + } + + + /** + * @return String DB-Id + */ + public static function getDatabaseId() + { + return Session::get(self::KEY_DBID); + } + + public static function setDatabaseId( $var ) + { + Session::set(self::KEY_DBID,$var); } @@ -86,7 +106,7 @@ class Session * Schliesst die aktuelle Session * * Diese Funktion sollte so schnell wie moeglich aufgerufen werden, da vorher - * keine andere Seite (im Frameset!) geladen werden kann + * keine andere Seite (im Frameset oder parallele AJAX-Requests) geladen werden kann * Nach Aufruf dieser Methode sind keine Session-Zugriffe ueber diese Klasse mehr * moeglich. */ diff --git a/modules/util/config-default.php b/modules/util/config-default.php @@ -733,8 +733,6 @@ function createDefaultConfig() $conf['security']['disable_dynamic_code']=true; $conf['security']['show_system_info']=true; $conf['security']['use_post_token']=true; - $conf['security']['renew_session_login']=false; - $conf['security']['renew_session_logout']=false; $conf['security']['default'] = array(); $conf['security']['default']['username']=''; $conf['security']['default']['password']='';