<?php /**************************************************************************** * LOG AND FATAL ERRORS ****************************************************************************/ class l { /** This variable should contain the name of the function to call when * handling fatal errors. */ private static $fatalErrorCallback = "l::defaultFatalError"; /** This array lists the errors the engine can encounter and handle * through the fatalError() function. */ private static $engineErrors = array( 0 => "Could not open configuration file", 1 => "Could not connect to database", 2 => "Failed to set up tracking data", 3 => "Failed to set up tracking data", 4 => "Failed to set up tracking data", 5 => "Failed to set up tracking data", 6 => 'Invalid request', 7 => 'Invalid request', 8 => 'Page not found', 9 => 'Page not found', 10 => 'Internal error', 11 => 'Internal error', 12 => "Failed to set up session data", 13 => "Failed to set up session data", 14 => "Failed to set up session data", 15 => "Failed to set up session data", 16 => 'Internal error', 17 => 'Internal error', 18 => "Internal error", 19 => 'Internal error', 20 => 'Internal error', 21 => 'Internal error', 22 => 'Internal error', 23 => 'Internal error', 24 => 'Internal error', 25 => 'Internal error', 26 => 'Invalid extension', 27 => 'Unhandled extension', 28 => 'Internal error', 29 => 'Internal error', 30 => 'Resource not found', 31 => 'Unhandler extension', ); /** This variable indicates whether the logging system has * been initialised. */ private static $initialised = false; /** This variable contains the prefix to use when writing * to syslog. */ private static $syslogPrefix = "lwEngine"; /** This variable defines a text that is used as a prefix * when logging strings. */ private static $prefix = ""; /** This variable prevents multiple "deprecated" entries from * being logged. */ private static $deprecatedLogged = false; /** This variable prevents multiple "FIXME" entries from * being logged. */ private static $fixmeLogged = false; /** This function is the default fatal error display function. */ private static function defaultFatalError($errno, $error, $info) { ob_start(); ?> <html> <head> <title>Legacy Worlds</title> </head> <body> <p> <b>The LegacyWorlds game engine encountered a fatal error:</b><br/> <?=$error?><br/> Please report this error by sending an e-mail to the staff at <a href='mailto:webmaster@legacyworlds.com'>webmaster@legacyworlds.com</a> explaining what happened. </p> </body> </html> <?php $html = ob_get_contents(); ob_end_clean(); die($html); } /** This method initialises communications with syslog. */ private static function init() { if (self::$initialised) { return; } openlog(self::$syslogPrefix, LOG_PID, LOG_USER); self::$initialised = true; } /** This method writes a string to the system log. */ private static function __write($txt, $level) { syslog($level, self::$prefix . $txt); } /** This method writes a string to the system log; * it is used by the external "logText" function and * should disappear in time. */ public static function write($txt, $level) { self::init(); if (is_null($level)) { $level = LOG_INFO; } self::__write($txt, $level); } /** This method displays one of the game engine's * fatal errors and adds log entries accordingly. */ public static function fatal($errno, $information = null) { // Log the error $errorText = self::$engineErrors[$errno] . " [" . sprintf("%03d", $errno) . "]"; self::critical($errorText); // Log additional information if (is_null($information)) { $information = array(); } elseif (!is_array($information)) { $information = array($information); } foreach ($information as $it) { self::info($it); } // Log additional details if (class_exists('input') && !is_null(input::$page)) { self::debug("Request: " . input::$path . "/" . input::$page . "." . input::$eType); if (tracking::$id != '') { $txt = "tracking: " . tracking::$id . " (" . tracking::$dbId . ")"; if (session::$id != '') { $txt .= "; session: " . session::$id . " (" . session::$dbId . ")"; if (!is_null($_SESSION['userid'])) { $txt .= "; user {$_SESSION['login']} ({$_SESSION['userid']})"; } } $txt .= "; user agent: {$_SERVER['HTTP_USER_AGENT']}"; self::debug($txt); } } self::backtrace(); eval(self::$fatalErrorCallback . '($errno, $errorText, $information);'); } /** This method writes a backtrace to the log, removing all * entries from the logging class. */ public static function backtrace() { $bt = debug_backtrace(); while (is_array($bt[1]) && isset($bt[1]['class']) && $bt[1]['class'] == 'l') { array_shift($bt); } self::info("Backtrace to the error:"); $base = dirname(config::$main['scriptdir']); foreach ($bt as $data) { $class = $data['class'] ?? ''; $cnLength = strlen($class); $str = "... " . str_repeat(' ', $cnLength > 30 ? 1 : (31 - $cnLength)) . $class . " :: " . $data['function']; if (!is_null($data['file'])) { $cnLength = strlen($data['function']); $fn = preg_replace("#^$base/#", "", $data['file']); $str .= str_repeat(' ', $cnLength > 25 ? 1 : (26 - $cnLength)) . " (line {$data['line']}, file '$fn')"; } self::info($str); } } /** This method changes the syslog prefix. */ public static function setSyslogPrefix($prefix) { self::$syslogPrefix = $prefix; if (self::$initialised) { closelog(); self::$initialised = false; } } /** This method changes the string prefix. */ public static function setPrefix($prefix) { self::$prefix = "$prefix "; } /** This method changes the function to call * for fatal errors. */ public static function setFatalHandler($function) { self::$fatalErrorCallback = $function; } /** This function logs the use of a deprecated * function call and prevents further logging of * similar occurences. */ public static function deprecated($function) { if (config::$main['debug'] == 2 && !self::$deprecatedLogged) { l::trace("DEPRECATED: $function"); l::backtrace(); self::$deprecatedLogged = true; } } /** This function logs FIXME's. */ public static function FIXME($text) { if (config::$main['debug'] >= 1 && !self::$fixmeLogged) { l::debug("FIXME: $text"); if (config::$main['debug'] == 2) { l::backtrace(); } self::$fixmeLogged = true; } } /******************* LOGGING METHODS ************************/ /* These methods should replace logText() wherever possible */ /************************************************************/ public static function crit($txt) { self::init(); self::__write($txt, LOG_CRIT); } public static function critical($txt) { self::init(); self::__write($txt, LOG_CRIT); } public static function error($txt) { self::init(); self::__write($txt, LOG_ERR); } public static function warn($txt) { self::init(); self::__write($txt, LOG_WARNING); } public static function warning($txt) { self::init(); self::__write($txt, LOG_WARNING); } public static function notice($txt) { self::init(); self::__write($txt, LOG_NOTICE); } public static function info($txt) { self::init(); self::__write($txt, LOG_INFO); } public static function debug($txt) { if (config::$main['debug'] >= 1) { self::init(); self::__write($txt, LOG_DEBUG); } } public static function trace($txt) { if (config::$main['debug'] == 2) { self::init(); self::__write($txt, LOG_DEBUG); } } } /** This function writes an entry to the system log. */ function logText($txt, $level = null) { l::deprecated("logText()"); l::write($txt, $level); } /** This function displays one of the game engine's fatal errors and adds * log entries accordingly. */ function fatalError($errno, $information = null) { l::deprecated("fatalError($errno)"); l::fatal($errno, $information); } ?>