openrat-cms

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

commit f9194cdb9a9a887627bc6802c353b54af5809860
parent 653e98126f057fefd752f2b626bb3207fa77484b
Author: Jan Dankert <devnull@localhost>
Date:   Sat, 30 Dec 2017 01:10:23 +0100

Schreibzugriffe aus dem HTML-UI sollen die API aufrufen. Die API ist jetzt auch soweit wieder funktionsfähig. Insgesamt noch weiter aufgeräumt und nach Modulen unterteilt.

Diffstat:
api/index.php | 16+++++++++++++++-
functions/db.inc.php | 33---------------------------------
index.php | 17+++++++++++++----
modules/cms-api/API.class.php | 163+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
modules/cms-api/api.php | 14--------------
modules/cms-api/dispatcher.php | 296-------------------------------------------------------------------------------
modules/cms-api/require.php | 4++--
modules/cms-core/Dispatcher.class.php | 6------
modules/cms-core/action/Action.class.php | 30++----------------------------
modules/cms-core/init.php | 19++++++++-----------
modules/cms-core/require.php | 11+++++++++--
modules/cms-ui/UI.class.php | 146+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
modules/cms-ui/require.php | 4++--
modules/cms-ui/ui.php | 117-------------------------------------------------------------------------------
modules/configuration/Configuration.class.php | 2+-
modules/template-engine/components/html/form/form.js | 5+++--
modules/template-engine/components/html/form/form.min.js | 4++--
17 files changed, 366 insertions(+), 521 deletions(-)

