significant rewrite to Input class
some items will be moved to Security class
added set_cookie()
added UTF-8 uniformity to input
diff --git a/system/core/Input.php b/system/core/Input.php
index 51c12a8..0760dc8 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -27,31 +27,14 @@
  * @link		http://codeigniter.com/user_guide/libraries/input.html
  */
 class CI_Input {
-	var $use_xss_clean		= FALSE;
-	var $xss_hash			= '';
-	var $ip_address			= FALSE;
-	var $user_agent			= FALSE;
-	var $allow_get_array	= FALSE;
 
-	/* never allowed, string replacement */
-	var $never_allowed_str = array(
-									'document.cookie'	=> '[removed]',
-									'document.write'	=> '[removed]',
-									'.parentNode'		=> '[removed]',
-									'.innerHTML'		=> '[removed]',
-									'window.location'	=> '[removed]',
-									'-moz-binding'		=> '[removed]',
-									'<!--'				=> '&lt;!--',
-									'-->'				=> '--&gt;',
-									'<![CDATA['			=> '&lt;![CDATA['
-									);
-	/* never allowed, regex replacement */
-	var $never_allowed_regex = array(
-										"javascript\s*:"			=> '[removed]',
-										"expression\s*(\(|&\#40;)"	=> '[removed]', // CSS and IE
-										"vbscript\s*:"				=> '[removed]', // IE, surprise!
-										"Redirect\s+302"			=> '[removed]'
-									);
+	var $ip_address				= FALSE;
+	var $user_agent				= FALSE;
+	var $_allow_get_array		= FALSE;
+	var $_standardize_newlines	= TRUE;
+	var $_enable_xss			= FALSE; // Set automatically based on config setting
+	var $_enable_csrf			= FALSE; // Set automatically based on config setting
+
 
 	/**
 	* Constructor
@@ -65,166 +48,30 @@
 	{
 		log_message('debug', "Input Class Initialized");
 
-		$CFG =& load_class('Config');
-		$this->use_xss_clean	= ($CFG->item('global_xss_filtering') === TRUE) ? TRUE : FALSE;
-		$this->allow_get_array	= ($CFG->item('enable_query_strings') === TRUE) ? TRUE : FALSE;
+		$this->_allow_get_array	= (config_item('enable_query_strings') === TRUE) ? TRUE : FALSE;
+		$this->_enable_xss		= (config_item('global_xss_filtering') === TRUE) ? TRUE : FALSE;
+		$this->_enable_csrf		= (config_item('csrf_protection') === TRUE) ? TRUE : FALSE;
+
+		// Do we need to load the security class?
+		if ($this->_enable_xss == TRUE OR $this->_enable_csrf == TRUE)
+		{
+			$this->security =& load_class('Security');
+		}
+
+		// Do we need the Unicode class?
+		if (UTF8_ENABLED === TRUE)
+		{
+			global $UNI;
+			$this->uni =& $UNI;
+		}
+
+		// Sanitize global arrays
 		$this->_sanitize_globals();
 	}
 
 	// --------------------------------------------------------------------
 
 	/**
-	* Sanitize Globals
-	*
-	* This function does the following:
-	*
-	* Unsets $_GET data (if query strings are not enabled)
-	*
-	* Unsets all globals if register_globals is enabled
-	*
-	* Standardizes newline characters to \n
-	*
-	* @access	private
-	* @return	void
-	*/
-	function _sanitize_globals()
-	{
-		// Would kind of be "wrong" to unset any of these GLOBALS
-		$protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST', '_SESSION', '_ENV', 'GLOBALS', 'HTTP_RAW_POST_DATA',
-							'system_folder', 'application_folder', 'BM', 'EXT', 'CFG', 'URI', 'RTR', 'OUT', 'IN');
-
-		// Unset globals for security. 
-		// This is effectively the same as register_globals = off
-		foreach (array($_GET, $_POST, $_COOKIE, $_SERVER, $_FILES, $_ENV, (isset($_SESSION) && is_array($_SESSION)) ? $_SESSION : array()) as $global)
-		{
-			if ( ! is_array($global))
-			{
-				if ( ! in_array($global, $protected))
-				{
-					unset($GLOBALS[$global]);
-				}
-			}
-			else
-			{
-				foreach ($global as $key => $val)
-				{
-					if ( ! in_array($key, $protected))
-					{
-						unset($GLOBALS[$key]);
-					}
-
-					if (is_array($val))
-					{
-						foreach($val as $k => $v)
-						{
-							if ( ! in_array($k, $protected))
-							{
-								unset($GLOBALS[$k]);
-							}
-						}
-					}
-				}
-			}
-		}
-
-		// Is $_GET data allowed? If not we'll set the $_GET to an empty array
-		if ($this->allow_get_array == FALSE)
-		{
-			$_GET = array();
-		}
-		else
-		{
-			$_GET = $this->_clean_input_data($_GET);
-		}
-
-		// Clean $_POST Data
-		$_POST = $this->_clean_input_data($_POST);
-
-		// Clean $_COOKIE Data
-		// Also get rid of specially treated cookies that might be set by a server
-		// or silly application, that are of no use to a CI application anyway
-		// but that when present will trip our 'Disallowed Key Characters' alarm
-		// http://www.ietf.org/rfc/rfc2109.txt
-		// note that the key names below are single quoted strings, and are not PHP variables
-		unset($_COOKIE['$Version']);
-		unset($_COOKIE['$Path']);
-		unset($_COOKIE['$Domain']);
-		$_COOKIE = $this->_clean_input_data($_COOKIE);
-
-		log_message('debug', "Global POST and COOKIE data sanitized");
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Clean Input Data
-	*
-	* This is a helper function. It escapes data and
-	* standardizes newline characters to \n
-	*
-	* @access	private
-	* @param	string
-	* @return	string
-	*/
-	function _clean_input_data($str)
-	{
-		if (is_array($str))
-		{
-			$new_array = array();
-			foreach ($str as $key => $val)
-			{
-				$new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
-			}
-			return $new_array;
-		}
-
-		// We strip slashes if magic quotes is on to keep things consistent
-		if (get_magic_quotes_gpc())
-		{
-			$str = stripslashes($str);
-		}
-
-		// Should we filter the input data?
-		if ($this->use_xss_clean === TRUE)
-		{
-			$str = $this->xss_clean($str);
-		}
-
-		// Standardize newlines
-		if (strpos($str, "\r") !== FALSE)
-		{
-			$str = str_replace(array("\r\n", "\r"), "\n", $str);
-		}
-
-		return $str;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Clean Keys
-	*
-	* This is a helper function. To prevent malicious users
-	* from trying to exploit keys we make sure that keys are
-	* only named with alpha-numeric text and a few other items.
-	*
-	* @access	private
-	* @param	string
-	* @return	string
-	*/
-	function _clean_input_keys($str)
-	{
-		if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str))
-		{
-			exit('Disallowed Key Characters.');
-		}
-
-		return $str;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	* Fetch from array
 	*
 	* This is a helper function to retrieve values from global arrays
@@ -244,7 +91,8 @@
 
 		if ($xss_clean === TRUE)
 		{
-			return $this->xss_clean($array[$index]);
+			$_security =& load_class('Security');
+			return $_security->xss_clean($array[$index]);
 		}
 
 		return $array[$index];
@@ -280,6 +128,7 @@
 		return $this->_fetch_from_array($_POST, $index, $xss_clean);
 	}
 
