error.php - index








































































































































































































































































































































































































































































































<?php
/*
    "NCSA httpd 1.3 would return some boring old error/problem message 
    which would often be meaningless to the user, and would provide no 
    means of logging the symptoms which caused it."
      -- Apache, 'Custom Error Responses'
*/
/*
    "Once you are ready for deployment, you should either disable error 
    reporting completely by setting error_reporting() to 0, or turn off 
    the error display using the php.ini option display_errors, to insulate 
    your code from probing. If you choose to do the latter, you should also 
    define the path to your log file using the error_log ini directive, and 
    turn log_errors on."
      -- PHP.NET
*/

/* ERROR.PHP - error and debug message handling

This gets included by INDEX.PHP and ADMIN.PHP (the two sole entry points) 
as the very first include; it provides two main things:

    Error and informational messages, both fatal and notices.
    Detailed debug/runtime message logging and displaying.
    A few server "error" functions.

Well, that's three. But we never said we could count...
*/

$GLOBALS['debug'] = '';
error_reporting(E_ALL E_STRICT E_NOTICE);

// some hosts will turn this off which can be annoying if there is an error
//ini_set('display_errors',1);

// the following is very useful to locate start-up errors, but we can't 
// use it based on a configuration setting as config may not be available
// what I do if a "blank screen" happens is to uncomment it and then it will
// display the modules that successfully loaded -- the one that does not is
// the one that has the error
//register_shutdown_function('modules_loaded');

_error_config();
checkbaduser();                // checks banned IPs and Referers
                    //  might exit

/* setmodule - each module calls this first, INDEX.PHP calls last */

function setmodule() {
    
$GLOBALS['modules'][] = caller(1,'file');
}
// see file MODULES


/* modules_loaded - display loaded modules list */

function modules_loaded() {
    foreach (
$GLOBALS['modules'] as $name)
        echo 
"\n<!-- $name -->";
}


/* errorlog - set the errorlog level */

// called by CONFIG *if* logged in as Admin and 'debug =' is non-zero

function errorlog($log) {
    global 
$error;

    
$error['error_log'] = $log;
    
register_shutdown_function('_msglogdump');
}


/* error - display a formated error message */

// we still only have a very clumsy way of handling errors...

// fatal errors are handled stupidly, as they just "fart"... just some stinky 
// error message that is offensive -- we HAVE to do something different, like 
// continue loading the program and, once we get to the start, THEN display a
// really informative message with links to the HTML compiled documentation!

function error($msg ''$arg '') {
    global 
$error;

    switch (
$msg) {                    // specials
    
case 'notfound':
        print 
"'$arg' not found";
        return;
    case 
'last':
        if (isset(
$error['last']))
            echo 
"last error: ".$error['last'];
        return;
    case 
'caller':
        list(
$file,$line,$func) = caller(2);
        
$func caller(3,'function');
        echo 
"called: $file,$line,$func$arg";
        return;
    case -
1:
        return 
$error;
    }

    
$error['last'] = $msg;

// two calls are here to displayhtml() and I am inclined to remove them and 
// have the caller do it instead...

    
if ($html geterror($msg)) {
        if (!
function_exists('displayhtml'))
            echo 
$html;
        else
            
displayhtml('message','$error',$html);
        return;
    }

    if (
debug()) {
        
$bt _backtrace();
        
$msg .= "<div class='e'><pre>$bt</pre></div>";
    }

    if (
$arg === FALSE) {                // log message?
        
if ($error['error_log'])
            
_msglog($msg);
        return;
    }

    if (
$arg === TRUE)                // return message?
        
return $msg;

    if (
$arg === -1) {
        
$msg obcomments($msg);
        echo 
"<!-- $msg -->";
        return;
    }

    if (
$arg == 'fatal') {                // early errors may be 
        
if (!function_exists('displayhtml'))    //  before display.php
            
exit($msg);            //  is loaded
        
$t 'fatalerror';
        if (
headers_sent())
            
$t 'error';
        
displayhtml($t,'$error',$msg);
        exit;
    }

    print 
$msg;
}


/* debug - display message or add to message queue */

