=')) { if (ini_get('error_reporting') & E_NOTICE) { error_reporting(ini_get('error_reporting') - E_NOTICE); } if (ini_get('error_reporting') & E_USER_NOTICE) { error_reporting(ini_get('error_reporting') - E_USER_NOTICE); } } if ((bool)ini_get('register_globals') === true) { $superglobals = array('_GET', '_COOKIE', '_FILES', '_POST', '_SERVER', '_ENV'); foreach ($superglobals AS $global) { if (is_array(${$global})) { foreach (${$global} AS $_key => $_val) { if (isset(${$_key})) { unset(${$_key}); } } } } } $oldlevel = ini_get('error_reporting'); $newlevel = $oldlevel; $levels = array(E_ERROR => E_USER_ERROR, E_WARNING => E_USER_WARNING, E_NOTICE => E_USER_NOTICE); foreach ($levels AS $php => $isso) { if ($oldlevel & $php) { if (!($oldlevel & $isso)) { $newlevel += $isso; } } else { if ($oldlevel & $isso) { $newlevel -= $isso; } } } error_reporting($newlevel); /**#@+ * Input cleaning type constant */ /** * Integer type */ define('TYPE_INT', 1); /** * Unsigned integer */ define('TYPE_UINT', 2); /** * Float type */ define('TYPE_FLOAT', 4); /** * Boolean type */ define('TYPE_BOOL', 8); /** * String - cleaned */ define('TYPE_STR', 16); /** * String - deliberate unclean */ define('TYPE_STRUN', 32); /** * No cleaning - here for use in API */ define('TYPE_NOCLEAN', 64); /** * Duplicate of TYPE_NOCLEAN, but shorter */ define('TYPE_NONE', TYPE_NOCLEAN); /** * Macro for using DB->escape_binary() without cleaning - used in API */ define('TYPE_BIN', 128); /**#@-*/ /** * Yes, required */ define('REQ_YES', 1); /** * No, not required */ define('REQ_NO', 0); /** * Blue Static ISSO Framework (ISSO) * * This framework allows a common backend to be used amongst all Blue * Static applications and is built to be abstract and flexible. * The base framework handles all loading and module management. * * Constants: * ISSO_NO_INPUT_SANITIZE - Disables the automatic input sanitizer * ISSO_CHECK_POST_REFERER - Will check to make sure that on POSTed * data, the referer matches the host * ISSO_MT_START - Define the microtime() value at the top of your * script and this will calculate the total execution * time * SVN - Place SVN keywords (like $Id) to display the information on output * * @author Blue Static * @copyright Copyright ©2002 - [#]year[#], Blue Static * @version $Revision$ * @package ISSO * */ class ISSO { /** * Location of ISSO, used for internal linking * @var string * @access private */ var $sourcepath = ''; /** * Path of the current application * @var string * @access private */ var $apppath = ''; /** * Web path used to get the web location of the installation of ISSO; only used for Printer module * @var string * @access private */ var $webpath = ''; /** * Name of the current application * @var string * @access private */ var $application = ''; /** * Version of the current application * @var string * @access private */ var $appversion = ''; /** * Whether debug mode is on or off * @var bool * @access private */ var $debug = false; /** * List of all active debug messages * @var array * @access private */ var $debuginfo = array(); /** * List of loaded modules * @var array * @access private */ var $modules = array(); /** * An array of sanitized variables that have been cleaned for HTML tag openers and double quotes * @var array * @access public */ var $in = array(); /** * If we are running with magic_quotes_gpc on or off * @var int * @access private */ var $magicquotes = 0; // ################################################################### /** * Constructor */ function __construct() { $GLOBALS['isso:callback'] = null; // error reporting set_error_handler(array(&$this, '_error_handler')); // magic quotes $this->magicquotes = get_magic_quotes_gpc(); set_magic_quotes_runtime(0); // some debug info that's always useful $this->debug('magic_quotes_gpc = ' . $this->magicquotes); $this->debug('register_globals = ' . ini_get('register_globals')); // attempt to set the sourcepath $path = call_user_func('debug_backtrace'); $this->setSourcePath(str_replace('kernel.php', '', $path[0]['file'])); // start input sanitize using variable_order GPC if (!defined('ISSO_NO_INPUT_SANITIZE')) { $this->exec_sanitize_data(); } if (defined('ISSO_CHECK_POST_REFERER')) { $this->exec_referer_check(); } } // ################################################################### /** * (PHP 4) Constructor */ function ISSO() { $this->__construct(); } // ################################################################### /** * Sets the sourcepath * * @access public * * @param string Source path */ function setSourcePath($path) { $this->sourcepath = $this->fetch_sourcepath($path); } // ################################################################### /** * Gets the sourcepath * * @access public * * @return string Source path */ function getSourcePath() { return $this->sourcepath; } // ################################################################### /** * Sets the apppath * * @access public * * @param string Application path */ function setAppPath($path) { $this->apppath = $this->fetch_sourcepath($path); } // ################################################################### /** * Gets the apppath * * @access public * * @return string Source path */ function getAppPath() { return $this->apppath; } // ################################################################### /** * Sets the webpath * * @access public * * @param string Web path */ function setWebPath($path) { $this->webpath = $this->fetch_sourcepath($path); } // ################################################################### /** * Gets the webpath * * @access public * * @return string Web path */ function getWebPath() { return $this->webpath; } // ################################################################### /** * Sets the applicaiton * * @access public * * @param string Applicaiton */ function setApplication($app) { $this->application = $app; } // ################################################################### /** * Gets the application * * @access public * * @return string Application */ function getApplication() { return $this->application; } // ################################################################### /** * Sets the appverison * * @access public * * @param string Applicaiton version */ function setAppVersion($version) { $this->appversion = $version; } // ################################################################### /** * Gets the appversion * * @access public * * @return string Application version */ function getAppVersion() { return $this->appversion; } // ################################################################### /** * Sets debug mode * * @access public * * @param boolean Debug? */ function setDebug($debug) { $this->debug = $debug; } // ################################################################### /** * Gets debug mode state * * @access public * * @return boolean Debug? */ function getDebug() { return $this->debug; } // ################################################################### /** * Prepares a path for being set as the sourcepath * * @access public * * @param string Source path or URL * * @return string Prepared source path */ function fetch_sourcepath($source) { if (substr($source, strlen($source) - 1) != DIRECTORY_SEPARATOR) { $source .= DIRECTORY_SEPARATOR; } return $source; } // ################################################################### /** * Loads a framework module * * @access public * * @param string Name of the framework file to load * @param string Internal variable to initialize as; to not instantiate (just require) leave it as NULL * @param bool Globalize the internal variable? * * @return object Instantiated instance */ function &load($framework, $asobject, $globalize = false) { // set the object interlock if (!method_exists($GLOBALS['isso:callback'], 'load')) { $GLOBALS['isso:callback'] =& $this; $this->modules['isso'] =& $this; } if ($this->is_loaded($framework)) { return $this->modules["$framework"]; } if ($this->sourcepath == '') { trigger_error('Invalid sourcepath specified', E_USER_ERROR); } if (file_exists($this->sourcepath . $framework . '.php')) { require_once($this->sourcepath . $framework . '.php'); } else { trigger_error('Could not find the framework ' . $this->sourcepath . $framework . '.php', E_USER_ERROR); } if ($asobject === null) { return; } if (isset($this->$asobject)) { trigger_error('Cannot instantiate framework `' . $framework . '` into `' . $asobject . '`', E_USER_ERROR); } $this->$asobject = new $framework($this); $this->modules["$framework"] =& $this->$asobject; if ($globalize) { $GLOBALS["$asobject"] =& $this->$asobject; } // allow for init_as_package to link if (method_exists($this->modules["$framework"], 'init_as_package')) { $this->modules[ $this->modules["$framework"]->init_as_package() ] =& $this->modules["$framework"]; } return $this->$asobject; } // ################################################################### /** * Prints a list of all currently loaded framework modules * * @access public * * @param bool Return the data as an array? * * @return mixed HTML output or an array of loaded modules */ function show_modules($return = false) { $modules = array(); foreach ($this->modules AS $object) { $module = get_class($object); if (method_exists($object, 'init_as_package') AND in_array($module, $modules)) { $module = $object->init_as_package() . " - ($module)"; } $modules[] = $module; } if ($return) { return $modules; } else { $output = "\n\n\n\n"; $this->message('Loaded Modules', $output, 1); } } // ################################################################### /** * Verifies to see if a framework has been loaded * * @access public * * @param string Framework name * * @return bool Whether or not the framework has been loaded */ function is_loaded($framework) { if (isset($this->modules["$framework"])) { return true; } else { return false; } } // ################################################################### /** * Prints an ISSO message * * @access public * * @param string The title of the message * @param string The content of the message * @param integer Type of message to be printed * @param bool Return the output? * @param bool Show the debug stack? * @param integer Message width * * @return mixed Output or null */ function message($title, $message, $type, $return = false, $stack = true, $width = 500) { switch ($type) { // Message case 1: $prefix = 'Message'; $color = '#669900'; $font = '#000000'; break; // Warning case 2: $prefix = 'Warning'; $color = '#003399'; $font = '#FFFFFF'; break; case 3: $prefix = 'Error'; $color = '#990000'; $font = '#EFEFEF'; break; } $backtrace = debug_backtrace(); array_shift($backtrace); if (isset($backtrace[0]) AND $backtrace[0]['function'] == '_error_handler') { array_shift($backtrace); } $trace = $this->format_debug_trace($backtrace); $output = "\n
\n"; $output .= "\n\n\t\n"; $output .= "\n\n\t\n"; $output .= (($stack AND $GLOBALS['isso:callback']->debug) ? "\n\n\t\n" : ''); $output .= "\n
$prefix: $title
$message
Debug Stack:
" . implode("\n", $trace) . "
\n
\n"; if ($return) { return $output; } else { print($output); } } // ################################################################### /** * Prepares a debug_backtrace() array for output to the browser by * compressing the array into visible text * * @access public * * @param array debug_backtrace() array * * @return array Formatted trace output */ function format_debug_trace($backtrace) { $trace = array(); foreach ($backtrace AS $i => $step) { $args = ''; $file = $step['file'] . ':' . $step['line']; $funct = (isset($step['class']) ? $step['class'] . '::' . $step['function'] : $step['function']); if (isset($step['args']) AND is_array($step['args'])) { // we need to do this so we don't get "Array to string conversion" notices foreach ($step['args'] AS $id => $arg) { if (is_array($arg)) { $step['args']["$id"] = 'Array'; } } $args = implode(', ', $step['args']); } $trace[] = "#$i $funct($args) called at [$file]"; } return $trace; } // ################################################################### /** * Custom error handler for ISSO; only handle E_WARNING, E_NOTICE, * E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE * * @access private * * @param integer Error number * @param string Error message string * @param string File that contains the error * @param string The line number of the error * @param string The active symbol table at which point the error occurred */ function _error_handler($errno, $errstr, $errfile, $errline, $errcontext) { $level = ini_get('error_reporting'); switch ($errno) { // Fatal case E_USER_ERROR: $title = 'Fatal'; $mode = 3; if (!($level & E_USER_ERROR)) { return; } break; // Error case E_USER_WARNING: case E_WARNING: $title = 'Warning'; $mode = 2; if (! (($level & E_USER_WARNING) AND ($level & E_WARNING)) ) { return; } break; // Warning case E_USER_NOTICE: case E_NOTICE: default: $title = 'Notice'; $mode = 1; if (! (($level & E_USER_NOTICE) AND ($level & E_NOTICE)) ) { return; } break; } $errstr .= " in $errfile on line $errline"; $errstr = str_replace(array(getcwd(), dirname(getcwd())), '', $errstr); $this->message($title, $errstr, $mode); if ($errno == E_USER_ERROR) { exit; } } // ################################################################### /** * Creates a table that explains the error reporting levels and their * state * * @access public */ function explain_error_reporting() { $levels = array( 'E_ERROR' => E_ERROR, 'E_WARNING' => E_WARNING, 'E_PARSE' => E_PARSE, 'E_NOTICE' => E_NOTICE, 'E_CORE_ERROR' => E_CORE_ERROR, 'E_CORE_WARNING' => E_CORE_WARNING, 'E_COMPILE_ERROR' => 64, 'E_COMPILE_WARNING' => 128, 'E_USER_ERROR' => E_USER_ERROR, 'E_USER_WARNING' => E_USER_WARNING, 'E_USER_NOTICE' => E_USER_NOTICE, 'E_ALL' => E_ALL, 'E_STRICT' => 2048 ); $table = ''; foreach ($levels AS $name => $value) { $table .= ' '; } $table .= '
' . $name . ' ' . (ini_get('error_reporting') & $value) . '
'; $this->message('Error Reporting', $table, 1); } // ################################################################### /** * Logs a debug message for verbose output * * @access public * * @param string Message */ function debug($message) { $this->debuginfo[] = $message; } // ################################################################### /** * Recursive XSS cleaner * * @access private * * @param mixed Unsanitized REQUEST data * * @return mixed Sanitized data */ function _sanitize_input_recursive($data) { foreach ($data AS $key => $value) { if (is_array($value)) { $data["$key"] = $this->_sanitize_input_recursive($value); } else { if ($this->magicquotes) { $value = str_replace("\'", "'", $value); } $data["$key"] = $this->sanitize($value); } } return $data; } // ################################################################### /** * Simple way to protect against HTML attacks with Unicode support * * @access public * * @param string Unsanitzed text * * @return string Properly protected text that only encodes potential threats */ function sanitize($text) { if ($this->magicquotes) { return str_replace(array('<', '>', '\"', '"'), array('<', '>', '"', '"'), $text); } else { return str_replace(array('<', '>', '"'), array('<', '>', '"'), $text); } } // ################################################################### /** * Unicode-safe entity encoding system; similar to sanitize() * * @access public * * @param string Unsanitized text * * @return string Unicode-safe sanitized text with entities preserved */ function entity_encode($text) { $text = str_replace('&', '&', $text); $text = $this->sanitize($text); return $text; } // ################################################################### /** * Takes text that has been processed for HTML and unsanitizes it * * @access public * * @param string Text that needs to be turned back into HTML * * @return string Unsanitized text */ function unsanitize($text) { return str_replace(array('<', '>', '"'), array('<', '>', '"'), $text); } // ################################################################### /** * Smart addslashes() that only applies itself it the Magic Quotes GPC * is off. This should only be run on database query values that come * from ISSO->in[] input; data that needs sanitization should be run * through ISSO->DB->escape_string() * * @access public * * @param string Some string * @param bool Force magic quotes to be off * * @return string String that has slashes added */ function escape($str, $force = true) { if ($this->magicquotes AND !$force) { if (isset($this->modules[ISSO_DB_LAYER])) { return $this->modules[ISSO_DB_LAYER]->escape_string(str_replace(array("\'", '\"'), array("'", '"'), $str)); } return $str; } else { if (isset($this->modules[ISSO_DB_LAYER])) { return $this->modules[ISSO_DB_LAYER]->escape_string($str); } return addslashes($str); } } // ################################################################### /** * Runs through all of the input data and sanitizes it. * * @access private */ function exec_sanitize_data() { $this->in = $this->_sanitize_input_recursive(array_merge($_GET, $_POST, $_COOKIE)); } // ################################################################### /** * Sanitize function for something other than a string (which * everything is sanitized for if you use exec_sanitize_data(). Cleaned * data is placed back into $isso->in; this makes it so you don't have * to constantly intval() [etc.] data. * * @access public * * @param array Array of elements to clean as varname => type */ function input_clean_array($vars) { foreach ($vars AS $varname => $type) { $this->input_clean($varname, $type); } } // ################################################################### /** * Sanitize function that does a single variable as oppoesd to an array * (see input_clean_array() for more details) * * @access public * * @param string Variable name in $isso->in[] * @param integer Sanitization type constant */ function input_clean($varname, $type) { if (isset($this->in["$varname"])) { $this->in["$varname"] = $this->clean($this->in["$varname"], $type); } else { $this->in["$varname"] = $this->clean(null, $type); } return $this->in["$varname"]; } // ################################################################### /** * Runs ISSO->escape() on a variable on ISSO->in[]. This is just a * short-hand wrapper so that queries can be shortened. When this is used, * the actual value in ISSO->in[] is not changed, only the return value * is escaped. * * @access public * * @param string Input variable * * @return string Escaped input */ function input_escape($varname) { if (isset($this->in["$varname"])) { return $this->escape($this->in["$varname"]); } else { return $this->escape(null); } } // ################################################################### /** * Cleaning function that does the work for input_clean(); this is * moved here so it can be used to clean things that aren't in * $isso->in[] * * @access public * * @param mixed Data * @param integer Sanitization type constant * * @return mixed Cleaned data */ function clean($value, $type) { if (is_array($value)) { return $this->clean_array($value, $type); } if ($type == TYPE_INT) { $value = intval($value); } else if ($type == TYPE_UINT) { $value = (($val = intval($value)) < 0 ? 0 : $val); } else if ($type == TYPE_FLOAT) { $value = floatval($value); } else if ($type == TYPE_BOOL) { $value = (bool)$value; } else if ($type == TYPE_STR) { $value = $value; } else if ($type == TYPE_STRUN) { $value = $this->unsanitize($value); } else if ($type == TYPE_NOCLEAN) { if ($this->magicquotes) { $value = str_replace(array('\"', "\'"), array('"', "'"), $value); } else { $value = $value; } } else if ($type == TYPE_BIN) { $value = $value; } else { trigger_error('Invalid clean type `' . $type . '` specified', E_USER_ERROR); } return $value; } // ################################################################### /** * Recursion function for ISSO->clean() * * @access private * * @param array Uncleaned array * @param integer Sanitization type constant * * @return array Cleaned array of data */ function clean_array($array, $type) { foreach ($array AS $key => $value) { $array["$key"] = $this->clean($value, $type); } return $array; } // ################################################################### /** * Checks to see if a POST refer is actually from us * * @access public */ function exec_referer_check() { if ($_SERVER['REQUEST_METHOD'] == 'POST') { $host = ($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_ENV['HTTP_HOST']; if ($host AND $_SERVER['HTTP_REFERER']) { $parts = parse_url($_SERVER['HTTP_REFERER']); $ourhost = $parts['host'] . (isset($parts['port']) ? ":$parts[port]" : ''); if ($ourhost != $host) { trigger_error('No external hosts are allowed to POST to this application', E_USER_ERROR); } $this->debug('remote post check = ok'); } else { $this->debug('remote post check = FAILED'); } } } // ################################################################### /** * Constructs a debug information box that contains various debugging * information points * * @access public * * @param bool Show template information? * * @return string Debugging block */ function construct_debug_block($dotemplates) { $debug = ''; if ($this->debug) { $debug = "\n"; $debug = "\n\n\n
\n\n
\n" . $this->message('Debug Information', $debug, 1, true, false) . "\n
$querydebug\n\n\n"; } return $debug; } } /*=====================================================================*\ || ################################################################### || # $HeadURL$ || # $Id$ || ################################################################### \*=====================================================================*/ ?>