+
 	// --------------------------------------------------------------------
 
 	/**
@@ -317,6 +166,68 @@
 		return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
 	}
 
+	// ------------------------------------------------------------------------
+
+	/**
+	* Set cookie
+	*
+	* Accepts six parameter, or you can submit an associative
+	* array in the first parameter containing all the values.
+	*
+	* @access	public
+	* @param	mixed
+	* @param	string	the value of the cookie
+	* @param	string	the number of seconds until expiration
+	* @param	string	the cookie domain.  Usually:  .yourdomain.com
+	* @param	string	the cookie path
+	* @param	string	the cookie prefix
+	* @return	void
+	*/
+	function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '')
+	{
+		if (is_array($name))
+		{
+			foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'name') as $item)
+			{
+				if (isset($name[$item]))
+				{
+					$$item = $name[$item];
+				}
+			}
+		}
+
+		if ($prefix == '' AND config_item('cookie_prefix') != '')
+		{
+			$prefix = config_item('cookie_prefix');
+		}
+		if ($domain == '' AND config_item('cookie_domain') != '')
+		{
+			$domain = config_item('cookie_domain');
+		}
+		if ($path == '/' AND config_item('cookie_path') != '/')
+		{
+			$path = config_item('cookie_path');
+		}
+
+		if ( ! is_numeric($expire))
+		{
+			$expire = time() - 86500;
+		}
+		else
+		{
+			if ($expire > 0)
+			{
+				$expire = time() + $expire;
+			}
+			else
+			{
+				$expire = 0;
+			}
+		}
+
+		setcookie($prefix.$name, $value, $expire, $path, $domain, 0);
+	}
+
 	// --------------------------------------------------------------------
 
 	/**
@@ -453,580 +364,155 @@
 	// --------------------------------------------------------------------
 
 	/**
-	* Filename Security
+	* Sanitize Globals
 	*
-	* @access	public
-	* @param	string
-	* @return	string
+	* This function does the following:
+	*
+	* Unsets $_GET data (if query strings are not enabled)
+	*
+	* Unsets all globals if register_globals is enabled
+	*
+	* Standardizes newline characters to \n
+	*
+	* @access	private
+	* @return	void
 	*/