diff --git a/api/index.php b/api/index.php @@ -1,5 +1,19 @@ <?php +// Excecuting the CMS application programming interface (API) + +require('../modules/cms-api/require.php'); + +use cms_api\API; + +try { + + API::execute(); + +} catch (Exception $e) { + + echo $e->getMessage(); + +} -require('../modules/cms-api/api.php'); ?> \ No newline at end of file diff --git a/functions/db.inc.php b/functions/db.inc.php @@ -1,32 +0,0 @@ -<?php -// 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. - - -/** - * Liefert die Datenbankverbindung fuer die aktuelle Sitzung. - * - * @return \database\Database - */ -function db_connection() -{ - - return Session::getDatabase(); -} - - -?>- \ No newline at end of file diff --git a/index.php b/index.php @@ -1,7 +1,17 @@ <?php - +// Excecuting the CMS user interface (UI) require('modules/cms-ui/require.php'); -require('modules/cms-ui/ui.php'); +use cms_ui\UI; + +try { + + UI::execute(); + +} catch (Exception $e) { + + echo '<h2>CMS UI Error</h2>'; + echo '<pre>' . $e->getMessage() . '</pre>'; + +} -?>- \ No newline at end of file diff --git a/modules/cms-api/API.class.php b/modules/cms-api/API.class.php @@ -0,0 +1,163 @@ +<?php + +namespace cms_api; + +use BadMethodCallException; +use cms\Dispatcher; +use Exception; +use JSON; +use Logger; +use ObjectNotFoundException; +use OpenRatException; +use SecurityException; +use XML; + +define('CMS_API_REQ_PARAM_SUBACTION', 'subaction'); +define('CMS_API_REQ_PARAM_ACTION', 'action'); + +define('CMS_API_OUTPUT_PHPARRAY', 1); +define('CMS_API_OUTPUT_PHPSERIALIZE', 2); +define('CMS_API_OUTPUT_JSON', 3); +define('CMS_API_OUTPUT_XML', 4); + +class API +{ + /** + * Führt einen API-Request durch. + */ + public static function execute() + { + $data = array(); + + try { + $action = $_REQUEST[CMS_API_REQ_PARAM_ACTION]; + $subaction = $_REQUEST[CMS_API_REQ_PARAM_SUBACTION]; + + $dispatcher = new Dispatcher(); + + $dispatcher->action = $action; + $dispatcher->subaction = $subaction; + + $data = $dispatcher->doAction(); + + } catch (BadMethodCallException $e) { + + API::sendHTTPStatus(500, 'Method not found'); + $data = array('status' => 500, 'error' => 'Method not found', 'description' => $e->getMessage(), 'reason' => $e->getCode()); + } catch (ObjectNotFoundException $e) { + + API::sendHTTPStatus(500, 'Object not found'); + $data = array('status' => 500, 'error' => 'Object not found', 'description' => $e->getMessage(), 'reason' => $e->getCode()); + } catch (OpenRatException $e) { + + API::sendHTTPStatus(500, 'Internal CMS Error'); + $data = array('status' => 500, 'error' => 'Internal CMS error', 'description' => $e->getMessage(), 'reason' => $e->getCode()); + } catch (SecurityException $e) { + + Logger::info('API request not allowed: ' . $e->getMessage()); + API::sendHTTPStatus(403, 'Forbidden'); + $data = array('status' => 403, 'error' => 'You are not allowed to execute this action.', 'description' => $e->getMessage(), 'reason' => $e->getCode()); + } catch (Exception $e) { + + API::sendHTTPStatus(500, 'Internal Server Error'); + $data = array('status' => 500, 'error' => 'Internal CMS error', 'description' => $e->getMessage(), 'reason' => $e->getCode()); + } + + + if (Logger::$level >= LOGGER_LOG_TRACE) + Logger::trace('Output' . "\n" . print_r($data, true)); + + // Weitere Variablen anreichern. + $data['session'] = array('name' => session_name(), 'id' => session_id(), 'token' => token()); + $data['version'] = OR_VERSION; + $data['api'] = '2'; + + + switch (API::discoverOutputType()) { + + case CMS_API_OUTPUT_PHPARRAY: + header('Content-Type: application/php-array; charset=UTF-8'); + $output = print_r($data, true); + break; + + case CMS_API_OUTPUT_PHPSERIALIZE: + header('Content-Type: application/php-serialized; charset=UTF-8'); + $output = serialize($data); + break; + + case CMS_API_OUTPUT_JSON: + header('Content-Type: application/json; charset=UTF-8'); + if (function_exists('json_encode')) + { + // Native Methode ist schneller.. + $output = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK | JSON_PARTIAL_OUTPUT_ON_ERROR); + } + else + { + // Fallback, falls json_encode() nicht existiert... + $json = new JSON(); + $output = $json->encode($data); + } + break; + + case CMS_API_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; charset=UTF-8'); + $output = $xml->encode($data); + exit; + break; + } + + + if (!headers_sent()) + // HTTP Spec: + // Applications SHOULD use this field to indicate the transfer-length of the message-body, unless this is prohibited by the rules in section 4.4. + // + // And the overhead of Transfer-Encoding chunked is eliminated... + header('Content-Length: ' . strlen($output)); + + echo $output; + + } + + /** + * Ermittelt den Output-Type für diesen API-Request. + * + * @return int Konstante CMS_API_OUTPUT_* + */ + private static function discoverOutputType() + { + $httpAccept = getenv('HTTP_ACCEPT'); + $types = explode(',', $httpAccept); + + $reqOutput = @$_REQUEST['output']; + + if (sizeof($types) == 1 && in_array('application/php-array', $types) || $reqOutput == 'php-array') + return CMS_API_OUTPUT_PHPARRAY; + + if (sizeof($types) == 1 && in_array('application/php-serialized', $types) || $reqOutput == 'php') + return CMS_API_OUTPUT_PHPSERIALIZE; + + if (sizeof($types) == 1 && in_array('application/json', $types) || $reqOutput == 'json') + return CMS_API_OUTPUT_JSON; + + if (sizeof($types) == 1 && in_array('application/xml', $types) || $reqOutput == 'xml') + return CMS_API_OUTPUT_XML; + + } + + /** + * @param $status int HTTP-Status + * @param $text string Statustext + */ + private static function sendHTTPStatus($status, $text) + { + if (headers_sent()) { + echo "$status $text"; + } else { + header('HTTP/1.0 ' . intval($status) . ' ' . $text); + } + } +} diff --git a/modules/cms-api/api.php b/modules/cms-api/api.php @@ -1,13 +0,0 @@ -<?php - -if (version_compare(PHP_VERSION, '5.3.0', '<')) - die("Sorry, PHP 5.3 is required."); - -// Welcome to OpenRat content management system. - -$_GET['action'] = 'index'; -$_GET['subaction'] = 'show'; - -require('dispatcher.php'); - -?>- \ No newline at end of file diff --git a/modules/cms-api/dispatcher.php b/modules/cms-api/dispatcher.php @@ -1,295 +0,0 @@ -<?php -// OpenRat Content Management System -// Copyright (C) 2002-2009 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; 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. - - - -// Diese Datei dient als "Dispatcher" und startet den zum Request passenden Controller ("*Action").. -// Jeder Request in der Anwendung läuft durch dieses Skript. -// -// Statische Resourcen (CSS,JS,Bilder,...) gehen nicht über diesen Dispatcher, sondern werden -// direkt geladen. - -try -{ - require_once( 'init.php' ); - - - // Werkzeugklassen einbinden. - require_once( OR_OBJECTCLASSES_DIR ."include.inc.".PHP_EXT ); - require_once( OR_TEXTCLASSES_DIR ."include.inc.".PHP_EXT ); - - // Datenbank-Funktionen einbinden. - require_once( OR_MODULES_DIR."database/require.".PHP_EXT ); - - // Jetzt erst die Sitzung starten (nachdem alle Klassen zur Verfügung stehen). - session_start(); - require_once( OR_MODULES_DIR."util/Session.class.".PHP_EXT ); - - // Vorhandene Konfiguration aus der Sitzung lesen. - $conf = Session::getConfig(); - - // Konfiguration lesen. - // Wenn Konfiguration noch nicht in Session vorhanden oder die Konfiguration geändert wurde (erkennbar anhand des Datei-Datums) - // dann die Konfiguration neu einlesen. - if ( !is_array( $conf ) || $conf['config']['auto_reload'] && Configuration::lastModificationTime()>$conf['config']['last_modification_time'] ) - { - // Da die Konfiguration neu eingelesen wird, sollten wir auch die Sitzung komplett leeren. - if ( is_array($conf) && $conf['config']['session_destroy_on_config_reload'] ) - session_unset(); - - // Fest eingebaute Standard-Konfiguration laden. - require(OR_MODULES_DIR.'util/config-default.php'); - $conf = createDefaultConfig(); - - $customConfig = Configuration::load(); - $conf = array_replace_recursive($conf, $customConfig); - - - $conf['build'] = parse_ini_file('build.ini' ); - $conf['version'] = parse_ini_file('version.ini'); - // Sprache lesen - - if ( $conf['i18n']['use_http'] ) - // Die vom Browser angeforderten Sprachen ermitteln - $languages = Http::getLanguages(); - else - // Nur Default-Sprache erlauben - $languages = array(); - - if ( isset($_COOKIE['or_language']) ) - $languages = array($_COOKIE['or_language']) + $languages; - - // Default-Sprache hinzufuegen. - // Wird dann verwendet, wenn die vom Browser angeforderten Sprachen - // nicht vorhanden sind - $languages[] = $conf['i18n']['default']; - $available = explode(',',$conf['i18n']['available']); - - foreach( $languages as $l ) - { - if ( !in_array($l,$available) ) - continue; - - // Pruefen, ob Sprache vorhanden ist. - $langFile = OR_LANGUAGE_DIR.'lang-'.$l.'.'.PHP_EXT; - - if ( !file_exists( $langFile ) ) - throw new LogicException("File does not exist: ".$langFile); - - require( $langFile ); - $conf['language'] = $lang; - $conf['language']['language_code'] = $l; - break; - } - - - if ( !isset($conf['language']) ) - Http::serverError('no language found! (languages='.implode(',',$languages).')' ); - - // Schreibt die Konfiguration in die Sitzung. Diese wird anschliessend nicht - // mehr veraendert. - Session::setConfig( $conf ); - } - - - // Nachdem die Konfiguration gelesen wurde, kann nun der Logger benutzt werden. - require_once( OR_MODULES_DIR."logger/require.".PHP_EXT ); - - // Logger initialisieren - Logger::$messageFormat = $conf['log']['format']; - Logger::$filename = $conf['log']['file']; - Logger::$dateFormat = $conf['log']['date_format']; - Logger::$nsLookup = $conf['log']['ns_lookup']; - - $cname = 'LOGGER_LOG_'.strtoupper($conf['log']['level']); - if (defined($cname)) - Logger::$level = constant($cname); - - - Logger::$messageCallback = function() - { - $action = Session::get('action'); - if ( empty($action) ) - $action = '-'; - - $action = Session::get('action'); - if ( empty($action) ) - $action = '-'; - - $user = Session::getUser(); - if ( is_object($user) ) - $username = $user->name; - else - $username = '-'; - - return array('user'=>$username,'action'=>$action); - }; - Logger::init(); - - - if ( !empty($conf['security']['umask']) ) - umask( octdec($conf['security']['umask']) ); - - if ( !empty($conf['interface']['timeout']) ) - set_time_limit( intval($conf['interface']['timeout']) ); - - if ( config('security','use_post_token') && $_SERVER['REQUEST_METHOD'] == 'POST' && @$REQ[REQ_PARAM_TOKEN]!=token() ) - { - Logger::error('Token mismatch: Needed '.token().' but got '.@$REQ[REQ_PARAM_TOKEN].'. Maybe an attacker?'); - Http::notAuthorized("Token mismatch","Token mismatch"); - } - - - define('FILE_SEP',$conf['interface']['file_separator']); - - define('TEMPLATE_DIR',OR_THEMES_DIR.$conf['interface']['theme'].'/templates'); - define('CSS_DIR' ,OR_THEMES_DIR.$conf['interface']['theme'].'/css' ); - define('IMAGE_DIR' ,OR_THEMES_DIR.$conf['interface']['theme'].'/images' ); - - define('PRODUCTION' ,$conf['production']); - define('DEVELOPMENT' ,!PRODUCTION); - - require_once( "functions/language.inc.".PHP_EXT ); - require_once( "functions/db.inc.".PHP_EXT ); - - // Verbindung zur Datenbank - // - $db = Session::getDatabase(); - if ( is_object( $db ) ) - { - $ok = $db->connect(); - if ( !$ok ) - Http::sendStatus('503','Service Unavailable','Database is not available: '.$db->error); - - Session::setDatabase( $db ); - $db->start(); - } - - if ( !empty($REQ[REQ_PARAM_ACTION]) ) - $action = $REQ[REQ_PARAM_ACTION]; - else - Http::serverError("no action supplied"); - - if ( !empty( $REQ[REQ_PARAM_SUBACTION] ) ) - $subaction = $REQ[REQ_PARAM_SUBACTION]; - else - { - Http::serverError("no method (subaction) supplied"); - } - - // Elternklassen einbinden - require_once( OR_ACTIONCLASSES_DIR.'Action.class.php' ); - require_once( OR_ACTIONCLASSES_DIR.'ObjectAction.class.php' ); - require_once( OR_ACTIONCLASSES_DIR.'FileAction.class.php' ); - - - $actionClassName = ucfirst($action).'Action'; - $actionClassNameWithNamespace = 'cms\\action\\'.$actionClassName; - - require_once( OR_ACTIONCLASSES_DIR.'/'.$actionClassName.'.class.php' ); - - // Erzeugen der Action-Klasse - try - { - $do = new $actionClassNameWithNamespace; - } - catch( ObjectNotFoundException $e ) - { - Logger::debug( "Object not found: ".$e->__toString() ); - Http::noContent(); - } - - $do->actionClassName = $actionClassName; - $do->actionName = $action; - $do->subActionName = $subaction; - - define('OR_ACTION',$action); - define('OR_METHOD',$subaction); - if ( isset($REQ[REQ_PARAM_ID]) ) - define('OR_ID' ,$REQ[REQ_PARAM_ID]); - else - define('OR_ID' ,''); - - $do->init(); - - - switch( @$do->security ) - { - case SECURITY_GUEST: - // Ok. - break; - case SECURITY_USER: - if ( !is_object($do->currentUser) ) - throw new SecurityException('No user logged in, but this action requires a valid user'); - break; - case SECURITY_ADMIN: - if ( !is_object($do->currentUser) || !$do->currentUser->isAdmin ) - throw new SecurityException('This action requires administration privileges, but user '.$do->currentUser->name.' is not an admin'); - break; - default: - } - - - - $isAction = $_SERVER['REQUEST_METHOD'] == 'POST'; - - if ( $isAction ) - { - // POST-Request => ...Post() wird aufgerufen. - $subactionMethodName = $subaction.'Post'; - } - else - { - // GET-Request => ...View() wird aufgerufen. - $subactionMethodName = $subaction.'View'; - // Daten werden nur angezeigt, die Sitzung kann also schon geschlossen werden. - if ( $action != 'index' ) // In Index wird die Perspektive manipuliert. - Session::close(); - } - - Logger::debug("Executing $action/$subaction/".@$REQ[REQ_PARAM_ID]); - - if ( ! method_exists($do,$subactionMethodName) ) - Http::noContent(); - - // Jetzt wird die Aktion aus der Actionklasse aufgerufen. - $result = $do->$subactionMethodName(); - $do->handleResult($result); - - $do->forward(); -} -catch( ObjectNotFoundException $e ) -{ - Logger::warn( "Object not found: ".$e->__toString() ); // Nur Debug, da dies bei gelöschten Objekten vorkommen kann. - Http::noContent(); -} -catch( OpenRatException $e ) -{ - Http::serverError( lang($e->key),$e->__toString()); -} -catch( SecurityException $e ) -{ - Logger::info($e->getMessage()); - Http::notAuthorized("You are not allowed to execute this action."); -} -catch( Exception $e ) -{ - Http::serverError( "Internal CMS error",$e->__toString() ); -} - -// fertig :) -?>- \ No newline at end of file diff --git a/modules/cms-api/require.php b/modules/cms-api/require.php @@ -1,4 +1,5 @@ <?php require_once(__DIR__ . "/../cms-core/require.php"); -?>- \ No newline at end of file + +require_once(__DIR__ . "/API.class.php"); diff --git a/modules/cms-core/Dispatcher.class.php b/modules/cms-core/Dispatcher.class.php @@ -161,9 +161,6 @@ class Dispatcher define('PRODUCTION', $conf['production']); define('DEVELOPMENT', !PRODUCTION); - require_once("functions/language.inc." . PHP_EXT); - require_once("functions/db.inc." . PHP_EXT); - // Verbindung zur Datenbank // $db = Session::getDatabase(); @@ -196,9 +193,6 @@ class Dispatcher $do->actionName = $this->action; $do->subActionName = $this->subaction; - define('OR_ACTION', $this->action); - define('OR_METHOD', $this->subaction); - if (isset($REQ[REQ_PARAM_ID])) define('OR_ID', $REQ[REQ_PARAM_ID]); else diff --git a/modules/cms-core/action/Action.class.php b/modules/cms-core/action/Action.class.php @@ -28,37 +28,11 @@ namespace { namespace cms\action { use cms\model\User; - use \DomainException; use \Html; use \Session; -use \Logger; -use \Http; - use \template_engine\TemplateEngine; + use \Logger; + use \Http; use \Text; - use \XML; -use \JSON; -use \Exception; -use \LogicException; - -// 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. - - - /** diff --git a/modules/cms-core/init.php b/modules/cms-core/init.php @@ -18,7 +18,6 @@ define('PHP_EXT' ,'php' ); -require_once( "functions/common.inc.".PHP_EXT ); define('IMG_EXT' ,'.gif' ); define('IMG_ICON_EXT' ,'.png' ); @@ -36,18 +35,19 @@ define('OR_TYPE_LINK' ,'link' ); define('OR_TYPE_URL' ,'url' ); -define('OR_MODULES_DIR' ,'./modules/'); +define( 'CMS_ROOT_DIR',__DIR__.'/../../'); + +define('OR_MODULES_DIR' ,CMS_ROOT_DIR.'modules/'); define('OR_ACTIONCLASSES_DIR' ,OR_MODULES_DIR.'cms-core/action/' ); -define('OR_FORMCLASSES_DIR' ,'./formClasses/' ); define('OR_OBJECTCLASSES_DIR' ,OR_MODULES_DIR.'cms-core/model/' ); -define('OR_LANGUAGE_DIR' ,'./language/' ); -define('OR_DBCLASSES_DIR' ,'./db/' ); +define('OR_LANGUAGE_DIR' ,CMS_ROOT_DIR.'language/' ); +define('OR_DBCLASSES_DIR' ,CMS_ROOT_DIR.'db/' ); define('OR_DYNAMICCLASSES_DIR',OR_MODULES_DIR.'cms-macros/macro/' ); define('OR_TEXTCLASSES_DIR' ,OR_MODULES_DIR.'wikiparser/' ); -define('OR_PREFERENCES_DIR' ,'./config/'); +define('OR_PREFERENCES_DIR' ,CMS_ROOT_DIR.'config/'); define('OR_CONFIG_DIR' ,OR_PREFERENCES_DIR ); -define('OR_THEMES_DIR' ,'./modules/cms-ui/themes/' ); -define('OR_TMP_DIR' ,'./tmp/' ); +define('OR_THEMES_DIR' ,OR_MODULES_DIR.'cms-ui/themes/' ); +define('OR_TMP_DIR' ,CMS_ROOT_DIR.'tmp/' ); define('OR_CONTROLLER_FILE' ,'dispatcher'); define('START_TIME' ,time() ); define('REQUEST_ID' ,'req'.time().rand() ); @@ -119,8 +119,5 @@ function fatal_handler() { register_shutdown_function( "fatal_handler" ); -require_once( "functions/request.inc.php" ); - - ?> \ No newline at end of file diff --git a/modules/cms-core/require.php b/modules/cms-core/require.php @@ -18,8 +18,15 @@ require_once(__DIR__ . "/model/require.php"); require_once(__DIR__ . "/auth/require.php"); // Session functions -require_once(__DIR__. "/../util/Session.class.php"); -require_once(__DIR__.'/init.php'); +require_once(__DIR__ . "/../util/Session.class.php"); + +// Helper functions... +require_once(__DIR__ . "/functions/common.inc.php"); +require_once(__DIR__ . "/functions/language.inc.php"); +require_once(__DIR__ . "/functions/request.inc.php"); + + +require_once(__DIR__ . '/init.php'); require_once(__DIR__ . "/Dispatcher.class.php"); diff --git a/modules/cms-ui/UI.class.php b/modules/cms-ui/UI.class.php @@ -0,0 +1,146 @@ +<?php + +namespace cms_ui; + +use BadMethodCallException; +use cms\Dispatcher; +use DomainException; +use Exception; +use Http; +use JSON; +use Logger; +use LogicException; +use ObjectNotFoundException; +use OpenRatException; +use SecurityException; +use Session; +use template_engine\TemplateEngine; + +define('CMS_UI_REQ_PARAM_SUBACTION', 'subaction'); +define('CMS_UI_REQ_PARAM_ACTION', 'action'); + + +class UI +{ + public static function execute() + { + try { + if (!empty($_REQUEST[CMS_UI_REQ_PARAM_ACTION])) + $action = $_REQUEST[CMS_UI_REQ_PARAM_ACTION]; + else + $action = 'index'; + + if (!empty($_REQUEST[CMS_UI_REQ_PARAM_SUBACTION])) + $subaction = $_REQUEST[CMS_UI_REQ_PARAM_SUBACTION]; + else { + $subaction = 'show'; + } + + $dispatcher = new Dispatcher(); + + $dispatcher->action = $action; + define('OR_ACTION', $action); + + $dispatcher->subaction = $subaction; + define('OR_METHOD', $subaction); + + + $data = $dispatcher->doAction(); + + $httpAccept = getenv('HTTP_ACCEPT'); + $types = explode(',', $httpAccept); + + if (sizeof($types) == 1 && in_array('application/json', $types) || @$_REQUEST['output'] == 'json') { + $json = new JSON(); + header('Content-Type: application/json; charset=UTF-8'); + if (function_exists('json_encode')) + // Native Methode ist schneller.. + echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK | JSON_PARTIAL_OUTPUT_ON_ERROR); + else + // Fallback, falls json_encode() nicht existiert... + echo $json->encode($data); + exit; + } + + header('Content-Type: text/html; charset=UTF-8'); + + $tplName = $action . '/' . $subaction; + + UI::outputTemplate($tplName,$data['output']); + } catch (BadMethodCallException $e) { + // Action-Method does not exist. + Http::noContent(); + } catch (ObjectNotFoundException $e) { + Logger::warn("Object not found: " . $e->__toString()); // Nur Debug, da dies bei gelöschten Objekten vorkommen kann. + Http::noContent(); + } catch (OpenRatException $e) { + Http::serverError(lang($e->key), $e->__toString()); + } catch (SecurityException $e) { + Logger::info($e->getMessage()); + Http::notAuthorized("You are not allowed to execute this action."); + } catch (Exception $e) { + Http::serverError("Internal CMS error", $e->__toString()); + } + } + + /** + * Executes and outputs a HTML template. + * + * @param $tplName string Name of template + * @param $output array Output data + */ + private static function outputTemplate($tplName, $output) + { + global $REQ; + global $PHP_SELF; + global $HTTP_SERVER_VARS; + global $image_dir; + global $view; + global $conf; + + $image_dir = OR_THEMES_DIR . $conf['interface']['theme'] . '/images/'; + + $user = Session::getUser(); + + if (!empty($conf['interface']['override_title'])) + $cms_title = $conf['interface']['override_title']; + else + $cms_title = OR_TITLE . ' ' . OR_VERSION; + + + + $subActionName = OR_ACTION; + $actionName = OR_METHOD; + $requestId = $_REQUEST['id']; + + $iFile = 'modules/cms-ui/themes/default/templates/' . $tplName . '.tpl.out.' . PHP_EXT; + + if (DEVELOPMENT) { + $srcXmlFilename = 'modules/cms-ui/themes/default/templates/' . $tplName . '.tpl.src.xml'; + + // Das Template kompilieren. + // Aus dem XML wird eine PHP-Datei erzeugt. + try { + $te = new TemplateEngine(); + $te->compile($srcXmlFilename, $iFile); + unset($te); + } catch (Exception $e) { + throw new DomainException("Compilation failed for Template '$tplName'.", 0, $e); + } + header("X-CMS-Template-File: " . $iFile); + } + + + // Übertragen der Ausgabe-Variablen in den aktuellen Kontext + // + extract($output); + + if (is_file($iFile)) + // Einbinden des Templates + require_once($iFile); + else + throw new LogicException("File '$iFile' not found."); + + + } +} diff --git a/modules/cms-ui/require.php b/modules/cms-ui/require.php @@ -2,4 +2,5 @@ require_once(__DIR__ . "/../cms-core/require.php"); require_once(__DIR__ . "/../template-engine/require.php"); -?>- \ No newline at end of file + +require_once(__DIR__ . "/UI.class.php"); diff --git a/modules/cms-ui/ui.php b/modules/cms-ui/ui.php @@ -1,116 +0,0 @@ -<?php - -use cms\Dispatcher; -use template_engine\TemplateEngine; - -define('CMS_UI_REQ_PARAM_SUBACTION' ,'subaction' ); -define('CMS_UI_REQ_PARAM_ACTION' ,'action' ); - - - -try { - - if (!empty($_REQUEST[CMS_UI_REQ_PARAM_ACTION])) - $action = $_REQUEST[CMS_UI_REQ_PARAM_ACTION]; - else - $action = 'index'; - - if (!empty($_REQUEST[CMS_UI_REQ_PARAM_SUBACTION])) - $subaction = $_REQUEST[CMS_UI_REQ_PARAM_SUBACTION]; - else { - $subaction = 'show'; - } - - $dispatcher = new Dispatcher(); - - $dispatcher->action = $action; - $dispatcher->subaction = $subaction; - - $output = $dispatcher->doAction(); - - $httpAccept = getenv('HTTP_ACCEPT'); - $types = explode(',', $httpAccept); - - if (sizeof($types) == 1 && in_array('application/json', $types) || @$_REQUEST['output'] == 'json') - { - $json = new JSON(); - header('Content-Type: application/json; charset=UTF-8'); - if (function_exists('json_encode')) - // Native Methode ist schneller.. - echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK | JSON_PARTIAL_OUTPUT_ON_ERROR); - else - // Fallback, falls json_encode() nicht existiert... - echo $json->encode($output); - exit; - } - - header('Content-Type: text/html; charset=UTF-8'); - - $tplName = $action . '/' . $subaction; - - global $REQ; - global $PHP_SELF; - global $HTTP_SERVER_VARS; - global $image_dir; - global $view; - - $image_dir = OR_THEMES_DIR . $conf['interface']['theme'] . '/images/'; - - $user = Session::getUser(); - - if (!empty($conf['interface']['override_title'])) - $cms_title = $conf['interface']['override_title']; - else - $cms_title = OR_TITLE . ' ' . OR_VERSION; - - $subActionName = $dispatcher->subaction; - $actionName = $dispatcher->action; - $requestId = $_REQUEST['id']; - - $iFile = 'modules/cms-ui/themes/default/templates/' . $tplName . '.tpl.out.' . PHP_EXT; - - if (DEVELOPMENT) { - $srcXmlFilename = 'modules/cms-ui/themes/default/templates/' . $tplName . '.tpl.src.xml'; - - // Das Template kompilieren. - // Aus dem XML wird eine PHP-Datei erzeugt. - try { - $te = new TemplateEngine(); - $te->compile($srcXmlFilename, $iFile); - unset($te); - } catch (Exception $e) { - throw new DomainException("Compilation failed for Template '$tplName'.", 0, $e); - } - header("X-CMS-Template-File: " . $iFile); - } - - - // Übertragen der Ausgabe-Variablen in den aktuellen Kontext - // - extract($output['output']); - - if (is_file($iFile)) - // Einbinden des Templates - require_once($iFile); - else - throw new LogicException("File '$iFile' not found."); - - -} catch (ObjectNotFoundException $e) { - Logger::warn("Object not found: " . $e->__toString()); // Nur Debug, da dies bei gelöschten Objekten vorkommen kann. - Http::noContent(); -} catch (OpenRatException $e) { - Http::serverError(lang($e->key), $e->__toString()); -} catch (SecurityException $e) { - Logger::info($e->getMessage()); - Http::notAuthorized("You are not allowed to execute this action."); -} catch (Exception $e) { - Http::serverError("Internal CMS error", $e->__toString()); -} - - - - - - -?>- \ No newline at end of file diff --git a/modules/configuration/Configuration.class.php b/modules/configuration/Configuration.class.php @@ -11,7 +11,7 @@ */ class Configuration { - public static $configFile = './config/config.yml'; + public static $configFile = __DIR__.'/../../config/config.yml'; /** * Ermittelt den Zeitpunkt der letzten Änderung der Konfigurationsdatei. diff --git a/modules/template-engine/components/html/form/form.js b/modules/template-engine/components/html/form/form.js @@ -49,8 +49,7 @@ function formSubmit(form) $(form).find('.error').removeClass('error'); var params = $(form).serializeArray(); - var url = './'; // Alle Parameter befinden sich im Formular - + var formMethod = $(form).attr('method').toUpperCase(); if ( formMethod == 'GET' ) @@ -64,6 +63,8 @@ function formSubmit(form) } else { + var url = './api/'; // Alle Parameter befinden sich im Formular + // POST-Request $(form).closest('div.content').addClass('loader'); url += '?output=json'; diff --git a/modules/template-engine/components/html/form/form.min.js b/modules/template-engine/components/html/form/form.min.js @@ -1,3 +1,3 @@ -;$(document).on('orViewLoaded',function(e,t){if($('div.panel form input[type=password]').length>0&&$('#uname').attr('value')!=''){$('div.panel form input[name=login_name] ').attr('value',$('#uname').attr('value'));$('div.panel form input[name=login_password]').attr('value',$('#upassword').attr('value'))};$(e.target).find('form[data-autosave="true"] input[type="checkbox"]').click(function(){formSubmit($(this).closest('form'))})});function formSubmit(e){if($('div.panel form input[type=password]').length>0){$('#uname').attr('value',$('div.panel form input[name=login_name]').attr('value'));$('#upassword').attr('value',$('div.panel form input[name=login_password]').attr('value'));$('#uname').closest('form').submit()};if($('#pageelement_edit_editor').length>0){var r=CKEDITOR.instances['pageelement_edit_editor'];if(r){var l=r.getData();$('#pageelement_edit_editor').html(l)}};var t=$('<div class="notice info"><div class="text loader"></div></div>');$('#noticebar').prepend(t);$(t).show();$(e).find('.error').removeClass('error');var a=$(e).serializeArray(),o='./',d=$(e).attr('method').toUpperCase();if(d=='GET'){var i=$(e).data('action'),n=$(e).data('method'),s=$(e).data('id');loadView($(e).closest('div.content'),i,n,s,a)} -else{$(e).closest('div.content').addClass('loader');o+='?output=json';a['output']='json';if($(e).data('async')||$(e).data('async')=='true'){$('div#dialog').html('').hide();$('div#filler').fadeOut(500)};$.ajax({'type':'POST',url:o,data:a,success:function(a,o,r){$(e).closest('div.content').removeClass('loader');$(t).remove();doResponse(a,o,e)},error:function(a,o,n){$(e).closest('div.content').removeClass('loader');$(t).remove();var i;try{var r=jQuery.parseJSON(a.responseText);i=r.error+'/'+r.description+': '+r.reason}catch(s){i=a.responseText};notify('error',i)}});$(e).fadeIn()}};function doResponse(e,t,a){if(t!='success'){alert('Server error: '+t);return};$.each(e['notices'],function(t,e){var o=$('<div class="notice '+e.status+'"><div class="text">'+e.text+'</div></div>');notifyBrowser(e.text);$.each(e.log,function(e,t){$(o).append('<div class="log">'+t+'</div>')});$('#noticebar').prepend(o);$(o).fadeIn().click(function(){$(this).fadeOut('fast',function(){$(this).remove()})});var r;if(e.status=='ok'){r=3;if($(a).data('async')!='true'){$('div#dialog').html('').hide();$('div#filler').fadeOut(500);$(a).closest('div.panel').find('div.header ul.views li.action.active').removeClass('dirty')}} +;$(document).on('orViewLoaded',function(e,t){if($('div.panel form input[type=password]').length>0&&$('#uname').attr('value')!=''){$('div.panel form input[name=login_name] ').attr('value',$('#uname').attr('value'));$('div.panel form input[name=login_password]').attr('value',$('#upassword').attr('value'))};$(e.target).find('form[data-autosave="true"] input[type="checkbox"]').click(function(){formSubmit($(this).closest('form'))})});function formSubmit(e){if($('div.panel form input[type=password]').length>0){$('#uname').attr('value',$('div.panel form input[name=login_name]').attr('value'));$('#upassword').attr('value',$('div.panel form input[name=login_password]').attr('value'));$('#uname').closest('form').submit()};if($('#pageelement_edit_editor').length>0){var r=CKEDITOR.instances['pageelement_edit_editor'];if(r){var l=r.getData();$('#pageelement_edit_editor').html(l)}};var t=$('<div class="notice info"><div class="text loader"></div></div>');$('#noticebar').prepend(t);$(t).show();$(e).find('.error').removeClass('error');var a=$(e).serializeArray(),d=$(e).attr('method').toUpperCase();if(d=='GET'){var i=$(e).data('action'),n=$(e).data('method'),s=$(e).data('id');loadView($(e).closest('div.content'),i,n,s,a)} +else{var o='./api/';$(e).closest('div.content').addClass('loader');o+='?output=json';a['output']='json';if($(e).data('async')||$(e).data('async')=='true'){$('div#dialog').html('').hide();$('div#filler').fadeOut(500)};$.ajax({'type':'POST',url:o,data:a,success:function(a,o,r){$(e).closest('div.content').removeClass('loader');$(t).remove();doResponse(a,o,e)},error:function(a,o,n){$(e).closest('div.content').removeClass('loader');$(t).remove();var i;try{var r=jQuery.parseJSON(a.responseText);i=r.error+'/'+r.description+': '+r.reason}catch(s){i=a.responseText};notify('error',i)}});$(e).fadeIn()}};function doResponse(e,t,a){if(t!='success'){alert('Server error: '+t);return};$.each(e['notices'],function(t,e){var o=$('<div class="notice '+e.status+'"><div class="text">'+e.text+'</div></div>');notifyBrowser(e.text);$.each(e.log,function(e,t){$(o).append('<div class="log">'+t+'</div>')});$('#noticebar').prepend(o);$(o).fadeIn().click(function(){$(this).fadeOut('fast',function(){$(this).remove()})});var r;if(e.status=='ok'){r=3;if($(a).data('async')!='true'){$('div#dialog').html('').hide();$('div#filler').fadeOut(500);$(a).closest('div.panel').find('div.header ul.views li.action.active').removeClass('dirty')}} else{r=8};setTimeout(function(){$(o).fadeOut('slow').remove()},r*1000)});$.each(e['errors'],function(e,t){$('input[name='+t+']').addClass('error').parent().addClass('error').parents('fieldset').addClass('show').addClass('open')});if(!e.control){};if(e.control.redirect)window.location.href=e.control.redirect;if(e.control.new_style)setUserStyle(e.control.new_style);if(e.control.refresh)refreshAll();else if(e.control.next_view)startView($(a).closest('div.content'),e.control.next_view);else if(e.errors.length==0)$(a).closest('div.panel').find('li.action.active').orLoadView()}; \ No newline at end of file