escape_binary() without cleaning - used in API */ define('TYPE_BIN', 128); /**#@-*/ /** * Input Sanitizer * * This class is responsible for cleaning input. * * Constants: * ISSO_CHECK_POST_REFERER - Will check to make sure that on POSTed * data, the referer matches the host * * @author Blue Static * @copyright Copyright ©2002 - [#]year[#], Blue Static * @version $Revision$ * @package ISSO * */ class BSInput { /** * An array of sanitized variables that have been cleaned for HTML tag openers and double quotes * @var array */ public $in = array(); /** * If we are running with magic_quotes_gpc on or off * @var int */ private $magicquotes = 0; // ################################################################### /** * Constructor: set instance variables and execute input cleaning */ public function __construct() { // magic quotes $this->magicquotes = get_magic_quotes_gpc(); set_magic_quotes_runtime(0); // some debug info that's always useful BSRegister::Debug('magic_quotes_gpc = ' . $this->magicquotes); BSRegister::Debug('register_globals = ' . ini_get('register_globals')); $this->sanitizeInputData(); if (defined('ISSO_CHECK_POST_REFERER')) { $this->checkPostReferer(); } } // ################################################################### /** * Recursive XSS cleaner * * @param mixed Unsanitized REQUEST data * * @return mixed Sanitized data */ private function sanitizeDataRecursive($data) { foreach ($data AS $key => $value) { if (is_array($value)) { $data["$key"] = $this->sanitizeDataRecursive($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 * * @param string Unsanitzed text * * @return string Properly protected text that only encodes potential threats */ public 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() * * @param string Unsanitized text * * @return string Unicode-safe sanitized text with entities preserved */ public function entityEncode($text) { $text = str_replace('&', '&', $text); $text = $this->sanitize($text); return $text; } // ################################################################### /** * Takes text that has been processed for HTML and unsanitizes it * * @param string Text that needs to be turned back into HTML * * @return string Unsanitized text */ public 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() * * @param string Some string * @param bool Force magic quotes to be off * * @return string String that has slashes added */ public function escape($str, $force = true) { if ($this->magicquotes AND !$force) { if (BSRegister::GetType('Db')) { return BSRegister::GetType('Db')->escape_string(str_replace(array("\'", '\"'), array("'", '"'), $str)); } return $str; } else { if (BSRegister::GetType('Db')) { return BSRegister::GetType('Db')->escape_string($str); } return addslashes($str); } } // ################################################################### /** * Runs through all of the input data and sanitizes it. */ private function sanitizeInputData() { $this->in = $this->sanitizeDataRecursive(array_merge($_GET, $_POST, $_COOKIE)); } // ################################################################### /** * Sanitize function for something other than a string (which * everything is sanitized for if you use sanitizeInputData(). Cleaned * data is placed back into ISSO->in; this makes it so you don't have * to constantly intval() [etc.] data. * * @param array Array of elements to clean as varname => type */ public function inputCleanArray($vars) { foreach ($vars AS $varname => $type) { $this->inputClean($varname, $type); } } // ################################################################### /** * Sanitize function that does a single variable as oppoesd to an array * (see inputCleanArray() for more details) * * @param string Variable name in ISSO->in[] * @param integer Sanitization type constant */ public function inputClean($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. * * @param string Input variable * * @return string Escaped input */ public function inputEscape($varname) { if (isset($this->in["$varname"])) { return $this->escape($this->in["$varname"]); } else { return $this->escape(null); } } // ################################################################### /** * Cleaning function that does the work for inputClean(); this is * moved here so it can be used to clean things that aren't in * ISSO->in[] * * @param mixed Data * @param integer Sanitization type constant * * @return mixed Cleaned data */ public function clean($value, $type) { if (is_array($value)) { return $this->cleanArray($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_NONE) { 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 specified in BSInput::clean()'); return; } return $value; } // ################################################################### /** * Recursion function for ISSO->clean() * * @param array Uncleaned array * @param integer Sanitization type constant * * @return array Cleaned array of data */ private function cleanArray($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 */ private function checkPostReferer() { 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'); exit; } BSRegister::Debug('remote post check = ok'); } else { BSRegister::Debug('remote post check = FAILED'); } } } } /*=====================================================================*\ || ################################################################### || # $HeadURL$ || # $Id$ || ################################################################### \*=====================================================================*/ ?>