preparing for re-design using new template-engine for future 0.11.x releases
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
@@ -47,7 +47,7 @@ class PhpHelper
|
||||
* @param string $charset
|
||||
* See php documentation about this
|
||||
*
|
||||
* @return array The array with htmlentitie'd strings
|
||||
* @return array|string The string or an array with htmlentities converted strings
|
||||
* @author Florian Lippert <flo@syscp.org>
|
||||
*/
|
||||
public static function htmlentitiesArray($subject, $fields = '', $quote_style = ENT_QUOTES, $charset = 'UTF-8')
|
||||
@@ -64,7 +64,7 @@ class PhpHelper
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$subject = htmlentities($subject, $quote_style, $charset);
|
||||
$subject = empty($subject) ? "" : htmlentities($subject, $quote_style, $charset);
|
||||
}
|
||||
|
||||
return $subject;
|
||||
@@ -120,22 +120,30 @@ class PhpHelper
|
||||
}
|
||||
|
||||
if (! isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) {
|
||||
global $theme;
|
||||
|
||||
// fallback
|
||||
if (empty($theme)) {
|
||||
$theme = "Sparkle";
|
||||
}
|
||||
// prevent possible file-path-disclosure
|
||||
$errfile = str_replace(\Froxlor\Froxlor::getInstallDir(), "", $errfile);
|
||||
// if we're not on the shell, output a nicer error-message
|
||||
$err_hint = file_get_contents(\Froxlor\Froxlor::getInstallDir() . '/templates/' . $theme . '/misc/phperrornice.tpl');
|
||||
// replace values
|
||||
$err_hint = str_replace("<TEXT>", '#' . $errno . ' ' . $errstr, $err_hint);
|
||||
$err_hint = str_replace("<DEBUG>", $errfile . ':' . $errline, $err_hint);
|
||||
|
||||
// show
|
||||
echo $err_hint;
|
||||
// build alert
|
||||
$type = 'danger';
|
||||
if ($errno == E_NOTICE || $errno == E_DEPRECATED || $errno == E_STRICT) {
|
||||
$type = 'info';
|
||||
} elseif ($errno = E_WARNING) {
|
||||
$type = 'warning';
|
||||
}
|
||||
$err_display = '<div class="alert alert-'.$type.' my-1" role="alert">';
|
||||
$err_display .= '<strong>#' . $errno . ' ' . $errstr . '</strong><br>';
|
||||
$err_display .= $errfile . ':' . $errline;
|
||||
// later depended on whether to show or now
|
||||
$err_display .= '<br><p><pre>';
|
||||
$debug = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
foreach ($debug as $dline) {
|
||||
$err_display .= $dline['function'] . '() called at [' . str_replace(\Froxlor\Froxlor::getInstallDir(), '', $dline['file']) . ':' . $dline['line'] . ']<br>';
|
||||
}
|
||||
$err_display .= '</pre></p>';
|
||||
// end later
|
||||
$err_display .= '</div>';
|
||||
// check for more existing errors
|
||||
$errors = isset(\Froxlor\UI\Panel\UI::Twig()->getGlobals()['global_errors']) ? \Froxlor\UI\Panel\UI::Twig()->getGlobals()['global_errors'] : "";
|
||||
\Froxlor\UI\Panel\UI::Twig()->addGlobal('global_errors', $errors . $err_display);
|
||||
// return true to ignore php standard error-handler
|
||||
return true;
|
||||
}
|
||||
@@ -144,6 +152,28 @@ class PhpHelper
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function phpExceptionHandler(\Exception $exception)
|
||||
{
|
||||
if (! isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) {
|
||||
$err_display = '<div class="alert alert-danger my-1" role="alert">';
|
||||
$err_display .= '<strong>#' . $exception->getCode() . ' ' . $exception->getMessage() . '</strong><br>';
|
||||
// later depended on whether to show or now
|
||||
$err_display .= '<br><p><pre>';
|
||||
$debug = $exception->getTrace();
|
||||
foreach ($debug as $dline) {
|
||||
$err_display .= $dline['function'] . '() called at [' . str_replace(\Froxlor\Froxlor::getInstallDir(), '', $dline['file']) . ':' . $dline['line'] . ']<br>';
|
||||
}
|
||||
$err_display .= '</pre></p>';
|
||||
// end later
|
||||
$err_display .= '</div>';
|
||||
// check for more existing errors
|
||||
$errors = isset(\Froxlor\UI\Panel\UI::Twig()->getGlobals()['global_errors']) ? \Froxlor\UI\Panel\UI::Twig()->getGlobals()['global_errors'] : "";
|
||||
\Froxlor\UI\Panel\UI::Twig()->addGlobal('global_errors', $errors . $err_display);
|
||||
// return true to ignore php standard error-handler
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static function loadConfigArrayDir()
|
||||
{
|
||||
// Workaround until we use gettext
|
||||
|
||||
54
lib/Froxlor/UI/Panel/CustomReflection.php
Normal file
54
lib/Froxlor/UI/Panel/CustomReflection.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Froxlor\UI\Panel;
|
||||
|
||||
class CustomReflection extends \Twig\Extension\AbstractExtension
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return array(
|
||||
new \Twig\TwigFunction('call_static', [
|
||||
$this,
|
||||
'callStaticMethod'
|
||||
]),
|
||||
new \Twig\TwigFunction('get_static', [
|
||||
$this,
|
||||
'getStaticProperty'
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
public function callStaticMethod($class, $method, array $args = [])
|
||||
{
|
||||
$refl = new \reflectionClass($class);
|
||||
// Check that method is static AND public
|
||||
if ($refl->hasMethod($method) && $refl->getMethod($method)->isStatic() && $refl->getMethod($method)->isPublic()) {
|
||||
return call_user_func_array($class . '::' . $method, $args);
|
||||
}
|
||||
throw new \RuntimeException(sprintf('Invalid static method call for class %s and method %s', $class, $method));
|
||||
}
|
||||
|
||||
public function getStaticProperty($class, $property)
|
||||
{
|
||||
$refl = new \reflectionClass($class);
|
||||
// Check that property is static AND public
|
||||
if ($refl->hasProperty($property) && $refl->getProperty($property)->isStatic() && $refl->getProperty($property)->isPublic()) {
|
||||
return $refl->getProperty($property)->getValue();
|
||||
}
|
||||
throw new \RuntimeException(sprintf('Invalid static property get for class %s and property %s', $class, $property));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'customreflection';
|
||||
}
|
||||
}
|
||||
102
lib/Froxlor/UI/Panel/FroxlorTwig.php
Normal file
102
lib/Froxlor/UI/Panel/FroxlorTwig.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Froxlor\UI\Panel;
|
||||
|
||||
class FroxlorTwig extends \Twig\Extension\AbstractExtension
|
||||
{
|
||||
|
||||
public function getFilters()
|
||||
{
|
||||
return array(
|
||||
new \Twig\TwigFilter('formatBytes', array(
|
||||
$this,
|
||||
'formatBytesFilter'
|
||||
)),
|
||||
new \Twig\TwigFilter('formatIP', array(
|
||||
$this,
|
||||
'formatIPFilter'
|
||||
)),
|
||||
new \Twig\TwigFilter('idnDecode', array(
|
||||
$this,
|
||||
'idnDecodeFilter'
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
public function getTests()
|
||||
{
|
||||
return array(
|
||||
new \Twig\TwigTest('numeric', function ($value) {
|
||||
return is_numeric($value);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public function getFunctions()
|
||||
{
|
||||
return array(
|
||||
new \Twig\TwigFunction('get_setting', [
|
||||
$this,
|
||||
'getSetting'
|
||||
]),
|
||||
new \Twig\TwigFunction('lng', [
|
||||
$this,
|
||||
'getLang'
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
public function formatBytesFilter($size, $suffix = "B", $factor = 1)
|
||||
{
|
||||
$size = $size * $factor;
|
||||
$units = array(
|
||||
'',
|
||||
'K',
|
||||
'M',
|
||||
'G',
|
||||
'T',
|
||||
'P',
|
||||
'E',
|
||||
'Z',
|
||||
'Y'
|
||||
);
|
||||
$power = $size > 0 ? floor(log($size, 1024)) : 0;
|
||||
if ($power < 0) {
|
||||
$size = 0.00;
|
||||
$power = 0;
|
||||
}
|
||||
return number_format($size / pow(1024, $power), 2, '.', ',') . ' ' . $units[$power] . $suffix;
|
||||
}
|
||||
|
||||
public function formatIPFilter($addr)
|
||||
{
|
||||
return inet_ntop(inet_pton($addr));
|
||||
}
|
||||
|
||||
public function idnDecodeFilter($entity)
|
||||
{
|
||||
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
|
||||
return $idna_convert->decode($entity);
|
||||
}
|
||||
|
||||
public function getSetting($setting = null)
|
||||
{
|
||||
return \Froxlor\Settings::Get($setting);
|
||||
}
|
||||
|
||||
public function getLang($identifier = null)
|
||||
{
|
||||
return \Froxlor\UI\Panel\UI::getLng($identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'froxlortwig';
|
||||
}
|
||||
}
|
||||
274
lib/Froxlor/UI/Panel/UI.php
Normal file
274
lib/Froxlor/UI/Panel/UI.php
Normal file
@@ -0,0 +1,274 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Froxlor\UI\Panel;
|
||||
|
||||
class UI
|
||||
{
|
||||
|
||||
/**
|
||||
* twig object
|
||||
*
|
||||
* @var \Twig\Environment
|
||||
*/
|
||||
private static $twig = null;
|
||||
|
||||
/**
|
||||
* twig buffer
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $twigbuf = array();
|
||||
|
||||
/**
|
||||
* language strigs array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $lng = array();
|
||||
|
||||
/**
|
||||
* default fallback theme
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $default_theme = 'Sparkle2';
|
||||
|
||||
private static $install_mode = false;
|
||||
|
||||
/**
|
||||
* send various security related headers
|
||||
*/
|
||||
public static function sendHeaders()
|
||||
{
|
||||
header("Content-Type: text/html; charset=UTF-8");
|
||||
|
||||
// prevent Froxlor pages from being cached
|
||||
header("Cache-Control: no-store, no-cache, must-revalidate");
|
||||
header("Pragma: no-cache");
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
|
||||
|
||||
// Prevent inline - JS to be executed (i.e. XSS) in browsers which support this,
|
||||
// Inline-JS is no longer allowed and used
|
||||
// See: http://people.mozilla.org/~bsterne/content-security-policy/index.html
|
||||
// New stuff see: https://www.owasp.org/index.php/List_of_useful_HTTP_headers and https://www.owasp.org/index.php/Content_Security_Policy
|
||||
$csp_content = "default-src 'self'; script-src 'self' 'unsafe-inline'; connect-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';";
|
||||
header("Content-Security-Policy: " . $csp_content);
|
||||
header("X-Content-Security-Policy: " . $csp_content);
|
||||
header("X-WebKit-CSP: " . $csp_content);
|
||||
|
||||
header("X-XSS-Protection: 1; mode=block");
|
||||
|
||||
// Don't allow to load Froxlor in an iframe to prevent i.e. clickjacking
|
||||
header("X-Frame-Options: DENY");
|
||||
|
||||
// Internet Explorer shall not guess the Content-Type, see:
|
||||
// http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx
|
||||
header("X-Content-Type-Options: nosniff");
|
||||
|
||||
// ensure that default timezone is set
|
||||
if (function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get")) {
|
||||
@date_default_timezone_set(@date_default_timezone_get());
|
||||
}
|
||||
|
||||
self::sendSslHeaders();
|
||||
}
|
||||
|
||||
private static function sendSslHeaders()
|
||||
{
|
||||
/**
|
||||
* If Froxlor was called via HTTPS -> enforce it for the next time by settings HSTS header according to settings
|
||||
*/
|
||||
if (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) {
|
||||
$maxage = \Froxlor\Settings::Get('system.hsts_maxage');
|
||||
if (empty($maxage)) {
|
||||
$maxage = 0;
|
||||
}
|
||||
$hsts_header = "Strict-Transport-Security: max-age=" . $maxage;
|
||||
if (\Froxlor\Settings::Get('system.hsts_incsub') == '1') {
|
||||
$hsts_header .= "; includeSubDomains";
|
||||
}
|
||||
if (\Froxlor\Settings::Get('system.hsts_preload') == '1') {
|
||||
$hsts_header .= "; preload";
|
||||
}
|
||||
header($hsts_header);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize Twig template engine
|
||||
*/
|
||||
public static function initTwig(bool $install_mode = false)
|
||||
{
|
||||
self::$install_mode = $install_mode;
|
||||
// init twig template engine
|
||||
$loader = new \Twig\Loader\FilesystemLoader(\Froxlor\Froxlor::getInstallDir() . '/templates/');
|
||||
self::$twig = new \Twig\Environment($loader, array(
|
||||
'debug' => true,
|
||||
'cache' => \Froxlor\Froxlor::getInstallDir() . '/cache',
|
||||
'auto_reload' => true
|
||||
));
|
||||
self::$twig->addExtension(new \Twig\Extension\DebugExtension());
|
||||
self::$twig->addExtension(new CustomReflection());
|
||||
self::$twig->addExtension(new FroxlorTwig());
|
||||
// empty buffer
|
||||
self::$twigbuf = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* twig wrapper
|
||||
*
|
||||
* @return \Twig\Environment
|
||||
*/
|
||||
public static function Twig()
|
||||
{
|
||||
return self::$twig;
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper for twig's "render" function to buffer the output
|
||||
*
|
||||
* @see \Twig\Environment::render()
|
||||
*/
|
||||
public static function TwigBuffer($name, array $context = [])
|
||||
{
|
||||
self::$twigbuf[] = [
|
||||
self::getTheme() . '/' . $name => $context
|
||||
];
|
||||
}
|
||||
|
||||
public static function getTheme()
|
||||
{
|
||||
// fallback
|
||||
$theme = self::$default_theme;
|
||||
if (!self::$install_mode) {
|
||||
// system default
|
||||
if (\Froxlor\Froxlor::DBVERSION <= 201909150) {
|
||||
\Froxlor\Settings::Set('panel.default_theme', 'Sparkle2');
|
||||
}
|
||||
$theme = (\Froxlor\Settings::Get('panel.default_theme') !== null) ? \Froxlor\Settings::Get('panel.default_theme') : $theme;
|
||||
// customer theme
|
||||
/*
|
||||
if (\Froxlor\CurrentUser::hasSession() && \Froxlor\CurrentUser::getField('theme') != $theme) {
|
||||
$theme = \Froxlor\CurrentUser::getField('theme');
|
||||
}
|
||||
*/
|
||||
}
|
||||
if (!file_exists(\Froxlor\Froxlor::getInstallDir() . '/templates/' . $theme)) {
|
||||
\Froxlor\PhpHelper::phpErrHandler(E_USER_WARNING, "Theme '" . $theme . "' could not be found.", __FILE__, __LINE__, null);
|
||||
$theme = self::$default_theme;
|
||||
}
|
||||
return $theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* echo output buffer and empty buffer-content
|
||||
*/
|
||||
public static function TwigOutputBuffer()
|
||||
{
|
||||
$output = "";
|
||||
foreach (self::$twigbuf as $buf) {
|
||||
foreach ($buf as $name => $context) {
|
||||
try {
|
||||
$output .= self::$twig->render($name, $context);
|
||||
} catch (\Exception $e) {
|
||||
// whoops, template error
|
||||
$errtpl = 'alert_nosession.html.twig';
|
||||
/*
|
||||
if (\Froxlor\CurrentUser::hasSession()) {
|
||||
$errtpl = 'alert.html.twig';
|
||||
}
|
||||
*/
|
||||
$edata = array(
|
||||
'type' => "danger",
|
||||
'heading' => "Template error",
|
||||
'alert_msg' => $e->getMessage(),
|
||||
'alert_info' => $e->getTraceAsString()
|
||||
);
|
||||
try {
|
||||
// try with user theme if set
|
||||
$output .= self::$twig->render(self::getTheme() . '/misc/' . $errtpl, $edata);
|
||||
} catch (\Exception $e) {
|
||||
// try with default theme if different from user theme
|
||||
if (self::getTheme() != self::$default_theme) {
|
||||
$output .= self::$twig->render(self::$default_theme . '/misc/' . $errtpl, $edata);
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
echo $output;
|
||||
// empty buffer
|
||||
self::$twigbuf = [];
|
||||
}
|
||||
|
||||
public static function setLng($lng = array())
|
||||
{
|
||||
self::$lng = $lng;
|
||||
}
|
||||
|
||||
public static function getLng($identifier, $context = null)
|
||||
{
|
||||
$id = explode(".", $identifier);
|
||||
if (is_null($context)) {
|
||||
$id_first = array_shift($id);
|
||||
if (!isset(self::$lng[$id_first])) {
|
||||
return null;
|
||||
}
|
||||
if (empty($id)) {
|
||||
return self::$lng[$id_first];
|
||||
} else {
|
||||
return self::getLng(implode(".", $id), self::$lng[$id_first]);
|
||||
}
|
||||
} else {
|
||||
$id_first = array_shift($id);
|
||||
if (empty($id)) {
|
||||
return isset($context[$id_first]) ? $context[$id_first] : null;
|
||||
} else {
|
||||
return self::getLng(implode(".", $id), $context[$id_first]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an array of available themes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getThemes()
|
||||
{
|
||||
$themespath = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/templates/');
|
||||
$themes_available = array();
|
||||
|
||||
if (is_dir($themespath)) {
|
||||
$its = new \DirectoryIterator($themespath);
|
||||
|
||||
foreach ($its as $it) {
|
||||
if ($it->isDir() && $it->getFilename() != '.' && $it->getFilename() != '..' && $it->getFilename() != 'misc') {
|
||||
$theme = $themespath . $it->getFilename();
|
||||
if (file_exists($theme . '/config.json')) {
|
||||
$themeconfig = json_decode(file_get_contents($theme . '/config.json'), true);
|
||||
if (array_key_exists('variants', $themeconfig) && is_array($themeconfig['variants'])) {
|
||||
foreach ($themeconfig['variants'] as $variant => $data) {
|
||||
if ($variant == "default") {
|
||||
$themes_available[$it->getFilename()] = $it->getFilename();
|
||||
} elseif (array_key_exists('description', $data)) {
|
||||
$themes_available[$it->getFilename() . '_' . $variant] = $data['description'];
|
||||
} else {
|
||||
$themes_available[$it->getFilename() . '_' . $variant] = $it->getFilename() . ' (' . $variant . ')';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$themes_available[$it->getFilename()] = $it->getFilename();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $themes_available;
|
||||
}
|
||||
}
|
||||
165
lib/init.php
165
lib/init.php
@@ -18,22 +18,22 @@
|
||||
*/
|
||||
|
||||
// define default theme for configurehint, etc.
|
||||
$_deftheme = 'Sparkle';
|
||||
$_deftheme = 'Froxlor';
|
||||
|
||||
// validate correct php version
|
||||
if (version_compare("7.1.0", PHP_VERSION, ">=")) {
|
||||
// get hint-template
|
||||
$vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/phprequirementfailed.tpl');
|
||||
$wrongphp_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/phprequirementfailed.html.twig');
|
||||
// replace values
|
||||
$vendor_hint = str_replace("<FROXLOR_PHPMIN>", "7.1.0", $vendor_hint);
|
||||
$vendor_hint = str_replace("<CURRENT_VERSION>", PHP_VERSION, $vendor_hint);
|
||||
$vendor_hint = str_replace("<CURRENT_YEAR>", date('Y', time()), $vendor_hint);
|
||||
die($vendor_hint);
|
||||
$wrongphp_hint = str_replace("<FROXLOR_PHPMIN>", "7.1.0", $wrongphp_hint);
|
||||
$wrongphp_hint = str_replace("<CURRENT_VERSION>", PHP_VERSION, $wrongphp_hint);
|
||||
$wrongphp_hint = str_replace("<CURRENT_YEAR>", date('Y', time()), $wrongphp_hint);
|
||||
die($wrongphp_hint);
|
||||
}
|
||||
|
||||
if (! file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
|
||||
if (!file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
|
||||
// get hint-template
|
||||
$vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/vendormissinghint.tpl');
|
||||
$vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/vendormissinghint.html.twig');
|
||||
// replace values
|
||||
$vendor_hint = str_replace("<FROXLOR_INSTALL_DIR>", dirname(__DIR__), $vendor_hint);
|
||||
$vendor_hint = str_replace("<CURRENT_YEAR>", date('Y', time()), $vendor_hint);
|
||||
@@ -46,37 +46,11 @@ use Froxlor\Database\Database;
|
||||
use Froxlor\Settings;
|
||||
use voku\helper\AntiXSS;
|
||||
use Froxlor\PhpHelper;
|
||||
use Froxlor\UI\Panel\UI;
|
||||
|
||||
header("Content-Type: text/html; charset=UTF-8");
|
||||
UI::sendHeaders();
|
||||
UI::initTwig();
|
||||
|
||||
// prevent Froxlor pages from being cached
|
||||
header("Cache-Control: no-store, no-cache, must-revalidate");
|
||||
header("Pragma: no-cache");
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
|
||||
|
||||
// Prevent inline - JS to be executed (i.e. XSS) in browsers which support this,
|
||||
// Inline-JS is no longer allowed and used
|
||||
// See: http://people.mozilla.org/~bsterne/content-security-policy/index.html
|
||||
// New stuff see: https://www.owasp.org/index.php/List_of_useful_HTTP_headers and https://www.owasp.org/index.php/Content_Security_Policy
|
||||
$csp_content = "default-src 'self'; script-src 'self'; connect-src 'self'; img-src 'self' data:; style-src 'self';";
|
||||
header("Content-Security-Policy: " . $csp_content);
|
||||
header("X-Content-Security-Policy: " . $csp_content);
|
||||
header("X-WebKit-CSP: " . $csp_content);
|
||||
|
||||
header("X-XSS-Protection: 1; mode=block");
|
||||
|
||||
// Don't allow to load Froxlor in an iframe to prevent i.e. clickjacking
|
||||
header("X-Frame-Options: DENY");
|
||||
|
||||
// Internet Explorer shall not guess the Content-Type, see:
|
||||
// http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx
|
||||
header("X-Content-Type-Options: nosniff");
|
||||
|
||||
// ensure that default timezone is set
|
||||
if (function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get")) {
|
||||
@date_default_timezone_set(@date_default_timezone_get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Globals Security Fix
|
||||
@@ -106,81 +80,51 @@ unset($key);
|
||||
$filename = htmlentities(basename($_SERVER['SCRIPT_NAME']));
|
||||
|
||||
// check whether the userdata file exists
|
||||
if (! file_exists(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
||||
$config_hint = file_get_contents(\Froxlor\Froxlor::getInstallDir() . '/templates/' . $_deftheme . '/misc/configurehint.tpl');
|
||||
$config_hint = str_replace("<CURRENT_YEAR>", date('Y', time()), $config_hint);
|
||||
die($config_hint);
|
||||
if (!file_exists(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
||||
UI::Twig()->addGlobal('install_mode', '1');
|
||||
echo UI::Twig()->render($_deftheme . '/misc/configurehint.html.twig');
|
||||
die();
|
||||
}
|
||||
|
||||
// check whether we can read the userdata file
|
||||
if (! is_readable(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
||||
if (!is_readable(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
||||
// get possible owner
|
||||
$posixusername = posix_getpwuid(posix_getuid());
|
||||
$posixgroup = posix_getgrgid(posix_getgid());
|
||||
// get hint-template
|
||||
$owner_hint = file_get_contents(\Froxlor\Froxlor::getInstallDir() . '/templates/' . $_deftheme . '/misc/ownershiphint.tpl');
|
||||
// replace values
|
||||
$owner_hint = str_replace("<USER>", $posixusername['name'], $owner_hint);
|
||||
$owner_hint = str_replace("<GROUP>", $posixgroup['name'], $owner_hint);
|
||||
$owner_hint = str_replace("<FROXLOR_INSTALL_DIR>", \Froxlor\Froxlor::getInstallDir(), $owner_hint);
|
||||
$owner_hint = str_replace("<CURRENT_YEAR>", date('Y', time()), $owner_hint);
|
||||
// show
|
||||
die($owner_hint);
|
||||
UI::Twig()->addGlobal('install_mode', '1');
|
||||
echo UI::Twig()->render($_deftheme . '/misc/ownershiphint.html.twig', [
|
||||
'user' => $posixusername['name'],
|
||||
'group' => $posixgroup['name'],
|
||||
'installdir' => \Froxlor\Froxlor::getInstallDir()
|
||||
]);
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the Usersettings eg.
|
||||
* MySQL-Username/Passwort etc.
|
||||
*/
|
||||
// include MySQL-Username/Passwort etc.
|
||||
require \Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php';
|
||||
|
||||
if (! isset($sql) || ! is_array($sql)) {
|
||||
$config_hint = file_get_contents(\Froxlor\Froxlor::getInstallDir() . '/templates/' . $_deftheme . '/misc/configurehint.tpl');
|
||||
$config_hint = str_replace("<CURRENT_YEAR>", date('Y', time()), $config_hint);
|
||||
die($config_hint);
|
||||
if (!isset($sql) || !is_array($sql)) {
|
||||
UI::Twig()->addGlobal('install_mode', '1');
|
||||
echo UI::Twig()->render($_deftheme . '/misc/configurehint.html.twig');
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the Functions
|
||||
*/
|
||||
@set_error_handler(array(
|
||||
// set error-handler
|
||||
@set_error_handler([
|
||||
'\\Froxlor\\PhpHelper',
|
||||
'phpErrHandler'
|
||||
));
|
||||
]);
|
||||
@set_exception_handler([
|
||||
'\\Froxlor\\PhpHelper',
|
||||
'phpExceptionHandler'
|
||||
]);
|
||||
|
||||
/**
|
||||
* Includes the MySQL-Tabledefinitions etc.
|
||||
*/
|
||||
// include MySQL-tabledefinitions
|
||||
require \Froxlor\Froxlor::getInstallDir() . '/lib/tables.inc.php';
|
||||
|
||||
/**
|
||||
* Create a new idna converter
|
||||
*/
|
||||
// create a new idna converter
|
||||
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
|
||||
|
||||
/**
|
||||
* If Froxlor was called via HTTPS -> enforce it for the next time by settings HSTS header according to settings
|
||||
*/
|
||||
$is_ssl = false;
|
||||
if (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) {
|
||||
$is_ssl = true;
|
||||
$maxage = Settings::Get('system.hsts_maxage');
|
||||
if (empty($maxage)) {
|
||||
$maxage = 0;
|
||||
}
|
||||
$hsts_header = "Strict-Transport-Security: max-age=" . $maxage;
|
||||
if (Settings::Get('system.hsts_incsub') == '1') {
|
||||
$hsts_header .= "; includeSubDomains";
|
||||
}
|
||||
if (Settings::Get('system.hsts_preload') == '1') {
|
||||
$hsts_header .= "; preload";
|
||||
}
|
||||
header($hsts_header);
|
||||
}
|
||||
|
||||
/**
|
||||
* SESSION MANAGEMENT
|
||||
*/
|
||||
// SESSION MANAGEMENT
|
||||
$remote_addr = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
if (empty($_SERVER['HTTP_USER_AGENT'])) {
|
||||
@@ -248,7 +192,7 @@ if (isset($s) && $s != "" && $nosession != 1) {
|
||||
$userinfo_stmt = Database::prepare($query);
|
||||
$userinfo = Database::pexecute_first($userinfo_stmt, $userinfo_data);
|
||||
|
||||
if ($userinfo && (($userinfo['adminsession'] == '1' && AREA == 'admin' && isset($userinfo['adminid'])) || ($userinfo['adminsession'] == '0' && (AREA == 'customer' || AREA == 'login') && isset($userinfo['customerid']))) && (! isset($userinfo['deactivated']) || $userinfo['deactivated'] != '1')) {
|
||||
if ($userinfo && (($userinfo['adminsession'] == '1' && AREA == 'admin' && isset($userinfo['adminid'])) || ($userinfo['adminsession'] == '0' && (AREA == 'customer' || AREA == 'login') && isset($userinfo['customerid']))) && (!isset($userinfo['deactivated']) || $userinfo['deactivated'] != '1')) {
|
||||
$upd_stmt = Database::prepare("
|
||||
UPDATE `" . TABLE_PANEL_SESSIONS . "` SET
|
||||
`lastactivity` = :lastactive
|
||||
@@ -303,14 +247,14 @@ if (isset($userinfo['language']) && isset($languages[$userinfo['language']])) {
|
||||
// default: use language from session, #277
|
||||
$language = $userinfo['language'];
|
||||
} else {
|
||||
if (! isset($userinfo['def_language']) || ! isset($languages[$userinfo['def_language']])) // this will always evaluat true, since it is the above statement inverted. @todo remove
|
||||
if (!isset($userinfo['def_language']) || !isset($languages[$userinfo['def_language']])) // this will always evaluat true, since it is the above statement inverted. @todo remove
|
||||
{
|
||||
if (isset($_GET['language']) && isset($languages[$_GET['language']])) {
|
||||
$language = $_GET['language'];
|
||||
} else {
|
||||
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
||||
$accept_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
|
||||
for ($i = 0; $i < count($accept_langs); $i ++) {
|
||||
for ($i = 0; $i < count($accept_langs); $i++) {
|
||||
// this only works for most common languages. some (uncommon) languages have a 3 letter iso-code.
|
||||
// to be able to use these also, we would have to depend on the intl extension for php (using Locale::lookup or similar)
|
||||
// as long as froxlor does not support any of these languages, we can leave it like that.
|
||||
@@ -322,7 +266,7 @@ if (isset($userinfo['language']) && isset($languages[$userinfo['language']])) {
|
||||
unset($iso);
|
||||
|
||||
// if HTTP_ACCEPT_LANGUAGES has no valid langs, use default (very unlikely)
|
||||
if (! strlen($language) > 0) {
|
||||
if (!strlen($language) > 0) {
|
||||
$language = Settings::Get('panel.standardlanguage');
|
||||
}
|
||||
}
|
||||
@@ -370,7 +314,7 @@ if (preg_match("/([a-z0-9\.\-]+)_([a-z0-9\.\-]+)/i", $theme, $matches)) {
|
||||
}
|
||||
|
||||
// check for existence of the theme
|
||||
if (! file_exists('templates/' . $theme . '/config.json')) {
|
||||
if (!file_exists('templates/' . $theme . '/config.json')) {
|
||||
// Fallback
|
||||
$theme = $_deftheme;
|
||||
}
|
||||
@@ -378,7 +322,7 @@ if (! file_exists('templates/' . $theme . '/config.json')) {
|
||||
$_themeoptions = json_decode(file_get_contents('templates/' . $theme . '/config.json'), true);
|
||||
|
||||
// check for existence of variant in theme
|
||||
if (! array_key_exists('variants', $_themeoptions) || ! array_key_exists($themevariant, $_themeoptions['variants'])) {
|
||||
if (!array_key_exists('variants', $_themeoptions) || !array_key_exists($themevariant, $_themeoptions['variants'])) {
|
||||
$themevariant = "default";
|
||||
}
|
||||
|
||||
@@ -494,25 +438,28 @@ if (array_key_exists('css', $_themeoptions['variants'][$themevariant]) && is_arr
|
||||
}
|
||||
}
|
||||
}
|
||||
eval("\$header = \"" . \Froxlor\UI\Template::getTemplate('header', '1') . "\";");
|
||||
|
||||
$current_year = date('Y', time());
|
||||
UI::Twig()->addGlobal('theme_js', $js);
|
||||
UI::Twig()->addGlobal('theme_css', $css);
|
||||
unset($js);
|
||||
unset($css);
|
||||
|
||||
/**
|
||||
* @TODO
|
||||
*
|
||||
$panel_imprint_url = Settings::Get('panel.imprint_url');
|
||||
if (!empty($panel_imprint_url) && strtolower(substr($panel_imprint_url, 0, 4)) != 'http') {
|
||||
$panel_imprint_url = 'https://'.$panel_imprint_url;
|
||||
$panel_imprint_url = 'https://' . $panel_imprint_url;
|
||||
}
|
||||
$panel_terms_url = Settings::Get('panel.terms_url');
|
||||
if (!empty($panel_terms_url) && strtolower(substr($panel_terms_url, 0, 4)) != 'http') {
|
||||
$panel_terms_url = 'https://'.$panel_terms_url;
|
||||
$panel_terms_url = 'https://' . $panel_terms_url;
|
||||
}
|
||||
$panel_privacy_url = Settings::Get('panel.privacy_url');
|
||||
if (!empty($panel_privacy_url) && strtolower(substr($panel_privacy_url, 0, 4)) != 'http') {
|
||||
$panel_privacy_url = 'https://'.$panel_privacy_url;
|
||||
$panel_privacy_url = 'https://' . $panel_privacy_url;
|
||||
}
|
||||
eval("\$footer = \"" . \Froxlor\UI\Template::getTemplate('footer', '1') . "\";");
|
||||
|
||||
unset($js);
|
||||
unset($css);
|
||||
*/
|
||||
|
||||
if (isset($_POST['action'])) {
|
||||
$action = trim(strip_tags($_POST['action']));
|
||||
|
||||
Reference in New Issue
Block a user