= 70200 && isset($config['devel']) && $config['devel']) { Tracy\Debugger::enable(Tracy\Debugger::Development); } if ((defined('OBS_DEBUG') && OBS_DEBUG) || !empty($_SERVER['REMOTE_ADDR']) || (PHP_SAPI === 'cli' && is_array($options['d']))) { // this include called before definitions :( if (function_exists('token_get_all') && !class_exists('ref')) { // Class ref loaded by class_exist call include_once($config['install_dir'] . "/libs/ref.inc.php"); } } // Set tracy theme (here for clarity. theme might not be correct if there's a bug in the load *after* a theme change) // Enable dark mode for Tracy dump() if (isset($_SESSION['mode']) && $_SESSION['mode'] === 'dark' && class_exists('Tracy\Debugger', FALSE)) { Tracy\Debugger::$dumpTheme = 'dark'; } // Fallback debugging functions if (!function_exists('r')) { function r($var) { if (function_exists('dump')) { dump($var); } else { print_r($var); } } } if (!function_exists('rt')) { function rt($var) { if (function_exists('dump')) { dump($var); } else { print_r($var); } } } if (!function_exists('dump')) { function dump($var) { if (PHP_SAPI === 'cli' && class_exists('ref', FALSE)) { rt($var); } elseif (class_exists('ref', FALSE)) { r($var); } else { print_r($var); } } } if (!function_exists('bdump')) { function bdump($var) { if (PHP_SAPI === 'cli' && class_exists('ref', FALSE)) { rt($var); } else { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); $file = $backtrace[0]['file'] ?? 'unknown'; $line = $backtrace[0]['line'] ?? 'unknown'; $caller_info = "$file : $line"; if (!isset($GLOBALS['dump'])) { $GLOBALS['dump'] = []; } $GLOBALS['dump'][] = [ 'data' => $var, 'caller_info' => $caller_info, ]; } } } /** * Observium's variable debugging. Chooses nice output depending upon web or cli * * @param $vars * @param $trace * * @return void */ function print_vars($vars, $trace = NULL) { if (PHP_SAPI === 'cli' || (defined('OBS_CLI') && OBS_CLI)) { // In cli, still prefer ref if (class_exists('ref', FALSE)) { try { ref::config('shortcutFunc', [ 'print_vars', 'print_debug_vars' ]); ref::config('showUrls', FALSE); if (defined('OBS_DEBUG') && OBS_DEBUG > 0) { if (is_null($trace)) { $backtrace = defined('DEBUG_BACKTRACE_IGNORE_ARGS') ? debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) : debug_backtrace(); } else { $backtrace = $trace; } ref::config('Backtrace', $backtrace); // pass original backtrace ref::config('showStringMatches', FALSE); } else { ref::config('showBacktrace', FALSE); ref::config('showResourceInfo', FALSE); ref::config('showStringMatches', FALSE); ref::config('showMethods', FALSE); } rt($vars); } catch (Exception $e) { print_r($vars); echo PHP_EOL; } } else { print_r($vars); echo PHP_EOL; } } elseif (class_exists('ref')) { // in Web use old ref class, when Tracy not possible to use try { ref::config('shortcutFunc', [ 'print_vars', 'print_debug_vars' ]); ref::config('showUrls', FALSE); if (defined('OBS_DEBUG') && OBS_DEBUG > 0) { if (is_null($trace)) { $backtrace = defined('DEBUG_BACKTRACE_IGNORE_ARGS') ? debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) : debug_backtrace(); } else { $backtrace = $trace; } ref::config('Backtrace', $backtrace); // pass original backtrace } else { ref::config('showBacktrace', FALSE); ref::config('showResourceInfo', FALSE); ref::config('showStringMatches', FALSE); ref::config('showMethods', FALSE); } //ref::config('stylePath', $GLOBALS['config']['html_dir'] . '/css/ref.css'); //ref::config('scriptPath', $GLOBALS['config']['html_dir'] . '/js/ref.js'); r($vars); } catch (Exception $e) { echo '
' . $output . '
'; } echo $output; } function whimsical_error_handler($errno, $errstr, $errfile, $errline) { // Handle only fatal errors if (!($errno & (E_ERROR | E_USER_ERROR))) { return FALSE; } // Call the display_error_page function display_error_page($errno, $errstr, $errfile, $errline, debug_backtrace()); exit(); } function whimsical_shutdown_handler() { $error = error_get_last(); if ($error !== NULL && $error['type'] & (E_ERROR | E_USER_ERROR | E_COMPILE_ERROR | E_PARSE)) { display_error_page($error['type'], $error['message'], $error['file'], $error['line'], []); exit(); } } function get_context_lines($file, $line_number, $context = 5) { $lines = file($file); $start = max(0, $line_number - $context - 1); $length = $context * 2 + 1; $context_lines = array_slice($lines, $start, $length); // Add tags around the line number being requested $context_lines[$line_number - $start - 1] = '' . $context_lines[$line_number - $start - 1] . ''; return [ 'start' => $start + 1, 'lines' => $context_lines ]; } function display_error_page($errno, $errstr, $errfile, $errline, $backtrace) { // Log the error //error_log("Custom error: [$errno] $errstr in $errfile on line $errline"); if (!defined('OBS_MIN_PHP_VERSION')) { define('OBS_MIN_PHP_VERSION', '7.2.24'); } // If the error is an uncaught exception, get the correct backtrace if (preg_match('/^Uncaught Error: (.+) in (.+):(\d+)$/m', $errstr, $matches)) { $backtrace = (new ErrorException($matches[1], 0, $errno, $matches[2], $matches[3])) -> getTrace(); $errstr = $matches[1]; } array_unshift($backtrace, ['file' => $errfile, 'line' => $errline]); // Remove the error handler and shutdown handler from the stack trace //$backtrace = array_filter($backtrace, function ($trace) { // return !in_array($trace['function'], ['whimsical_error_handler', 'whimsical_shutdown_handler', 'display_error_page']); //}); if (PHP_SAPI === "cli") { // Define color codes $color_red = "\033[31m"; $color_yellow = "\033[33m"; $color_green = "\033[32m"; $color_cyan = "\033[36m"; $color_reset = "\033[0m"; // Output text-only error for CLI echo " ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡶⠋⠁⠙⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⣠⡶⠛⠛⠲⣤⣀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⣠⠄⣠⣾⣡⠀⠀⠀⠀⠸⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⢰⡏⠀⠀⠀⠀⠈⣿⣷⣤⡐⣄⣽⡾⠧⠤⠤⣤⣤⣾⣿⣾⣿⣯⣀⡀⠀⠀⠀⢠⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⢷⡀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣯⣤⣤⡀⣠⣈⣹⣽⣿⣿⣿⣿⣷⣦⣄⠀⢀⡾⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠈⠻⣆⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⣠⠞⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠈⢳⣆⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⣾⣷⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⣘⣿⣿⣿⣿⣿⣟⣿⣿⣿⣿⣿⣿⣿⣿⢡{$color_red}⡼{$color_reset}⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⡏{$color_red}⣯⡇{$color_reset}⣿⣿⣿⡏⣿⣿⣿{$color_red}⣜⣛{$color_reset}⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣭⣾⣿⣿⣿⣇⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀⠘⢷⣄⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⢠⣿⣿⡏⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⢿⣿⣿⡿⠁⠀⠀⠀⠸⣿⣷⡀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⢸⣿⣿⡇⠈⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠻⣿⣿⡟⢠⣿⣿⡟⠁⠀⠀⠀⠀⠙⣻⣿⣿⣆⠀⠀⠀⠀⠀ ⠀⠀⠀⠈⣿⣿⣷⡈⠛⠿⣿⣿⡆⠻⢿⣿⣽⣿⣯⣿⠿⠃⠀⠻⠛⣰⣿⣿⠏⠀⠀⠀⠀⢀⣙⣿⣿⣿⣿⣿⣧⡀⠀⠀⠀ ⠀⠀⠀⠀⢿⠈⠙⠻⠷⠤⠄⢉⡁⠀⠀⠙⢉⣵⣌⠀⠀⠀⣀⠄⠘⠛⠋⠁⢀⣀⣤⣤⣭⣭⣽⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀ ⠀⠀⠀⢀⣿⡄⠀⠀⠀⠀⠀⠀⠉⠓⢦⣄⡉⠉⢉⣩⠶⠋⠁⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀ ⠀⠀⠀⣼⣿⣿⣷⣶⣶⣆⣀⡀⠀⠀⠀⠀⠉⠉⠉⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀ ⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣥⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣦⣾⣿⣿⣿⣿⣿⣿⡿⠿⠿⡟⠿⣿⣟⡿⢿⡛⠀⣘⣿⣿⡆ ⠀⠀⠀⢿⣿⣿⠿⠿⠿⠿⢿⣿⣿⣷⣿⡆⠀⠀⣶⣶⣾⡿⠛⠛⠛⠛⠻⣿⣿⣿⡟⠉⠀⠀⠀⠈⠁⠁⢀⢀⠲⣬⣿⣿⡇ ⠀⠀⠀⠘⡏⠳⣤⡄⠀⡄⠀⠀⠈⠙⢿⣧⠀⢀⣿⣿⠏⠀⠀⠀⠀⢀⣠⣿⣿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠈⣯⣷⣿⣿⣿⡇ ⠀⠀⠀⠀⢿⠀⠀⠉⠳⣇⠀⠀⠀⠀⠀⢻⠀⢸⣿⣿⣆⢠⠀⡆⣰⡿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡾⣿⣿⣿⣿⣿⡇ ⠀⠀⠀⠀⠘⣧⠀⠀⠀⠹⣷⣤⣄⠀⡈⣾⡆⢸⡿⠋⠿⠾⠴⠷⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⠞⠉⣶⣾⣿⣿⣿⣿⠀ ⠀⠀⠀⠀⠀⠈⠳⣄⠀⠀⠀⠉⠻⣿⣿⣿⣇⠸⡷⠀⠀⠀⢀⣠⢄⣠⣶⣤⣤⣤⡤⠤⠖⠛⠉⠀⠠⣤⣼⣿⣿⣿⣿⡏⠀ ⠀⠀⠀⠀⠀⠀⠀⠉⢻⣷⠶⠒⠀⠀⠁⠈⢿⡄⣷⣆⣤⣶⡿⠛⠛⠛⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⣿⠇⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠘⣏⠀⠀⠀⠀⠀⠀⠘⣧⣿⣿⡿⢋⡤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⣾⣿⣿⣿⣿⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⡄⠀⠀⠀⠀⠀⠀⢸⣿⣿⣶⣫⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⢦⣵⣿⣿⣿⣿⠇⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣆⠀⠀⠀⠀⠀⠀⣿⣿⣿⠇⠀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠳⠦⣴⣿⣶⣿⣿⣿⣿⡿⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⢷⣄⠀⠀⠀⠀⢹⣿⣿⣾⣿⣋⣤⡄⠀⠀⠀⠀⠀⠀⠀⠠⣈⠻⣿⣿⣿⣿⣿⡇⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠛⣦⣤⣤⣾⣿⣿⣿⣿⣿⣯⡴⠂⣀⡀⠀⡀⡀⡀⢠⣬⣻⣿⣿⣿⣿⡿⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣠⡴⠊⠉⠀⠈⢹⠿⣿⣿⣿⣿⣿⣷⣾⣿⠾⡿⡿⠿⣷⣦⣿⣿⣿⣿⣿⡟⠁⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠛⠷⠦⠤⠤⠴⠶⠶⠶⠶⠚⠉⠀⠀⠈⣉⣩⠽⠟⠋⠁⠀⠀⣁⣠⠿⠛⠋⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n"; /* echo "\n{$color_rd}"; echo " ___ _ \n"; echo " / _ \ ___ _ __ ___| | \n"; echo " | | | |/ _ \| '_ \/ __| | \n"; echo " | |_| | (_) | |_) \__ \_| \n"; echo " \___/ \___/| .__/|___(_) \n"; echo " |_| {$color_reset}\n"; echo "\n"; */ echo "{$color_red}Oops! Something went wrong! You may want to report this to the Observium developers.{$color_reset}\n"; echo "\n"; echo "{$color_green}$errstr in $errfile:$errline{$color_reset}\n"; // Check and print a warning if the current PHP version is below the minimum required if (version_compare(PHP_VERSION, OBS_MIN_PHP_VERSION, '<')) { echo "\n{$color_red}Warning: Your PHP version (" . PHP_VERSION . ") is below the minimum required version (" . OBS_MIN_PHP_VERSION . ").\nPlease upgrade your PHP version before reporting issues.{$color_reset}\n"; } echo "\n{$color_yellow}Stack trace:{$color_reset}\n"; foreach ($backtrace as $i => $trace) { $file = $trace['file'] ?? '(unknown file)'; $line = $trace['line'] ?? '(unknown line)'; $function = $trace['function'] ?? '(unknown function)'; echo "\n{$color_cyan}#$i: {$function} called at [{$file}:{$line}]{$color_reset}\n"; if (file_exists($file)) { $context_lines = get_context_lines($file, $line); foreach ($context_lines['lines'] as $j => $context_line) { $context_line = trim($context_line); $line_number = $context_lines['start'] + $j; if ($line_number == $line) { echo "{$color_red}{$line_number}: {$context_line}{$color_reset}\n"; } else { echo "{$color_reset}{$line_number}: {$context_line}{$color_reset}\n"; } } } } echo "\n"; exit(); } if (is_api() && function_exists('api_json_halt')) { // Use json error in API instead html page $error = [ 'error' => 'Oops! Something went wrong! You may want to report this to the Observium developers.' ]; // Check and print a warning if the current PHP version is below the minimum required if (version_compare(PHP_VERSION, OBS_MIN_PHP_VERSION, '<')) { $error['php_minimum_required'] = "Your PHP version (" . PHP_VERSION . ") is below the minimum required version (" . OBS_MIN_PHP_VERSION . "). Please upgrade your PHP version before reporting issues."; } $error['trace'] = []; //echo "\n{$color_yellow}Stack trace:{$color_reset}\n"; foreach ($backtrace as $i => $trace) { $file = $trace['file'] ?? '(unknown file)'; $line = $trace['line'] ?? '(unknown line)'; $function = $trace['function'] ?? '(unknown function)'; $trace = "#$i: {$function} called at [{$file}:{$line}]\n"; if (file_exists($file)) { $context_lines = get_context_lines($file, $line); foreach ($context_lines['lines'] as $j => $context_line) { $context_line = trim($context_line); $line_number = $context_lines['start'] + $j; if ($line_number == $line) { $trace .= "{$line_number}: {$context_line}\n"; } else { $trace .= "{$line_number}: {$context_line}\n"; } } } $error['trace'][$i] = $trace; } api_json_halt(500, "$errstr in $errfile:$errline", $error); } // Display the whimsical error page http_response_code(500); ?>Warning: Your PHP version (" . PHP_VERSION . ") is below the minimum required version (" . OBS_MIN_PHP_VERSION . "). Please upgrade your PHP version before reporting issues.
"; echo "
= htmlspecialchars($context_lines['start'] + $j) ?>: = htmlspecialchars($context_line) ?>
= htmlspecialchars($context_lines['start'] + $j) ?>: = htmlspecialchars($context_line) ?>