diff options
Diffstat (limited to 'system')
36 files changed, 627 insertions, 491 deletions
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index 99c261e74..f3e1439ff 100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -53,7 +53,14 @@ * Load the framework constants * ------------------------------------------------------ */ - require(APPPATH.'config/constants'.EXT); + if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants'.EXT)) + { + require(APPPATH.'config/'.ENVIRONMENT.'/constants'.EXT); + } + else + { + require(APPPATH.'config/constants'.EXT); + } /* * ------------------------------------------------------ @@ -190,6 +197,13 @@ } /* + * ----------------------------------------------------- + * Load the security class for xss and csrf support + * ----------------------------------------------------- + */ + $SEC =& load_class('Security', 'core'); + +/* * ------------------------------------------------------ * Load the Input class and sanitize globals * ------------------------------------------------------ @@ -365,4 +379,4 @@ /* End of file CodeIgniter.php */ -/* Location: ./system/core/CodeIgniter.php */ +/* Location: ./system/core/CodeIgniter.php */
\ No newline at end of file diff --git a/system/core/Common.php b/system/core/Common.php index cd6b93355..1aca809ab 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -88,7 +88,7 @@ @unlink($file); return TRUE; } - elseif (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE) + elseif ( ! is_file($file) OR ($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE) { return FALSE; } @@ -208,19 +208,18 @@ return $_config[0]; } - $file_path = APPPATH.'config/'.ENVIRONMENT.'/config'.EXT; + // Is the config file in the environment folder? + if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config'.EXT)) + { + $file_path = APPPATH.'config/config'.EXT; + } // Fetch the config file if ( ! file_exists($file_path)) { - $file_path = APPPATH.'config/config'.EXT; - - if ( ! file_exists($file_path)) - { - exit('The configuration file does not exist.'); - } + exit('The configuration file does not exist.'); } - + require($file_path); // Does the $config array exist in the file? @@ -477,28 +476,26 @@ * @param string * @return string */ - function remove_invisible_characters($str) + function remove_invisible_characters($str, $url_encoded = TRUE) { - static $non_displayables; - - if ( ! isset($non_displayables)) + $non_displayables = array(); + + // every control character except newline (dec 10) + // carriage return (dec 13), and horizontal tab (dec 09) + + if ($url_encoded) { - // every control character except newline (dec 10), carriage return (dec 13), and horizontal tab (dec 09), - $non_displayables = array( - '/%0[0-8bcef]/', // url encoded 00-08, 11, 12, 14, 15 - '/%1[0-9a-f]/', // url encoded 16-31 - '/[\x00-\x08]/', // 00-08 - '/\x0b/', '/\x0c/', // 11, 12 - '/[\x0e-\x1f]/' // 14-31 - ); + $non_displayables[] = '/%0[0-8bcef]/'; // url encoded 00-08, 11, 12, 14, 15 + $non_displayables[] = '/%1[0-9a-f]/'; // url encoded 16-31 } + + $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127 do { - $cleaned = $str; - $str = preg_replace($non_displayables, '', $str); + $str = preg_replace($non_displayables, '', $str, -1, $count); } - while ($cleaned != $str); + while ($count); return $str; } diff --git a/system/core/Config.php b/system/core/Config.php index a2a7dd564..863c5ef4b 100644 --- a/system/core/Config.php +++ b/system/core/Config.php @@ -81,29 +81,37 @@ class CI_Config { function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) { $file = ($file == '') ? 'config' : str_replace(EXT, '', $file); + $found = FALSE; $loaded = FALSE; foreach ($this->_config_paths as $path) - { - $file_path = $path.'config/'.ENVIRONMENT.'/'.$file.EXT; + { + $check_locations = defined('ENVIRONMENT') + ? array(ENVIRONMENT.'/'.$file, $file) + : array($file); - if (in_array($file_path, $this->is_loaded, TRUE)) + foreach ($check_locations as $location) { - $loaded = TRUE; - continue; - } + $file_path = $path.'config/'.$location.EXT; - if ( ! file_exists($file_path)) - { - log_message('debug', 'Config for '.ENVIRONMENT.' environment is not found. Trying global config.'); - $file_path = $path.'config/'.$file.EXT; - - if ( ! file_exists($file_path)) + if (in_array($file_path, $this->is_loaded, TRUE)) + { + $loaded = TRUE; + continue 2; + } + + if (file_exists($file_path)) { - continue; + $found = TRUE; + break; } } - + + if ($found === FALSE) + { + continue; + } + include($file_path); if ( ! isset($config) OR ! is_array($config)) @@ -144,9 +152,9 @@ class CI_Config { { return FALSE; } - show_error('The configuration file '.ENVIRONMENT.'/'.$file.EXT.' and '.$file.EXT.' do not exist.'); + show_error('The configuration file '.$file.EXT.' does not exist.'); } - + return TRUE; } @@ -318,4 +326,4 @@ class CI_Config { // END CI_Config class /* End of file Config.php */ -/* Location: ./system/core/Config.php */ +/* Location: ./system/core/Config.php */
\ No newline at end of file diff --git a/system/core/Hooks.php b/system/core/Hooks.php index 75fd811b0..24fa1055b 100644 --- a/system/core/Hooks.php +++ b/system/core/Hooks.php @@ -65,7 +65,15 @@ class CI_Hooks { // Grab the "hooks" definition file. // If there are no hooks, we're done. - @include(APPPATH.'config/hooks'.EXT); + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/hooks'.EXT)) + { + include(APPPATH.'config/'.ENVIRONMENT.'/hooks'.EXT); + } + elseif (is_file(APPPATH.'config/hooks'.EXT)) + { + include(APPPATH.'config/hooks'.EXT); + } + if ( ! isset($hook) OR ! is_array($hook)) { diff --git a/system/core/Input.php b/system/core/Input.php index 626245390..dc7612e64 100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -53,11 +53,8 @@ class CI_Input { $this->_enable_xss = (config_item('global_xss_filtering') === TRUE); $this->_enable_csrf = (config_item('csrf_protection') === TRUE); - // Do we need to load the security class? - if ($this->_enable_xss == TRUE OR $this->_enable_csrf == TRUE) - { - $this->security =& load_class('Security'); - } + global $SEC; + $this->security =& $SEC; // Do we need the UTF-8 class? if (UTF8_ENABLED === TRUE) @@ -92,8 +89,7 @@ class CI_Input { if ($xss_clean === TRUE) { - $_security =& load_class('Security'); - return $_security->xss_clean($array[$index]); + return $this->security->xss_clean($array[$index]); } return $array[$index]; @@ -527,6 +523,9 @@ class CI_Input { { $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) @@ -539,7 +538,7 @@ class CI_Input { { if (strpos($str, "\r") !== FALSE) { - $str = str_replace(array("\r\n", "\r"), PHP_EOL, $str); + $str = str_replace(array("\r\n", "\r", "\r\n\n"), PHP_EOL, $str); } } @@ -642,8 +641,7 @@ class CI_Input { if ($xss_clean === TRUE) { - $_security =& load_class('Security'); - return $_security->xss_clean($this->headers[$index]); + return $this->security->xss_clean($this->headers[$index]); } return $this->headers[$index]; diff --git a/system/core/Lang.php b/system/core/Lang.php index fb177902e..0b926a303 100644 --- a/system/core/Lang.php +++ b/system/core/Lang.php @@ -130,6 +130,13 @@ class CI_Lang { function line($line = '') { $line = ($line == '' OR ! isset($this->language[$line])) ? FALSE : $this->language[$line]; + + // Because killer robots like unicorns! + if ($line === FALSE) + { + log_message('error', 'Could not find the language line "'.$line.'"'); + } + return $line; } diff --git a/system/core/Loader.php b/system/core/Loader.php index 7003318ee..e75805d0e 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -79,9 +79,9 @@ class CI_Loader { { if (is_array($library)) { - foreach ($library as $read) + foreach ($library as $class) { - $this->library($read); + $this->library($class, $params); } return; @@ -97,17 +97,7 @@ class CI_Loader { $params = NULL; } - if (is_array($library)) - { - foreach ($library as $class) - { - $this->_ci_load_class($class, $params, $object_name); - } - } - else - { - $this->_ci_load_class($library, $params, $object_name); - } + $this->_ci_load_class($library, $params, $object_name); } // -------------------------------------------------------------------- @@ -882,12 +872,12 @@ class CI_Loader { // We test for both uppercase and lowercase, for servers that // are case-sensitive with regard to file names. Check for environment // first, global next - if (file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).EXT)) + if (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).EXT)) { include_once($path .'config/'.ENVIRONMENT.'/'.strtolower($class).EXT); break; } - elseif (file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).EXT)) + elseif (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).EXT)) { include_once($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).EXT); break; @@ -975,7 +965,15 @@ class CI_Loader { */ function _ci_autoloader() { - include_once(APPPATH.'config/autoload'.EXT); + if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload'.EXT)) + { + include_once(APPPATH.'config/'.ENVIRONMENT.'/autoload'.EXT); + } + else + { + include_once(APPPATH.'config/autoload'.EXT); + } + if ( ! isset($autoload)) { @@ -1103,4 +1101,4 @@ class CI_Loader { } /* End of file Loader.php */ -/* Location: ./system/core/Loader.php */
\ No newline at end of file +/* Location: ./system/core/Loader.php */ diff --git a/system/core/Output.php b/system/core/Output.php index 6644b3bff..bcba2577a 100644 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -28,13 +28,12 @@ */ class CI_Output { + public $parse_exec_vars = TRUE; // whether or not to parse variables like {elapsed_time} and {memory_usage} protected $final_output; protected $cache_expiration = 0; protected $headers = array(); protected $mime_types = array(); protected $enable_profiler = FALSE; - protected $parse_exec_vars = TRUE; // whether or not to parse variables like {elapsed_time} and {memory_usage} - protected $_zlib_oc = FALSE; protected $_profiler_sections = array(); @@ -43,9 +42,18 @@ class CI_Output { $this->_zlib_oc = @ini_get('zlib.output_compression'); // Get mime types for later - include APPPATH.'config/mimes'.EXT; + if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT)) + { + include APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT; + } + else + { + include APPPATH.'config/mimes'.EXT; + } + + $this->mime_types = $mimes; - + log_message('debug', "Output Class Initialized"); } @@ -78,7 +86,7 @@ class CI_Output { function set_output($output) { $this->final_output = $output; - + return $this; } @@ -168,7 +176,7 @@ class CI_Output { $header = 'Content-Type: '.$mime_type; $this->headers[] = array($header, TRUE); - + return $this; } diff --git a/system/core/Router.php b/system/core/Router.php index 6893e6e92..d451aab68 100644 --- a/system/core/Router.php +++ b/system/core/Router.php @@ -87,7 +87,15 @@ class CI_Router { } // Load the routes.php file. - @include(APPPATH.'config/routes'.EXT); + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/routes'.EXT)) + { + include(APPPATH.'config/'.ENVIRONMENT.'/routes'.EXT); + } + elseif (is_file(APPPATH.'config/routes'.EXT)) + { + include(APPPATH.'config/routes'.EXT); + } + $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route; unset($route); diff --git a/system/libraries/Security.php b/system/core/Security.php index 58db4e79c..ceef9779c 100644 --- a/system/libraries/Security.php +++ b/system/core/Security.php @@ -22,44 +22,44 @@ * @subpackage Libraries * @category Security * @author ExpressionEngine Dev Team - * @link http://codeigniter.com/user_guide/libraries/sessions.html + * @link http://codeigniter.com/user_guide/libraries/security.html */ class CI_Security { - - public $xss_hash = ''; - public $csrf_hash = ''; - public $csrf_expire = 7200; // Two hours (in seconds) - public $csrf_token_name = 'ci_csrf_token'; - public $csrf_cookie_name = 'ci_csrf_token'; + + protected $_xss_hash = ''; + protected $_csrf_hash = ''; + protected $_csrf_expire = 7200; // Two hours (in seconds) + protected $_csrf_token_name = 'ci_csrf_token'; + protected $_csrf_cookie_name = 'ci_csrf_token'; /* never allowed, string replacement */ - public $never_allowed_str = array( - 'document.cookie' => '[removed]', - 'document.write' => '[removed]', - '.parentNode' => '[removed]', - '.innerHTML' => '[removed]', - 'window.location' => '[removed]', - '-moz-binding' => '[removed]', - '<!--' => '<!--', - '-->' => '-->', - '<![CDATA[' => '<![CDATA[' - ); - /* never allowed, regex replacement */ - public $never_allowed_regex = array( - "javascript\s*:" => '[removed]', - "expression\s*(\(|&\#40;)" => '[removed]', // CSS and IE - "vbscript\s*:" => '[removed]', // IE, surprise! - "Redirect\s+302" => '[removed]' - ); + protected $_never_allowed_str = array( + 'document.cookie' => '[removed]', + 'document.write' => '[removed]', + '.parentNode' => '[removed]', + '.innerHTML' => '[removed]', + 'window.location' => '[removed]', + '-moz-binding' => '[removed]', + '<!--' => '<!--', + '-->' => '-->', + '<![CDATA[' => '<![CDATA[' + ); + /* never allowed, regex replacement */ + 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 + */ public function __construct() { - $this->csrf_token_name = (config_item('csrf_token_name')) ? config_item('csrf_token_name') : 'csrf_token_name'; - $this->csrf_cookie_name = (config_item('csrf_cookie_name')) ? config_item('csrf_cookie_name') : 'csrf_cookie_name'; - $this->csrf_expire = (config_item('csrf_expire')) ? config_item('csrf_expire') : 7200; - // Append application specific cookie prefix to token name - $this->csrf_cookie_name = (config_item('cookie_prefix')) ? config_item('cookie_prefix').$this->csrf_token_name : $this->csrf_token_name; + $this->_csrf_cookie_name = (config_item('cookie_prefix')) ? config_item('cookie_prefix').$this->_csrf_token_name : $this->_csrf_token_name; // Set the CSRF hash $this->_csrf_set_hash(); @@ -72,8 +72,7 @@ class CI_Security { /** * Verify Cross Site Request Forgery Protection * - * @access public - * @return null + * @return object */ public function csrf_verify() { @@ -84,26 +83,30 @@ class CI_Security { } // Do the tokens exist in both the _POST and _COOKIE arrays? - if ( ! isset($_POST[$this->csrf_token_name]) OR ! isset($_COOKIE[$this->csrf_cookie_name])) + if ( ! isset($_POST[$this->_csrf_token_name]) OR + ! isset($_COOKIE[$this->_csrf_cookie_name])) { $this->csrf_show_error(); } // Do the tokens match? - if ($_POST[$this->csrf_token_name] != $_COOKIE[$this->csrf_cookie_name]) + if ($_POST[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name]) { $this->csrf_show_error(); } - // We kill this since we're done and we don't want to polute the _POST array - unset($_POST[$this->csrf_token_name]); + // We kill this since we're done and we don't want to + // polute the _POST array + unset($_POST[$this->_csrf_token_name]); // Nothing should last forever - unset($_COOKIE[$this->csrf_cookie_name]); + unset($_COOKIE[$this->_csrf_cookie_name]); $this->_csrf_set_hash(); $this->csrf_set_cookie(); log_message('debug', "CSRF token verified "); + + return $this; } // -------------------------------------------------------------------- @@ -111,57 +114,68 @@ class CI_Security { /** * Set Cross Site Request Forgery Protection Cookie * - * @access public - * @return null + * @return object */ public function csrf_set_cookie() { - $expire = time() + $this->csrf_expire; + $expire = time() + $this->_csrf_expire; $secure_cookie = (config_item('cookie_secure') === TRUE) ? 1 : 0; - setcookie($this->csrf_cookie_name, $this->csrf_hash, $expire, config_item('cookie_path'), config_item('cookie_domain'), $secure_cookie); + if ($secure_cookie) + { + $req = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : FALSE; + + if ( ! $req OR $req == 'off') + { + return FALSE; + } + } + + 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; } // -------------------------------------------------------------------- /** - * Set Cross Site Request Forgery Protection Cookie + * Show CSRF Error * - * @access private - * @return null + * @return void */ - private function _csrf_set_hash() + public function csrf_show_error() { - if ($this->csrf_hash == '') - { - // 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 sub-pages causing this feature to fail - if (isset($_COOKIE[$this->csrf_cookie_name]) AND $_COOKIE[$this->csrf_cookie_name] != '') - { - $this->csrf_hash = $_COOKIE[$this->csrf_cookie_name]; - } - else - { - $this->csrf_hash = md5(uniqid(rand(), TRUE)); - } - } + show_error('The action you have requested is not allowed.'); + } - return $this->csrf_hash; + // -------------------------------------------------------------------- + + /** + * Get CSRF Hash + * + * Getter Method + * + * @return string self::_csrf_hash + */ + public function get_csrf_hash() + { + return $this->_csrf_hash; } // -------------------------------------------------------------------- /** - * Show CSRF Error + * Get CSRF Token Name * - * @access public - * @return null + * Getter Method + * + * @return string self::csrf_token_name */ - public function csrf_show_error() + public function get_csrf_token_name() { - show_error('The action you have requested is not allowed.'); + return $this->_csrf_token_name; } // -------------------------------------------------------------------- @@ -188,7 +202,6 @@ class CI_Security { * harvested from examining vulnerabilities in other programs: * http://ha.ckers.org/xss.html * - * @access public * @param mixed string or array * @return string */ @@ -213,35 +226,8 @@ class CI_Security { */ $str = remove_invisible_characters($str); - /* - * Protect GET variables in URLs - */ - - // 901119URL5918AMP18930PROTECT8198 - - $str = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-]+)|i', $this->xss_hash()."\\1=\\2", $str); - - /* - * Validate standard character entities - * - * Add a semicolon if missing. We do this to enable - * the conversion of entities to ASCII later. - * - */ - $str = preg_replace('#(&\#?[0-9a-z]{2,})([\x00-\x20])*;?#i', "\\1;\\2", $str); - - /* - * Validate UTF16 two byte encoding (x00) - * - * Just as above, adds a semicolon if missing. - * - */ - $str = preg_replace('#(&\#x?)([0-9A-F]+);?#i',"\\1\\2;",$str); - - /* - * Un-Protect GET variables in URLs - */ - $str = str_replace($this->xss_hash(), '&', $str); + // Validate Entities in URLs + $str = $this->_validate_entities($str); /* * URL Decode @@ -265,7 +251,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); /* @@ -278,9 +264,8 @@ 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 large blocks of data, - * so we use str_replace. - * + * NOTE: preg_replace was found to be amazingly slow here on + * large blocks of data, so we use str_replace. */ if (strpos($str, "\t") !== FALSE) @@ -293,34 +278,23 @@ class CI_Security { */ $converted_string = $str; - /* - * Not Allowed Under Any Conditions - */ - - foreach ($this->never_allowed_str as $key => $val) - { - $str = str_replace($key, $val, $str); - } - - foreach ($this->never_allowed_regex as $key => $val) - { - $str = preg_replace("#".$key."#i", $val, $str); - } + // Remove Strings that are never allowed + $str = $this->_do_never_allowed($str); /* * Makes PHP tags safe * - * Note: XML tags are inadvertently replaced too: + * Note: XML tags are inadvertently replaced too: * - * <?xml + * <?xml * * But it doesn't seem to pose a problem. - * */ 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 do the long opening tags. + // 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); } else @@ -333,9 +307,12 @@ class CI_Security { * * This corrects words like: j a v a s c r i p t * These words are compacted back to their correct state. - * */ - $words = array('javascript', 'expression', 'vbscript', 'script', 'applet', 'alert', 'document', 'write', 'cookie', 'window'); + $words = array( + 'javascript', 'expression', 'vbscript', 'script', + 'applet', 'alert', 'document', 'write', 'cookie', 'window' + ); + foreach ($words as $word) { $temp = ''; @@ -352,8 +329,9 @@ 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 preg_match(), especially if the pattern exists in the string + * 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 { @@ -374,30 +352,12 @@ class CI_Security { $str = preg_replace("#<(/*)(script|xss)(.*?)\>#si", '[removed]', $str); } } - while ($original != $str); + while($original != $str); unset($original); - /* - * Remove JavaScript Event Handlers - * - * Note: This code is a little blunt. It removes - * the event handler and anything up to the closing >, - * but it's unlikely to be a problem. - * - */ - $event_handlers = array('[^a-z_\-]on\w*','xmlns'); - - if ($is_image === TRUE) - { - /* - * Adobe Photoshop puts XML metadata into JFIF images, including namespacing, - * so we have to allow this for images. -Paul - */ - unset($event_handlers[array_search('xmlns', $event_handlers)]); - } - - $str = preg_replace("#<([^><]+?)(".implode('|', $event_handlers).")(\s*=\s*[^><]*)([><]*)#i", "<\\1\\4", $str); + // Remove evil attributes such as style, onclick and xmlns + $str = $this->_remove_evil_attributes($str, $is_image); /* * Sanitize naughty HTML elements @@ -407,7 +367,6 @@ class CI_Security { * * So this: <blink> * Becomes: <blink> - * */ $naughty = 'alert|applet|audio|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|isindex|layer|link|meta|object|plaintext|style|script|textarea|title|video|xml|xss'; $str = preg_replace_callback('#<(/*\s*)('.$naughty.')([^><]*)([><]*)#is', array($this, '_sanitize_naughty_html'), $str); @@ -423,45 +382,28 @@ class CI_Security { * * For example: eval('some code') * Becomes: eval('some code') - * */ $str = preg_replace('#(alert|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', "\\1\\2(\\3)", $str); - /* - * Final clean up - * - * This adds a bit of extra precaution in case - * something got through the above filters - * - */ - foreach ($this->never_allowed_str as $key => $val) - { - $str = str_replace($key, $val, $str); - } - foreach ($this->never_allowed_regex as $key => $val) - { - $str = preg_replace("#".$key."#i", $val, $str); - } + // Final clean up + // This adds a bit of extra precaution in case + // something got through the above filters + $str = $this->_do_never_allowed($str); /* - * 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. 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 code found and removed/changed during processing. + * 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. + * 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 + * code found and removed/changed during processing. */ if ($is_image === TRUE) { - if ($str == $converted_string) - { - return TRUE; - } - else - { - return FALSE; - } + return ($str == $converted_string) ? TRUE: FALSE; } log_message('debug', "XSS Filtering completed"); @@ -473,59 +415,208 @@ class CI_Security { /** * Random Hash for protecting URLs * - * @access public * @return string */ public function xss_hash() { - if ($this->xss_hash == '') + if ($this->_xss_hash == '') { if (phpversion() >= 4.2) + { mt_srand(); + } else + { mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff); + } - $this->xss_hash = md5(time() + mt_rand(0, 1999999999)); + $this->_xss_hash = md5(time() + mt_rand(0, 1999999999)); } - return $this->xss_hash; + return $this->_xss_hash; } // -------------------------------------------------------------------- /** + * HTML Entities Decode + * + * 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. + * + * @param string + * @param string + * @return string + */ + 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; + } + + // -------------------------------------------------------------------- + + /** + * Filename Security + * + * @param string + * @return string + */ + public function sanitize_filename($str, $relative_path = FALSE) + { + $bad = array( + "../", + "<!--", + "-->", + "<", + ">", + "'", + '"', + '&', + '$', + '#', + '{', + '}', + '[', + ']', + '=', + ';', + '?', + "%20", + "%22", + "%3c", // < + "%253c", // < + "%3e", // > + "%0e", // > + "%28", // ( + "%29", // ) + "%2528", // ( + "%26", // & + "%24", // $ + "%3f", // ? + "%3b", // ; + "%3d" // = + ); + + if ( ! $relative_path) + { + $bad[] = './'; + $bad[] = '/'; + } + + $str = remove_invisible_characters($str, FALSE); + return stripslashes(str_replace($bad, '', $str)); + } + + // ---------------------------------------------------------------- + + /** * Compact Exploded Words * * Callback function for xss_clean() to remove whitespace from * things like j a v a s c r i p t * - * @access private * @param type * @return type */ - private function _compact_exploded_words($matches) + protected function _compact_exploded_words($matches) { return preg_replace('/\s+/s', '', $matches[1]).$matches[2]; } // -------------------------------------------------------------------- + + /* + * Remove Evil HTML Attributes (like evenhandlers and style) + * + * It removes the evil attribute and either: + * - Everything up until a space + * For example, everything between the pipes: + * <a |style=document.write('hello');alert('world');| class=link> + * - Everything inside the quotes + * For example, everything between the pipes: + * <a |style="document.write('hello'); alert('world');"| class="link"> + * + * @param string $str The string to check + * @param boolean $is_image TRUE if this is an image + * @return string The string with the evil attributes removed + */ + 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'); + + if ($is_image === TRUE) + { + /* + * Adobe Photoshop puts XML metadata into JFIF images, + * including namespacing, so we have to allow this for images. + */ + unset($evil_attributes[array_search('xmlns', $evil_attributes)]); + } + + do { + $str = preg_replace( + "#<(/?[^><]+?)([^A-Za-z\-])(".implode('|', $evil_attributes).")(\s*=\s*)([\"][^>]*?[\"]|[\'][^>]*?[\']|[^>]*?)([\s><])([><]*)#i", + "<$1$6", + $str, -1, $count + ); + } while ($count); + + return $str; + } + + // -------------------------------------------------------------------- /** * Sanitize Naughty HTML * * Callback function for xss_clean() to remove naughty HTML elements * - * @access private * @param array * @return string */ - private function _sanitize_naughty_html($matches) + protected function _sanitize_naughty_html($matches) { // encode opening brace $str = '<'.$matches[1].$matches[2].$matches[3]; // encode captured opening or closing brace to prevent recursive vectors - $str .= str_replace(array('>', '<'), array('>', '<'), $matches[4]); + $str .= str_replace(array('>', '<'), array('>', '<'), + $matches[4]); return $str; } @@ -540,16 +631,18 @@ class CI_Security { * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in * PHP 5.2+ on link-heavy strings * - * @access private * @param array * @return string */ - private function _js_link_removal($match) + 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\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]); + + 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]); } + // -------------------------------------------------------------------- + /** * JS Image Removal * @@ -558,14 +651,14 @@ class CI_Security { * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in * PHP 5.2+ on image tag heavy strings * - * @access private * @param array * @return string */ - private function _js_img_removal($match) + 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\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]); + + 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]); } // -------------------------------------------------------------------- @@ -575,11 +668,10 @@ class CI_Security { * * Used as a callback for XSS Clean * - * @access private * @param array * @return string */ - private function _convert_attribute($match) + protected function _convert_attribute($match) { return str_replace(array('>', '<', '\\'), array('>', '<', '\\\\'), $match[0]); } @@ -591,11 +683,10 @@ class CI_Security { * * Filters tag attributes for consistency and safety * - * @access private * @param string * @return string */ - private function _filter_attributes($str) + protected function _filter_attributes($str) { $out = ''; @@ -617,118 +708,109 @@ class CI_Security { * * Used as a callback for XSS Clean * - * @access private * @param array * @return string */ - private function _decode_entity($match) + protected function _decode_entity($match) { return $this->entity_decode($match[0], strtoupper(config_item('charset'))); } // -------------------------------------------------------------------- - + /** - * HTML Entities Decode - * - * 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 + * Validate URL entities * - * 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. + * Called by xss_clean() * - * @access public - * @param string - * @param string - * @return string + * @param string + * @return string */ - public function entity_decode($str, $charset='UTF-8') + protected function _validate_entities($str) { - if (stristr($str, '&') === FALSE) return $str; + /* + * Protect GET variables in URLs + */ + + // 901119URL5918AMP18930PROTECT8198 + + $str = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-]+)|i', $this->xss_hash()."\\1=\\2", $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. + /* + * Validate standard character entities + * + * Add a semicolon if missing. We do this to enable + * the conversion of entities to ASCII later. + * + */ + $str = preg_replace('#(&\#?[0-9a-z]{2,})([\x00-\x20])*;?#i', "\\1;\\2", $str); - if (function_exists('html_entity_decode') && (strtolower($charset) != 'utf-8' OR is_php('5.0.0'))) - { - $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); - } + /* + * Validate UTF16 two byte encoding (x00) + * + * Just as above, adds a semicolon if missing. + * + */ + $str = preg_replace('#(&\#x?)([0-9A-F]+);?#i',"\\1\\2;",$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); + /* + * Un-Protect GET variables in URLs + */ + $str = str_replace($this->xss_hash(), '&', $str); + + return $str; + } - // Literal Entities - Slightly slow so we do another check - if (stristr($str, '&') === FALSE) + // ---------------------------------------------------------------------- + + /** + * Do Never Allowed + * + * A utility function for xss_clean() + * + * @param string + * @return string + */ + protected function _do_never_allowed($str) + { + foreach ($this->_never_allowed_str as $key => $val) { - $str = strtr($str, array_flip(get_html_translation_table(HTML_ENTITIES))); + $str = str_replace($key, $val, $str); } + foreach ($this->_never_allowed_regex as $key => $val) + { + $str = preg_replace("#".$key."#i", $val, $str); + } + return $str; } // -------------------------------------------------------------------- /** - * Filename Security + * Set Cross Site Request Forgery Protection Cookie * - * @access public - * @param string * @return string */ - public function sanitize_filename($str, $relative_path = FALSE) + protected function _csrf_set_hash() { - $bad = array( - "../", - "<!--", - "-->", - "<", - ">", - "'", - '"', - '&', - '$', - '#', - '{', - '}', - '[', - ']', - '=', - ';', - '?', - "%20", - "%22", - "%3c", // < - "%253c", // < - "%3e", // > - "%0e", // > - "%28", // ( - "%29", // ) - "%2528", // ( - "%26", // & - "%24", // $ - "%3f", // ? - "%3b", // ; - "%3d" // = - ); - - if ( ! $relative_path) + if ($this->_csrf_hash == '') { - $bad[] = './'; - $bad[] = '/'; + // 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 + // sub-pages causing this feature to fail + 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)); } - return stripslashes(str_replace($bad, '', $str)); + return $this->_csrf_hash; } } diff --git a/system/core/URI.php b/system/core/URI.php index c43cde005..80dc62e58 100644 --- a/system/core/URI.php +++ b/system/core/URI.php @@ -64,14 +64,14 @@ class CI_URI { // Is the request coming from the command line? if (defined('STDIN')) { - $this->uri_string = $this->_parse_cli_args(); + $this->_set_uri_string($this->_parse_cli_args()); return; } // Let's try the REQUEST_URI first, this will work in most situations if ($uri = $this->_detect_uri()) { - $this->uri_string = $uri; + $this->_set_uri_string($uri); return; } @@ -80,7 +80,7 @@ class CI_URI { $path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO'); if (trim($path, '/') != '' && $path != "/".SELF) { - $this->uri_string = $path; + $this->_set_uri_string($path); return; } @@ -88,43 +88,54 @@ class CI_URI { $path = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING'); if (trim($path, '/') != '') { - $this->uri_string = $path; + $this->_set_uri_string($path); return; } // As a last ditch effort lets try using the $_GET array if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '') { - $this->uri_string = key($_GET); + $this->_set_uri_string(key($_GET)); return; } // We've exhausted all our options... $this->uri_string = ''; + return; } - else - { - $uri = strtoupper($this->config->item('uri_protocol')); - if ($uri == 'REQUEST_URI') - { - $this->uri_string = $this->_detect_uri(); - return; - } - elseif ($uri == 'CLI') - { - $this->uri_string = $this->_parse_cli_args(); - return; - } + $uri = strtoupper($this->config->item('uri_protocol')); - $this->uri_string = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri); + if ($uri == 'REQUEST_URI') + { + $this->_set_uri_string($this->_detect_uri()); + return; } - - // If the URI contains only a slash we'll kill it - if ($this->uri_string == '/') + elseif ($uri == 'CLI') { - $this->uri_string = ''; + $this->_set_uri_string($this->_parse_cli_args()); + return; } + + $path = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri); + $this->_set_uri_string($path); + } + + // -------------------------------------------------------------------- + + /** + * Set the URI String + * + * @access public + * @return string + */ + function _set_uri_string($str) + { + // Filter out control characters + $str = remove_invisible_characters($str, FALSE); + + // If the URI contains only a slash we'll kill it + $this->uri_string = ($str == '/') ? '' : $str; } // -------------------------------------------------------------------- diff --git a/system/core/Utf8.php b/system/core/Utf8.php index 5d5a7ef72..2a27d1f35 100644 --- a/system/core/Utf8.php +++ b/system/core/Utf8.php @@ -107,7 +107,7 @@ class CI_Utf8 { */ function safe_ascii_for_xml($str) { - return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $str); + return remove_invisible_characters($str, FALSE); } // -------------------------------------------------------------------- diff --git a/system/database/DB.php b/system/database/DB.php index 93ee3922a..8bf1ba8ba 100644 --- a/system/database/DB.php +++ b/system/database/DB.php @@ -27,17 +27,12 @@ function &DB($params = '', $active_record_override = NULL) // Load the DB config file if a DSN string wasn't passed if (is_string($params) AND strpos($params, '://') === FALSE) { - - $file_path = APPPATH.'config/'.ENVIRONMENT.'/database'.EXT; - - if ( ! file_exists($file_path)) + // Is the config file in the environment folder? + if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/database'.EXT)) { - log_message('debug', 'Database config for '.ENVIRONMENT.' environment is not found. Trying global config.'); - $file_path = APPPATH.'config/database'.EXT; - - if ( ! file_exists($file_path)) + if ( ! file_exists($file_path = APPPATH.'config/database'.EXT)) { - continue; + show_error('The configuration file database'.EXT.' does not exist.'); } } diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php index ee72dbbf4..db8471364 100644 --- a/system/database/DB_active_rec.php +++ b/system/database/DB_active_rec.php @@ -1020,11 +1020,11 @@ class CI_DB_active_record extends CI_DB_driver { if ($query->num_rows() == 0) { - return '0'; + return 0; } $row = $query->row(); - return $row->numrows; + return (int) $row->numrows; } // -------------------------------------------------------------------- diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index 5048c0b4a..65397ed8f 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -267,9 +267,11 @@ class CI_DB_mssql_driver extends CI_DB { // escape LIKE condition wildcards if ($like === TRUE) { - $str = str_replace( array('%', '_', $this->_like_escape_chr), - array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr), - $str); + $str = str_replace( + array($this->_like_escape_chr, '%', '_'), + array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), + $str + ); } return $str; diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php index 6cecd0d11..f8073d238 100644 --- a/system/helpers/download_helper.php +++ b/system/helpers/download_helper.php @@ -58,7 +58,14 @@ if ( ! function_exists('force_download')) $extension = end($x); // Load the mime types - @include(APPPATH.'config/mimes'.EXT); + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT)) + { + include(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT); + } + elseif (is_file(APPPATH.'config/mimes'.EXT)) + { + include(APPPATH.'config/mimes'.EXT); + } // Set a default mime if we can't find it if ( ! isset($mimes[$extension])) diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php index 9518e4843..44344947e 100644 --- a/system/helpers/file_helper.php +++ b/system/helpers/file_helper.php @@ -352,7 +352,16 @@ if ( ! function_exists('get_mime_by_extension')) if ( ! is_array($mimes)) { - if ( ! require_once(APPPATH.'config/mimes.php')) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT)) + { + include(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT); + } + elseif (is_file(APPPATH.'config/mimes'.EXT)) + { + include(APPPATH.'config/mimes'.EXT); + } + + if ( ! is_array($mimes)) { return FALSE; } diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php index 532309794..8aa788c6c 100644 --- a/system/helpers/form_helper.php +++ b/system/helpers/form_helper.php @@ -49,11 +49,15 @@ if ( ! function_exists('form_open')) $attributes = 'method="post"'; } + // If an action is not a full URL then turn it into one if ($action && strpos($action, '://') === FALSE) { $action = $CI->config->site_url($action); } + // If no action is provided then set to the current url + $action OR $action = $CI->config->site_url($CI->uri->uri_string()); + $form = '<form action="'.$action.'"'; $form .= _attributes_to_string($attributes, TRUE); diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php index 68c6f5908..c6103ab6f 100644 --- a/system/helpers/html_helper.php +++ b/system/helpers/html_helper.php @@ -258,7 +258,16 @@ if ( ! function_exists('doctype')) if ( ! is_array($_doctypes)) { - if ( ! require_once(APPPATH.'config/doctypes.php')) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/doctypes'.EXT)) + { + include(APPPATH.'config/'.ENVIRONMENT.'/doctypes'.EXT); + } + elseif (is_file(APPPATH.'config/doctypes'.EXT)) + { + include(APPPATH.'config/doctypes'.EXT); + } + + if ( ! is_array($_doctypes)) { return FALSE; } diff --git a/system/helpers/security_helper.php b/system/helpers/security_helper.php index 61ebf46f9..678dac821 100644 --- a/system/helpers/security_helper.php +++ b/system/helpers/security_helper.php @@ -67,22 +67,6 @@ if ( ! function_exists('sanitize_filename')) /** * Hash encode a string * - * This is simply an alias for do_hash() - * dohash() is now deprecated - */ -if ( ! function_exists('dohash')) -{ - function dohash($str, $type = 'sha1') - { - return do_hash($str, $type); - } -} - -// -------------------------------------------------------------------- - -/** - * Hash encode a string - * * @access public * @param string * @return string @@ -93,23 +77,7 @@ if ( ! function_exists('do_hash')) { if ($type == 'sha1') { - if ( ! function_exists('sha1')) - { - if ( ! function_exists('mhash')) - { - require_once(BASEPATH.'libraries/Sha1'.EXT); - $SH = new CI_SHA; - return $SH->generate($str); - } - else - { - return bin2hex(mhash(MHASH_SHA1, $str)); - } - } - else - { - return sha1($str); - } + return sha1($str); } else { diff --git a/system/helpers/smiley_helper.php b/system/helpers/smiley_helper.php index 463881f58..a2d1031b3 100644 --- a/system/helpers/smiley_helper.php +++ b/system/helpers/smiley_helper.php @@ -229,19 +229,21 @@ if ( ! function_exists('_get_smiley_array')) { function _get_smiley_array() { - if ( ! file_exists(APPPATH.'config/smileys'.EXT)) + if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/smileys'.EXT)) { - return FALSE; + include(APPPATH.'config/'.ENVIRONMENT.'/smileys'.EXT); } - - include(APPPATH.'config/smileys'.EXT); - - if ( ! isset($smileys) OR ! is_array($smileys)) + elseif (file_exists(APPPATH.'config/smileys'.EXT)) + { + include(APPPATH.'config/smileys'.EXT); + } + + if (isset($smileys) AND is_array($smileys)) { - return FALSE; + return $smileys; } - return $smileys; + return FALSE; } } diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php index 96afd4cee..cca093976 100644 --- a/system/helpers/text_helper.php +++ b/system/helpers/text_helper.php @@ -366,12 +366,14 @@ if ( ! function_exists('convert_accented_characters')) { function convert_accented_characters($str) { - if ( ! file_exists(APPPATH.'config/foreign_chars'.EXT)) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars'.EXT)) { - return $str; + include(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars'.EXT); + } + elseif (is_file(APPPATH.'config/foreign_chars'.EXT)) + { + include(APPPATH.'config/foreign_chars'.EXT); } - - include APPPATH.'config/foreign_chars'.EXT; if ( ! isset($foreign_characters)) { diff --git a/system/helpers/typography_helper.php b/system/helpers/typography_helper.php index 302bf45c5..19b4eec03 100644 --- a/system/helpers/typography_helper.php +++ b/system/helpers/typography_helper.php @@ -84,9 +84,8 @@ if ( ! function_exists('entity_decode')) { function entity_decode($str, $charset='UTF-8') { - $CI =& get_instance(); - $CI->load->library('security'); - return $CI->security->entity_decode($str, $charset); + global $SEC; + return $SEC->entity_decode($str, $charset); } } diff --git a/system/language/english/form_validation_lang.php b/system/language/english/form_validation_lang.php index b01885091..3f2409007 100644 --- a/system/language/english/form_validation_lang.php +++ b/system/language/english/form_validation_lang.php @@ -19,6 +19,9 @@ $lang['regex_match'] = "The %s field is not in the correct format."; $lang['matches'] = "The %s field does not match the %s field."; $lang['is_natural'] = "The %s field must contain only positive numbers."; $lang['is_natural_no_zero'] = "The %s field must contain a number greater than zero."; +$lang['decimal'] = "The %s field must contain a decimal number."; +$lang['less_than'] = "The %s field must contain a number less than %s."; +$lang['greater_than'] = "The %s field must contain a number greater than %s."; /* End of file form_validation_lang.php */ diff --git a/system/language/english/ftp_lang.php b/system/language/english/ftp_lang.php index 392b2b272..1e5168cf8 100644 --- a/system/language/english/ftp_lang.php +++ b/system/language/english/ftp_lang.php @@ -1,17 +1,17 @@ <?php -$lang['ftp_no_connection'] = "Unable to locate a valid connection ID. Please make sure you are connected before peforming any file routines."; +$lang['ftp_no_connection'] = "Unable to locate a valid connection ID. Please make sure you are connected before peforming any file routines."; $lang['ftp_unable_to_connect'] = "Unable to connect to your FTP server using the supplied hostname."; -$lang['ftp_unable_to_login'] = "Unable to login to your FTP server. Please check your username and password."; +$lang['ftp_unable_to_login'] = "Unable to login to your FTP server. Please check your username and password."; $lang['ftp_unable_to_makdir'] = "Unable to create the directory you have specified."; $lang['ftp_unable_to_changedir'] = "Unable to change directories."; -$lang['ftp_unable_to_chmod'] = "Unable to set file permissions. Please check your path. Note: This feature is only available in PHP 5 or higher."; -$lang['ftp_unable_to_upload'] = "Unable to upload the specified file. Please check your path."; -$lang['ftp_unable_to_download'] = "Unable to download the specified file. Please check your path."; -$lang['ftp_no_source_file'] = "Unable to locate the source file. Please check your path."; +$lang['ftp_unable_to_chmod'] = "Unable to set file permissions. Please check your path. Note: This feature is only available in PHP 5 or higher."; +$lang['ftp_unable_to_upload'] = "Unable to upload the specified file. Please check your path."; +$lang['ftp_unable_to_download'] = "Unable to download the specified file. Please check your path."; +$lang['ftp_no_source_file'] = "Unable to locate the source file. Please check your path."; $lang['ftp_unable_to_rename'] = "Unable to rename the file."; $lang['ftp_unable_to_delete'] = "Unable to delete the file."; -$lang['ftp_unable_to_move'] = "Unable to move the file. Please make sure the destination directory exists."; +$lang['ftp_unable_to_move'] = "Unable to move the file. Please make sure the destination directory exists."; /* End of file ftp_lang.php */ diff --git a/system/libraries/Cache/Cache.php b/system/libraries/Cache/Cache.php index d3f6105ea..61e7aa761 100644 --- a/system/libraries/Cache/Cache.php +++ b/system/libraries/Cache/Cache.php @@ -24,11 +24,11 @@ * @author ExpressionEngine Dev Team * @link */ -class Cache extends CI_Driver_Library { +class CI_Cache extends CI_Driver_Library { protected $valid_drivers = array( - 'cache_apc', 'cache_file', 'cache_memcached', 'cache_dummy' - ); + 'cache_apc', 'cache_file', 'cache_memcached', 'cache_dummy' + ); protected $_cache_path = NULL; // Path of cache files (if file-based cache) protected $_adapter = 'dummy'; diff --git a/system/libraries/Cache/drivers/Cache_apc.php b/system/libraries/Cache/drivers/Cache_apc.php index 4b995c793..de75719c4 100644 --- a/system/libraries/Cache/drivers/Cache_apc.php +++ b/system/libraries/Cache/drivers/Cache_apc.php @@ -25,7 +25,7 @@ * @link */ -class Cache_apc extends CI_Driver { +class CI_Cache_apc extends CI_Driver { /** * Get diff --git a/system/libraries/Cache/drivers/Cache_dummy.php b/system/libraries/Cache/drivers/Cache_dummy.php index 74f689241..de47acb43 100644 --- a/system/libraries/Cache/drivers/Cache_dummy.php +++ b/system/libraries/Cache/drivers/Cache_dummy.php @@ -25,7 +25,7 @@ * @link */ -class Cache_dummy extends CI_Driver { +class CI_Cache_dummy extends CI_Driver { /** * Get diff --git a/system/libraries/Cache/drivers/Cache_file.php b/system/libraries/Cache/drivers/Cache_file.php index 86d1a3b6a..13e2d1af6 100644 --- a/system/libraries/Cache/drivers/Cache_file.php +++ b/system/libraries/Cache/drivers/Cache_file.php @@ -25,7 +25,7 @@ * @link */ -class Cache_file extends CI_Driver { +class CI_Cache_file extends CI_Driver { protected $_cache_path; diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php index 5f5a31591..ec2fd216a 100644 --- a/system/libraries/Cache/drivers/Cache_memcached.php +++ b/system/libraries/Cache/drivers/Cache_memcached.php @@ -25,7 +25,7 @@ * @link */ -class Cache_memcached extends CI_Driver { +class CI_Cache_memcached extends CI_Driver { private $_memcached; // Holds the memcached object diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php index 02e093d7e..d1838f2c1 100644 --- a/system/libraries/Driver.php +++ b/system/libraries/Driver.php @@ -44,7 +44,11 @@ class CI_Driver_Library { // The class will be prefixed with the parent lib $child_class = $this->lib_name.'_'.$child; - if (in_array(strtolower($child_class), array_map('strtolower', $this->valid_drivers))) + // Remove the CI_ prefix and lowercase + $lib_name = strtolower(preg_replace('/^CI_/', '', $this->lib_name)); + $driver_name = strtolower(preg_replace('/^CI_/', '', $child_class)); + + if (in_array($driver_name, array_map('strtolower', $this->valid_drivers))) { // check and see if the driver is in a separate file if ( ! class_exists($child_class)) @@ -52,19 +56,15 @@ class CI_Driver_Library { // check application path first foreach (array(APPPATH, BASEPATH) as $path) { - // and check for case sensitivity of both the parent and child libs - foreach (array(ucfirst($this->lib_name), strtolower($this->lib_name)) as $lib) + // loves me some nesting! + foreach (array(ucfirst($driver_name), $driver_name) as $class) { - // loves me some nesting! - foreach (array(ucfirst($child_class), strtolower($child_class)) as $class) - { - $filepath = $path.'libraries/'.$this->lib_name.'/drivers/'.$child_class.EXT; + $filepath = $path.'libraries/'.$lib_name.'/drivers/'.$class.EXT; - if (file_exists($filepath)) - { - include_once $filepath; - break; - } + if (file_exists($filepath)) + { + include_once $filepath; + break; } } } diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php index adfd17db1..cfc02eda9 100644 --- a/system/libraries/Form_validation.php +++ b/system/libraries/Form_validation.php @@ -1336,11 +1336,6 @@ class CI_Form_validation { */ function xss_clean($str) { - if ( ! isset($this->CI->security)) - { - $this->CI->load->library('security'); - } - return $this->CI->security->xss_clean($str); } diff --git a/system/libraries/Javascript.php b/system/libraries/Javascript.php index 167859abd..34e0d7001 100644 --- a/system/libraries/Javascript.php +++ b/system/libraries/Javascript.php @@ -855,7 +855,7 @@ class CI_Javascript { } elseif (is_string($result) OR $is_key) { - return '"'.str_replace(array('\\', "\t", "\n", "\r", '"'), array('\\\\', '\\t', '\\n', "\\r", '\"'), $result).'"'; + return '"'.str_replace(array('\\', "\t", "\n", "\r", '"', '/'), array('\\\\', '\\t', '\\n', "\\r", '\"', '\/'), $result).'"'; } elseif (is_scalar($result)) { diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php index e15ea1b5d..e80049fa4 100644 --- a/system/libraries/Upload.php +++ b/system/libraries/Upload.php @@ -142,7 +142,7 @@ class CI_Upload { */ public function do_upload($field = 'userfile') { - + // Is $_FILES[$field] set? If not, no reason to continue. if ( ! isset($_FILES[$field])) { @@ -875,12 +875,6 @@ class CI_Upload { } $CI =& get_instance(); - - if ( ! isset($CI->security)) - { - $CI->load->library('security'); - } - return $CI->security->xss_clean($data, TRUE); } @@ -951,11 +945,21 @@ class CI_Upload { if (count($this->mimes) == 0) { - if (@require_once(APPPATH.'config/mimes'.EXT)) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT)) + { + include(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT); + } + elseif (is_file(APPPATH.'config/mimes'.EXT)) + { + include(APPPATH.'config//mimes'.EXT); + } + else { - $this->mimes = $mimes; - unset($mimes); + return FALSE; } + + $this->mimes = $mimes; + unset($mimes); } return ( ! isset($this->mimes[$mime])) ? FALSE : $this->mimes[$mime]; diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php index 3774fc283..04cda7312 100644 --- a/system/libraries/User_agent.php +++ b/system/libraries/User_agent.php @@ -84,7 +84,15 @@ class CI_User_agent { */ private function _load_agent_file() { - if ( ! @include(APPPATH.'config/user_agents'.EXT)) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/user_agents'.EXT)) + { + include(APPPATH.'config/'.ENVIRONMENT.'/user_agents'.EXT); + } + elseif (is_file(APPPATH.'config/user_agents'.EXT)) + { + include(APPPATH.'config/user_agents'.EXT); + } + else { return FALSE; } diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php index a24bca9b6..5da6ea6ae 100644 --- a/system/libraries/Xmlrpc.php +++ b/system/libraries/Xmlrpc.php @@ -504,12 +504,7 @@ class XML_RPC_Response function decode($array=FALSE) { $CI =& get_instance(); - - if ($this->xss_clean && ! isset($CI->security)) - { - $CI->load->library('security'); - } - + if ($array !== FALSE && is_array($array)) { while (list($key) = each($array)) @@ -1121,12 +1116,7 @@ class XML_RPC_Message extends CI_Xmlrpc function output_parameters($array=FALSE) { $CI =& get_instance(); - - if ($this->xss_clean && ! isset($CI->security)) - { - $CI->load->library('security'); - } - + if ($array !== FALSE && is_array($array)) { while (list($key) = each($array)) |