blob: 4fd2061c7415027d71ac78a41e4f2aeeef4c8810 [file] [log] [blame]
adminb0dd10f2006-08-25 17:25:49 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * Code Igniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author Rick Ellis
9 * @copyright Copyright (c) 2006, pMachine, Inc.
admine334c472006-10-21 19:44:22 +000010 * @license http://www.codeignitor.com/user_guide/license.html
adminb0dd10f2006-08-25 17:25:49 +000011 * @link http://www.codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
admine334c472006-10-21 19:44:22 +000015
adminb0dd10f2006-08-25 17:25:49 +000016// ------------------------------------------------------------------------
17
18/**
19 * Input Class
admine334c472006-10-21 19:44:22 +000020 *
adminb0dd10f2006-08-25 17:25:49 +000021 * Pre-processes global input data for security
22 *
23 * @package CodeIgniter
24 * @subpackage Libraries
25 * @category Input
26 * @author Rick Ellis
27 * @link http://www.codeigniter.com/user_guide/libraries/input.html
28 */
29class CI_Input {
30 var $use_xss_clean = FALSE;
31 var $ip_address = FALSE;
32 var $user_agent = FALSE;
33 var $allow_get_array = FALSE;
34
35 /**
36 * Constructor
37 *
38 * Sets whether to globally enable the XSS processing
39 * and whether to allow the $_GET array
40 *
41 * @access public
42 */
43 function CI_Input()
44 {
admin04ea44e2006-10-03 19:17:59 +000045 log_message('debug', "Input Class Initialized");
46
admin7099a582006-10-10 17:47:59 +000047 $CFG =& load_class('Config');
adminb0dd10f2006-08-25 17:25:49 +000048 $this->use_xss_clean = ($CFG->item('global_xss_filtering') === TRUE) ? TRUE : FALSE;
admin04ea44e2006-10-03 19:17:59 +000049 $this->allow_get_array = ($CFG->item('enable_query_strings') === TRUE) ? TRUE : FALSE;
adminb0dd10f2006-08-25 17:25:49 +000050 $this->_sanitize_globals();
51 }
adminb0dd10f2006-08-25 17:25:49 +000052
53 // --------------------------------------------------------------------
54
55 /**
56 * Sanitize Globals
57 *
adminbd6bee72006-10-21 19:39:00 +000058 * This function does the following:
adminb0dd10f2006-08-25 17:25:49 +000059 *
60 * Unsets $_GET data (if query strings are not enabled)
61 *
62 * Unsets all globals if register_globals is enabled
63 *
64 * Standardizes newline characters to \n
65 *
66 * @access private
67 * @return void
68 */
69 function _sanitize_globals()
70 {
71 // Unset globals. This is effectively the same as register_globals = off
72 foreach (array($_GET, $_POST, $_COOKIE) as $global)
73 {
74 if ( ! is_array($global))
75 {
Rick Ellis325197e2006-11-20 17:29:05 +000076 global $global;
77 $$global = NULL;
adminb0dd10f2006-08-25 17:25:49 +000078 }
79 else
80 {
81 foreach ($global as $key => $val)
82 {
Rick Ellis325197e2006-11-20 17:29:05 +000083 global $$key;
84 $$key = NULL;
admin04ea44e2006-10-03 19:17:59 +000085 }
adminb0dd10f2006-08-25 17:25:49 +000086 }
87 }
88
admin04ea44e2006-10-03 19:17:59 +000089 // Is $_GET data allowed? If not we'll set the $_GET to an empty array
adminb0dd10f2006-08-25 17:25:49 +000090 if ($this->allow_get_array == FALSE)
91 {
92 $_GET = array();
93 }
94
95 // Clean $_POST Data
96 if (is_array($_POST) AND count($_POST) > 0)
97 {
98 foreach($_POST as $key => $val)
admin04ea44e2006-10-03 19:17:59 +000099 {
100 $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
101 }
adminb0dd10f2006-08-25 17:25:49 +0000102 }
103
104 // Clean $_COOKIE Data
105 if (is_array($_COOKIE) AND count($_COOKIE) > 0)
106 {
107 foreach($_COOKIE as $key => $val)
admine334c472006-10-21 19:44:22 +0000108 {
adminb0dd10f2006-08-25 17:25:49 +0000109 $_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
admin04ea44e2006-10-03 19:17:59 +0000110 }
adminb0dd10f2006-08-25 17:25:49 +0000111 }
112
113 log_message('debug', "Global POST and COOKIE data sanitized");
114 }
adminb0dd10f2006-08-25 17:25:49 +0000115
116 // --------------------------------------------------------------------
117
118 /**
adminbd6bee72006-10-21 19:39:00 +0000119 * Clean Input Data
adminb0dd10f2006-08-25 17:25:49 +0000120 *
admine334c472006-10-21 19:44:22 +0000121 * This is a helper function. It escapes data and
adminb0dd10f2006-08-25 17:25:49 +0000122 * standardizes newline characters to \n
123 *
124 * @access private
125 * @param string
126 * @return string
127 */
128 function _clean_input_data($str)
129 {
130 if (is_array($str))
131 {
132 $new_array = array();
133 foreach ($str as $key => $val)
134 {
admin04ea44e2006-10-03 19:17:59 +0000135 $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
adminb0dd10f2006-08-25 17:25:49 +0000136 }
137 return $new_array;
138 }
139
140 if ($this->use_xss_clean === TRUE)
141 {
142 $str = $this->xss_clean($str);
143 }
144
admin04ea44e2006-10-03 19:17:59 +0000145 // Standardize newlines
adminb0dd10f2006-08-25 17:25:49 +0000146 return preg_replace("/\015\012|\015|\012/", "\n", $str);
147 }
adminb0dd10f2006-08-25 17:25:49 +0000148
149 // --------------------------------------------------------------------
150
151 /**
152 * Clean Keys
153 *
admine334c472006-10-21 19:44:22 +0000154 * This is a helper function. To prevent malicious users
155 * from trying to exploit keys we make sure that keys are
adminb0dd10f2006-08-25 17:25:49 +0000156 * only named with alpha-numeric text and a few other items.
157 *
158 * @access private
159 * @param string
160 * @return string
161 */
162 function _clean_input_keys($str)
admin04ea44e2006-10-03 19:17:59 +0000163 {
adminb0dd10f2006-08-25 17:25:49 +0000164 if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str))
admine334c472006-10-21 19:44:22 +0000165 {
adminb0dd10f2006-08-25 17:25:49 +0000166 exit('Disallowed Key Characters: '.$str);
167 }
168
169 if ( ! get_magic_quotes_gpc())
170 {
171 return addslashes($str);
172 }
173
174 return $str;
175 }
adminb0dd10f2006-08-25 17:25:49 +0000176
177 // --------------------------------------------------------------------
178
179 /**
180 * Fetch an item from the POST array
181 *
182 * @access public
183 * @param string
admin10c3f412006-10-08 07:21:12 +0000184 * @param bool
adminb0dd10f2006-08-25 17:25:49 +0000185 * @return string
186 */
187 function post($index = '', $xss_clean = FALSE)
188 {
189 if ( ! isset($_POST[$index]))
190 {
191 return FALSE;
192 }
admin04ea44e2006-10-03 19:17:59 +0000193
194 if ($xss_clean === TRUE)
adminb0dd10f2006-08-25 17:25:49 +0000195 {
admin04ea44e2006-10-03 19:17:59 +0000196 if (is_array($_POST[$index]))
adminb0dd10f2006-08-25 17:25:49 +0000197 {
admin04ea44e2006-10-03 19:17:59 +0000198 foreach($_POST[$index] as $key => $val)
199 {
200 $_POST[$index][$key] = $this->xss_clean($val);
201 }
adminb0dd10f2006-08-25 17:25:49 +0000202 }
203 else
204 {
admin04ea44e2006-10-03 19:17:59 +0000205 return $this->xss_clean($_POST[$index]);
adminb0dd10f2006-08-25 17:25:49 +0000206 }
207 }
admin04ea44e2006-10-03 19:17:59 +0000208
209 return $_POST[$index];
adminb0dd10f2006-08-25 17:25:49 +0000210 }
adminb0dd10f2006-08-25 17:25:49 +0000211
212 // --------------------------------------------------------------------
213
214 /**
215 * Fetch an item from the COOKIE array
216 *
217 * @access public
218 * @param string
admin10c3f412006-10-08 07:21:12 +0000219 * @param bool
adminb0dd10f2006-08-25 17:25:49 +0000220 * @return string
221 */
222 function cookie($index = '', $xss_clean = FALSE)
223 {
224 if ( ! isset($_COOKIE[$index]))
225 {
226 return FALSE;
227 }
admin04ea44e2006-10-03 19:17:59 +0000228
229 if ($xss_clean === TRUE)
230 {
231 if (is_array($_COOKIE[$index]))
adminb0dd10f2006-08-25 17:25:49 +0000232 {
admin04ea44e2006-10-03 19:17:59 +0000233 $cookie = array();
234 foreach($_COOKIE[$index] as $key => $val)
admin2fcd16b2006-10-03 16:41:54 +0000235 {
admin04ea44e2006-10-03 19:17:59 +0000236 $cookie[$key] = $this->xss_clean($val);
admin2fcd16b2006-10-03 16:41:54 +0000237 }
admin04ea44e2006-10-03 19:17:59 +0000238
239 return $cookie;
adminb0dd10f2006-08-25 17:25:49 +0000240 }
241 else
242 {
admin04ea44e2006-10-03 19:17:59 +0000243 return $this->xss_clean($_COOKIE[$index]);
adminb0dd10f2006-08-25 17:25:49 +0000244 }
245 }
admin04ea44e2006-10-03 19:17:59 +0000246 else
247 {
248 return $_COOKIE[$index];
249 }
adminb0dd10f2006-08-25 17:25:49 +0000250 }
admin10c3f412006-10-08 07:21:12 +0000251
252 // --------------------------------------------------------------------
253
254 /**
255 * Fetch an item from the SERVER array
256 *
257 * @access public
258 * @param string
259 * @param bool
260 * @return string
261 */
262 function server($index = '', $xss_clean = FALSE)
263 {
264 if ( ! isset($_SERVER[$index]))
265 {
266 return FALSE;
267 }
268
269 if ($xss_clean === TRUE)
270 {
271 return $this->xss_clean($_SERVER[$index]);
272 }
273
274 return $_SERVER[$index];
275 }
adminb0dd10f2006-08-25 17:25:49 +0000276
277 // --------------------------------------------------------------------
278
279 /**
280 * Fetch the IP Address
281 *
282 * @access public
283 * @return string
284 */
285 function ip_address()
286 {
287 if ($this->ip_address !== FALSE)
288 {
289 return $this->ip_address;
290 }
admin10c3f412006-10-08 07:21:12 +0000291
292 if ($this->server('REMOTE_ADDR') AND $this->server('HTTP_CLIENT_IP'))
293 {
294 $this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
295 }
296 elseif ($this->server('REMOTE_ADDR'))
297 {
298 $this->ip_address = $_SERVER['REMOTE_ADDR'];
299 }
300 elseif ($this->server('HTTP_CLIENT_IP'))
301 {
302 $this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
303 }
304 elseif ($this->server('HTTP_X_FORWARDED_FOR'))
305 {
306 $this->ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
307 }
308
309 if ($this->ip_address === FALSE)
310 {
admin7099a582006-10-10 17:47:59 +0000311 $this->ip_address = '0.0.0.0';
312 return $this->ip_address;
admin10c3f412006-10-08 07:21:12 +0000313 }
adminb0dd10f2006-08-25 17:25:49 +0000314
315 if (strstr($this->ip_address, ','))
316 {
317 $x = explode(',', $this->ip_address);
318 $this->ip_address = end($x);
319 }
320
321 if ( ! $this->valid_ip($this->ip_address))
322 {
323 $this->ip_address = '0.0.0.0';
324 }
admin10c3f412006-10-08 07:21:12 +0000325
adminb0dd10f2006-08-25 17:25:49 +0000326 return $this->ip_address;
327 }
adminb0dd10f2006-08-25 17:25:49 +0000328
329 // --------------------------------------------------------------------
330
331 /**
332 * Validate IP Address
333 *
334 * @access public
335 * @param string
336 * @return string
337 */
338 function valid_ip($ip)
339 {
340 return ( ! preg_match( "/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $ip)) ? FALSE : TRUE;
341 }
adminb0dd10f2006-08-25 17:25:49 +0000342
343 // --------------------------------------------------------------------
344
345 /**
346 * User Agent
347 *
348 * @access public
349 * @return string
350 */
351 function user_agent()
352 {
353 if ($this->user_agent !== FALSE)
354 {
355 return $this->user_agent;
356 }
357
358 $this->user_agent = ( ! isset($_SERVER['HTTP_USER_AGENT'])) ? FALSE : $_SERVER['HTTP_USER_AGENT'];
359
360 return $this->user_agent;
361 }
adminb0dd10f2006-08-25 17:25:49 +0000362
363 // --------------------------------------------------------------------
364
365 /**
366 * XSS Clean
367 *
368 * Sanitizes data so that Cross Site Scripting Hacks can be
paulburdick40a7c682007-01-13 00:03:37 +0000369 * prevented.  This function does a fair amount of work but
adminb0dd10f2006-08-25 17:25:49 +0000370 * it is extremely thorough, designed to prevent even the
paulburdick40a7c682007-01-13 00:03:37 +0000371 * most obscure XSS attempts.  Nothing is ever 100% foolproof,
adminb0dd10f2006-08-25 17:25:49 +0000372 * of course, but I haven't been able to get anything passed
373 * the filter.
374 *
375 * Note: This function should only be used to deal with data
paulburdick40a7c682007-01-13 00:03:37 +0000376 * upon submission.  It's not something that should
adminb0dd10f2006-08-25 17:25:49 +0000377 * be used for general runtime processing.
378 *
379 * This function was based in part on some code and ideas I
380 * got from Bitflux: http://blog.bitflux.ch/wiki/XSS_Prevention
381 *
382 * To help develop this script I used this great list of
admine334c472006-10-21 19:44:22 +0000383 * vulnerabilities along with a few other hacks I've
adminb0dd10f2006-08-25 17:25:49 +0000384 * harvested from examining vulnerabilities in other programs:
385 * http://ha.ckers.org/xss.html
386 *
387 * @access public
388 * @param string
389 * @return string
390 */
391 function xss_clean($str, $charset = 'ISO-8859-1')
392 {
393 /*
394 * Remove Null Characters
395 *
396 * This prevents sandwiching null characters
397 * between ascii characters, like Java\0script.
398 *
399 */
400 $str = preg_replace('/\0+/', '', $str);
401 $str = preg_replace('/(\\\\0)+/', '', $str);
402
403 /*
adminbd6bee72006-10-21 19:39:00 +0000404 * Validate standard character entities
adminb0dd10f2006-08-25 17:25:49 +0000405 *
406 * Add a semicolon if missing. We do this to enable
407 * the conversion of entities to ASCII later.
408 *
409 */
410 $str = preg_replace('#(&\#*\w+)[\x00-\x20]+;#u',"\\1;",$str);
411
412 /*
admine334c472006-10-21 19:44:22 +0000413 * Validate UTF16 two byte encoding (x00)
adminb0dd10f2006-08-25 17:25:49 +0000414 *
415 * Just as above, adds a semicolon if missing.
416 *
417 */
418 $str = preg_replace('#(&\#x*)([0-9A-F]+);*#iu',"\\1\\2;",$str);
419
420 /*
421 * URL Decode
422 *
423 * Just in case stuff like this is submitted:
424 *
425 * <a href="http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D">Google</a>
426 *
427 * Note: Normally urldecode() would be easier but it removes plus signs
428 *
429 */
430 $str = preg_replace("/%u0([a-z0-9]{3})/i", "&#x\\1;", $str);
admin04ea44e2006-10-03 19:17:59 +0000431 $str = preg_replace("/%([a-z0-9]{2})/i", "&#x\\1;", $str);
432
adminb0dd10f2006-08-25 17:25:49 +0000433 /*
admine334c472006-10-21 19:44:22 +0000434 * Convert character entities to ASCII
adminb0dd10f2006-08-25 17:25:49 +0000435 *
436 * This permits our tests below to work reliably.
437 * We only convert entities that are within tags since
438 * these are the ones that will pose security problems.
439 *
440 */
admin04ea44e2006-10-03 19:17:59 +0000441 if (preg_match_all("/<(.+?)>/si", $str, $matches))
442 {
adminb0dd10f2006-08-25 17:25:49 +0000443 for ($i = 0; $i < count($matches['0']); $i++)
444 {
admine334c472006-10-21 19:44:22 +0000445 $str = str_replace($matches['1'][$i],
446 $this->_html_entity_decode($matches['1'][$i], $charset),
adminb0dd10f2006-08-25 17:25:49 +0000447 $str);
448 }
449 }
paulburdick40a7c682007-01-13 00:03:37 +0000450
451 /*
452 * Not Allowed Under Any Conditions
453 */
454 $bad = array(
455 'document.cookie' => '[removed]',
456 'document.write' => '[removed]',
457 'window.location' => '[removed]',
458 "javascript\s*:" => '[removed]',
459 "Redirect\s+302" => '[removed]',
460 '<!--' => '&lt;!--',
461 '-->' => '--&gt;'
462 );
463
464 foreach ($bad as $key => $val)
465 {
466 $str = preg_replace("#".$key."#i", $val, $str);
467 }
adminb0dd10f2006-08-25 17:25:49 +0000468
469 /*
470 * Convert all tabs to spaces
471 *
472 * This prevents strings like this: ja vascript
473 * Note: we deal with spaces between characters later.
474 *
475 */
476 $str = preg_replace("#\t+#", " ", $str);
477
478 /*
479 * Makes PHP tags safe
480 *
481 * Note: XML tags are inadvertently replaced too:
482 *
483 * <?xml
484 *
485 * But it doesn't seem to pose a problem.
486 *
487 */
adminbc042dd2006-09-21 02:46:59 +0000488 $str = str_replace(array('<?php', '<?PHP', '<?', '?>'), array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);
adminb0dd10f2006-08-25 17:25:49 +0000489
490 /*
491 * Compact any exploded words
492 *
493 * This corrects words like: j a v a s c r i p t
494 * These words are compacted back to their correct state.
495 *
496 */
497 $words = array('javascript', 'vbscript', 'script', 'applet', 'alert', 'document', 'write', 'cookie', 'window');
498 foreach ($words as $word)
499 {
500 $temp = '';
501 for ($i = 0; $i < strlen($word); $i++)
502 {
503 $temp .= substr($word, $i, 1)."\s*";
504 }
505
506 $temp = substr($temp, 0, -3);
507 $str = preg_replace('#'.$temp.'#s', $word, $str);
508 $str = preg_replace('#'.ucfirst($temp).'#s', ucfirst($word), $str);
509 }
510
511 /*
512 * Remove disallowed Javascript in links or img tags
513 */
514 $str = preg_replace("#<a.+?href=.*?(alert\(|alert&\#40;|javascript\:|window\.|document\.|\.cookie|<script|<xss).*?\>.*?</a>#si", "", $str);
515 $str = preg_replace("#<img.+?src=.*?(alert\(|alert&\#40;|javascript\:|window\.|document\.|\.cookie|<script|<xss).*?\>#si", "", $str);
516 $str = preg_replace("#<(script|xss).*?\>#si", "", $str);
517
518 /*
519 * Remove JavaScript Event Handlers
520 *
521 * Note: This code is a little blunt. It removes
admine334c472006-10-21 19:44:22 +0000522 * the event handler and anything up to the closing >,
adminbd6bee72006-10-21 19:39:00 +0000523 * but it's unlikely to be a problem.
adminb0dd10f2006-08-25 17:25:49 +0000524 *
525 */
526 $str = preg_replace('#(<[^>]+.*?)(onblur|onchange|onclick|onfocus|onload|onmouseover|onmouseup|onmousedown|onselect|onsubmit|onunload|onkeypress|onkeydown|onkeyup|onresize)[^>]*>#iU',"\\1>",$str);
527
528 /*
529 * Sanitize naughty HTML elements
530 *
admine334c472006-10-21 19:44:22 +0000531 * If a tag containing any of the words in the list
adminb0dd10f2006-08-25 17:25:49 +0000532 * below is found, the tag gets converted to entities.
533 *
534 * So this: <blink>
535 * Becomes: &lt;blink&gt;
536 *
537 */
538 $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', "&lt;\\1\\2\\3&gt;", $str);
539
540 /*
541 * Sanitize naughty scripting elements
542 *
543 * Similar to above, only instead of looking for
544 * tags it looks for PHP and JavaScript commands
545 * that are disallowed. Rather than removing the
546 * code, it simply converts the parenthesis to entities
adminbd6bee72006-10-21 19:39:00 +0000547 * rendering the code un-executable.
adminb0dd10f2006-08-25 17:25:49 +0000548 *
549 * For example: eval('some code')
550 * Becomes: eval&#40;'some code'&#41;
551 *
552 */
553 $str = preg_replace('#(alert|cmd|passthru|eval|exec|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', "\\1\\2&#40;\\3&#41;", $str);
554
555 /*
556 * Final clean up
557 *
558 * This adds a bit of extra precaution in case
559 * something got through the above filters
560 *
561 */
562 $bad = array(
paulburdick40a7c682007-01-13 00:03:37 +0000563 'document.cookie' => '[removed]',
564 'document.write' => '[removed]',
565 'window.location' => '[removed]',
566 "javascript\s*:" => '[removed]',
567 "Redirect\s+302" => '[removed]',
adminb0dd10f2006-08-25 17:25:49 +0000568 '<!--' => '&lt;!--',
569 '-->' => '--&gt;'
570 );
571
572 foreach ($bad as $key => $val)
573 {
admine334c472006-10-21 19:44:22 +0000574 $str = preg_replace("#".$key."#i", $val, $str);
adminb0dd10f2006-08-25 17:25:49 +0000575 }
576
admin04ea44e2006-10-03 19:17:59 +0000577
adminb0dd10f2006-08-25 17:25:49 +0000578 log_message('debug', "XSS Filtering completed");
579 return $str;
580 }
adminb0dd10f2006-08-25 17:25:49 +0000581
admin04ea44e2006-10-03 19:17:59 +0000582 // --------------------------------------------------------------------
adminb0dd10f2006-08-25 17:25:49 +0000583
584 /**
585 * HTML Entities Decode
586 *
587 * This function is a replacement for html_entity_decode()
588 *
589 * In some versions of PHP the native function does not work
590 * when UTF-8 is the specified character set, so this gives us
591 * a work-around. More info here:
592 * http://bugs.php.net/bug.php?id=25670
593 *
594 * @access private
595 * @param string
596 * @param string
597 * @return string
598 */
599 /* -------------------------------------------------
admin04ea44e2006-10-03 19:17:59 +0000600 /* Replacement for html_entity_decode()
601 /* -------------------------------------------------*/
602
603 /*
admine334c472006-10-21 19:44:22 +0000604 NOTE: html_entity_decode() has a bug in some PHP versions when UTF-8 is the
admin04ea44e2006-10-03 19:17:59 +0000605 character set, and the PHP developers said they were not back porting the
606 fix to versions other than PHP 5.x.
607 */
admine334c472006-10-21 19:44:22 +0000608 function _html_entity_decode($str, $charset='ISO-8859-1')
adminb0dd10f2006-08-25 17:25:49 +0000609 {
610 if (stristr($str, '&') === FALSE) return $str;
611
612 // The reason we are not using html_entity_decode() by itself is because
613 // while it is not technically correct to leave out the semicolon
614 // at the end of an entity most browsers will still interpret the entity
615 // correctly. html_entity_decode() does not convert entities without
616 // semicolons, so we are left with our own little solution here. Bummer.
617
618 if (function_exists('html_entity_decode') && (strtolower($charset) != 'utf-8' OR version_compare(phpversion(), '5.0.0', '>=')))
619 {
620 $str = html_entity_decode($str, ENT_COMPAT, $charset);
621 $str = preg_replace('~&#x([0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str);
622 return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str);
623 }
624
625 // Numeric Entities
626 $str = preg_replace('~&#x([0-9a-f]{2,5});{0,1}~ei', 'chr(hexdec("\\1"))', $str);
627 $str = preg_replace('~&#([0-9]{2,4});{0,1}~e', 'chr(\\1)', $str);
628
629 // Literal Entities - Slightly slow so we do another check
630 if (stristr($str, '&') === FALSE)
631 {
632 $str = strtr($str, array_flip(get_html_translation_table(HTML_ENTITIES)));
633 }
634
635 return $str;
636 }
637
638}
639// END Input class
640?>