2 /*------------------------------------------------------------
3 * CarbonPHP framework (C) Tom Bell
4 * http://tombell.org.uk
5 *------------------------------------------------------------*/
7 if (!defined('CARBON_PATH'))
9 exit('Direct script access is not allowed.');
14 protected $use_xss_clean = false;
15 protected $ip_address = false;
16 protected $user_agent = false;
17 protected $allow_get_array = false;
19 public function __construct()
21 $config =& load_class('Config');
22 $this->use_xss_clean
= ($config->get_config_item('use_xss_filtering') === true) ?
true : false;
23 $this->allow_get_array
= ($config->get_config_item('use_query_strings') === true) ?
true : false;
24 $this->_sanitise_globals();
26 log_message('debug', 'Input.php - Carbon_Input class initialised');
29 protected function _sanitise_globals()
51 foreach (array($_GET, $_POST, $_COOKIE, $_SERVER, $_FILES, $_ENV, (isset($_SESSION) && is_array($_SESSION)) ?
$_SESSION : array()) as $global)
53 if (!is_array($global))
55 if (!in_array($global, $protected))
57 unset($GLOBALS[$global]);
62 foreach ($global as $key => $val)
64 if (!in_array($key, $protected))
66 unset($GLOBALS[$key]);
71 foreach ($val as $k => $v)
73 if (!in_array($k, $protected))
83 if ($this->allow_get_array
== false)
89 if (is_array($_GET) && count($_GET) > 0)
91 foreach ($_GET as $key => $val)
93 $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
98 if (is_array($_POST) && count($_POST) > 0)
100 foreach ($_POST as $key => $val)
102 $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
106 if (is_array($_COOKIE) && count($_COOKIE) > 0)
108 foreach ($_COOKIE as $key => $val)
110 $_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
114 log_message('debug', 'Input.php - Global GET, POST, and COOKIE arrays have been sanitised');
117 protected function _clean_input_data($string)
119 if (is_array($string))
121 $new_array = array();
123 foreach ($string as $key => $val)
125 $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
131 if (get_magic_quotes_gpc())
133 $string = stripslashes($string);
136 if ($this->use_xss_clean
=== true)
138 $string = $this->xss_clean($string);
141 return preg_replace("/\015\012|\015|\012/", "\n", $string);
144 protected function _clean_input_keys($string)
146 if (!preg_match("/^[a-z0-9:_\/-]+$/i", $string))
148 exit('Disallowed characters in the array key.');
154 public function get($index = '', $xss_clean = false)
156 if (!isset($_GET[$index]))
161 if ($xss_clean === true)
163 if (is_array($_GET[$index]))
165 foreach ($_GET[$index] as $key => $val)
167 $_GET[$index][$key] = $this->xss_clean($val);
172 return $this->xss_clean($_GET[$index]);
176 return $_GET[$index];
179 public function post($index = '', $xss_clean = false)
181 if (!isset($_POST[$index]))
186 if ($xss_clean === true)
188 if (is_array($_POST[$index]))
190 foreach ($_POST[$index] as $key => $val)
192 $_POST[$index][$key] = $this->xss_clean($val);
197 return $this->xss_clean($_POST[$index]);
201 return $_POST[$index];
204 public function cookie($index = '', $xss_clean = false)
206 if (!isset($_COOKIE[$index]))
211 if ($xss_clean === true)
213 if (is_array($_COOKIE[$index]))
217 foreach ($_COOKIE[$index] as $key => $val)
219 $cookie[$key] = $this->xss_clean($val);
226 return $this->xss_clean($_COOKIE[$index]);
231 return $_COOKIE[$index];
235 public function server($index = '', $xss_clean = false)
237 if (!isset($_SERVER[$index]))
242 if ($xss_clean === true)
244 return $this->xss_clean($_SERVER[$index]);
247 return $_SERVER[$index];
250 public function ip_address()
252 if ($this->ip_address
!== false)
254 return $this->ip_address
;
257 if ($this->server('REMOTE_ADDR') && $this->server('HTTP_CLIENT_IP'))
259 $this->ip_address
= $_SERVER['HTTP_CLIENT_IP'];
261 else if ($this->server('REMOTE_ADDR'))
263 $this->ip_address
= $_SERVER['REMOTE_ADDR'];
265 else if ($this->server('HTTP_CLIENT_IP'))
267 $this->ip_address
= $_SERVER['HTTP_CLIENT_IP'];
269 else if ($this->server('HTTP_X_FORWARDED_FOR'))
271 $this->ip_address
= $_SERVER['HTTP_X_FORWARDED_FOR'];
274 if ($this->ip_address
=== false)
276 $this->ip_address
= '0.0.0.0';
278 return $this->ip_address
;
281 if (strstr($this->ip_address
, ','))
283 $x = explode(',', $this->ip_address
);
284 $this->ip_address
= end($x);
287 if (!$this->valid_ip($this->ip_address
))
289 $this->ip_address
= '0.0.0.0';
292 return $this->ip_address
;
295 public function valid_ip($ip)
297 $ip_segments = explode('.', $ip);
299 if (count($ip_segments) != 4)
304 if (substr($ip_segments[0], 0, 1) == '0')
309 foreach ($ip_segments as $segment)
311 if (preg_match("/[^0-9]/", $segment) ||
$segment > 255 ||
strlen($segment) > 3)
320 public function user_agent()
322 if ($this->user_agent
!== false)
324 return $this->user_agent
;
327 $this->user_agent
= (!isset($_SERVER['HTTP_USER_AGENT'])) ?
false : $_SERVER['HTTP_USER_AGENT'];
329 return $this->user_agent
;
332 public function filename_security($string)
369 return stripslashes(str_replace($bad, '', $string));
372 public function xss_clean($string)
374 $string = preg_replace('/\0+/', '', $string);
375 $string = preg_replace('/(\\\\0)+/', '', $string);
377 $string = preg_replace('#(&\#?[0-9a-z]+)[\x00-\x20]*;?#i', "\\1;", $string);
379 $string = preg_replace('#(&\#x?)([0-9A-F]+);?#i', "\\1\\2;", $string);
381 $string = preg_replace("/(%20)+/", '9u3iovBnRThju941s89rKozm', $string);
382 $string = preg_replace("/%u0([a-z0-9]{3})/i", "&#x\\1;", $string);
383 $string = preg_replace("/%([a-z0-9]{2})/i", "&#x\\1;", $string);
384 $string = str_replace('9u3iovBnRThju941s89rKozm', "%20", $string);
386 $string = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_attribute_conversion'), $string);
387 $string = preg_replace_callback("/<([\w]+)[^>]*>/si", array($this, '_html_entity_decode_callback'), $string);
389 $string = str_replace("\t", " ", $string);
392 'document.cookie' => '[removed]',
393 'document.write' => '[removed]',
394 '.parentNode' => '[removed]',
395 '.innerHTML' => '[removed]',
396 'window.location' => '[removed]',
397 '-moz-binding' => '[removed]',
400 '<!CDATA[' => '<![CDATA['
403 foreach ($bad as $key => $val)
405 $string = str_replace($key, $val, $string);
409 "javascript\s*:" => '[removed]',
410 "expression\s*\(" => '[removed]',
411 "Redirect\s+302" => '[removed]'
414 foreach ($bad as $key => $val)
416 $string = preg_replace("#" . $key . "#i", $val, $string);
419 $string = str_replace(array('<?php', '<?PHP', '<?', '?' . '>'), array('<?php', '<?PHP', '<?', '?>'), $string);
421 $words = array('javascript', 'expression', 'vbscript', 'script', 'applet', 'alert', 'document', 'write', 'cookie', 'window');
423 foreach ($words as $word)
427 for ($i = 0; $i < strlen($word); $i++
)
429 $temp .= substr($word, $i, 1) . "\s*";
432 $string = preg_replace('#(' . substr($temp, 0, -3) . ')(\W)#ise', "preg_replace('/\s+/s', '', '\\1') . '\\2'", $string);
439 if (stripos($string, '</a>') !== false ||
preg_match("/<\/a>/i", $string))
441 $string = preg_replace_callback("#<a.*?</a>#si", array($this, '_js_link_removal'), $string);
444 if (stripos($string, '<img') !== false ||
preg_match("/img/i", $string))
446 $string = preg_replace_callback("#<img.*?" . ">#si", array($this, '_js_img_removal'), $string);
449 if (stripos($string, 'script') !== false ||
stripos($string, 'xss') !== false ||
preg_match("/(script|xss)/i", $string))
451 $string = preg_replace("#</*(script|xss).*?\>#si", "", $string);
454 while ($original != $string);
458 $event_handlers = array('onblur', 'onchange', 'onclick', 'onfocus', 'onload', 'onmouseover', 'onmouseup', 'onmousedown', 'onselect', 'onsubmit', 'onupload', 'onkeypress', 'onkeydown', 'onkeyup', 'onresize', 'xmlns');
459 $string = preg_replace("#<([^>]+)(" . implode('|', $event_handlers) . ")([^>]*)>#iU", "<\\1\\2\\3>", $string);
461 $string = 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>", $string);
463 $string = preg_replace('#(alert|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', "\\1\\2(\\3)", $string);
466 'document.cookie' => '[removed]',
467 'document.write' => '[removed]',
468 '.parentNode' => '[removed]',
469 '.innerHTML' => '[removed]',
470 'window.location' => '[removed]',
471 '-moz-binding' => '[removed]',
474 '<!CDATA[' => '<![CDATA['
477 foreach ($bad as $key => $val)
479 $string = str_replace($key, $val, $string);
483 "javascript\s*:" => '[removed]',
484 "expression\s*\(" => '[removed]',
485 "Redirect\s+302" => '[removed]'
488 foreach ($bad as $key => $val)
490 $string = preg_replace("#" . $key . "#i", $val, $string);
493 log_message('debug', 'XSS filtering completed');
498 protected function _js_link_removal($match)
500 return preg_replace("#<a.+?href=.*?(alert\(|alert&\#40;|javascript\:|window\.|document\.|\.cookie|<script|<xss).*?\>.*?</a>#si", "", $match[0]);
503 protected function _js_img_removal($match)
505 return preg_replace("#<img.+?src=.*?(alert\(|alert&\#40;|javascript\:|window\.|document\.|\.cookie|<script|<xss).*?\>#si", "", $match[0]);
508 protected function _attribute_conversion($match)
510 return str_replace('>', '<', $match[0]);
513 protected function _html_entity_decode_callback($match)
515 $config =& load_class('Config');
517 $charset = $config->get_config_item('charset');
519 return $this->_html_entity_decode($match[0], strtoupper($charset));
522 protected function _html_entity_decode($string, $charset = 'UTF-8')
524 if (stristr($string, '&') === false)
529 if (function_exists('html_entitiy_decode') && strtolower($charset) != 'utf-8')
531 $string = html_entity_decode($string, ENT_COMPAT
, $charset);
532 $string = preg_match('~&#x([0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $string);
534 return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $string);
537 $string = preg_replace('~&#x([0-9a-f]{2,5});{0,1}~ei', 'chr(hexdec("\\1"))', $string);
538 $string = preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $string);
540 if (stristr($string, '&') === false)
542 $string = strtr($string, array(get_html_translation_table(HTML_ENTITIES
)));