openrat-cms

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

commit 198e275165c6e5cfb0c41d7b8d4eec795af8d143
parent d8d60ab19dfac17b14f106941a41b4687d3b3d2b
Author: dankert <devnull@localhost>
Date:   Mon, 27 Dec 2010 23:45:50 +0100

Action-Klassen verschieben: actionClasses -> action

Diffstat:
action/Action.class.php | 761+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
actionClasses/Action.class.php | 761-------------------------------------------------------------------------------
2 files changed, 761 insertions(+), 761 deletions(-)

diff --git a/action/Action.class.php b/action/Action.class.php @@ -0,0 +1,760 @@ +<?php +// --------------------------------------------------------------------------- +// $Id$ +// --------------------------------------------------------------------------- +// OpenRat Content Management System +// Copyright (C) 2002-2004 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. + + +define('OR_NOTICE_OK' ,'ok' ); +define('OR_NOTICE_WARN' ,'warning'); +define('OR_NOTICE_ERROR','error' ); + +define('OR_FILTER_ALPHA' ,'abc' ); +define('OR_FILTER_ALPHANUM','abc123'); +define('OR_FILTER_FILENAME','file' ); +define('OR_FILTER_MAIL' ,'mail' ); +define('OR_FILTER_TEXT' ,'text' ); +define('OR_FILTER_FULL' ,'full' ); +define('OR_FILTER_NUMBER' ,'123' ); +define('OR_FILTER_RAW' ,'raw' ); +define('OR_FILTER_ALL' ,'all' ); + +/** + * Eltern-Klasse fuer alle Actions. + * + * Diese Klasse stellt grundlegende action-uebergreifende Methoden + * bereit. + * Dient als Ueberklasse fuer alle abgeleiteten Action-Klassen in + * diesem Package bzw. Verzeichnis. + * + * @author Jan Dankert + * @package openrat.actions + * @abstract + */ +class Action +{ + var $db; + var $templateVars = Array(); + var $actionName; + var $subActionName; + var $actionClassName; + + var $writable; + var $publishing; + var $actionConfig; + var $refresh; + + /** + * Aktuell angemeldeter Benutzer.<br> + * Wird ind er Funktion "init()" gesetzt. + * + * @var Object Benutzer + */ + var $currentUser; + + + + function setCharset( $charset ) + { + Session::set('charset',$charset); + } + + + + function setStyle( $style ) + { + Session::set('style',$style); + } + + + /** + * Wird durch das Controller-Skript (do.php) nach der Kontruierung des Objektes aufgerufen. + * So koennen Unterklassen ihren eigenen Kontruktor besitzen, ohne den Superkontruktor + * (=diese Funktion) aufrufen zu m�ssen. + */ + function init() + { + global $conf; + $this->writable = !$conf['security']['readonly' ]; + $this->publishing = !$conf['security']['nopublish']; + $this->currentUser = Session::getUser(); + + $this->templateVars['errors' ] = array(); + $this->templateVars['notices'] = array(); + + if ( !$this->isEditable() || isset($_COOKIE['or_always_edit']) ) + $this->templateVars['mode'] = 'edit'; + else + $this->templateVars['mode'] = $this->getRequestVar('mode'); + + header('Content-Language: '.$conf['language']['language_code']); + + $this->refresh = false; + } + + + /** + * Liest eine Session-Variable + * + * @param String $varName Schl�ssel + * @return mixed + */ + function getSessionVar( $varName ) + { + global $SESS; + + if ( !isset($SESS[ $varName ]) ) + return ''; + else return $SESS[ $varName ]; + } + + + /** + * Setzt eine Session-Variable + * + * @param Sring $varName Schl�ssel + * @param mixed $value Inhalt + * @return mixed + */ + function setSessionVar( $varName,$value ) + { + global $SESS; + + $SESS[ $varName ] = $value; + } + + + /** + * Ermittelt den Inhalt der gew�nschten Request-Variablen. + * Falls nicht vorhanden, wird "" zur�ckgegeben. + * + * @param String $varName Schl�ssel + * @return String Inhalt + */ + function getRequestVar( $varName,$transcode=OR_FILTER_FULL ) + { + global $REQ; + + if ( !isset($REQ[ $varName ]) ) + return ''; + + + switch( $transcode ) + { + case OR_FILTER_ALPHA: + $white = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + break; + + case OR_FILTER_ALPHANUM: + $white = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,_-!?%&/()'; + break; + + case OR_FILTER_FILENAME: + // RFC 1738, Section 2.2: + // Thus, only alphanumerics, the special characters "$-_.+!*'(),", and + // reserved characters used for their reserved purposes may be used + // unencoded within a URL. + $white = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$-_.+!*(),'."'"; + break; + + case OR_FILTER_MAIL: + $white = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-@'; + break; + + case OR_FILTER_TEXT: + case OR_FILTER_FULL: + case OR_FILTER_ALL: + // Ausfiltern von Control-Chars ( ASCII < 32 außer CR,LF) und HTML (<,>) + $white = ''; + $white .= chr(10).chr(13); // Line-Feed, Carriage-Return + for ($i = 32; $i <= 59; $i++) $white .= chr($i); // Zahlen + // 60: '<' + $white .= chr(61); + // 62: '>' + for ($i = 63; $i <= 126; $i++) $white .= chr($i); // abc + for ($i = 128; $i <= 255; $i++) $white .= chr($i); // Sonderzeichen incl. UTF-8, UTF-16 (beginnen mit Bit 1) + break; + + case OR_FILTER_NUMBER: + $white = '1234567890.'; + break; + + case OR_FILTER_RAW: + return $REQ[ $varName ]; + + default: + Http::serverError('Unknown request filter','not found: '.$transcode); + return '?'; + } + + $value = $REQ[ $varName ]; + $newValue = Text::clean( $value, $white ); + + if ( strlen($newValue) != strlen($value) ) + $this->addNotice('','','UNEXPECTED_CHARS',OR_NOTICE_WARN); + + return $newValue; + } + + + /** + * Ermittelt, ob der aktuelle Request eine Variable mit dem + * angegebenen Namen enth�lt. + * + * @param String $varName Schl�ssel + * @return boolean true, falls vorhanden. + */ + function hasRequestVar( $varName ) + { + global $REQ; + + return( isset($REQ[$varName]) && (!empty($REQ[$varName]) || $REQ[$varName]=='0') ); + } + + + /** + * Ermittelt die aktuelle Id aus dem Request.<br> + * Um welche ID es sich handelt, ist abh�ngig von der Action. + * + * @return Integer + */ + function getRequestId() + { + if ( $this->hasRequestVar('idvar') ) + return intval( $this->getRequestVar( $this->getRequestVar('idvar') ) ); + else + return intval( $this->getRequestVar( REQ_PARAM_ID ) ); + } + + + + /** + * Setzt eine Variable f�r die Oberfl�che. + * + * @param String $varName Schl�ssel + * @param Mixed $value + */ + function setTemplateVar( $varName,$value ) + { + $this->templateVars[ $varName ] = $value; + } + + + /** + * Setzt eine Liste von Variablen f�r die Oberfl�che. + * + * @param Array $varList Assoziatives Array + */ + function setTemplateVars( $varList ) + { + foreach( $varList as $name=>$value ) + { + $this->setTemplateVar( $name,$value ); + } + } + + + /** + * F�gt einen Validierungsfehler hinzu. + * + * @param String $name Name des validierten Eingabefeldes + * @param String Textschl�ssel der Fehlermeldung (optional) + */ + function addValidationError( $name,$message="COMMON_VALIDATION_ERROR",$vars=array(),$log=array() ) + { + if ( !empty($message) ) + $this->addNotice('','',$message,OR_NOTICE_ERROR,$vars,$log); + + $this->templateVars['errors'][] = $name; + } + + + /** + * F�gt ein Meldung hinzu. + * + * @param String $type Typ des Objektes, zu dem diese Meldung geh�rt. + * @param String $name Name des Objektes, zu dem diese Meldung geh�rt. + * @param String $text Textschl�ssel der Fehlermeldung (optional) + * @param String $status Einer der Werte OR_NOTICE_(OK|WARN|ERROR) + * @param Array $vars Variablen f�r den Textschl�ssel + * @param Array $log Weitere Hinweistexte f�r diese Meldung. + */ + function addNotice( $type,$name,$text,$status=OR_NOTICE_OK,$vars=array(),$log=array() ) + { + if ( $status === true ) + $status = OR_NOTICE_OK; + elseif ( $status === false ) + $status = OR_NOTICE_ERROR; + + $this->templateVars['notice_status'] = $status; + + if ( $status == OR_NOTICE_OK && isset($_COOKIE['or_ignore_ok_notices'])) + return; + + if ( !is_array($log)) + $log = array($log); + + if ( !is_array($vars)) + $vars = array($vars); + + $this->templateVars['notices'][] = array('type'=>$type, + 'name'=>$name, + 'key'=>'NOTICE_'.$text, + 'vars'=>$vars, + 'text'=>lang('NOTICE_'.$text,$vars), + 'log'=>$log, + 'status'=>$status); + } + + + + /** + * Ausgabe des Templates.<br> + * <br> + * Erst hier soll die Ausgabe auf die Standardausgabe, also die + * Ausgabe f�r den Browser, starten.<br> + * <br> + * + * @param String Wird nicht benutzt! + */ + function forward() + { + $db = db_connection(); + +// if ( isset($this->actionConfig[$this->subActionName]['direct']) ) +// { +// if ( is_object( $db ) ) +// $db->commit(); +// exit; // Die Ausgabe ist bereits erfolgt (z.B. Bin�rdateien o. WebDAV) +// } + + // Pruefen, ob HTTP-Header gesendet wurden. Dies deutet stark darauf hin, dass eine + // PHP-Fehlermeldung ausgegeben wurde. In diesem Fall wird hier abgebrochen. + // Weitere Ausgabe wuerde keinen Sinn machen, da wir nicht wissen, was + // passiert ist. +// if ( headers_sent() ) +// { +// Http::serverError("Some server error messages occured - see above - CMS canceled."); +// } + +// if ( is_object( $db ) ) +// $db->commit(); + + $expires = substr(gmdate('r'),0,-5).'GMT'; + //header('Expires: ' .$expires ); + + //header('X-Content-Security-Policy: '.'allow *; script-src \'self\'; options \'inline-script\''); + + + $httpAccept = getenv('HTTP_ACCEPT'); + $types = explode(',',$httpAccept); + + if ( version_compare(PHP_VERSION, '4.3.0', '>=') ) + Logger::trace('Output'."\n".print_r($this->templateVars,true)); + + // Weitere Variablen anreichern. + $this->templateVars['session'] = array('name'=>session_name(),'id'=>session_id(),'token'=>token() ); + $this->templateVars['version'] = OR_VERSION; + + if ( sizeof($types)==1 && in_array('application/php-array',$types) || $this->getRequestVar('output')=='php-array' ) + { + if (version_compare(PHP_VERSION, '4.3.0', '<')) + Http::serverError('application/php-array is only available with PHP >= 4.3'); + + header('Content-Type: application/php-array'); + echo print_r($this->templateVars,true); + exit; + } + + if ( sizeof($types)==1 && in_array('application/php-serialized',$types) || $this->getRequestVar('output')=='php' ) + { + header('Content-Type: application/php-serialized'); + serialize($this->templateVars); + exit; + } + + if ( sizeof($types)==1 && in_array('application/json',$types) || $this->getRequestVar('output')=='json' ) + { + require_once( OR_SERVICECLASSES_DIR."JSON.class.".PHP_EXT ); + $json = new JSON(); + header('Content-Type: application/json'); + echo $json->encode( $this->templateVars ); + exit; + } + + if ( sizeof($types)==1 && in_array('application/xml',$types) || $this->getRequestVar('output')=='xml' ) + { + require_once( OR_SERVICECLASSES_DIR."XML.class.".PHP_EXT ); + $xml = new XML(); + $xml->root = 'server'; // Name des XML-root-Elementes + header('Content-Type: application/xml'); + echo $xml->encode( $this->templateVars ); + exit; + } + + $this->setMenu(); + + $tplName = $this->actionName.'/'.$this->subActionName; + + + if ( isset($this->actionConfig[$this->subActionName]['action']) ) + $tplName = $this->actionConfig[$this->subActionName]['action'].'/'.$this->subActionName; + + if (isset($this->actionConfig[$this->subActionName]['alias'])) + $tplName = (method_exists(new ObjectAction(),$this->subActionName)?'object':$this->actionName).'/'.$this->actionConfig[$this->subActionName]['alias']; + + if (isset($this->actionConfig[$this->subActionName]['target'])) + $targetSubActionName = $this->actionConfig[$this->subActionName]['target']; + else + $targetSubActionName = $this->subActionName; + + + if ( isset($this->actionConfig[$this->subActionName]['menu'])) + $windowTitle = 'menu_title_'.$this->actionName.'_'.$this->actionConfig[$this->subActionName]['menu']; + + global $conf; + global $REQ; + global $PHP_SELF; + global $HTTP_SERVER_VARS; + global $image_dir; + + $tplName = str_replace( '_','/',$tplName ); + + $tplFileName = $tplName.'.tpl.'.PHP_EXT; + $conf_php = PHP_EXT; + + // ?bertragen der Array-Variablen in den aktuellen Kontext + // + extract( $this->templateVars ); + + // Falls Eingabefehler, dann Uebertragen der Request-Variablen in den aktuellen Kontext + if ( count($errors)>0 ) + foreach( $REQ as $requestVar=>$dummy ) + if ( !isset($$requestVar) ) + // Aber achtung, hier geben wir die Request-Variablen einfach so wieder raus! + $$requestVar = $this->getRequestVar( $requestVar ); + + // Setzen einiger Standard-Variablen + // + $tpl_dir = OR_THEMES_DIR.$conf['interface']['theme'].'/pages/html/'; + $image_dir = OR_THEMES_EXT_DIR.$conf['interface']['theme'].'/images/'; + + $user = Session::getUser(); + + $root_stylesheet = OR_THEMES_EXT_DIR.$conf['interface']['theme'].'/css/base.css'; + + if ( !is_object($user) ) + $user_stylesheet = OR_THEMES_EXT_DIR.$conf['interface']['theme'].'/css/'.$conf['interface']['style']['default'].'.css'; + else + $user_stylesheet = OR_THEMES_EXT_DIR.$conf['interface']['theme'].'/css/'.$user->style.'.css'; + + $self = $HTTP_SERVER_VARS['PHP_SELF']; + + $tplFileName = str_replace( '_','/',$tplFileName ); + + if ( !empty($conf['interface']['override_title']) ) + $cms_title = $conf['interface']['override_title']; + else + $cms_title = OR_TITLE.' '.OR_VERSION; + + $charset = $this->getCharset(); + + $showDuration = $conf['interface']['show_duration']; + + $subActionName = $this->subActionName; + $actionName = $this->actionName; + $requestId = $this->getRequestId(); + + if ( $conf['theme']['compiler']['enable'] ) + { + $te = new TemplateEngine(); + $te->compile( $tplName ); + unset($te); + } + + $iFile = $tpl_dir.$tplFileName; + //try + //{ + if ( is_file($iFile)) + // Einbinden des Templates + require_once( $iFile ); + else + echo "File not found: $iFile"; + //} + //catch( Exception $e ) + //{ + // echo "Error occured:".$e; + //} + } + + + /** + * Ruft eine weitere Subaction auf. + * + * @param String $subActionName Name der n�chsten Subaction. Es muss eine Methode mit diesem Namen geben. + */ + function callSubAction( $subActionName ) + { + if ( in_array($this->actionName,array('page','file','link','folder')) ) + Session::setSubaction( $subActionName ); + + $this->subActionName = $subActionName; + + Logger::trace("next subaction is '$subActionName'"); + + $this->$subActionName(); + } + + + /** + * Ermitteln, ob Benutzer Administratorrechte besitzt + * @return Boolean TRUE, falls der Benutzer ein Administrator ist. + */ + function userIsAdmin() + { + $user = Session::getUser(); + return is_object($user) && $user->isAdmin; + } + + + /** + * Ermitteln des Benutzerobjektes aus der Session + * @return User + */ + function getUserFromSession() + { + return Session::getUser(); + } + + + + /** + * Benutzen eines sog. "Conditional GET". + * + * Diese Funktion setzt einen "Last-Modified"-HTTP-Header. + * Ist der Inhalt der Seite nicht neuer, so wird der Inhalt + * der Seite nicht ausgegeben, sondern nur HTTP-Status 304 + * ("304 not modified") gesetzt. + * Der Rest der Seite muss dann nicht mehr erzeugt werden, + * wodurch die Performance stark erhoeht werden kann. + * Ggf. kann das Benutzen dieses Mechanismus zu unerw�nschten + * Effekten f�hren, dann muss "conditional GET" in der + * Konfiguration deaktiviert werden. + * + * Credits: Danke an Charles Miller + * @see http://fishbowl.pastiche.org/2002/10/21/http_conditional_get_for_rss_hackers + * + * Gefunden auf: + * @see http://simon.incutio.com/archive/2003/04/23/conditionalGet + * + * @param Timestamp Letztes Aenderungsdatum dieser Seite + */ + function lastModified( $time ) + { + return; + $user = Session::getUser(); + if ( $user->loginDate > $time && !isset($this->actionConfig[$this->subActionName]['direct']) ) + // Falls Benutzer-Login nach letzter �nderung. + // Zweck: Nach einem Login sollte mind. 1x jede Seite neu geladen werden, dies + // Ist z.B. nach einer Style-�nderung durch den Benutzer notwendig. + // Falls aus Versehen doch einmal zuviel gecacht wurde, kann man das durch ein + // Neu-Login beheben. + $time = $user->loginDate; + + // Conditional-Get eingeschaltet? + global $conf; + if ( ! $conf['cache']['conditional_get'] ) + return; + + $lastModified = substr(date('r',$time -date('Z')),0,-5).'GMT'; + $etag = '"'.md5($lastModified).'"'; + + // Header senden + header('Last-Modified: '.$lastModified ); + header('ETag: ' .$etag ); + + // Die vom Interpreter sonst automatisch gesetzten + // Header uebersteuern + header('Cache-Control: must-revalidate'); + header('Pragma:'); + + // See if the client has provided the required headers + $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false; + $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH'] ) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH'] ) : false; + + if ( !$if_modified_since && !$if_none_match ) + return; + + // At least one of the headers is there - check them + if ( $if_none_match && $if_none_match != $etag ) + return; // etag is there but doesn't match + + + if ( $if_modified_since && $if_modified_since != $lastModified ) + return; // if-modified-since is there but doesn't match + + // Der entfernte Browser bzw. Proxy holt die Seite nun aus seinem Cache + header('HTTP/1.0 304 Not Modified'); + exit; // Sofortiges Skript-Ende + } + + + + /** + * @param max Anzahl der Sekunden, die die Seite im Browsercache bleiben darf + */ + function maxAge( $max=3600 ) + { + // Die Header "Last-Modified" und "ETag" wurden bereits in der + // Methode "lastModified()" gesetzt. + + header('Expires: '.substr(date('r',time()-date('Z')+$max),0,-5).'GMT' ); + header('Pragma: '); // 'Pragma' ist Bullshit und + // wird von den meisten Browsern ignoriert. + header('Cache-Control: public, max-age='.$max.", s-maxage=".$max); + } + + + + function setMenu() + { + if (!isset($this->actionConfig[$this->subActionName]['menu'])) + return; + $windowMenu = array(); + $name = $this->actionConfig[$this->subActionName]['menu']; + $menuList = explode(',',$this->actionConfig['menu']['menu']); + //$menuList = explode(',',$this->actionConfig['menu'][$name]); + + if ( isset($this->actionConfig[$this->subActionName]['menuaction'])) + $actionName = $this->actionConfig[$this->subActionName]['menuaction']; + else + $actionName = $this->subActionName; + + foreach( $menuList as $menuName ) + { + if ( isset($this->actionConfig[$menuName]['alias']) ) + $menuText = 'menu_'.$this->actionName.'_'.$this->actionConfig[$menuName]['alias']; + else + $menuText = 'menu_'.$this->actionName.'_'.$menuName; + + + $menuKey = 'accesskey_window_'.$menuName; + + $menuEntry = array('subaction'=>$menuName, + 'text' =>$menuText, + 'title' =>$menuText.'_DESC', + 'key' =>$menuKey ); + + if ( $this->checkMenu($menuName) ) + $menuEntry['url'] = Html::url($actionName,$menuName,$this->getRequestId()); + + $windowMenu[] = $menuEntry; + } + $this->setTemplateVar('windowMenu',$windowMenu); + } + + + + /** + * Ermittelt, ob der Men�punkt aktiv ist. + * Ob ein Men�punkt als aktiv angezeigt werden soll, steht meist erst zur Laufzeit fest. + * <br> + * Diese Methode kann von den Unterklassen �berschrieben werden. + * Falls diese Methode nicht �berschrieben wird, sind alle Men�punkte aktiv. + * + * @param String $name Logischer Name des Men�punktes + * @return boolean TRUE, wenn Men�punkt aktiv ist. + */ + function checkMenu( $name ) + { + // Standard: Alle Men�punkt sind aktiv. + return true; + } + + + + /** + * Ermitelt den Zeichensatz fuer die Ausgabe. + * + * Falls für die Datenbank-Verbindung ein Zeichensatz angegeben ist, so wird + * dieser genommen und in HTTP-Response-Header sowieso auch im HTML-Kopf verwendet. + * + * Falls nicht vorhanden, wird der Zeichensatz aus der geladenen Sprachdatei verwendet. Diese + * ergibt sich dann aus der Sprache, die der Browser anfordert. + * + * @return String Zeichensatz + */ + function getCharset() + { + return charset(); + } + + + /** + * Stellt fest, ob die Anzeige dieser Aktion editierbar ist. + * + * @return boolean + */ + function isEditable() + { + return isset($this->actionConfig[$this->subActionName]['editable']) && $this->actionConfig[$this->subActionName]['editable']; + } + + + /** + * Sorgt dafür, dass alle anderen Views aktualisiert werden. + * + * Diese Methode sollte dann aufgerufen werden, wenn Objekte geändert werden + * und dies Einfluss auf andere Views hat. + */ + function refresh() + { + $this->refresh = true; + } + + + /** + * Stellt fest, ob sich die Anzeige im Editier-Modus befindet. + * + * @return boolean + */ + function isEditMode() + { + if ( readonly() ) + return false; + + return !$this->isEditable() || $this->getRequestVar('mode')=='edit' || isset($_COOKIE['or_always_edit']) || (isset($this->templateVars) && $this->templateVars['mode']=='edit'); + } + + + + /** + * + * @param $viewName + * @param $viewAction + * @param $viewSubaction + */ + function updateView( $viewName, $viewAction,$viewSubaction ) + { + global $views; + if ( array_key_exists($viewName,$views) ) + $views[$viewName] = array('action'=>$viewAction,'subaction'=>$viewSubaction); + } +} + +?>+ \ No newline at end of file diff --git a/actionClasses/Action.class.php b/actionClasses/Action.class.php @@ -1,760 +0,0 @@ -<?php -// --------------------------------------------------------------------------- -// $Id$ -// --------------------------------------------------------------------------- -// OpenRat Content Management System -// Copyright (C) 2002-2004 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. - - -define('OR_NOTICE_OK' ,'ok' ); -define('OR_NOTICE_WARN' ,'warning'); -define('OR_NOTICE_ERROR','error' ); - -define('OR_FILTER_ALPHA' ,'abc' ); -define('OR_FILTER_ALPHANUM','abc123'); -define('OR_FILTER_FILENAME','file' ); -define('OR_FILTER_MAIL' ,'mail' ); -define('OR_FILTER_TEXT' ,'text' ); -define('OR_FILTER_FULL' ,'full' ); -define('OR_FILTER_NUMBER' ,'123' ); -define('OR_FILTER_RAW' ,'raw' ); -define('OR_FILTER_ALL' ,'all' ); - -/** - * Eltern-Klasse fuer alle Actions. - * - * Diese Klasse stellt grundlegende action-uebergreifende Methoden - * bereit. - * Dient als Ueberklasse fuer alle abgeleiteten Action-Klassen in - * diesem Package bzw. Verzeichnis. - * - * @author Jan Dankert - * @package openrat.actions - * @abstract - */ -class Action -{ - var $db; - var $templateVars = Array(); - var $actionName; - var $subActionName; - var $actionClassName; - - var $writable; - var $publishing; - var $actionConfig; - var $refresh; - - /** - * Aktuell angemeldeter Benutzer.<br> - * Wird ind er Funktion "init()" gesetzt. - * - * @var Object Benutzer - */ - var $currentUser; - - - - function setCharset( $charset ) - { - Session::set('charset',$charset); - } - - - - function setStyle( $style ) - { - Session::set('style',$style); - } - - - /** - * Wird durch das Controller-Skript (do.php) nach der Kontruierung des Objektes aufgerufen. - * So koennen Unterklassen ihren eigenen Kontruktor besitzen, ohne den Superkontruktor - * (=diese Funktion) aufrufen zu m�ssen. - */ - function init() - { - global $conf; - $this->writable = !$conf['security']['readonly' ]; - $this->publishing = !$conf['security']['nopublish']; - $this->currentUser = Session::getUser(); - - $this->templateVars['errors' ] = array(); - $this->templateVars['notices'] = array(); - - if ( !$this->isEditable() || isset($_COOKIE['or_always_edit']) ) - $this->templateVars['mode'] = 'edit'; - else - $this->templateVars['mode'] = $this->getRequestVar('mode'); - - header('Content-Language: '.$conf['language']['language_code']); - - $this->refresh = false; - } - - - /** - * Liest eine Session-Variable - * - * @param String $varName Schl�ssel - * @return mixed - */ - function getSessionVar( $varName ) - { - global $SESS; - - if ( !isset($SESS[ $varName ]) ) - return ''; - else return $SESS[ $varName ]; - } - - - /** - * Setzt eine Session-Variable - * - * @param Sring $varName Schl�ssel - * @param mixed $value Inhalt - * @return mixed - */ - function setSessionVar( $varName,$value ) - { - global $SESS; - - $SESS[ $varName ] = $value; - } - - - /** - * Ermittelt den Inhalt der gew�nschten Request-Variablen. - * Falls nicht vorhanden, wird "" zur�ckgegeben. - * - * @param String $varName Schl�ssel - * @return String Inhalt - */ - function getRequestVar( $varName,$transcode=OR_FILTER_FULL ) - { - global $REQ; - - if ( !isset($REQ[ $varName ]) ) - return ''; - - - switch( $transcode ) - { - case OR_FILTER_ALPHA: - $white = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - break; - - case OR_FILTER_ALPHANUM: - $white = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,_-!?%&/()'; - break; - - case OR_FILTER_FILENAME: - // RFC 1738, Section 2.2: - // Thus, only alphanumerics, the special characters "$-_.+!*'(),", and - // reserved characters used for their reserved purposes may be used - // unencoded within a URL. - $white = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$-_.+!*(),'."'"; - break; - - case OR_FILTER_MAIL: - $white = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-@'; - break; - - case OR_FILTER_TEXT: - case OR_FILTER_FULL: - case OR_FILTER_ALL: - // Ausfiltern von Control-Chars ( ASCII < 32 außer CR,LF) und HTML (<,>) - $white = ''; - $white .= chr(10).chr(13); // Line-Feed, Carriage-Return - for ($i = 32; $i <= 59; $i++) $white .= chr($i); // Zahlen - // 60: '<' - $white .= chr(61); - // 62: '>' - for ($i = 63; $i <= 126; $i++) $white .= chr($i); // abc - for ($i = 128; $i <= 255; $i++) $white .= chr($i); // Sonderzeichen incl. UTF-8, UTF-16 (beginnen mit Bit 1) - break; - - case OR_FILTER_NUMBER: - $white = '1234567890.'; - break; - - case OR_FILTER_RAW: - return $REQ[ $varName ]; - - default: - Http::serverError('Unknown request filter','not found: '.$transcode); - return '?'; - } - - $value = $REQ[ $varName ]; - $newValue = Text::clean( $value, $white ); - - if ( strlen($newValue) != strlen($value) ) - $this->addNotice('','','UNEXPECTED_CHARS',OR_NOTICE_WARN); - - return $newValue; - } - - - /** - * Ermittelt, ob der aktuelle Request eine Variable mit dem - * angegebenen Namen enth�lt. - * - * @param String $varName Schl�ssel - * @return boolean true, falls vorhanden. - */ - function hasRequestVar( $varName ) - { - global $REQ; - - return( isset($REQ[$varName]) && (!empty($REQ[$varName]) || $REQ[$varName]=='0') ); - } - - - /** - * Ermittelt die aktuelle Id aus dem Request.<br> - * Um welche ID es sich handelt, ist abh�ngig von der Action. - * - * @return Integer - */ - function getRequestId() - { - if ( $this->hasRequestVar('idvar') ) - return intval( $this->getRequestVar( $this->getRequestVar('idvar') ) ); - else - return intval( $this->getRequestVar( REQ_PARAM_ID ) ); - } - - - - /** - * Setzt eine Variable f�r die Oberfl�che. - * - * @param String $varName Schl�ssel - * @param Mixed $value - */ - function setTemplateVar( $varName,$value ) - { - $this->templateVars[ $varName ] = $value; - } - - - /** - * Setzt eine Liste von Variablen f�r die Oberfl�che. - * - * @param Array $varList Assoziatives Array - */ - function setTemplateVars( $varList ) - { - foreach( $varList as $name=>$value ) - { - $this->setTemplateVar( $name,$value ); - } - } - - - /** - * F�gt einen Validierungsfehler hinzu. - * - * @param String $name Name des validierten Eingabefeldes - * @param String Textschl�ssel der Fehlermeldung (optional) - */ - function addValidationError( $name,$message="COMMON_VALIDATION_ERROR",$vars=array(),$log=array() ) - { - if ( !empty($message) ) - $this->addNotice('','',$message,OR_NOTICE_ERROR,$vars,$log); - - $this->templateVars['errors'][] = $name; - } - - - /** - * F�gt ein Meldung hinzu. - * - * @param String $type Typ des Objektes, zu dem diese Meldung geh�rt. - * @param String $name Name des Objektes, zu dem diese Meldung geh�rt. - * @param String $text Textschl�ssel der Fehlermeldung (optional) - * @param String $status Einer der Werte OR_NOTICE_(OK|WARN|ERROR) - * @param Array $vars Variablen f�r den Textschl�ssel - * @param Array $log Weitere Hinweistexte f�r diese Meldung. - */ - function addNotice( $type,$name,$text,$status=OR_NOTICE_OK,$vars=array(),$log=array() ) - { - if ( $status === true ) - $status = OR_NOTICE_OK; - elseif ( $status === false ) - $status = OR_NOTICE_ERROR; - - $this->templateVars['notice_status'] = $status; - - if ( $status == OR_NOTICE_OK && isset($_COOKIE['or_ignore_ok_notices'])) - return; - - if ( !is_array($log)) - $log = array($log); - - if ( !is_array($vars)) - $vars = array($vars); - - $this->templateVars['notices'][] = array('type'=>$type, - 'name'=>$name, - 'key'=>'NOTICE_'.$text, - 'vars'=>$vars, - 'text'=>lang('NOTICE_'.$text,$vars), - 'log'=>$log, - 'status'=>$status); - } - - - - /** - * Ausgabe des Templates.<br> - * <br> - * Erst hier soll die Ausgabe auf die Standardausgabe, also die - * Ausgabe f�r den Browser, starten.<br> - * <br> - * - * @param String Wird nicht benutzt! - */ - function forward() - { - $db = db_connection(); - -// if ( isset($this->actionConfig[$this->subActionName]['direct']) ) -// { -// if ( is_object( $db ) ) -// $db->commit(); -// exit; // Die Ausgabe ist bereits erfolgt (z.B. Bin�rdateien o. WebDAV) -// } - - // Pruefen, ob HTTP-Header gesendet wurden. Dies deutet stark darauf hin, dass eine - // PHP-Fehlermeldung ausgegeben wurde. In diesem Fall wird hier abgebrochen. - // Weitere Ausgabe wuerde keinen Sinn machen, da wir nicht wissen, was - // passiert ist. -// if ( headers_sent() ) -// { -// Http::serverError("Some server error messages occured - see above - CMS canceled."); -// } - -// if ( is_object( $db ) ) -// $db->commit(); - - $expires = substr(gmdate('r'),0,-5).'GMT'; - //header('Expires: ' .$expires ); - - //header('X-Content-Security-Policy: '.'allow *; script-src \'self\'; options \'inline-script\''); - - - $httpAccept = getenv('HTTP_ACCEPT'); - $types = explode(',',$httpAccept); - - if ( version_compare(PHP_VERSION, '4.3.0', '>=') ) - Logger::trace('Output'."\n".print_r($this->templateVars,true)); - - // Weitere Variablen anreichern. - $this->templateVars['session'] = array('name'=>session_name(),'id'=>session_id(),'token'=>token() ); - $this->templateVars['version'] = OR_VERSION; - - if ( sizeof($types)==1 && in_array('application/php-array',$types) || $this->getRequestVar('output')=='php-array' ) - { - if (version_compare(PHP_VERSION, '4.3.0', '<')) - Http::serverError('application/php-array is only available with PHP >= 4.3'); - - header('Content-Type: application/php-array'); - echo print_r($this->templateVars,true); - exit; - } - - if ( sizeof($types)==1 && in_array('application/php-serialized',$types) || $this->getRequestVar('output')=='php' ) - { - header('Content-Type: application/php-serialized'); - serialize($this->templateVars); - exit; - } - - if ( sizeof($types)==1 && in_array('application/json',$types) || $this->getRequestVar('output')=='json' ) - { - require_once( OR_SERVICECLASSES_DIR."JSON.class.".PHP_EXT ); - $json = new JSON(); - header('Content-Type: application/json'); - echo $json->encode( $this->templateVars ); - exit; - } - - if ( sizeof($types)==1 && in_array('application/xml',$types) || $this->getRequestVar('output')=='xml' ) - { - require_once( OR_SERVICECLASSES_DIR."XML.class.".PHP_EXT ); - $xml = new XML(); - $xml->root = 'server'; // Name des XML-root-Elementes - header('Content-Type: application/xml'); - echo $xml->encode( $this->templateVars ); - exit; - } - - $this->setMenu(); - - $tplName = $this->actionName.'/'.$this->subActionName; - - - if ( isset($this->actionConfig[$this->subActionName]['action']) ) - $tplName = $this->actionConfig[$this->subActionName]['action'].'/'.$this->subActionName; - - if (isset($this->actionConfig[$this->subActionName]['alias'])) - $tplName = (method_exists(new ObjectAction(),$this->subActionName)?'object':$this->actionName).'/'.$this->actionConfig[$this->subActionName]['alias']; - - if (isset($this->actionConfig[$this->subActionName]['target'])) - $targetSubActionName = $this->actionConfig[$this->subActionName]['target']; - else - $targetSubActionName = $this->subActionName; - - - if ( isset($this->actionConfig[$this->subActionName]['menu'])) - $windowTitle = 'menu_title_'.$this->actionName.'_'.$this->actionConfig[$this->subActionName]['menu']; - - global $conf; - global $REQ; - global $PHP_SELF; - global $HTTP_SERVER_VARS; - global $image_dir; - - $tplName = str_replace( '_','/',$tplName ); - - $tplFileName = $tplName.'.tpl.'.PHP_EXT; - $conf_php = PHP_EXT; - - // ?bertragen der Array-Variablen in den aktuellen Kontext - // - extract( $this->templateVars ); - - // Falls Eingabefehler, dann Uebertragen der Request-Variablen in den aktuellen Kontext - if ( count($errors)>0 ) - foreach( $REQ as $requestVar=>$dummy ) - if ( !isset($$requestVar) ) - // Aber achtung, hier geben wir die Request-Variablen einfach so wieder raus! - $$requestVar = $this->getRequestVar( $requestVar ); - - // Setzen einiger Standard-Variablen - // - $tpl_dir = OR_THEMES_DIR.$conf['interface']['theme'].'/pages/html/'; - $image_dir = OR_THEMES_EXT_DIR.$conf['interface']['theme'].'/images/'; - - $user = Session::getUser(); - - $root_stylesheet = OR_THEMES_EXT_DIR.$conf['interface']['theme'].'/css/base.css'; - - if ( !is_object($user) ) - $user_stylesheet = OR_THEMES_EXT_DIR.$conf['interface']['theme'].'/css/'.$conf['interface']['style']['default'].'.css'; - else - $user_stylesheet = OR_THEMES_EXT_DIR.$conf['interface']['theme'].'/css/'.$user->style.'.css'; - - $self = $HTTP_SERVER_VARS['PHP_SELF']; - - $tplFileName = str_replace( '_','/',$tplFileName ); - - if ( !empty($conf['interface']['override_title']) ) - $cms_title = $conf['interface']['override_title']; - else - $cms_title = OR_TITLE.' '.OR_VERSION; - - $charset = $this->getCharset(); - - $showDuration = $conf['interface']['show_duration']; - - $subActionName = $this->subActionName; - $actionName = $this->actionName; - $requestId = $this->getRequestId(); - - if ( $conf['theme']['compiler']['enable'] ) - { - $te = new TemplateEngine(); - $te->compile( $tplName ); - unset($te); - } - - $iFile = $tpl_dir.$tplFileName; - //try - //{ - if ( is_file($iFile)) - // Einbinden des Templates - require_once( $iFile ); - else - echo "File not found: $iFile"; - //} - //catch( Exception $e ) - //{ - // echo "Error occured:".$e; - //} - } - - - /** - * Ruft eine weitere Subaction auf. - * - * @param String $subActionName Name der n�chsten Subaction. Es muss eine Methode mit diesem Namen geben. - */ - function callSubAction( $subActionName ) - { - if ( in_array($this->actionName,array('page','file','link','folder')) ) - Session::setSubaction( $subActionName ); - - $this->subActionName = $subActionName; - - Logger::trace("next subaction is '$subActionName'"); - - $this->$subActionName(); - } - - - /** - * Ermitteln, ob Benutzer Administratorrechte besitzt - * @return Boolean TRUE, falls der Benutzer ein Administrator ist. - */ - function userIsAdmin() - { - $user = Session::getUser(); - return is_object($user) && $user->isAdmin; - } - - - /** - * Ermitteln des Benutzerobjektes aus der Session - * @return User - */ - function getUserFromSession() - { - return Session::getUser(); - } - - - - /** - * Benutzen eines sog. "Conditional GET". - * - * Diese Funktion setzt einen "Last-Modified"-HTTP-Header. - * Ist der Inhalt der Seite nicht neuer, so wird der Inhalt - * der Seite nicht ausgegeben, sondern nur HTTP-Status 304 - * ("304 not modified") gesetzt. - * Der Rest der Seite muss dann nicht mehr erzeugt werden, - * wodurch die Performance stark erhoeht werden kann. - * Ggf. kann das Benutzen dieses Mechanismus zu unerw�nschten - * Effekten f�hren, dann muss "conditional GET" in der - * Konfiguration deaktiviert werden. - * - * Credits: Danke an Charles Miller - * @see http://fishbowl.pastiche.org/2002/10/21/http_conditional_get_for_rss_hackers - * - * Gefunden auf: - * @see http://simon.incutio.com/archive/2003/04/23/conditionalGet - * - * @param Timestamp Letztes Aenderungsdatum dieser Seite - */ - function lastModified( $time ) - { - return; - $user = Session::getUser(); - if ( $user->loginDate > $time && !isset($this->actionConfig[$this->subActionName]['direct']) ) - // Falls Benutzer-Login nach letzter �nderung. - // Zweck: Nach einem Login sollte mind. 1x jede Seite neu geladen werden, dies - // Ist z.B. nach einer Style-�nderung durch den Benutzer notwendig. - // Falls aus Versehen doch einmal zuviel gecacht wurde, kann man das durch ein - // Neu-Login beheben. - $time = $user->loginDate; - - // Conditional-Get eingeschaltet? - global $conf; - if ( ! $conf['cache']['conditional_get'] ) - return; - - $lastModified = substr(date('r',$time -date('Z')),0,-5).'GMT'; - $etag = '"'.md5($lastModified).'"'; - - // Header senden - header('Last-Modified: '.$lastModified ); - header('ETag: ' .$etag ); - - // Die vom Interpreter sonst automatisch gesetzten - // Header uebersteuern - header('Cache-Control: must-revalidate'); - header('Pragma:'); - - // See if the client has provided the required headers - $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false; - $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH'] ) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH'] ) : false; - - if ( !$if_modified_since && !$if_none_match ) - return; - - // At least one of the headers is there - check them - if ( $if_none_match && $if_none_match != $etag ) - return; // etag is there but doesn't match - - - if ( $if_modified_since && $if_modified_since != $lastModified ) - return; // if-modified-since is there but doesn't match - - // Der entfernte Browser bzw. Proxy holt die Seite nun aus seinem Cache - header('HTTP/1.0 304 Not Modified'); - exit; // Sofortiges Skript-Ende - } - - - - /** - * @param max Anzahl der Sekunden, die die Seite im Browsercache bleiben darf - */ - function maxAge( $max=3600 ) - { - // Die Header "Last-Modified" und "ETag" wurden bereits in der - // Methode "lastModified()" gesetzt. - - header('Expires: '.substr(date('r',time()-date('Z')+$max),0,-5).'GMT' ); - header('Pragma: '); // 'Pragma' ist Bullshit und - // wird von den meisten Browsern ignoriert. - header('Cache-Control: public, max-age='.$max.", s-maxage=".$max); - } - - - - function setMenu() - { - if (!isset($this->actionConfig[$this->subActionName]['menu'])) - return; - $windowMenu = array(); - $name = $this->actionConfig[$this->subActionName]['menu']; - $menuList = explode(',',$this->actionConfig['menu']['menu']); - //$menuList = explode(',',$this->actionConfig['menu'][$name]); - - if ( isset($this->actionConfig[$this->subActionName]['menuaction'])) - $actionName = $this->actionConfig[$this->subActionName]['menuaction']; - else - $actionName = $this->subActionName; - - foreach( $menuList as $menuName ) - { - if ( isset($this->actionConfig[$menuName]['alias']) ) - $menuText = 'menu_'.$this->actionName.'_'.$this->actionConfig[$menuName]['alias']; - else - $menuText = 'menu_'.$this->actionName.'_'.$menuName; - - - $menuKey = 'accesskey_window_'.$menuName; - - $menuEntry = array('subaction'=>$menuName, - 'text' =>$menuText, - 'title' =>$menuText.'_DESC', - 'key' =>$menuKey ); - - if ( $this->checkMenu($menuName) ) - $menuEntry['url'] = Html::url($actionName,$menuName,$this->getRequestId()); - - $windowMenu[] = $menuEntry; - } - $this->setTemplateVar('windowMenu',$windowMenu); - } - - - - /** - * Ermittelt, ob der Men�punkt aktiv ist. - * Ob ein Men�punkt als aktiv angezeigt werden soll, steht meist erst zur Laufzeit fest. - * <br> - * Diese Methode kann von den Unterklassen �berschrieben werden. - * Falls diese Methode nicht �berschrieben wird, sind alle Men�punkte aktiv. - * - * @param String $name Logischer Name des Men�punktes - * @return boolean TRUE, wenn Men�punkt aktiv ist. - */ - function checkMenu( $name ) - { - // Standard: Alle Men�punkt sind aktiv. - return true; - } - - - - /** - * Ermitelt den Zeichensatz fuer die Ausgabe. - * - * Falls für die Datenbank-Verbindung ein Zeichensatz angegeben ist, so wird - * dieser genommen und in HTTP-Response-Header sowieso auch im HTML-Kopf verwendet. - * - * Falls nicht vorhanden, wird der Zeichensatz aus der geladenen Sprachdatei verwendet. Diese - * ergibt sich dann aus der Sprache, die der Browser anfordert. - * - * @return String Zeichensatz - */ - function getCharset() - { - return charset(); - } - - - /** - * Stellt fest, ob die Anzeige dieser Aktion editierbar ist. - * - * @return boolean - */ - function isEditable() - { - return isset($this->actionConfig[$this->subActionName]['editable']) && $this->actionConfig[$this->subActionName]['editable']; - } - - - /** - * Sorgt dafür, dass alle anderen Views aktualisiert werden. - * - * Diese Methode sollte dann aufgerufen werden, wenn Objekte geändert werden - * und dies Einfluss auf andere Views hat. - */ - function refresh() - { - $this->refresh = true; - } - - - /** - * Stellt fest, ob sich die Anzeige im Editier-Modus befindet. - * - * @return boolean - */ - function isEditMode() - { - if ( readonly() ) - return false; - - return !$this->isEditable() || $this->getRequestVar('mode')=='edit' || isset($_COOKIE['or_always_edit']) || (isset($this->templateVars) && $this->templateVars['mode']=='edit'); - } - - - - /** - * - * @param $viewName - * @param $viewAction - * @param $viewSubaction - */ - function updateView( $viewName, $viewAction,$viewSubaction ) - { - global $views; - if ( array_key_exists($viewName,$views) ) - $views[$viewName] = array('action'=>$viewAction,'subaction'=>$viewSubaction); - } -} - -?>- \ No newline at end of file