diff options
Diffstat (limited to 'system/libraries/Input.php')
-rw-r--r-- | system/libraries/Input.php | 222 |
1 files changed, 112 insertions, 110 deletions
diff --git a/system/libraries/Input.php b/system/libraries/Input.php index 9b012d320..e3515661d 100644 --- a/system/libraries/Input.php +++ b/system/libraries/Input.php @@ -32,7 +32,7 @@ class CI_Input { var $ip_address = FALSE;
var $user_agent = FALSE;
var $allow_get_array = FALSE;
-
+
/**
* Constructor
*
@@ -40,19 +40,19 @@ class CI_Input { * and whether to allow the $_GET array
*
* @access public
- */
+ */
function CI_Input()
- {
+ {
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 = ($CFG->item('enable_query_strings') === TRUE) ? TRUE : FALSE;
$this->_sanitize_globals();
}
-
+
// --------------------------------------------------------------------
-
+
/**
* Sanitize Globals
*
@@ -72,7 +72,7 @@ class CI_Input { // 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)
@@ -92,7 +92,7 @@ class CI_Input { {
unset($GLOBALS[$key]);
}
-
+
if (is_array($val))
{
foreach($val as $k => $v)
@@ -103,7 +103,7 @@ class CI_Input { }
}
}
- }
+ }
}
}
@@ -122,30 +122,30 @@ class CI_Input { }
}
}
-
+
// Clean $_POST Data
if (is_array($_POST) AND count($_POST) > 0)
{
foreach($_POST as $key => $val)
- {
+ {
$_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
- }
+ }
}
-
+
// Clean $_COOKIE Data
if (is_array($_COOKIE) AND count($_COOKIE) > 0)
{
foreach($_COOKIE as $key => $val)
- {
+ {
$_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
- }
+ }
}
-
+
log_message('debug', "Global POST and COOKIE data sanitized");
- }
-
+ }
+
// --------------------------------------------------------------------
-
+
/**
* Clean Input Data
*
@@ -155,7 +155,7 @@ class CI_Input { * @access private
* @param string
* @return string
- */
+ */
function _clean_input_data($str)
{
if (is_array($str))
@@ -167,25 +167,25 @@ class CI_Input { }
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
return preg_replace("/\015\012|\015|\012/", "\n", $str);
}
-
+
// --------------------------------------------------------------------
-
+
/**
* Clean Keys
*
@@ -198,7 +198,7 @@ class CI_Input { * @return string
*/
function _clean_input_keys($str)
- {
+ {
if (! preg_match("/^[a-z0-9:_\/-]+$/i", $str))
{
exit('Disallowed Key Characters.');
@@ -208,7 +208,7 @@ class CI_Input { }
// --------------------------------------------------------------------
-
+
/**
* Fetch an item from the GET array
*
@@ -218,7 +218,7 @@ class CI_Input { * @return string
*/
function get($index = '', $xss_clean = FALSE)
- {
+ {
if (! isset($_GET[$index]))
{
return FALSE;
@@ -229,7 +229,7 @@ class CI_Input { if (is_array($_GET[$index]))
{
foreach($_GET[$index] as $key => $val)
- {
+ {
$_GET[$index][$key] = $this->xss_clean($val);
}
}
@@ -241,9 +241,9 @@ class CI_Input { return $_GET[$index];
}
-
+
// --------------------------------------------------------------------
-
+
/**
* Fetch an item from the POST array
*
@@ -253,7 +253,7 @@ class CI_Input { * @return string
*/
function post($index = '', $xss_clean = FALSE)
- {
+ {
if (! isset($_POST[$index]))
{
return FALSE;
@@ -264,7 +264,7 @@ class CI_Input { if (is_array($_POST[$index]))
{
foreach($_POST[$index] as $key => $val)
- {
+ {
$_POST[$index][$key] = $this->xss_clean($val);
}
}
@@ -276,9 +276,9 @@ class CI_Input { return $_POST[$index];
}
-
+
// --------------------------------------------------------------------
-
+
/**
* Fetch an item from the COOKIE array
*
@@ -303,7 +303,7 @@ class CI_Input { {
$cookie[$key] = $this->xss_clean($val);
}
-
+
return $cookie;
}
else
@@ -318,7 +318,7 @@ class CI_Input { }
// --------------------------------------------------------------------
-
+
/**
* Fetch an item from the SERVER array
*
@@ -328,7 +328,7 @@ class CI_Input { * @return string
*/
function server($index = '', $xss_clean = FALSE)
- {
+ {
if (! isset($_SERVER[$index]))
{
return FALSE;
@@ -338,12 +338,12 @@ class CI_Input { {
return $this->xss_clean($_SERVER[$index]);
}
-
+
return $_SERVER[$index];
}
-
+
// --------------------------------------------------------------------
-
+
/**
* Fetch the IP Address
*
@@ -356,7 +356,7 @@ class CI_Input { {
return $this->ip_address;
}
-
+
if ($this->server('REMOTE_ADDR') AND $this->server('HTTP_CLIENT_IP'))
{
$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
@@ -373,29 +373,29 @@ class CI_Input { {
$this->ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
-
+
if ($this->ip_address === FALSE)
{
$this->ip_address = '0.0.0.0';
return $this->ip_address;
}
-
+
if (strstr($this->ip_address, ','))
{
$x = explode(',', $this->ip_address);
$this->ip_address = end($x);
}
-
+
if (! $this->valid_ip($this->ip_address))
{
$this->ip_address = '0.0.0.0';
}
-
+
return $this->ip_address;
}
-
+
// --------------------------------------------------------------------
-
+
/**
* Validate IP Address
*
@@ -408,7 +408,7 @@ class CI_Input { function valid_ip($ip)
{
$ip_segments = explode('.', $ip);
-
+
// Always 4 segments needed
if (count($ip_segments) != 4)
{
@@ -429,12 +429,12 @@ class CI_Input { return FALSE;
}
}
-
+
return TRUE;
}
-
+
// --------------------------------------------------------------------
-
+
/**
* User Agent
*
@@ -447,14 +447,14 @@ class CI_Input { {
return $this->user_agent;
}
-
+
$this->user_agent = (! isset($_SERVER['HTTP_USER_AGENT'])) ? FALSE : $_SERVER['HTTP_USER_AGENT'];
-
+
return $this->user_agent;
}
-
+
// --------------------------------------------------------------------
-
+
/**
* Filename Security
*
@@ -497,13 +497,13 @@ class CI_Input { "%3f", // ?
"%3b", // ;
"%3d" // =
- );
-
- return stripslashes(str_replace($bad, '', $str));
+ );
+
+ return stripslashes(str_replace($bad, '', $str));
}
-
+
// --------------------------------------------------------------------
-
+
/**
* XSS Clean
*
@@ -542,10 +542,10 @@ class CI_Input { {
$str[$key] = $this->xss_clean($str[$key]);
}
-
+
return $str;
}
-
+
/*
* Remove Null Characters
*
@@ -572,7 +572,7 @@ class CI_Input { *
*/
$str = preg_replace('#(&\#?[0-9a-z]+)[\x00-\x20]*;?#i', "\\1;", $str);
-
+
/*
* Validate UTF16 two byte encoding (x00)
*
@@ -586,7 +586,7 @@ class CI_Input { */
$str = str_replace($this->xss_hash(), '&', $str);
-
+
/*
* URL Decode
*
@@ -596,9 +596,9 @@ class CI_Input { *
* Note: Use rawurldecode() so it does not remove plus signs
*
- */
+ */
$str = rawurldecode($str);
-
+
/*
* Convert character entities to ASCII
*
@@ -607,15 +607,15 @@ class CI_Input { * these are the ones that will pose security problems.
*
*/
-
+
$str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_attribute_conversion'), $str);
$str = preg_replace_callback("/<([\w]+)[^>]*>/si", array($this, '_html_entity_decode_callback'), $str);
/*
-
+
Old Code that when modified to use preg_replace()'s above became more efficient memory-wise
-
+
if (preg_match_all("/[a-z]+=([\'\"]).*?\\1/si", $str, $matches))
{
for ($i = 0; $i < count($matches[0]); $i++)
@@ -639,7 +639,7 @@ class CI_Input { }
}
*/
-
+
/*
* Convert all tabs to spaces
*
@@ -649,12 +649,14 @@ class CI_Input { * so we use str_replace.
*
*/
-
- $str = str_replace("\t", " ", $str);
+
+ if (strpos($str, "\t") !== FALSE) {
+ $str = str_replace("\t", " ", $str);
+ }
/*
* Not Allowed Under Any Conditions
- */
+ */
$bad = array(
'document.cookie' => '[removed]',
'document.write' => '[removed]',
@@ -677,12 +679,12 @@ class CI_Input { "expression\s*\(" => '[removed]', // CSS and IE
"Redirect\s+302" => '[removed]'
);
-
+
foreach ($bad as $key => $val)
{
$str = preg_replace("#".$key."#i", $val, $str);
}
-
+
/*
* Makes PHP tags safe
*
@@ -692,16 +694,16 @@ class CI_Input { *
* But it doesn't seem to pose a problem.
*
- */
+ */
$str = str_replace(array('<?php', '<?PHP', '<?', '?'.'>'), array('<?php', '<?PHP', '<?', '?>'), $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)
{
@@ -710,31 +712,31 @@ class CI_Input { {
$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('#('.substr($temp, 0, -3).')(\W)#ise', "preg_replace('/\s+/s', '', '\\1').'\\2'", $str);
}
-
+
/*
* Remove disallowed Javascript in links or img tags
*/
do
{
$original = $str;
-
+
if ((version_compare(PHP_VERSION, '5.0', '>=') === TRUE && stripos($str, '</a>') !== FALSE) OR
preg_match("/<\/a>/i", $str))
{
$str = preg_replace_callback("#<a.*?</a>#si", array($this, '_js_link_removal'), $str);
}
-
+
if ((version_compare(PHP_VERSION, '5.0', '>=') === TRUE && stripos($str, '<img') !== FALSE) OR
preg_match("/img/i", $str))
{
$str = preg_replace_callback("#<img.*?".">#si", array($this, '_js_img_removal'), $str);
}
-
+
if ((version_compare(PHP_VERSION, '5.0', '>=') === TRUE && (stripos($str, 'script') !== FALSE OR stripos($str, 'xss') !== FALSE)) OR
preg_match("/(script|xss)/i", $str))
{
@@ -742,7 +744,7 @@ class CI_Input { }
}
while($original != $str);
-
+
unset($original);
/*
@@ -752,10 +754,10 @@ class CI_Input { * the event handler and anything up to the closing >,
* but it's unlikely to be a problem.
*
- */
+ */
$event_handlers = array('onblur','onchange','onclick','onfocus','onload','onmouseover','onmouseup','onmousedown','onselect','onsubmit','onunload','onkeypress','onkeydown','onkeyup','onresize', 'xmlns');
$str = preg_replace("#<([^>]+)(".implode('|', $event_handlers).")([^>]*)>#iU", "<\\1\\2\\3>", $str);
-
+
/*
* Sanitize naughty HTML elements
*
@@ -765,9 +767,9 @@ class CI_Input { * So this: <blink>
* Becomes: <blink>
*
- */
+ */
$str = preg_replace('#<(/*\s*)(alert|applet|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|layer|link|meta|object|plaintext|style|script|textarea|title|xml|xss)([^>]*)>#is', "<\\1\\2\\3>", $str);
-
+
/*
* Sanitize naughty scripting elements
*
@@ -782,14 +784,14 @@ class CI_Input { *
*/
$str = preg_replace('#(alert|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', "\\1\\2(\\3)", $str);
-
+
/*
* Final clean up
*
* This adds a bit of extra precaution in case
* something got through the above filters
*
- */
+ */
$bad = array(
'document.cookie' => '[removed]',
'document.write' => '[removed]',
@@ -812,19 +814,19 @@ class CI_Input { "expression\s*\(" => '[removed]', // CSS and IE
"Redirect\s+302" => '[removed]'
);
-
+
foreach ($bad as $key => $val)
{
$str = preg_replace("#".$key."#i", $val, $str);
}
-
-
+
+
log_message('debug', "XSS Filtering completed");
return $str;
}
// --------------------------------------------------------------------
-
+
/**
* Random Hash for protecting URLs
*
@@ -832,22 +834,22 @@ class CI_Input { * @return string
*/
function xss_hash()
- {
+ {
if ($this->xss_hash == '')
{
if (phpversion() >= 4.2)
mt_srand();
else
mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff);
-
+
$this->xss_hash = md5(time() + mt_rand(0, 1999999999));
}
-
+
return $this->xss_hash;
}
// --------------------------------------------------------------------
-
+
/**
* JS Link Removal
*
@@ -864,7 +866,7 @@ class CI_Input { {
return preg_replace("#<a.+?href=.*?(alert\(|alert&\#40;|javascript\:|window\.|document\.|\.cookie|<script|<xss).*?\>.*?</a>#si", "", $match[0]);
}
-
+
/**
* JS Image Removal
*
@@ -883,7 +885,7 @@ class CI_Input { }
// --------------------------------------------------------------------
-
+
/**
* Attribute Conversion
*
@@ -897,7 +899,7 @@ class CI_Input { {
return str_replace('>', '<', $match[0]);
}
-
+
// --------------------------------------------------------------------
/**
@@ -918,7 +920,7 @@ class CI_Input { }
// --------------------------------------------------------------------
-
+
/**
* HTML Entities Decode
*
@@ -937,7 +939,7 @@ class CI_Input { /* -------------------------------------------------
/* 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
@@ -946,30 +948,30 @@ class CI_Input { function _html_entity_decode($str, $charset='UTF-8')
{
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', '>=')))
{
$str = html_entity_decode($str, ENT_COMPAT, $charset);
$str = preg_replace('~&#x([0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str);
return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str);
}
-
+
// Numeric Entities
$str = preg_replace('~&#x([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)
{
$str = strtr($str, array_flip(get_html_translation_table(HTML_ENTITIES)));
}
-
+
return $str;
}
|