-	function filename_security($str)
+	function _sanitize_globals()
 	{
-		$bad = array(
-						"../",
-						"./",
-						"<!--",
-						"-->",
-						"<",
-						">",
-						"'",
-						'"',
-						'&',
-						'$',
-						'#',
-						'{',
-						'}',
-						'[',
-						']',
-						'=',
-						';',
-						'?',
-						"%20",
-						"%22",
-						"%3c",		// <
-						"%253c", 	// <
-						"%3e", 		// >
-						"%0e", 		// >
-						"%28", 		// (  
-						"%29", 		// ) 
-						"%2528", 	// (
-						"%26", 		// &
-						"%24", 		// $
-						"%3f", 		// ?
-						"%3b", 		// ;
-						"%3d"		// =
-					);
+		// It would be "wrong" to unset any of these GLOBALS.
+		$protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST', '_SESSION', '_ENV', 'GLOBALS', 'HTTP_RAW_POST_DATA',
+							'system_folder', 'application_folder', 'BM', 'EXT', 'CFG', 'URI', 'RTR', 'OUT', 'IN');
 
-		return stripslashes(str_replace($bad, '', $str));
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* XSS Clean
-	*
-	* Sanitizes data so that Cross Site Scripting Hacks can be
-	* prevented.  This function does a fair amount of work but
-	* it is extremely thorough, designed to prevent even the
-	* most obscure XSS attempts.  Nothing is ever 100% foolproof,
-	* of course, but I haven't been able to get anything passed
-	* the filter.
-	*
-	* Note: This function should only be used to deal with data
-	* upon submission.  It's not something that should
-	* be used for general runtime processing.
-	*
-	* This function was based in part on some code and ideas I
-	* got from Bitflux: http://blog.bitflux.ch/wiki/XSS_Prevention
-	*
-	* To help develop this script I used this great list of
-	* vulnerabilities along with a few other hacks I've
-	* harvested from examining vulnerabilities in other programs:
-	* http://ha.ckers.org/xss.html
-	*
-	* @access	public
-	* @param	string
-	* @return	string
-	*/
-	function xss_clean($str, $is_image = FALSE)
-	{
-		/*
-		* Is the string an array?
-		*
-		*/
-		if (is_array($str))
+		// Unset globals for securiy. 
+		// This is effectively the same as register_globals = off
+		foreach (array($_GET, $_POST, $_COOKIE) as $global)
 		{
-			while (list($key) = each($str))
+			if ( ! is_array($global))
 			{
-				$str[$key] = $this->xss_clean($str[$key]);
+				if ( ! in_array($global, $protected))
+				{
+					global $$global;
+					$$global = NULL;
+				}
 			}
-
-			return $str;
+			else
+			{
+				foreach ($global as $key => $val)
+				{
+					if ( ! in_array($key, $protected))
+					{
+						global $$key;
+						$$key = NULL;
+					}
+				}
+			}
 		}
 
-		/*
-		* Remove Invisible Characters
-		*/
-		$str = $this->_remove_invisible_characters($str);
-
-		/*
-		* Protect GET variables in URLs
-		*/
-
-		// 901119URL5918AMP18930PROTECT8198
-
-		$str = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-]+)|i', $this->xss_hash()."\\1=\\2", $str);
-
-		/*
-		* Validate standard character entities
-		*
-		* Add a semicolon if missing.  We do this to enable
-		* the conversion of entities to ASCII later.
-		*
-		*/
-		$str = preg_replace('#(&\#?[0-9a-z]{2,})([\x00-\x20])*;?#i', "\\1;\\2", $str);
-
-		/*
-		* Validate UTF16 two byte encoding (x00) 
-		*
-		* Just as above, adds a semicolon if missing.
-		*
-		*/
-		$str = preg_replace('#(&\#x?)([0-9A-F]+);?#i',"\\1\\2;",$str);
-
-		/*
-		* Un-Protect GET variables in URLs
-		*/
-		$str = str_replace($this->xss_hash(), '&', $str);
-
-		/*
-		* URL Decode
-		*
-		* Just in case stuff like this is submitted:
-		*
-		* <a href="http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D">Google</a>
-		*
-		* Note: Use rawurldecode() so it does not remove plus signs
-		*
-		*/
-		$str = rawurldecode($str);
-
-		/*
-		* Convert character entities to ASCII 
-		*
-		* This permits our tests below to work reliably.
-		* We only convert entities that are within tags since
-		* these are the ones that will pose security problems.
-		*
-		*/
-
-		$str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str);
-
-		$str = preg_replace_callback("/<\w+.*?(?=>|<|$)/si", array($this, '_html_entity_decode_callback'), $str);
-
-		/*
-		* Remove Invisible Characters Again!
-		*/
-		$str = $this->_remove_invisible_characters($str);
-
-		/*
-		* Convert all tabs to spaces
-		*
-		* This prevents strings like this: ja	vascript
-		* NOTE: we deal with spaces between characters later.
-		* NOTE: preg_replace was found to be amazingly slow here on large blocks of data,
-		* so we use str_replace.
-		*
-		*/
-
- 		if (strpos($str, "\t") !== FALSE)
+		// Is $_GET data allowed? If not we'll set the $_GET to an empty array
+		if ($this->_allow_get_array == FALSE)
 		{
-			$str = str_replace("\t", ' ', $str);
-		}
-
-		/*
-		* Capture converted string for later comparison
-		*/
-		$converted_string = $str;
-
-		/*
-		* Not Allowed Under Any Conditions
-		*/
-
-		foreach ($this->never_allowed_str as $key => $val)
-		{
-			$str = str_replace($key, $val, $str);   
-		}
-
-		foreach ($this->never_allowed_regex as $key => $val)
-		{
-			$str = preg_replace("#".$key."#i", $val, $str);   
-		}
-
-		/*
-		* Makes PHP tags safe
-		*
-		*  Note: XML tags are inadvertently replaced too:
-		*
-		*	<?xml
-		*
-		* But it doesn't seem to pose a problem.
-		*
-		*/
-		if ($is_image === TRUE)
-		{
-			// Images have a tendency to have the PHP short opening and closing tags every so often
-			// so we skip those and only do the long opening tags.
-			$str = preg_replace('/<\?(php)/i', "&lt;?\\1", $str);
+			$_GET = array();
 		}
 		else
 		{
-			$str = str_replace(array('<?', '?'.'>'),  array('&lt;?', '?&gt;'), $str);
-		}
-
-		/*
-		* Compact any exploded words
-		*
-		* This corrects words like:  j a v a s c r i p t
-		* These words are compacted back to their correct state.
-		*
-		*/
-		$words = array('javascript', 'expression', 'vbscript', 'script', 'applet', 'alert', 'document', 'write', 'cookie', 'window');
-		foreach ($words as $word)
-		{
-			$temp = '';
-
-			for ($i = 0, $wordlen = strlen($word); $i < $wordlen; $i++)
+			if (is_array($_GET) AND count($_GET) > 0)
 			{
-				$temp .= substr($word, $i, 1)."\s*";
-			}
-
-			// We only want to do this when it is followed by a non-word character
-			// That way valid stuff like "dealer to" does not become "dealerto"
-			$str = preg_replace_callback('#('.substr($temp, 0, -3).')(\W)#is', array($this, '_compact_exploded_words'), $str);
-		}
-
-		/*
-		* Remove disallowed Javascript in links or img tags
-		* We used to do some version comparisons and use of stripos for PHP5, but it is dog slow compared
-		* to these simplified non-capturing preg_match(), especially if the pattern exists in the string
-		*/
-		do
-		{
-			$original = $str;
-
-			if (preg_match("/<a/i", $str))
-			{
-				$str = preg_replace_callback("#<a\s+([^>]*?)(>|$)#si", array($this, '_js_link_removal'), $str);
-			}
-
-			if (preg_match("/<img/i", $str))
-			{
-				$str = preg_replace_callback("#<img\s+([^>]*?)(\s?/?>|$)#si", array($this, '_js_img_removal'), $str);
-			}
-
-			if (preg_match("/script/i", $str) OR preg_match("/xss/i", $str))
-			{
-				$str = preg_replace("#<(/*)(script|xss)(.*?)\>#si", '[removed]', $str);
-			}
-		}
-		while($original != $str);
-
-		unset($original);
-
-		/*
-		* Remove JavaScript Event Handlers
-		*
-		* Note: This code is a little blunt.  It removes
-		* the event handler and anything up to the closing >,
-		* but it's unlikely to be a problem.
-		*
-		*/
-		$event_handlers = array('[^a-z_\-]on\w*','xmlns');
-
-		if ($is_image === TRUE)
-		{
-			/*
-			* Adobe Photoshop puts XML metadata into JFIF images, including namespacing, 
-			* so we have to allow this for images. -Paul
-			*/
-			unset($event_handlers[array_search('xmlns', $event_handlers)]);
-		}
-
-		$str = preg_replace("#<([^><]+?)(".implode('|', $event_handlers).")(\s*=\s*[^><]*)([><]*)#i", "<\\1\\4", $str);
-
-		/*
-		* Sanitize naughty HTML elements
-		*
-		* If a tag containing any of the words in the list
-		* below is found, the tag gets converted to entities.
-		*
-		* So this: <blink>
-		* Becomes: &lt;blink&gt;
-		*
-		*/
-		$naughty = 'alert|applet|audio|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|isindex|layer|link|meta|object|plaintext|style|script|textarea|title|video|xml|xss';
-		$str = preg_replace_callback('#<(/*\s*)('.$naughty.')([^><]*)([><]*)#is', array($this, '_sanitize_naughty_html'), $str);
-
-		/*
-		* Sanitize naughty scripting elements
-		*
-		* Similar to above, only instead of looking for
-		* tags it looks for PHP and JavaScript commands
-		* that are disallowed.  Rather than removing the
-		* code, it simply converts the parenthesis to entities
-		* rendering the code un-executable.
-		*
-		* For example:	eval('some code')
-		* Becomes:		eval&#40;'some code'&#41;
-		*
-		*/
-		$str = preg_replace('#(alert|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', "\\1\\2&#40;\\3&#41;", $str);
-
-		/*
-		* Final clean up
-		*
-		* This adds a bit of extra precaution in case
-		* something got through the above filters
-		*
-		*/
-		foreach ($this->never_allowed_str as $key => $val)
-		{
-			$str = str_replace($key, $val, $str);   
-		}
-
-		foreach ($this->never_allowed_regex as $key => $val)
-		{
-			$str = preg_replace("#".$key."#i", $val, $str);
-		}
-
-		/*
-		*  Images are Handled in a Special Way
-		*  - Essentially, we want to know that after all of the character conversion is done whether
-		*  any unwanted, likely XSS, code was found.  If not, we return TRUE, as the image is clean.
-		*  However, if the string post-conversion does not matched the string post-removal of XSS,
-		*  then it fails, as there was unwanted XSS code found and removed/changed during processing.
-		*/
-
-		if ($is_image === TRUE)
-		{
-			if ($str == $converted_string)
-			{
-				return TRUE;
-			}
-			else
-			{
-				return FALSE;
+				foreach($_GET as $key => $val)
+				{
+					$_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
+				}
 			}
 		}
 
