diff options
Diffstat (limited to 'system/core')
-rwxr-xr-x[-rw-r--r--] | system/core/Benchmark.php | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | system/core/CodeIgniter.php | 40 | ||||
-rw-r--r-- | system/core/Common.php | 30 | ||||
-rwxr-xr-x[-rw-r--r--] | system/core/Config.php | 29 | ||||
-rw-r--r-- | system/core/Controller.php | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | system/core/Exceptions.php | 17 | ||||
-rwxr-xr-x[-rw-r--r--] | system/core/Hooks.php | 15 | ||||
-rwxr-xr-x[-rw-r--r--] | system/core/Input.php | 75 | ||||
-rwxr-xr-x[-rw-r--r--] | system/core/Lang.php | 13 | ||||
-rw-r--r-- | system/core/Loader.php | 136 | ||||
-rwxr-xr-x[-rw-r--r--] | system/core/Model.php | 1 | ||||
-rwxr-xr-x[-rw-r--r--] | system/core/Output.php | 61 | ||||
-rwxr-xr-x[-rw-r--r--] | system/core/Router.php | 59 | ||||
-rwxr-xr-x[-rw-r--r--] | system/core/Security.php | 208 | ||||
-rwxr-xr-x[-rw-r--r--] | system/core/URI.php | 31 |
15 files changed, 567 insertions, 155 deletions
diff --git a/system/core/Benchmark.php b/system/core/Benchmark.php index 515550e9f..a200727ab 100644..100755 --- a/system/core/Benchmark.php +++ b/system/core/Benchmark.php @@ -29,6 +29,11 @@ */ class CI_Benchmark { + /** + * List of all benchmark markers and when they were added + * + * @var array + */ var $marker = array(); // -------------------------------------------------------------------- diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index 94fecb5c0..db1aee574 100644..100755 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -27,17 +27,19 @@ * @link http://codeigniter.com/user_guide/ */ -/* - * ------------------------------------------------------ - * Define the CodeIgniter Version - * ------------------------------------------------------ +/** + * CodeIgniter Version + * + * @var string + * */ - define('CI_VERSION', '2.0.3'); + define('CI_VERSION', '2.1.0'); -/* - * ------------------------------------------------------ - * Define the CodeIgniter Branch (Core = TRUE, Reactor = FALSE) - * ------------------------------------------------------ +/** + * CodeIgniter Branch (Core = TRUE, Reactor = FALSE) + * + * @var boolean + * */ define('CI_CORE', FALSE); @@ -267,7 +269,25 @@ OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller'))) ) { - show_404("{$class}/{$method}"); + if ( ! empty($RTR->routes['404_override'])) + { + $x = explode('/', $RTR->routes['404_override']); + $class = $x[0]; + $method = (isset($x[1]) ? $x[1] : 'index'); + if ( ! class_exists($class)) + { + if ( ! file_exists(APPPATH.'controllers/'.$class.'.php')) + { + show_404("{$class}/{$method}"); + } + + include_once(APPPATH.'controllers/'.$class.'.php'); + } + } + else + { + show_404("{$class}/{$method}"); + } } /* diff --git a/system/core/Common.php b/system/core/Common.php index db9fbeb9f..d79375475 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -132,9 +132,9 @@ if ( ! function_exists('load_class')) $name = FALSE; - // Look for the class first in the native system/libraries folder - // thenin the local application/libraries folder - foreach (array(BASEPATH, APPPATH) as $path) + // Look for the class first in the local application/libraries folder + // then in the native system/libraries folder + foreach (array(APPPATH, BASEPATH) as $path) { if (file_exists($path.$directory.'/'.$class.'.php')) { @@ -536,5 +536,29 @@ if ( ! function_exists('remove_invisible_characters')) } } +// ------------------------------------------------------------------------ + +/** +* Returns HTML escaped variable +* +* @access public +* @param mixed +* @return mixed +*/ +if ( ! function_exists('html_escape')) +{ + function html_escape($var) + { + if (is_array($var)) + { + return array_map('html_escape', $var); + } + else + { + return htmlspecialchars($var, ENT_QUOTES, config_item('charset')); + } + } +} + /* End of file Common.php */ /* Location: ./system/core/Common.php */
\ No newline at end of file diff --git a/system/core/Config.php b/system/core/Config.php index 0e6f10e07..714c4667b 100644..100755 --- a/system/core/Config.php +++ b/system/core/Config.php @@ -28,8 +28,23 @@ */ class CI_Config { + /** + * List of all loaded config values + * + * @var array + */ var $config = array(); + /** + * List of all loaded config files + * + * @var array + */ var $is_loaded = array(); + /** + * List of paths to search when trying to load a config file + * + * @var array + */ var $_config_paths = array(APPPATH); /** @@ -251,13 +266,13 @@ class CI_Config { return $this->slash_item('base_url').$this->item('index_page').'?'.$this->_uri_string($uri); } } - + // ------------------------------------------------------------- - + /** * Base URL * Returns base_url [. uri_string] - * + * * @access public * @param string $uri * @return string @@ -266,12 +281,12 @@ class CI_Config { { return $this->slash_item('base_url').ltrim($this->_uri_string($uri),'/'); } - + // ------------------------------------------------------------- - + /** * Build URI string for use in Config::site_url() and Config::base_url() - * + * * @access protected * @param $uri * @return string @@ -305,7 +320,7 @@ class CI_Config { } // -------------------------------------------------------------------- - + /** * System URL * diff --git a/system/core/Controller.php b/system/core/Controller.php index ec86b7920..fddb81e19 100644 --- a/system/core/Controller.php +++ b/system/core/Controller.php @@ -48,7 +48,7 @@ class CI_Controller { $this->load =& load_class('Loader', 'core'); - $this->load->set_base_classes()->ci_autoloader(); + $this->load->initialize(); log_message('debug', "Controller Class Initialized"); } diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php index bff86a92f..869739a5a 100644..100755 --- a/system/core/Exceptions.php +++ b/system/core/Exceptions.php @@ -30,8 +30,21 @@ class CI_Exceptions { var $message; var $filename; var $line; + + /** + * Nesting level of the output buffering mechanism + * + * @var int + * @access public + */ var $ob_level; + /** + * List if available error levels + * + * @var array + * @access public + */ var $levels = array( E_ERROR => 'Error', E_WARNING => 'Warning', @@ -84,7 +97,8 @@ class CI_Exceptions { * 404 Page Not Found Handler * * @access private - * @param string + * @param string the page + * @param bool log error yes/no * @return string */ function show_404($page = '', $log_error = TRUE) @@ -115,6 +129,7 @@ class CI_Exceptions { * @param string the heading * @param string the message * @param string the template name + * @param int the status code * @return string */ function show_error($heading, $message, $template = 'error_general', $status_code = 500) diff --git a/system/core/Hooks.php b/system/core/Hooks.php index fd6380f0a..33f1c034c 100644..100755 --- a/system/core/Hooks.php +++ b/system/core/Hooks.php @@ -28,8 +28,23 @@ */ class CI_Hooks { + /** + * Determines wether hooks are enabled + * + * @var bool + */ var $enabled = FALSE; + /** + * List of all hooks set in config/hooks.php + * + * @var array + */ var $hooks = array(); + /** + * Determines wether hook is in progress, used to prevent infinte loops + * + * @var bool + */ var $in_progress = FALSE; /** diff --git a/system/core/Input.php b/system/core/Input.php index cfbef942d..9bfb5f1fb 100644..100755 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -28,15 +28,51 @@ */ class CI_Input { + /** + * IP address of the current user + * + * @var string + */ var $ip_address = FALSE; + /** + * user agent (web browser) being used by the current user + * + * @var string + */ var $user_agent = FALSE; + /** + * If FALSE, then $_GET will be set to an empty array + * + * @var bool + */ var $_allow_get_array = TRUE; + /** + * If TRUE, then newlines are standardized + * + * @var bool + */ var $_standardize_newlines = TRUE; - var $_enable_xss = FALSE; // Set automatically based on config setting - var $_enable_csrf = FALSE; // Set automatically based on config setting - + /** + * Determines whether the XSS filter is always active when GET, POST or COOKIE data is encountered + * Set automatically based on config setting + * + * @var bool + */ + var $_enable_xss = FALSE; + /** + * Enables a CSRF cookie token to be set. + * Set automatically based on config setting + * + * @var bool + */ + var $_enable_csrf = FALSE; + /** + * List of all HTTP request headers + * + * @var array + */ protected $headers = array(); - + /** * Constructor @@ -147,7 +183,7 @@ class CI_Input { } return $post; } - + return $this->_fetch_from_array($_POST, $index, $xss_clean); } @@ -402,9 +438,9 @@ class CI_Input { function _sanitize_globals() { // It would be "wrong" to unset any of these GLOBALS. - $protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST', + $protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST', '_SESSION', '_ENV', 'GLOBALS', 'HTTP_RAW_POST_DATA', - 'system_folder', 'application_folder', 'BM', 'EXT', + 'system_folder', 'application_folder', 'BM', 'EXT', 'CFG', 'URI', 'RTR', 'OUT', 'IN'); // Unset globals for securiy. @@ -512,8 +548,12 @@ class CI_Input { return $new_array; } - // We strip slashes if magic quotes is on to keep things consistent - if (function_exists('get_magic_quotes_gpc') AND get_magic_quotes_gpc()) + /* We strip slashes if magic quotes is on to keep things consistent + + NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and + it will probably not exist in future versions at all. + */ + if ( ! is_php('5.4') && get_magic_quotes_gpc()) { $str = stripslashes($str); } @@ -523,7 +563,7 @@ class CI_Input { { $str = $this->uni->clean_string($str); } - + // Remove control characters $str = remove_invisible_characters($str); @@ -579,9 +619,11 @@ class CI_Input { /** * Request Headers * - * In Apache, you can simply call apache_request_headers(), however for + * In Apache, you can simply call apache_request_headers(), however for * people running other webservers the function is undefined. * + * @param bool XSS cleaning + * * @return array */ public function request_headers($xss_clean = FALSE) @@ -609,10 +651,10 @@ class CI_Input { { $key = str_replace('_', ' ', strtolower($key)); $key = str_replace(' ', '-', ucwords($key)); - + $this->headers[$key] = $val; } - + return $this->headers; } @@ -633,7 +675,7 @@ class CI_Input { { $this->request_headers(); } - + if ( ! isset($this->headers[$index])) { return FALSE; @@ -644,7 +686,7 @@ class CI_Input { return $this->security->xss_clean($this->headers[$index]); } - return $this->headers[$index]; + return $this->headers[$index]; } // -------------------------------------------------------------------- @@ -676,7 +718,6 @@ class CI_Input { } } -// END Input class /* End of file Input.php */ -/* Location: ./system/core/Input.php */ +/* Location: ./system/core/Input.php */
\ No newline at end of file diff --git a/system/core/Lang.php b/system/core/Lang.php index 170e6c725..5ac671838 100644..100755 --- a/system/core/Lang.php +++ b/system/core/Lang.php @@ -26,7 +26,17 @@ */ class CI_Lang { + /** + * List of translations + * + * @var array + */ var $language = array(); + /** + * List of loaded language files + * + * @var array + */ var $is_loaded = array(); /** @@ -47,6 +57,9 @@ class CI_Lang { * @access public * @param mixed the name of the language file to be loaded. Can be an array * @param string the language (english, etc.) + * @param bool return loaded array of translations + * @param bool add suffix to $langfile + * @param string alternative path to look for language file * @return mixed */ function load($langfile = '', $idiom = '', $return = FALSE, $add_suffix = TRUE, $alt_path = '') diff --git a/system/core/Loader.php b/system/core/Loader.php index 7c8b298ac..6b7ee0c28 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -29,18 +29,91 @@ class CI_Loader { // All these are set automatically. Don't mess with them. + /** + * Nesting level of the output buffering mechanism + * + * @var int + * @access protected + */ protected $_ci_ob_level; + /** + * List of paths to load views from + * + * @var array + * @access protected + */ protected $_ci_view_paths = array(); + /** + * List of paths to load libraries from + * + * @var array + * @access protected + */ protected $_ci_library_paths = array(); + /** + * List of paths to load models from + * + * @var array + * @access protected + */ protected $_ci_model_paths = array(); + /** + * List of paths to load helpers from + * + * @var array + * @access protected + */ protected $_ci_helper_paths = array(); + /** + * List of loaded base classes + * Set by the controller class + * + * @var array + * @access protected + */ protected $_base_classes = array(); // Set by the controller class + /** + * List of cached variables + * + * @var array + * @access protected + */ protected $_ci_cached_vars = array(); + /** + * List of loaded classes + * + * @var array + * @access protected + */ protected $_ci_classes = array(); + /** + * List of loaded files + * + * @var array + * @access protected + */ protected $_ci_loaded_files = array(); + /** + * List of loaded models + * + * @var array + * @access protected + */ protected $_ci_models = array(); + /** + * List of loaded helpers + * + * @var array + * @access protected + */ protected $_ci_helpers = array(); - protected $_ci_varmap = array('unit_test' => 'unit', + /** + * List of class name mappings + * + * @var array + * @access protected + */ + protected $_ci_varmap = array('unit_test' => 'unit', 'user_agent' => 'agent'); /** @@ -55,24 +128,29 @@ class CI_Loader { $this->_ci_helper_paths = array(APPPATH, BASEPATH); $this->_ci_model_paths = array(APPPATH); $this->_ci_view_paths = array(APPPATH.'views/' => TRUE); - + log_message('debug', "Loader Class Initialized"); } // -------------------------------------------------------------------- - + /** - * Set _base_classes variable + * Initialize the Loader * * This method is called once in CI_Controller. * - * @param array + * @param array * @return object */ - public function set_base_classes() + public function initialize() { + $this->_ci_classes = array(); + $this->_ci_loaded_files = array(); + $this->_ci_models = array(); $this->_base_classes =& is_loaded(); - + + $this->_ci_autoloader(); + return $this; } @@ -96,7 +174,7 @@ class CI_Loader { { return $this->_ci_classes[$class]; } - + return FALSE; } @@ -366,6 +444,7 @@ class CI_Loader { * the controller class and its "view" files. * * @param array + * @param string * @return void */ public function vars($vars = array(), $val = '') @@ -507,6 +586,8 @@ class CI_Loader { * Loads a config file * * @param string + * @param bool + * @param bool * @return void */ public function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) @@ -535,6 +616,11 @@ class CI_Loader { require BASEPATH.'libraries/Driver.php'; } + if ($library == '') + { + return FALSE; + } + // We can save the loader some time since Drivers will *always* be in a subfolder, // and typically identically named to the library if ( ! strpos($library, '/')) @@ -553,13 +639,13 @@ class CI_Loader { * Prepends a parent path to the library, model, helper, and config path arrays * * @param string - * @param boolean + * @param boolean * @return void */ public function add_package_path($path, $view_cascade=TRUE) { $path = rtrim($path, '/').'/'; - + array_unshift($this->_ci_library_paths, $path); array_unshift($this->_ci_model_paths, $path); array_unshift($this->_ci_helper_paths, $path); @@ -595,6 +681,7 @@ class CI_Loader { * If no path is provided, the most recently added path is removed. * * @param type + * @param bool * @return type */ public function remove_package_path($path = '', $remove_config_path = TRUE) @@ -619,7 +706,7 @@ class CI_Loader { unset($this->{$var}[$key]); } } - + if (isset($this->_ci_view_paths[$path.'views/'])) { unset($this->_ci_view_paths[$path.'views/']); @@ -658,7 +745,7 @@ class CI_Loader { { $$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val]; } - + $file_exists = FALSE; // Set the path to the requested file @@ -680,11 +767,11 @@ class CI_Loader { $file_exists = TRUE; break; } - + if ( ! $cascade) { break; - } + } } } @@ -913,6 +1000,7 @@ class CI_Loader { * * @param string * @param string + * @param bool * @param string an optional object name * @return null */ @@ -935,22 +1023,22 @@ class CI_Loader { // first, global next if (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php')) { - include_once($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'); + include($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'); break; } elseif (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php')) { - include_once($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'); + include($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'); break; } elseif (file_exists($path .'config/'.strtolower($class).'.php')) { - include_once($path .'config/'.strtolower($class).'.php'); + include($path .'config/'.strtolower($class).'.php'); break; } elseif (file_exists($path .'config/'.ucfirst(strtolower($class)).'.php')) { - include_once($path .'config/'.ucfirst(strtolower($class)).'.php'); + include($path .'config/'.ucfirst(strtolower($class)).'.php'); break; } } @@ -1020,23 +1108,19 @@ class CI_Loader { * The config/autoload.php file contains an array that permits sub-systems, * libraries, and helpers to be loaded automatically. * - * This function is public, as it's used in the CI_Controller class. - * However, there is no reason you should ever needs to use it. - * * @param array * @return void */ - public function ci_autoloader() + private function _ci_autoloader() { if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php')) { - include_once(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'); + include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'); } else { - include_once(APPPATH.'config/autoload.php'); + include(APPPATH.'config/autoload.php'); } - if ( ! isset($autoload)) { @@ -1122,6 +1206,7 @@ class CI_Loader { /** * Get a reference to a specific library or model * + * @param string * @return bool */ protected function &_ci_get_component($component) @@ -1138,6 +1223,7 @@ class CI_Loader { * This function preps the name of various items to make loading them more reliable. * * @param mixed + * @param string * @return array */ protected function _ci_prep_filename($filename, $extension) diff --git a/system/core/Model.php b/system/core/Model.php index 8566a0b66..e15ffbebc 100644..100755 --- a/system/core/Model.php +++ b/system/core/Model.php @@ -42,6 +42,7 @@ class CI_Model { * Allows models to access CI's loaded classes using the same * syntax as controllers. * + * @param string * @access private */ function __get($key) diff --git a/system/core/Output.php b/system/core/Output.php index 05ace919c..ccecafd2b 100644..100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -28,15 +28,67 @@ */ class CI_Output { + /** + * Current output string + * + * @var string + * @access protected + */ protected $final_output; + /** + * Cache expiration time + * + * @var int + * @access protected + */ protected $cache_expiration = 0; + /** + * List of server headers + * + * @var array + * @access protected + */ protected $headers = array(); - protected $mime_types = array(); + /** + * List of mime types + * + * @var array + * @access protected + */ + protected $mime_types = array(); + /** + * Determines wether profiler is enabled + * + * @var book + * @access protected + */ protected $enable_profiler = FALSE; + /** + * Determines if output compression is enabled + * + * @var bool + * @access protected + */ protected $_zlib_oc = FALSE; + /** + * List of profiler sections + * + * @var array + * @access protected + */ protected $_profiler_sections = array(); - protected $parse_exec_vars = TRUE; // whether or not to parse variables like {elapsed_time} and {memory_usage} + /** + * Whether or not to parse variables like {elapsed_time} and {memory_usage} + * + * @var bool + * @access protected + */ + protected $parse_exec_vars = TRUE; + /** + * Constructor + * + */ function __construct() { $this->_zlib_oc = @ini_get('zlib.output_compression'); @@ -127,6 +179,7 @@ class CI_Output { * * @access public * @param string + * @param bool * @return void */ function set_header($header, $replace = TRUE) @@ -265,6 +318,7 @@ class CI_Output { * benchmark timer so the page rendering speed and memory usage can be shown. * * @access public + * @param string * @return mixed */ function _display($output = '') @@ -401,6 +455,7 @@ class CI_Output { * Write a Cache File * * @access public + * @param string * @return void */ function _write_cache($output) @@ -452,6 +507,8 @@ class CI_Output { * Update/serve a cached file * * @access public + * @param object config class + * @param object uri class * @return void */ function _display_cache(&$CFG, &$URI) diff --git a/system/core/Router.php b/system/core/Router.php index 5e92a04b1..6da667472 100644..100755 --- a/system/core/Router.php +++ b/system/core/Router.php @@ -28,12 +28,54 @@ */ class CI_Router { + /** + * Config class + * + * @var object + * @access public + */ var $config; + /** + * List of routes + * + * @var array + * @access public + */ var $routes = array(); + /** + * List of error routes + * + * @var array + * @access public + */ var $error_routes = array(); + /** + * Current class name + * + * @var string + * @access public + */ var $class = ''; + /** + * Current method name + * + * @var string + * @access public + */ var $method = 'index'; + /** + * Sub-directory that contains the requested controller class + * + * @var string + * @access public + */ var $directory = ''; + /** + * Default controller (and method if specific) + * + * @var string + * @access public + */ var $default_controller; /** @@ -95,7 +137,7 @@ class CI_Router { { include(APPPATH.'config/routes.php'); } - + $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route; unset($route); @@ -244,7 +286,20 @@ class CI_Router { // Does the requested controller exist in the sub-folder? if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php')) { - show_404($this->fetch_directory().$segments[0]); + if ( ! empty($this->routes['404_override'])) + { + $x = explode('/', $this->routes['404_override']); + + $this->set_directory(''); + $this->set_class($x[0]); + $this->set_method(isset($x[1]) ? $x[1] : 'index'); + + return $x; + } + else + { + show_404($this->fetch_directory().$segments[0]); + } } } else diff --git a/system/core/Security.php b/system/core/Security.php index 3617cadcc..a3e227437 100644..100755 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -25,14 +25,49 @@ * @link http://codeigniter.com/user_guide/libraries/security.html */ class CI_Security { - + + /** + * Random Hash for protecting URLs + * + * @var string + * @access protected + */ protected $_xss_hash = ''; + /** + * Random Hash for Cross Site Request Forgery Protection Cookie + * + * @var string + * @access protected + */ protected $_csrf_hash = ''; - protected $_csrf_expire = 7200; // Two hours (in seconds) + /** + * Expiration time for Cross Site Request Forgery Protection Cookie + * Defaults to two hours (in seconds) + * + * @var int + * @access protected + */ + protected $_csrf_expire = 7200; + /** + * Token name for Cross Site Request Forgery Protection Cookie + * + * @var string + * @access protected + */ protected $_csrf_token_name = 'ci_csrf_token'; + /** + * Cookie name for Cross Site Request Forgery Protection Cookie + * + * @var string + * @access protected + */ protected $_csrf_cookie_name = 'ci_csrf_token'; - - /* never allowed, string replacement */ + /** + * List of never allowed strings + * + * @var array + * @access protected + */ protected $_never_allowed_str = array( 'document.cookie' => '[removed]', 'document.write' => '[removed]', @@ -42,17 +77,24 @@ class CI_Security { '-moz-binding' => '[removed]', '<!--' => '<!--', '-->' => '-->', - '<![CDATA[' => '<![CDATA[' + '<![CDATA[' => '<![CDATA[', + '<comment>' => '<comment>' ); /* never allowed, regex replacement */ + /** + * List of never allowed regex replacement + * + * @var array + * @access protected + */ protected $_never_allowed_regex = array( "javascript\s*:" => '[removed]', "expression\s*(\(|&\#40;)" => '[removed]', // CSS and IE "vbscript\s*:" => '[removed]', // IE, surprise! "Redirect\s+302" => '[removed]' ); - + /** * Constructor */ @@ -95,7 +137,7 @@ class CI_Security { } // Do the tokens exist in both the _POST and _COOKIE arrays? - if ( ! isset($_POST[$this->_csrf_token_name]) OR + if ( ! isset($_POST[$this->_csrf_token_name]) OR ! isset($_COOKIE[$this->_csrf_cookie_name])) { $this->csrf_show_error(); @@ -107,7 +149,7 @@ class CI_Security { $this->csrf_show_error(); } - // We kill this since we're done and we don't want to + // We kill this since we're done and we don't want to // polute the _POST array unset($_POST[$this->_csrf_token_name]); @@ -117,7 +159,7 @@ class CI_Security { $this->csrf_set_cookie(); log_message('debug', "CSRF token verified "); - + return $this; } @@ -146,7 +188,7 @@ class CI_Security { setcookie($this->_csrf_cookie_name, $this->_csrf_hash, $expire, config_item('cookie_path'), config_item('cookie_domain'), $secure_cookie); log_message('debug', "CRSF cookie Set"); - + return $this; } @@ -165,9 +207,9 @@ class CI_Security { // -------------------------------------------------------------------- /** - * Get CSRF Hash + * Get CSRF Hash * - * Getter Method + * Getter Method * * @return string self::_csrf_hash */ @@ -215,6 +257,7 @@ class CI_Security { * http://ha.ckers.org/xss.html * * @param mixed string or array + * @param bool * @return string */ public function xss_clean($str, $is_image = FALSE) @@ -263,7 +306,7 @@ class CI_Security { */ $str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str); - + $str = preg_replace_callback("/<\w+.*?(?=>|<|$)/si", array($this, '_decode_entity'), $str); /* @@ -276,7 +319,7 @@ class CI_Security { * * This prevents strings like this: ja vascript * NOTE: we deal with spaces between characters later. - * NOTE: preg_replace was found to be amazingly slow here on + * NOTE: preg_replace was found to be amazingly slow here on * large blocks of data, so we use str_replace. */ @@ -304,8 +347,8 @@ class CI_Security { */ if ($is_image === TRUE) { - // Images have a tendency to have the PHP short opening and - // closing tags every so often so we skip those and only + // Images have a tendency to have the PHP short opening and + // closing tags every so often so we skip those and only // do the long opening tags. $str = preg_replace('/<\?(php)/i', "<?\\1", $str); } @@ -321,10 +364,10 @@ class CI_Security { * These words are compacted back to their correct state. */ $words = array( - 'javascript', 'expression', 'vbscript', 'script', + 'javascript', 'expression', 'vbscript', 'script', 'applet', 'alert', 'document', 'write', 'cookie', 'window' ); - + foreach ($words as $word) { $temp = ''; @@ -341,8 +384,8 @@ class CI_Security { /* * Remove disallowed Javascript in links or img tags - * We used to do some version comparisons and use of stripos for PHP5, - * but it is dog slow compared to these simplified non-capturing + * We used to do some version comparisons and use of stripos for PHP5, + * but it is dog slow compared to these simplified non-capturing * preg_match(), especially if the pattern exists in the string */ do @@ -405,11 +448,11 @@ class CI_Security { /* * Images are Handled in a Special Way - * - Essentially, we want to know that after all of the character - * conversion is done whether any unwanted, likely XSS, code was found. + * - Essentially, we want to know that after all of the character + * conversion is done whether any unwanted, likely XSS, code was found. * If not, we return TRUE, as the image is clean. - * However, if the string post-conversion does not matched the - * string post-removal of XSS, then it fails, as there was unwanted XSS + * However, if the string post-conversion does not matched the + * string post-removal of XSS, then it fails, as there was unwanted XSS * code found and removed/changed during processing. */ @@ -433,15 +476,7 @@ class CI_Security { { if ($this->_xss_hash == '') { - if (phpversion() >= 4.2) - { - mt_srand(); - } - else - { - mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff); - } - + mt_srand(); $this->_xss_hash = md5(time() + mt_rand(0, 1999999999)); } @@ -455,14 +490,11 @@ class CI_Security { * * This function is a replacement for html_entity_decode() * - * In some versions of PHP the native function does not work - * when UTF-8 is the specified character set, so this gives us - * a work-around. More info here: - * http://bugs.php.net/bug.php?id=25670 - * - * NOTE: html_entity_decode() has a bug in some PHP versions when UTF-8 is the - * character set, and the PHP developers said they were not back porting the - * fix to versions other than PHP 5.x. + * The reason we are not using html_entity_decode() by itself is because + * while it is not technically correct to leave out the semicolon + * at the end of an entity most browsers will still interpret the entity + * correctly. html_entity_decode() does not convert entities without + * semicolons, so we are left with our own little solution here. Bummer. * * @param string * @param string @@ -470,33 +502,14 @@ class CI_Security { */ public function entity_decode($str, $charset='UTF-8') { - if (stristr($str, '&') === FALSE) return $str; - - // The reason we are not using html_entity_decode() by itself is because - // while it is not technically correct to leave out the semicolon - // at the end of an entity most browsers will still interpret the entity - // correctly. html_entity_decode() does not convert entities without - // semicolons, so we are left with our own little solution here. Bummer. - - if (function_exists('html_entity_decode') && - (strtolower($charset) != 'utf-8')) - { - $str = html_entity_decode($str, ENT_COMPAT, $charset); - $str = preg_replace('~&#x(0*[0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str); - return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str); - } - - // Numeric Entities - $str = preg_replace('~&#x(0*[0-9a-f]{2,5});{0,1}~ei', 'chr(hexdec("\\1"))', $str); - $str = preg_replace('~&#([0-9]{2,4});{0,1}~e', 'chr(\\1)', $str); - - // Literal Entities - Slightly slow so we do another check if (stristr($str, '&') === FALSE) { - $str = strtr($str, array_flip(get_html_translation_table(HTML_ENTITIES))); + return $str; } - return $str; + $str = html_entity_decode($str, ENT_COMPAT, $charset); + $str = preg_replace('~&#x(0*[0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str); + return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str); } // -------------------------------------------------------------------- @@ -505,6 +518,7 @@ class CI_Security { * Filename Security * * @param string + * @param bool * @return string */ public function sanitize_filename($str, $relative_path = FALSE) @@ -542,7 +556,7 @@ class CI_Security { "%3b", // ; "%3d" // = ); - + if ( ! $relative_path) { $bad[] = './'; @@ -570,7 +584,7 @@ class CI_Security { } // -------------------------------------------------------------------- - + /* * Remove Evil HTML Attributes (like evenhandlers and style) * @@ -578,7 +592,7 @@ class CI_Security { * - Everything up until a space * For example, everything between the pipes: * <a |style=document.write('hello');alert('world');| class=link> - * - Everything inside the quotes + * - Everything inside the quotes * For example, everything between the pipes: * <a |style="document.write('hello'); alert('world');"| class="link"> * @@ -589,7 +603,7 @@ class CI_Security { protected function _remove_evil_attributes($str, $is_image) { // All javascript event handlers (e.g. onload, onclick, onmouseover), style, and xmlns - $evil_attributes = array('on\w*', 'style', 'xmlns'); + $evil_attributes = array('on\w*', 'style', 'xmlns', 'formaction'); if ($is_image === TRUE) { @@ -601,16 +615,36 @@ class CI_Security { } do { - $str = preg_replace( - "#<(/?[^><]+?)([^A-Za-z\-])(".implode('|', $evil_attributes).")(\s*=\s*)([\"][^>]*?[\"]|[\'][^>]*?[\']|[^>]*?)([\s><])([><]*)#i", - "<$1$6", - $str, -1, $count - ); + $count = 0; + $attribs = array(); + + // find occurrences of illegal attribute strings without quotes + preg_match_all("/(".implode('|', $evil_attributes).")\s*=\s*([^\s]*)/is", $str, $matches, PREG_SET_ORDER); + + foreach ($matches as $attr) + { + $attribs[] = preg_quote($attr[0], '/'); + } + + // find occurrences of illegal attribute strings with quotes (042 and 047 are octal quotes) + preg_match_all("/(".implode('|', $evil_attributes).")\s*=\s*(\042|\047)([^\\2]*?)(\\2)/is", $str, $matches, PREG_SET_ORDER); + + foreach ($matches as $attr) + { + $attribs[] = preg_quote($attr[0], '/'); + } + + // replace illegal attribute strings that are inside an html tag + if (count($attribs) > 0) + { + $str = preg_replace("/<(\/?[^><]+?)([^A-Za-z\-])(".implode('|', $attribs).")([\s><])([><]*)/i", '<$1$2$4$5', $str, -1, $count); + } + } while ($count); return $str; } - + // -------------------------------------------------------------------- /** @@ -627,7 +661,7 @@ class CI_Security { $str = '<'.$matches[1].$matches[2].$matches[3]; // encode captured opening or closing brace to prevent recursive vectors - $str .= str_replace(array('>', '<'), array('>', '<'), + $str .= str_replace(array('>', '<'), array('>', '<'), $matches[4]); return $str; @@ -649,7 +683,7 @@ class CI_Security { protected function _js_link_removal($match) { $attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1])); - + return str_replace($match[1], preg_replace("#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]); } @@ -669,7 +703,7 @@ class CI_Security { protected function _js_img_removal($match) { $attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1])); - + return str_replace($match[1], preg_replace("#src=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]); } @@ -729,13 +763,13 @@ class CI_Security { } // -------------------------------------------------------------------- - + /** * Validate URL entities * * Called by xss_clean() * - * @param string + * @param string * @return string */ protected function _validate_entities($str) @@ -743,9 +777,9 @@ class CI_Security { /* * Protect GET variables in URLs */ - + // 901119URL5918AMP18930PROTECT8198 - + $str = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-]+)|i', $this->xss_hash()."\\1=\\2", $str); /* @@ -769,7 +803,7 @@ class CI_Security { * Un-Protect GET variables in URLs */ $str = str_replace($this->xss_hash(), '&', $str); - + return $str; } @@ -794,7 +828,7 @@ class CI_Security { { $str = preg_replace("#".$key."#i", $val, $str); } - + return $str; } @@ -809,16 +843,16 @@ class CI_Security { { if ($this->_csrf_hash == '') { - // If the cookie exists we will use it's value. + // If the cookie exists we will use it's value. // We don't necessarily want to regenerate it with - // each page load since a page could contain embedded + // each page load since a page could contain embedded // sub-pages causing this feature to fail - if (isset($_COOKIE[$this->_csrf_cookie_name]) && + if (isset($_COOKIE[$this->_csrf_cookie_name]) && $_COOKIE[$this->_csrf_cookie_name] != '') { return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name]; } - + return $this->_csrf_hash = md5(uniqid(rand(), TRUE)); } diff --git a/system/core/URI.php b/system/core/URI.php index 20f0f006b..a3ae20cc3 100644..100755 --- a/system/core/URI.php +++ b/system/core/URI.php @@ -28,9 +28,34 @@ */ class CI_URI { + /** + * List of cached uri segments + * + * @var array + * @access public + */ var $keyval = array(); + /** + * Current uri string + * + * @var string + * @access public + */ var $uri_string; + /** + * List of uri segments + * + * @var array + * @access public + */ var $segments = array(); + /** + * Re-indexed list of uri segments + * Starts at 1 instead of 0 + * + * @var array + * @access public + */ var $rsegments = array(); /** @@ -127,6 +152,7 @@ class CI_URI { * Set the URI String * * @access public + * @param string * @return string */ function _set_uri_string($str) @@ -366,6 +392,11 @@ class CI_URI { /** * Identical to above only it uses the re-routed segment array * + * @access public + * @param integer the starting segment number + * @param array an array of default values + * @return array + * */ function ruri_to_assoc($n = 3, $default = array()) { |