openrat-cms

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

commit 3f1894f51547aa2b3739e80a722093b17901b0f0
parent 82180babe9baec8e15d1c22d6c5320c744638d53
Author: Jan Dankert <develop@jandankert.de>
Date:   Sat,  9 Nov 2019 01:10:57 +0100

Refactoring: New base class for all action classes.

Diffstat:
modules/cms-core/action/BaseAction.class.php | 19+++++++++++++++++++
modules/cms-core/action/ConfigurationAction.class.php | 2+-
modules/cms-core/action/ElementAction.class.php | 2+-
modules/cms-core/action/GroupAction.class.php | 2+-
modules/cms-core/action/GrouplistAction.class.php | 182++++++++++++++++++++++++++++++++++++++++----------------------------------------
modules/cms-core/action/LanguageAction.class.php | 2+-
modules/cms-core/action/LanguagelistAction.class.php | 2+-
modules/cms-core/action/LoginAction.class.php | 2+-
modules/cms-core/action/ModelAction.class.php | 2+-
modules/cms-core/action/ModellistAction.class.php | 220++++++++++++++++++++++++++++++++++++++++----------------------------------------
modules/cms-core/action/ObjectAction.class.php | 2+-
modules/cms-core/action/PageelementAction.class.php | 2+-
modules/cms-core/action/ProfileAction.class.php | 658++++++++++++++++++++++++++++++++++++++++----------------------------------------
modules/cms-core/action/ProjectAction.class.php | 2+-
modules/cms-core/action/ProjectlistAction.class.php | 2+-
modules/cms-core/action/SearchAction.class.php | 2+-
modules/cms-core/action/StartAction.class.php | 2662++++++++++++++++++++++++++++++++++++++++----------------------------------------
modules/cms-core/action/TemplateAction.class.php | 2+-
modules/cms-core/action/TemplatelistAction.class.php | 2+-
modules/cms-core/action/TreeAction.class.php | 2+-
modules/cms-core/action/UserAction.class.php | 2+-
modules/cms-core/action/UserlistAction.class.php | 174++++++++++++++++++++++++++++++++++++++++----------------------------------------
modules/cms-core/action/WebdavAction.class.php | 2438++++++++++++++++++++++++++++++++++++++++----------------------------------------
modules/cms-core/model/BaseObject.class.php | 13+++++++++++++
modules/cms-core/require.php | 1+
25 files changed, 3216 insertions(+), 3183 deletions(-)

