blob: 143babf5c9f7c6cf29698d4b65660d0b7584d058 [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02005 * An open source application development framework for PHP
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +02007 * This content is released under the MIT License (MIT)
Andrey Andreev64e98aa2012-01-07 20:29:10 +02008 *
Andrey Andreevcce6bd12018-01-09 11:32:02 +02009 * Copyright (c) 2014 - 2018, British Columbia Institute of Technology
Andrey Andreev64e98aa2012-01-07 20:29:10 +020010 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020011 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
Derek Jonesf4a4bd82011-10-20 12:18:42 -050017 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020018 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @package CodeIgniter
30 * @author EllisLab Dev Team
Andrey Andreev1924e872016-01-11 12:55:34 +020031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
Andrey Andreevcce6bd12018-01-09 11:32:02 +020032 * @copyright Copyright (c) 2014 - 2018, British Columbia Institute of Technology (http://bcit.ca/)
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020033 * @license http://opensource.org/licenses/MIT MIT License
Andrey Andreevbd202c92016-01-11 12:50:18 +020034 * @link https://codeigniter.com
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020035 * @since Version 1.0.0
Derek Allard2067d1a2008-11-13 22:59:24 +000036 * @filesource
37 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020038defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000039
Derek Allard2067d1a2008-11-13 22:59:24 +000040/**
41 * Input Class
42 *
43 * Pre-processes global input data for security
44 *
45 * @package CodeIgniter
46 * @subpackage Libraries
47 * @category Input
Derek Jonesf4a4bd82011-10-20 12:18:42 -050048 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +020049 * @link https://codeigniter.com/user_guide/libraries/input.html
Derek Allard2067d1a2008-11-13 22:59:24 +000050 */
51class CI_Input {
Derek Allard2067d1a2008-11-13 22:59:24 +000052
David Behler9b5df592011-08-14 21:04:17 +020053 /**
54 * IP address of the current user
55 *
Andrey Andreev1887ec62012-10-27 16:22:07 +030056 * @var string
David Behler9b5df592011-08-14 21:04:17 +020057 */
Andrey Andreev52caf592015-02-27 15:09:34 +020058 protected $ip_address = FALSE;
Andrey Andreev92ebfb62012-05-17 12:49:24 +030059
David Behler9b5df592011-08-14 21:04:17 +020060 /**
Andrey Andreev1887ec62012-10-27 16:22:07 +030061 * Allow GET array flag
David Behler9b5df592011-08-14 21:04:17 +020062 *
Andrey Andreev1887ec62012-10-27 16:22:07 +030063 * If set to FALSE, then $_GET will be set to an empty array.
David Behler9b5df592011-08-14 21:04:17 +020064 *
Andrey Andreev1887ec62012-10-27 16:22:07 +030065 * @var bool
David Behler9b5df592011-08-14 21:04:17 +020066 */
Andrey Andreev1887ec62012-10-27 16:22:07 +030067 protected $_allow_get_array = TRUE;
Andrey Andreev92ebfb62012-05-17 12:49:24 +030068
David Behler9b5df592011-08-14 21:04:17 +020069 /**
Andrey Andreevbfb635b2014-01-08 18:32:05 +020070 * Standardize new lines flag
David Behler9b5df592011-08-14 21:04:17 +020071 *
Andrey Andreev1887ec62012-10-27 16:22:07 +030072 * If set to TRUE, then newlines are standardized.
73 *
74 * @var bool
David Behler9b5df592011-08-14 21:04:17 +020075 */
Andrey Andreevefc08e92014-04-15 14:32:52 +030076 protected $_standardize_newlines;
Andrey Andreev92ebfb62012-05-17 12:49:24 +030077
David Behler9b5df592011-08-14 21:04:17 +020078 /**
Andrey Andreev1887ec62012-10-27 16:22:07 +030079 * Enable XSS flag
80 *
81 * Determines whether the XSS filter is always active when
82 * GET, POST or COOKIE data is encountered.
83 * Set automatically based on config setting.
84 *
85 * @var bool
86 */
87 protected $_enable_xss = FALSE;
88
89 /**
90 * Enable CSRF flag
91 *
David Behler9b5df592011-08-14 21:04:17 +020092 * Enables a CSRF cookie token to be set.
Andrey Andreev1887ec62012-10-27 16:22:07 +030093 * Set automatically based on config setting.
David Behler9b5df592011-08-14 21:04:17 +020094 *
Andrey Andreev1887ec62012-10-27 16:22:07 +030095 * @var bool
David Behler9b5df592011-08-14 21:04:17 +020096 */
Andrey Andreev1887ec62012-10-27 16:22:07 +030097 protected $_enable_csrf = FALSE;
Andrey Andreev92ebfb62012-05-17 12:49:24 +030098
David Behler9b5df592011-08-14 21:04:17 +020099 /**
100 * List of all HTTP request headers
101 *
102 * @var array
103 */
Andrey Andreev1887ec62012-10-27 16:22:07 +0300104 protected $headers = array();
David Behler9b5df592011-08-14 21:04:17 +0200105
Andrey Andreevd0ac8b12015-02-27 11:41:52 +0200106 /**
107 * Raw input stream data
108 *
109 * Holds a cache of php://input contents
110 *
111 * @var string
112 */
Ignasimgcae95882015-02-26 02:46:14 +0100113 protected $_raw_input_stream;
Ignasimgf9fbf112015-02-06 09:21:07 +0100114
Derek Allard2067d1a2008-11-13 22:59:24 +0000115 /**
Andrey Andreevd0ac8b12015-02-27 11:41:52 +0200116 * Parsed input stream data
Andrey Andreev303eef02012-11-06 14:55:48 +0200117 *
118 * Parsed from php://input at runtime
119 *
120 * @see CI_Input::input_stream()
121 * @var array
122 */
Andrey Andreevd0ac8b12015-02-27 11:41:52 +0200123 protected $_input_stream;
124
Andrey Andreev88fd8e42015-02-27 11:43:01 +0200125 protected $security;
Andrey Andreev7d365dc2015-02-27 14:32:15 +0200126 protected $uni;
Andrey Andreev88fd8e42015-02-27 11:43:01 +0200127
Andrey Andreevd0ac8b12015-02-27 11:41:52 +0200128 // --------------------------------------------------------------------
Andrey Andreev303eef02012-11-06 14:55:48 +0200129
130 /**
Andrey Andreev1887ec62012-10-27 16:22:07 +0300131 * Class constructor
Greg Akera9263282010-11-10 15:26:43 -0600132 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300133 * Determines whether to globally enable the XSS processing
134 * and whether to allow the $_GET array.
Andrey Andreev92ebfb62012-05-17 12:49:24 +0300135 *
136 * @return void
Greg Akera9263282010-11-10 15:26:43 -0600137 */
138 public function __construct()
Derek Allard2067d1a2008-11-13 22:59:24 +0000139 {
Andrey Andreev9e2dcd42017-11-29 12:59:45 +0200140 $this->_allow_get_array = (config_item('allow_get_array') !== FALSE);
Andrey Andreevbfb635b2014-01-08 18:32:05 +0200141 $this->_enable_xss = (config_item('global_xss_filtering') === TRUE);
142 $this->_enable_csrf = (config_item('csrf_protection') === TRUE);
fabianozenatti523cda32014-03-21 12:13:03 +0100143 $this->_standardize_newlines = (bool) config_item('standardize_newlines');
Derek Jones69fc4fc2010-03-02 13:36:31 -0600144
Andrey Andreevc26b9eb2014-02-24 11:31:36 +0200145 $this->security =& load_class('Security', 'core');
Derek Jones69fc4fc2010-03-02 13:36:31 -0600146
Pascal Krieteaaec1e42011-01-20 00:01:21 -0500147 // Do we need the UTF-8 class?
Derek Jones69fc4fc2010-03-02 13:36:31 -0600148 if (UTF8_ENABLED === TRUE)
149 {
Andrey Andreevc26b9eb2014-02-24 11:31:36 +0200150 $this->uni =& load_class('Utf8', 'core');
Derek Jones69fc4fc2010-03-02 13:36:31 -0600151 }
152
153 // Sanitize global arrays
Derek Allard2067d1a2008-11-13 22:59:24 +0000154 $this->_sanitize_globals();
Andrey Andreev90726b82015-01-20 12:39:22 +0200155
Andrey Andreevdd28a882015-09-07 16:03:05 +0300156 // CSRF Protection check
157 if ($this->_enable_csrf === TRUE && ! is_cli())
158 {
159 $this->security->csrf_verify();
160 }
161
Andrey Andreev90726b82015-01-20 12:39:22 +0200162 log_message('info', 'Input Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +0000163 }
164
165 // --------------------------------------------------------------------
166
167 /**
Greg Akera9263282010-11-10 15:26:43 -0600168 * Fetch from array
169 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300170 * Internal method used to retrieve values from global arrays.
Greg Akera9263282010-11-10 15:26:43 -0600171 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300172 * @param array &$array $_GET, $_POST, $_COOKIE, $_SERVER, etc.
Ahmad Anbarff89a4e2014-12-02 17:26:30 +0200173 * @param mixed $index Index for item to be fetched from $array
Andrey Andreev1887ec62012-10-27 16:22:07 +0300174 * @param bool $xss_clean Whether to apply XSS filtering
175 * @return mixed
Greg Akera9263282010-11-10 15:26:43 -0600176 */
Andrey Andreev7c60b122014-02-08 18:47:19 +0200177 protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000178 {
Andrey Andreevef29f832014-12-02 18:03:47 +0200179 is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
180
Andrey Andreev7c60b122014-02-08 18:47:19 +0200181 // If $index is NULL, it means that the whole $array is requested
Andrey Andreevef29f832014-12-02 18:03:47 +0200182 isset($index) OR $index = array_keys($array);
183
184 // allow fetching multiple keys at once
185 if (is_array($index))
Andrey Andreev7c60b122014-02-08 18:47:19 +0200186 {
187 $output = array();
Andrey Andreev6b3bf4c2014-12-02 18:04:41 +0200188 foreach ($index as $key)
Andrey Andreev7c60b122014-02-08 18:47:19 +0200189 {
190 $output[$key] = $this->_fetch_from_array($array, $key, $xss_clean);
191 }
192
193 return $output;
194 }
195
nisheeth-barthwala7447d22013-03-21 15:48:10 +0530196 if (isset($array[$index]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000197 {
nisheeth-barthwala7447d22013-03-21 15:48:10 +0530198 $value = $array[$index];
199 }
nisheeth-barthwal47ea5a82013-03-26 18:57:28 +0530200 elseif (($count = preg_match_all('/(?:^[^\[]+)|\[[^]]*\]/', $index, $matches)) > 1) // Does the index contain array notation
nisheeth-barthwala7447d22013-03-21 15:48:10 +0530201 {
nisheeth-barthwal47ea5a82013-03-26 18:57:28 +0530202 $value = $array;
nisheeth-barthwal77236e02013-03-25 23:42:36 +0530203 for ($i = 0; $i < $count; $i++)
nisheeth-barthwala7447d22013-03-21 15:48:10 +0530204 {
nisheeth-barthwal77236e02013-03-25 23:42:36 +0530205 $key = trim($matches[0][$i], '[]');
nisheeth-barthwal408cbb42013-03-26 19:06:40 +0530206 if ($key === '') // Empty notation will return the value as array
nisheeth-barthwala7447d22013-03-21 15:48:10 +0530207 {
nisheeth-barthwal77236e02013-03-25 23:42:36 +0530208 break;
nisheeth-barthwala7447d22013-03-21 15:48:10 +0530209 }
nisheeth-barthwal47ea5a82013-03-26 18:57:28 +0530210
211 if (isset($value[$key]))
nisheeth-barthwala7447d22013-03-21 15:48:10 +0530212 {
nisheeth-barthwal47ea5a82013-03-26 18:57:28 +0530213 $value = $value[$key];
nisheeth-barthwal77236e02013-03-25 23:42:36 +0530214 }
215 else
216 {
217 return NULL;
nisheeth-barthwala7447d22013-03-21 15:48:10 +0530218 }
219 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000220 }
nisheeth-barthwal77236e02013-03-25 23:42:36 +0530221 else
Derek Allard2067d1a2008-11-13 22:59:24 +0000222 {
nisheeth-barthwal77236e02013-03-25 23:42:36 +0530223 return NULL;
Derek Allard2067d1a2008-11-13 22:59:24 +0000224 }
225
nisheeth-barthwal77236e02013-03-25 23:42:36 +0530226 return ($xss_clean === TRUE)
227 ? $this->security->xss_clean($value)
228 : $value;
Derek Allard2067d1a2008-11-13 22:59:24 +0000229 }
230
231 // --------------------------------------------------------------------
232
233 /**
Timothy Warren40403d22012-04-19 16:38:50 -0400234 * Fetch an item from the GET array
235 *
Ahmad Anbarff89a4e2014-12-02 17:26:30 +0200236 * @param mixed $index Index for item to be fetched from $_GET
Andrey Andreev1887ec62012-10-27 16:22:07 +0300237 * @param bool $xss_clean Whether to apply XSS filtering
238 * @return mixed
Timothy Warren40403d22012-04-19 16:38:50 -0400239 */
Andrey Andreev80a16b12014-01-08 17:19:03 +0200240 public function get($index = NULL, $xss_clean = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000241 {
nisheeth-barthwala5bcfb12013-03-23 10:53:51 +0530242 return $this->_fetch_from_array($_GET, $index, $xss_clean);
Derek Allard2067d1a2008-11-13 22:59:24 +0000243 }
244
245 // --------------------------------------------------------------------
246
247 /**
Timothy Warren40403d22012-04-19 16:38:50 -0400248 * Fetch an item from the POST array
249 *
Ahmad Anbarff89a4e2014-12-02 17:26:30 +0200250 * @param mixed $index Index for item to be fetched from $_POST
Andrey Andreev1887ec62012-10-27 16:22:07 +0300251 * @param bool $xss_clean Whether to apply XSS filtering
252 * @return mixed
Timothy Warren40403d22012-04-19 16:38:50 -0400253 */
Andrey Andreev80a16b12014-01-08 17:19:03 +0200254 public function post($index = NULL, $xss_clean = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000255 {
nisheeth-barthwala5bcfb12013-03-23 10:53:51 +0530256 return $this->_fetch_from_array($_POST, $index, $xss_clean);
Derek Allard2067d1a2008-11-13 22:59:24 +0000257 }
258
259 // --------------------------------------------------------------------
260
261 /**
Andrey Andreev1887ec62012-10-27 16:22:07 +0300262 * Fetch an item from POST data with fallback to GET
Timothy Warren40403d22012-04-19 16:38:50 -0400263 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300264 * @param string $index Index for item to be fetched from $_POST or $_GET
265 * @param bool $xss_clean Whether to apply XSS filtering
266 * @return mixed
Timothy Warren40403d22012-04-19 16:38:50 -0400267 */
Andrey Andreev7c60b122014-02-08 18:47:19 +0200268 public function post_get($index, $xss_clean = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000269 {
Andrey Andreev9448afb2012-02-08 19:49:19 +0200270 return isset($_POST[$index])
nisheeth-barthwala5bcfb12013-03-23 10:53:51 +0530271 ? $this->post($index, $xss_clean)
272 : $this->get($index, $xss_clean);
Derek Allard2067d1a2008-11-13 22:59:24 +0000273 }
274
275 // --------------------------------------------------------------------
276
277 /**
vlakoff441fd262013-08-11 20:36:41 +0200278 * Fetch an item from GET data with fallback to POST
279 *
280 * @param string $index Index for item to be fetched from $_GET or $_POST
281 * @param bool $xss_clean Whether to apply XSS filtering
282 * @return mixed
283 */
Andrey Andreev7c60b122014-02-08 18:47:19 +0200284 public function get_post($index, $xss_clean = NULL)
vlakoff441fd262013-08-11 20:36:41 +0200285 {
286 return isset($_GET[$index])
287 ? $this->get($index, $xss_clean)
288 : $this->post($index, $xss_clean);
289 }
290
291 // --------------------------------------------------------------------
292
293 /**
Timothy Warren40403d22012-04-19 16:38:50 -0400294 * Fetch an item from the COOKIE array
295 *
Ahmad Anbarff89a4e2014-12-02 17:26:30 +0200296 * @param mixed $index Index for item to be fetched from $_COOKIE
Andrey Andreev1887ec62012-10-27 16:22:07 +0300297 * @param bool $xss_clean Whether to apply XSS filtering
298 * @return mixed
Timothy Warren40403d22012-04-19 16:38:50 -0400299 */
Andrey Andreev7c60b122014-02-08 18:47:19 +0200300 public function cookie($index = NULL, $xss_clean = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000301 {
nisheeth-barthwala5bcfb12013-03-23 10:53:51 +0530302 return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
Derek Allard2067d1a2008-11-13 22:59:24 +0000303 }
304
Andrey Andreev1887ec62012-10-27 16:22:07 +0300305 // --------------------------------------------------------------------
306
307 /**
308 * Fetch an item from the SERVER array
309 *
Ahmad Anbarff89a4e2014-12-02 17:26:30 +0200310 * @param mixed $index Index for item to be fetched from $_SERVER
Andrey Andreev1887ec62012-10-27 16:22:07 +0300311 * @param bool $xss_clean Whether to apply XSS filtering
312 * @return mixed
313 */
Andrey Andreev7c60b122014-02-08 18:47:19 +0200314 public function server($index, $xss_clean = NULL)
Andrey Andreev1887ec62012-10-27 16:22:07 +0300315 {
316 return $this->_fetch_from_array($_SERVER, $index, $xss_clean);
317 }
318
Derek Jones69fc4fc2010-03-02 13:36:31 -0600319 // ------------------------------------------------------------------------
320
321 /**
Andrey Andreev303eef02012-11-06 14:55:48 +0200322 * Fetch an item from the php://input stream
323 *
324 * Useful when you need to access PUT, DELETE or PATCH request data.
325 *
326 * @param string $index Index for item to be fetched
327 * @param bool $xss_clean Whether to apply XSS filtering
328 * @return mixed
329 */
Andrey Andreev7c60b122014-02-08 18:47:19 +0200330 public function input_stream($index = NULL, $xss_clean = NULL)
Andrey Andreev303eef02012-11-06 14:55:48 +0200331 {
Andrey Andreevdc134a82014-05-08 10:00:55 +0300332 // Prior to PHP 5.6, the input stream can only be read once,
333 // so we'll need to check if we have already done that first.
Andrey Andreev303eef02012-11-06 14:55:48 +0200334 if ( ! is_array($this->_input_stream))
335 {
Ignasimgcae95882015-02-26 02:46:14 +0100336 // $this->raw_input_stream will trigger __get().
Ignasimg0b5569f2015-02-20 17:56:55 +0100337 parse_str($this->raw_input_stream, $this->_input_stream);
Andrey Andreev7c60b122014-02-08 18:47:19 +0200338 is_array($this->_input_stream) OR $this->_input_stream = array();
Andrey Andreev303eef02012-11-06 14:55:48 +0200339 }
340
341 return $this->_fetch_from_array($this->_input_stream, $index, $xss_clean);
342 }
343
344 // ------------------------------------------------------------------------
345
346 /**
Timothy Warren40403d22012-04-19 16:38:50 -0400347 * Set cookie
348 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300349 * Accepts an arbitrary number of parameters (up to 7) or an associative
Timothy Warren40403d22012-04-19 16:38:50 -0400350 * array in the first parameter containing all the values.
351 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300352 * @param string|mixed[] $name Cookie name or an array containing parameters
353 * @param string $value Cookie value
354 * @param int $expire Cookie expiration time in seconds
355 * @param string $domain Cookie domain (e.g.: '.yourdomain.com')
356 * @param string $path Cookie path (default: '/')
357 * @param string $prefix Cookie name prefix
358 * @param bool $secure Whether to only transfer cookies via SSL
359 * @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript)
Timothy Warren40403d22012-04-19 16:38:50 -0400360 * @return void
361 */
Andrey Andreev422b8892017-02-01 14:36:49 +0200362 public function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL)
Derek Jones69fc4fc2010-03-02 13:36:31 -0600363 {
364 if (is_array($name))
365 {
tobiasbg9aa7dc92011-02-18 21:57:13 +0100366 // always leave 'name' in last place, as the loop will break otherwise, due to $$item
freewil4ad0fd82012-03-13 22:37:42 -0400367 foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name') as $item)
Derek Jones69fc4fc2010-03-02 13:36:31 -0600368 {
369 if (isset($name[$item]))
370 {
371 $$item = $name[$item];
372 }
373 }
374 }
375
Alex Bilbieed944a32012-06-02 11:07:47 +0100376 if ($prefix === '' && config_item('cookie_prefix') !== '')
Derek Jones69fc4fc2010-03-02 13:36:31 -0600377 {
378 $prefix = config_item('cookie_prefix');
379 }
Andrey Andreev9ba661b2012-06-04 14:44:34 +0300380
381 if ($domain == '' && config_item('cookie_domain') != '')
Derek Jones69fc4fc2010-03-02 13:36:31 -0600382 {
383 $domain = config_item('cookie_domain');
384 }
Andrey Andreev9ba661b2012-06-04 14:44:34 +0300385
Alex Bilbieed944a32012-06-02 11:07:47 +0100386 if ($path === '/' && config_item('cookie_path') !== '/')
Derek Jones69fc4fc2010-03-02 13:36:31 -0600387 {
388 $path = config_item('cookie_path');
389 }
Andrey Andreev9ba661b2012-06-04 14:44:34 +0300390
Andrey Andreev422b8892017-02-01 14:36:49 +0200391 $secure = ($secure === NULL && config_item('cookie_secure') !== NULL)
392 ? (bool) config_item('cookie_secure')
393 : (bool) $secure;
Andrey Andreev9ba661b2012-06-04 14:44:34 +0300394
Andrey Andreev422b8892017-02-01 14:36:49 +0200395 $httponly = ($httponly === NULL && config_item('cookie_httponly') !== NULL)
396 ? (bool) config_item('cookie_httponly')
397 : (bool) $httponly;
Derek Jones69fc4fc2010-03-02 13:36:31 -0600398
399 if ( ! is_numeric($expire))
400 {
401 $expire = time() - 86500;
402 }
403 else
404 {
Phil Sturgeonc8089152010-12-27 19:06:28 +0000405 $expire = ($expire > 0) ? time() + $expire : 0;
Derek Jones69fc4fc2010-03-02 13:36:31 -0600406 }
407
freewil4ad0fd82012-03-13 22:37:42 -0400408 setcookie($prefix.$name, $value, $expire, $path, $domain, $secure, $httponly);
Derek Jones69fc4fc2010-03-02 13:36:31 -0600409 }
410
Derek Allard2067d1a2008-11-13 22:59:24 +0000411 // --------------------------------------------------------------------
412
413 /**
Timothy Warren40403d22012-04-19 16:38:50 -0400414 * Fetch the IP Address
415 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300416 * Determines and validates the visitor's IP address.
417 *
418 * @return string IP address
Timothy Warren40403d22012-04-19 16:38:50 -0400419 */
Bo-Yi Wu4db872f2011-09-12 10:52:37 +0800420 public function ip_address()
Derek Allard2067d1a2008-11-13 22:59:24 +0000421 {
422 if ($this->ip_address !== FALSE)
423 {
424 return $this->ip_address;
425 }
Barry Mienydd671972010-10-04 16:33:58 +0200426
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300427 $proxy_ips = config_item('proxy_ips');
Andrey Andreevea7a8662012-10-09 13:36:31 +0300428 if ( ! empty($proxy_ips) && ! is_array($proxy_ips))
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300429 {
430 $proxy_ips = explode(',', str_replace(' ', '', $proxy_ips));
431 }
Andrey Andreev5b92ae12012-10-04 13:05:03 +0300432
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300433 $this->ip_address = $this->server('REMOTE_ADDR');
434
435 if ($proxy_ips)
436 {
437 foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP') as $header)
Jordan Pittman8960acf2012-07-23 09:05:49 -0300438 {
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300439 if (($spoof = $this->server($header)) !== NULL)
Jordan Pittman8960acf2012-07-23 09:05:49 -0300440 {
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300441 // Some proxies typically list the whole chain of IP
442 // addresses through which the client has reached us.
443 // e.g. client_ip, proxy_ip1, proxy_ip2, etc.
Andrey Andreeve24eed72012-11-02 23:33:45 +0200444 sscanf($spoof, '%[^,]', $spoof);
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300445
446 if ( ! $this->valid_ip($spoof))
447 {
448 $spoof = NULL;
449 }
450 else
451 {
Jordan Pittmana5a71352012-07-20 19:36:43 -0300452 break;
453 }
454 }
Andrey Andreev5b92ae12012-10-04 13:05:03 +0300455 }
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300456
Andrey Andreeve45ad2b2012-10-09 13:11:15 +0300457 if ($spoof)
Andrey Andreev5b92ae12012-10-04 13:05:03 +0300458 {
Andrey Andreev9df35b42012-10-09 13:37:58 +0300459 for ($i = 0, $c = count($proxy_ips); $i < $c; $i++)
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300460 {
461 // Check if we have an IP address or a subnet
462 if (strpos($proxy_ips[$i], '/') === FALSE)
463 {
464 // An IP address (and not a subnet) is specified.
465 // We can compare right away.
466 if ($proxy_ips[$i] === $this->ip_address)
467 {
468 $this->ip_address = $spoof;
469 break;
470 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000471
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300472 continue;
473 }
474
475 // We have a subnet ... now the heavy lifting begins
476 isset($separator) OR $separator = $this->valid_ip($this->ip_address, 'ipv6') ? ':' : '.';
477
478 // If the proxy entry doesn't match the IP protocol - skip it
479 if (strpos($proxy_ips[$i], $separator) === FALSE)
480 {
481 continue;
482 }
483
484 // Convert the REMOTE_ADDR IP address to binary, if needed
Andrey Andreev82d2cf12012-10-13 12:38:42 +0300485 if ( ! isset($ip, $sprintf))
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300486 {
487 if ($separator === ':')
488 {
489 // Make sure we're have the "full" IPv6 format
Andrey Andreev82d2cf12012-10-13 12:38:42 +0300490 $ip = explode(':',
491 str_replace('::',
492 str_repeat(':', 9 - substr_count($this->ip_address, ':')),
493 $this->ip_address
494 )
495 );
496
Heesung Ahn0fc46ca2015-03-18 18:49:22 -0400497 for ($j = 0; $j < 8; $j++)
Andrey Andreev82d2cf12012-10-13 12:38:42 +0300498 {
Heesung Ahn0fc46ca2015-03-18 18:49:22 -0400499 $ip[$j] = intval($ip[$j], 16);
Andrey Andreev82d2cf12012-10-13 12:38:42 +0300500 }
501
502 $sprintf = '%016b%016b%016b%016b%016b%016b%016b%016b';
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300503 }
504 else
505 {
Andrey Andreev82d2cf12012-10-13 12:38:42 +0300506 $ip = explode('.', $this->ip_address);
507 $sprintf = '%08b%08b%08b%08b';
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300508 }
509
Andrey Andreev82d2cf12012-10-13 12:38:42 +0300510 $ip = vsprintf($sprintf, $ip);
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300511 }
512
513 // Split the netmask length off the network address
Andrey Andreeve24eed72012-11-02 23:33:45 +0200514 sscanf($proxy_ips[$i], '%[^/]/%d', $netaddr, $masklen);
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300515
516 // Again, an IPv6 address is most likely in a compressed form
517 if ($separator === ':')
518 {
Andrey Andreev82d2cf12012-10-13 12:38:42 +0300519 $netaddr = explode(':', str_replace('::', str_repeat(':', 9 - substr_count($netaddr, ':')), $netaddr));
Andrey Andreev9fd92482016-07-19 14:04:17 +0300520 for ($j = 0; $j < 8; $j++)
Andrey Andreev82d2cf12012-10-13 12:38:42 +0300521 {
Andrey Andreev3a89d3c2016-11-03 16:26:31 +0200522 $netaddr[$j] = intval($netaddr[$j], 16);
Andrey Andreev82d2cf12012-10-13 12:38:42 +0300523 }
524 }
525 else
526 {
527 $netaddr = explode('.', $netaddr);
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300528 }
529
Andrey Andreev82d2cf12012-10-13 12:38:42 +0300530 // Convert to binary and finally compare
531 if (strncmp($ip, vsprintf($sprintf, $netaddr), $masklen) === 0)
Andrey Andreev9ac557f2012-10-06 20:27:57 +0300532 {
533 $this->ip_address = $spoof;
534 break;
535 }
536 }
537 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000538 }
539
Derek Allard2067d1a2008-11-13 22:59:24 +0000540 if ( ! $this->valid_ip($this->ip_address))
541 {
Andrey Andreev64e98aa2012-01-07 20:29:10 +0200542 return $this->ip_address = '0.0.0.0';
Derek Allard2067d1a2008-11-13 22:59:24 +0000543 }
544
545 return $this->ip_address;
546 }
547
548 // --------------------------------------------------------------------
549
550 /**
Timothy Warren40403d22012-04-19 16:38:50 -0400551 * Validate IP Address
552 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300553 * @param string $ip IP address
554 * @param string $which IP protocol: 'ipv4' or 'ipv6'
Timothy Warren40403d22012-04-19 16:38:50 -0400555 * @return bool
556 */
Andrey Andreev5a257182012-06-10 06:18:14 +0300557 public function valid_ip($ip, $which = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000558 {
Andrey Andreev5a257182012-06-10 06:18:14 +0300559 switch (strtolower($which))
560 {
561 case 'ipv4':
562 $which = FILTER_FLAG_IPV4;
563 break;
564 case 'ipv6':
565 $which = FILTER_FLAG_IPV6;
566 break;
567 default:
568 $which = NULL;
569 break;
570 }
571
572 return (bool) filter_var($ip, FILTER_VALIDATE_IP, $which);
Derek Allard2067d1a2008-11-13 22:59:24 +0000573 }
574
575 // --------------------------------------------------------------------
576
577 /**
Andrey Andreev1887ec62012-10-27 16:22:07 +0300578 * Fetch User Agent string
Timothy Warren40403d22012-04-19 16:38:50 -0400579 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300580 * @return string|null User Agent string or NULL if it doesn't exist
Timothy Warren40403d22012-04-19 16:38:50 -0400581 */
Andrey Andreev8850e372014-02-27 21:56:06 +0200582 public function user_agent($xss_clean = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000583 {
Andrey Andreev8850e372014-02-27 21:56:06 +0200584 return $this->_fetch_from_array($_SERVER, 'HTTP_USER_AGENT', $xss_clean);
Derek Allard2067d1a2008-11-13 22:59:24 +0000585 }
586
587 // --------------------------------------------------------------------
588
589 /**
Timothy Warren40403d22012-04-19 16:38:50 -0400590 * Sanitize Globals
591 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300592 * Internal method serving for the following purposes:
Timothy Warren40403d22012-04-19 16:38:50 -0400593 *
Andrey Andreevb78a8c72014-04-15 17:21:16 +0300594 * - Unsets $_GET data, if query strings are not enabled
Andrey Andreev1887ec62012-10-27 16:22:07 +0300595 * - Cleans POST, COOKIE and SERVER data
596 * - Standardizes newline characters to PHP_EOL
Timothy Warren40403d22012-04-19 16:38:50 -0400597 *
598 * @return void
599 */
Andrey Andreev90cfe142012-01-08 04:46:42 +0200600 protected function _sanitize_globals()
Derek Allard2067d1a2008-11-13 22:59:24 +0000601 {
Derek Jones69fc4fc2010-03-02 13:36:31 -0600602 // Is $_GET data allowed? If not we'll set the $_GET to an empty array
Alex Bilbieed944a32012-06-02 11:07:47 +0100603 if ($this->_allow_get_array === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000604 {
Derek Jones69fc4fc2010-03-02 13:36:31 -0600605 $_GET = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000606 }
Andrey Andreeve70238e2015-09-07 16:07:45 +0300607 elseif (is_array($_GET))
Derek Allard2067d1a2008-11-13 22:59:24 +0000608 {
Andrey Andreev9448afb2012-02-08 19:49:19 +0200609 foreach ($_GET as $key => $val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000610 {
Andrey Andreev9448afb2012-02-08 19:49:19 +0200611 $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
Derek Allard2067d1a2008-11-13 22:59:24 +0000612 }
613 }
614
Derek Jones69fc4fc2010-03-02 13:36:31 -0600615 // Clean $_POST Data
Andrey Andreeve70238e2015-09-07 16:07:45 +0300616 if (is_array($_POST))
Derek Allard2067d1a2008-11-13 22:59:24 +0000617 {
Pascal Kriete5d5895f2011-02-14 13:27:07 -0500618 foreach ($_POST as $key => $val)
Derek Jones69fc4fc2010-03-02 13:36:31 -0600619 {
620 $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
621 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000622 }
623
Derek Jones69fc4fc2010-03-02 13:36:31 -0600624 // Clean $_COOKIE Data
Andrey Andreeve70238e2015-09-07 16:07:45 +0300625 if (is_array($_COOKIE))
Derek Allard2067d1a2008-11-13 22:59:24 +0000626 {
Derek Jones69fc4fc2010-03-02 13:36:31 -0600627 // Also get rid of specially treated cookies that might be set by a server
628 // or silly application, that are of no use to a CI application anyway
629 // but that when present will trip our 'Disallowed Key Characters' alarm
630 // http://www.ietf.org/rfc/rfc2109.txt
631 // note that the key names below are single quoted strings, and are not PHP variables
Andrey Andreev5ac428b2014-01-08 16:07:31 +0200632 unset(
633 $_COOKIE['$Version'],
634 $_COOKIE['$Path'],
635 $_COOKIE['$Domain']
636 );
Derek Jones69fc4fc2010-03-02 13:36:31 -0600637
Pascal Kriete5d5895f2011-02-14 13:27:07 -0500638 foreach ($_COOKIE as $key => $val)
Derek Jones69fc4fc2010-03-02 13:36:31 -0600639 {
Andrey Andreevfd0aabb2013-09-23 13:18:20 +0300640 if (($cookie_key = $this->_clean_input_keys($key)) !== FALSE)
641 {
642 $_COOKIE[$cookie_key] = $this->_clean_input_data($val);
643 }
644 else
645 {
646 unset($_COOKIE[$key]);
647 }
Derek Jones69fc4fc2010-03-02 13:36:31 -0600648 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000649 }
650
Derek Jones69fc4fc2010-03-02 13:36:31 -0600651 // Sanitize PHP_SELF
652 $_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
653
Andrey Andreevfd0aabb2013-09-23 13:18:20 +0300654 log_message('debug', 'Global POST, GET and COOKIE data sanitized');
Derek Allard2067d1a2008-11-13 22:59:24 +0000655 }
656
657 // --------------------------------------------------------------------
658
659 /**
Timothy Warren40403d22012-04-19 16:38:50 -0400660 * Clean Input Data
661 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300662 * Internal method that aids in escaping data and
663 * standardizing newline characters to PHP_EOL.
Timothy Warren40403d22012-04-19 16:38:50 -0400664 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300665 * @param string|string[] $str Input string(s)
Timothy Warren40403d22012-04-19 16:38:50 -0400666 * @return string
667 */
Andrey Andreev90cfe142012-01-08 04:46:42 +0200668 protected function _clean_input_data($str)
Derek Allard2067d1a2008-11-13 22:59:24 +0000669 {
Derek Jones69fc4fc2010-03-02 13:36:31 -0600670 if (is_array($str))
Derek Allard2067d1a2008-11-13 22:59:24 +0000671 {
Derek Jones69fc4fc2010-03-02 13:36:31 -0600672 $new_array = array();
Andrey Andreev1887ec62012-10-27 16:22:07 +0300673 foreach (array_keys($str) as $key)
Derek Jones69fc4fc2010-03-02 13:36:31 -0600674 {
Andrey Andreev1887ec62012-10-27 16:22:07 +0300675 $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($str[$key]);
Derek Jones69fc4fc2010-03-02 13:36:31 -0600676 }
677 return $new_array;
Derek Allard2067d1a2008-11-13 22:59:24 +0000678 }
679
Andrey Andreevaf728622011-10-20 10:11:59 +0300680 /* We strip slashes if magic quotes is on to keep things consistent
681
682 NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and
Andrey Andreev10fb7d12015-08-03 10:05:29 +0300683 it will probably not exist in future versions at all.
Andrey Andreevaf728622011-10-20 10:11:59 +0300684 */
685 if ( ! is_php('5.4') && get_magic_quotes_gpc())
Derek Allard2067d1a2008-11-13 22:59:24 +0000686 {
Derek Jones69fc4fc2010-03-02 13:36:31 -0600687 $str = stripslashes($str);
688 }
689
690 // Clean UTF-8 if supported
691 if (UTF8_ENABLED === TRUE)
692 {
693 $str = $this->uni->clean_string($str);
694 }
David Behler9b5df592011-08-14 21:04:17 +0200695
Pascal Kriete14a0ac62011-04-05 14:55:56 -0400696 // Remove control characters
Andrey Andreev5ac428b2014-01-08 16:07:31 +0200697 $str = remove_invisible_characters($str, FALSE);
Derek Jones69fc4fc2010-03-02 13:36:31 -0600698
Derek Jones69fc4fc2010-03-02 13:36:31 -0600699 // Standardize newlines if needed
Eric Robertsb75e13d2013-01-27 20:10:09 -0600700 if ($this->_standardize_newlines === TRUE)
Derek Jones69fc4fc2010-03-02 13:36:31 -0600701 {
Eric Robertsb75e13d2013-01-27 20:10:09 -0600702 return preg_replace('/(?:\r\n|[\r\n])/', PHP_EOL, $str);
Derek Allard2067d1a2008-11-13 22:59:24 +0000703 }
704
705 return $str;
706 }
707
708 // --------------------------------------------------------------------
709
710 /**
Timothy Warren40403d22012-04-19 16:38:50 -0400711 * Clean Keys
712 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300713 * Internal method that helps to prevent malicious users
Timothy Warren40403d22012-04-19 16:38:50 -0400714 * from trying to exploit keys we make sure that keys are
715 * only named with alpha-numeric text and a few other items.
716 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300717 * @param string $str Input string
Ä°rfan Evrensd02a69a2015-02-06 20:53:22 +0200718 * @param bool $fatal Whether to terminate script exection
Andrey Andreevfd0aabb2013-09-23 13:18:20 +0300719 * or to return FALSE if an invalid
720 * key is encountered
721 * @return string|bool
Timothy Warren40403d22012-04-19 16:38:50 -0400722 */
Andrey Andreevfd0aabb2013-09-23 13:18:20 +0300723 protected function _clean_input_keys($str, $fatal = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000724 {
bigCat3c0846b2012-08-21 00:20:20 +0800725 if ( ! preg_match('/^[a-z0-9:_\/|-]+$/i', $str))
Derek Allard2067d1a2008-11-13 22:59:24 +0000726 {
Andrey Andreevfd0aabb2013-09-23 13:18:20 +0300727 if ($fatal === TRUE)
728 {
729 return FALSE;
730 }
731 else
732 {
733 set_status_header(503);
734 echo 'Disallowed Key Characters.';
Andrey Andreev7cf682a2014-03-13 14:55:45 +0200735 exit(7); // EXIT_USER_INPUT
Andrey Andreevfd0aabb2013-09-23 13:18:20 +0300736 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000737 }
738
Derek Jones69fc4fc2010-03-02 13:36:31 -0600739 // Clean UTF-8 if supported
740 if (UTF8_ENABLED === TRUE)
741 {
Andrey Andreev64e98aa2012-01-07 20:29:10 +0200742 return $this->uni->clean_string($str);
Derek Jones69fc4fc2010-03-02 13:36:31 -0600743 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000744
Derek Jones69fc4fc2010-03-02 13:36:31 -0600745 return $str;
746 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000747
Greg Akerec2f5712010-11-15 16:22:12 -0600748 // --------------------------------------------------------------------
749
750 /**
751 * Request Headers
752 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300753 * @param bool $xss_clean Whether to apply XSS filtering
Andrey Andreev64e98aa2012-01-07 20:29:10 +0200754 * @return array
Greg Akerec2f5712010-11-15 16:22:12 -0600755 */
756 public function request_headers($xss_clean = FALSE)
757 {
CJ71cff1d2013-04-16 21:50:55 +0800758 // If header is already defined, return it immediately
759 if ( ! empty($this->headers))
760 {
Andrey Andreevcd3d5952016-04-04 10:28:31 +0300761 return $this->_fetch_from_array($this->headers, NULL, $xss_clean);
CJ71cff1d2013-04-16 21:50:55 +0800762 }
763
Andrey Andreev1887ec62012-10-27 16:22:07 +0300764 // In Apache, you can simply call apache_request_headers()
Greg Akerec2f5712010-11-15 16:22:12 -0600765 if (function_exists('apache_request_headers'))
766 {
Andrey Andreevcd3d5952016-04-04 10:28:31 +0300767 $this->headers = apache_request_headers();
Greg Akerec2f5712010-11-15 16:22:12 -0600768 }
Andrey Andreevcd3d5952016-04-04 10:28:31 +0300769 else
Greg Akerec2f5712010-11-15 16:22:12 -0600770 {
Andrey Andreevcd3d5952016-04-04 10:28:31 +0300771 isset($_SERVER['CONTENT_TYPE']) && $this->headers['Content-Type'] = $_SERVER['CONTENT_TYPE'];
Greg Akerec2f5712010-11-15 16:22:12 -0600772
Andrey Andreevcd3d5952016-04-04 10:28:31 +0300773 foreach ($_SERVER as $key => $val)
774 {
775 if (sscanf($key, 'HTTP_%s', $header) === 1)
776 {
777 // take SOME_HEADER and turn it into Some-Header
778 $header = str_replace('_', ' ', strtolower($header));
779 $header = str_replace(' ', '-', ucwords($header));
780
781 $this->headers[$header] = $_SERVER[$key];
782 }
CJ826990f2013-04-16 14:17:53 +0800783 }
Greg Akerec2f5712010-11-15 16:22:12 -0600784 }
David Behler9b5df592011-08-14 21:04:17 +0200785
Andrey Andreevcd3d5952016-04-04 10:28:31 +0300786 return $this->_fetch_from_array($this->headers, NULL, $xss_clean);
Greg Akerec2f5712010-11-15 16:22:12 -0600787 }
788
789 // --------------------------------------------------------------------
790
791 /**
792 * Get Request Header
793 *
794 * Returns the value of a single member of the headers class member
795 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300796 * @param string $index Header name
797 * @param bool $xss_clean Whether to apply XSS filtering
Adriano Rosaf112e4a2014-10-03 13:15:46 -0300798 * @return string|null The requested header on success or NULL on failure
Greg Akerec2f5712010-11-15 16:22:12 -0600799 */
800 public function get_request_header($index, $xss_clean = FALSE)
801 {
Andrey Andreevb7639482015-06-08 14:44:47 +0300802 static $headers;
803
804 if ( ! isset($headers))
Greg Akerec2f5712010-11-15 16:22:12 -0600805 {
Andrey Andreevd45180c2015-08-15 09:09:38 +0300806 empty($this->headers) && $this->request_headers();
Andrey Andreevb7639482015-06-08 14:44:47 +0300807 foreach ($this->headers as $key => $value)
808 {
809 $headers[strtolower($key)] = $value;
810 }
Greg Akerec2f5712010-11-15 16:22:12 -0600811 }
David Behler9b5df592011-08-14 21:04:17 +0200812
Andrey Andreevb7639482015-06-08 14:44:47 +0300813 $index = strtolower($index);
814
815 if ( ! isset($headers[$index]))
Greg Akerec2f5712010-11-15 16:22:12 -0600816 {
Phil Sturgeon55a6ddb2012-05-23 18:37:24 +0100817 return NULL;
Greg Akerec2f5712010-11-15 16:22:12 -0600818 }
819
Andrey Andreev9448afb2012-02-08 19:49:19 +0200820 return ($xss_clean === TRUE)
Andrey Andreevb7639482015-06-08 14:44:47 +0300821 ? $this->security->xss_clean($headers[$index])
822 : $headers[$index];
Greg Akerec2f5712010-11-15 16:22:12 -0600823 }
824
Greg Aker081ac9d2010-11-22 14:42:53 -0600825 // --------------------------------------------------------------------
Phil Sturgeonc3828712011-01-19 12:31:47 +0000826
Greg Aker081ac9d2010-11-22 14:42:53 -0600827 /**
Andrey Andreev1887ec62012-10-27 16:22:07 +0300828 * Is AJAX request?
Greg Aker081ac9d2010-11-22 14:42:53 -0600829 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300830 * Test to see if a request contains the HTTP_X_REQUESTED_WITH header.
Greg Aker081ac9d2010-11-22 14:42:53 -0600831 *
Andrey Andreev9448afb2012-02-08 19:49:19 +0200832 * @return bool
Greg Aker081ac9d2010-11-22 14:42:53 -0600833 */
834 public function is_ajax_request()
835 {
Andrey Andreev9448afb2012-02-08 19:49:19 +0200836 return ( ! empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
Greg Aker081ac9d2010-11-22 14:42:53 -0600837 }
838
Phil Sturgeonc3828712011-01-19 12:31:47 +0000839 // --------------------------------------------------------------------
840
841 /**
Andrey Andreev1887ec62012-10-27 16:22:07 +0300842 * Is CLI request?
Phil Sturgeonc3828712011-01-19 12:31:47 +0000843 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300844 * Test to see if a request was made from the command line.
Phil Sturgeonc3828712011-01-19 12:31:47 +0000845 *
Andrey Andreevf964b162013-11-12 17:04:55 +0200846 * @deprecated 3.0.0 Use is_cli() instead
Andrey Andreev10fb7d12015-08-03 10:05:29 +0300847 * @return bool
Phil Sturgeonc3828712011-01-19 12:31:47 +0000848 */
849 public function is_cli_request()
850 {
Andrey Andreevf964b162013-11-12 17:04:55 +0200851 return is_cli();
Phil Sturgeonc3828712011-01-19 12:31:47 +0000852 }
853
Michiel Vugteveenbe0ca262012-03-07 19:09:51 +0100854 // --------------------------------------------------------------------
855
856 /**
857 * Get Request Method
858 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300859 * Return the request method
Michiel Vugteveenbe0ca262012-03-07 19:09:51 +0100860 *
Andrey Andreev1887ec62012-10-27 16:22:07 +0300861 * @param bool $upper Whether to return in upper or lower case
862 * (default: FALSE)
863 * @return string
Michiel Vugteveenbe0ca262012-03-07 19:09:51 +0100864 */
Michiel Vugteveen704fb162012-03-07 20:42:33 +0100865 public function method($upper = FALSE)
Michiel Vugteveenbe0ca262012-03-07 19:09:51 +0100866 {
Michiel Vugteveendc900df2012-03-07 20:41:37 +0100867 return ($upper)
868 ? strtoupper($this->server('REQUEST_METHOD'))
869 : strtolower($this->server('REQUEST_METHOD'));
Michiel Vugteveenbe0ca262012-03-07 19:09:51 +0100870 }
871
Andrey Andreevd0ac8b12015-02-27 11:41:52 +0200872 // ------------------------------------------------------------------------
873
874 /**
875 * Magic __get()
876 *
877 * Allows read access to protected properties
878 *
879 * @param string $name
880 * @return mixed
881 */
882 public function __get($name)
883 {
884 if ($name === 'raw_input_stream')
885 {
886 isset($this->_raw_input_stream) OR $this->_raw_input_stream = file_get_contents('php://input');
887 return $this->_raw_input_stream;
888 }
Andrey Andreev52caf592015-02-27 15:09:34 +0200889 elseif ($name === 'ip_address')
890 {
891 return $this->ip_address;
892 }
Andrey Andreevd0ac8b12015-02-27 11:41:52 +0200893 }
894
Derek Allard2067d1a2008-11-13 22:59:24 +0000895}