首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > PHP >

CI框架源码翻阅-Input.php

2013-03-13 
CI框架源码阅读---------Input.php?phpif ( ! defined(BASEPATH)) exit(No direct script access allo

CI框架源码阅读---------Input.php

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');/** * CodeIgniter * * An open source application development framework for PHP 5.1.6 or newer * * @packageCodeIgniter * @authorExpressionEngine Dev Team * @copyrightCopyright (c) 2008 - 2011, EllisLab, Inc. * @licensehttp://codeigniter.com/user_guide/license.html * @linkhttp://codeigniter.com * @sinceVersion 1.0 * @filesource */// ------------------------------------/** * Input Class *  * Pre-processes global input data for security * * @packageCodeIgniter * @subpackageLibraries * @categoryInput * @authorExpressionEngine Dev Team * @linkhttp://codeigniter.com/user_guide/libraries/input.html */class CI_Input {/** * IP address of the current user * 当前用户的ip地址 * @var string */var $ip_address= FALSE;/** * user agent (web browser) being used by the current user * 当前用户(web浏览器)代理 * @var string */var $user_agent= FALSE;/** * If FALSE, then $_GET will be set to an empty array * 如果是FALSE , $_GET将被设置为空数组 * @var bool */var $_allow_get_array= TRUE;/** * If TRUE, then newlines are standardized * 如果为TRUR,新行将被标准化 * * @var bool */var $_standardize_newlines= TRUE;/** * Determines whether the XSS filter is always active when GET, POST or COOKIE data is encountered * Set automatically based on config setting * 决定是否总是在GET ,POST , COOKIE数据中进行XSS过滤     * 在配置选项里面配置是否自动开启 *  * @var bool */var $_enable_xss= FALSE;/** * Enables a CSRF cookie token to be set. * Set automatically based on config setting * 允许CSRF cookie令牌 * * @var bool */var $_enable_csrf= FALSE;/** * List of all HTTP request headers * HTTP请求头部的列表 * @var array */protected $headers= array();/** * Constructor * 设置是否全局允许XSS处理和是否允许使用$_GET数组 * Sets whether to globally enable the XSS processing * and whether to allow the $_GET array * * @returnvoid */public function __construct(){log_message('debug', "Input Class Initialized");// 从配置文件中获取是否进行全局允许使用$_GET XSS过滤和csrf保护$this->_allow_get_array= (config_item('allow_get_array') === TRUE);$this->_enable_xss= (config_item('global_xss_filtering') === TRUE);$this->_enable_csrf= (config_item('csrf_protection') === TRUE);// 清除globals变量,在开启了globals_register的情况下,相当于关闭了此配置。// 开启一道 安全防护global $SEC;$this->security =& $SEC;// Do we need the UTF-8 class?if (UTF8_ENABLED === TRUE){global $UNI;$this->uni =& $UNI;}// Sanitize global arrays$this->_sanitize_globals();}// --------------------------------/** * Fetch from array * 从$array获取值,如果设置了xss_clean 那么进行过滤  * This is a helper function to retrieve 检索 values from global arrays * 这是一个帮助函数用来从全局数组中检索 * * @accessprivate * @paramarray * @paramstring * @parambool * @returnstring */function _fetch_from_array(&$array, $index = '', $xss_clean = FALSE){if ( ! isset($array[$index])){return FALSE;}if ($xss_clean === TRUE){return $this->security->xss_clean($array[$index]);}return $array[$index];}// --------------------------------/*** Fetch an item from the GET array* 获取过滤后的GET数组* @accesspublic* @paramstring* @parambool* @returnstring*/function get($index = NULL, $xss_clean = FALSE){// Check if a field has been provided// 检查是否一个字段已经被提供if ($index === NULL AND ! empty($_GET)){$get = array();// loop through the full _GET array// 遍历_GET数组foreach (array_keys($_GET) as $key){$get[$key] = $this->_fetch_from_array($_GET, $key, $xss_clean);}return $get;}return $this->_fetch_from_array($_GET, $index, $xss_clean);}// --------------------------------/*** Fetch an item from the POST array* 获取过滤后的$_POST值* @accesspublic* @paramstring* @parambool* @returnstring*/function post($index = NULL, $xss_clean = FALSE){// Check if a field has been providedif ($index === NULL AND ! empty($_POST)){$post = array();// Loop through the full _POST array and return itforeach (array_keys($_POST) as $key){$post[$key] = $this->_fetch_from_array($_POST, $key, $xss_clean);}return $post;}return $this->_fetch_from_array($_POST, $index, $xss_clean);}// --------------------------------/*** Fetch an item from either the GET array or the POST* 从get和post中获取值, post优先* @accesspublic* @paramstringThe index key* @paramboolXSS cleaning* @returnstring*/function get_post($index = '', $xss_clean = FALSE){if ( ! isset($_POST[$index]) ){return $this->get($index, $xss_clean);}else{return $this->post($index, $xss_clean);}}// --------------------------------/*** Fetch an item from the COOKIE array* 返回过滤后的COOKIE值* @accesspublic* @paramstring* @parambool* @returnstring*/function cookie($index = '', $xss_clean = FALSE){return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);}// ------------------------------------/*** Set cookie** Accepts six parameter, or you can submit an associative* array in the first parameter containing all the values.* 接收6个参数或者接收一个关联数组里面包含所有的值* @accesspublic* @parammixed* @paramstringthe value of the cookie* @paramstringthe number of seconds until expiration* @paramstringthe cookie domain.  Usually:  .yourdomain.com* @paramstringthe cookie path* @paramstringthe cookie prefix* @parambooltrue makes the cookie secure* @returnvoid*/function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE){// 如果第一个值是数组 将数组中的值分别赋值给留个参数if (is_array($name)){// always leave 'name' in last place, as the loop will break otherwise, due to $$itemforeach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'name') as $item){if (isset($name[$item])){$$item = $name[$item];}}}// 如果某个参数为默认值但是config.php中的配置不是默认值// 则使用config.php中的配置值if ($prefix == '' AND config_item('cookie_prefix') != ''){$prefix = config_item('cookie_prefix');}if ($domain == '' AND config_item('cookie_domain') != ''){$domain = config_item('cookie_domain');}if ($path == '/' AND config_item('cookie_path') != '/'){$path = config_item('cookie_path');}if ($secure == FALSE AND config_item('cookie_secure') != FALSE){$secure = config_item('cookie_secure');}if ( ! is_numeric($expire)){$expire = time() - 86500;}else{$expire = ($expire > 0) ? time() + $expire : 0;}setcookie($prefix.$name, $value, $expire, $path, $domain, $secure);}// --------------------------------/*** Fetch an item from the SERVER array* 返回过滤后的$_SERVER值* @accesspublic* @paramstring* @parambool* @returnstring*/function server($index = '', $xss_clean = FALSE){return $this->_fetch_from_array($_SERVER, $index, $xss_clean);}// --------------------------------/*** Fetch the IP Address* 返回当前用户的IP。如果IP地址无效,返回0.0.0.0的IP:* @returnstring*/public function ip_address(){// 如果已经有了ip_address 则返回if ($this->ip_address !== FALSE){return $this->ip_address;}$proxy_ips = config_item('proxy_ips');if ( ! empty($proxy_ips)){$proxy_ips = explode(',', str_replace(' ', '', $proxy_ips));foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP') as $header){if (($spoof = $this->server($header)) !== FALSE){// Some proxies typically list the whole chain of IP// addresses through which the client has reached us.// e.g. client_ip, proxy_ip1, proxy_ip2, etc.if (strpos($spoof, ',') !== FALSE){$spoof = explode(',', $spoof, 2);$spoof = $spoof[0];}if ( ! $this->valid_ip($spoof)){$spoof = FALSE;}else{break;}}}$this->ip_address = ($spoof !== FALSE && in_array($_SERVER['REMOTE_ADDR'], $proxy_ips, TRUE))? $spoof : $_SERVER['REMOTE_ADDR'];}else{$this->ip_address = $_SERVER['REMOTE_ADDR'];}if ( ! $this->valid_ip($this->ip_address)){$this->ip_address = '0.0.0.0';}return $this->ip_address;}// --------------------------------/*** Validate IP Address* 测试输入的IP地址是不是有效,返回布尔值TRUE或者FALSE。 * 注意:$this->input->ip_address()自动测试输入的IP地址本身格式是不是有效。* @accesspublic* @paramstring* @paramstringipv4 or ipv6* @returnbool*/public function valid_ip($ip, $which = ''){$which = strtolower($which);// First check if filter_var is availableif (is_callable('filter_var')){switch ($which) {case 'ipv4':$flag = FILTER_FLAG_IPV4;break;case 'ipv6':$flag = FILTER_FLAG_IPV6;break;default:$flag = '';break;}return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flag);}if ($which !== 'ipv6' && $which !== 'ipv4'){if (strpos($ip, ':') !== FALSE){$which = 'ipv6';}elseif (strpos($ip, '.') !== FALSE){$which = 'ipv4';}else{return FALSE;}}$func = '_valid_'.$which;return $this->$func($ip);}// --------------------------------/*** Validate IPv4 Address* 验证ipv4地址* Updated version suggested by Geert De Deckere** @accessprotected* @paramstring* @returnbool*/protected function _valid_ipv4($ip){$ip_segments = explode('.', $ip);// Always 4 segments neededif (count($ip_segments) !== 4){return FALSE;}// IP can not start with 0if ($ip_segments[0][0] == '0'){return FALSE;}// Check each segmentforeach ($ip_segments as $segment){// IP segments must be digits and can not be// longer than 3 digits or greater then 255if ($segment == '' OR preg_match("/[^0-9]/", $segment) OR $segment > 255 OR strlen($segment) > 3){return FALSE;}}return TRUE;}// --------------------------------/*** Validate IPv6 Address* 验证ipv6地址* @accessprotected* @paramstring* @returnbool*/protected function _valid_ipv6($str){// 8 groups, separated by :// 0-ffff per group// one set of consecutive 0 groups can be collapsed to ::$groups = 8;$collapsed = FALSE;$chunks = array_filter(preg_split('/(:{1,2})/', $str, NULL, PREG_SPLIT_DELIM_CAPTURE));// Rule out easy nonsenseif (current($chunks) == ':' OR end($chunks) == ':'){return FALSE;}// PHP supports IPv4-mapped IPv6 addresses, so we'll expect those as wellif (strpos(end($chunks), '.') !== FALSE){$ipv4 = array_pop($chunks);if ( ! $this->_valid_ipv4($ipv4)){return FALSE;}$groups--;}while ($seg = array_pop($chunks)){if ($seg[0] == ':'){if (--$groups == 0){return FALSE;// too many groups}if (strlen($seg) > 2){return FALSE;// long separator}if ($seg == '::'){if ($collapsed){return FALSE;// multiple collapsed}$collapsed = TRUE;}}elseif (preg_match("/[^0-9a-f]/i", $seg) OR strlen($seg) > 4){return FALSE; // invalid segment}}return $collapsed OR $groups == 1;}// --------------------------------/*** User Agent* 返回当前用户正在使用的浏览器的user agent信息。 如果不能得到数据,返回FALSE。* 一般user_agent为空的时候被认定为手机访问,或者curl的抓取,或则会蜘蛛抓取* @accesspublic* @returnstring*/function user_agent(){if ($this->user_agent !== FALSE){return $this->user_agent;}$this->user_agent = ( ! isset($_SERVER['HTTP_USER_AGENT'])) ? FALSE : $_SERVER['HTTP_USER_AGENT'];return $this->user_agent;}// --------------------------------/*** Sanitize Globals* 清理全局数组* This function does the following:* 这个函数做了下面的操作:* Unsets $_GET data (if query strings are not enabled)* 销毁$_GET (如果query strings 没有开启)* Unsets all globals if register_globals is enabled* 销毁所有全局数组如果register_globals开启** Standardizes newline characters to \n* 标准化换行符\n* @accessprivate* @returnvoid*/function _sanitize_globals(){// It would be "wrong" to unset any of these GLOBALS.// 销毁下面的全局数组将是错误的。$protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST','_SESSION', '_ENV', 'GLOBALS', 'HTTP_RAW_POST_DATA','system_folder', 'application_folder', 'BM', 'EXT','CFG', 'URI', 'RTR', 'OUT', 'IN');// Unset globals for securiy.为了安全销毁除了上面之外的全局数组// This is effectively the same as register_globals = off// 这样的效果和register_globals是相同的        // 经过下面处理后,所有的非保护的全局变量将被删除掉foreach (array($_GET, $_POST, $_COOKIE) as $global){if ( ! is_array($global)){if ( ! in_array($global, $protected)){global $$global;$$global = NULL;}}else{foreach ($global as $key => $val){if ( ! in_array($key, $protected)){global $$key;$$key = NULL;}}}}// Is $_GET data allowed? If not we'll set the $_GET to an empty array// 是否允许$_GET数据? 如果不允许的话,设置$_GET为空数组if ($this->_allow_get_array == FALSE){$_GET = array();}else{if (is_array($_GET) AND count($_GET) > 0){foreach ($_GET as $key => $val){$_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);}}}// Clean $_POST Data// 过滤$_POST 数组if (is_array($_POST) AND count($_POST) > 0){foreach ($_POST as $key => $val){$_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);}}// Clean $_COOKIE Data// 过滤$_COOKIE数组if (is_array($_COOKIE) AND count($_COOKIE) > 0){// Also get rid of specially treated cookies that might be set by a server// or silly application, that are of no use to a CI application anyway// but that when present will trip our 'Disallowed Key Characters' alarm// http://www.ietf.org/rfc/rfc2109.txt// note that the key names below are single quoted strings, and are not PHP variablesunset($_COOKIE['$Version']);unset($_COOKIE['$Path']);unset($_COOKIE['$Domain']);foreach ($_COOKIE as $key => $val){$_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);}}// Sanitize PHP_SELF$_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);// CSRF Protection check on HTTP requests// CSRF保护检测http请求if ($this->_enable_csrf == TRUE && ! $this->is_cli_request()){$this->security->csrf_verify();}log_message('debug', "Global POST and COOKIE data sanitized");}// --------------------------------/*** Clean Input Data* 过滤input数据* This is a helper function. It escapes data and* standardizes newline characters to \n** @accessprivate* @paramstring* @returnstring*/function _clean_input_data($str){if (is_array($str)){$new_array = array();foreach ($str as $key => $val){$new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);}return $new_array;}/* We strip slashes if magic quotes is on to keep things consistent如果小于PHP5.4版本,并且get_magic_quotes_gpc开启了,则去掉斜线。   NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and   it will probably not exist in future versions at all。   注意:在PHP5.4及之后版本,get_magic_quotes_gpc()将总是返回0,   在后续版本中可能会移除该特性*/if ( ! is_php('5.4') && get_magic_quotes_gpc()){$str = stripslashes($str);}// Clean UTF-8 if supported 如果支持清理utf8if (UTF8_ENABLED === TRUE){$str = $this->uni->clean_string($str);}// Remove control characters $str = remove_invisible_characters($str);// Should we filter the input data?if ($this->_enable_xss === TRUE){$str = $this->security->xss_clean($str);}// Standardize newlines if neededif ($this->_standardize_newlines == TRUE){if (strpos($str, "\r") !== FALSE){$str = str_replace(array("\r\n", "\r", "\r\n\n"), PHP_EOL, $str);}}return $str;}// --------------------------------/*** Clean Keys* 过滤键值 * This is a helper function. To prevent malicious users* from trying to exploit keys we make sure that keys are* only named with alpha-numeric text and a few other items.** @accessprivate* @paramstring* @returnstring*/function _clean_input_keys($str){if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str)){exit('Disallowed Key Characters.');}// Clean UTF-8 if supportedif (UTF8_ENABLED === TRUE){$str = $this->uni->clean_string($str);}return $str;}// --------------------------------/** * Request Headers * 返回请求头(header)数组。 * In Apache, you can simply call apache_request_headers(), however for * people running other webservers the function is undefined. * * @parambool XSS cleaning * * @return array */public function request_headers($xss_clean = FALSE){// Look at Apache go!if (function_exists('apache_request_headers')){$headers = apache_request_headers();}else{$headers['Content-Type'] = (isset($_SERVER['CONTENT_TYPE'])) ? $_SERVER['CONTENT_TYPE'] : @getenv('CONTENT_TYPE');foreach ($_SERVER as $key => $val){if (strncmp($key, 'HTTP_', 5) === 0){$headers[substr($key, 5)] = $this->_fetch_from_array($_SERVER, $key, $xss_clean);}}}// take SOME_HEADER and turn it into Some-Headerforeach ($headers as $key => $val){$key = str_replace('_', ' ', strtolower($key));$key = str_replace(' ', '-', ucwords($key));$this->headers[$key] = $val;}return $this->headers;}// --------------------------------/** * Get Request Header * 返回请求头(request header)数组中某一个元素的值 * Returns the value of a single member of the headers class member * * @param stringarray key for $this->headers * @parambooleanXSS Clean or not * @return mixedFALSE on failure, string on success */public function get_request_header($index, $xss_clean = FALSE){if (empty($this->headers)){$this->request_headers();}if ( ! isset($this->headers[$index])){return FALSE;}if ($xss_clean === TRUE){return $this->security->xss_clean($this->headers[$index]);}return $this->headers[$index];}// --------------------------------/** * Is ajax Request?  * 判断是否为ajax请求 * Test to see if a request contains the HTTP_X_REQUESTED_WITH header * * @return boolean */public function is_ajax_request(){return ($this->server('HTTP_X_REQUESTED_WITH') === 'XMLHttpRequest');}// --------------------------------/** * Is cli Request? * 判断是否来自cli请求 * Test to see if a request was made from the command line * * @return bool */public function is_cli_request(){return (php_sapi_name() === 'cli' OR defined('STDIN'));}}/* End of file Input.php *//* Location: ./system/core/Input.php */

热点排行