'Error', E_WARNING => 'Warning', E_PARSE => 'Parsing Error', E_NOTICE => 'Notice', E_CORE_ERROR => 'Core Error', E_CORE_WARNING => 'Core Warning', E_COMPILE_ERROR => 'Compile Error', E_COMPILE_WARNING => 'Compile Warning', E_DEPRECATED => 'Deprecated Warning', E_USER_ERROR => 'User Error', E_USER_WARNING => 'User Warning', E_USER_NOTICE => 'User Notice', E_USER_DEPRECATED => 'User Deprecated Warning', E_STRICT => 'Runtime Notice', E_RECOVERABLE_ERROR => 'Catchable Fatal Error', MYBB_SQL => 'MyBB SQL Error', MYBB_TEMPLATE => 'MyBB Template Error', MYBB_GENERAL => 'MyBB Error', MYBB_NOT_INSTALLED => 'MyBB Error', MYBB_NOT_UPGRADED => 'MyBB Error', MYBB_INSTALL_DIR_EXISTS => 'MyBB Error', MYBB_SQL_LOAD_ERROR => 'MyBB Error', MYBB_CACHE_NO_WRITE => 'MyBB Error', MYBB_CACHEHANDLER_LOAD_ERROR => 'MyBB Error', ); /** * Array of MyBB error types * * @var array */ public $mybb_error_types = array( MYBB_SQL, MYBB_TEMPLATE, MYBB_GENERAL, MYBB_NOT_INSTALLED, MYBB_NOT_UPGRADED, MYBB_INSTALL_DIR_EXISTS, MYBB_SQL_LOAD_ERROR, MYBB_CACHE_NO_WRITE, MYBB_CACHEHANDLER_LOAD_ERROR, ); /** * Array of all of the error types to ignore * * @var array */ public $ignore_types = array( E_DEPRECATED, E_NOTICE, E_USER_NOTICE, E_STRICT ); /** * String of all the warnings collected * * @var string */ public $warnings = ""; /** * Is MyBB in an errornous state? (Have we received an error?) * * @var boolean */ public $has_errors = false; /** * Display errors regardless of related settings (useful during initialization stage) * * @var boolean */ public $force_display_errors = false; /** * Initializes the error handler * */ function __construct() { // Lets set the error handler in here so we can just do $handler = new errorHandler() and be all set up. $error_types = E_ALL; foreach($this->ignore_types as $bit) { $error_types = $error_types & ~$bit; } error_reporting($error_types); set_error_handler(array(&$this, "error_callback"), $error_types); } /** * Passes relevant arguments for error processing. * * @param string $type The error type (i.e. E_ERROR, E_FATAL) * @param string $message The error message * @param string $file The error file * @param integer $line The error line */ function error_callback($type, $message, $file=null, $line=0) { return $this->error($type, $message, $file, $line); } /** * Processes an error. * * @param string $type The error type (i.e. E_ERROR, E_FATAL) * @param string $message The error message * @param string $file The error file * @param integer $line The error line * @param boolean $allow_output Whether or not output is permitted * @return boolean True if parsing was a success, otherwise assume a error */ function error($type, $message, $file=null, $line=0, $allow_output=true) { global $mybb; // Error reporting turned off for this type if((error_reporting() & $type) == 0) { return true; } if(in_array($type, $this->ignore_types)) { return true; } $file = str_replace(MYBB_ROOT, "", $file); if($type == MYBB_SQL || strpos(strtolower($this->error_types[$type]), 'warning') === false) { $this->has_errors = true; } // For some reason in the installer this setting is set to "<" $accepted_error_types = array('both', 'error', 'warning', 'none'); if(isset($mybb->settings['errortypemedium']) && in_array($mybb->settings['errortypemedium'], $accepted_error_types)) { $errortypemedium = $mybb->settings['errortypemedium']; } else { $errortypemedium = "none"; } if(isset($mybb->settings['errorlogmedium'])) { $errorlogmedium = $mybb->settings['errorlogmedium']; } else { $errorlogmedium = 'none'; } if(defined("IN_TASK")) { global $task; require_once MYBB_ROOT."inc/functions_task.php"; $filestr = ''; if($file) { $filestr = " - Line: $line - File: $file"; } add_task_log($task, "{$this->error_types[$type]} - [$type] ".var_export($message, true)."{$filestr}"); } // Saving error to log file. if($errorlogmedium == "log" || $errorlogmedium == "both") { $this->log_error($type, $message, $file, $line); } // Are we emailing the Admin a copy? if($errorlogmedium == "mail" || $errorlogmedium == "both") { $this->email_error($type, $message, $file, $line); } if($allow_output === true) { // SQL Error if($type == MYBB_SQL) { $this->output_error($type, $message, $file, $line); } // PHP Error elseif(strpos(strtolower($this->error_types[$type]), 'warning') === false) { $this->output_error($type, $message, $file, $line); } // PHP Warning elseif(in_array($errortypemedium, array('warning', 'both'))) { global $templates; $warning = "{$this->error_types[$type]} [$type] $message - Line: $line - File: $file PHP ".PHP_VERSION." (".PHP_OS.")
\n"; if(is_object($templates) && method_exists($templates, "get") && !defined("IN_ADMINCP")) { $this->warnings .= $warning; $this->warnings .= $this->generate_backtrace(); } else { echo "
{$warning}".$this->generate_backtrace()."
"; } } } return true; } /** * Returns all the warnings * * @return string|bool The warnings or false if no warnings exist */ function show_warnings() { global $lang, $templates; if(empty($this->warnings)) { return false; } // Incase a template fails and we're receiving a blank page. if(MANUAL_WARNINGS) { echo $this->warnings."
"; } if(!$lang->warnings) { $lang->warnings = "The following warnings occurred:"; } $template_exists = false; if(!is_object($templates) || !method_exists($templates, 'get')) { if(@file_exists(MYBB_ROOT."inc/class_templates.php")) { @require_once MYBB_ROOT."inc/class_templates.php"; $templates = new templates; $template_exists = true; } } else { $template_exists = true; } $warning = ''; if($template_exists == true) { eval("\$warning = \"".$templates->get("php_warnings")."\";"); } return $warning; } /** * Triggers a user created error * Example: $error_handler->trigger("Some Warning", E_USER_ERROR); * * @param string $message Message * @param string|int $type Type */ function trigger($message="", $type=E_USER_ERROR) { global $lang; if(!$message) { if(isset($lang->unknown_user_trigger)) { $message = $lang->unknown_user_trigger; } else { $message .= 'An unknown error has been triggered.'; } } if(in_array($type, $this->mybb_error_types)) { $this->error($type, $message); } else { trigger_error($message, $type); } } /** * Logs the error in the specified error log file. * * @param string $type Warning type * @param string $message Warning message * @param string $file Warning file * @param integer $line Warning line */ function log_error($type, $message, $file, $line) { global $mybb; if($type == MYBB_SQL) { $message = "SQL Error: {$message['error_no']} - {$message['error']}\nQuery: {$message['query']}"; } // Do not log something that might be executable $message = str_replace('generate_backtrace(false, 2); if($back_trace) { $back_trace = "\t{$back_trace}\n"; } $error_data = "\n"; $error_data .= "\t".TIME_NOW."\n"; $error_data .= "\t\n"; $error_data .= "\t".$line."\n"; $error_data .= "\t".$type."\n"; $error_data .= "\t".$this->error_types[$type]."\n"; $error_data .= "\t".$message."\n"; $error_data .= $back_trace; $error_data .= "\n\n"; if(isset($mybb->settings['errorloglocation']) && trim($mybb->settings['errorloglocation']) != "") { @error_log($error_data, 3, $mybb->settings['errorloglocation']); } else { @error_log($error_data, 0); } } /** * Emails the error in the specified error log file. * * @param string $type Warning type * @param string $message Warning message * @param string $file Warning file * @param integer $line Warning line * @return bool returns false if no admin email is set */ function email_error($type, $message, $file, $line) { global $mybb; if(empty($mybb->settings['adminemail'])) { return false; } if($type == MYBB_SQL) { $message = "SQL Error: {$message['error_no']} - {$message['error']}\nQuery: {$message['query']}"; } if(function_exists('debug_backtrace')) { ob_start(); debug_print_backtrace(); $trace = ob_get_contents(); ob_end_clean(); $back_trace = "\nBack Trace: {$trace}"; } else { $back_trace = ''; } $message = "Your copy of MyBB running on {$mybb->settings['bbname']} ({$mybb->settings['bburl']}) has experienced an error. Details of the error include:\n---\nType: $type\nFile: $file (Line no. $line)\nMessage\n$message{$back_trace}"; @my_mail($mybb->settings['adminemail'], "MyBB error on {$mybb->settings['bbname']}", $message, $mybb->settings['adminemail']); return true; } /** * @param string $type * @param string $message * @param string $file * @param int $line */ function output_error($type, $message, $file, $line) { global $mybb, $parser, $lang; if(isset($mybb->settings['bbname'])) { $bbname = $mybb->settings['bbname']; } else { $bbname = "MyBB"; } // For some reason in the installer this setting is set to "<" $accepted_error_types = array('both', 'error', 'warning', 'none'); if(isset($mybb->settings['errortypemedium']) && in_array($mybb->settings['errortypemedium'], $accepted_error_types)) { $errortypemedium = $mybb->settings['errortypemedium']; } else { $errortypemedium = "none"; } $show_details = ( $this->force_display_errors || in_array($errortypemedium, array('both', 'error')) || defined("IN_INSTALL") || defined("IN_UPGRADE") ); if($type == MYBB_SQL) { $title = "MyBB SQL Error"; $error_message = "

MyBB has experienced an internal SQL error and cannot continue.

"; if($show_details) { $message['query'] = htmlspecialchars_uni($message['query']); $message['error'] = htmlspecialchars_uni($message['error']); $error_message .= "
\n"; $error_message .= "
SQL Error:
\n
{$message['error_no']} - {$message['error']}
\n"; if($message['query'] != "") { $error_message .= "
Query:
\n
{$message['query']}
\n"; } $error_message .= "
\n"; } } else { $title = "MyBB Internal Error"; $error_message = "

MyBB has experienced an internal error and cannot continue.

"; if($show_details) { $error_message .= "
\n"; $error_message .= "
Error Type:
\n
{$this->error_types[$type]} ($type)
\n"; $error_message .= "
Error Message:
\n
{$message}
\n"; if(!empty($file)) { $error_message .= "
Location:
File: {$file}
Line: {$line}
\n"; if(!@preg_match('#config\.php|settings\.php#', $file) && @file_exists($file)) { $code_pre = @file($file); $code = ""; if(isset($code_pre[$line-4])) { $code .= $line-3 . ". ".$code_pre[$line-4]; } if(isset($code_pre[$line-3])) { $code .= $line-2 . ". ".$code_pre[$line-3]; } if(isset($code_pre[$line-2])) { $code .= $line-1 . ". ".$code_pre[$line-2]; } $code .= $line . ". ".$code_pre[$line-1]; // The actual line. if(isset($code_pre[$line])) { $code .= $line+1 . ". ".$code_pre[$line]; } if(isset($code_pre[$line+1])) { $code .= $line+2 . ". ".$code_pre[$line+1]; } if(isset($code_pre[$line+2])) { $code .= $line+3 . ". ".$code_pre[$line+2]; } unset($code_pre); $parser_exists = false; if(!is_object($parser) || !method_exists($parser, 'mycode_parse_php')) { if(@file_exists(MYBB_ROOT."inc/class_parser.php")) { @require_once MYBB_ROOT."inc/class_parser.php"; $parser = new postParser; $parser_exists = true; } } else { $parser_exists = true; } if($parser_exists) { $code = $parser->mycode_parse_php($code, true); } else { $code = @nl2br($code); } $error_message .= "
Code:
{$code}
\n"; } } $backtrace = $this->generate_backtrace(); if($backtrace && !in_array($type, $this->mybb_error_types)) { $error_message .= "
Backtrace:
{$backtrace}
\n"; } $error_message .= "
\n"; } } if(isset($lang->settings['charset'])) { $charset = $lang->settings['charset']; } else { $charset = 'UTF-8'; } $contact_site_owner = ''; $is_in_contact = defined('THIS_SCRIPT') && THIS_SCRIPT === 'contact.php'; if( !empty($mybb->settings['contactlink']) && ( !empty($mybb->settings['contact']) && !$is_in_contact && ( $mybb->settings['contactlink'] == "contact.php" && ( !isset($mybb->user['uid']) || ($mybb->settings['contact_guests'] != 1 && $mybb->user['uid'] == 0) || $mybb->user['uid'] > 0 ) ) || $mybb->settings['contactlink'] != "contact.php" ) ) { if( !my_validate_url($mybb->settings['contactlink'], true, true) && my_substr($mybb->settings['contactlink'], 0, 7) != 'mailto:' ) { $mybb->settings['contactlink'] = $mybb->settings['bburl'].'/'.$mybb->settings['contactlink']; } $contact_site_owner = <<contact the site owner. HTML; } $additional_name = ''; $docs_link = 'https://docs.mybb.com'; $common_issues_link = 'https://docs.mybb.com/1.8/faq/'; $support_link = 'https://community.mybb.com/'; if(isset($lang->settings['docs_link'])) { $docs_link = $lang->settings['docs_link']; } if(isset($lang->settings['common_issues_link'])) { $common_issues_link = $lang->settings['common_issues_link']; } if(isset($lang->settings['support_link'])) { $support_link = $lang->settings['support_link']; } if(isset($lang->settings['additional_name'])) { $additional_name = $lang->settings['additional_name']; } $contact = << If you're a visitor of this website, please wait a few minutes and try again.{$contact_site_owner}

If you are the site owner, please check the MyBB{$additional_name} Documentation for help resolving common issues, or get technical help on the MyBB{$additional_name} Community Forums.

HTML; if(!headers_sent() && !defined("IN_INSTALL") && !defined("IN_UPGRADE")) { @header('HTTP/1.1 503 Service Temporarily Unavailable'); @header('Status: 503 Service Temporarily Unavailable'); @header('Retry-After: 1800'); @header("Content-type: text/html; charset={$charset}"); $file_name = basename($_SERVER['SCRIPT_FILENAME']); if(function_exists('htmlspecialchars_uni')) { $file_name = htmlspecialchars_uni($file_name); } else { $file_name = htmlspecialchars($file_name); } echo << {$bbname} - Internal Error

{$title}

{$error_message}
EOF; } else { echo << #mybb_error_content { border: 1px solid #026CB1; background: #fff; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } #mybb_error_content a:link { color: #026CB1; text-decoration: none; } #mybb_error_content a:visited { color: #026CB1; text-decoration: none; } #mybb_error_content a:hover, a:active { color: #000; text-decoration: underline; } #mybb_error_content h2 { font-size: 12px; padding: 4px; background: #026CB1; color: #fff; margin: 0; border-bottom: none; } #mybb_error_error { padding: 6px; } #mybb_error_footer { font-size: 12px; border-top: 1px dotted #DDDDDD; padding-top: 10px; } #mybb_error_content dt { font-weight: bold; }

{$title}

{$error_message}
EOF; } exit(1); } /** * Generates a backtrace if the server supports it. * * @return string The generated backtrace */ function generate_backtrace($html=true, $strip=1) { $backtrace = ''; if(function_exists("debug_backtrace")) { $trace = debug_backtrace(1<<1 /* DEBUG_BACKTRACE_IGNORE_ARGS */); if($html) { $backtrace = "\n"; $backtrace .= "\n"; $backtrace .= "\n"; $backtrace .= "\n"; $backtrace .= "\n"; $backtrace .= "\n\n"; } // Strip off calls from trace $trace = array_slice($trace, $strip); $i = 0; foreach($trace as $call) { if(empty($call['file'])) $call['file'] = "[PHP]"; if(empty($call['line'])) $call['line'] = " "; if(!empty($call['class'])) $call['function'] = $call['class'].$call['type'].$call['function']; $call['file'] = str_replace(MYBB_ROOT, "/", $call['file']); if($html) { $backtrace .= "\n"; $backtrace .= "\n"; $backtrace .= "\n"; $backtrace .= "\n"; $backtrace .= "\n"; } else { $backtrace .= "#{$i} {$call['function']}() called at [{$call['file']}:{$call['line']}]\n"; } $i++; } if($html) { $backtrace .= "
FileLineFunction
{$call['file']}{$call['line']}{$call['function']}
\n"; } } return $backtrace; } }