'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('', '< ?', $message);
$back_trace = $this->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 .= "File | \n";
$backtrace .= "Line | \n";
$backtrace .= "Function | \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 .= "{$call['file']} | \n";
$backtrace .= "{$call['line']} | \n";
$backtrace .= "{$call['function']} | \n";
$backtrace .= "
\n";
}
else
{
$backtrace .= "#{$i} {$call['function']}() called at [{$call['file']}:{$call['line']}]\n";
}
$i++;
}
if($html)
{
$backtrace .= "
\n";
}
}
return $backtrace;
}
}