function debug($msg NULL$trunc 0) {
    global 
$error;

    
$error_log $error['error_log'];

    if (
$msg === NULL)
        return 
$error_log;

    if (
$error_log == 0)
        return;

    list(
$file,$line,$func) = caller(1);
    
$func caller(2,'function');

    if (
function_exists('config'))
        if ((
$t config('debugmod')) && $t != $file)
            return;

    if (
$msg === TRUE)
        
$msg '(true)';

    if (
$msg === FALSE)
        
$msg '(false)';

    if (
is_resource($msg))
        
$msg 'Resource: '.get_resource_type($msg);

    if (
is_object($msg))
        
$msg 'Object: '.get_class($msg);

    if (
is_array($msg))
        
$msg "Array: {".rtrim(implode(',',$msg),','). "}";

    if (
$trunc == 0)
        if (
function_exists('config') && config('debugtruncate'))
            
$trunc config('debugtruncate');

    if (
$trunc && $trunc != -&& strlen($msg) > $trunc)
        
$msg substr($msg,0,$trunc).' ...';

    if (
function_exists('config') && config('debugentities'))
        
$msg htmlentities($msg);

    if (
function_exists('config') && config('debugconvertnl'))
        
$msg str_replace("\n",'\n',$msg);

    
$c '';
    if (
function_exists('config') && config('debugcaller')) {
        list(
$f,$l,$nu) = caller(2);
        
$c "($f,$l)";
    }

    if (
function_exists('config') && !config('nodebugfunc'))
        
$msg "$c($file,$line,$func$msg";
    else
        
$msg "$c($file,$line$msg";

    if (
$error_log == -1)
        print 
$msg '<br>';

    else
    if (
$error_log == 100)
        print 
'<!-- '.$msg.' -->'.THIS_EOL;

    else
    if (
$error_log == 200)
        
$GLOBALS['debug'] .= $msg.'<br>'.THIS_EOL;

    else
        
_msglog($msg);
}


/* redirect - send browser to a new location */

// assumes $url starts with a '?'

function redirect($url) {

    
$host 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];

    if (
headers_sent($file,$line)) {
        
debug("headers already sent by $file, line $line");
        
debug(implode('<br>',headers_list()));
        print(
"Location: <a href='$url'>$url</a>");
        exit;
    }

    if (
config('noredirect'))
        print(
"Location: <a href='$url'>$url</a>");
    else
        
header("Location: $host$url");
    exit;
}


/* HTML error handler stuff */


/* htmlseterror - set globally accessible error message */

// this sets the "global" error message to one of the defined error messages
// see ERROR.INI

function htmlseterror($name$id NULL) {
    global 
$error;

    
$error =& $error['error_msgs'];

    if (
$id && strpos($error['id_list'],$id) !== FALSE) {
        
$GLOBALS[$id] = $name;
        return;
    }

    if (!isset(
$error[$name]))
        
$name 'DEFAULT';

    if (!
is_array($error[$name])) {
        
$id $error['default_id'];
        
$ms $error[$name];
    }
    else {
        
$id $error[$name]['id'];
        
$ms $error[$name]['msg'];
    }

    
$GLOBALS[$id] = $ms;

    return 
$ms;
}


/* htmlgeterror - get a global error message based on ID/name lookup */

function htmlgeterror($name NULL) {
    global 
$error;

    
$error =& $error['error_msgs'];

    if (
$name == NULL)
        
$id $error['default_id'];    // default "global" message

    
if (strpos($error['id_list'],$name) !== FALSE)
        
$id $name;            // one of the "global" messages

    
if (isset($id))                // did we get one
        
return (@$GLOBALS[$id]) ? $GLOBALS[$id] : "";

    if (!isset(
$error[$name]))        // no message?
        
return "error '$name' error!";    //  oh no, an error error!

    
if (is_array($error[$name]))        // one of comment/system
        
return $error[$name]['msg'];    //  messages

    
return $error[$name];            // an other message
}


/* geterror - just get the error message or not */

function geterror($name) {
    global 
$error;

    return @
$error['error_msgs'][$name];
}


/* checkbaduser - look for match of banned ip or user agent */

// Right now a 404 is sent for the spammers so maybe they'll go away.

