PluginProbe
ShiftController Employee Shift Scheduling / 2.1.0
ShiftController Employee Shift Scheduling v2.1.0
4.9.97 4.9.96 4.9.95 4.9.74 4.9.75 4.9.76 4.9.77 4.9.78 4.9.84 4.9.85 4.9.87 4.9.91 4.9.92 trunk 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 3.2.4 All 38 releases
shiftcontroller / happ / system / core / Input.php

Input.php in ShiftController Employee Shift Scheduling 2.1.0, at happ/system/core/Input.php

849 lines 17.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 /**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 5.1.6 or newer
6 *
7 * @package CodeIgniter
8 * @author ExpressionEngine Dev Team
9 * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
10 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
16 // ------------------------------------------------------------------------
17
18 /**
19 * Input Class
20 *
21 * Pre-processes global input data for security
22 *
23 * @package CodeIgniter
24 * @subpackage Libraries
25 * @category Input
26 * @author ExpressionEngine Dev Team
27 * @link http://codeigniter.com/user_guide/libraries/input.html
28 */
29 class CI_Input {
30
31 /**
32 * IP address of the current user
33 *
34 * @var string
35 */
36 var $ip_address = FALSE;
37 /**
38 * user agent (web browser) being used by the current user
39 *
40 * @var string
41 */
42 var $user_agent = FALSE;
43 /**
44 * If FALSE, then $_GET will be set to an empty array
45 *
46 * @var bool
47 */
48 var $_allow_get_array = TRUE;
49 /**
50 * If TRUE, then newlines are standardized
51 *
52 * @var bool
53 */
54 var $_standardize_newlines = TRUE;
55 /**
56 * Determines whether the XSS filter is always active when GET, POST or COOKIE data is encountered
57 * Set automatically based on config setting
58 *
59 * @var bool
60 */
61 var $_enable_xss = FALSE;
62 /**
63 * Enables a CSRF cookie token to be set.
64 * Set automatically based on config setting
65 *
66 * @var bool
67 */
68 var $_enable_csrf = FALSE;
69 /**
70 * List of all HTTP request headers
71 *
72 * @var array
73 */
74 protected $headers = array();
75
76 /**
77 * Constructor
78 *
79 * Sets whether to globally enable the XSS processing
80 * and whether to allow the $_GET array
81 *
82 * @return void
83 */
84 public function __construct()
85 {
86 log_message('debug', "Input Class Initialized");
87
88 $this->_allow_get_array = (config_item('allow_get_array') === TRUE);
89 $this->_enable_xss = (config_item('global_xss_filtering') === TRUE);
90 $this->_enable_csrf = (config_item('csrf_protection') === TRUE);
91
92 global $SEC;
93 $this->security =& $SEC;
94
95 // Do we need the UTF-8 class?
96 if (UTF8_ENABLED === TRUE)
97 {
98 global $UNI;
99 $this->uni =& $UNI;
100 }
101
102 // Sanitize global arrays
103 $this->_sanitize_globals();
104 }
105
106 // --------------------------------------------------------------------
107
108 /**
109 * Fetch from array
110 *
111 * This is a helper function to retrieve values from global arrays
112 *
113 * @access private
114 * @param array
115 * @param string
116 * @param bool
117 * @return string
118 */
119 function _fetch_from_array(&$array, $index = '', $xss_clean = FALSE)
120 {
121 if ( ! isset($array[$index]))
122 {
123 return FALSE;
124 }
125
126 if ($xss_clean === TRUE)
127 {
128 return $this->security->xss_clean($array[$index]);
129 }
130
131 return $array[$index];
132 }
133
134 // --------------------------------------------------------------------
135
136 /**
137 * Fetch an item from the GET array
138 *
139 * @access public
140 * @param string
141 * @param bool
142 * @return string
143 */
144 function get($index = NULL, $xss_clean = FALSE)
145 {
146 // Check if a field has been provided
147 if ($index === NULL AND ! empty($_GET))
148 {
149 $get = array();
150
151 // loop through the full _GET array
152 foreach (array_keys($_GET) as $key)
153 {
154 $get[$key] = $this->_fetch_from_array($_GET, $key, $xss_clean);
155 }
156 return $get;
157 }
158
159 return $this->_fetch_from_array($_GET, $index, $xss_clean);
160 }
161
162 // --------------------------------------------------------------------
163
164 /**
165 * Fetch an item from the POST array
166 *
167 * @access public
168 * @param string
169 * @param bool
170 * @return string
171 */
172 function post($index = NULL, $xss_clean = FALSE)
173 {
174 // Check if a field has been provided
175 if ($index === NULL AND ! empty($_POST))
176 {
177 $post = array();
178
179 // Loop through the full _POST array and return it
180 foreach (array_keys($_POST) as $key)
181 {
182 $post[$key] = $this->_fetch_from_array($_POST, $key, $xss_clean);
183 }
184 return $post;
185 }
186
187 return $this->_fetch_from_array($_POST, $index, $xss_clean);
188 }
189
190
191 // --------------------------------------------------------------------
192
193 /**
194 * Fetch an item from either the GET array or the POST
195 *
196 * @access public
197 * @param string The index key
198 * @param bool XSS cleaning
199 * @return string
200 */
201 function get_post($index = '', $xss_clean = FALSE)
202 {
203 if ( ! isset($_POST[$index]) )
204 {
205 return $this->get($index, $xss_clean);
206 }
207 else
208 {
209 return $this->post($index, $xss_clean);
210 }
211 }
212
213 // --------------------------------------------------------------------
214
215 /**
216 * Fetch an item from the COOKIE array
217 *
218 * @access public
219 * @param string
220 * @param bool
221 * @return string
222 */
223 function cookie($index = '', $xss_clean = FALSE)
224 {
225 return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
226 }
227
228 // ------------------------------------------------------------------------
229
230 /**
231 * Set cookie
232 *
233 * Accepts six parameter, or you can submit an associative
234 * array in the first parameter containing all the values.
235 *
236 * @access public
237 * @param mixed
238 * @param string the value of the cookie
239 * @param string the number of seconds until expiration
240 * @param string the cookie domain. Usually: .yourdomain.com
241 * @param string the cookie path
242 * @param string the cookie prefix
243 * @param bool true makes the cookie secure
244 * @return void
245 */
246 function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE)
247 {
248 if (is_array($name))
249 {
250 // always leave 'name' in last place, as the loop will break otherwise, due to $$item
251 foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'name') as $item)
252 {
253 if (isset($name[$item]))
254 {
255 $$item = $name[$item];
256 }
257 }
258 }
259
260 if ($prefix == '' AND config_item('cookie_prefix') != '')
261 {
262 $prefix = config_item('cookie_prefix');
263 }
264 if ($domain == '' AND config_item('cookie_domain') != '')
265 {
266 $domain = config_item('cookie_domain');
267 }
268 if ($path == '/' AND config_item('cookie_path') != '/')
269 {
270 $path = config_item('cookie_path');
271 }
272 if ($secure == FALSE AND config_item('cookie_secure') != FALSE)
273 {
274 $secure = config_item('cookie_secure');
275 }
276
277 if ( ! is_numeric($expire))
278 {
279 $expire = time() - 86500;
280 }
281 else
282 {
283 $expire = ($expire > 0) ? time() + $expire : 0;
284 }
285
286 setcookie($prefix.$name, $value, $expire, $path, $domain, $secure);
287 }
288
289 // --------------------------------------------------------------------
290
291 /**
292 * Fetch an item from the SERVER array
293 *
294 * @access public
295 * @param string
296 * @param bool
297 * @return string
298 */
299 function server($index = '', $xss_clean = FALSE)
300 {
301 return $this->_fetch_from_array($_SERVER, $index, $xss_clean);
302 }
303
304 // --------------------------------------------------------------------
305
306 /**
307 * Fetch the IP Address
308 *
309 * @return string
310 */
311 public function ip_address()
312 {
313 if ($this->ip_address !== FALSE)
314 {
315 return $this->ip_address;
316 }
317
318 $proxy_ips = config_item('proxy_ips');
319 if ( ! empty($proxy_ips))
320 {
321 $proxy_ips = explode(',', str_replace(' ', '', $proxy_ips));
322 foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP') as $header)
323 {
324 if (($spoof = $this->server($header)) !== FALSE)
325 {
326 // Some proxies typically list the whole chain of IP
327 // addresses through which the client has reached us.
328 // e.g. client_ip, proxy_ip1, proxy_ip2, etc.
329 if (strpos($spoof, ',') !== FALSE)
330 {
331 $spoof = explode(',', $spoof, 2);
332 $spoof = $spoof[0];
333 }
334
335 if ( ! $this->valid_ip($spoof))
336 {
337 $spoof = FALSE;
338 }
339 else
340 {
341 break;
342 }
343 }
344 }
345
346 $this->ip_address = ($spoof !== FALSE && in_array($_SERVER['REMOTE_ADDR'], $proxy_ips, TRUE))
347 ? $spoof : $_SERVER['REMOTE_ADDR'];
348 }
349 else
350 {
351 $this->ip_address = $_SERVER['REMOTE_ADDR'];
352 }
353
354 if ( ! $this->valid_ip($this->ip_address))
355 {
356 $this->ip_address = '0.0.0.0';
357 }
358
359 return $this->ip_address;
360 }
361
362 // --------------------------------------------------------------------
363
364 /**
365 * Validate IP Address
366 *
367 * @access public
368 * @param string
369 * @param string ipv4 or ipv6
370 * @return bool
371 */
372 public function valid_ip($ip, $which = '')
373 {
374 $which = strtolower($which);
375
376 // First check if filter_var is available
377 if (is_callable('filter_var'))
378 {
379 switch ($which) {
380 case 'ipv4':
381 $flag = FILTER_FLAG_IPV4;
382 break;
383 case 'ipv6':
384 $flag = FILTER_FLAG_IPV6;
385 break;
386 default:
387 $flag = '';
388 break;
389 }
390
391 return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flag);
392 }
393
394 if ($which !== 'ipv6' && $which !== 'ipv4')
395 {
396 if (strpos($ip, ':') !== FALSE)
397 {
398 $which = 'ipv6';
399 }
400 elseif (strpos($ip, '.') !== FALSE)
401 {
402 $which = 'ipv4';
403 }
404 else
405 {
406 return FALSE;
407 }
408 }
409
410 $func = '_valid_'.$which;
411 return $this->$func($ip);
412 }
413
414 // --------------------------------------------------------------------
415
416 /**
417 * Validate IPv4 Address
418 *
419 * Updated version suggested by Geert De Deckere
420 *
421 * @access protected
422 * @param string
423 * @return bool
424 */
425 protected function _valid_ipv4($ip)
426 {
427 $ip_segments = explode('.', $ip);
428
429 // Always 4 segments needed
430 if (count($ip_segments) !== 4)
431 {
432 return FALSE;
433 }
434 // IP can not start with 0
435 if ($ip_segments[0][0] == '0')
436 {
437 return FALSE;
438 }
439
440 // Check each segment
441 foreach ($ip_segments as $segment)
442 {
443 // IP segments must be digits and can not be
444 // longer than 3 digits or greater then 255
445 if ($segment == '' OR preg_match("/[^0-9]/", $segment) OR $segment > 255 OR strlen($segment) > 3)
446 {
447 return FALSE;
448 }
449 }
450
451 return TRUE;
452 }
453
454 // --------------------------------------------------------------------
455
456 /**
457 * Validate IPv6 Address
458 *
459 * @access protected
460 * @param string
461 * @return bool
462 */
463 protected function _valid_ipv6($str)
464 {
465 // 8 groups, separated by :
466 // 0-ffff per group
467 // one set of consecutive 0 groups can be collapsed to ::
468
469 $groups = 8;
470 $collapsed = FALSE;
471
472 $chunks = array_filter(
473 preg_split('/(:{1,2})/', $str, NULL, PREG_SPLIT_DELIM_CAPTURE)
474 );
475
476 // Rule out easy nonsense
477 if (current($chunks) == ':' OR end($chunks) == ':')
478 {
479 return FALSE;
480 }
481
482 // PHP supports IPv4-mapped IPv6 addresses, so we'll expect those as well
483 if (strpos(end($chunks), '.') !== FALSE)
484 {
485 $ipv4 = array_pop($chunks);
486
487 if ( ! $this->_valid_ipv4($ipv4))
488 {
489 return FALSE;
490 }
491
492 $groups--;
493 }
494
495 while ($seg = array_pop($chunks))
496 {
497 if ($seg[0] == ':')
498 {
499 if (--$groups == 0)
500 {
501 return FALSE; // too many groups
502 }
503
504 if (strlen($seg) > 2)
505 {
506 return FALSE; // long separator
507 }
508
509 if ($seg == '::')
510 {
511 if ($collapsed)
512 {
513 return FALSE; // multiple collapsed
514 }
515
516 $collapsed = TRUE;
517 }
518 }
519 elseif (preg_match("/[^0-9a-f]/i", $seg) OR strlen($seg) > 4)
520 {
521 return FALSE; // invalid segment
522 }
523 }
524
525 return $collapsed OR $groups == 1;
526 }
527
528 // --------------------------------------------------------------------
529
530 /**
531 * User Agent
532 *
533 * @access public
534 * @return string
535 */
536 function user_agent()
537 {
538 if ($this->user_agent !== FALSE)
539 {
540 return $this->user_agent;
541 }
542
543 $this->user_agent = ( ! isset($_SERVER['HTTP_USER_AGENT'])) ? FALSE : $_SERVER['HTTP_USER_AGENT'];
544
545 return $this->user_agent;
546 }
547
548 // --------------------------------------------------------------------
549
550 /**
551 * Sanitize Globals
552 *
553 * This function does the following:
554 *
555 * Unsets $_GET data (if query strings are not enabled)
556 *
557 * Unsets all globals if register_globals is enabled
558 *
559 * Standardizes newline characters to \n
560 *
561 * @access private
562 * @return void
563 */
564 function _sanitize_globals()
565 {
566 // It would be "wrong" to unset any of these GLOBALS.
567 $protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST',
568 '_SESSION', '_ENV', 'GLOBALS', 'HTTP_RAW_POST_DATA',
569 'system_folder', 'application_folder', 'BM', 'EXT',
570 'CFG', 'URI', 'RTR', 'OUT', 'IN');
571
572 // Unset globals for securiy.
573 // This is effectively the same as register_globals = off
574 foreach (array($_GET, $_POST, $_COOKIE) as $global)
575 {
576 if ( ! is_array($global))
577 {
578 if ( ! in_array($global, $protected))
579 {
580 global $$global;
581 $$global = NULL;
582 }
583 }
584 else
585 {
586 foreach ($global as $key => $val)
587 {
588 if ( ! in_array($key, $protected))
589 {
590 global $$key;
591 $$key = NULL;
592 }
593 }
594 }
595 }
596
597 // Is $_GET data allowed? If not we'll set the $_GET to an empty array
598 if ($this->_allow_get_array == FALSE)
599 {
600 $_GET = array();
601 }
602 else
603 {
604 if (is_array($_GET) AND count($_GET) > 0)
605 {
606 foreach ($_GET as $key => $val)
607 {
608 $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
609 }
610 }
611 }
612
613 // Clean $_POST Data
614 if (is_array($_POST) AND count($_POST) > 0)
615 {
616 foreach ($_POST as $key => $val)
617 {
618 $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
619 }
620 }
621
622 // Clean $_COOKIE Data
623 if (is_array($_COOKIE) AND count($_COOKIE) > 0)
624 {
625 // Also get rid of specially treated cookies that might be set by a server
626 // or silly application, that are of no use to a CI application anyway
627 // but that when present will trip our 'Disallowed Key Characters' alarm
628 // http://www.ietf.org/rfc/rfc2109.txt
629 // note that the key names below are single quoted strings, and are not PHP variables
630 unset($_COOKIE['$Version']);
631 unset($_COOKIE['$Path']);
632 unset($_COOKIE['$Domain']);
633
634 foreach ($_COOKIE as $key => $val)
635 {
636 $_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
637 }
638 }
639
640 // Sanitize PHP_SELF
641 $_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
642
643
644 // CSRF Protection check on HTTP requests
645 if ($this->_enable_csrf == TRUE && ! $this->is_cli_request())
646 {
647 $this->security->csrf_verify();
648 }
649
650 log_message('debug', "Global POST and COOKIE data sanitized");
651 }
652
653 // --------------------------------------------------------------------
654
655 /**
656 * Clean Input Data
657 *
658 * This is a helper function. It escapes data and
659 * standardizes newline characters to \n
660 *
661 * @access private
662 * @param string
663 * @return string
664 */
665 function _clean_input_data($str)
666 {
667 if (is_array($str))
668 {
669 $new_array = array();
670 foreach ($str as $key => $val)
671 {
672 $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
673 }
674 return $new_array;
675 }
676
677 /* We strip slashes if magic quotes is on to keep things consistent
678
679 NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and
680 it will probably not exist in future versions at all.
681 */
682 if ( ! is_php('5.4') && get_magic_quotes_gpc())
683 {
684 $str = stripslashes($str);
685 }
686
687 // Clean UTF-8 if supported
688 if (UTF8_ENABLED === TRUE)
689 {
690 $str = $this->uni->clean_string($str);
691 }
692
693 // Remove control characters
694 $str = remove_invisible_characters($str);
695
696 // Should we filter the input data?
697 if ($this->_enable_xss === TRUE)
698 {
699 $str = $this->security->xss_clean($str);
700 }
701
702 // Standardize newlines if needed
703 if ($this->_standardize_newlines == TRUE)
704 {
705 if (strpos($str, "\r") !== FALSE)
706 {
707 $str = str_replace(array("\r\n", "\r", "\r\n\n"), PHP_EOL, $str);
708 }
709 }
710
711 return $str;
712 }
713
714 // --------------------------------------------------------------------
715
716 /**
717 * Clean Keys
718 *
719 * This is a helper function. To prevent malicious users
720 * from trying to exploit keys we make sure that keys are
721 * only named with alpha-numeric text and a few other items.
722 *
723 * @access private
724 * @param string
725 * @return string
726 */
727 function _clean_input_keys($str)
728 {
729 if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str))
730 {
731 exit('Disallowed Key Characters.');
732 }
733
734 // Clean UTF-8 if supported
735 if (UTF8_ENABLED === TRUE)
736 {
737 $str = $this->uni->clean_string($str);
738 }
739
740 return $str;
741 }
742
743 // --------------------------------------------------------------------
744
745 /**
746 * Request Headers
747 *
748 * In Apache, you can simply call apache_request_headers(), however for
749 * people running other webservers the function is undefined.
750 *
751 * @param bool XSS cleaning
752 *
753 * @return array
754 */
755 public function request_headers($xss_clean = FALSE)
756 {
757 // Look at Apache go!
758 if (function_exists('apache_request_headers'))
759 {
760 $headers = apache_request_headers();
761 }
762 else
763 {
764 $headers['Content-Type'] = (isset($_SERVER['CONTENT_TYPE'])) ? $_SERVER['CONTENT_TYPE'] : @getenv('CONTENT_TYPE');
765
766 foreach ($_SERVER as $key => $val)
767 {
768 if (strncmp($key, 'HTTP_', 5) === 0)
769 {
770 $headers[substr($key, 5)] = $this->_fetch_from_array($_SERVER, $key, $xss_clean);
771 }
772 }
773 }
774
775 // take SOME_HEADER and turn it into Some-Header
776 foreach ($headers as $key => $val)
777 {
778 $key = str_replace('_', ' ', strtolower($key));
779 $key = str_replace(' ', '-', ucwords($key));
780
781 $this->headers[$key] = $val;
782 }
783
784 return $this->headers;
785 }
786
787 // --------------------------------------------------------------------
788
789 /**
790 * Get Request Header
791 *
792 * Returns the value of a single member of the headers class member
793 *
794 * @param string array key for $this->headers
795 * @param boolean XSS Clean or not
796 * @return mixed FALSE on failure, string on success
797 */
798 public function get_request_header($index, $xss_clean = FALSE)
799 {
800 if (empty($this->headers))
801 {
802 $this->request_headers();
803 }
804
805 if ( ! isset($this->headers[$index]))
806 {
807 return FALSE;
808 }
809
810 if ($xss_clean === TRUE)
811 {
812 return $this->security->xss_clean($this->headers[$index]);
813 }
814
815 return $this->headers[$index];
816 }
817
818 // --------------------------------------------------------------------
819
820 /**
821 * Is ajax Request?
822 *
823 * Test to see if a request contains the HTTP_X_REQUESTED_WITH header
824 *
825 * @return boolean
826 */
827 public function is_ajax_request()
828 {
829 return ($this->server('HTTP_X_REQUESTED_WITH') === 'XMLHttpRequest');
830 }
831
832 // --------------------------------------------------------------------
833
834 /**
835 * Is cli Request?
836 *
837 * Test to see if a request was made from the command line
838 *
839 * @return bool
840 */
841 public function is_cli_request()
842 {
843 return (php_sapi_name() === 'cli' OR defined('STDIN'));
844 }
845
846 }
847
848 /* End of file Input.php */
849 /* Location: ./system/core/Input.php */