diff --git a/modules/cms-core/action/BaseAction.class.php b/modules/cms-core/action/BaseAction.class.php @@ -0,0 +1,18 @@ +<?php + + +namespace cms\action { + + + /** + */ + class BaseAction extends Action + { + + public function __construct() + { + parent::__construct(); + + } + } +}+ \ No newline at end of file diff --git a/modules/cms-core/action/ConfigurationAction.class.php b/modules/cms-core/action/ConfigurationAction.class.php @@ -25,7 +25,7 @@ use Session; * @author Jan Dankert * @package openrat.actions */ -class ConfigurationAction extends Action +class ConfigurationAction extends BaseAction { public $security = Action::SECURITY_ADMIN; diff --git a/modules/cms-core/action/ElementAction.class.php b/modules/cms-core/action/ElementAction.class.php @@ -17,7 +17,7 @@ use Text; * * @author Jan Dankert */ -class ElementAction extends Action +class ElementAction extends BaseAction { public $security = Action::SECURITY_USER; diff --git a/modules/cms-core/action/GroupAction.class.php b/modules/cms-core/action/GroupAction.class.php @@ -34,7 +34,7 @@ use \Html; * @author Jan Dankert */ -class GroupAction extends Action +class GroupAction extends BaseAction { public $security = Action::SECURITY_ADMIN; diff --git a/modules/cms-core/action/GrouplistAction.class.php b/modules/cms-core/action/GrouplistAction.class.php @@ -1,92 +1,92 @@ -<?php - -namespace cms\action; - -use cms\model\Group; -// 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. - - -/** - * Action-Klasse zum Bearbeiten einer Benutzergruppe. - * - * @author $Author$ - * @version $Revision$ - * @package openrat.actions - */ - -class GrouplistAction extends Action -{ - public $security = Action::SECURITY_ADMIN; - - function __construct() - { - parent::__construct(); - } - - - /** - * Liste aller Gruppen. - */ - function showView() - { - $list = array(); - - foreach( Group::getAll() as $id=>$name ) - { - $list[$id] = array(); - $list[$id]['id' ] = $id; - $list[$id]['name'] = $name; - } - - $this->setTemplateVar('el', $list); - } - - - function editView() - { - $this->nextSubAction('show'); - } - - - - function addView() - { - } - - - function addPost() - { - if ( $this->getRequestVar('name') != '') - { - $this->group = new Group(); - $this->group->name = $this->getRequestVar('name'); - $this->group->add(); - $this->addNotice('group',$this->group->name,'ADDED','ok'); - $this->callSubAction('listing'); - } - else - { - $this->addValidationError('name'); - $this->callSubAction('add'); - } - } - - - - +<?php + +namespace cms\action; + +use cms\model\Group; +// 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. + + +/** + * Action-Klasse zum Bearbeiten einer Benutzergruppe. + * + * @author $Author$ + * @version $Revision$ + * @package openrat.actions + */ + +class GrouplistAction extends BaseAction +{ + public $security = Action::SECURITY_ADMIN; + + function __construct() + { + parent::__construct(); + } + + + /** + * Liste aller Gruppen. + */ + function showView() + { + $list = array(); + + foreach( Group::getAll() as $id=>$name ) + { + $list[$id] = array(); + $list[$id]['id' ] = $id; + $list[$id]['name'] = $name; + } + + $this->setTemplateVar('el', $list); + } + + + function editView() + { + $this->nextSubAction('show'); + } + + + + function addView() + { + } + + + function addPost() + { + if ( $this->getRequestVar('name') != '') + { + $this->group = new Group(); + $this->group->name = $this->getRequestVar('name'); + $this->group->add(); + $this->addNotice('group',$this->group->name,'ADDED','ok'); + $this->callSubAction('listing'); + } + else + { + $this->addValidationError('name'); + $this->callSubAction('add'); + } + } + + + + } \ No newline at end of file diff --git a/modules/cms-core/action/LanguageAction.class.php b/modules/cms-core/action/LanguageAction.class.php @@ -30,7 +30,7 @@ use \Html; * @author $Author$ * @package openrat.actions */ -class LanguageAction extends Action +class LanguageAction extends BaseAction { public $security = Action::SECURITY_USER; diff --git a/modules/cms-core/action/LanguagelistAction.class.php b/modules/cms-core/action/LanguagelistAction.class.php @@ -33,7 +33,7 @@ use \Html; * @author $Author$ * @package openrat.actions */ -class LanguagelistAction extends Action +class LanguagelistAction extends BaseAction { public $security = Action::SECURITY_USER; diff --git a/modules/cms-core/action/LoginAction.class.php b/modules/cms-core/action/LoginAction.class.php @@ -56,7 +56,7 @@ define('PROJECTID_ADMIN',-1); * @package openrat.actions */ -class LoginAction extends Action +class LoginAction extends BaseAction { public $security = Action::SECURITY_GUEST; diff --git a/modules/cms-core/action/ModelAction.class.php b/modules/cms-core/action/ModelAction.class.php @@ -33,7 +33,7 @@ use \Html; * @version $Revision$ * @package openrat.actions */ -class ModelAction extends Action +class ModelAction extends BaseAction { public $security = Action::SECURITY_USER; diff --git a/modules/cms-core/action/ModellistAction.class.php b/modules/cms-core/action/ModellistAction.class.php @@ -1,111 +1,111 @@ -<?php - -namespace cms\action; - -use cms\model\Model; -use cms\model\Project; -use Html; -use Session; - -// 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. - - -/** - * Action-Klasse zum Bearbeiten eines Projetmodells - * - * @author Jan Dankert - * @package openrat.actions - */ -class ModellistAction extends Action -{ - /** - * @var Project - */ - public $project; - - public $security = Action::SECURITY_USER; - - - function __construct() - { - parent::__construct(); - } - - - public function init() - { - - $this->project = new Project( $this->request->getRequestId()); - } - - - function showView() - { - $project = new Project( $this->project->projectid ); - - $list = array(); - foreach( $project->getModelIds() as $id ) - { - $m = new Model( $id ); - $m->load(); - - $list[$id]['id' ] = $id; - $list[$id]['name'] = $m->name; - - $list[$id]['is_default'] = $m->isDefault; - $list[$id]['select_url'] = Html::url('index','model',$id); - } - $this->setTemplateVar( 'el',$list ); - $this->setTemplateVar( 'add',$this->userIsAdmin() ); - } - - - /** - * Bearbeiten der Variante. - * Ermitteln aller Eigenschaften der Variante. - */ - function editView() - { - $this->nextSubAction('show'); - } - - - - - function addView() - { - } - - - function addPost() - { - $model = new Model(); - $model->projectid = $this->getRequestVar('projectid'); - $model->name = $this->getRequestVar('name'); - $model->add(); - - // Wenn kein Namen eingegeben, dann einen setzen. - if ( empty($model->name) ) - { - // Name ist "Variante <id>" - $model->name = lang('MODEL').' '.$model->modelid; - $model->save(); - } - } - +<?php + +namespace cms\action; + +use cms\model\Model; +use cms\model\Project; +use Html; +use Session; + +// 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. + + +/** + * Action-Klasse zum Bearbeiten eines Projetmodells + * + * @author Jan Dankert + * @package openrat.actions + */ +class ModellistAction extends BaseAction +{ + /** + * @var Project + */ + public $project; + + public $security = Action::SECURITY_USER; + + + function __construct() + { + parent::__construct(); + } + + + public function init() + { + + $this->project = new Project( $this->request->getRequestId()); + } + + + function showView() + { + $project = new Project( $this->project->projectid ); + + $list = array(); + foreach( $project->getModelIds() as $id ) + { + $m = new Model( $id ); + $m->load(); + + $list[$id]['id' ] = $id; + $list[$id]['name'] = $m->name; + + $list[$id]['is_default'] = $m->isDefault; + $list[$id]['select_url'] = Html::url('index','model',$id); + } + $this->setTemplateVar( 'el',$list ); + $this->setTemplateVar( 'add',$this->userIsAdmin() ); + } + + + /** + * Bearbeiten der Variante. + * Ermitteln aller Eigenschaften der Variante. + */ + function editView() + { + $this->nextSubAction('show'); + } + + + + + function addView() + { + } + + + function addPost() + { + $model = new Model(); + $model->projectid = $this->getRequestVar('projectid'); + $model->name = $this->getRequestVar('name'); + $model->add(); + + // Wenn kein Namen eingegeben, dann einen setzen. + if ( empty($model->name) ) + { + // Name ist "Variante <id>" + $model->name = lang('MODEL').' '.$model->modelid; + $model->save(); + } + } + } \ No newline at end of file diff --git a/modules/cms-core/action/ObjectAction.class.php b/modules/cms-core/action/ObjectAction.class.php @@ -21,7 +21,7 @@ use Session; * @author Jan Dankert */ -class ObjectAction extends Action +class ObjectAction extends BaseAction { public $security = Action::SECURITY_USER; diff --git a/modules/cms-core/action/PageelementAction.class.php b/modules/cms-core/action/PageelementAction.class.php @@ -46,7 +46,7 @@ use ValidationException; * @version $Revision$ * @package openrat.actions */ -class PageelementAction extends Action +class PageelementAction extends BaseAction { public $security = Action::SECURITY_USER; diff --git a/modules/cms-core/action/ProfileAction.class.php b/modules/cms-core/action/ProfileAction.class.php @@ -1,330 +1,330 @@ -<?php - -namespace cms\action; - - -// 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. -use cms\model\BaseObject; -use language\Language; -use LogicException; -use Mail; -use security\Base2n; -use \Session; - - -/** - * Action-Klasse zum Bearbeiten des Benutzerprofiles - * - * @author $Author$ - * @version $Revision$ - * @package openrat.actions - */ -class ProfileAction extends Action -{ - public $security = Action::SECURITY_USER; - - private $user; - var $defaultSubAction = 'edit'; - - /** - * Konstruktor. - * Setzen der Benutzer-Objektes. - */ - function __construct() - { - parent::__construct(); - - $this->user = Session::getUser(); - } - - - /** - * Abspeichern des Profiles - */ - function editPost() - { - $this->user->fullname = $this->getRequestVar('fullname'); - $this->user->tel = $this->getRequestVar('tel' ); - $this->user->desc = $this->getRequestVar('desc' ); - $this->user->style = $this->getRequestVar('style' ); - $this->user->language = $this->getRequestVar('language'); - $this->user->timezone = $this->getRequestVar('timezone'); - $this->user->hotp = $this->hasRequestVar('hotp' ); - $this->user->totp = $this->hasRequestVar('totp' ); - - - $this->setStyle( $this->user->style ); // Style sofort anwenden - Session::setUser( $this->user ); - - if ( !empty($this->user->fullname) ) - { - $this->user->save(); - $this->setStyle($this->user->style); - $this->addNotice('user',$this->user->name,'SAVED','ok'); - } - else - { - $this->addValidationError('fullname'); - } - - - // Ausgewählte Sprache sofort verwenden. - $l = $this->getRequestVar('language'); - - $this->setLanguage($l); - } - - - - /** - * Anzeigen einer Maske zum Ändern des Kennwortes. - */ - function pwView() - { - // Kennwortänderung funktioniert natürlich nur in der internen Datenbank. - // - // Hier wird festgestellt, ob der Benutzer sich über die interne Datenbank angemeldet hat. - // Nur dann kann man auch sein Kennwort ändern. - $user = $this->getUserFromSession(); - $pwchangePossible = in_array( strtolower($user->loginModuleName), array('cookieauth','internal')); - $this->setTemplateVar('pwchange_enabled', $pwchangePossible); - } - - - - /** - * Anzeige einer Maske zum Ändern der E-Mail-Adresse - */ - function mailView() - { - } - - - - /* - * Es wird eine E-Mail mit einem Freischaltcode an die eingegebene Adresse geschickt. - */ - function mailPost() - { - srand ((double)microtime()*1000003); - $code = rand(); // Zufalls-Freischaltcode erzeugen - $newMail = $this->getRequestVar('mail'); - - if ( empty($newMail) ) - { - // Keine E-Mail-Adresse eingegeben. - $this->addValidationError('mail'); - return; - } - else - { - // Der Freischaltcode wird in der Sitzung gespeichert. - Session::set('mailChangeCode',$code ); - Session::set('mailChangeMail',$newMail); - - // E-Mail an die neue Adresse senden. - $mail = new Mail( $newMail,'mail_change_code' ); - $mail->setVar('code',$code ); - $mail->setVar('name',$this->user->getName()); - - if ( $mail->send() ) - { - $this->addNotice('user',$this->user->name,'mail_sent',OR_NOTICE_OK); // Meldung - } - else - { - $this->addNotice('user',$this->user->name,'mail_not_sent',OR_NOTICE_ERROR,array(),$mail->error); // Meldung - return; - } - } - } - - - - /** - * Anzeige einer Maske, in die der Freischaltcode für das - * Ändern der E-Mail-Adresse eingetragen werden muss. - */ - function confirmmailView() - { - } - - - - /** - * Abspeichern der neuen E-Mail-Adresse - */ - function confirmmailPost() - { - $sessionCode = Session::get('mailChangeCode'); - $newMail = Session::get('mailChangeMail'); - $inputRegisterCode = $this->getRequestVar('code'); - - if ( $sessionCode == $inputRegisterCode ) - { - // Best�tigungscode stimmt �berein. - // E-Mail-Adresse �ndern. - $this->user->mail = $newMail; - $this->user->save(); - - $this->addNotice('user',$this->user->name,'SAVED',OR_NOTICE_OK); - } - else - { - // Best�tigungscode stimmt nicht. - $this->addValidationError('code','code_not_match'); - } - - } - - - - public function pwPost() - { - if ( ! $this->user->checkPassword( $this->getRequestVar('act_password') ) ) - { - $this->addValidationError('act_password'); - } - elseif ( $this->getRequestVar('password1') == '' ) - { - $this->addValidationError('password1'); - } - elseif ( $this->getRequestVar('password1') != $this->getRequestVar('password2') ) - { - $this->addValidationError('password2','PASSWORDS_DO_NOT_MATCH'); - } - elseif ( strlen($this->getRequestVar('password1'))<intval(config('security','password','min_length')) ) - { - $this->addValidationError('password1','PASSWORD_MINLENGTH',array('minlength'=>config('security','password','min_length'))); - } - else - { - $this->user->setPassword( $this->getRequestVar('password1') ); - $this->addNotice('user',$this->user->name,'SAVED','ok'); - } - } - - - - /** - * Anzeige aller Benutzer-Eigenschaften. - */ - function editView() - { - $issuer = urlencode(config('application','operator')); - $account = $this->user->name.'@'.$_SERVER['SERVER_NAME']; - - $base32 = new Base2n(5, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', FALSE, TRUE, TRUE); - $secret = $base32->encode(hex2bin($this->user->otpSecret)); - $counter = $this->user->hotpCount; - - $this->setTemplateVars( $this->user->getProperties() ); - - $this->setTemplateVar( 'allstyles',$this->user->getAvailableStyles() ); - - $this->setTemplateVar('timezone_list',timezone_identifiers_list() ); - - $languages = explode(',',config('i18n','available')); - foreach($languages as $id=>$name) - { - unset($languages[$id]); - $languages[$name] = $name; - } - $this->setTemplateVar('language_list',$languages); - - $this->setTemplateVars( - $this->user->getProperties() + - array('totpSecretUrl' => "otpauth://totp/{$issuer}:{$account}?secret={$secret}&issuer={$issuer}", - 'hotpSecretUrl' => "otpauth://hotp/{$issuer}:{$account}?secret={$secret}&issuer={$issuer}&counter={$counter}" - ) - ); - - - } - - - - /** - * Anzeige aller Gruppen des angemeldeten Benutzers. - * - */ - function membershipsView() - { - $this->setTemplateVar( 'groups',$this->user->getGroups() ); - } - - - - /** - * @param String $name Menüpunkt - * @return boolean true, falls Menüpunkt zugelassen - */ - function checkMenu( $name ) - { - global $conf; - - switch( $name ) - { - case 'pwchange': - // Die Funktion "Kennwort setzen" ist nur aktiv, wenn als Authentifizierungs-Backend - // auch die interne Benutzerdatenbank eingesetzt wird. - return @$conf['security']['auth']['type'] == 'database' - && !@$conf['security']['auth']['userdn']; - - default: - return true; - } - } - - /** - * Setzt eine Sprache für den Benutzer. - * - * @param $l string Sprache - */ - public function setLanguage($l) - { - $conf = Session::getConfig(); - $language = new \language\Language(); - $conf['language'] = $language->getLanguage($l,PRODUCTION); - $conf['language']['language_code'] = $l; - Session::setConfig($conf); - } - - - - /** - * Ermittelt die letzten Änderungen, die durch den aktuellen Benutzer in allen Projekten gemacht worden sind. - */ - public function historyView() - { - $lastChanges = $this->user->getLastChanges(); - - $timeline = array(); - - foreach( $lastChanges as $entry ) - { - $timeline[ $entry['objectid'] ] = $entry; - $baseObject = new BaseObject( $entry['objectid']); - $baseObject->objectLoad(); - $timeline[ $entry['objectid'] ]['type'] = $baseObject->getType(); - } - $this->setTemplateVar('timeline', $timeline); - } - - +<?php + +namespace cms\action; + + +// 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. +use cms\model\BaseObject; +use language\Language; +use LogicException; +use Mail; +use security\Base2n; +use \Session; + + +/** + * Action-Klasse zum Bearbeiten des Benutzerprofiles + * + * @author $Author$ + * @version $Revision$ + * @package openrat.actions + */ +class ProfileAction extends BaseAction +{ + public $security = Action::SECURITY_USER; + + private $user; + var $defaultSubAction = 'edit'; + + /** + * Konstruktor. + * Setzen der Benutzer-Objektes. + */ + function __construct() + { + parent::__construct(); + + $this->user = Session::getUser(); + } + + + /** + * Abspeichern des Profiles + */ + function editPost() + { + $this->user->fullname = $this->getRequestVar('fullname'); + $this->user->tel = $this->getRequestVar('tel' ); + $this->user->desc = $this->getRequestVar('desc' ); + $this->user->style = $this->getRequestVar('style' ); + $this->user->language = $this->getRequestVar('language'); + $this->user->timezone = $this->getRequestVar('timezone'); + $this->user->hotp = $this->hasRequestVar('hotp' ); + $this->user->totp = $this->hasRequestVar('totp' ); + + + $this->setStyle( $this->user->style ); // Style sofort anwenden + Session::setUser( $this->user ); + + if ( !empty($this->user->fullname) ) + { + $this->user->save(); + $this->setStyle($this->user->style); + $this->addNotice('user',$this->user->name,'SAVED','ok'); + } + else + { + $this->addValidationError('fullname'); + } + + + // Ausgewählte Sprache sofort verwenden. + $l = $this->getRequestVar('language'); + + $this->setLanguage($l); + } + + + + /** + * Anzeigen einer Maske zum Ändern des Kennwortes. + */ + function pwView() + { + // Kennwortänderung funktioniert natürlich nur in der internen Datenbank. + // + // Hier wird festgestellt, ob der Benutzer sich über die interne Datenbank angemeldet hat. + // Nur dann kann man auch sein Kennwort ändern. + $user = $this->getUserFromSession(); + $pwchangePossible = in_array( strtolower($user->loginModuleName), array('cookieauth','internal')); + $this->setTemplateVar('pwchange_enabled', $pwchangePossible); + } + + + + /** + * Anzeige einer Maske zum Ändern der E-Mail-Adresse + */ + function mailView() + { + } + + + + /* + * Es wird eine E-Mail mit einem Freischaltcode an die eingegebene Adresse geschickt. + */ + function mailPost() + { + srand ((double)microtime()*1000003); + $code = rand(); // Zufalls-Freischaltcode erzeugen + $newMail = $this->getRequestVar('mail'); + + if ( empty($newMail) ) + { + // Keine E-Mail-Adresse eingegeben. + $this->addValidationError('mail'); + return; + } + else + { + // Der Freischaltcode wird in der Sitzung gespeichert. + Session::set('mailChangeCode',$code ); + Session::set('mailChangeMail',$newMail); + + // E-Mail an die neue Adresse senden. + $mail = new Mail( $newMail,'mail_change_code' ); + $mail->setVar('code',$code ); + $mail->setVar('name',$this->user->getName()); + + if ( $mail->send() ) + { + $this->addNotice('user',$this->user->name,'mail_sent',OR_NOTICE_OK); // Meldung + } + else + { + $this->addNotice('user',$this->user->name,'mail_not_sent',OR_NOTICE_ERROR,array(),$mail->error); // Meldung + return; + } + } + } + + + + /** + * Anzeige einer Maske, in die der Freischaltcode für das + * Ändern der E-Mail-Adresse eingetragen werden muss. + */ + function confirmmailView() + { + } + + + + /** + * Abspeichern der neuen E-Mail-Adresse + */ + function confirmmailPost() + { + $sessionCode = Session::get('mailChangeCode'); + $newMail = Session::get('mailChangeMail'); + $inputRegisterCode = $this->getRequestVar('code'); + + if ( $sessionCode == $inputRegisterCode ) + { + // Best�tigungscode stimmt �berein. + // E-Mail-Adresse �ndern. + $this->user->mail = $newMail; + $this->user->save(); + + $this->addNotice('user',$this->user->name,'SAVED',OR_NOTICE_OK); + } + else + { + // Best�tigungscode stimmt nicht. + $this->addValidationError('code','code_not_match'); + } + + } + + + + public function pwPost() + { + if ( ! $this->user->checkPassword( $this->getRequestVar('act_password') ) ) + { + $this->addValidationError('act_password'); + } + elseif ( $this->getRequestVar('password1') == '' ) + { + $this->addValidationError('password1'); + } + elseif ( $this->getRequestVar('password1') != $this->getRequestVar('password2') ) + { + $this->addValidationError('password2','PASSWORDS_DO_NOT_MATCH'); + } + elseif ( strlen($this->getRequestVar('password1'))<intval(config('security','password','min_length')) ) + { + $this->addValidationError('password1','PASSWORD_MINLENGTH',array('minlength'=>config('security','password','min_length'))); + } + else + { + $this->user->setPassword( $this->getRequestVar('password1') ); + $this->addNotice('user',$this->user->name,'SAVED','ok'); + } + } + + + + /** + * Anzeige aller Benutzer-Eigenschaften. + */ + function editView() + { + $issuer = urlencode(config('application','operator')); + $account = $this->user->name.'@'.$_SERVER['SERVER_NAME']; + + $base32 = new Base2n(5, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', FALSE, TRUE, TRUE); + $secret = $base32->encode(hex2bin($this->user->otpSecret)); + $counter = $this->user->hotpCount; + + $this->setTemplateVars( $this->user->getProperties() ); + + $this->setTemplateVar( 'allstyles',$this->user->getAvailableStyles() ); + + $this->setTemplateVar('timezone_list',timezone_identifiers_list() ); + + $languages = explode(',',config('i18n','available')); + foreach($languages as $id=>$name) + { + unset($languages[$id]); + $languages[$name] = $name; + } + $this->setTemplateVar('language_list',$languages); + + $this->setTemplateVars( + $this->user->getProperties() + + array('totpSecretUrl' => "otpauth://totp/{$issuer}:{$account}?secret={$secret}&issuer={$issuer}", + 'hotpSecretUrl' => "otpauth://hotp/{$issuer}:{$account}?secret={$secret}&issuer={$issuer}&counter={$counter}" + ) + ); + + + } + + + + /** + * Anzeige aller Gruppen des angemeldeten Benutzers. + * + */ + function membershipsView() + { + $this->setTemplateVar( 'groups',$this->user->getGroups() ); + } + + + + /** + * @param String $name Menüpunkt + * @return boolean true, falls Menüpunkt zugelassen + */ + function checkMenu( $name ) + { + global $conf; + + switch( $name ) + { + case 'pwchange': + // Die Funktion "Kennwort setzen" ist nur aktiv, wenn als Authentifizierungs-Backend + // auch die interne Benutzerdatenbank eingesetzt wird. + return @$conf['security']['auth']['type'] == 'database' + && !@$conf['security']['auth']['userdn']; + + default: + return true; + } + } + + /** + * Setzt eine Sprache für den Benutzer. + * + * @param $l string Sprache + */ + public function setLanguage($l) + { + $conf = Session::getConfig(); + $language = new \language\Language(); + $conf['language'] = $language->getLanguage($l,PRODUCTION); + $conf['language']['language_code'] = $l; + Session::setConfig($conf); + } + + + + /** + * Ermittelt die letzten Änderungen, die durch den aktuellen Benutzer in allen Projekten gemacht worden sind. + */ + public function historyView() + { + $lastChanges = $this->user->getLastChanges(); + + $timeline = array(); + + foreach( $lastChanges as $entry ) + { + $timeline[ $entry['objectid'] ] = $entry; + $baseObject = new BaseObject( $entry['objectid']); + $baseObject->objectLoad(); + $timeline[ $entry['objectid'] ]['type'] = $baseObject->getType(); + } + $this->setTemplateVar('timeline', $timeline); + } + + } \ No newline at end of file diff --git a/modules/cms-core/action/ProjectAction.class.php b/modules/cms-core/action/ProjectAction.class.php @@ -29,7 +29,7 @@ use cms\model\Folder; * @version $Revision$ * @package openrat.actions */ -class ProjectAction extends Action +class ProjectAction extends BaseAction { public $security = Action::SECURITY_ADMIN; diff --git a/modules/cms-core/action/ProjectlistAction.class.php b/modules/cms-core/action/ProjectlistAction.class.php @@ -30,7 +30,7 @@ use cms\model\Project; * @version $Revision$ * @package openrat.actions */ -class ProjectlistAction extends Action +class ProjectlistAction extends BaseAction { public $security = Action::SECURITY_USER; diff --git a/modules/cms-core/action/SearchAction.class.php b/modules/cms-core/action/SearchAction.class.php @@ -49,7 +49,7 @@ define('SEARCH_FLAG_VALUE' ,16); * @version $Revision$ * @package openrat.actions */ -class SearchAction extends Action +class SearchAction extends BaseAction { public $security = Action::SECURITY_USER; diff --git a/modules/cms-core/action/StartAction.class.php b/modules/cms-core/action/StartAction.class.php @@ -1,1332 +1,1332 @@ -<?php - -namespace cms\action; - -use cms\model\User; -use cms\model\Project; -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 Http; -use Logger; -use \security\Password; -use Session; -use \Html; -use \Mail; - -// 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. - - -if ( !defined('PROJECTID_ADMIN') ) - define('PROJECTID_ADMIN',-1); - -/** - * Action-Klasse fuer die Start-Action - * @author $Author$ - * @version $Revision$ - * @package openrat.actions - * @deprecated - */ - -class StartAction extends Action -{ - public $security = Action::SECURITY_USER; - - var $mustChangePassword = false; - - function setDb( $dbid ) - { - global $conf; - - if ( !isset($conf['database'][$dbid] )) - throw new \LogicException( 'unknown DB-Id: '.$dbid ); - - $db = db_connection(); - if ( is_object($db) ) - { - $db->rollback(); - } - - $db = new Database( $conf['database'][$dbid] ); - $db->id = $dbid; - $db->start(); - Session::setDatabase( $db ); - } - - - - function checkForDb() - { - global $conf; - $dbid = $this->getRequestVar('dbid'); - - if ( $dbid != '' ) - $this->setDb( $dbid ); - } - - - - 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 ); - } - - - - function checkLogin( $name,$pw,$pw1,$pw2 ) - { - Logger::debug( "login user $name" ); - - global $conf; - global $SESS; - - unset( $SESS['user'] ); - - - $db = db_connection(); - - 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 ); - - $this->mustChangePassword = $user->mustChangePassword; - - if ( $this->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; - $this->mustChangePassword = false; - $user->mustChangePassword = false; - } - } - - // Falls Login erfolgreich - if ( $ok ) - { - // Login war erfolgreich! - $user->load(); - $user->setCurrent(); - Logger::info( 'login successful' ); - - return true; - } - else - { - Logger::info( "login for user $name failed" ); - - return false; - } - } - - - - /** - * Anzeigen der Loginmaske. - * - * Es wird nur die Loginmaske angezeigt. - * Hier nie "304 not modified" setzen, da sonst keine - * Login-Fehlermeldung erscheinen kann - */ - function loginView() - { - 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'); - } - - 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'].' ('.$dbconf['host'].')' ); - } - - $openid_provider = array(); - foreach( explode(',',$conf['security']['openid']['provider']) 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($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 ); - - $db = Session::getDatabase(); - if ( is_object($db) ) - $this->setTemplateVar('actdbid',$db->id); - elseif( isset($this->templateVars['actid']) ) - ; - else - $this->setTemplateVar('actdbid',$conf['database']['default']); - - - // Den Benutzernamen aus dem Client-Zertifikat lesen und in die Loginmaske eintragen. - $ssl_user_var = $conf['security']['ssl']['user_var']; - if ( !empty($ssl_user_var) ) - { - $username = getenv( $ssl_user_var ); - - if ( empty($username) ) - { - echo lang('ERROR_LOGIN_BROKEN_SSL_CERT'); - Logger::warn( 'no username in SSL client certificate (var='.$ssl_user_var.').' ); - exit; - } - - // Benutzername ist in Eingabemaske unveränderlich - $this->setTemplateVar('force_username',$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']); - } - - - - /** - * Setzt die neue Projekt-Id und lädt die Workbench neu. - * - */ - public function projectmenuPost() - { - - $this->evaluateRequestVars( array('projectid'=>$this->getRequestId()) ); - } - - - /** - * Erzeugt ein Projekt-Auswahlmenue. - */ - public function projectmenuView() - { - $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->getReadableProjects(); - - $list = array(); - - foreach( $projects as $id=>$name ) - { - $p = array(); - $p['url' ] = Html::url('start','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); - } - - //$this->metaValues(); - } - - - - /** - * Erzeugt eine Anwendungsliste. - */ - public function applicationsView() - { - 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> - */ - function openid() - { - global $conf; - $openId = Session::get('openid'); - - if ( !$openId->checkAuthentication() ) - { - $this->addNotice('user',$openId->user,'LOGIN_OPENID_FAILED',OR_NOTICE_ERROR,array('name'=>$openId->user),array($openId->error) ); - $this->addValidationError('openid_url',''); - $this->callSubAction('showlogin'); - return; - } - - //Html::debug($openId); - - // Anmeldung wurde mit "is_valid:true" best�tigt. - // Der Benutzer ist jetzt eingeloggt. - $username = $openId->getUserFromIdentiy(); - - if ( empty($username) ) - { - // Es konnte kein Benutzername ermittelt werden. - $this->addNotice('user',$username,'LOGIN_OPENID_FAILED','error',array('name'=>$username) ); - $this->addValidationError('openid_url',''); - $this->callSubAction('showlogin'); - return; - } - - $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 - { - // Benutzer ist nicht in Benutzertabelle vorhanden (und angelegt werden soll er auch nicht). - $this->addNotice('user',$username,'LOGIN_OPENID_FAILED','error',array('name'=>$username) ); - $this->addValidationError('openid_url',''); - $this->callSubAction('showlogin'); - return; - } - } - else - { - // Benutzer ist bereits vorhanden. - if ( @$conf['security']['openid']['update_user']) - { - $user->fullname = $openId->info['fullname']; - $user->mail = $openId->info['email']; - $user->save(); - } - } - - $user->setCurrent(); // Benutzer ist jetzt in der Sitzung. - } - - - /** - * Login. - */ - function loginPost() - { - 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); - $openId->redirect(); - } - - - // Ermitteln, ob der Baum angezeigt werden soll - // Ist die Breite zu klein, dann wird der Baum nicht angezeigt - Session::set('showtree',intval($this->getRequestVar('screenwidth')) > $conf['interface']['min_width'] ); - - $loginOk = $this->checkLogin( $loginName, - $loginPassword, - $newPassword1, - $newPassword2 ); - - usleep(hexdec(Password::randomHexString(1))); // delay: 0-255 ms - - if ( !$loginOk ) - { - - if ( $this->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',''); - } - - Logger::debug("Login failed for user '$loginName'"); - - $this->callSubAction('login'); - return; - } - else - { - Logger::debug("Login successful for user '$loginName'"); - - // Anmeldung erfolgreich. - if ( config('security','renew_session_login') ) - $this->recreateSession(); - - $user = Session::getUser(); - $this->addNotice('user',$user->name,'LOGIN_OK',OR_NOTICE_OK,array('name'=>$user->fullname)); - } - - // Benutzer ist angemeldet - } - - - /** - * 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['alias' ]) && - $subActionName != 'menu' ) - { - $engine = new template_engine\TemplateEngine(); - $engine->compile( strtolower(str_replace('Action','',$actionName)).'/'.$subActionName); - } - } - } - } - - // Umleiten auf eine definierte URL.s - $redirect_url = @$conf['security']['logout']['redirect_url']; - - if ( !empty($redirect_url) ) - { - header('Location: '.$redirect_url); - exit; - } - } - - - - /** - * Benutzer meldet sich ab. - */ - function logoutView() - { - } - - - /** - * Ausw�hlen der Administration. - */ - function administrationPost() - { - } - - - - /** - * Auswaehlen des Benutzer-Profiles. - */ - function profilePost() - { - } - - - - /** - * Auswaehlen der Startseite. - */ - function startPost() - { - } - - - - /** - * 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 languagePost() - { - $user = Session::getUser(); - if ( ! is_object($user) ) - { - throw new \LogicException('No user in session'); - return; - } - - $this->evaluateRequestVars( array(REQ_PARAM_LANGUAGE_ID=>$this->getRequestId()) ); - } - - - function modelPost() - { - $user = Session::getUser(); - if ( ! is_object($user) ) - { - $this->callSubAction('show'); - return; - } - - $this->evaluateRequestVars( array(REQ_PARAM_MODEL_ID=>$this->getRequestId()) ); - } - - - /** - * Auswerten der Request-Variablen. - */ - private function evaluateRequestVars( $add = array() ) - { - } - - - function switchuser() - { - $user = Session::getUser(); - - if ( ! $user->isAdmin ) - throw new \SecurityException(""); - - $this->recreateSession(); - - $newUser = new User( $this->getRequestId() ); - $newUser->load(); - - $newUser->setCurrent(); - } - - - function showView() - { - 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 ); - - $this->metaValues(); - } - - - - 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. - */ - function register() - { - - } - - - /** - * Registriercode erzeugen und per E-Mail dem Benutzer mitteilen. - * Maske anzeigen, damit Benuter Registriercode anzeigen kann. - */ - public function registercode() - { - $email_address = $this->getRequestVar('mail','mail'); - - if ( ! Mail::checkAddress($email_address) ) - { - $this->addValidationError('mail'); - $this->setTemplateVar('mail',$email_address); - $this->callSubAction('register'); - return; - } - - - srand ((double)microtime()*1000003); - $registerCode = rand(); - - Session::set('registerCode',$registerCode ); - - // 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); - $this->callSubAction('register'); - return; - } - } - - - - public function registeruserdata() - { - global $conf; - - Session::set('registerMail',$this->getRequestVar('mail') ); - // TODO: Attribut "Password" abfragen - 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']); - } - - - /** - * Benutzerregistierung. - * Benutzer hat Best�tigungscode erhalten und eingegeben. - */ - public function registercommit() - { - 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'); - $this->callSubAction('registeruserdata'); - return; - } - - // Best�tigungscode stimmt �berein. - // Neuen Benutzer anlegen. - - if ( !$this->hasRequestVar('username') ) - { - $this->addValidationError('username'); - $this->callSubAction('registeruserdata'); - return; - } - - $user = User::loadWithName( $this->getRequestVar('username') ); - if ( $user->isValid() ) - { - $this->addValidationError('username','USER_ALREADY_IN_DATABASE'); - $this->callSubAction('registeruserdata'); - return; - } - - if ( strlen($this->getRequestVar('password')) < $conf['security']['password']['min_length'] ) - { - $this->addValidationError('password','password_minlength',array('minlength'=>$conf['security']['password']['min_length'])); - $this->callSubAction('registeruserdata'); - 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. - */ - public function password() - { - global $conf; - - // TODO: Attribut "Password" abfragen - 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']); - - } - - - /* - 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. - */ - public function passwordcode() - { - if ( !$this->hasRequestVar('username') ) - { - $this->addValidationError('username'); - $this->callSubAction('password'); - return; - } - - $this->checkForDb(); - - $user = User::loadWithName( $this->getRequestVar("username") ); - - Password::delay(); - - // Html::debug($user); - 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. - * - */ - public function passwordinputcode() - { - - } - - - /** - * Neues Kennwort erzeugen und dem Benutzer zusenden. - */ - public function passwordcommit() - { - $username = $this->getSessionVar("password_commit_name"); - - if ( $this->getRequestVar("code")=='' || - $this->getSessionVar("password_commit_code") != $this->getRequestVar("code") ) - { - $this->addValidationError('code','PASSWORDCODE_NOT_MATCH'); - $this->callSubAction('passwordinputcode'); - 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. - */ - private 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 - } - } - - - - - - - /** - * Ermittelt die letzten Änderungen, die durch den aktuellen Benutzer im aktuellen Projekt gemacht worden sind. - */ - public function userprojecttimelineView() - { - //$project = Session::getProject(); - //$result = $project->getMyLastChanges(); - $result = array(); - - $this->setTemplateVar('timeline', $result); - } - - -} - - +<?php + +namespace cms\action; + +use cms\model\User; +use cms\model\Project; +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 Http; +use Logger; +use \security\Password; +use Session; +use \Html; +use \Mail; + +// 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. + + +if ( !defined('PROJECTID_ADMIN') ) + define('PROJECTID_ADMIN',-1); + +/** + * Action-Klasse fuer die Start-Action + * @author $Author$ + * @version $Revision$ + * @package openrat.actions + * @deprecated + */ + +class StartAction extends BaseAction +{ + public $security = Action::SECURITY_USER; + + var $mustChangePassword = false; + + function setDb( $dbid ) + { + global $conf; + + if ( !isset($conf['database'][$dbid] )) + throw new \LogicException( 'unknown DB-Id: '.$dbid ); + + $db = db_connection(); + if ( is_object($db) ) + { + $db->rollback(); + } + + $db = new Database( $conf['database'][$dbid] ); + $db->id = $dbid; + $db->start(); + Session::setDatabase( $db ); + } + + + + function checkForDb() + { + global $conf; + $dbid = $this->getRequestVar('dbid'); + + if ( $dbid != '' ) + $this->setDb( $dbid ); + } + + + + 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 ); + } + + + + function checkLogin( $name,$pw,$pw1,$pw2 ) + { + Logger::debug( "login user $name" ); + + global $conf; + global $SESS; + + unset( $SESS['user'] ); + + + $db = db_connection(); + + 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 ); + + $this->mustChangePassword = $user->mustChangePassword; + + if ( $this->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; + $this->mustChangePassword = false; + $user->mustChangePassword = false; + } + } + + // Falls Login erfolgreich + if ( $ok ) + { + // Login war erfolgreich! + $user->load(); + $user->setCurrent(); + Logger::info( 'login successful' ); + + return true; + } + else + { + Logger::info( "login for user $name failed" ); + + return false; + } + } + + + + /** + * Anzeigen der Loginmaske. + * + * Es wird nur die Loginmaske angezeigt. + * Hier nie "304 not modified" setzen, da sonst keine + * Login-Fehlermeldung erscheinen kann + */ + function loginView() + { + 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'); + } + + 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'].' ('.$dbconf['host'].')' ); + } + + $openid_provider = array(); + foreach( explode(',',$conf['security']['openid']['provider']) 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($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 ); + + $db = Session::getDatabase(); + if ( is_object($db) ) + $this->setTemplateVar('actdbid',$db->id); + elseif( isset($this->templateVars['actid']) ) + ; + else + $this->setTemplateVar('actdbid',$conf['database']['default']); + + + // Den Benutzernamen aus dem Client-Zertifikat lesen und in die Loginmaske eintragen. + $ssl_user_var = $conf['security']['ssl']['user_var']; + if ( !empty($ssl_user_var) ) + { + $username = getenv( $ssl_user_var ); + + if ( empty($username) ) + { + echo lang('ERROR_LOGIN_BROKEN_SSL_CERT'); + Logger::warn( 'no username in SSL client certificate (var='.$ssl_user_var.').' ); + exit; + } + + // Benutzername ist in Eingabemaske unveränderlich + $this->setTemplateVar('force_username',$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']); + } + + + + /** + * Setzt die neue Projekt-Id und lädt die Workbench neu. + * + */ + public function projectmenuPost() + { + + $this->evaluateRequestVars( array('projectid'=>$this->getRequestId()) ); + } + + + /** + * Erzeugt ein Projekt-Auswahlmenue. + */ + public function projectmenuView() + { + $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->getReadableProjects(); + + $list = array(); + + foreach( $projects as $id=>$name ) + { + $p = array(); + $p['url' ] = Html::url('start','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); + } + + //$this->metaValues(); + } + + + + /** + * Erzeugt eine Anwendungsliste. + */ + public function applicationsView() + { + 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> + */ + function openid() + { + global $conf; + $openId = Session::get('openid'); + + if ( !$openId->checkAuthentication() ) + { + $this->addNotice('user',$openId->user,'LOGIN_OPENID_FAILED',OR_NOTICE_ERROR,array('name'=>$openId->user),array($openId->error) ); + $this->addValidationError('openid_url',''); + $this->callSubAction('showlogin'); + return; + } + + //Html::debug($openId); + + // Anmeldung wurde mit "is_valid:true" best�tigt. + // Der Benutzer ist jetzt eingeloggt. + $username = $openId->getUserFromIdentiy(); + + if ( empty($username) ) + { + // Es konnte kein Benutzername ermittelt werden. + $this->addNotice('user',$username,'LOGIN_OPENID_FAILED','error',array('name'=>$username) ); + $this->addValidationError('openid_url',''); + $this->callSubAction('showlogin'); + return; + } + + $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 + { + // Benutzer ist nicht in Benutzertabelle vorhanden (und angelegt werden soll er auch nicht). + $this->addNotice('user',$username,'LOGIN_OPENID_FAILED','error',array('name'=>$username) ); + $this->addValidationError('openid_url',''); + $this->callSubAction('showlogin'); + return; + } + } + else + { + // Benutzer ist bereits vorhanden. + if ( @$conf['security']['openid']['update_user']) + { + $user->fullname = $openId->info['fullname']; + $user->mail = $openId->info['email']; + $user->save(); + } + } + + $user->setCurrent(); // Benutzer ist jetzt in der Sitzung. + } + + + /** + * Login. + */ + function loginPost() + { + 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); + $openId->redirect(); + } + + + // Ermitteln, ob der Baum angezeigt werden soll + // Ist die Breite zu klein, dann wird der Baum nicht angezeigt + Session::set('showtree',intval($this->getRequestVar('screenwidth')) > $conf['interface']['min_width'] ); + + $loginOk = $this->checkLogin( $loginName, + $loginPassword, + $newPassword1, + $newPassword2 ); + + usleep(hexdec(Password::randomHexString(1))); // delay: 0-255 ms + + if ( !$loginOk ) + { + + if ( $this->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',''); + } + + Logger::debug("Login failed for user '$loginName'"); + + $this->callSubAction('login'); + return; + } + else + { + Logger::debug("Login successful for user '$loginName'"); + + // Anmeldung erfolgreich. + if ( config('security','renew_session_login') ) + $this->recreateSession(); + + $user = Session::getUser(); + $this->addNotice('user',$user->name,'LOGIN_OK',OR_NOTICE_OK,array('name'=>$user->fullname)); + } + + // Benutzer ist angemeldet + } + + + /** + * 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['alias' ]) && + $subActionName != 'menu' ) + { + $engine = new template_engine\TemplateEngine(); + $engine->compile( strtolower(str_replace('Action','',$actionName)).'/'.$subActionName); + } + } + } + } + + // Umleiten auf eine definierte URL.s + $redirect_url = @$conf['security']['logout']['redirect_url']; + + if ( !empty($redirect_url) ) + { + header('Location: '.$redirect_url); + exit; + } + } + + + + /** + * Benutzer meldet sich ab. + */ + function logoutView() + { + } + + + /** + * Ausw�hlen der Administration. + */ + function administrationPost() + { + } + + + + /** + * Auswaehlen des Benutzer-Profiles. + */ + function profilePost() + { + } + + + + /** + * Auswaehlen der Startseite. + */ + function startPost() + { + } + + + + /** + * 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 languagePost() + { + $user = Session::getUser(); + if ( ! is_object($user) ) + { + throw new \LogicException('No user in session'); + return; + } + + $this->evaluateRequestVars( array(REQ_PARAM_LANGUAGE_ID=>$this->getRequestId()) ); + } + + + function modelPost() + { + $user = Session::getUser(); + if ( ! is_object($user) ) + { + $this->callSubAction('show'); + return; + } + + $this->evaluateRequestVars( array(REQ_PARAM_MODEL_ID=>$this->getRequestId()) ); + } + + + /** + * Auswerten der Request-Variablen. + */ + private function evaluateRequestVars( $add = array() ) + { + } + + + function switchuser() + { + $user = Session::getUser(); + + if ( ! $user->isAdmin ) + throw new \SecurityException(""); + + $this->recreateSession(); + + $newUser = new User( $this->getRequestId() ); + $newUser->load(); + + $newUser->setCurrent(); + } + + + function showView() + { + 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 ); + + $this->metaValues(); + } + + + + 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. + */ + function register() + { + + } + + + /** + * Registriercode erzeugen und per E-Mail dem Benutzer mitteilen. + * Maske anzeigen, damit Benuter Registriercode anzeigen kann. + */ + public function registercode() + { + $email_address = $this->getRequestVar('mail','mail'); + + if ( ! Mail::checkAddress($email_address) ) + { + $this->addValidationError('mail'); + $this->setTemplateVar('mail',$email_address); + $this->callSubAction('register'); + return; + } + + + srand ((double)microtime()*1000003); + $registerCode = rand(); + + Session::set('registerCode',$registerCode ); + + // 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); + $this->callSubAction('register'); + return; + } + } + + + + public function registeruserdata() + { + global $conf; + + Session::set('registerMail',$this->getRequestVar('mail') ); + // TODO: Attribut "Password" abfragen + 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']); + } + + + /** + * Benutzerregistierung. + * Benutzer hat Best�tigungscode erhalten und eingegeben. + */ + public function registercommit() + { + 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'); + $this->callSubAction('registeruserdata'); + return; + } + + // Best�tigungscode stimmt �berein. + // Neuen Benutzer anlegen. + + if ( !$this->hasRequestVar('username') ) + { + $this->addValidationError('username'); + $this->callSubAction('registeruserdata'); + return; + } + + $user = User::loadWithName( $this->getRequestVar('username') ); + if ( $user->isValid() ) + { + $this->addValidationError('username','USER_ALREADY_IN_DATABASE'); + $this->callSubAction('registeruserdata'); + return; + } + + if ( strlen($this->getRequestVar('password')) < $conf['security']['password']['min_length'] ) + { + $this->addValidationError('password','password_minlength',array('minlength'=>$conf['security']['password']['min_length'])); + $this->callSubAction('registeruserdata'); + 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. + */ + public function password() + { + global $conf; + + // TODO: Attribut "Password" abfragen + 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']); + + } + + + /* + 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. + */ + public function passwordcode() + { + if ( !$this->hasRequestVar('username') ) + { + $this->addValidationError('username'); + $this->callSubAction('password'); + return; + } + + $this->checkForDb(); + + $user = User::loadWithName( $this->getRequestVar("username") ); + + Password::delay(); + + // Html::debug($user); + 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. + * + */ + public function passwordinputcode() + { + + } + + + /** + * Neues Kennwort erzeugen und dem Benutzer zusenden. + */ + public function passwordcommit() + { + $username = $this->getSessionVar("password_commit_name"); + + if ( $this->getRequestVar("code")=='' || + $this->getSessionVar("password_commit_code") != $this->getRequestVar("code") ) + { + $this->addValidationError('code','PASSWORDCODE_NOT_MATCH'); + $this->callSubAction('passwordinputcode'); + 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. + */ + private 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 + } + } + + + + + + + /** + * Ermittelt die letzten Änderungen, die durch den aktuellen Benutzer im aktuellen Projekt gemacht worden sind. + */ + public function userprojecttimelineView() + { + //$project = Session::getProject(); + //$result = $project->getMyLastChanges(); + $result = array(); + + $this->setTemplateVar('timeline', $result); + } + + +} + + ?> \ No newline at end of file diff --git a/modules/cms-core/action/TemplateAction.class.php b/modules/cms-core/action/TemplateAction.class.php @@ -40,7 +40,7 @@ use \Text; * @package openrat.actions */ -class TemplateAction extends Action +class TemplateAction extends BaseAction { public $security = Action::SECURITY_USER; diff --git a/modules/cms-core/action/TemplatelistAction.class.php b/modules/cms-core/action/TemplatelistAction.class.php @@ -31,7 +31,7 @@ use Session; * @package openrat.actions */ -class TemplatelistAction extends Action +class TemplatelistAction extends BaseAction { public $security = Action::SECURITY_USER; diff --git a/modules/cms-core/action/TreeAction.class.php b/modules/cms-core/action/TreeAction.class.php @@ -41,7 +41,7 @@ use Session; * @package openrat.actions */ -class TreeAction extends Action +class TreeAction extends BaseAction { public $security = Action::SECURITY_GUEST; diff --git a/modules/cms-core/action/UserAction.class.php b/modules/cms-core/action/UserAction.class.php @@ -41,7 +41,7 @@ use \Mail; * @version $Revision$ * @package openrat.actions */ -class UserAction extends Action +class UserAction extends BaseAction { public $security = Action::SECURITY_ADMIN; diff --git a/modules/cms-core/action/UserlistAction.class.php b/modules/cms-core/action/UserlistAction.class.php @@ -1,88 +1,88 @@ -<?php - -namespace cms\action; - -use cms\model\User; - -// 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. - - -/** - * Action-Klasse zum Bearbeiten eines Benutzers - * @author $Author$ - * @version $Revision$ - * @package openrat.actions - */ -class UserlistAction extends Action -{ - public $security = Action::SECURITY_ADMIN; - - function __construct() - { - parent::__construct(); - } - - - function showView() - { - $list = array(); - - foreach( User::getAllUsers() as $user ) - { - $list[$user->userid] = $user->getProperties(); - $list[$user->userid]['id' ] = $user->userid; - } - $this->setTemplateVar('el',$list); - } - - - /** - * Eigenschaften des Benutzers anzeigen - */ - function editView() - { - $this->nextSubAction('show'); - } - - - - function addView() - { - } - - - - function addPost() - { - if ( $this->getRequestVar('name') != '' ) - { - $this->user = new User(); - $this->user->add( $this->getRequestVar('name') ); - $this->addNotice('user',$this->user->name,'ADDED','ok'); - } - else - { - $this->addValidationError('name'); - $this->callSubAction('add'); - } - } - - - - +<?php + +namespace cms\action; + +use cms\model\User; + +// 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. + + +/** + * Action-Klasse zum Bearbeiten eines Benutzers + * @author $Author$ + * @version $Revision$ + * @package openrat.actions + */ +class UserlistAction extends BaseAction +{ + public $security = Action::SECURITY_ADMIN; + + function __construct() + { + parent::__construct(); + } + + + function showView() + { + $list = array(); + + foreach( User::getAllUsers() as $user ) + { + $list[$user->userid] = $user->getProperties(); + $list[$user->userid]['id' ] = $user->userid; + } + $this->setTemplateVar('el',$list); + } + + + /** + * Eigenschaften des Benutzers anzeigen + */ + function editView() + { + $this->nextSubAction('show'); + } + + + + function addView() + { + } + + + + function addPost() + { + if ( $this->getRequestVar('name') != '' ) + { + $this->user = new User(); + $this->user->add( $this->getRequestVar('name') ); + $this->addNotice('user',$this->user->name,'ADDED','ok'); + } + else + { + $this->addValidationError('name'); + $this->callSubAction('add'); + } + } + + + + } \ No newline at end of file diff --git a/modules/cms-core/action/WebdavAction.class.php b/modules/cms-core/action/WebdavAction.class.php @@ -1,1220 +1,1220 @@ -<?php - -namespace cms\action; - -use cms\model\User; -use cms\model\Project; -use cms\model\Page; -use cms\model\Folder; -use cms\model\BaseObject; -use cms\model\File; -use cms\model\Link; - - -/** - * Action-Klasse fuer WebDAV.<br> - * - * Das virtuelle Ordnersystem dieses CMS kann �ber das WebDAV-Protokoll - * dargestellt werden. - * - * Diese Klasse nimmt die Anfragen von WebDAV-Clients entgegen, zerlegt die - * Anfrage und erzeugt eine Antwort, die im HTTP-Body zur�ck �bertragen - * wird. - * <br> - * WebDAV ist spezifiziert in der RFC 2518.<br> - * Siehe <code>http://www.ietf.org/rfc/rfc2518.txt</code><br> - * - * Implementiert wird DAV-Level 1 (d.h. ohne LOCK). - * - * Der Zugang über WebDAV beinhaltet einige Nachteile: - * - Login ist nur mit Name/Kennwort möglich (kein OpenId) - * - Nur die Standard-Datenbank kann verwendet werden - * - Der Client muss Cookies unterstützen - * - * @author Jan Dankert - * @package openrat.actions - * @deprecated - */ - -class WebdavAction extends Action -{ - public $security = SECURITY_USER; - - // Zahlreiche Instanzvariablen, die im Konstruktor - // beim Zerlegen der Anfrag gef�llt werden. - var $defaultSubAction = 'show'; - var $database; - var $depth; - var $project; - var $folder; - var $obj; - var $filename; - var $pathnames = array(); - var $uri; - var $headers; - var $requestType; - var $request; - var $destination = null; - var $fullSkriptName; - var $create; - var $readonly; - var $maxFileSize; - var $webdav_conf; - var $overwrite = false; - - - /** - * Im Kontruktor wird der Request analysiert und ggf. eine Authentifzierung - * durchgefuehrt. - */ - function __construct() - { - parent::__construct(); - - if (!defined('E_STRICT')) - define('E_STRICT', 2048); - - // Nicht notwendig, da wir den Error-Handler umbiegen: - error_reporting(0); // PHP-Fehlermeldungen zerstoeren XML-Dokument, daher ausschalten. - - // PHP-Fehler ins Log schreiben, damit die Ausgabe nicht zerstoert wird. - if (version_compare(PHP_VERSION, '5.0.0', '>')) - set_error_handler('webdavErrorHandler',E_ERROR | E_WARNING); - else - set_error_handler('webdavErrorHandler'); - - - //Changed tobias - //global $conf; - $prefs = new Preferences(); - $conf = $prefs->load(); - //End changed Tobias - $this->webdav_conf = $conf['webdav']; - - if ( $this->webdav_conf['compliant_to_redmond'] ) - header('MS-Author-Via: DAV' ); // Extrawurst fuer MS-Clients. - - if ( $this->webdav_conf['expose_openrat'] ) - header('X-Dav-powered-by: OpenRat CMS'); // Bandbreite verschwenden :) - - Logger::trace( 'WEBDAV: URI='.$_SERVER['REQUEST_URI']); - - if ( !$conf['webdav']['enable']) - { - Logger::warn( 'WEBDAV is disabled by configuration' ); - $this->httpStatus('403 Forbidden'); - exit; - } - - $this->create = $this->webdav_conf['create']; - $this->readonly = $this->webdav_conf['readonly']; - $this->maxFileSize = $this->webdav_conf['max_file_size']; - - Logger::debug( 'WEBDAV method is '.$_GET['subaction'] ); - - $this->headers = getallheaders(); - /* DAV compliant servers MUST support the "0", "1" and - * "infinity" behaviors. By default, the PROPFIND method without a Depth - * header MUST act as if a "Depth: infinity" header was included. */ - if ( !isset($this->headers['Depth']) ) - $this->depth = 1; - elseif ( strtolower($this->headers['Depth'])=='infinity') - $this->depth = 1; - else - $this->depth = intval($this->headers['Depth']); - - if ( isset($this->headers['Destination']) ) - $this->destination = $this->headers['Destination']; - - if ( isset($this->headers['Overwrite']) ) - $this->overwrite = $this->headers['Overwrite'] == 'T'; - - // Pr�fen, ob Benutzer angemeldet ist. - $user = $this->getUserFromSession(); - - // Authentisierung erzwingen (au�er bei Methode OPTIONS). - // For the motivation for not checking OPTIONS requests see - // http://pear.php.net/bugs/bug.php?id=5363 - if ( !is_object($user) && $_GET[REQ_PARAM_SUBACTION] != 'options' ) - { - Logger::debug( 'Checking Authentication' ); - - if ( !is_object(Session::getDatabase()) ) - $this->setDefaultDb(); - - $ok = false; - if ( isset($_SERVER['PHP_AUTH_USER']) ) - { - $user = new User(); - $user->name = $_SERVER['PHP_AUTH_USER']; - - $ok = $user->checkPassword( $_SERVER['PHP_AUTH_PW'] ); - - if ( $ok ) - { - $user->load(); - $user->setCurrent(); - $this->redirectWithSessionId(); - } - } - - if ( !$ok ) - { - // Client ist nicht angemeldet, daher wird nun die - // Authentisierung angefordert. - Logger::debug( 'Requesting Client to authenticate' ); - header('WWW-Authenticate: Basic realm="'.OR_TITLE.'"'); - $this->httpStatus('401 Unauthorized'); - exit; - } - } - elseif ( !is_object($user) && $_GET[REQ_PARAM_SUBACTION] == 'options' ) - { - $this->setDefaultDb(); - } - - - $this->fullSkriptName = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'/'; - - if ( $this->webdav_conf['session_in_uri'] ) - $sos = 1+strlen(session_id())+strlen($this->webdav_conf['session_in_uri_prefix']); - else - $sos = 0; - - // URL parsen. - $uri = substr($_SERVER['REQUEST_URI'],strlen($_SERVER['SCRIPT_NAME']) + $sos); - - Logger::debug( 'WebDAV: URI="'.$uri.'"' ); - - $uri = $this->parseURI( $uri ); - $this->requestType = $uri['type' ]; - $this->folder = $uri['folder' ]; - $this->obj = $uri['object' ]; - $this->project = $uri['project']; - - $this->fullSkriptName .= implode('/',$uri['path']); - - if ( is_object($this->obj) && $this->obj->isFolder ) - $this->fullSkriptName .= '/'; - - /* - * Verzeichnisse muessen mit einem '/' enden. Falls nicht, Redirect aussfuehren. - * - * RFC 2518, 5.2 Collection Resources, Page 11: - * "For example, if a client invokes a - * method on http://foo.bar/blah (no trailing slash), the resource - * http://foo.bar/blah/ (trailing slash) may respond as if the operation - * were invoked on it, and should return a content-location header with - * http://foo.bar/blah/ in it. In general clients SHOULD use the "/" - * form of collection names." - */ - if ( is_object($this->obj) && - $this->obj->isFolder && - $_GET['subaction'] == 'get' && - substr($_SERVER['REQUEST_URI'],strlen($_SERVER['REQUEST_URI'])-1 ) != '/' ) - { - Logger::debug( 'WebDAV: Redirecting lame client to slashyfied URL' ); - - header('HTTP/1.1 302 Moved Temporarily'); - header('Location: '.$_SERVER['REQUEST_URI'].'/'); - exit; - } - - // Falls vorhanden, den "Destination"-Header parsen. - if ( isset($_SERVER['HTTP_DESTINATION']) ) - { - $destUri = parse_url( $_SERVER['HTTP_DESTINATION'] ); - - $uri = substr($destUri['path'],strlen($_SERVER['SCRIPT_NAME'])+$sos); - - // URL parsen. - $this->destination = $this->parseURI( $uri ); - } - - // Den Request-BODY aus der Standardeingabe lesen. - $this->request = implode('',file('php://input')); - } - - - - /** - * Falls ein WebDAV-Client keine Cookies setzen kann (was HTTP/1.1 eigentlich - * der Fall sein sollte), kann die Session-Id in die URL eingetragen - * werden. Dies muss in der Konfiguration aktiviert werden. - */ - function redirectWithSessionId() - { - if ( $this->webdav_conf['session_in_uri'] ) - { - header('Location: '.dirname($_SERVER['REQUEST_URI']).'/'. $this->webdav_conf['session_in_uri_prefix'].session_id().'/'.basename($_SERVER['REQUEST_URI'])); - //$this->httpStatus('303 See Other'); - $this->httpStatus('302 Moved'); - } - } - - - - /** - * Da im WebDAV-Request keine Datenbank-Id angegeben werden kann, benutzen - * wir hier die Standard-Datenbank. - */ - function setDefaultDb() - { - global $conf; - - if ( !isset($conf['database']['default']) ) - { - Logger::error('No default database in configuration'); - $this->httpStatus('500 Internal Server Error - no default-database in configuration'); - } - - $dbid = $conf['database']['default']; - - $db = new DB( $conf['database'][$dbid] ); - $db->id = $dbid; - Session::setDatabase( $db ); - } - - - - function allowed_methods() - { - - if ($this->readonly) - return array('OPTIONS','HEAD','GET','PROPFIND'); // Readonly-Modus - else - // PROPPATCH unterstuetzen wir garnicht, aber lt. Spec sollten wir das. - return array('OPTIONS','HEAD','GET','PROPFIND','DELETE','PUT','COPY','MOVE','MKCOL','PROPPATCH'); - } - - - - /** - * HTTP-Methode OPTIONS.<br> - * <br> - * Es werden die verfuegbaren Methoden ermittelt und ausgegeben. - */ - function options() - { - header('DAV: 1'); // Wir haben DAV-Level 1. - header('Allow: '.implode(', ',$this->allowed_methods()) ); - - $this->httpStatus( '200 OK' ); - } - - - - /** - * Setzt einen HTTP-Status.<br> - * <br> - * Es wird ein HTTP-Status gesetzt, zus�tzlich wird der Status in den Header "X-WebDAV-Status" geschrieben.<br> - * Ist der Status nicht 200 oder 207 (hier folgt ein BODY), wird das Skript beendet. - */ - function httpStatus( $status = true ) - { - if ( $status === true ) - $status = '200 OK'; - - Logger::debug('WEBDAV: HTTP-Status: '.$status); - - header('HTTP/1.1 '.$status); - header('X-WebDAV-Status: '.$status,true); - - // RFC 2616 (HTTP/1.1), Section 10.4.6 "405 Method Not Allowed" says: - // "[...] The response MUST include an - // Allow header containing a list of valid methods for the requested - // resource." - // - // RFC 2616 (HTTP/1.1), Section 14.7 "Allow" says: - // "[...] An Allow header field MUST be - // present in a 405 (Method Not Allowed) response." - if ( substr($status,0,3) == '405' ) - header('Allow: '.implode(', ',$this->allowed_methods()) ); - } - - - - /** - * WebDav-HEAD-Methode. - */ - function head() - { - if ( $this->obj == null ) - { - $this->httpStatus( '404 Not Found' ); - } - elseif ( $this->obj->isFolder ) - { - $this->httpStatus( '200 OK' ); - } - elseif( $this->obj->isPage ) - { - $this->httpStatus( '200 OK' ); - } - elseif( $this->obj->isLink ) - { - $this->httpStatus( '200 OK' ); - } - elseif( $this->obj->isFile ) - { - $this->httpStatus( '200 OK' ); - } - } - - - - /** - * WebDav-GET-Methode. - * Die gew�nschte Datei wird geladen und im HTTP-Body mitgeliefert. - */ - function get() - { - if ( $this->obj->isFolder ) - $this->getDirectory(); - elseif( $this->obj->isPage ) - { - $this->httpStatus( '200 OK' ); - - header('Content-Type: text/html'); - - $page = new Page( $this->obj->objectid ); - $page->load(); - echo '<html><head><title>OpenRat WEBDAV Access</title></head>'; - echo '<body>'; - echo '<h1>'.$page->full_filename().'</h1>'; - echo '<pre>'; - echo 'No Content available'; - echo '</pre>'; - echo '</body>'; - echo '</html>'; - } - elseif( $this->obj->isLink ) - { - $this->httpStatus( '200 OK' ); - - header('Content-Type: text/plain'); - - $link = new Link( $this->obj->objectid ); - $link->load(); - echo 'url: ' .$link->url ."\n"; - echo 'target-id: '.$link->linkedObjectId."\n"; - } - elseif( $this->obj->isFile ) - { - $this->httpStatus( '200 OK' ); - - $file = new File( $this->obj->objectid ); - $file->load(); - - header('Content-Type: '.$file->mimeType() ); - header('X-File-Id: '.$file->fileid ); - - // Angabe Content-Disposition - // - Bild soll "inline" gezeigt werden - // - Dateiname wird benutzt, wenn der Browser das Bild speichern moechte - header('Content-Disposition: inline; filename='.$file->filename() ); - header('Content-Transfer-Encoding: binary' ); - header('Content-Description: '.$file->name ); - - $file->write(); // Bild aus Datenbank laden und in tempor�re Datei schreiben - - // Groesse des Bildes in Bytes - // Der Browser hat so die Moeglichkeit, einen Fortschrittsbalken zu zeigen - header('Content-Length: '.filesize($file->tmpfile()) ); - readfile( $file->tmpfile() ); - } - } - - - - /** - * Erzeugt ein Unix-�hnliche Ausgabe des Verzeichnisses als HTML. - */ - function getDirectory() - { - $this->httpStatus( '200 OK' ); - - // Verzeichnis ausgeben - header('Content-Type: text/html'); - $nl = "\n"; - $titel = 'Index of '.htmlspecialchars($this->fullSkriptName); - $format = "%15s %-19s %-s\n"; - - echo '<html><head><title>'.$titel.'</title></head>'; - echo '<body>'; - echo '<h1>'.$titel.'</h1>'.$nl; - echo '<pre>'; - - printf($format, "Size", "Last modified", "Filename"); - - if ( $this->requestType == 'projectlist' ) - { - foreach(Project::getAllProjects() as $projectName ) - { - $objektinhalt = array(); - $z = 30*365.25*24*60*60; - $objektinhalt['createdate' ] = $z; - $objektinhalt['lastchangedate'] = $z; - $objektinhalt['size' ] = 1; - echo '<a href="'.$this->fullSkriptName.'/'.$projectName.'"> </a>'; - } - } - elseif( $this->requestType == 'object' ) // Verzeichnisinhalt - { - $objects = $this->folder->getObjects(); - - foreach( $objects as $object ) - { - printf($format, - number_format(1), - strftime("%Y-%m-%d %H:%M:%S",$object->lastchangeDate ), - '<a href="'.$object->filename.'">'.$object->filename.'</a>'); - echo $nl; - } - } - - echo '</pre>'; - echo '</body>'; - echo '</html>'; - } - - - - /** - * Die Methode LOCK sollte garnicht aufgerufen werden, da wir nur - * Dav-Level 1 implementieren und dies dem Client auch mitteilen.<br> - * <br> - * Ausgabe von HTTP-Status 412 (Precondition failed) - */ - function lock() - { - $this->httpStatus('412 Precondition failed'); - $this->options(); - } - - - - /** - * Die Methode UNLOCK sollte garnicht aufgerufen werden, da wir nur - * Dav-Level 1 implementieren und dies dem Client auch mitteilen.<br> - * <br> - * Ausgabe von HTTP-Status 412 (Precondition failed) - */ - function unlock() - { - $this->httpStatus('412 Precondition failed'); - $this->options(); - } - - - - /** - * Die Methode POST ist bei WebDav nicht sinnvoll.<br> - * <br> - * Ausgabe von HTTP-Status 405 (Method Not Allowed) - */ - function post() - { - // Die Methode POST ist bei Webdav nicht sinnvoll. - $this->httpStatus('405 Method Not Allowed' ); - } - - - - /** - * Verzeichnis anlegen. - */ - function mkcol() - { - - if ( !empty($this->request) ) - { - $this->httpStatus('415 Unsupported Media Type' ); // Kein Body erlaubt - } - elseif ( $this->readonly ) - { - $this->httpStatus('403 Forbidden' ); // Kein Schreibzugriff erlaubt - } - elseif ( !$this->folder->hasRight( ACL_CREATE_FOLDER ) ) - { - $this->httpStatus('403 Forbidden' ); // Benutzer darf das nicht - } - elseif ( $this->obj == null ) - { - // Die URI ist noch nicht vorhanden - $f = new Folder(); - $f->filename = basename($this->fullSkriptName); - $f->parentid = $this->folder->objectid; - $f->projectid = $this->project->projectid; - $f->add(); - $this->httpStatus('201 Created'); - } - else - { - // MKCOL ist nicht moeglich, wenn die URI schon existiert. - Logger::warn('MKCOL-Request to an existing resource'); - $this->httpStatus('405 Method Not Allowed' ); - } - } - - - - /** - * Objekt l�schen. - */ - function delete() - { - if ( $this->readonly ) - { - $this->httpStatus('403 Forbidden' ); // Kein Schreibzugriff erlaubt - } - else - { - if ( $this->obj == null ) - { - // Nicht existente URIs kann man auch nicht loeschen. - $this->httpStatus('404 Not Found' ); - } - elseif ( ! $this->obj->hasRight( ACL_DELETE ) ) - { - $this->httpStatus('403 Forbidden' ); // Benutzer darf die Resource nicht loeschen - } - elseif ( $this->obj->isFolder ) - { - $f = new Folder( $this->obj->objectid ); - $f->deleteAll(); - $this->httpStatus( true ); // OK - Logger::debug('Deleted folder with id '.$this->obj->objectid ); - } - elseif ( $this->obj->isFile ) - { - $f = new File( $this->obj->objectid ); - $f->delete(); - $this->httpStatus( true ); // OK - } - elseif ( $this->obj->isPage ) - { - $p = new Page( $this->obj->objectid ); - $p->delete(); - $this->httpStatus( true ); // OK - } - elseif ( $this->obj->isLink ) - { - $l = new Link( $this->obj->objectid ); - $l->delete(); - $this->httpStatus( true ); // OK - } - - } - } - - - - /** - * Kopieren eines Objektes.<br> - * Momentan ist nur das Kopieren einer Datei implementiert.<br> - * Das Kopieren von Ordnern, Verkn�pfungen und Seiten ist nicht moeglich. - */ - function copy() - { - if ( $this->readonly || !$this->create ) - { - Logger::error('WEBDAV: COPY request, but readonly or no creating'); - $this->httpStatus('405 Not Allowed' ); - } - elseif( $this->obj == null ) - { - // Was nicht da ist, laesst sich auch nicht verschieben. - Logger::error('WEBDAV: COPY request, but Source not found'); - $this->httpStatus('405 Not Allowed' ); - } - elseif ( $this->destination == null ) - { - Logger::error('WEBDAV: COPY request, but no "Destination:"-Header'); - // $this->httpStatus('405 Not Allowed' ); - $this->httpStatus('412 Precondition failed'); - } - else - { - // URL parsen. - $dest = $this->destination; - $destinationProject = $dest['project']; - $destinationFolder = $dest['folder' ]; - $destinationObject = $dest['object' ]; - - if ( $dest['type'] != 'object' ) - { - Logger::debug('WEBDAV: COPY request, but "Destination:"-Header mismatch'); - $this->httpStatus('405 Not Allowed'); - } - elseif ( $this->project->projectid != $destinationProject->projectid ) - { - // Kopieren in anderes Projekt nicht moeglich. - Logger::debug('WEBDAV: COPY request denied, project does not match'); - $this->httpStatus('403 Forbidden'); - } - elseif ( $destinationObject != null ) - { - Logger::debug('WEBDAV: COPY request denied, Destination exists. Overwriting is not supported'); - $this->httpStatus('403 Forbidden'); - } - elseif ( is_object($destinationFolder) && ! $destinationFolder->hasRight( ACL_CREATE_FILE ) ) - { - $this->httpStatus('403 Forbidden' ); // Benutzer darf das nicht - } - elseif ( is_object($destinationObject) && $destinationObject->isFolder) - { - Logger::debug('WEBDAV: COPY request denied, Folder-Copy not implemented'); - $this->httpStatus('405 Not Allowed'); - } - elseif ( is_object($destinationObject) && $destinationObject->isLink) - { - Logger::debug('WEBDAV: COPY request denied, Link copy not implemented'); - $this->httpStatus('405 Not Allowed'); - } - elseif ( is_object($destinationObject) && $destinationObject->isPage) - { - Logger::debug('WEBDAV: COPY request denied, Page copy not implemented'); - $this->httpStatus('405 Not Allowed'); - } - else - { - $f = new File(); - $f->filename = basename($_SERVER['HTTP_DESTINATION']); - $f->name = ''; - $f->parentid = $destinationFolder->objectid; - $f->projectid = $this->project->projectid; - $f->add(); - $f->copyValueFromFile( $this->obj->objectid ); - - Logger::debug('WEBDAV: COPY request accepted' ); - // Objekt wird in anderen Ordner kopiert. - $this->httpStatus('201 Created' ); - } - } - - } - - - - /** - * Verschieben eines Objektes.<br> - * <br> - * Folgende Operationen sind m�glich:<br> - * - Unbenennen eines Objektes (alle Typen)<br> - * - Verschieben eines Objektes (alle Typen) in einen anderen Ordner.<br> - */ - function move() - { - if ( $this->readonly ) - { - $this->httpStatus('403 Forbidden - Readonly Mode' ); // Schreibgeschuetzt - } - elseif ( !$this->create ) - { - $this->httpStatus('403 Forbidden - No creation' ); // Schreibgeschuetzt - } - elseif( $this->obj == null ) - { - // Was nicht da ist, laesst sich auch nicht verschieben. - $this->httpStatus('404 Not Found' ); - } - elseif( is_object($this->obj) && ! $this->obj->hasRight( ACL_WRITE ) ) - { - // Was nicht da ist, laesst sich auch nicht verschieben. - Logger::error('Source '.$this->obj->objectid.' is not writable: Forbidden'); - $this->httpStatus('403 Forbidden' ); - } - elseif ( $this->destination == null ) - { - Logger::error('WEBDAV: MOVE request, but no "Destination:"-Header'); - // $this->httpStatus('405 Not Allowed' ); - $this->httpStatus('412 Precondition failed'); - } - else - { - $dest = $this->destination; - $destinationProject = $dest['project']; - $destinationFolder = $dest['folder' ]; - $destinationObject = $dest['object' ]; - - if ( $dest['type'] != 'object' ) - { - Logger::debug('WEBDAV: MOVE request, but "Destination:"-Header mismatch'); - $this->httpStatus('405 Not Allowed'); - return; - } - - if ( is_object($destinationFolder) && ! $destinationFolder->hasRight( ACL_CREATE_FILE ) ) - { - Logger::error('Source '.$this->obj->objectid.' is not writable: Forbidden'); - $this->httpStatus('403 Forbidden' ); - } - - if ( $destinationObject != null ) - { - Logger::debug('WEBDAV: MOVE request denied, destination exists'); - $this->httpStatus('412 Precondition Failed'); - return; - } - - if ( $this->project->projectid != $destinationProject->projectid ) - { - // Verschieben in anderes Projekt nicht moeglich. - Logger::debug('WEBDAV: MOVE request denied, project does not match'); - $this->httpStatus('405 Not Allowed'); - return; - } - - if ( $this->folder->objectid == $destinationFolder->objectid ) - { - Logger::debug('WEBDAV: MOVE request accepted, object renamed'); - // Resource bleibt in gleichem Ordner. - $this->obj->filename = basename($_SERVER['HTTP_DESTINATION']); - $this->obj->objectSave(false); - $this->httpStatus('201 Created' ); - return; - } - - if ( $destinationFolder->isFolder ) - { - Logger::debug('WEBDAV: MOVE request accepted, Destination: '.$destinationFolder->filename ); - // Objekt wird in anderen Ordner verschoben. - $this->obj->setParentId( $destinationFolder->objectid ); - $this->httpStatus('201 Created' ); - return; - } - - Logger::warn('WEBDAV: MOVE request failed' ); - $this->httpStatus('500 Internal Server Error' ); - } - } - - - - /** - * Anlegen oder �berschreiben Dateien �ber PUT.<br> - * Dateien k�nnen neu angelegt und �berschrieben werden.<br> - * <br> - * Seiten k�nnen nicht �berschrieben werden. Wird versucht, - * eine Seite mit PUT zu �berschreiben, wird der Status "405 Not Allowed" gemeldet.<br> - */ - function put() - { - // TODO: 409 (Conflict) wenn �bergeordneter Ordner nicht da. - - if ( $this->webdav_conf['readonly'] ) - { - $this->httpStatus('405 Not Allowed' ); - } - elseif ( strlen($this->request) > $this->maxFileSize*1000 ) - { - // Maximale Dateigroesse ueberschritten. - // Der Status 207 "Zuwenig Speicherplatz" passt nicht ganz, aber fast :) - $this->httpStatus('507 Insufficient Storage' ); - } - elseif ( $this->obj == null ) - { - // Neue Datei anlegen - if ( !$this->webdav_conf['create'] ) - { - Logger::warn('WEBDAV: Creation of files not allowed by configuration' ); - $this->httpStatus('405 Not Allowed' ); - } - - if ( ! $this->folder->hasRight( ACL_CREATE_FILE ) ) - { - $this->httpStatus('403 Forbidden'); - return; - } - - $file = new File(); - $file->filename = basename($this->fullSkriptName); - $file->extension = ''; - $file->size = strlen($this->request); - $file->parentid = $this->folder->objectid; - $file->projectid = $this->project->projectid; - $file->value = $this->request; - $file->add(); - $this->httpStatus('201 Created'); - return; - } - elseif ( $this->obj->isFile ) - { - if ( ! $this->obj->hasRight( ACL_WRITE ) ) - { - Logger::debug('PUT failed, parent folder not writable by user' ); - $this->httpStatus('403 Forbidden'); - return; - } - - // Bestehende Datei ueberschreiben. - $file = new File( $this->obj->objectid ); - $file->saveValue( $this->request ); - $file->setTimestamp(); - $this->httpStatus('204 No Content'); - Logger::debug('PUT ok, file is created' ); - return; - } - elseif ( $this->obj->isFolder ) - { - Logger::error('PUT on folder is not supported, use PROPFIND. Lame client?' ); - $this->httpStatus('405 Not Allowed' ); - } - else - { - // Fuer andere Objekttypen (Links, Seiten) ist kein PUT moeglich. - Logger::warn('PUT only available for files, pages and links are ignored' ); - $this->httpStatus('405 Not Allowed' ); - } - } - - - - /** - * WebDav-Methode PROPFIND. - * - * Diese Methode wird - * - beim Ermitteln von Verzeichnisinhalten und - * - beim Ermitteln von Metainformationen zu einer Datei - * verwendet. - * - * Das Ergebnis wird in einer XML-Zeichenkette geliefert. - */ - function propfind() - { - switch( $this->requestType ) - { - case 'projectlist': // Projektliste - - $inhalte = array(); - - $objektinhalt = array(); - $z = 30*365.25*24*60*60; - $objektinhalt['createdate' ] = $z; - $objektinhalt['lastchangedate'] = $z; - $objektinhalt['size' ] = 1; - $objektinhalt['name' ] = $this->fullSkriptName; - $objektinhalt['displayname' ] = ''; - $objektinhalt['type'] = 'folder'; - - $inhalte[] = $objektinhalt; - - foreach(Project::getAllProjects() as $projectid=> $projectName ) - { - $project = new Project( $projectid ); - $rootObjectId = $project->getRootObjectId(); - $folder = new Folder( $rootObjectId ); - $folder->load(); - - $objektinhalt = array(); - $z = 30*365.25*24*60*60; - $objektinhalt['createdate' ] = $z; - $objektinhalt['lastchangedate'] = $folder->lastchangeDate; - $objektinhalt['size' ] = $project->size(); - $objektinhalt['name' ] = $this->fullSkriptName.$projectName.'/'; - $objektinhalt['displayname' ] = $projectName; - $objektinhalt['type'] = 'folder'; - $inhalte[] = $objektinhalt; - } - - $this->multiStatus( $inhalte ); - break; - - case 'object': // Verzeichnisinhalt - - if ( $this->obj == null ) - { - // Objekt existiert nicht. - Logger::trace( 'WEBDAV: PROPFIND of non-existent object'); - $this->httpStatus('404 Not Found'); - return; - } - elseif ( $this->obj->isFolder ) - { - if ( ! $this->obj->hasRight( ACL_READ )) - { - Logger::debug( 'Folder '.$this->obj->objectid.': access denied'); - $this->httpStatus('403 Forbidden'); - } - - $inhalte = array(); - - $objektinhalt = array(); - $objektinhalt['createdate' ] = $this->obj->createDate; - $objektinhalt['lastchangedate'] = $this->obj->lastchangeDate; - $objektinhalt['name' ] = $this->fullSkriptName; - $objektinhalt['displayname' ] = basename($this->fullSkriptName); - $objektinhalt['type' ] = 'folder'; - $objektinhalt['size' ] = 0; - $inhalte[] = $objektinhalt; - - if ( $this->depth > 0 ) - { - $objects = $this->folder->getObjects(); - foreach( $objects as $object ) - { - if ( ! $object->hasRight( ACL_READ )) - continue; - - //$object->loadRaw(); - $objektinhalt = array(); - $objektinhalt['createdate' ] = $object->createDate; - $objektinhalt['lastchangedate'] = $object->lastchangeDate; - $objektinhalt['displayname' ] = $object->filename; - - switch( $object->getType() ) - { - - case OR_TYPE_FOLDER: - $objektinhalt['name'] = $this->fullSkriptName.$object->filename.'/'; - $objektinhalt['type'] = 'folder'; - $objektinhalt['size'] = 0; - $inhalte[] = $objektinhalt; - break; - case OR_TYPE_FILE: - $objektinhalt['name'] = $this->fullSkriptName.$object->filename; - $objektinhalt['type'] = 'file'; - $file = new File($object->objectid); - $file->load(); - $objektinhalt['size'] = $file->size; - $objektinhalt['mime'] = 'application/x-non-readable'; - $inhalte[] = $objektinhalt; - break; - case OR_TYPE_LINK: - $objektinhalt['name'] = $this->fullSkriptName.$object->filename; - $objektinhalt['type'] = 'file'; - $objektinhalt['size'] = 0; - $objektinhalt['mime'] = 'application/x-non-readable'; - $inhalte[] = $objektinhalt; - break; - case OR_TYPE_PAGE: - $objektinhalt['name'] = $this->fullSkriptName.$object->filename; - $objektinhalt['type'] = 'file'; - $objektinhalt['size'] = 0; - $inhalte[] = $objektinhalt; - break; - default: - } - } - } - Logger::trace( 'WEBDAV: PROPFIND-2'); - -// if ( count($inhalte)==0 ) -// $inhalte[] = array('createdate'=>0,'lastchangedate'=>0,'name'=>'empty','size'=>0,'type'=>'file'); - - Logger::trace('Anzahl Dateien:'.count($inhalte)); - $this->multiStatus( $inhalte ); - } - else - { - $object = $this->obj; - Logger::trace( 'WEBDAV: PROPFIND of file'); - $objektinhalt = array(); - $objektinhalt = array(); - $objektinhalt['name'] = $this->fullSkriptName.'/'.$object->filename.'/'; - $objektinhalt['displayname'] = $object->filename; - $objektinhalt['createdate' ] = $object->createDate; - $objektinhalt['lastchangedate'] = $object->lastchangeDate; - $file = new File( $this->obj->objectid ); - $file->load(); - $objektinhalt['size' ] = $file->size; - $objektinhalt['type' ] = 'file'; - - - $this->multiStatus( array($objektinhalt) ); - } - break; - - default: - Logger::warn('Internal Error, unknown request type: '. $this->requestType); - $this->httpStatus('500 Internal Server Error'); - } - } - - - /** - * Webdav-Methode PROPPATCH ist nicht implementiert. - */ - function proppatch() - { - // TODO: Multistatus erzeugen. - // Evtl. ist '409 Conflict' besser? - $this->httpStatus('405 Not Allowed'); - } - - - /** - * Erzeugt einen Multi-Status. - * @access private - */ - function multiStatus( $files ) - { - $this->httpStatus('207 Multi-Status'); - header('Content-Type: text/xml; charset=utf-8'); - - $response = ''; - $response .= '<?xml version="1.0" encoding="utf-8" ?>'; - $response .= '<d:multistatus xmlns:d="DAV:">'; - - foreach( $files as $file ) - $response .= $this->getResponse( $file['name'],$file ); - - $response .= '</d:multistatus>'; - Logger::trace('PROPFIND: '.$response); - - $response = utf8_encode($response); - - header('Content-Length: '.strlen($response)); - echo $response; - } - - - /** - * Erzeugt ein "response"-Element, welches in ein "multistatus"-element verwendet werden kann. - */ - function getResponse( $file,$options ) - { - // TODO: Nur angeforderte Elemente erzeugen. - $response = ''; - $response .= '<d:response>'; - $response .= '<d:href>'.$file.'</d:href>'; - $response .= '<d:propstat>'; - $response .= '<d:prop>'; - // $response .= '<d:source></d:source>'; - $response .= '<d:creationdate>'.date('r',$options['createdate']).'</d:creationdate>'; - $response .= '<d:displayname>'.$options['displayname'].'</d:displayname>'; - $response .= '<d:getcontentlength>'.$options['size'].'</d:getcontentlength>'; - $response .= '<d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">'.date('r',$options['lastchangedate']).'</d:getlastmodified>'; - - if ( $options['type'] == 'folder') - $response .= '<d:resourcetype><d:collection/></d:resourcetype>'; - else - $response .= '<d:resourcetype />'; - - $response .= '<d:categories />'; - $response .= '<d:fields></d:fields>'; - - - -// $response .= '<d:getcontenttype>text/html</d:getcontenttype>'; -// $response .= '<d:getcontentlength />'; -// $response .= '<d:getcontentlanguage />'; -// $response .= '<d:executable />'; -// $response .= '<d:resourcetype>'; -// $response .= '<d:collection />'; -// $response .= '</d:resourcetype>'; -// $response .= '<d:getetag />'; - - $response .= '</d:prop>'; - $response .= '<d:status>HTTP/1.1 200 OK</d:status>'; - $response .= '</d:propstat>'; - $response .= '</d:response>'; - - return $response; - } - - - - /** - * URI parsen. - */ - function parseURI( $uri ) - { - // Ergebnis initialisieren (damit alle Schl�ssel vorhanden sind) - $ergebnis = array('type' => null, - 'project' => null, - 'path' => array(), - 'folder' => null, - 'object' => null ); - - Logger::trace( 'WEBDAV: Parsen der URI '.$uri); - $uriParts = explode('/',$uri); - - $nr = 0; - $f = null; - $o = null; - $ergebnis['type'] = 'projectlist'; - - foreach( $uriParts as $uriPart ) - { - if ( empty( $uriPart)) - continue; - - $ergebnis['path'][] = $uriPart; - - if ( $f == null ) - { - // URI='/project/' - // Name des Projektes in der URL, es wird das Projekt geladen. - $ergebnis['type'] = 'object'; - - $p = new Project(); - $p->name = $uriPart; - Logger::trace("Projektname: ".$p->name); - $p->loadByName(); - $ergebnis['project'] = $p; - // Das Projekt hat weder Sprache noch Variante gesetzt. - //Session::setProjectLanguage( new Language( $this->project->getDefaultLanguageId() ) ); - //Session::setProjectModel ( new Model ( $this->project->getDefaultModelId() ) ); - - $oid = $p->getRootObjectId(); - - $f = new Folder($oid); - $ergebnis['object'] = $f; - $ergebnis['folder'] = $f; - - } - else - { - if ( $ergebnis['object'] == null ) - { - $this->httpStatus('409 Conflict'); - exit; - } - - $oid = $f->getObjectIdByFileName($uriPart); - - if ( $oid == 0 ) - { - Logger::trace( 'WEBDAV: URL-Part does not exist: '.$uriPart); - $ergebnis['object'] = null; - } - else - { - Logger::trace( 'Teil '.$uriPart); - $o = new BaseObject($oid); - $o->load(); - $ergebnis['object'] = $o; - - if ( $o->isFolder ) - { - $f = new Folder($oid); - $ergebnis['folder'] = $f; - } - } - } - } - - return $ergebnis; - } -} - - - -/** - * Fehler-Handler fuer WEBDAV.<br> - * Bei einem Laufzeitfehler ist eine Ausgabe des Fehlers auf der Standardausgabe sinnlos, - * da der WebDAV-Client dies nicht lesen oder erkennen kann. - * Daher wird der Fehler-Handler umgebogen, so dass nur ein Logeintrag sowie ein - * Server-Fehler erzeugt wird. - */ -function webdavErrorHandler($errno, $errstr, $errfile, $errline) -{ - Logger::warn('WEBDAV ERROR: '.$errno.'/'.$errstr.'/file:'.$errfile.'/line:'.$errline); - - // Wir teilen dem Client mit, dass auf dem Server was schief gelaufen ist. - WebdavAction::httpStatus('500 Internal Server Error, WebDAV-Request failed with "'.$errstr.'"'); -} - +<?php + +namespace cms\action; + +use cms\model\User; +use cms\model\Project; +use cms\model\Page; +use cms\model\Folder; +use cms\model\BaseObject; +use cms\model\File; +use cms\model\Link; + + +/** + * Action-Klasse fuer WebDAV.<br> + * + * Das virtuelle Ordnersystem dieses CMS kann �ber das WebDAV-Protokoll + * dargestellt werden. + * + * Diese Klasse nimmt die Anfragen von WebDAV-Clients entgegen, zerlegt die + * Anfrage und erzeugt eine Antwort, die im HTTP-Body zur�ck �bertragen + * wird. + * <br> + * WebDAV ist spezifiziert in der RFC 2518.<br> + * Siehe <code>http://www.ietf.org/rfc/rfc2518.txt</code><br> + * + * Implementiert wird DAV-Level 1 (d.h. ohne LOCK). + * + * Der Zugang über WebDAV beinhaltet einige Nachteile: + * - Login ist nur mit Name/Kennwort möglich (kein OpenId) + * - Nur die Standard-Datenbank kann verwendet werden + * - Der Client muss Cookies unterstützen + * + * @author Jan Dankert + * @package openrat.actions + * @deprecated + */ + +class WebdavAction extends BaseAction +{ + public $security = SECURITY_USER; + + // Zahlreiche Instanzvariablen, die im Konstruktor + // beim Zerlegen der Anfrag gef�llt werden. + var $defaultSubAction = 'show'; + var $database; + var $depth; + var $project; + var $folder; + var $obj; + var $filename; + var $pathnames = array(); + var $uri; + var $headers; + var $requestType; + var $request; + var $destination = null; + var $fullSkriptName; + var $create; + var $readonly; + var $maxFileSize; + var $webdav_conf; + var $overwrite = false; + + + /** + * Im Kontruktor wird der Request analysiert und ggf. eine Authentifzierung + * durchgefuehrt. + */ + function __construct() + { + parent::__construct(); + + if (!defined('E_STRICT')) + define('E_STRICT', 2048); + + // Nicht notwendig, da wir den Error-Handler umbiegen: + error_reporting(0); // PHP-Fehlermeldungen zerstoeren XML-Dokument, daher ausschalten. + + // PHP-Fehler ins Log schreiben, damit die Ausgabe nicht zerstoert wird. + if (version_compare(PHP_VERSION, '5.0.0', '>')) + set_error_handler('webdavErrorHandler',E_ERROR | E_WARNING); + else + set_error_handler('webdavErrorHandler'); + + + //Changed tobias + //global $conf; + $prefs = new Preferences(); + $conf = $prefs->load(); + //End changed Tobias + $this->webdav_conf = $conf['webdav']; + + if ( $this->webdav_conf['compliant_to_redmond'] ) + header('MS-Author-Via: DAV' ); // Extrawurst fuer MS-Clients. + + if ( $this->webdav_conf['expose_openrat'] ) + header('X-Dav-powered-by: OpenRat CMS'); // Bandbreite verschwenden :) + + Logger::trace( 'WEBDAV: URI='.$_SERVER['REQUEST_URI']); + + if ( !$conf['webdav']['enable']) + { + Logger::warn( 'WEBDAV is disabled by configuration' ); + $this->httpStatus('403 Forbidden'); + exit; + } + + $this->create = $this->webdav_conf['create']; + $this->readonly = $this->webdav_conf['readonly']; + $this->maxFileSize = $this->webdav_conf['max_file_size']; + + Logger::debug( 'WEBDAV method is '.$_GET['subaction'] ); + + $this->headers = getallheaders(); + /* DAV compliant servers MUST support the "0", "1" and + * "infinity" behaviors. By default, the PROPFIND method without a Depth + * header MUST act as if a "Depth: infinity" header was included. */ + if ( !isset($this->headers['Depth']) ) + $this->depth = 1; + elseif ( strtolower($this->headers['Depth'])=='infinity') + $this->depth = 1; + else + $this->depth = intval($this->headers['Depth']); + + if ( isset($this->headers['Destination']) ) + $this->destination = $this->headers['Destination']; + + if ( isset($this->headers['Overwrite']) ) + $this->overwrite = $this->headers['Overwrite'] == 'T'; + + // Pr�fen, ob Benutzer angemeldet ist. + $user = $this->getUserFromSession(); + + // Authentisierung erzwingen (au�er bei Methode OPTIONS). + // For the motivation for not checking OPTIONS requests see + // http://pear.php.net/bugs/bug.php?id=5363 + if ( !is_object($user) && $_GET[REQ_PARAM_SUBACTION] != 'options' ) + { + Logger::debug( 'Checking Authentication' ); + + if ( !is_object(Session::getDatabase()) ) + $this->setDefaultDb(); + + $ok = false; + if ( isset($_SERVER['PHP_AUTH_USER']) ) + { + $user = new User(); + $user->name = $_SERVER['PHP_AUTH_USER']; + + $ok = $user->checkPassword( $_SERVER['PHP_AUTH_PW'] ); + + if ( $ok ) + { + $user->load(); + $user->setCurrent(); + $this->redirectWithSessionId(); + } + } + + if ( !$ok ) + { + // Client ist nicht angemeldet, daher wird nun die + // Authentisierung angefordert. + Logger::debug( 'Requesting Client to authenticate' ); + header('WWW-Authenticate: Basic realm="'.OR_TITLE.'"'); + $this->httpStatus('401 Unauthorized'); + exit; + } + } + elseif ( !is_object($user) && $_GET[REQ_PARAM_SUBACTION] == 'options' ) + { + $this->setDefaultDb(); + } + + + $this->fullSkriptName = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'/'; + + if ( $this->webdav_conf['session_in_uri'] ) + $sos = 1+strlen(session_id())+strlen($this->webdav_conf['session_in_uri_prefix']); + else + $sos = 0; + + // URL parsen. + $uri = substr($_SERVER['REQUEST_URI'],strlen($_SERVER['SCRIPT_NAME']) + $sos); + + Logger::debug( 'WebDAV: URI="'.$uri.'"' ); + + $uri = $this->parseURI( $uri ); + $this->requestType = $uri['type' ]; + $this->folder = $uri['folder' ]; + $this->obj = $uri['object' ]; + $this->project = $uri['project']; + + $this->fullSkriptName .= implode('/',$uri['path']); + + if ( is_object($this->obj) && $this->obj->isFolder ) + $this->fullSkriptName .= '/'; + + /* + * Verzeichnisse muessen mit einem '/' enden. Falls nicht, Redirect aussfuehren. + * + * RFC 2518, 5.2 Collection Resources, Page 11: + * "For example, if a client invokes a + * method on http://foo.bar/blah (no trailing slash), the resource + * http://foo.bar/blah/ (trailing slash) may respond as if the operation + * were invoked on it, and should return a content-location header with + * http://foo.bar/blah/ in it. In general clients SHOULD use the "/" + * form of collection names." + */ + if ( is_object($this->obj) && + $this->obj->isFolder && + $_GET['subaction'] == 'get' && + substr($_SERVER['REQUEST_URI'],strlen($_SERVER['REQUEST_URI'])-1 ) != '/' ) + { + Logger::debug( 'WebDAV: Redirecting lame client to slashyfied URL' ); + + header('HTTP/1.1 302 Moved Temporarily'); + header('Location: '.$_SERVER['REQUEST_URI'].'/'); + exit; + } + + // Falls vorhanden, den "Destination"-Header parsen. + if ( isset($_SERVER['HTTP_DESTINATION']) ) + { + $destUri = parse_url( $_SERVER['HTTP_DESTINATION'] ); + + $uri = substr($destUri['path'],strlen($_SERVER['SCRIPT_NAME'])+$sos); + + // URL parsen. + $this->destination = $this->parseURI( $uri ); + } + + // Den Request-BODY aus der Standardeingabe lesen. + $this->request = implode('',file('php://input')); + } + + + + /** + * Falls ein WebDAV-Client keine Cookies setzen kann (was HTTP/1.1 eigentlich + * der Fall sein sollte), kann die Session-Id in die URL eingetragen + * werden. Dies muss in der Konfiguration aktiviert werden. + */ + function redirectWithSessionId() + { + if ( $this->webdav_conf['session_in_uri'] ) + { + header('Location: '.dirname($_SERVER['REQUEST_URI']).'/'. $this->webdav_conf['session_in_uri_prefix'].session_id().'/'.basename($_SERVER['REQUEST_URI'])); + //$this->httpStatus('303 See Other'); + $this->httpStatus('302 Moved'); + } + } + + + + /** + * Da im WebDAV-Request keine Datenbank-Id angegeben werden kann, benutzen + * wir hier die Standard-Datenbank. + */ + function setDefaultDb() + { + global $conf; + + if ( !isset($conf['database']['default']) ) + { + Logger::error('No default database in configuration'); + $this->httpStatus('500 Internal Server Error - no default-database in configuration'); + } + + $dbid = $conf['database']['default']; + + $db = new DB( $conf['database'][$dbid] ); + $db->id = $dbid; + Session::setDatabase( $db ); + } + + + + function allowed_methods() + { + + if ($this->readonly) + return array('OPTIONS','HEAD','GET','PROPFIND'); // Readonly-Modus + else + // PROPPATCH unterstuetzen wir garnicht, aber lt. Spec sollten wir das. + return array('OPTIONS','HEAD','GET','PROPFIND','DELETE','PUT','COPY','MOVE','MKCOL','PROPPATCH'); + } + + + + /** + * HTTP-Methode OPTIONS.<br> + * <br> + * Es werden die verfuegbaren Methoden ermittelt und ausgegeben. + */ + function options() + { + header('DAV: 1'); // Wir haben DAV-Level 1. + header('Allow: '.implode(', ',$this->allowed_methods()) ); + + $this->httpStatus( '200 OK' ); + } + + + + /** + * Setzt einen HTTP-Status.<br> + * <br> + * Es wird ein HTTP-Status gesetzt, zus�tzlich wird der Status in den Header "X-WebDAV-Status" geschrieben.<br> + * Ist der Status nicht 200 oder 207 (hier folgt ein BODY), wird das Skript beendet. + */ + function httpStatus( $status = true ) + { + if ( $status === true ) + $status = '200 OK'; + + Logger::debug('WEBDAV: HTTP-Status: '.$status); + + header('HTTP/1.1 '.$status); + header('X-WebDAV-Status: '.$status,true); + + // RFC 2616 (HTTP/1.1), Section 10.4.6 "405 Method Not Allowed" says: + // "[...] The response MUST include an + // Allow header containing a list of valid methods for the requested + // resource." + // + // RFC 2616 (HTTP/1.1), Section 14.7 "Allow" says: + // "[...] An Allow header field MUST be + // present in a 405 (Method Not Allowed) response." + if ( substr($status,0,3) == '405' ) + header('Allow: '.implode(', ',$this->allowed_methods()) ); + } + + + + /** + * WebDav-HEAD-Methode. + */ + function head() + { + if ( $this->obj == null ) + { + $this->httpStatus( '404 Not Found' ); + } + elseif ( $this->obj->isFolder ) + { + $this->httpStatus( '200 OK' ); + } + elseif( $this->obj->isPage ) + { + $this->httpStatus( '200 OK' ); + } + elseif( $this->obj->isLink ) + { + $this->httpStatus( '200 OK' ); + } + elseif( $this->obj->isFile ) + { + $this->httpStatus( '200 OK' ); + } + } + + + + /** + * WebDav-GET-Methode. + * Die gew�nschte Datei wird geladen und im HTTP-Body mitgeliefert. + */ + function get() + { + if ( $this->obj->isFolder ) + $this->getDirectory(); + elseif( $this->obj->isPage ) + { + $this->httpStatus( '200 OK' ); + + header('Content-Type: text/html'); + + $page = new Page( $this->obj->objectid ); + $page->load(); + echo '<html><head><title>OpenRat WEBDAV Access</title></head>'; + echo '<body>'; + echo '<h1>'.$page->full_filename().'</h1>'; + echo '<pre>'; + echo 'No Content available'; + echo '</pre>'; + echo '</body>'; + echo '</html>'; + } + elseif( $this->obj->isLink ) + { + $this->httpStatus( '200 OK' ); + + header('Content-Type: text/plain'); + + $link = new Link( $this->obj->objectid ); + $link->load(); + echo 'url: ' .$link->url ."\n"; + echo 'target-id: '.$link->linkedObjectId."\n"; + } + elseif( $this->obj->isFile ) + { + $this->httpStatus( '200 OK' ); + + $file = new File( $this->obj->objectid ); + $file->load(); + + header('Content-Type: '.$file->mimeType() ); + header('X-File-Id: '.$file->fileid ); + + // Angabe Content-Disposition + // - Bild soll "inline" gezeigt werden + // - Dateiname wird benutzt, wenn der Browser das Bild speichern moechte + header('Content-Disposition: inline; filename='.$file->filename() ); + header('Content-Transfer-Encoding: binary' ); + header('Content-Description: '.$file->name ); + + $file->write(); // Bild aus Datenbank laden und in tempor�re Datei schreiben + + // Groesse des Bildes in Bytes + // Der Browser hat so die Moeglichkeit, einen Fortschrittsbalken zu zeigen + header('Content-Length: '.filesize($file->tmpfile()) ); + readfile( $file->tmpfile() ); + } + } + + + + /** + * Erzeugt ein Unix-�hnliche Ausgabe des Verzeichnisses als HTML. + */ + function getDirectory() + { + $this->httpStatus( '200 OK' ); + + // Verzeichnis ausgeben + header('Content-Type: text/html'); + $nl = "\n"; + $titel = 'Index of '.htmlspecialchars($this->fullSkriptName); + $format = "%15s %-19s %-s\n"; + + echo '<html><head><title>'.$titel.'</title></head>'; + echo '<body>'; + echo '<h1>'.$titel.'</h1>'.$nl; + echo '<pre>'; + + printf($format, "Size", "Last modified", "Filename"); + + if ( $this->requestType == 'projectlist' ) + { + foreach(Project::getAllProjects() as $projectName ) + { + $objektinhalt = array(); + $z = 30*365.25*24*60*60; + $objektinhalt['createdate' ] = $z; + $objektinhalt['lastchangedate'] = $z; + $objektinhalt['size' ] = 1; + echo '<a href="'.$this->fullSkriptName.'/'.$projectName.'"> </a>'; + } + } + elseif( $this->requestType == 'object' ) // Verzeichnisinhalt + { + $objects = $this->folder->getObjects(); + + foreach( $objects as $object ) + { + printf($format, + number_format(1), + strftime("%Y-%m-%d %H:%M:%S",$object->lastchangeDate ), + '<a href="'.$object->filename.'">'.$object->filename.'</a>'); + echo $nl; + } + } + + echo '</pre>'; + echo '</body>'; + echo '</html>'; + } + + + + /** + * Die Methode LOCK sollte garnicht aufgerufen werden, da wir nur + * Dav-Level 1 implementieren und dies dem Client auch mitteilen.<br> + * <br> + * Ausgabe von HTTP-Status 412 (Precondition failed) + */ + function lock() + { + $this->httpStatus('412 Precondition failed'); + $this->options(); + } + + + + /** + * Die Methode UNLOCK sollte garnicht aufgerufen werden, da wir nur + * Dav-Level 1 implementieren und dies dem Client auch mitteilen.<br> + * <br> + * Ausgabe von HTTP-Status 412 (Precondition failed) + */ + function unlock() + { + $this->httpStatus('412 Precondition failed'); + $this->options(); + } + + + + /** + * Die Methode POST ist bei WebDav nicht sinnvoll.<br> + * <br> + * Ausgabe von HTTP-Status 405 (Method Not Allowed) + */ + function post() + { + // Die Methode POST ist bei Webdav nicht sinnvoll. + $this->httpStatus('405 Method Not Allowed' ); + } + + + + /** + * Verzeichnis anlegen. + */ + function mkcol() + { + + if ( !empty($this->request) ) + { + $this->httpStatus('415 Unsupported Media Type' ); // Kein Body erlaubt + } + elseif ( $this->readonly ) + { + $this->httpStatus('403 Forbidden' ); // Kein Schreibzugriff erlaubt + } + elseif ( !$this->folder->hasRight( ACL_CREATE_FOLDER ) ) + { + $this->httpStatus('403 Forbidden' ); // Benutzer darf das nicht + } + elseif ( $this->obj == null ) + { + // Die URI ist noch nicht vorhanden + $f = new Folder(); + $f->filename = basename($this->fullSkriptName); + $f->parentid = $this->folder->objectid; + $f->projectid = $this->project->projectid; + $f->add(); + $this->httpStatus('201 Created'); + } + else + { + // MKCOL ist nicht moeglich, wenn die URI schon existiert. + Logger::warn('MKCOL-Request to an existing resource'); + $this->httpStatus('405 Method Not Allowed' ); + } + } + + + + /** + * Objekt l�schen. + */ + function delete() + { + if ( $this->readonly ) + { + $this->httpStatus('403 Forbidden' ); // Kein Schreibzugriff erlaubt + } + else + { + if ( $this->obj == null ) + { + // Nicht existente URIs kann man auch nicht loeschen. + $this->httpStatus('404 Not Found' ); + } + elseif ( ! $this->obj->hasRight( ACL_DELETE ) ) + { + $this->httpStatus('403 Forbidden' ); // Benutzer darf die Resource nicht loeschen + } + elseif ( $this->obj->isFolder ) + { + $f = new Folder( $this->obj->objectid ); + $f->deleteAll(); + $this->httpStatus( true ); // OK + Logger::debug('Deleted folder with id '.$this->obj->objectid ); + } + elseif ( $this->obj->isFile ) + { + $f = new File( $this->obj->objectid ); + $f->delete(); + $this->httpStatus( true ); // OK + } + elseif ( $this->obj->isPage ) + { + $p = new Page( $this->obj->objectid ); + $p->delete(); + $this->httpStatus( true ); // OK + } + elseif ( $this->obj->isLink ) + { + $l = new Link( $this->obj->objectid ); + $l->delete(); + $this->httpStatus( true ); // OK + } + + } + } + + + + /** + * Kopieren eines Objektes.<br> + * Momentan ist nur das Kopieren einer Datei implementiert.<br> + * Das Kopieren von Ordnern, Verkn�pfungen und Seiten ist nicht moeglich. + */ + function copy() + { + if ( $this->readonly || !$this->create ) + { + Logger::error('WEBDAV: COPY request, but readonly or no creating'); + $this->httpStatus('405 Not Allowed' ); + } + elseif( $this->obj == null ) + { + // Was nicht da ist, laesst sich auch nicht verschieben. + Logger::error('WEBDAV: COPY request, but Source not found'); + $this->httpStatus('405 Not Allowed' ); + } + elseif ( $this->destination == null ) + { + Logger::error('WEBDAV: COPY request, but no "Destination:"-Header'); + // $this->httpStatus('405 Not Allowed' ); + $this->httpStatus('412 Precondition failed'); + } + else + { + // URL parsen. + $dest = $this->destination; + $destinationProject = $dest['project']; + $destinationFolder = $dest['folder' ]; + $destinationObject = $dest['object' ]; + + if ( $dest['type'] != 'object' ) + { + Logger::debug('WEBDAV: COPY request, but "Destination:"-Header mismatch'); + $this->httpStatus('405 Not Allowed'); + } + elseif ( $this->project->projectid != $destinationProject->projectid ) + { + // Kopieren in anderes Projekt nicht moeglich. + Logger::debug('WEBDAV: COPY request denied, project does not match'); + $this->httpStatus('403 Forbidden'); + } + elseif ( $destinationObject != null ) + { + Logger::debug('WEBDAV: COPY request denied, Destination exists. Overwriting is not supported'); + $this->httpStatus('403 Forbidden'); + } + elseif ( is_object($destinationFolder) && ! $destinationFolder->hasRight( ACL_CREATE_FILE ) ) + { + $this->httpStatus('403 Forbidden' ); // Benutzer darf das nicht + } + elseif ( is_object($destinationObject) && $destinationObject->isFolder) + { + Logger::debug('WEBDAV: COPY request denied, Folder-Copy not implemented'); + $this->httpStatus('405 Not Allowed'); + } + elseif ( is_object($destinationObject) && $destinationObject->isLink) + { + Logger::debug('WEBDAV: COPY request denied, Link copy not implemented'); + $this->httpStatus('405 Not Allowed'); + } + elseif ( is_object($destinationObject) && $destinationObject->isPage) + { + Logger::debug('WEBDAV: COPY request denied, Page copy not implemented'); + $this->httpStatus('405 Not Allowed'); + } + else + { + $f = new File(); + $f->filename = basename($_SERVER['HTTP_DESTINATION']); + $f->name = ''; + $f->parentid = $destinationFolder->objectid; + $f->projectid = $this->project->projectid; + $f->add(); + $f->copyValueFromFile( $this->obj->objectid ); + + Logger::debug('WEBDAV: COPY request accepted' ); + // Objekt wird in anderen Ordner kopiert. + $this->httpStatus('201 Created' ); + } + } + + } + + + + /** + * Verschieben eines Objektes.<br> + * <br> + * Folgende Operationen sind m�glich:<br> + * - Unbenennen eines Objektes (alle Typen)<br> + * - Verschieben eines Objektes (alle Typen) in einen anderen Ordner.<br> + */ + function move() + { + if ( $this->readonly ) + { + $this->httpStatus('403 Forbidden - Readonly Mode' ); // Schreibgeschuetzt + } + elseif ( !$this->create ) + { + $this->httpStatus('403 Forbidden - No creation' ); // Schreibgeschuetzt + } + elseif( $this->obj == null ) + { + // Was nicht da ist, laesst sich auch nicht verschieben. + $this->httpStatus('404 Not Found' ); + } + elseif( is_object($this->obj) && ! $this->obj->hasRight( ACL_WRITE ) ) + { + // Was nicht da ist, laesst sich auch nicht verschieben. + Logger::error('Source '.$this->obj->objectid.' is not writable: Forbidden'); + $this->httpStatus('403 Forbidden' ); + } + elseif ( $this->destination == null ) + { + Logger::error('WEBDAV: MOVE request, but no "Destination:"-Header'); + // $this->httpStatus('405 Not Allowed' ); + $this->httpStatus('412 Precondition failed'); + } + else + { + $dest = $this->destination; + $destinationProject = $dest['project']; + $destinationFolder = $dest['folder' ]; + $destinationObject = $dest['object' ]; + + if ( $dest['type'] != 'object' ) + { + Logger::debug('WEBDAV: MOVE request, but "Destination:"-Header mismatch'); + $this->httpStatus('405 Not Allowed'); + return; + } + + if ( is_object($destinationFolder) && ! $destinationFolder->hasRight( ACL_CREATE_FILE ) ) + { + Logger::error('Source '.$this->obj->objectid.' is not writable: Forbidden'); + $this->httpStatus('403 Forbidden' ); + } + + if ( $destinationObject != null ) + { + Logger::debug('WEBDAV: MOVE request denied, destination exists'); + $this->httpStatus('412 Precondition Failed'); + return; + } + + if ( $this->project->projectid != $destinationProject->projectid ) + { + // Verschieben in anderes Projekt nicht moeglich. + Logger::debug('WEBDAV: MOVE request denied, project does not match'); + $this->httpStatus('405 Not Allowed'); + return; + } + + if ( $this->folder->objectid == $destinationFolder->objectid ) + { + Logger::debug('WEBDAV: MOVE request accepted, object renamed'); + // Resource bleibt in gleichem Ordner. + $this->obj->filename = basename($_SERVER['HTTP_DESTINATION']); + $this->obj->objectSave(false); + $this->httpStatus('201 Created' ); + return; + } + + if ( $destinationFolder->isFolder ) + { + Logger::debug('WEBDAV: MOVE request accepted, Destination: '.$destinationFolder->filename ); + // Objekt wird in anderen Ordner verschoben. + $this->obj->setParentId( $destinationFolder->objectid ); + $this->httpStatus('201 Created' ); + return; + } + + Logger::warn('WEBDAV: MOVE request failed' ); + $this->httpStatus('500 Internal Server Error' ); + } + } + + + + /** + * Anlegen oder �berschreiben Dateien �ber PUT.<br> + * Dateien k�nnen neu angelegt und �berschrieben werden.<br> + * <br> + * Seiten k�nnen nicht �berschrieben werden. Wird versucht, + * eine Seite mit PUT zu �berschreiben, wird der Status "405 Not Allowed" gemeldet.<br> + */ + function put() + { + // TODO: 409 (Conflict) wenn �bergeordneter Ordner nicht da. + + if ( $this->webdav_conf['readonly'] ) + { + $this->httpStatus('405 Not Allowed' ); + } + elseif ( strlen($this->request) > $this->maxFileSize*1000 ) + { + // Maximale Dateigroesse ueberschritten. + // Der Status 207 "Zuwenig Speicherplatz" passt nicht ganz, aber fast :) + $this->httpStatus('507 Insufficient Storage' ); + } + elseif ( $this->obj == null ) + { + // Neue Datei anlegen + if ( !$this->webdav_conf['create'] ) + { + Logger::warn('WEBDAV: Creation of files not allowed by configuration' ); + $this->httpStatus('405 Not Allowed' ); + } + + if ( ! $this->folder->hasRight( ACL_CREATE_FILE ) ) + { + $this->httpStatus('403 Forbidden'); + return; + } + + $file = new File(); + $file->filename = basename($this->fullSkriptName); + $file->extension = ''; + $file->size = strlen($this->request); + $file->parentid = $this->folder->objectid; + $file->projectid = $this->project->projectid; + $file->value = $this->request; + $file->add(); + $this->httpStatus('201 Created'); + return; + } + elseif ( $this->obj->isFile ) + { + if ( ! $this->obj->hasRight( ACL_WRITE ) ) + { + Logger::debug('PUT failed, parent folder not writable by user' ); + $this->httpStatus('403 Forbidden'); + return; + } + + // Bestehende Datei ueberschreiben. + $file = new File( $this->obj->objectid ); + $file->saveValue( $this->request ); + $file->setTimestamp(); + $this->httpStatus('204 No Content'); + Logger::debug('PUT ok, file is created' ); + return; + } + elseif ( $this->obj->isFolder ) + { + Logger::error('PUT on folder is not supported, use PROPFIND. Lame client?' ); + $this->httpStatus('405 Not Allowed' ); + } + else + { + // Fuer andere Objekttypen (Links, Seiten) ist kein PUT moeglich. + Logger::warn('PUT only available for files, pages and links are ignored' ); + $this->httpStatus('405 Not Allowed' ); + } + } + + + + /** + * WebDav-Methode PROPFIND. + * + * Diese Methode wird + * - beim Ermitteln von Verzeichnisinhalten und + * - beim Ermitteln von Metainformationen zu einer Datei + * verwendet. + * + * Das Ergebnis wird in einer XML-Zeichenkette geliefert. + */ + function propfind() + { + switch( $this->requestType ) + { + case 'projectlist': // Projektliste + + $inhalte = array(); + + $objektinhalt = array(); + $z = 30*365.25*24*60*60; + $objektinhalt['createdate' ] = $z; + $objektinhalt['lastchangedate'] = $z; + $objektinhalt['size' ] = 1; + $objektinhalt['name' ] = $this->fullSkriptName; + $objektinhalt['displayname' ] = ''; + $objektinhalt['type'] = 'folder'; + + $inhalte[] = $objektinhalt; + + foreach(Project::getAllProjects() as $projectid=> $projectName ) + { + $project = new Project( $projectid ); + $rootObjectId = $project->getRootObjectId(); + $folder = new Folder( $rootObjectId ); + $folder->load(); + + $objektinhalt = array(); + $z = 30*365.25*24*60*60; + $objektinhalt['createdate' ] = $z; + $objektinhalt['lastchangedate'] = $folder->lastchangeDate; + $objektinhalt['size' ] = $project->size(); + $objektinhalt['name' ] = $this->fullSkriptName.$projectName.'/'; + $objektinhalt['displayname' ] = $projectName; + $objektinhalt['type'] = 'folder'; + $inhalte[] = $objektinhalt; + } + + $this->multiStatus( $inhalte ); + break; + + case 'object': // Verzeichnisinhalt + + if ( $this->obj == null ) + { + // Objekt existiert nicht. + Logger::trace( 'WEBDAV: PROPFIND of non-existent object'); + $this->httpStatus('404 Not Found'); + return; + } + elseif ( $this->obj->isFolder ) + { + if ( ! $this->obj->hasRight( ACL_READ )) + { + Logger::debug( 'Folder '.$this->obj->objectid.': access denied'); + $this->httpStatus('403 Forbidden'); + } + + $inhalte = array(); + + $objektinhalt = array(); + $objektinhalt['createdate' ] = $this->obj->createDate; + $objektinhalt['lastchangedate'] = $this->obj->lastchangeDate; + $objektinhalt['name' ] = $this->fullSkriptName; + $objektinhalt['displayname' ] = basename($this->fullSkriptName); + $objektinhalt['type' ] = 'folder'; + $objektinhalt['size' ] = 0; + $inhalte[] = $objektinhalt; + + if ( $this->depth > 0 ) + { + $objects = $this->folder->getObjects(); + foreach( $objects as $object ) + { + if ( ! $object->hasRight( ACL_READ )) + continue; + + //$object->loadRaw(); + $objektinhalt = array(); + $objektinhalt['createdate' ] = $object->createDate; + $objektinhalt['lastchangedate'] = $object->lastchangeDate; + $objektinhalt['displayname' ] = $object->filename; + + switch( $object->getType() ) + { + + case OR_TYPE_FOLDER: + $objektinhalt['name'] = $this->fullSkriptName.$object->filename.'/'; + $objektinhalt['type'] = 'folder'; + $objektinhalt['size'] = 0; + $inhalte[] = $objektinhalt; + break; + case OR_TYPE_FILE: + $objektinhalt['name'] = $this->fullSkriptName.$object->filename; + $objektinhalt['type'] = 'file'; + $file = new File($object->objectid); + $file->load(); + $objektinhalt['size'] = $file->size; + $objektinhalt['mime'] = 'application/x-non-readable'; + $inhalte[] = $objektinhalt; + break; + case OR_TYPE_LINK: + $objektinhalt['name'] = $this->fullSkriptName.$object->filename; + $objektinhalt['type'] = 'file'; + $objektinhalt['size'] = 0; + $objektinhalt['mime'] = 'application/x-non-readable'; + $inhalte[] = $objektinhalt; + break; + case OR_TYPE_PAGE: + $objektinhalt['name'] = $this->fullSkriptName.$object->filename; + $objektinhalt['type'] = 'file'; + $objektinhalt['size'] = 0; + $inhalte[] = $objektinhalt; + break; + default: + } + } + } + Logger::trace( 'WEBDAV: PROPFIND-2'); + +// if ( count($inhalte)==0 ) +// $inhalte[] = array('createdate'=>0,'lastchangedate'=>0,'name'=>'empty','size'=>0,'type'=>'file'); + + Logger::trace('Anzahl Dateien:'.count($inhalte)); + $this->multiStatus( $inhalte ); + } + else + { + $object = $this->obj; + Logger::trace( 'WEBDAV: PROPFIND of file'); + $objektinhalt = array(); + $objektinhalt = array(); + $objektinhalt['name'] = $this->fullSkriptName.'/'.$object->filename.'/'; + $objektinhalt['displayname'] = $object->filename; + $objektinhalt['createdate' ] = $object->createDate; + $objektinhalt['lastchangedate'] = $object->lastchangeDate; + $file = new File( $this->obj->objectid ); + $file->load(); + $objektinhalt['size' ] = $file->size; + $objektinhalt['type' ] = 'file'; + + + $this->multiStatus( array($objektinhalt) ); + } + break; + + default: + Logger::warn('Internal Error, unknown request type: '. $this->requestType); + $this->httpStatus('500 Internal Server Error'); + } + } + + + /** + * Webdav-Methode PROPPATCH ist nicht implementiert. + */ + function proppatch() + { + // TODO: Multistatus erzeugen. + // Evtl. ist '409 Conflict' besser? + $this->httpStatus('405 Not Allowed'); + } + + + /** + * Erzeugt einen Multi-Status. + * @access private + */ + function multiStatus( $files ) + { + $this->httpStatus('207 Multi-Status'); + header('Content-Type: text/xml; charset=utf-8'); + + $response = ''; + $response .= '<?xml version="1.0" encoding="utf-8" ?>'; + $response .= '<d:multistatus xmlns:d="DAV:">'; + + foreach( $files as $file ) + $response .= $this->getResponse( $file['name'],$file ); + + $response .= '</d:multistatus>'; + Logger::trace('PROPFIND: '.$response); + + $response = utf8_encode($response); + + header('Content-Length: '.strlen($response)); + echo $response; + } + + + /** + * Erzeugt ein "response"-Element, welches in ein "multistatus"-element verwendet werden kann. + */ + function getResponse( $file,$options ) + { + // TODO: Nur angeforderte Elemente erzeugen. + $response = ''; + $response .= '<d:response>'; + $response .= '<d:href>'.$file.'</d:href>'; + $response .= '<d:propstat>'; + $response .= '<d:prop>'; + // $response .= '<d:source></d:source>'; + $response .= '<d:creationdate>'.date('r',$options['createdate']).'</d:creationdate>'; + $response .= '<d:displayname>'.$options['displayname'].'</d:displayname>'; + $response .= '<d:getcontentlength>'.$options['size'].'</d:getcontentlength>'; + $response .= '<d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">'.date('r',$options['lastchangedate']).'</d:getlastmodified>'; + + if ( $options['type'] == 'folder') + $response .= '<d:resourcetype><d:collection/></d:resourcetype>'; + else + $response .= '<d:resourcetype />'; + + $response .= '<d:categories />'; + $response .= '<d:fields></d:fields>'; + + + +// $response .= '<d:getcontenttype>text/html</d:getcontenttype>'; +// $response .= '<d:getcontentlength />'; +// $response .= '<d:getcontentlanguage />'; +// $response .= '<d:executable />'; +// $response .= '<d:resourcetype>'; +// $response .= '<d:collection />'; +// $response .= '</d:resourcetype>'; +// $response .= '<d:getetag />'; + + $response .= '</d:prop>'; + $response .= '<d:status>HTTP/1.1 200 OK</d:status>'; + $response .= '</d:propstat>'; + $response .= '</d:response>'; + + return $response; + } + + + + /** + * URI parsen. + */ + function parseURI( $uri ) + { + // Ergebnis initialisieren (damit alle Schl�ssel vorhanden sind) + $ergebnis = array('type' => null, + 'project' => null, + 'path' => array(), + 'folder' => null, + 'object' => null ); + + Logger::trace( 'WEBDAV: Parsen der URI '.$uri); + $uriParts = explode('/',$uri); + + $nr = 0; + $f = null; + $o = null; + $ergebnis['type'] = 'projectlist'; + + foreach( $uriParts as $uriPart ) + { + if ( empty( $uriPart)) + continue; + + $ergebnis['path'][] = $uriPart; + + if ( $f == null ) + { + // URI='/project/' + // Name des Projektes in der URL, es wird das Projekt geladen. + $ergebnis['type'] = 'object'; + + $p = new Project(); + $p->name = $uriPart; + Logger::trace("Projektname: ".$p->name); + $p->loadByName(); + $ergebnis['project'] = $p; + // Das Projekt hat weder Sprache noch Variante gesetzt. + //Session::setProjectLanguage( new Language( $this->project->getDefaultLanguageId() ) ); + //Session::setProjectModel ( new Model ( $this->project->getDefaultModelId() ) ); + + $oid = $p->getRootObjectId(); + + $f = new Folder($oid); + $ergebnis['object'] = $f; + $ergebnis['folder'] = $f; + + } + else + { + if ( $ergebnis['object'] == null ) + { + $this->httpStatus('409 Conflict'); + exit; + } + + $oid = $f->getObjectIdByFileName($uriPart); + + if ( $oid == 0 ) + { + Logger::trace( 'WEBDAV: URL-Part does not exist: '.$uriPart); + $ergebnis['object'] = null; + } + else + { + Logger::trace( 'Teil '.$uriPart); + $o = new BaseObject($oid); + $o->load(); + $ergebnis['object'] = $o; + + if ( $o->isFolder ) + { + $f = new Folder($oid); + $ergebnis['folder'] = $f; + } + } + } + } + + return $ergebnis; + } +} + + + +/** + * Fehler-Handler fuer WEBDAV.<br> + * Bei einem Laufzeitfehler ist eine Ausgabe des Fehlers auf der Standardausgabe sinnlos, + * da der WebDAV-Client dies nicht lesen oder erkennen kann. + * Daher wird der Fehler-Handler umgebogen, so dass nur ein Logeintrag sowie ein + * Server-Fehler erzeugt wird. + */ +function webdavErrorHandler($errno, $errstr, $errfile, $errline) +{ + Logger::warn('WEBDAV ERROR: '.$errno.'/'.$errstr.'/file:'.$errfile.'/line:'.$errline); + + // Wir teilen dem Client mit, dass auf dem Server was schief gelaufen ist. + WebdavAction::httpStatus('500 Internal Server Error, WebDAV-Request failed with "'.$errstr.'"'); +} + ?> \ No newline at end of file diff --git a/modules/cms-core/model/BaseObject.class.php b/modules/cms-core/model/BaseObject.class.php @@ -26,6 +26,7 @@ class BaseObject const TYPEID_IMAGE = 6; const TYPEID_TEXT = 7; const TYPEID_ALIAS = 8; + const TYPEID_MACRO = 9; const TYPE_FOLDER = 'folder'; const TYPE_FILE = 'file' ; @@ -35,6 +36,7 @@ class BaseObject const TYPE_IMAGE = 'image' ; const TYPE_TEXT = 'text' ; const TYPE_ALIAS = 'alias' ; + const TYPE_MACRO = 'macro' ; /** eindeutige ID dieses Objektes * @see #$objectid @@ -164,6 +166,12 @@ class BaseObject var $isAlias = false; /** + * Kennzeichen, ob Objekt ein Alias ist + * @type Boolean + */ + var $isMacro = false; + + /** * Kennzeichnet den Typ dieses Objektes. * Muss den Inhalt OR_FILE, OR_FOLDER, OR_PAGE oder OR_LINK haben. * Vorbelegung mit <code>null</code>. @@ -380,6 +388,8 @@ SQL return self::TYPE_URL; if ($this->isAlias) return self::TYPE_ALIAS; + if ($this->isMacro) + return self::TYPE_MACRO; return 'unknown'; } @@ -730,6 +740,7 @@ SQL $this->isLink = ( $row['typeid'] == self::TYPEID_LINK ); $this->isUrl = ( $row['typeid'] == self::TYPEID_URL ); $this->isAlias = ( $row['typeid'] == self::TYPEID_ALIAS ); + $this->isMacro = ( $row['typeid'] == self::TYPEID_MACRO ); } @@ -800,6 +811,7 @@ SQL $this->isLink = ( $row['typeid'] == self::TYPEID_LINK ); $this->isUrl = ( $row['typeid'] == self::TYPEID_URL ); $this->isAlias = ( $row['typeid'] == self::TYPEID_ALIAS ); + $this->isMacro = ( $row['typeid'] == self::TYPEID_MACRO ); if ( $this->isRoot ) { @@ -1310,6 +1322,7 @@ SQL if ($this->isLink ) return self::TYPEID_LINK; if ($this->isUrl ) return self::TYPEID_URL; if ($this->isAlias ) return self::TYPEID_ALIAS; + if ($this->isMacro ) return self::TYPEID_MACRO; } diff --git a/modules/cms-core/require.php b/modules/cms-core/require.php @@ -13,6 +13,7 @@ require_once(__DIR__ . '/../language/require.php'); // Internal baseclasses require_once(__DIR__ . '/action/Action.class.php'); +require_once(__DIR__ . '/action/BaseAction.class.php'); require_once(__DIR__ . '/action/ObjectAction.class.php'); require_once(__DIR__ . '/action/FileAction.class.php'); require_once(__DIR__ . '/action/RequestParams.class.php');