function checkbaduser() {
    global 
$error;

    
$e =& $error['error_msgs'];

    if (isset(
$e['HTTP_USER_AGENT']))
        foreach (
$e['HTTP_USER_AGENT'] as $_)
            if (
strstr($_SERVER['HTTP_USER_AGENT'],$_)) {
                
sleep(30);
                
notfound();
                exit;
            }

    if (isset(
$e['REMOTE_ADDR']))
        foreach (
$e['REMOTE_ADDR'] as $_)
            if (
strstr($_SERVER['REMOTE_ADDR'],$_)) {
                
notfound();
                exit;
            }

}

/* checkbadinput - look for "banned words" */

// Comment spammers use the "[link=" and "[url=" strings. Those are the two 
// default "ban words" and the code stops and logs the IP and UA string if 
// detected. the logging is experimental and to gather statistics

function checkbadinput($data) {
    global 
$error;

    
$e =& $error['error_msgs'];

    if (!isset(
$e['BAN_WORDS']))
        return;

    foreach (
$e['BAN_WORDS'] as $k => $v)
        if (
stristr($data,$v))
            
forbidden();
}

function 
notfound() {
    
header('HTTP/1.1 404 Not Found');
echo 
'<!DOCTYPE HTML>
<html><head><title>404 Not Found</title></head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<hr>
<ADDRESS>
Web Server at <a href="">where are we?</a>
</ADDRESS>
</body>
</html>
'
;
    exit;
}
function 
forbidden() {
    
header("HTTP/1.1 403 Forbidden");
echo 
'<!DOCTYPE HTML>
<HTML><HEAD><TITLE>403 Forbidden</TITLE>
</HEAD><BODY>
<H1>That is Forbidden</H1>
You have done something wrong.
</BODY>
</HTML>
'
;
    exit;
}
function 
servererror() {
    
header('HTTP/1.1 500 Internal Server Error');
echo 
'<!DOCTYPE HTML>
<HTML><HEAD><TITLE>500 Internal Server Error</TITLE>
</HEAD><BODY>
<H1>Internal Server Error</H1>
<P>The server encountered an internal error or misconfiguration and was unable to complete your request.</P>
<P>Please contact the server administrator to inform of the time the error occurred and of anything you might have done that may have caused the error.</P>
<P>More information about this error may be available in the server error log.</P>
</BODY>
</HTML>
'
;
    exit;
}


/* "internal" functions (used here and nowhere else) */


// _msglog - place a string into the message log

function _msglog($msg) {
    global 
$error;

    
$error['message_log'][] = $msg;
}


// _msglogdump - display the message log (as a shutdown fuction)

function _msglogdump() {
    global 
$error;

    
$e $error['error_log'];
    if (
$e <= || $e >= 100) return;        // special cases

    
print THIS_EOL.
    
"<div style='font-size:13px;background:white;color:black;'><pre>";
    foreach (
$error['message_log'] as $msg)
        print 
THIS_EOL.$msg;
    print 
"</pre></div>";
}

/* _backtrace - this version is vastly better than the last one! sheesh */

function _backtrace() {

//    if (config('errorfullbacktrace'))
        
return print_r(debug_backtrace(),1);
 
    
ob_start();
    if (
defined('DEBUG_BACKTRACE_IGNORE_ARGS'))
        
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
    else
        
debug_print_backtrace();
    
$out ob_get_contents();
    
ob_end_clean();

    if (
config('errorbacktrace'))
        return 
$out;

    
$out explode(THIS_EOL,$out);
    if (isset(
$out[3]))
        
$bt[] = substr($out[3],2);
    
$bt[] = substr($out[2],2);
    
$s '';
    foreach (
$bt as $t) {
        
$t str_replace($_SERVER['DOCUMENT_ROOT'],'',$t);
        
$t str_replace(array('[',']'),'',$t);
        
$s .= $t '<br>';
    }
    return 
$s;
}

/* this module's config */

function _error_config() {
    global 
$error;

// we have an INI to PHP array tool now and are going to slowly convert 
// some INI files to PHP files - that will make this code load much faster
/* going to delay this
    if (file_exists('dat/error_dat.php')) {
        include 'dat/error_dat.php';
        return;
    }
*/
    
$error['error_log'] = 0;
    
$error['message_log'] = array("<b>message log:</b>");

    
// this reads the error messages "database" into memory
    
$error['error_msgs'] = parse_ini_file("error.ini",TRUE);
}

?>