-		log_message('debug', "XSS Filtering completed");
-		return $str;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Random Hash for protecting URLs
-	*
-	* @access	public
-	* @return	string
-	*/
-	function xss_hash()
-	{
-		if ($this->xss_hash == '')
+		// Clean $_POST Data
+		if (is_array($_POST) AND count($_POST) > 0)
 		{
-			if (phpversion() >= 4.2)
-				mt_srand();
-			else
-				mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff);
-
-			$this->xss_hash = md5(time() + mt_rand(0, 1999999999));
+			foreach($_POST as $key => $val)
+			{
+				$_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
+			}
 		}
 
-		return $this->xss_hash;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Remove Invisible Characters
-	*
-	* This prevents sandwiching null characters
-	* between ascii characters, like Java\0script.
-	*
-	* @access	public
-	* @param	string
-	* @return	string
-	*/
-	function _remove_invisible_characters($str)
-	{
-		static $non_displayables;
-
-		if ( ! isset($non_displayables))
+		// Clean $_COOKIE Data
+		if (is_array($_COOKIE) AND count($_COOKIE) > 0)
 		{
-			// every control character except newline (dec 10), carriage return (dec 13), and horizontal tab (dec 09),
-			$non_displayables = array(
-										'/%0[0-8bcef]/',			// url encoded 00-08, 11, 12, 14, 15
-										'/%1[0-9a-f]/',				// url encoded 16-31
-										'/[\x00-\x08]/',			// 00-08
-										'/\x0b/', '/\x0c/',			// 11, 12
-										'/[\x0e-\x1f]/'				// 14-31
-									);
+			// Also get rid of specially treated cookies that might be set by a server
+			// or silly application, that are of no use to a CI application anyway
+			// but that when present will trip our 'Disallowed Key Characters' alarm
+			// http://www.ietf.org/rfc/rfc2109.txt
+			// note that the key names below are single quoted strings, and are not PHP variables
+			unset($_COOKIE['$Version']);
+			unset($_COOKIE['$Path']);
+			unset($_COOKIE['$Domain']);
+
+			foreach($_COOKIE as $key => $val)
+			{
+				$_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
+			}
 		}
 
-		do
+		// Sanitize PHP_SELF
+		$_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
+
+
+		// CSRF Protection check
+		if ($this->_enable_csrf == TRUE)
 		{
-			$cleaned = $str;
-			$str = preg_replace($non_displayables, '', $str);
+			$this->security->csrf_verify();
 		}
-		while ($cleaned != $str);
 
-		return $str;
+		log_message('debug', "Global POST and COOKIE data sanitized");
 	}
 
 	// --------------------------------------------------------------------
 
 	/**
-	* Compact Exploded Words
+	* Clean Input Data
 	*
-	* Callback function for xss_clean() to remove whitespace from
-	* things like j a v a s c r i p t
-	*
-	* @access	public
-	* @param	type
-	* @return	type
-	*/
-	function _compact_exploded_words($matches)
-	{
-		return preg_replace('/\s+/s', '', $matches[1]).$matches[2];
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Sanitize Naughty HTML
-	*
-	* Callback function for xss_clean() to remove naughty HTML elements
-	*
-	* @access	private
-	* @param	array
-	* @return	string
-	*/
-	function _sanitize_naughty_html($matches)
-	{
-		// encode opening brace
-		$str = '&lt;'.$matches[1].$matches[2].$matches[3];
-
-		// encode captured opening or closing brace to prevent recursive vectors
-		$str .= str_replace(array('>', '<'), array('&gt;', '&lt;'), $matches[4]);
-
-		return $str;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* JS Link Removal
-	*
-	* Callback function for xss_clean() to sanitize links
-	* This limits the PCRE backtracks, making it more performance friendly
-	* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in
-	* PHP 5.2+ on link-heavy strings
-	*
-	* @access	private
-	* @param	array
-	* @return	string
-	*/
-	function _js_link_removal($match)
-	{
-		$attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]));
-		return str_replace($match[1], preg_replace("#href=.*?(alert\(|alert&\#40;|javascript\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]);
-	}
-
-	/**
-	* JS Image Removal
-	*
-	* Callback function for xss_clean() to sanitize image tags
-	* This limits the PCRE backtracks, making it more performance friendly
-	* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in
-	* PHP 5.2+ on image tag heavy strings
-	*
-	* @access	private
-	* @param	array
-	* @return	string
-	*/
-	function _js_img_removal($match)
-	{
-		$attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]));
-		return str_replace($match[1], preg_replace("#src=.*?(alert\(|alert&\#40;|javascript\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Attribute Conversion
-	*
-	* Used as a callback for XSS Clean
-	*
-	* @access	public
-	* @param	array
-	* @return	string
-	*/
-	function _convert_attribute($match)
-	{
-		return str_replace(array('>', '<', '\\'), array('&gt;', '&lt;', '\\\\'), $match[0]);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* HTML Entity Decode Callback
-	*
-	* Used as a callback for XSS Clean
-	*
-	* @access	public
-	* @param	array
-	* @return	string
-	*/
-	function _html_entity_decode_callback($match)
-	{
-		$CFG =& load_class('Config');
-		$charset = $CFG->item('charset');
-
-		return $this->_html_entity_decode($match[0], strtoupper($charset));
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* HTML Entities Decode
-	*
-	* This function is a replacement for html_entity_decode()
-	*
-	* In some versions of PHP the native function does not work
-	* when UTF-8 is the specified character set, so this gives us
-	* a work-around.  More info here:
-	* http://bugs.php.net/bug.php?id=25670
+	* This is a helper function. It escapes data and
+	* standardizes newline characters to \n
 	*
 	* @access	private
 	* @param	string
-	* @param	string
 	* @return	string
 	*/
-	/* -------------------------------------------------
-	/*  Replacement for html_entity_decode()
-	/* -------------------------------------------------*/
-
-	/*
-	NOTE: html_entity_decode() has a bug in some PHP versions when UTF-8 is the
-	character set, and the PHP developers said they were not back porting the
-	fix to versions other than PHP 5.x.
-	*/
-	function _html_entity_decode($str, $charset='UTF-8')
+	function _clean_input_data($str)
 	{
-		if (stristr($str, '&') === FALSE) return $str;
-
-		// The reason we are not using html_entity_decode() by itself is because
-		// while it is not technically correct to leave out the semicolon
-		// at the end of an entity most browsers will still interpret the entity
-		// correctly.  html_entity_decode() does not convert entities without
-		// semicolons, so we are left with our own little solution here. Bummer.
-
-		if (function_exists('html_entity_decode') && (strtolower($charset) != 'utf-8' OR version_compare(phpversion(), '5.0.0', '>=')))
+		if (is_array($str))
 		{
-			$str = html_entity_decode($str, ENT_COMPAT, $charset);
-			$str = preg_replace('~&#x(0*[0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str);
-			return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str);
+			$new_array = array();
+			foreach ($str as $key => $val)
+			{
+				$new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
+			}
+			return $new_array;
 		}
 
-		// Numeric Entities
-		$str = preg_replace('~&#x(0*[0-9a-f]{2,5});{0,1}~ei', 'chr(hexdec("\\1"))', $str);
-		$str = preg_replace('~&#([0-9]{2,4});{0,1}~e', 'chr(\\1)', $str);
-
-		// Literal Entities - Slightly slow so we do another check
-		if (stristr($str, '&') === FALSE)
+		// We strip slashes if magic quotes is on to keep things consistent
+		if (get_magic_quotes_gpc())
 		{
-			$str = strtr($str, array_flip(get_html_translation_table(HTML_ENTITIES)));
+			$str = stripslashes($str);
+		}
+
+		// Clean UTF-8 if supported
+		if (UTF8_ENABLED === TRUE)
+		{
+			$str = $this->uni->clean_string($str);
+		}
+
+		// Should we filter the input data?
+		if ($this->_enable_xss === TRUE)
+		{
+			$str = $this->security->xss_clean($str);
+		}
+
+		// Standardize newlines if needed
+		if ($this->_standardize_newlines == TRUE)
+		{
+			if (strpos($str, "\r") !== FALSE)
+			{
+				$str = str_replace(array("\r\n", "\r"), "\n", $str);
+			}
 		}
 
 		return $str;
@@ -1035,30 +521,31 @@
 	// --------------------------------------------------------------------
 
 	/**
-	* Filter Attributes
+	* Clean Keys
 	*
-	* Filters tag attributes for consistency and safety
+	* This is a helper function. To prevent malicious users
+	* from trying to exploit keys we make sure that keys are
+	* only named with alpha-numeric text and a few other items.
 	*
-	* @access	public
+	* @access	private
 	* @param	string
 	* @return	string
 	*/
-	function _filter_attributes($str)
+	function _clean_input_keys($str)
 	{
-		$out = '';
-
-		if (preg_match_all('#\s*[a-z\-]+\s*=\s*(\042|\047)([^\\1]*?)\\1#is', $str, $matches))
+		if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str))
 		{
-			foreach ($matches[0] as $match)
-			{
-				$out .= preg_replace("#/\*.*?\*/#s", '', $match);
-			}
+			exit('Disallowed Key Characters.');
 		}
 
-		return $out;
-	}
+		// Clean UTF-8 if supported
+		if (UTF8_ENABLED === TRUE)
+		{
+			$str = $this->uni->clean_string($str);
+		}
 
-	// --------------------------------------------------------------------
+		return $str;
+	}
 
 }
 // END Input class