Merge branch 'main' of github.com:Froxlor/Froxlor
This commit is contained in:
@@ -162,7 +162,7 @@ class Ajax
|
||||
$content = preg_replace("/[\r\n]+/", " ", strip_tags($item->description));
|
||||
$content = substr($content, 0, 150) . "...";
|
||||
|
||||
$items .= UI::twig()->render($this->theme . '/user/newsfeeditem.html.twig', [
|
||||
$items .= UI::twig()->render(UI::validateThemeTemplate('/user/newsfeeditem.html.twig', $this->theme), [
|
||||
'link' => $link,
|
||||
'title' => $title,
|
||||
'date' => $date,
|
||||
@@ -201,7 +201,7 @@ class Ajax
|
||||
$result['last_update_check'] = $uc_data['ts'];
|
||||
$result['channel'] = Settings::Get('system.update_channel');
|
||||
|
||||
$result_rendered = UI::twig()->render($this->theme . '/misc/version_top.html.twig', $result);
|
||||
$result_rendered = UI::twig()->render(UI::validateThemeTemplate('/misc/version_top.html.twig', $this->theme), $result);
|
||||
return $this->jsonResponse($result_rendered);
|
||||
} catch (Exception $e) {
|
||||
// don't display anything if just not allowed due to permissions
|
||||
|
||||
@@ -117,6 +117,6 @@ class Api
|
||||
|
||||
private function stripcslashesDeep($value)
|
||||
{
|
||||
return is_array($value) ? array_map([$this, 'stripcslashesDeep'], $value) : stripcslashes($value);
|
||||
return is_array($value) ? array_map([$this, 'stripcslashesDeep'], $value) : (!empty($value) ? stripcslashes($value) : null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ use Froxlor\Cron\TaskId;
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\FroxlorLogger;
|
||||
use Froxlor\System\Cronjob;
|
||||
use Froxlor\UI\Response;
|
||||
use Froxlor\Validate\Validate;
|
||||
use PDO;
|
||||
|
||||
@@ -41,6 +42,14 @@ use PDO;
|
||||
class Cronjobs extends ApiCommand implements ResourceEntity
|
||||
{
|
||||
|
||||
private array $allowed_intervals = [
|
||||
'MINUTE',
|
||||
'HOUR',
|
||||
'DAY',
|
||||
'WEEK',
|
||||
'MONTH'
|
||||
];
|
||||
|
||||
/**
|
||||
* You cannot add new cronjobs yet.
|
||||
*/
|
||||
@@ -118,6 +127,10 @@ class Cronjobs extends ApiCommand implements ResourceEntity
|
||||
$interval_value = Validate::validate($interval_value, 'interval_value', '/^([0-9]+)$/Di', 'stringisempty', [], true);
|
||||
$interval_interval = Validate::validate($interval_interval, 'interval_interval', '', '', [], true);
|
||||
|
||||
if (!in_array(strtoupper($interval_interval), $this->allowed_intervals)) {
|
||||
Response::standardError('invalidcronjobintervalvalue', implode(", ", $this->allowed_intervals), true);
|
||||
}
|
||||
|
||||
// put together interval value
|
||||
$interval = $interval_value . ' ' . strtoupper($interval_interval);
|
||||
|
||||
|
||||
@@ -157,16 +157,15 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
||||
* this functions validates a given value as ErrorDocument
|
||||
* refs #267
|
||||
*
|
||||
* @param
|
||||
* string error-document-string
|
||||
* @param string $errdoc
|
||||
* @param bool $throw_exception
|
||||
*
|
||||
* @return string error-document-string
|
||||
*
|
||||
*/
|
||||
private function correctErrorDocument($errdoc = null, $throw_exception = false)
|
||||
private function correctErrorDocument(string $errdoc, $throw_exception = false)
|
||||
{
|
||||
if ($errdoc !== null && $errdoc != '') {
|
||||
if (trim($errdoc) != '') {
|
||||
// not a URL
|
||||
if ((strtoupper(substr($errdoc, 0, 5)) != 'HTTP:' && strtoupper(substr($errdoc, 0, 6)) != 'HTTPS:') || !Validate::validateUrl($errdoc)) {
|
||||
// a file
|
||||
@@ -176,14 +175,14 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
||||
if (!substr($errdoc, 0, 1) == '/') {
|
||||
$errdoc = '/' . $errdoc;
|
||||
}
|
||||
} else {
|
||||
} elseif (preg_match('/^"([^\r\n\t\f\0"]+)"$/', $errdoc)) {
|
||||
// a string (check for ending ")
|
||||
// string won't work for lighty
|
||||
if (Settings::Get('system.webserver') == 'lighttpd') {
|
||||
Response::standardError('stringerrordocumentnotvalidforlighty', '', $throw_exception);
|
||||
} elseif (substr($errdoc, -1) != '"') {
|
||||
$errdoc .= '"';
|
||||
}
|
||||
} else {
|
||||
Response::standardError('invaliderrordocumentvalue', '', $throw_exception);
|
||||
}
|
||||
} else {
|
||||
if (Settings::Get('system.webserver') == 'lighttpd') {
|
||||
@@ -191,7 +190,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
||||
}
|
||||
}
|
||||
}
|
||||
return $errdoc;
|
||||
return trim($errdoc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -87,7 +87,8 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
||||
$path = FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
|
||||
$username = Validate::validate($username, 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', [], true);
|
||||
$authname = Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', [], true);
|
||||
Validate::validate($password, 'password', '', '', [], true);
|
||||
$password = Validate::validate($password, 'password', '', '', [], true);
|
||||
$password = Crypt::validatePassword($password, true);
|
||||
|
||||
// check for duplicate usernames for the path
|
||||
$username_path_check_stmt = Database::prepare("
|
||||
@@ -244,7 +245,8 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
||||
|
||||
// validation
|
||||
$authname = Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', [], true);
|
||||
Validate::validate($password, 'password', '', '', [], true);
|
||||
$password = Validate::validate($password, 'password', '', '', [], true);
|
||||
$password = Crypt::validatePassword($password, true);
|
||||
|
||||
$upd_query = "";
|
||||
$upd_params = [
|
||||
|
||||
@@ -246,7 +246,10 @@ final class InstallCommand extends Command
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->io->error($e->getMessage());
|
||||
return $this->showStep($step, $extended, $decoded_input);
|
||||
if ($this->io->confirm('Retry?', empty($decoded_input))) {
|
||||
return $this->showStep($step, $extended, $decoded_input);
|
||||
}
|
||||
return self::FAILURE;
|
||||
}
|
||||
if ($step == 3) {
|
||||
// do actual install with data from $this->formfielddata
|
||||
@@ -297,7 +300,7 @@ final class InstallCommand extends Command
|
||||
$json_output = [];
|
||||
foreach ($fields['install']['sections'] as $section => $section_fields) {
|
||||
foreach ($section_fields['fields'] as $name => $field) {
|
||||
if ($name == 'system' || $name == 'manual_config') {
|
||||
if ($name == 'system' || $name == 'manual_config' || $name == 'target_servername') {
|
||||
continue;
|
||||
}
|
||||
if ($field['type'] == 'text' || $field['type'] == 'email') {
|
||||
|
||||
@@ -148,7 +148,7 @@ class ConfigDisplay
|
||||
if ($lasttype != '' && $lasttype != $_action['type']) {
|
||||
$commands = trim($commands);
|
||||
$numbrows = count(explode("\n", $commands));
|
||||
$configpage .= UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [
|
||||
$configpage .= UI::twig()->render(UI::validateThemeTemplate('/settings/conf/command.html.twig', self::$theme), [
|
||||
'commands' => $commands,
|
||||
'numbrows' => $numbrows
|
||||
]);
|
||||
@@ -182,7 +182,7 @@ class ConfigDisplay
|
||||
$commands = trim($commands_pre);
|
||||
if ($commands != "") {
|
||||
$numbrows = count(explode("\n", $commands));
|
||||
$commands_pre = UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [
|
||||
$commands_pre = UI::twig()->render(UI::validateThemeTemplate('/settings/conf/command.html.twig', self::$theme), [
|
||||
'commands' => $commands,
|
||||
'numbrows' => $numbrows
|
||||
]);
|
||||
@@ -190,12 +190,12 @@ class ConfigDisplay
|
||||
$commands = trim($commands_post);
|
||||
if ($commands != "") {
|
||||
$numbrows = count(explode("\n", $commands));
|
||||
$commands_post = UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [
|
||||
$commands_post = UI::twig()->render(UI::validateThemeTemplate('/settings/conf/command.html.twig', self::$theme), [
|
||||
'commands' => $commands,
|
||||
'numbrows' => $numbrows
|
||||
]);
|
||||
}
|
||||
$configpage .= UI::twig()->render(self::$theme . '/settings/conf/fileblock.html.twig', [
|
||||
$configpage .= UI::twig()->render(UI::validateThemeTemplate('/settings/conf/fileblock.html.twig', self::$theme), [
|
||||
'realname' => $realname,
|
||||
'commands_pre' => $commands_pre,
|
||||
'commands_file' => $commands_file,
|
||||
@@ -210,7 +210,7 @@ class ConfigDisplay
|
||||
$commands = trim($commands);
|
||||
if ($commands != '') {
|
||||
$numbrows = count(explode("\n", $commands));
|
||||
$configpage .= UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', [
|
||||
$configpage .= UI::twig()->render(UI::validateThemeTemplate('/settings/conf/command.html.twig', self::$theme), [
|
||||
'commands' => $commands,
|
||||
'numbrows' => $numbrows
|
||||
]);
|
||||
@@ -233,7 +233,7 @@ class ConfigDisplay
|
||||
$file_content = htmlspecialchars($file_content);
|
||||
$numbrows = count(explode("\n", $file_content));
|
||||
//eval("\$files=\"" . \Froxlor\UI\Template::getTemplate("configfiles/configfiles_file") . "\";");
|
||||
$files = UI::twig()->render(self::$theme . '/settings/conf/file.html.twig', [
|
||||
$files = UI::twig()->render(UI::validateThemeTemplate('/settings/conf/file.html.twig', self::$theme), [
|
||||
'distro_editor' => self::$editor,
|
||||
'realname' => $realname,
|
||||
'numbrows' => $numbrows,
|
||||
|
||||
@@ -147,9 +147,9 @@ class FileDir
|
||||
*/
|
||||
public static function makeSecurePath($path)
|
||||
{
|
||||
// check for bad characters, some are allowed with escaping
|
||||
// check for bad characters, some are allowed with escaping,
|
||||
// but we generally don't want them in our directory-names,
|
||||
// thx to aaronmueller for this snipped
|
||||
// thx to aaronmueller for this snippet
|
||||
$badchars = [
|
||||
':',
|
||||
';',
|
||||
@@ -161,7 +161,11 @@ class FileDir
|
||||
'$',
|
||||
'~',
|
||||
'?',
|
||||
"\0"
|
||||
"\0",
|
||||
"\n",
|
||||
"\r",
|
||||
"\t",
|
||||
"\f"
|
||||
];
|
||||
foreach ($badchars as $bc) {
|
||||
$path = str_replace($bc, "", $path);
|
||||
@@ -606,7 +610,7 @@ class FileDir
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public static function getFilesystemQuota()
|
||||
|
||||
@@ -31,7 +31,7 @@ final class Froxlor
|
||||
{
|
||||
|
||||
// Main version variable
|
||||
const VERSION = '2.0.9';
|
||||
const VERSION = '2.0.10';
|
||||
|
||||
// Database version (YYYYMMDDC where C is a daily counter)
|
||||
const DBVERSION = '202301180';
|
||||
|
||||
@@ -92,7 +92,7 @@ class Text
|
||||
$result = $attributes['fields'];
|
||||
$apikey_data = include Froxlor::getInstallDir() . '/lib/formfields/formfield.api_key.php';
|
||||
|
||||
$body = UI::twig()->render(UI::getTheme() . '/user/inline-form.html.twig', [
|
||||
$body = UI::twig()->render(UI::validateThemeTemplate('/user/inline-form.html.twig'), [
|
||||
'formaction' => $linker->getLink(['section' => 'index', 'page' => 'apikeys']),
|
||||
'formdata' => $apikey_data['apikey'],
|
||||
'editid' => $attributes['fields']['id']
|
||||
|
||||
@@ -95,7 +95,7 @@ class UI
|
||||
session_set_cookie_params([
|
||||
'lifetime' => self::$install_mode ? 7200 : 600, // will be renewed based on settings in lib/init.php
|
||||
'path' => '/',
|
||||
'domain' => $_SERVER['SERVER_NAME'],
|
||||
'domain' => explode(':', $_SERVER['HTTP_HOST'])[0],
|
||||
'secure' => self::requestIsHttps(),
|
||||
'httponly' => true,
|
||||
'samesite' => 'Strict'
|
||||
@@ -260,7 +260,18 @@ class UI
|
||||
*/
|
||||
public static function twigBuffer($name, array $context = [])
|
||||
{
|
||||
$template_file = self::getTheme() . '/' . $name;
|
||||
$template_file = self::validateThemeTemplate($name);
|
||||
|
||||
self::$twigbuf[] = [
|
||||
$template_file => $context
|
||||
];
|
||||
}
|
||||
|
||||
public static function validateThemeTemplate(string $name, string $theme = "") {
|
||||
if (empty(trim($theme))) {
|
||||
$theme = self::getTheme();
|
||||
}
|
||||
$template_file = $theme . '/' . $name;
|
||||
if (!file_exists(Froxlor::getInstallDir() . '/templates/' . $template_file)) {
|
||||
PhpHelper::phpErrHandler(E_USER_WARNING, "Template '" . $template_file . "' could not be found, trying fallback theme", __FILE__, __LINE__);
|
||||
$template_file = self::$default_theme . '/'. $name;
|
||||
@@ -268,10 +279,7 @@ class UI
|
||||
PhpHelper::phpErrHandler(E_USER_ERROR, "Unknown template '" . $template_file . "'", __FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
self::$twigbuf[] = [
|
||||
$template_file => $context
|
||||
];
|
||||
return $template_file;
|
||||
}
|
||||
|
||||
public static function getTheme()
|
||||
|
||||
@@ -332,7 +332,7 @@ if (CurrentUser::hasSession()) {
|
||||
$cookie_params = [
|
||||
'expires' => time() + Settings::Get('session.sessiontimeout'),
|
||||
'path' => '/',
|
||||
'domain' => $_SERVER['SERVER_NAME'],
|
||||
'domain' => explode(':', $_SERVER['HTTP_HOST'])[0],
|
||||
'secure' => UI::requestIsHttps(),
|
||||
'httponly' => true,
|
||||
'samesite' => 'Strict'
|
||||
|
||||
Reference in New Issue
Block a user