Deprecated: Assigning the return value of new by reference is deprecated in /home/bluestat/public_html/source/index.php on line 477
ISSO - Blob - ViewGit - Blue Static
<?php
/*=====================================================================*\
|| ###################################################################
|| # Blue Static ISSO Framework
|| # Copyright (c)2005-2009 Iris Studios, Inc.
|| #
|| # This program is free software; you can redistribute it and/or modify
|| # it under the terms of the GNU General Public License as published by
|| # the Free Software Foundation; version 2 of the License.
|| #
|| # This program is distributed in the hope that it will be useful, but
|| # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|| # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|| # more details.
|| #
|| # You should have received a copy of the GNU General Public License along
|| # with this program; if not, write to the Free Software Foundation, Inc.,
|| # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|| ###################################################################
\*=====================================================================*/

/**
 * Input sanitizer (Input.php)
 *
 * @package	ISSO
 */

/**#@+
 * 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_NONE', 64);

/**
 * Macro for using DB->escape_binary() without cleaning - used in API
 */
define('TYPE_BIN', 128);
/**#@-*/

/**
 * Input Sanitizer
 *
 * This class is responsible for cleaning input.
 *
 * @author		Blue Static
 * @copyright	Copyright (c)2005 - 2009, Blue Static
 * @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
		BSApp::debug('magic_quotes_gpc = ' . $this->magicquotes);
		BSApp::debug('register_globals = ' . ini_get('register_globals'));

		$this->_sanitizeInputData();
	}

	/**
	 * 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('&lt;', '&gt;', '&quot;', '&quot;'), $text);
		}
		else
		{
			return str_replace(array('<', '>', '"'), array('&lt;', '&gt;', '&quot;'), $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('&', '&amp;', $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('&lt;', '&gt;', '&quot;'), 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 Db->escapeString()
	 *
	 * @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)
	{
		$db = BSApp::$db;
		if ($this->magicquotes && !$force)
		{
			if ($db)
			{
				return $db->escapeString(str_replace(array("\'", '\"'), array("'", '"'), $str));
			}
			return $str;
		}
		else
		{
			if ($db)
			{
				return $db->escapeString($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 Input->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 Input->escape() on a variable on Input->in[]. This is just a
	 * short-hand wrapper so that queries can be shortened. When this is used,
	 * the actual value in Input->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
	 * Input->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
		{
			throw new Exception('Invalid clean type specified in BSInput::clean()');
			return;
		}

		return $value;
	}

	/**
	 * Recursion function for Input->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;
	}

	/**
	 * Returns the lowercase version of the HTTP method (post or get)
	 *
	 * @return	string	HTTP method
	 */
	public function getHttpMethod()
	{
		$method = strtolower($_SERVER['REQUEST_METHOD']);
		if (!in_array($method, array('get', 'post')))
		{
			throw new Exception('Invalid server request method: ' . $method);
		}
		return $method;
	}

	/**
	 * Checks to see if a POST refer is actually from us
	 */
	public function checkPostReferer()
	{
		if ($this->getHttpMethod() == 'post')
		{
			$host = ($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_ENV['HTTP_HOST'];

			if ($host && $_SERVER['HTTP_REFERER'])
			{
				$parts = parse_url($_SERVER['HTTP_REFERER']);
				$ourhost = $parts['host'] . (isset($parts['port']) ? ":$parts[port]" : '');

				if ($ourhost != $host)
				{
					throw new Exception('No external hosts are allowed to POST to this application');
					exit;
				}
				BSApp::debug('remote post check = ok');
			}
			else
			{
				BSApp::debug('remote post check = FAILED');
			}
		}
	}
}

?>