copy a few files from mvu fork
This commit is contained in:
parent
4da4c47915
commit
d5783efff7
@ -1,6 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once (__DIR__ . '/internals/base.php');
|
require_once (__DIR__ . '/internals/website.php');
|
||||||
|
|
||||||
|
$site = new Website();
|
||||||
|
$site->init();
|
||||||
|
|
||||||
$URL_RULES =
|
$URL_RULES =
|
||||||
[
|
[
|
||||||
@ -79,6 +82,8 @@ $URL_RULES =
|
|||||||
[ 'url' => ['404'], 'target' => 'pages/error_404.php', 'options' => [], ],
|
[ 'url' => ['404'], 'target' => 'pages/error_404.php', 'options' => [], ],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$site->serve($URL_RULES);
|
||||||
|
|
||||||
//#############################################################################
|
//#############################################################################
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
26
www/internals/pageframeoptions.php
Normal file
26
www/internals/pageframeoptions.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php if(count(get_included_files()) ==1) exit("Direct access not permitted.");
|
||||||
|
|
||||||
|
|
||||||
|
class PageFrameOptions
|
||||||
|
{
|
||||||
|
/** @var string */
|
||||||
|
public $raw;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $title = '';
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
public $statuscode = 200;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
public $force_404 = false;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $force_404_message = '';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $frame = 'default_frame.php';
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $contentType = null;
|
||||||
|
}
|
115
www/internals/ruleengine.php
Normal file
115
www/internals/ruleengine.php
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<?php if(count(get_included_files()) ==1) exit("Direct access not permitted.");
|
||||||
|
|
||||||
|
require_once "website.php";
|
||||||
|
require_once "utils.php";
|
||||||
|
|
||||||
|
class RuleEngine
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Website $app
|
||||||
|
* @param array $urlConfig
|
||||||
|
* @return URLRoute
|
||||||
|
*/
|
||||||
|
public static function findRoute(Website $app, array $urlConfig): URLRoute
|
||||||
|
{
|
||||||
|
if ($app->isProd())
|
||||||
|
$requri = $_SERVER['REQUEST_URI'];
|
||||||
|
else
|
||||||
|
$requri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : 'localhost:80/';
|
||||||
|
|
||||||
|
$parse = parse_url($requri);
|
||||||
|
|
||||||
|
$path = isset($parse['path']) ? $parse['path'] : '';
|
||||||
|
$pathparts = preg_split('@/@', $path, NULL, PREG_SPLIT_NO_EMPTY);
|
||||||
|
$partcount = count($pathparts);
|
||||||
|
|
||||||
|
foreach ($urlConfig as $rule)
|
||||||
|
{
|
||||||
|
$route = self::testRule($app, $rule, $requri, $pathparts, $partcount);
|
||||||
|
if ($route === null) continue;
|
||||||
|
|
||||||
|
if ($app->getCurrentRights() >= $route->minimal_access_rights) return $route;
|
||||||
|
|
||||||
|
if ($app->isLoggedIn()) return URLRoute::getInsufficentRightsRoute($requri);
|
||||||
|
|
||||||
|
if (!$app->isLoggedIn()) return URLRoute::getLoginRoute($route, $requri);
|
||||||
|
}
|
||||||
|
|
||||||
|
return URLRoute::getNotFoundRoute($requri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function testRule(Website $app, array $rule, string $requri, array $pathparts, int $partcount)
|
||||||
|
{
|
||||||
|
if ($partcount !== count($rule['url'])) return null;
|
||||||
|
|
||||||
|
$urlparams = [];
|
||||||
|
|
||||||
|
$match = true;
|
||||||
|
for($i = 0; $i < $partcount; $i++)
|
||||||
|
{
|
||||||
|
$comp = $rule['url'][$i];
|
||||||
|
if (startsWith($comp, '?{') && endsWith($comp, '}'))
|
||||||
|
{
|
||||||
|
$ident = substr($comp, 2, strlen($comp)-3);
|
||||||
|
$urlparams[$ident] = $pathparts[$i];
|
||||||
|
}
|
||||||
|
else if ($comp === '*')
|
||||||
|
{
|
||||||
|
if (!isset($urlparams['*'])) $urlparams['*'] = [];
|
||||||
|
$urlparams['*'] []= $pathparts[$i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (strtolower($comp) !== strtolower($pathparts[$i])) { $match = false; break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$match) return null;
|
||||||
|
|
||||||
|
$route = new URLRoute($rule['target'], $requri);
|
||||||
|
|
||||||
|
foreach($rule['parameter'] as $optname => $optvalue)
|
||||||
|
{
|
||||||
|
$value = $optvalue;
|
||||||
|
|
||||||
|
if ($value === '%GET%')
|
||||||
|
{
|
||||||
|
if (!isset($_GET[$optname])) { $match = false; break; }
|
||||||
|
$value = $_GET[$optname];
|
||||||
|
}
|
||||||
|
else if ($value === '%POST%')
|
||||||
|
{
|
||||||
|
if (!isset($_POST[$optname])) { $match = false; break; }
|
||||||
|
$value = $_POST[$optname];
|
||||||
|
}
|
||||||
|
else if ($value === '%URL%')
|
||||||
|
{
|
||||||
|
if (!isset($urlparams[$optname])) { $match = false; break; }
|
||||||
|
$value = urldecode($urlparams[$optname]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$route->parameter[strtolower($optname)] = $value;
|
||||||
|
}
|
||||||
|
if (!$match) return null;
|
||||||
|
|
||||||
|
$ctrlOpt = $rule['options'];
|
||||||
|
|
||||||
|
if (in_array('disabled', $ctrlOpt)) return null;
|
||||||
|
if (in_array('api', $ctrlOpt)) $route->isAPI = true;
|
||||||
|
|
||||||
|
if (isset($ctrlOpt['method']) && $_SERVER["REQUEST_METHOD"] !== $ctrlOpt['method']) return null;
|
||||||
|
|
||||||
|
$route->minimal_access_rights = (($rule['rights']===null) ? 0 : $rule['rights']);
|
||||||
|
|
||||||
|
if ($app->isProd() && $app->config->app_enforce_https && isHTTPRequest() && !in_array('http', $ctrlOpt))
|
||||||
|
{
|
||||||
|
// enforce https
|
||||||
|
$redirect = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
||||||
|
ob_end_clean();
|
||||||
|
header('HTTP/1.1 301 Moved Permanently');
|
||||||
|
header('Location: ' . $redirect);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $route;
|
||||||
|
}
|
||||||
|
}
|
122
www/internals/urlroute.php
Normal file
122
www/internals/urlroute.php
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<?php if(count(get_included_files()) ==1) exit("Direct access not permitted.");
|
||||||
|
|
||||||
|
require_once "URLRoute.php";
|
||||||
|
|
||||||
|
class URLRoute
|
||||||
|
{
|
||||||
|
/** @var string */
|
||||||
|
public $targetpath;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $full_url;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
public $parameter;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
public $minimal_access_rights;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
public $isAPI;
|
||||||
|
|
||||||
|
public function __construct(string $target, string $url)
|
||||||
|
{
|
||||||
|
$this->targetpath = __DIR__ . '/../pages/' . $target;
|
||||||
|
$this->full_url = $url;
|
||||||
|
$this->parameter = [];
|
||||||
|
$this->minimal_access_rights = 0;
|
||||||
|
$this->isAPI = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param VApp $app
|
||||||
|
* @return PageFrameOptions
|
||||||
|
*/
|
||||||
|
public function get(Website $app): PageFrameOptions
|
||||||
|
{
|
||||||
|
$pfo = new PageFrameOptions();
|
||||||
|
|
||||||
|
$pfo->title = $app->config->verein_kurzel . " Orga"; // default title
|
||||||
|
if ($this->isAPI)
|
||||||
|
{
|
||||||
|
$pfo->frame = 'no_frame.php';
|
||||||
|
$pfo->contentType = 'application/json';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getDirect($app, $pfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Website $app
|
||||||
|
* @param PageFrameOptions $pfo
|
||||||
|
* @return PageFrameOptions
|
||||||
|
*/
|
||||||
|
public function getDirect(Website $app, PageFrameOptions $pfo): PageFrameOptions
|
||||||
|
{
|
||||||
|
@ob_end_clean();
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
global $ROUTE;
|
||||||
|
global $FRAME_OPTIONS;
|
||||||
|
global $APP;
|
||||||
|
$ROUTE = $this;
|
||||||
|
$FRAME_OPTIONS = $pfo;
|
||||||
|
$APP = $app;
|
||||||
|
|
||||||
|
/** @noinspection PhpIncludeInspection */
|
||||||
|
require $this->targetpath;
|
||||||
|
|
||||||
|
$FRAME_OPTIONS->raw = ob_get_clean();
|
||||||
|
|
||||||
|
return $FRAME_OPTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $requri
|
||||||
|
* @return URLRoute
|
||||||
|
*/
|
||||||
|
public static function getInsufficentRightsRoute(string $requri): URLRoute
|
||||||
|
{
|
||||||
|
$r = new URLRoute('errors/insufficent_rights.php', $requri);
|
||||||
|
$r->parameter = [];
|
||||||
|
$r->minimal_access_rights = 0;
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param URLRoute $route
|
||||||
|
* @param string $requri
|
||||||
|
* @return URLRoute
|
||||||
|
*/
|
||||||
|
public static function getLoginRoute(URLRoute $route, string $requri): URLRoute
|
||||||
|
{
|
||||||
|
$r = new URLRoute('login.php', $requri);
|
||||||
|
$r->parameter = [ 'redirect' => $route->full_url ];
|
||||||
|
$r->minimal_access_rights = 0;
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $requri
|
||||||
|
* @return URLRoute
|
||||||
|
*/
|
||||||
|
public static function getNotFoundRoute(string $requri): URLRoute
|
||||||
|
{
|
||||||
|
$r = new URLRoute('errors/not_found.php', $requri);
|
||||||
|
$r->parameter = [];
|
||||||
|
$r->minimal_access_rights = 0;
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $requri
|
||||||
|
* @return URLRoute
|
||||||
|
*/
|
||||||
|
public static function getServerErrorRoute(string $requri): URLRoute
|
||||||
|
{
|
||||||
|
$r = new URLRoute('errors/server_error.php', $requri);
|
||||||
|
$r->parameter = [];
|
||||||
|
$r->minimal_access_rights = 0;
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
}
|
@ -11,22 +11,6 @@ global $ADDITIONAL_STYLESHEETS;
|
|||||||
$ADDITIONAL_SCRIPTS = [];
|
$ADDITIONAL_SCRIPTS = [];
|
||||||
$ADDITIONAL_STYLESHEETS = [];
|
$ADDITIONAL_STYLESHEETS = [];
|
||||||
|
|
||||||
function InitPHP() {
|
|
||||||
|
|
||||||
set_error_handler("exception_error_handler"); // errors as exceptions for global catch
|
|
||||||
|
|
||||||
ob_start(); // buffer outpt so it can be discarded in httpError
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function exception_error_handler($severity, $message, $file, $line) {
|
|
||||||
if (!(error_reporting() & $severity)) {
|
|
||||||
// This error code is not included in error_reporting
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new ErrorException($message, 0, $severity, $file, $line);
|
|
||||||
}
|
|
||||||
|
|
||||||
function startsWith($haystack, $needle)
|
function startsWith($haystack, $needle)
|
||||||
{
|
{
|
||||||
$length = strlen($needle);
|
$length = strlen($needle);
|
176
www/internals/website.php
Normal file
176
www/internals/website.php
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
<?php if(count(get_included_files()) ==1) exit("Direct access not permitted.");
|
||||||
|
|
||||||
|
require_once 'ruleengine.php';
|
||||||
|
require_once 'urlroute.php';
|
||||||
|
require_once 'pageframeoptions.php';
|
||||||
|
|
||||||
|
class Website
|
||||||
|
{
|
||||||
|
/** @var Website */
|
||||||
|
private static $instance;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
set_error_handler("exception_error_handler"); // errors as exceptions for global catch
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$this->config = require (__DIR__ . "/config.php");
|
||||||
|
}
|
||||||
|
catch (exception $e)
|
||||||
|
{
|
||||||
|
$this->serveServerError("config.php not found", formatException($e), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!$this->config['prod'])
|
||||||
|
{
|
||||||
|
ini_set('display_errors', 1);
|
||||||
|
ini_set('display_startup_errors', 1);
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$instance = $this;
|
||||||
|
}
|
||||||
|
catch (exception $e)
|
||||||
|
{
|
||||||
|
$this->serveServerError("Initialization failed", formatException($e), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getInstance()
|
||||||
|
{
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function serve($rules)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$route = RuleEngine::findRoute($this, $rules);
|
||||||
|
|
||||||
|
$result = $route->get($this);
|
||||||
|
|
||||||
|
if ($result->force_404)
|
||||||
|
{
|
||||||
|
$this->serveCustom404($route->full_url, $result);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result->contentType !== null) header('Content-Type: ' . $result->contentType);
|
||||||
|
http_response_code($result->statuscode);
|
||||||
|
|
||||||
|
$this->output($result, $route);
|
||||||
|
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
$this->serveServerError(null, formatException($e), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function serveCustom404(string $uri, PageFrameOptions $frameOpt)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
@ob_end_clean();
|
||||||
|
|
||||||
|
$frameOpt->statuscode = 404;
|
||||||
|
$frameOpt->title = 'Page not found';
|
||||||
|
|
||||||
|
$route = URLRoute::getNotFoundRoute($uri);
|
||||||
|
|
||||||
|
$result = $route->getDirect($this, $frameOpt);
|
||||||
|
|
||||||
|
$this->output($result, $route);
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
$this->serveServerError(null, formatException($e), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $message
|
||||||
|
* @param string|null $debugInfo
|
||||||
|
* @param PageFrameOptions|null $frameOpt
|
||||||
|
*/
|
||||||
|
private function serveServerError($message, $debugInfo, $frameOpt)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
@ob_end_clean();
|
||||||
|
|
||||||
|
if ($frameOpt === null) $frameOpt = new PageFrameOptions();
|
||||||
|
|
||||||
|
$frameOpt->statuscode = 500;
|
||||||
|
$frameOpt->title = 'Internal Server Error';
|
||||||
|
$frameOpt->frame = 'error_frame.php';
|
||||||
|
|
||||||
|
$route = URLRoute::getServerErrorRoute($_SERVER['REQUEST_URI']);
|
||||||
|
|
||||||
|
$route->parameter['message'] = $message;
|
||||||
|
$route->parameter['debuginfo'] = $debugInfo;
|
||||||
|
|
||||||
|
$result = $route->getDirect($this, $frameOpt);
|
||||||
|
|
||||||
|
$this->output($result, $route);
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
http_response_code(500);
|
||||||
|
die('Internal Server Error');
|
||||||
|
}
|
||||||
|
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param PageFrameOptions $pfo
|
||||||
|
* @param URLRoute $route
|
||||||
|
*/
|
||||||
|
private function output(PageFrameOptions $pfo, URLRoute $route)
|
||||||
|
{
|
||||||
|
if ($pfo->contentType !== null) header('Content-Type: ' . $pfo->contentType);
|
||||||
|
http_response_code($pfo->statuscode);
|
||||||
|
|
||||||
|
global $ROUTE;
|
||||||
|
global $FRAME_OPTIONS;
|
||||||
|
global $APP;
|
||||||
|
$ROUTE = $route;
|
||||||
|
$FRAME_OPTIONS = $pfo;
|
||||||
|
$APP = $this;
|
||||||
|
|
||||||
|
/** @noinspection PhpIncludeInspection */
|
||||||
|
require __DIR__ . '/../pages/frame/' . $FRAME_OPTIONS->frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isProd()
|
||||||
|
{
|
||||||
|
if ($this->config == null) return true;
|
||||||
|
return $this->config['prod'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $severity
|
||||||
|
* @param $message
|
||||||
|
* @param $file
|
||||||
|
* @param $line
|
||||||
|
* @throws ErrorException
|
||||||
|
*/
|
||||||
|
function exception_error_handler($severity, $message, $file, $line) {
|
||||||
|
// This error code is not included in error_reporting
|
||||||
|
if (!(error_reporting() & $severity)) return;
|
||||||
|
throw new ErrorException($message, 0, $severity, $file, $line);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user