kinda fix error-handlers; more work on admin-dashboard

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
Michael Kaufmann
2022-02-17 17:23:04 +01:00
parent b4d9b1037d
commit 9dce16e5c7
5 changed files with 96 additions and 69 deletions

View File

@@ -186,7 +186,9 @@ if ($page == 'overview') {
UI::Twig()->addGlobal('userinfo', $userinfo); UI::Twig()->addGlobal('userinfo', $userinfo);
UI::TwigBuffer('user/index.html.twig', [ UI::TwigBuffer('user/index.html.twig', [
'sysinfo' => $sysinfo, 'sysinfo' => $sysinfo,
'overview' => $overview 'overview' => $overview,
'outstanding_tasks' => $outstanding_tasks,
'cron_last_runs' => $cron_last_runs
]); ]);
UI::TwigOutputBuffer(); UI::TwigOutputBuffer();
} elseif ($page == 'change_password') { } elseif ($page == 'change_password') {

View File

@@ -1,4 +1,5 @@
<?php <?php
namespace Froxlor; namespace Froxlor;
class PhpHelper class PhpHelper
@@ -53,12 +54,12 @@ class PhpHelper
public static function htmlentitiesArray($subject, $fields = '', $quote_style = ENT_QUOTES, $charset = 'UTF-8') public static function htmlentitiesArray($subject, $fields = '', $quote_style = ENT_QUOTES, $charset = 'UTF-8')
{ {
if (is_array($subject)) { if (is_array($subject)) {
if (! is_array($fields)) { if (!is_array($fields)) {
$fields = self::arrayTrim(explode(' ', $fields)); $fields = self::arrayTrim(explode(' ', $fields));
} }
foreach ($subject as $field => $value) { foreach ($subject as $field => $value) {
if ((! is_array($fields) || empty($fields)) || (is_array($fields) && ! empty($fields) && in_array($field, $fields))) { if ((!is_array($fields) || empty($fields)) || (is_array($fields) && !empty($fields) && in_array($field, $fields))) {
// Just call ourselve to manage multi-dimensional arrays // Just call ourselve to manage multi-dimensional arrays
$subject[$field] = self::htmlentitiesArray($subject[$field], $fields, $quote_style, $charset); $subject[$field] = self::htmlentitiesArray($subject[$field], $fields, $quote_style, $charset);
} }
@@ -90,7 +91,7 @@ class PhpHelper
if (is_array($subject)) { if (is_array($subject)) {
$fields = self::arrayTrim(explode(' ', $fields)); $fields = self::arrayTrim(explode(' ', $fields));
foreach ($subject as $field => $value) { foreach ($subject as $field => $value) {
if ((! is_array($fields) || empty($fields)) || (is_array($fields) && ! empty($fields) && in_array($field, $fields))) { if ((!is_array($fields) || empty($fields)) || (is_array($fields) && !empty($fields) && in_array($field, $fields))) {
$subject[$field] = str_replace($search, $replace, $subject[$field]); $subject[$field] = str_replace($search, $replace, $subject[$field]);
} }
} }
@@ -108,18 +109,17 @@ class PhpHelper
* @param string $errstr * @param string $errstr
* @param string $errfile * @param string $errfile
* @param int $errline * @param int $errline
* @param array $errcontext
* *
* @return void|boolean * @return void|boolean
*/ */
public static function phpErrHandler($errno, $errstr, $errfile, $errline, $errcontext = array()) public static function phpErrHandler($errno, $errstr, $errfile, $errline)
{ {
if (! (error_reporting() & $errno)) { if (!(error_reporting() & $errno)) {
// This error code is not included in error_reporting // This error code is not included in error_reporting
return; return;
} }
if (! isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) { if (!isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) {
// prevent possible file-path-disclosure // prevent possible file-path-disclosure
$errfile = str_replace(\Froxlor\Froxlor::getInstallDir(), "", $errfile); $errfile = str_replace(\Froxlor\Froxlor::getInstallDir(), "", $errfile);
// build alert // build alert
@@ -129,7 +129,7 @@ class PhpHelper
} elseif ($errno = E_WARNING) { } elseif ($errno = E_WARNING) {
$type = 'warning'; $type = 'warning';
} }
$err_display = '<div class="alert alert-'.$type.' my-1" role="alert">'; $err_display = '<div class="alert alert-' . $type . ' my-1" role="alert">';
$err_display .= '<strong>#' . $errno . ' ' . $errstr . '</strong><br>'; $err_display .= '<strong>#' . $errno . ' ' . $errstr . '</strong><br>';
$err_display .= $errfile . ':' . $errline; $err_display .= $errfile . ':' . $errline;
// later depended on whether to show or now // later depended on whether to show or now
@@ -154,23 +154,19 @@ class PhpHelper
public static function phpExceptionHandler(\Throwable $exception) public static function phpExceptionHandler(\Throwable $exception)
{ {
if (! isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) { if (!isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) {
$err_display = '<div class="alert alert-danger my-1" role="alert">'; // show
$err_display .= '<strong>#' . $exception->getCode() . ' ' . $exception->getMessage() . '</strong><br>'; \Froxlor\UI\Panel\UI::initTwig(true);
// later depended on whether to show or now \Froxlor\UI\Panel\UI::Twig()->addGlobal('install_mode', '1');
$err_display .= '<br><p><pre>'; \Froxlor\UI\Panel\UI::TwigBuffer('misc/alert_nosession.html.twig', [
$debug = $exception->getTrace(); 'page_title' => 'Uncaught exception',
foreach ($debug as $dline) { 'heading' => 'Uncaught exception',
$err_display .= $dline['function'] . '() called at [' . str_replace(\Froxlor\Froxlor::getInstallDir(), '', $dline['file']) . ':' . $dline['line'] . ']<br>'; 'type' => 'danger',
} 'alert_msg' => $exception->getCode() . ' ' . $exception->getMessage(),
$err_display .= '</pre></p>'; 'alert_info' => $exception->getTraceAsString()
// end later ]);
$err_display .= '</div>'; echo \Froxlor\UI\Panel\UI::TwigOutputBuffer();
// check for more existing errors die();
$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;
} }
} }
@@ -194,7 +190,7 @@ class PhpHelper
// we assume that this is a list of // we assume that this is a list of
// setting-groups to be selected // setting-groups to be selected
$selection = null; $selection = null;
for ($x = 0; $x < $numargs; $x ++) { for ($x = 0; $x < $numargs; $x++) {
$arg = func_get_arg($x); $arg = func_get_arg($x);
if (is_array($arg) && isset($arg[0])) { if (is_array($arg) && isset($arg[0])) {
$selection = $arg; $selection = $arg;
@@ -211,7 +207,7 @@ class PhpHelper
if (is_dir($data_dirname)) { if (is_dir($data_dirname)) {
$data_dirhandle = opendir($data_dirname); $data_dirhandle = opendir($data_dirname);
while (false !== ($data_filename = readdir($data_dirhandle))) { while (false !== ($data_filename = readdir($data_dirhandle))) {
if ($data_filename != '.' && $data_filename != '..' && $data_filename != '' && substr($data_filename, - 4) == '.php') { if ($data_filename != '.' && $data_filename != '..' && $data_filename != '' && substr($data_filename, -4) == '.php') {
$data_files[] = $data_dirname . $data_filename; $data_files[] = $data_dirname . $data_filename;
} }
} }
@@ -367,7 +363,7 @@ class PhpHelper
$i = 0; $i = 0;
while ($size >= $sys['size'] && $i < $depth) { while ($size >= $sys['size'] && $i < $depth) {
$size /= $sys['size']; $size /= $sys['size'];
$i ++; $i++;
} }
return sprintf($retstring, $size, $sys['prefix'][$i]); return sprintf($retstring, $size, $sys['prefix'][$i]);
@@ -390,7 +386,7 @@ class PhpHelper
$matches = array(); $matches = array();
if (count($vars) > 0 && preg_match_all($pattern, $text, $matches)) { if (count($vars) > 0 && preg_match_all($pattern, $text, $matches)) {
for ($i = 0; $i < count($matches[1]); $i ++) { for ($i = 0; $i < count($matches[1]); $i++) {
$current = $matches[1][$i]; $current = $matches[1][$i];
if (isset($vars[$current])) { if (isset($vars[$current])) {
@@ -444,7 +440,7 @@ class PhpHelper
'ssl_default_vhostconf_domain', 'ssl_default_vhostconf_domain',
'filecontent' 'filecontent'
]; ];
if (isset($global) && ! empty($global)) { if (isset($global) && !empty($global)) {
$tmp = $global; $tmp = $global;
foreach ($tmp as $index => $value) { foreach ($tmp as $index => $value) {
if (!in_array($index, $ignored_fields)) { if (!in_array($index, $ignored_fields)) {

View File

@@ -193,6 +193,11 @@ class Cronjob
} }
} }
/**
* returns an array of all cronjobs and when they last were executed
*
* @return array
*/
public static function getCronjobsLastRun() public static function getCronjobsLastRun()
{ {
global $lng; global $lng;
@@ -200,20 +205,13 @@ class Cronjob
$query = "SELECT `lastrun`, `desc_lng_key` FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `isactive` = '1' ORDER BY `cronfile` ASC"; $query = "SELECT `lastrun`, `desc_lng_key` FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `isactive` = '1' ORDER BY `cronfile` ASC";
$result = Database::query($query); $result = Database::query($query);
$cronjobs_last_run = ''; $cronjobs_last_run = [];
while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result->fetch(\PDO::FETCH_ASSOC)) {
$cronjobs_last_run[] = [
$lastrun = $lng['cronjobs']['notyetrun']; 'title' => $lng['crondesc'][$row['desc_lng_key']],
if ($row['lastrun'] > 0) { 'lastrun' => $row['lastrun']
$lastrun = date('d.m.Y H:i:s', $row['lastrun']); ];
} }
$text = $lng['crondesc'][$row['desc_lng_key']];
$value = $lastrun;
eval("\$cronjobs_last_run .= \"" . \Froxlor\UI\Template::getTemplate("index/overview_item") . "\";");
}
return $cronjobs_last_run; return $cronjobs_last_run;
} }
@@ -231,6 +229,11 @@ class Cronjob
)); ));
} }
/**
* returns an array of tasks that are queued to be run by the cronjob
*
* @return array
*/
public static function getOutstandingTasks() public static function getOutstandingTasks()
{ {
global $lng; global $lng;
@@ -238,8 +241,7 @@ class Cronjob
$query = "SELECT * FROM `" . TABLE_PANEL_TASKS . "` ORDER BY `type` ASC"; $query = "SELECT * FROM `" . TABLE_PANEL_TASKS . "` ORDER BY `type` ASC";
$result = Database::query($query); $result = Database::query($query);
$value = '<ul class="cronjobtask">'; $tasks = [];
$tasks = '';
while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { while ($row = $result->fetch(\PDO::FETCH_ASSOC)) {
if ($row['data'] != '') { if ($row['data'] != '') {
@@ -249,41 +251,35 @@ class Cronjob
$task_id = $row['type']; $task_id = $row['type'];
if (\Froxlor\Cron\TaskId::isValid($task_id)) { if (\Froxlor\Cron\TaskId::isValid($task_id)) {
$task_constname = \Froxlor\Cron\TaskId::convertToConstant($task_id); $task_constname = \Froxlor\Cron\TaskId::convertToConstant($task_id);
$task_desc = isset($lng['tasks'][$task_constname]) ? $lng['tasks'][$task_constname] : $task_constname; $task = [
'desc' => isset($lng['tasks'][$task_constname]) ? $lng['tasks'][$task_constname] : $task_constname
];
if (is_array($row['data'])) { if (is_array($row['data'])) {
// task includes loginname // task includes loginname
if (isset($row['data']['loginname'])) { if (isset($row['data']['loginname'])) {
$loginname = $row['data']['loginname']; $loginname = $row['data']['loginname'];
$task_desc = str_replace('%loginname%', $loginname, $task_desc); $task['desc'] = str_replace('%loginname%', $loginname, $task['desc']);
} }
// task includes domain data // task includes domain data
if (isset($row['data']['domain'])) { if (isset($row['data']['domain'])) {
$domain = $row['data']['domain']; $domain = $row['data']['domain'];
$task_desc = str_replace('%domain%', $domain, $task_desc); $task['desc'] = str_replace('%domain%', $domain, $task['desc']);
} }
} }
} else { } else {
// unknown // unknown
$task_desc = "ERROR: Unknown task type '" . $row['type'] . "'"; $task = ['desc' => "ERROR: Unknown task type '" . $row['type'] . "'"];
} }
if ($task_desc != '') { $tasks[] = $task;
$tasks .= '<li>' . $task_desc . '</li>';
}
} }
if (trim($tasks) == '') { if (empty($tasks)) {
$value .= '<li>' . $lng['tasks']['noneoutstanding'] . '</li>'; $tasks = [['desc' => $lng['tasks']['noneoutstanding']]];
} else {
$value .= $tasks;
} }
$value .= '</ul>';
$text = $lng['tasks']['outstanding_tasks']; $text = $lng['tasks']['outstanding_tasks'];
eval("\$outstanding_tasks = \"" . \Froxlor\UI\Template::getTemplate("index/overview_item") . "\";"); return $tasks;
return $outstanding_tasks;
} }
/** /**

View File

@@ -8,11 +8,19 @@
<meta name="googlebot" content="nosnippet"/> <meta name="googlebot" content="nosnippet"/>
<!-- CSS --> <!-- CSS -->
{% if theme_css is empty %}
<link href="templates/Froxlor/assets/css/main.css" rel="stylesheet" type="text/css" />
{% else %}
{{ theme_css|raw }} {{ theme_css|raw }}
{% endif %}
{% block custom_css %}{% endblock %} {% block custom_css %}{% endblock %}
<!-- Scripts --> <!-- Scripts -->
{% if theme_js is empty %}
<script type="text/javascript" src="templates/Froxlor/assets/js/main.js"></script>
{% else %}
{{ theme_js|raw }} {{ theme_js|raw }}
{% endif %}
{% block custom_js %}{% endblock %} {% block custom_js %}{% endblock %}
<title>Froxlor <title>Froxlor
{% if page_title %} {% if page_title %}

View File

@@ -110,6 +110,31 @@
</div> </div>
</div> </div>
</div> </div>
{% if userinfo.adminsession == 1 %}
{# froxlor-details #}
<div class="card mb-3">
<div class="card-header">
<i class="fa-solid fa-wrench"></i>
{{ lng('admin.froxlordetails') }}
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">{{ lng('tasks.outstanding_tasks') }}</div>
{% for task in outstanding_tasks %}
<i class="fa-regular fa-clock"></i> {{ task.desc }}<br>
{% endfor %}
</div>
</li>
{% for cronrun in cron_last_runs %}
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">{{ cronrun.title }}</div>
<span class="badge bg-primary">{% if cronrun.lastrun > 0 %}{{ cronrun.lastrun|date('d.m.Y H:i') }}{% else %}{{ lng('cronjobs.notyetrun') }}{% endif %}</span>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div> </div>
{% if userinfo.adminsession == 1 %} {% if userinfo.adminsession == 1 %}
<div <div