-
Jonathan Swaelens authored
Add more logging in trigger error Signed-off-by:
Jonathan Swaelens <jonathan.swaelens@fusiondirectory.org>
Verified260c9e0d
<?php
/*
This code is part of FusionDirectory (http://www.fusiondirectory.org/)
Copyright (C) 2003-2010 Cajus Pollmeier
Copyright (C) 2011-2020 FusionDirectory
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*!
* \file php_setup.inc
* Source code for php_setup
*/
require_once('variables.inc');
require_once('class_URL.inc');
/*!
* \brief Escape string for HTML output
*/
function htmlescape (string $str): string
{
return htmlspecialchars($str, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
/*!
* \brief Unescape string for HTML output, reverse of htmlescape
*/
function htmlunescape (string $html): string
{
return html_entity_decode($html, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
function html_trace ($errstr = "")
{
static $hideArgs = [
'LDAP/init' => [3],
'userinfo/loginUser' => [1],
'change_password' => [1],
'cred_decrypt' => [0, 1],
'LDAP/__construct' => [1],
];
if (!function_exists('debug_backtrace')) {
return ['', ''];
}
$trace = array_slice(debug_backtrace(), 1);
$loc = '';
if (isset($trace[0]['file'])) {
$loc = ' - ' . _('File') . ': ' . $trace[0]['file'];
if (isset($trace[0]['line'])) {
$loc .= ' (' . _('Line') . ' ' . $trace[0]['line'] . ')';
}
}
$return_html = '<table width="100%" style="background-color:#402005;color:white;border:2px solid red;border-spacing:0;border-collapse:collapse;">' .
'<tr><td colspan="3">' .
'<h1 style="color:white">' . htmlescape(_('PHP error') . ' "' . $errstr . '"' . $loc) . '</h1>' .
'</td></tr>';
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
$return_mailto = rawurlencode('=== Trace ===');
/* Generate trace history */
for ($index = 1, $c = count($trace); $index < $c; $index++) {
$ct = $trace[$index];
$loc = '';
$func = '';
if (isset($ct['class'])) {
$loc .= _('class') . ' ' . $ct['class'];
$func .= $ct['class'];
if (isset($ct['function'])) {
$loc .= ' / ';
$func .= '/';
}
}
if (isset($ct['function'])) {
$loc .= _('function') . ' ' . $ct['function'];
$func .= $ct['function'];
}
if (isset($ct['type'])) {
switch ($ct['type']) {
case '::':
$type = _('static');
break;
case '->':
$type = _('method');
break;
default:
$type = 'unknown';
break;
}
} else {
$type = '-';
}
$args = '';
if (isset($ct['args'])) {
if (isset($hideArgs[$func])) {
$hideArgsIndexes = $hideArgs[$func];
} else {
$hideArgsIndexes = [];
}
$f = function ($index, $arg) use (&$f, $hideArgsIndexes) {
static $i = 0;
if (($i == 0) && in_array($index, $hideArgsIndexes)) {
return '***';
}
if ($i > 4) {
return '…';
}
if (is_object($arg)) {
return 'CLASS: ' . get_class($arg);
} elseif (is_array($arg)) { /* Avoid converting array to string errors */
$i++;
$ret = 'array(' . implode(',', array_map($f, array_keys($arg), $arg)) . ')';
$i--;
return $ret;
} else {
if (strlen("$arg") > 512) {
$arg = substr("$arg", 0, 512) . "…";
}
return '"' . htmlescape("$arg") . '"';
}
};
$args = implode(',', array_map($f, array_keys($ct['args']), $ct['args']));
}
if (empty($args)) {
$args = '-';
}
if (isset($ct['file'])) {
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
$file = $ct['file'];
} else {
$file = '';
}
if (isset($ct['line'])) {
$line = $ct['line'];
} else {
$line = '';
}
$color = ($index & 1) ? '#404040' : '606060';
$return_html .= "<tr style='background-color:$color'><td style='padding-left:20px' width=\"30%\">" . htmlescape(_("Trace") . "[$index]: $loc") . '</td>';
$return_html .= "<td>" . htmlescape(_("File") . ": $file (" . _('Line') . " $line)") . '</td><td width="10%">' . htmlescape(_("Type") . ": $type") . '</td></tr>';
$return_html .= "<tr style='background-color:$color'><td colspan=3 style='padding-left:20px;'>" . htmlescape(_("Arguments") . ": $args") . '</td></tr>';
/* Add trace part to mailto body */
$return_mailto .= rawurlencode(
"\nTrace[" . $index . "]:" . $loc .
"\nFile : " . $file .
"\nLine : " . $line .
"\nType : " . $type .
"\n " . $args .
"\n");
}
$return_html .= "</table>";
$return_mailto .= rawurlencode("=== /Trace ===");
return [$return_html, $return_mailto];
}
/*!
* \brief Raise an error
*
* \param string $errno
*
* \param string $errstr The error string
*
* \param string $errfile The error filename
*
* \param string $errline The error line
*/
function gosaRaiseError ($errno, $errstr, $errfile, $errline)
{
global $error_collector, $config, $error_collector_mailto;
// To avoid recursion - restore original error handler.
restore_error_handler();
/* Return if error reporting is set to zero */
if (error_reporting() == 0) {
set_error_handler('gosaRaiseError', E_WARNING | E_NOTICE | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_STRICT);
return FALSE;
}
/* Workaround for buggy imap_open error outputs */
if (preg_match('/imap_open/', $errstr)) {
set_error_handler('gosaRaiseError', E_WARNING | E_NOTICE | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_STRICT);
return;
}
/* Hide ldap size limit messages */
if (preg_match('/ldap_error/', $errstr) && preg_match('/sizelimit/', $errstr)) {
set_error_handler('gosaRaiseError', E_WARNING | E_NOTICE | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_STRICT);
return;
}
/* Send all errors to logging class, except "Ldap : No such object" messages*/
if (class_exists('logging') && !preg_match('/No such object/', $errstr)) {
logging::log('error', 'php', $errfile, [], 'Type:' . $errno . ', Message:' . $errstr . ', File:' . $errfile . ', Line: ' . $errline);
}
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
/* Error messages are hidden in FusionDirectory, so we only send them to the logging class and abort here */
if (isset($config->data) && $config->get_cfg_value('displayerrors') != 'TRUE') {
set_error_handler('gosaRaiseError', E_WARNING | E_NOTICE | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_STRICT);
return;
}
/* Create header as needed */
if ($error_collector == "") {
$error_collector = '
<div class="error">
<table width="100%">
<tr>
<td>
<img src="geticon.php?context=status&icon=dialog-warning&size=16" alt="" class="center"/>
<strong style="font-size:14px">' .
htmlescape(_('Generating this page caused the PHP interpreter to raise some errors!')) . '
</strong>
</td>
<td align="right">
<button onClick="$(\'errorbox\').toggle();">' .
htmlescape(_('Toggle information')) . '
</button>
</td>
</tr>
</table>
</div>
<div id="errorbox" style="position:absolute; z-index:150; display: none;">';
}
list($html_trace, $mailto_trace) = html_trace($errstr);
$error_collector .= $html_trace;
/* Flush in case of fatal errors */
if (preg_match('/^fatal/i', $errstr) || (PHP_ERROR_FATAL == 'TRUE')) {
trigger_error("Source error: " . $errstr . " in " . $errfile . " on line " . $errline);
session::destroy('Fatal error');
if (PHP_ERROR_FATAL == 'TRUE') {
$error_collector = str_replace('display: none;', '', $error_collector);
}
echo $error_collector . "</div>";
flush();
exit;
}
set_error_handler('gosaRaiseError', E_WARNING | E_NOTICE | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_STRICT);
}
/*!
* \brief Catches throwables that no one catched
*
* \param Throwable $throwable
*/
function fusiondirectoryExceptionHandler (Throwable $throwable)
{
try {
logging::log('error', 'fatal', '', [], 'Uncaught ' . get_class($throwable) . ': ' . $throwable->getMessage());
} catch (Throwable $t) {
/* Ignore exceptions/errors here */
}
try {
if ($throwable instanceof FatalError) {
$throwable->display();
} else {
$error = new FatalError(htmlescape(sprintf(_('Uncaught %s: %s'), get_class($throwable), $throwable->getMessage())), 0, $throwable);
$error->display();
}
} catch (Throwable $t) {
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
/* Minimal display if exceptions happens when building the pretty one */
echo 'Uncaught ' . get_class($throwable) . ': ' . $throwable->getMessage();
}
exit(255);
}
/*!
* \brief Dummy error handler
*/
function dummy_error_handler ()
{
}
/* Bail out for incompatible/old PHP versions */
if (!version_compare(phpversion(), PHP_MIN_VERSION, ">=")) {
echo "PHP version needs to be " . PHP_MIN_VERSION . " or above to run FusionDirectory. Aborted.";
exit();
}
/* Set timezone */
date_default_timezone_set("GMT");
/* Get base dir for reference */
$BASE_DIR = dirname(dirname(__FILE__));
$ROOT_DIR = $BASE_DIR . "/html";
error_reporting(E_ALL | E_STRICT);
/* Register error handler */
$error_collector = "";
$error_collector_mailto = "";
set_error_handler('gosaRaiseError', E_WARNING | E_NOTICE | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_STRICT);
set_exception_handler('fusiondirectoryExceptionHandler');
$variables_order = 'ES';
ini_set('track_vars', '1');
ini_set('display_errors', '1');
ini_set('report_memleaks', '1');
ini_set('include_path', ".:$BASE_DIR/include:" . PHP_DIR . ':' . PEAR_DIR);
/* Do smarty setup */
require(SMARTY);
$smarty = new Smarty;
$smarty->setTemplateDir($BASE_DIR . '/ihtml/');
$smarty->caching = Smarty::CACHING_OFF;
$smarty->assign('css_files', []);
$smarty->assign('js_files', []);
$smarty->registerPlugin('modifier', 'base64_encode', 'base64_encode');
$smarty->php_handling = Smarty::PHP_REMOVE;
/* Check for SSL connection */
$ssl = '';
if (!URL::sslOn()) {
$ssl = URL::getSslUrl();
}