From 7c6a5891c25bfdd392ed6317fd8f87b58386f030 Mon Sep 17 00:00:00 2001 From: Kyle Farris Date: Fri, 11 Mar 2011 17:33:05 -0500 Subject: Changed the 'plural' function so that it doesn't ruin the captalization of your string. It also take into consideration acronyms which are all caps. --- system/helpers/inflector_helper.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php index 4cd7486b4..3042202cb 100644 --- a/system/helpers/inflector_helper.php +++ b/system/helpers/inflector_helper.php @@ -82,18 +82,17 @@ if ( ! function_exists('plural')) { function plural($str, $force = FALSE) { - $str = strtolower(trim($str)); $end = substr($str, -1); - if ($end == 'y') + if (preg_match('/y/i',$end)) { // Y preceded by vowel => regular plural - $vowels = array('a', 'e', 'i', 'o', 'u'); + $vowels = array('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'); $str = in_array(substr($str, -2, 1), $vowels) ? $str.'s' : substr($str, 0, -1).'ies'; } - elseif ($end == 'h') + elseif (preg_match('/h/i',$end)) { - if (substr($str, -2) == 'ch' OR substr($str, -2) == 'sh') + if(preg_match('/^[c|s]h$/i',substr($str, -2))) { $str .= 'es'; } @@ -102,7 +101,7 @@ if ( ! function_exists('plural')) $str .= 's'; } } - elseif ($end == 's') + elseif (preg_match('/s/i',$end)) { if ($force == TRUE) { -- cgit v1.2.3-24-g4f1b From af376a2df84123549293af846f827ff4da30bf5e Mon Sep 17 00:00:00 2001 From: Kyle Farris Date: Fri, 11 Mar 2011 17:46:53 -0500 Subject: Forgot to trim the string first. --- system/helpers/inflector_helper.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php index 3042202cb..e1cd66be0 100644 --- a/system/helpers/inflector_helper.php +++ b/system/helpers/inflector_helper.php @@ -81,7 +81,8 @@ if ( ! function_exists('singular')) if ( ! function_exists('plural')) { function plural($str, $force = FALSE) - { + { + $str = trim($str); $end = substr($str, -1); if (preg_match('/y/i',$end)) -- cgit v1.2.3-24-g4f1b From 2f620fe804ae5b7f4f20adc70ceaee1cf616a655 Mon Sep 17 00:00:00 2001 From: Kyle Farris Date: Fri, 11 Mar 2011 18:34:07 -0500 Subject: Fixed the capitalization "bug" in the singular function as well. --- system/helpers/inflector_helper.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php index e1cd66be0..c7c113b8a 100644 --- a/system/helpers/inflector_helper.php +++ b/system/helpers/inflector_helper.php @@ -41,20 +41,22 @@ if ( ! function_exists('singular')) { function singular($str) { - $str = strtolower(trim($str)); + $str = trim($str); $end = substr($str, -3); - - if ($end == 'ies') + + $str = preg_replace('/(.*)?([s|c]h)es/i','$1$2',$str); + + if (strtolower($end) == 'ies') { - $str = substr($str, 0, strlen($str)-3).'y'; + $str = substr($str, 0, strlen($str)-3).(preg_match('/[a-z]/',$end) ? 'y' : 'Y'); } - elseif ($end == 'ses') + elseif (strtolower($end) == 'ses') { $str = substr($str, 0, strlen($str)-2); } else { - $end = substr($str, -1); + $end = strtolower(substr($str, -1)); if ($end == 's') { -- cgit v1.2.3-24-g4f1b From c9c045a7feee07563c8d14bac3381f7af0e17280 Mon Sep 17 00:00:00 2001 From: Pascal Kriete Date: Tue, 5 Apr 2011 14:50:41 -0400 Subject: Improving parameter security in xss clean --- system/libraries/Security.php | 620 ++++++++++++++++++++++++------------------ 1 file changed, 351 insertions(+), 269 deletions(-) diff --git a/system/libraries/Security.php b/system/libraries/Security.php index 58db4e79c..ceef9779c 100644 --- a/system/libraries/Security.php +++ b/system/libraries/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[' - ); - /* 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[' + ); + /* 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: * - * #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: * 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,41 +415,190 @@ 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: + * + * - Everything inside the quotes + * For example, everything between the pipes: + * + * + * @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; + } + // -------------------------------------------------------------------- /** @@ -515,17 +606,17 @@ class CI_Security { * * 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|_filter_attributes(str_replace(array('<', '>'), '', $match[1])); - return str_replace($match[1], preg_replace("#src=.*?(alert\(|alert&\#40;|javascript\:|charset\=|window\.|document\.|\.cookie|', '<', '\\'), 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; } } -- cgit v1.2.3-24-g4f1b From 0ff50269e6bac31870a4d69bf4bc0bb895999f1f Mon Sep 17 00:00:00 2001 From: Pascal Kriete Date: Tue, 5 Apr 2011 14:52:03 -0400 Subject: tweaking remove_invisible_characters to make urlencoded character stripping optional --- system/core/Common.php | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/system/core/Common.php b/system/core/Common.php index f424a2cc9..b4bd5b097 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -477,28 +477,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; } -- cgit v1.2.3-24-g4f1b From 14a0ac63a9dfb72e4681c37f7727cd48882152bd Mon Sep 17 00:00:00 2001 From: Pascal Kriete Date: Tue, 5 Apr 2011 14:55:56 -0400 Subject: Moving security to core. --- system/core/CodeIgniter.php | 7 + system/core/Input.php | 16 +- system/core/Security.php | 820 ++++++++++++++++++++++++++++++++++++++++++ system/core/Utf8.php | 2 +- system/libraries/Security.php | 820 ------------------------------------------ 5 files changed, 835 insertions(+), 830 deletions(-) create mode 100644 system/core/Security.php delete mode 100644 system/libraries/Security.php diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index 39a4d7ffd..7f4595e68 100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -196,6 +196,13 @@ } } +/* + * ----------------------------------------------------- + * Load the security class for xss and csrf support + * ----------------------------------------------------- + */ + $SEC =& load_class('Security', 'core'); + /* * ------------------------------------------------------ * Load the Input class and sanitize globals diff --git a/system/core/Input.php b/system/core/Input.php index 18131350f..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) @@ -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/Security.php b/system/core/Security.php new file mode 100644 index 000000000..ceef9779c --- /dev/null +++ b/system/core/Security.php @@ -0,0 +1,820 @@ + '[removed]', + 'document.write' => '[removed]', + '.parentNode' => '[removed]', + '.innerHTML' => '[removed]', + 'window.location' => '[removed]', + '-moz-binding' => '[removed]', + '' => '-->', + ' '<![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() + { + // 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; + + // Set the CSRF hash + $this->_csrf_set_hash(); + + log_message('debug', "Security Class Initialized"); + } + + // -------------------------------------------------------------------- + + /** + * Verify Cross Site Request Forgery Protection + * + * @return object + */ + public function csrf_verify() + { + // If no POST data exists we will set the CSRF cookie + if (count($_POST) == 0) + { + return $this->csrf_set_cookie(); + } + + // 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])) + { + $this->csrf_show_error(); + } + + // Do the tokens match? + 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]); + + // Nothing should last forever + unset($_COOKIE[$this->_csrf_cookie_name]); + $this->_csrf_set_hash(); + $this->csrf_set_cookie(); + + log_message('debug', "CSRF token verified "); + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Set Cross Site Request Forgery Protection Cookie + * + * @return object + */ + public function csrf_set_cookie() + { + $expire = time() + $this->_csrf_expire; + $secure_cookie = (config_item('cookie_secure') === TRUE) ? 1 : 0; + + 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; + } + + // -------------------------------------------------------------------- + + /** + * Show CSRF Error + * + * @return void + */ + public function csrf_show_error() + { + show_error('The action you have requested is not allowed.'); + } + + // -------------------------------------------------------------------- + + /** + * Get CSRF Hash + * + * Getter Method + * + * @return string self::_csrf_hash + */ + public function get_csrf_hash() + { + return $this->_csrf_hash; + } + + // -------------------------------------------------------------------- + + /** + * Get CSRF Token Name + * + * Getter Method + * + * @return string self::csrf_token_name + */ + public function get_csrf_token_name() + { + return $this->_csrf_token_name; + } + + // -------------------------------------------------------------------- + + /** + * XSS Clean + * + * Sanitizes data so that Cross Site Scripting Hacks can be + * prevented. This function does a fair amount of work but + * it is extremely thorough, designed to prevent even the + * most obscure XSS attempts. Nothing is ever 100% foolproof, + * of course, but I haven't been able to get anything passed + * the filter. + * + * Note: This function should only be used to deal with data + * upon submission. It's not something that should + * be used for general runtime processing. + * + * This function was based in part on some code and ideas I + * got from Bitflux: http://channel.bitflux.ch/wiki/XSS_Prevention + * + * To help develop this script I used this great list of + * vulnerabilities along with a few other hacks I've + * harvested from examining vulnerabilities in other programs: + * http://ha.ckers.org/xss.html + * + * @param mixed string or array + * @return string + */ + public function xss_clean($str, $is_image = FALSE) + { + /* + * Is the string an array? + * + */ + if (is_array($str)) + { + while (list($key) = each($str)) + { + $str[$key] = $this->xss_clean($str[$key]); + } + + return $str; + } + + /* + * Remove Invisible Characters + */ + $str = remove_invisible_characters($str); + + // Validate Entities in URLs + $str = $this->_validate_entities($str); + + /* + * URL Decode + * + * Just in case stuff like this is submitted: + * + * Google + * + * Note: Use rawurldecode() so it does not remove plus signs + * + */ + $str = rawurldecode($str); + + /* + * Convert character entities to ASCII + * + * This permits our tests below to work reliably. + * We only convert entities that are within tags since + * these are the ones that will pose security problems. + * + */ + + $str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str); + + $str = preg_replace_callback("/<\w+.*?(?=>|<|$)/si", array($this, '_decode_entity'), $str); + + /* + * Remove Invisible Characters Again! + */ + $str = remove_invisible_characters($str); + + /* + * Convert all tabs to spaces + * + * 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. + */ + + if (strpos($str, "\t") !== FALSE) + { + $str = str_replace("\t", ' ', $str); + } + + /* + * Capture converted string for later comparison + */ + $converted_string = $str; + + // Remove Strings that are never allowed + $str = $this->_do_never_allowed($str); + + /* + * Makes PHP tags safe + * + * Note: XML tags are inadvertently replaced too: + * + * '), array('<?', '?>'), $str); + } + + /* + * Compact any exploded words + * + * 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' + ); + + foreach ($words as $word) + { + $temp = ''; + + for ($i = 0, $wordlen = strlen($word); $i < $wordlen; $i++) + { + $temp .= substr($word, $i, 1)."\s*"; + } + + // We only want to do this when it is followed by a non-word character + // That way valid stuff like "dealer to" does not become "dealerto" + $str = preg_replace_callback('#('.substr($temp, 0, -3).')(\W)#is', array($this, '_compact_exploded_words'), $str); + } + + /* + * 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 + */ + do + { + $original = $str; + + if (preg_match("/]*?)(>|$)#si", array($this, '_js_link_removal'), $str); + } + + if (preg_match("/]*?)(\s?/?>|$)#si", array($this, '_js_img_removal'), $str); + } + + if (preg_match("/script/i", $str) OR preg_match("/xss/i", $str)) + { + $str = preg_replace("#<(/*)(script|xss)(.*?)\>#si", '[removed]', $str); + } + } + while($original != $str); + + unset($original); + + // Remove evil attributes such as style, onclick and xmlns + $str = $this->_remove_evil_attributes($str, $is_image); + + /* + * Sanitize naughty HTML elements + * + * If a tag containing any of the words in the list + * below is found, the tag gets converted to entities. + * + * So this: + * 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); + + /* + * Sanitize naughty scripting elements + * + * Similar to above, only instead of looking for + * tags it looks for PHP and JavaScript commands + * that are disallowed. Rather than removing the + * code, it simply converts the parenthesis to entities + * rendering the code un-executable. + * + * 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 + $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. + */ + + if ($is_image === TRUE) + { + return ($str == $converted_string) ? TRUE: FALSE; + } + + log_message('debug', "XSS Filtering completed"); + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Random Hash for protecting URLs + * + * @return string + */ + public function 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)); + } + + 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 + * + * @param type + * @return type + */ + 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: + * + * - Everything inside the quotes + * For example, everything between the pipes: + * + * + * @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 + * + * @param array + * @return string + */ + 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]); + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * JS Link Removal + * + * Callback function for xss_clean() to sanitize links + * This limits the PCRE backtracks, making it more performance friendly + * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in + * PHP 5.2+ on link-heavy strings + * + * @param array + * @return string + */ + 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|_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|', '<', '\\'), array('>', '<', '\\\\'), $match[0]); + } + + // -------------------------------------------------------------------- + + /** + * Filter Attributes + * + * Filters tag attributes for consistency and safety + * + * @param string + * @return string + */ + protected function _filter_attributes($str) + { + $out = ''; + + if (preg_match_all('#\s*[a-z\-]+\s*=\s*(\042|\047)([^\\1]*?)\\1#is', $str, $matches)) + { + foreach ($matches[0] as $match) + { + $out .= preg_replace("#/\*.*?\*/#s", '', $match); + } + } + + return $out; + } + + // -------------------------------------------------------------------- + + /** + * HTML Entity Decode Callback + * + * Used as a callback for XSS Clean + * + * @param array + * @return string + */ + protected function _decode_entity($match) + { + return $this->entity_decode($match[0], strtoupper(config_item('charset'))); + } + + // -------------------------------------------------------------------- + + /** + * Validate URL entities + * + * Called by xss_clean() + * + * @param string + * @return string + */ + protected function _validate_entities($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); + + return $str; + } + + // ---------------------------------------------------------------------- + + /** + * 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 = str_replace($key, $val, $str); + } + + foreach ($this->_never_allowed_regex as $key => $val) + { + $str = preg_replace("#".$key."#i", $val, $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Set Cross Site Request Forgery Protection Cookie + * + * @return string + */ + protected function _csrf_set_hash() + { + 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]) && + $_COOKIE[$this->_csrf_cookie_name] != '') + { + return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name]; + } + + return $this->_csrf_hash = md5(uniqid(rand(), TRUE)); + } + + return $this->_csrf_hash; + } + +} +// END Security Class + +/* End of file Security.php */ +/* Location: ./system/libraries/Security.php */ \ No newline at end of file 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/libraries/Security.php b/system/libraries/Security.php deleted file mode 100644 index ceef9779c..000000000 --- a/system/libraries/Security.php +++ /dev/null @@ -1,820 +0,0 @@ - '[removed]', - 'document.write' => '[removed]', - '.parentNode' => '[removed]', - '.innerHTML' => '[removed]', - 'window.location' => '[removed]', - '-moz-binding' => '[removed]', - '' => '-->', - ' '<![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() - { - // 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; - - // Set the CSRF hash - $this->_csrf_set_hash(); - - log_message('debug', "Security Class Initialized"); - } - - // -------------------------------------------------------------------- - - /** - * Verify Cross Site Request Forgery Protection - * - * @return object - */ - public function csrf_verify() - { - // If no POST data exists we will set the CSRF cookie - if (count($_POST) == 0) - { - return $this->csrf_set_cookie(); - } - - // 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])) - { - $this->csrf_show_error(); - } - - // Do the tokens match? - 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]); - - // Nothing should last forever - unset($_COOKIE[$this->_csrf_cookie_name]); - $this->_csrf_set_hash(); - $this->csrf_set_cookie(); - - log_message('debug', "CSRF token verified "); - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Set Cross Site Request Forgery Protection Cookie - * - * @return object - */ - public function csrf_set_cookie() - { - $expire = time() + $this->_csrf_expire; - $secure_cookie = (config_item('cookie_secure') === TRUE) ? 1 : 0; - - 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; - } - - // -------------------------------------------------------------------- - - /** - * Show CSRF Error - * - * @return void - */ - public function csrf_show_error() - { - show_error('The action you have requested is not allowed.'); - } - - // -------------------------------------------------------------------- - - /** - * Get CSRF Hash - * - * Getter Method - * - * @return string self::_csrf_hash - */ - public function get_csrf_hash() - { - return $this->_csrf_hash; - } - - // -------------------------------------------------------------------- - - /** - * Get CSRF Token Name - * - * Getter Method - * - * @return string self::csrf_token_name - */ - public function get_csrf_token_name() - { - return $this->_csrf_token_name; - } - - // -------------------------------------------------------------------- - - /** - * XSS Clean - * - * Sanitizes data so that Cross Site Scripting Hacks can be - * prevented. This function does a fair amount of work but - * it is extremely thorough, designed to prevent even the - * most obscure XSS attempts. Nothing is ever 100% foolproof, - * of course, but I haven't been able to get anything passed - * the filter. - * - * Note: This function should only be used to deal with data - * upon submission. It's not something that should - * be used for general runtime processing. - * - * This function was based in part on some code and ideas I - * got from Bitflux: http://channel.bitflux.ch/wiki/XSS_Prevention - * - * To help develop this script I used this great list of - * vulnerabilities along with a few other hacks I've - * harvested from examining vulnerabilities in other programs: - * http://ha.ckers.org/xss.html - * - * @param mixed string or array - * @return string - */ - public function xss_clean($str, $is_image = FALSE) - { - /* - * Is the string an array? - * - */ - if (is_array($str)) - { - while (list($key) = each($str)) - { - $str[$key] = $this->xss_clean($str[$key]); - } - - return $str; - } - - /* - * Remove Invisible Characters - */ - $str = remove_invisible_characters($str); - - // Validate Entities in URLs - $str = $this->_validate_entities($str); - - /* - * URL Decode - * - * Just in case stuff like this is submitted: - * - * Google - * - * Note: Use rawurldecode() so it does not remove plus signs - * - */ - $str = rawurldecode($str); - - /* - * Convert character entities to ASCII - * - * This permits our tests below to work reliably. - * We only convert entities that are within tags since - * these are the ones that will pose security problems. - * - */ - - $str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str); - - $str = preg_replace_callback("/<\w+.*?(?=>|<|$)/si", array($this, '_decode_entity'), $str); - - /* - * Remove Invisible Characters Again! - */ - $str = remove_invisible_characters($str); - - /* - * Convert all tabs to spaces - * - * 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. - */ - - if (strpos($str, "\t") !== FALSE) - { - $str = str_replace("\t", ' ', $str); - } - - /* - * Capture converted string for later comparison - */ - $converted_string = $str; - - // Remove Strings that are never allowed - $str = $this->_do_never_allowed($str); - - /* - * Makes PHP tags safe - * - * Note: XML tags are inadvertently replaced too: - * - * '), array('<?', '?>'), $str); - } - - /* - * Compact any exploded words - * - * 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' - ); - - foreach ($words as $word) - { - $temp = ''; - - for ($i = 0, $wordlen = strlen($word); $i < $wordlen; $i++) - { - $temp .= substr($word, $i, 1)."\s*"; - } - - // We only want to do this when it is followed by a non-word character - // That way valid stuff like "dealer to" does not become "dealerto" - $str = preg_replace_callback('#('.substr($temp, 0, -3).')(\W)#is', array($this, '_compact_exploded_words'), $str); - } - - /* - * 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 - */ - do - { - $original = $str; - - if (preg_match("/]*?)(>|$)#si", array($this, '_js_link_removal'), $str); - } - - if (preg_match("/]*?)(\s?/?>|$)#si", array($this, '_js_img_removal'), $str); - } - - if (preg_match("/script/i", $str) OR preg_match("/xss/i", $str)) - { - $str = preg_replace("#<(/*)(script|xss)(.*?)\>#si", '[removed]', $str); - } - } - while($original != $str); - - unset($original); - - // Remove evil attributes such as style, onclick and xmlns - $str = $this->_remove_evil_attributes($str, $is_image); - - /* - * Sanitize naughty HTML elements - * - * If a tag containing any of the words in the list - * below is found, the tag gets converted to entities. - * - * So this: - * 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); - - /* - * Sanitize naughty scripting elements - * - * Similar to above, only instead of looking for - * tags it looks for PHP and JavaScript commands - * that are disallowed. Rather than removing the - * code, it simply converts the parenthesis to entities - * rendering the code un-executable. - * - * 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 - $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. - */ - - if ($is_image === TRUE) - { - return ($str == $converted_string) ? TRUE: FALSE; - } - - log_message('debug', "XSS Filtering completed"); - return $str; - } - - // -------------------------------------------------------------------- - - /** - * Random Hash for protecting URLs - * - * @return string - */ - public function 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)); - } - - 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 - * - * @param type - * @return type - */ - 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: - * - * - Everything inside the quotes - * For example, everything between the pipes: - * - * - * @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 - * - * @param array - * @return string - */ - 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]); - - return $str; - } - - // -------------------------------------------------------------------- - - /** - * JS Link Removal - * - * Callback function for xss_clean() to sanitize links - * This limits the PCRE backtracks, making it more performance friendly - * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in - * PHP 5.2+ on link-heavy strings - * - * @param array - * @return string - */ - 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|_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|', '<', '\\'), array('>', '<', '\\\\'), $match[0]); - } - - // -------------------------------------------------------------------- - - /** - * Filter Attributes - * - * Filters tag attributes for consistency and safety - * - * @param string - * @return string - */ - protected function _filter_attributes($str) - { - $out = ''; - - if (preg_match_all('#\s*[a-z\-]+\s*=\s*(\042|\047)([^\\1]*?)\\1#is', $str, $matches)) - { - foreach ($matches[0] as $match) - { - $out .= preg_replace("#/\*.*?\*/#s", '', $match); - } - } - - return $out; - } - - // -------------------------------------------------------------------- - - /** - * HTML Entity Decode Callback - * - * Used as a callback for XSS Clean - * - * @param array - * @return string - */ - protected function _decode_entity($match) - { - return $this->entity_decode($match[0], strtoupper(config_item('charset'))); - } - - // -------------------------------------------------------------------- - - /** - * Validate URL entities - * - * Called by xss_clean() - * - * @param string - * @return string - */ - protected function _validate_entities($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); - - return $str; - } - - // ---------------------------------------------------------------------- - - /** - * 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 = str_replace($key, $val, $str); - } - - foreach ($this->_never_allowed_regex as $key => $val) - { - $str = preg_replace("#".$key."#i", $val, $str); - } - - return $str; - } - - // -------------------------------------------------------------------- - - /** - * Set Cross Site Request Forgery Protection Cookie - * - * @return string - */ - protected function _csrf_set_hash() - { - 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]) && - $_COOKIE[$this->_csrf_cookie_name] != '') - { - return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name]; - } - - return $this->_csrf_hash = md5(uniqid(rand(), TRUE)); - } - - return $this->_csrf_hash; - } - -} -// END Security Class - -/* End of file Security.php */ -/* Location: ./system/libraries/Security.php */ \ No newline at end of file -- cgit v1.2.3-24-g4f1b From 6984aaf27f53b91ab1eafcdccd5fb871dfcd5f18 Mon Sep 17 00:00:00 2001 From: Pascal Kriete Date: Tue, 5 Apr 2011 14:58:04 -0400 Subject: Removing security loading calls. --- system/helpers/typography_helper.php | 5 ++--- system/libraries/Form_validation.php | 5 ----- system/libraries/Upload.php | 6 ------ system/libraries/Xmlrpc.php | 14 ++------------ 4 files changed, 4 insertions(+), 26 deletions(-) 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/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/Upload.php b/system/libraries/Upload.php index 5816a5558..b62e0d73c 100644 --- a/system/libraries/Upload.php +++ b/system/libraries/Upload.php @@ -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); } 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)) -- cgit v1.2.3-24-g4f1b From 73598e3ced570c42128ec5e90d67f509bd24fa5d Mon Sep 17 00:00:00 2001 From: Pascal Kriete Date: Tue, 5 Apr 2011 15:01:05 -0400 Subject: Tightening up control character handling in urls --- system/core/URI.php | 57 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 23 deletions(-) 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; } // -------------------------------------------------------------------- -- cgit v1.2.3-24-g4f1b From 6b488674368cf695a228e87e7d8e0f4f40fe4181 Mon Sep 17 00:00:00 2001 From: Pascal Kriete Date: Tue, 5 Apr 2011 15:02:15 -0400 Subject: Removing dohash and deprecating CI_SHA --- system/helpers/security_helper.php | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) 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 @@ -64,22 +64,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 * @@ -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 { -- cgit v1.2.3-24-g4f1b From f1bd6fa78a3235ade2365a43bb5124ff72807c96 Mon Sep 17 00:00:00 2001 From: Pascal Kriete Date: Tue, 5 Apr 2011 15:04:28 -0400 Subject: Fixed a bug in the Javascript Library where improperly escaped characters could result in arbitrary javascript execution. --- system/libraries/Javascript.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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)) { -- cgit v1.2.3-24-g4f1b From 1a73cb0a2847087645bc5d968743c8a2d8bd52b7 Mon Sep 17 00:00:00 2001 From: Pascal Kriete Date: Tue, 5 Apr 2011 15:17:41 -0400 Subject: Changelogging --- user_guide/changelog.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/user_guide/changelog.html b/user_guide/changelog.html index 013c55766..ffdc27266 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -66,12 +66,19 @@ Hg Tag: n/a

-

These functions return boolean TRUE upon success and FALSE for failure. If they fail you can retrieve the +

These functions return boolean TRUE upon success and FALSE for failure. If they fail you can retrieve the error message using this function:

echo $this->image_lib->display_errors(); @@ -138,7 +138,7 @@ error message using this function:

    echo $this->image_lib->display_errors();
}
-

Note: You can optionally specify the HTML formatting to be applied to the errors, by submitting the opening/closing +

Note: You can optionally specify the HTML formatting to be applied to the errors, by submitting the opening/closing tags in the function, like this:

$this->image_lib->display_errors('<p>', '</p>'); @@ -146,11 +146,11 @@ tags in the function, like this:

Preferences

-

The preferences described below allow you to tailor the image processing to suit your needs.

+

The preferences described below allow you to tailor the image processing to suit your needs.

Note that not all preferences are available for every -function. For example, the x/y axis preferences are only available for image cropping. Likewise, the width and height -preferences have no effect on cropping. The "availability" column indicates which functions support a given preference.

+function. For example, the x/y axis preferences are only available for image cropping. Likewise, the width and height +preferences have no effect on cropping. The "availability" column indicates which functions support a given preference.

Availability Legend:

@@ -187,7 +187,7 @@ preferences have no effect on cropping. The "availability" column indicates whi library_path None None -Sets the server path to your ImageMagick or NetPBM library. If you use either of those libraries you must supply the path. +Sets the server path to your ImageMagick or NetPBM library. If you use either of those libraries you must supply the path. R, C, X @@ -195,7 +195,7 @@ preferences have no effect on cropping. The "availability" column indicates whi source_image None None -Sets the source image name/path. The path must be a relative or absolute server path, not a URL. +Sets the source image name/path. The path must be a relative or absolute server path, not a URL. R, C, S, W @@ -203,7 +203,7 @@ preferences have no effect on cropping. The "availability" column indicates whi dynamic_output FALSE TRUE/FALSE (boolean) -Determines whether the new image file should be written to disk or generated dynamically. Note: If you choose the dynamic setting, only one image can be shown at a time, and it can't be positioned on the page. It simply outputs the raw image dynamically to your browser, along with image headers. +Determines whether the new image file should be written to disk or generated dynamically. Note: If you choose the dynamic setting, only one image can be shown at a time, and it can't be positioned on the page. It simply outputs the raw image dynamically to your browser, along with image headers. R, C, X, W @@ -221,7 +221,7 @@ preferences have no effect on cropping. The "availability" column indicates whi new_image None None -Sets the destination image name/path. You'll use this preference when creating an image copy. The path must be a relative or absolute server path, not a URL. +Sets the destination image name/path. You'll use this preference when creating an image copy. The path must be a relative or absolute server path, not a URL. R, C, X, W @@ -253,7 +253,7 @@ preferences have no effect on cropping. The "availability" column indicates whi thumb_marker _thumb None -Specifies the thumbnail indicator. It will be inserted just before the file extension, so mypic.jpg would become mypic_thumb.jpg +Specifies the thumbnail indicator. It will be inserted just before the file extension, so mypic.jpg would become mypic_thumb.jpg R @@ -281,7 +281,7 @@ preferences have no effect on cropping. The "availability" column indicates whi rotation_angle None 90, 180, 270, vrt, hor -Specifies the angle of rotation when rotating images. Note that PHP rotates counter-clockwise, so a 90 degree rotation to the right must be specified as 270. +Specifies the angle of rotation when rotating images. Note that PHP rotates counter-clockwise, so a 90 degree rotation to the right must be specified as 270. X @@ -306,7 +306,7 @@ preferences have no effect on cropping. The "availability" column indicates whi

Setting preferences in a config file

If you prefer not to set preferences using the above method, you can instead put them into a config file. -Simply create a new file called image_lib.php, add the $config +Simply create a new file called image_lib.php, add the $config array in that file. Then save the file in: config/image_lib.php and it will be used automatically. You will NOT need to use the $this->image_lib->initialize function if you save your preferences in a config file.

@@ -319,7 +319,7 @@ or create a thumbnail image.

For practical purposes there is no difference between creating a copy and creating a thumbnail except a thumb will have the thumbnail marker as part of the name (ie, mypic_thumb.jpg).

-

All preferences listed in the table above are available for this function except these three: rotation_angle, x_axis, and y_axis.

+

All preferences listed in the table above are available for this function except these three: rotation_angle, x_axis, and y_axis.

Creating a Thumbnail

@@ -358,7 +358,7 @@ preferences for the X and Y axis (in pixels) specifying where to crop, like this $config['x_axis'] = '100';
$config['y_axis'] = '40';
-

All preferences listed in the table above are available for this function except these: rotation_angle, width, height, create_thumb, new_image.

+

All preferences listed in the table above are available for this function except these: rotation_angle, width, height, create_thumb, new_image.

Here's an example showing how you might crop an image:

@@ -378,8 +378,8 @@ if ( ! $this->image_lib->crop())

Note: Without a visual interface it is difficult to crop images, so this function is not very useful -unless you intend to build such an interface. That's exactly what we did using for the photo -gallery module in ExpressionEngine, the CMS we develop. We added a JavaScript UI that lets the cropping +unless you intend to build such an interface. That's exactly what we did using for the photo +gallery module in ExpressionEngine, the CMS we develop. We added a JavaScript UI that lets the cropping area be selected.

$this->image_lib->rotate()

@@ -443,7 +443,7 @@ containing your watermark over the source image.

Just as with the other functions (resizing, cropping, and rotating) the general process for watermarking involves setting the preferences corresponding to the action you intend to perform, then -calling the watermark function. Here is an example:

+calling the watermark function. Here is an example:

$config['source_image'] = '/path/to/image/mypic.jpg';
@@ -452,9 +452,9 @@ $config['wm_type'] = 'text';
$config['wm_font_path'] = './system/fonts/texb.ttf';
$config['wm_font_size'] = '16';
$config['wm_font_color'] = 'ffffff';
-$config['wm_vrt_alignment'] = 'bottom';
-$config['wm_hor_alignment'] = 'center';
-$config['wm_padding'] = '20';
+$config['wm_vrt_alignment'] = 'bottom';
+$config['wm_hor_alignment'] = 'center';
+$config['wm_padding'] = '20';

$this->image_lib->initialize($config);
@@ -462,7 +462,7 @@ $this->image_lib->initialize($config); $this->image_lib->watermark();
-

The above example will use a 16 pixel True Type font to create the text "Copyright 2006 - John Doe". The watermark +

The above example will use a 16 pixel True Type font to create the text "Copyright 2006 - John Doe". The watermark will be positioned at the bottom/center of the image, 20 pixels from the bottom of the image.

Note: In order for the image class to be allowed to do any processing, the image file must have "write" file permissions. For example, 777.

@@ -491,14 +491,14 @@ will be positioned at the bottom/center of the image, 20 pixels from the bottom source_image None None -Sets the source image name/path. The path must be a relative or absolute server path, not a URL. +Sets the source image name/path. The path must be a relative or absolute server path, not a URL. dynamic_output FALSE TRUE/FALSE (boolean) -Determines whether the new image file should be written to disk or generated dynamically. Note: If you choose the dynamic setting, only one image can be shown at a time, and it can't be positioned on the page. It simply outputs the raw image dynamically to your browser, along with image headers. +Determines whether the new image file should be written to disk or generated dynamically. Note: If you choose the dynamic setting, only one image can be shown at a time, and it can't be positioned on the page. It simply outputs the raw image dynamically to your browser, along with image headers. @@ -563,28 +563,28 @@ will be positioned at the bottom/center of the image, 20 pixels from the bottom wm_text None None -The text you would like shown as the watermark. Typically this will be a copyright notice. +The text you would like shown as the watermark. Typically this will be a copyright notice. wm_font_path None None -The server path to the True Type Font you would like to use. If you do not use this option, the native GD font will be used. +The server path to the True Type Font you would like to use. If you do not use this option, the native GD font will be used. wm_font_size 16 None -The size of the text. Note: If you are not using the True Type option above, the number is set using a range of 1 - 5. Otherwise, you can use any valid pixel size for the font you're using. +The size of the text. Note: If you are not using the True Type option above, the number is set using a range of 1 - 5. Otherwise, you can use any valid pixel size for the font you're using. wm_font_color ffffff None -The font color, specified in hex. Note, you must use the full 6 character hex value (ie, 993300), rather than the three character abbreviated version (ie fff). +The font color, specified in hex. Note, you must use the full 6 character hex value (ie, 993300), rather than the three character abbreviated version (ie fff). diff --git a/user_guide/libraries/input.html b/user_guide/libraries/input.html index 08b8ab0d3..6070b6c48 100644 --- a/user_guide/libraries/input.html +++ b/user_guide/libraries/input.html @@ -70,20 +70,20 @@ Input Class

Security Filtering

-

The security filtering function is called automatically when a new controller is invoked. It does the following:

+

The security filtering function is called automatically when a new controller is invoked. It does the following:

    -
  • Destroys the global GET array. Since CodeIgniter does not utilize GET strings, there is no reason to allow it.
  • +
  • Destroys the global GET array. Since CodeIgniter does not utilize GET strings, there is no reason to allow it.
  • Destroys all global variables in the event register_globals is turned on.
  • Filters the POST/COOKIE array keys, permitting only alpha-numeric (and a few other) characters.
  • -
  • Provides XSS (Cross-site Scripting Hacks) filtering. This can be enabled globally, or upon request.
  • +
  • Provides XSS (Cross-site Scripting Hacks) filtering. This can be enabled globally, or upon request.
  • Standardizes newline characters to \n

XSS Filtering

-

The Input class has the ability to filter input automatically to prevent cross-site scripting attacks. If you want the filter to run automatically every time it encounters POST or COOKIE data you can enable it by opening your +

The Input class has the ability to filter input automatically to prevent cross-site scripting attacks. If you want the filter to run automatically every time it encounters POST or COOKIE data you can enable it by opening your application/config/config.php file and setting this:

$config['global_xss_filtering'] = TRUE; @@ -93,9 +93,9 @@ Input Class

Using POST, COOKIE, or SERVER Data

-

CodeIgniter comes with three helper functions that let you fetch POST, COOKIE or SERVER items. The main advantage of using the provided +

CodeIgniter comes with three helper functions that let you fetch POST, COOKIE or SERVER items. The main advantage of using the provided functions rather than fetching an item directly ($_POST['something']) is that the functions will check to see if the item is set and -return false (boolean) if not. This lets you conveniently use data without having to test whether an item exists first. +return false (boolean) if not. This lets you conveniently use data without having to test whether an item exists first. In other words, normally you might do something like this:

@@ -128,7 +128,7 @@ else

The function returns FALSE (boolean) if the item you are attempting to retrieve does not exist.

-

The second optional parameter lets you run the data through the XSS filter. It's enabled by setting the second parameter to boolean TRUE;

+

The second optional parameter lets you run the data through the XSS filter. It's enabled by setting the second parameter to boolean TRUE;

$this->input->post('some_data', TRUE); @@ -179,7 +179,7 @@ else

$this->input->set_cookie()

-

Sets a cookie containing the values you specify. There are two ways to pass information to this function so that a cookie can be set: +

Sets a cookie containing the values you specify. There are two ways to pass information to this function so that a cookie can be set: Array Method, and Discrete Parameters:

Array Method

@@ -203,10 +203,10 @@ $this->input->set_cookie($cookie);

Only the name and value are required. To delete a cookie set it with the expiration blank.

-

The expiration is set in seconds, which will be added to the current time. Do not include the time, but rather only the -number of seconds from now that you wish the cookie to be valid. If the expiration is set to +

The expiration is set in seconds, which will be added to the current time. Do not include the time, but rather only the +number of seconds from now that you wish the cookie to be valid. If the expiration is set to zero the cookie will only last as long as the browser is open.

-

For site-wide cookies regardless of how your site is requested, add your URL to the domain starting with a period, like this: .your-domain.com

+

For site-wide cookies regardless of how your site is requested, add your URL to the domain starting with a period, like this: .your-domain.com

The path is usually not needed since the function sets a root path.

The prefix is only needed if you need to avoid name collisions with other identically named cookies for your server.

The secure boolean is only needed if you want to make it a secure cookie by setting it to TRUE.

@@ -219,25 +219,25 @@ zero the cookie will only last as long as the browser is open.

$this->input->cookie()

-

Lets you fetch a cookie. The first parameter will contain the name of the cookie you are looking for (including any prefixes):

+

Lets you fetch a cookie. The first parameter will contain the name of the cookie you are looking for (including any prefixes):

cookie('some_cookie');

The function returns FALSE (boolean) if the item you are attempting to retrieve does not exist.

-

The second optional parameter lets you run the data through the XSS filter. It's enabled by setting the second parameter to boolean TRUE;

+

The second optional parameter lets you run the data through the XSS filter. It's enabled by setting the second parameter to boolean TRUE;

cookie('some_cookie', TRUE);

$this->input->ip_address()

-

Returns the IP address for the current user. If the IP address is not valid, the function will return an IP of: 0.0.0.0

+

Returns the IP address for the current user. If the IP address is not valid, the function will return an IP of: 0.0.0.0

echo $this->input->ip_address();

$this->input->valid_ip($ip)

-

Takes an IP address as input and returns TRUE or FALSE (boolean) if it is valid or not. Note: The $this->input->ip_address() function above +

Takes an IP address as input and returns TRUE or FALSE (boolean) if it is valid or not. Note: The $this->input->ip_address() function above validates the IP automatically.

if ( ! $this->input->valid_ip($ip))
@@ -256,7 +256,7 @@ else

See the User Agent Class for methods which extract information from the user agent string.

$this->input->request_headers()

-

Useful if running in a non-Apache environment where apache_request_headers() will not be supported. Returns an array of headers.

+

Useful if running in a non-Apache environment where apache_request_headers() will not be supported. Returns an array of headers.

$headers = $this->input->request_headers(); diff --git a/user_guide/libraries/javascript.html b/user_guide/libraries/javascript.html index 4e262279d..cd3adf1d2 100644 --- a/user_guide/libraries/javascript.html +++ b/user_guide/libraries/javascript.html @@ -65,11 +65,11 @@ JavaScript Driver $this->load->library('javascript'); -

The Javascript class also accepts parameters, js_library_driver (string) default 'jquery' and autoload (bool) default TRUE. You may override the defaults if you wish by sending an associative array:

+

The Javascript class also accepts parameters, js_library_driver (string) default 'jquery' and autoload (bool) default TRUE. You may override the defaults if you wish by sending an associative array:

$this->load->library('javascript', array('js_library_driver' => 'scripto', 'autoload' => FALSE)); -

Again, presently only 'jquery' is available. You may wish to set autoload to FALSE, though, if you do not want the jQuery library to automatically include a script tag for the main jQuery script file. This is useful if you are loading it from a location outside of CodeIgniter, or already have the script tag in your markup.

+

Again, presently only 'jquery' is available. You may wish to set autoload to FALSE, though, if you do not want the jQuery library to automatically include a script tag for the main jQuery script file. This is useful if you are loading it from a location outside of CodeIgniter, or already have the script tag in your markup.

Once loaded, the jQuery library object will be available using: $this->javascript

Setup and Configuration

@@ -93,7 +93,7 @@ JavaScript Driver $this->load->library('jquery'); -

You may send an optional parameter to determine whether or not a script tag for the main jQuery file will be automatically included when loading the library. It will be created by default. To prevent this, load the library as follows:

+

You may send an optional parameter to determine whether or not a script tag for the main jQuery file will be automatically included when loading the library. It will be created by default. To prevent this, load the library as follows:

$this->load->library('jquery', FALSE); @@ -115,7 +115,7 @@ JavaScript Driver

Effects

-

The query library supports a powerful Effects repertoire. Before an effect can be used, it must be loaded:

+

The query library supports a powerful Effects repertoire. Before an effect can be used, it must be loaded:

$this->jquery->effect([optional path] plugin name); // for example @@ -125,8 +125,8 @@ $this->jquery->effect('bounce');

hide() / show()

Each of this functions will affect the visibility of an item on your page. hide() will set an item invisible, show() will reveal it.

-

$this->jquery->hide(target, optional speed, optional extra information);
- $this->jquery->show(target, optional speed, optional extra information);

+

$this->jquery->hide(target, optional speed, optional extra information);
+ $this->jquery->show(target, optional speed, optional extra information);

  • "target" will be any valid jQuery selector or selectors.
  • @@ -162,8 +162,8 @@ $this->jquery->click('#trigger', $this->jquery->animate('#note', $pa

    fadeIn() / fadeOut()

    -

    $this->jquery->fadeIn(target, optional speed, optional extra information);
    - $this->jquery->fadeOut(target, optional speed, optional extra information);

    +

    $this->jquery->fadeIn(target, optional speed, optional extra information);
    + $this->jquery->fadeOut(target, optional speed, optional extra information);

    • "target" will be any valid jQuery selector or selectors.
    • "speed" is optional, and is set to either slow, normal, fast, or alternatively a number of milliseconds.
    • @@ -182,8 +182,8 @@ $this->jquery->click('#trigger', $this->jquery->animate('#note', $pa

      fadeIn() / fadeOut()

      These effects cause an element(s) to disappear or reappear over time.

      -

      $this->jquery->fadeIn(target, optional speed, optional extra information);
      - $this->jquery->fadeOut(target, optional speed, optional extra information);

      +

      $this->jquery->fadeIn(target, optional speed, optional extra information);
      + $this->jquery->fadeOut(target, optional speed, optional extra information);

      • "target" will be any valid jQuery selector or selectors.
      • "speed" is optional, and is set to either slow, normal, fast, or alternatively a number of milliseconds.
      • @@ -193,9 +193,9 @@ $this->jquery->click('#trigger', $this->jquery->animate('#note', $pa

        slideUp() / slideDown() / slideToggle()

        These effects cause an element(s) to slide.

        -

        $this->jquery->slideUp(target, optional speed, optional extra information);
        - $this->jquery->slideDown(target, optional speed, optional extra information);
        -$this->jquery->slideToggle(target, optional speed, optional extra information);

        +

        $this->jquery->slideUp(target, optional speed, optional extra information);
        + $this->jquery->slideDown(target, optional speed, optional extra information);
        +$this->jquery->slideToggle(target, optional speed, optional extra information);

        • "target" will be any valid jQuery selector or selectors.
        • "speed" is optional, and is set to either slow, normal, fast, or alternatively a number of milliseconds.
        • diff --git a/user_guide/libraries/language.html b/user_guide/libraries/language.html index 75863c2ac..1b253fa00 100644 --- a/user_guide/libraries/language.html +++ b/user_guide/libraries/language.html @@ -60,30 +60,30 @@ Language Class

          The Language Class provides functions to retrieve language files and lines of text for purposes of internationalization.

          -

          In your CodeIgniter system folder you'll find one called language containing sets of language files. You can create +

          In your CodeIgniter system folder you'll find one called language containing sets of language files. You can create your own language files as needed in order to display error and other messages in other languages.

          -

          Language files are typically stored in your system/language directory. Alternately you can create a folder called language inside -your application folder and store them there. CodeIgniter will look first in your application/language -directory. If the directory does not exist or the specified language is not located there CI will instead look in your global +

          Language files are typically stored in your system/language directory. Alternately you can create a folder called language inside +your application folder and store them there. CodeIgniter will look first in your application/language +directory. If the directory does not exist or the specified language is not located there CI will instead look in your global system/language folder.

          -

          Note:  Each language should be stored in its own folder. For example, the English files are located at: +

          Note:  Each language should be stored in its own folder. For example, the English files are located at: system/language/english

          Creating Language Files

          -

          Language files must be named with _lang.php as the file extension. For example, let's say you want to create a file -containing error messages. You might name it: error_lang.php

          +

          Language files must be named with _lang.php as the file extension. For example, let's say you want to create a file +containing error messages. You might name it: error_lang.php

          Within the file you will assign each line of text to an array called $lang with this prototype:

          $lang['language_key'] = "The actual message to be shown";

          Note: It's a good practice to use a common prefix for all messages in a given file to avoid collisions with -similarly named items in other files. For example, if you are creating error messages you might prefix them with error_

          +similarly named items in other files. For example, if you are creating error messages you might prefix them with error_

          $lang['error_email_missing'] = "You must submit an email address";
          $lang['error_url_missing'] = "You must submit a URL";
          @@ -92,12 +92,12 @@ $lang['error_username_missing'] = "You must submit a username";
          Loading A Language File -

          In order to fetch a line from a particular file you must load the file first. Loading a language file is done with the following code:

          +

          In order to fetch a line from a particular file you must load the file first. Loading a language file is done with the following code:

          $this->lang->load('filename', 'language');

          Where filename is the name of the file you wish to load (without the file extension), and language -is the language set containing it (ie, english). If the second parameter is missing, the default language set in your +is the language set containing it (ie, english). If the second parameter is missing, the default language set in your application/config/config.php file will be used.

          @@ -109,7 +109,7 @@ is the language set containing it (ie, english). If the second parameter is mis

          Where language_key is the array key corresponding to the line you wish to show.

          -

          Note: This function simply returns the line. It does not echo it for you.

          +

          Note: This function simply returns the line. It does not echo it for you.

          Using language lines as form labels

          diff --git a/user_guide/libraries/loader.html b/user_guide/libraries/loader.html index 1d93af5ed..50ec60c1f 100644 --- a/user_guide/libraries/loader.html +++ b/user_guide/libraries/loader.html @@ -58,7 +58,7 @@ Loader Class

          Loader Class

          -

          Loader, as the name suggests, is used to load elements. These elements can be libraries (classes) View files, +

          Loader, as the name suggests, is used to load elements. These elements can be libraries (classes) View files, Helpers, Models, or your own files.

          Note: This class is initialized automatically by the system so there is no need to do it manually.

          @@ -69,7 +69,7 @@ Loader Class

          $this->load->library('class_name', $config, 'object name')

          -

          This function is used to load core classes. Where class_name is the name of the class you want to load. +

          This function is used to load core classes. Where class_name is the name of the class you want to load. Note: We use the terms "class" and "library" interchangeably.

          For example, if you would like to send email with CodeIgniter, the first step is to load the email class within your controller:

          @@ -96,7 +96,7 @@ For example, if you have file located at:

          Setting options

          -

          The second (optional) parameter allows you to optionally pass configuration setting. You will typically pass these as an array:

          +

          The second (optional) parameter allows you to optionally pass configuration setting. You will typically pass these as an array:

          $config = array (
          @@ -113,7 +113,7 @@ $this->load->library('email', $config);

          Assigning a Library to a different object name

          -

          If the third (optional) parameter is blank, the library will usually be assigned to an object with the same name as the library. For example, if the library is named Session, it +

          If the third (optional) parameter is blank, the library will usually be assigned to an object with the same name as the library. For example, if the library is named Session, it will be assigned to a variable named $this->session.

          If you prefer to set your own class names you can pass its value to the third parameter:

          @@ -131,20 +131,20 @@ $this->my_session

          $this->load->view('file_name', $data, true/false)

          -

          This function is used to load your View files. If you haven't read the Views section of the +

          This function is used to load your View files. If you haven't read the Views section of the user guide it is recommended that you do since it shows you how this function is typically used.

          -

          The first parameter is required. It is the name of the view file you would like to load.  Note: The .php file extension does not need to be specified unless you use something other than .php.

          +

          The first parameter is required. It is the name of the view file you would like to load.  Note: The .php file extension does not need to be specified unless you use something other than .php.

          The second optional parameter can take an associative array or an object as input, which it runs through the PHP extract function to -convert to variables that can be used in your view files. Again, read the Views page to learn +convert to variables that can be used in your view files. Again, read the Views page to learn how this might be useful.

          The third optional parameter lets you change the behavior of the function so that it returns data as a string -rather than sending it to your browser. This can be useful if you want to process the data in some way. If you -set the parameter to true (boolean) it will return data. The default behavior is false, which sends it -to your browser. Remember to assign it to a variable if you want the data returned:

          +rather than sending it to your browser. This can be useful if you want to process the data in some way. If you +set the parameter to true (boolean) it will return data. The default behavior is false, which sends it +to your browser. Remember to assign it to a variable if you want the data returned:

          $string = $this->load->view('myfile', '', true); @@ -159,7 +159,7 @@ to your browser. Remember to assign it to a variable if you want the data retur
          $this->fubar->function();

          $this->load->database('options', true/false)

          -

          This function lets you load the database class. The two parameters are optional. Please see the +

          This function lets you load the database class. The two parameters are optional. Please see the database section for more info.

          @@ -168,9 +168,9 @@ $this->fubar->function();

          $this->load->vars($array)

          This function takes an associative array as input and generates variables using the PHP extract function. -This function produces the same result as using the second parameter of the $this->load->view() function above. The reason you might +This function produces the same result as using the second parameter of the $this->load->view() function above. The reason you might want to use this function independently is if you would like to set some global variables in the constructor of your controller -and have them become available in any view file loaded from any function. You can have multiple calls to this function. The data get cached +and have them become available in any view file loaded from any function. You can have multiple calls to this function. The data get cached and merged into one array for conversion to variables.

          @@ -180,7 +180,7 @@ and merged into one array for conversion to variables.

          $this->load->file('filepath/filename', true/false)

          -

          This is a generic file loading function. Supply the filepath and name in the first parameter and it will open and read the file. +

          This is a generic file loading function. Supply the filepath and name in the first parameter and it will open and read the file. By default the data is sent to your browser, just like a View file, but if you set the second parameter to true (boolean) it will instead return the data as a string.

          @@ -194,7 +194,7 @@ it will instead return the data as a string.

          Application "Packages"

          -

          An application package allows for the easy distribution of complete sets of resources in a single directory, complete with its own libraries, models, helpers, config, and language files. It is recommended that these packages be placed in the application/third_party folder. Below is a sample map of an package directory

          +

          An application package allows for the easy distribution of complete sets of resources in a single directory, complete with its own libraries, models, helpers, config, and language files. It is recommended that these packages be placed in the application/third_party folder. Below is a sample map of an package directory

          Sample Package "Foo Bar" Directory Map

          @@ -210,18 +210,18 @@ libraries/
          models/
          -

          Whatever the purpose of the "Foo Bar" application package, it has its own config files, helpers, language files, libraries, and models. To use these resources in your controllers, you first need to tell the Loader that you are going to be loading resources from a package, by adding the package path.

          +

          Whatever the purpose of the "Foo Bar" application package, it has its own config files, helpers, language files, libraries, and models. To use these resources in your controllers, you first need to tell the Loader that you are going to be loading resources from a package, by adding the package path.

          $this->load->add_package_path()

          -

          Adding a package path instructs the Loader class to prepend a given path for subsequent requests for resources. As an example, the "Foo Bar" application package above has a library named Foo_bar.php. In our controller, we'd do the following:

          +

          Adding a package path instructs the Loader class to prepend a given path for subsequent requests for resources. As an example, the "Foo Bar" application package above has a library named Foo_bar.php. In our controller, we'd do the following:

          $this->load->add_package_path(APPPATH.'third_party/foo_bar/');
          $this->load->library('foo_bar');

          $this->load->remove_package_path()

          -

          When your controller is finished using resources from an application package, and particularly if you have other application packages you want to work with, you may wish to remove the package path so the Loader no longer looks in that folder for resources. To remove the last path added, simply call the method with no parameters.

          +

          When your controller is finished using resources from an application package, and particularly if you have other application packages you want to work with, you may wish to remove the package path so the Loader no longer looks in that folder for resources. To remove the last path added, simply call the method with no parameters.

          $this->load->remove_package_path()

          @@ -231,8 +231,8 @@ $this->load->library('foo_bar');

          Package view files

          -

          By Default, package view files paths are set when add_package_path() is called. View paths are looped through, and once a match is encountered that view is loaded.

          -

          In this instance, it is possible for view naming collisions within packages to occur, and possibly the incorrect package being loaded. To ensure against this, set an optional second parameter of FALSE when calling add_package_path().

          +

          By Default, package view files paths are set when add_package_path() is called. View paths are looped through, and once a match is encountered that view is loaded.

          +

          In this instance, it is possible for view naming collisions within packages to occur, and possibly the incorrect package being loaded. To ensure against this, set an optional second parameter of FALSE when calling add_package_path().

          $this->load->add_package_path(APPPATH.'my_app', TRUE);
          diff --git a/user_guide/libraries/output.html b/user_guide/libraries/output.html index 4d1f8d97a..8846e15ff 100644 --- a/user_guide/libraries/output.html +++ b/user_guide/libraries/output.html @@ -58,7 +58,7 @@ Output Class

          Output Class

          -

          The Output class is a small class with one main function: To send the finalized web page to the requesting browser. It is +

          The Output class is a small class with one main function: To send the finalized web page to the requesting browser. It is also responsible for caching your web pages, if you use that feature.

          Note: This class is initialized automatically by the system so there is no need to do it manually.

          @@ -70,7 +70,7 @@ It is possible, however, for you to manually intervene with the output if you ne

          $this->output->set_output();

          -

          Permits you to manually set the final output string. Usage example:

          +

          Permits you to manually set the final output string. Usage example:

          $this->output->set_output($data); @@ -95,7 +95,7 @@ $this->output

          $this->output->get_output();

          -

          Permits you to manually retrieve any output that has been sent for storage in the output class. Usage example:

          +

          Permits you to manually retrieve any output that has been sent for storage in the output class. Usage example:

          $string = $this->output->get_output();

          Note that data will only be retrievable from this function if it has been previously sent to the output class by one of the @@ -104,7 +104,7 @@ CodeIgniter functions like $this->load->view().

          $this->output->append_output();

          -

          Appends data onto the output string. Usage example:

          +

          Appends data onto the output string. Usage example:

          $this->output->append_output($data); @@ -112,7 +112,7 @@ CodeIgniter functions like $this->load->view().

          $this->output->set_header();

          -

          Permits you to manually set server headers, which the output class will send for you when outputting the final rendered display. Example:

          +

          Permits you to manually set server headers, which the output class will send for you when outputting the final rendered display. Example:

          $this->output->set_header("HTTP/1.0 200 OK");
          @@ -125,10 +125,10 @@ $this->output->set_header("Pragma: no-cache");

          $this->output->set_status_header(code, 'text');

          -

          Permits you to manually set a server status header. Example:

          +

          Permits you to manually set a server status header. Example:

          $this->output->set_status_header('401');
          -// Sets the header as: Unauthorized
          +// Sets the header as: Unauthorized

          See here for a full list of headers.

          @@ -147,14 +147,14 @@ at the bottom of your pages for debugging and optimization purposes.

          $this->output->set_profiler_sections();

          -

          Permits you to enable/disable specific sections of the Profiler when enabled. Please refer to the Profiler documentation for further information.

          +

          Permits you to enable/disable specific sections of the Profiler when enabled. Please refer to the Profiler documentation for further information.

          $this->output->cache();

          -

          The CodeIgniter output library also controls caching. For more information, please see the caching documentation.

          +

          The CodeIgniter output library also controls caching. For more information, please see the caching documentation.

          Parsing Execution Variables

          -

          CodeIgniter will parse the pseudo-variables {elapsed_time} and {memory_usage} in your output by default. To disable this, set the $parse_exec_vars class property to FALSE in your controller. +

          CodeIgniter will parse the pseudo-variables {elapsed_time} and {memory_usage} in your output by default. To disable this, set the $parse_exec_vars class property to FALSE in your controller. $this->output->parse_exec_vars = FALSE; diff --git a/user_guide/libraries/pagination.html b/user_guide/libraries/pagination.html index 3c366a69f..a6b9287a3 100644 --- a/user_guide/libraries/pagination.html +++ b/user_guide/libraries/pagination.html @@ -72,26 +72,26 @@ Pagination Class $this->load->library('pagination');

          $config['base_url'] = 'http://example.com/index.php/test/page/';
          $config['total_rows'] = 200;
          -$config['per_page'] = 20; +$config['per_page'] = 20;

          $this->pagination->initialize($config);

          -echo $this->pagination->create_links(); +echo $this->pagination->create_links();

          Notes:

          -

          The $config array contains your configuration variables. It is passed to the $this->pagination->initialize function as shown above. Although there are some twenty items you can configure, at -minimum you need the three shown. Here is a description of what those items represent:

          +

          The $config array contains your configuration variables. It is passed to the $this->pagination->initialize function as shown above. Although there are some twenty items you can configure, at +minimum you need the three shown. Here is a description of what those items represent:

            -
          • base_url This is the full URL to the controller class/function containing your pagination. In the example - above, it is pointing to a controller called "Test" and a function called "page". Keep in mind that you can +
          • base_url This is the full URL to the controller class/function containing your pagination. In the example + above, it is pointing to a controller called "Test" and a function called "page". Keep in mind that you can re-route your URI if you need a different structure.
          • total_rows This number represents the total rows in the result set you are creating pagination for. Typically this number will be the total rows that your database query returned.
          • -
          • per_page The number of items you intend to show per page. In the above example, you would be showing 20 items per page.
          • +
          • per_page The number of items you intend to show per page. In the above example, you would be showing 20 items per page.

          The create_links() function returns an empty string when there is no pagination to show.

          @@ -100,7 +100,7 @@ minimum you need the three shown. Here is a description of what those items rep

          Setting preferences in a config file

          If you prefer not to set preferences using the above method, you can instead put them into a config file. -Simply create a new file called pagination.php, add the $config +Simply create a new file called pagination.php, add the $config array in that file. Then save the file in: config/pagination.php and it will be used automatically. You will NOT need to use the $this->pagination->initialize function if you save your preferences in a config file.

          @@ -122,9 +122,9 @@ something different you can specify it.

          $config['page_query_string'] = TRUE

          By default, the pagination library assume you are using URI Segments, and constructs your links something like

          http://example.com/index.php/test/page/20

          -

          If you have $config['enable_query_strings'] set to TRUE your links will automatically be re-written using Query Strings. This option can also be explictly set. Using $config['page_query_string'] set to TRUE, the pagination link will become.

          +

          If you have $config['enable_query_strings'] set to TRUE your links will automatically be re-written using Query Strings. This option can also be explictly set. Using $config['page_query_string'] set to TRUE, the pagination link will become.

          http://example.com/index.php?c=test&m=page&per_page=20

          -

          Note that "per_page" is the default query string passed, however can be configured using $config['query_string_segment'] = 'your_string'

          +

          Note that "per_page" is the default query string passed, however can be configured using $config['query_string_segment'] = 'your_string'

          Adding Enclosing Markup

          If you would like to surround the entire pagination with some markup you can do it with these two prefs:

          diff --git a/user_guide/libraries/parser.html b/user_guide/libraries/parser.html index cb2f100a2..4f04aaf48 100644 --- a/user_guide/libraries/parser.html +++ b/user_guide/libraries/parser.html @@ -83,10 +83,10 @@ variables or variable tag pairs. If you've never used a template engine, pseudo- PHP from your templates (view files).

          Note: CodeIgniter does not require you to use this class -since using pure PHP in your view pages lets them run a little faster. However, some developers prefer to use a template engine if +since using pure PHP in your view pages lets them run a little faster. However, some developers prefer to use a template engine if they work with designers who they feel would find some confusion working with PHP.

          -

          Also Note: The Template Parser Class is not a +

          Also Note: The Template Parser Class is not a full-blown template parsing solution. We've kept it very lean on purpose in order to maintain maximum performance.

          @@ -102,7 +102,7 @@ full-blown template parsing solution. We've kept it very lean on purpose in orde

          $this->parser->parse()

          -

          This method accepts a template name and data array as input, and it generates a parsed version. Example:

          +

          This method accepts a template name and data array as input, and it generates a parsed version. Example:

          $this->load->library('parser');

          @@ -114,11 +114,11 @@ $data = array(
          $this->parser->parse('blog_template', $data);

          The first parameter contains the name of the view file (in this example the file would be called blog_template.php), -and the second parameter contains an associative array of data to be replaced in the template. In the above example, the +and the second parameter contains an associative array of data to be replaced in the template. In the above example, the template would contain two variables: {blog_title} and {blog_heading}

          -

          There is no need to "echo" or do something with the data returned by $this->parser->parse(). It is automatically -passed to the output class to be sent to the browser. However, if you do want the data returned instead of sent to the output class you can +

          There is no need to "echo" or do something with the data returned by $this->parser->parse(). It is automatically +passed to the output class to be sent to the browser. However, if you do want the data returned instead of sent to the output class you can pass TRUE (boolean) to the third parameter:

          $string = $this->parser->parse('blog_template', $data, TRUE); @@ -130,8 +130,8 @@ pass TRUE (boolean) to the third parameter:

          Variable Pairs

          -

          The above example code allows simple variables to be replaced. What if you would like an entire block of variables to be -repeated, with each iteration containing new values? Consider the template example we showed at the top of the page:

          +

          The above example code allows simple variables to be replaced. What if you would like an entire block of variables to be +repeated, with each iteration containing new values? Consider the template example we showed at the top of the page:

          <html>
          <head>
          diff --git a/user_guide/libraries/security.html b/user_guide/libraries/security.html index 735187459..0cb1d0cb1 100644 --- a/user_guide/libraries/security.html +++ b/user_guide/libraries/security.html @@ -63,11 +63,11 @@ Security Class

          XSS Filtering

          CodeIgniter comes with a Cross Site Scripting Hack prevention filter which can either run automatically to filter -all POST and COOKIE data that is encountered, or you can run it on a per item basis. By default it does not +all POST and COOKIE data that is encountered, or you can run it on a per item basis. By default it does not run globally since it requires a bit of processing overhead, and since you may not need it in all cases.

          The XSS filter looks for commonly used techniques to trigger Javascript or other types of code that attempt to hijack cookies -or do other malicious things. If anything disallowed is encountered it is rendered safe by converting the data to character entities.

          +or do other malicious things. If anything disallowed is encountered it is rendered safe by converting the data to character entities.

          Note: This function should only be used to deal with data upon submission. It's not something that should be used for general runtime processing since it requires a fair amount of processing overhead.

          @@ -88,7 +88,7 @@ Note: This function should only be used to deal with data upon submission. It's

          Note: If you use the form validation class, it gives you the option of XSS filtering as well.

          -

          An optional second parameter, is_image, allows this function to be used to test images for potential XSS attacks, useful for file upload security. When this second parameter is set to TRUE, instead of returning an altered string, the function returns TRUE if the image is safe, and FALSE if it contained potentially malicious information that a browser may attempt to execute.

          +

          An optional second parameter, is_image, allows this function to be used to test images for potential XSS attacks, useful for file upload security. When this second parameter is set to TRUE, instead of returning an altered string, the function returns TRUE if the image is safe, and FALSE if it contained potentially malicious information that a browser may attempt to execute.

          if ($this->security->xss_clean($file, TRUE) === FALSE)
          {
          @@ -98,7 +98,7 @@ Note: This function should only be used to deal with data upon submission. It's

          $this->security->sanitize_filename()

          -

          When accepting filenames from user input, it is best to sanitize them to prevent directory traversal and other security related issues. To do so, use the sanitize_filename() method of the Security class. Here is an example:

          +

          When accepting filenames from user input, it is best to sanitize them to prevent directory traversal and other security related issues. To do so, use the sanitize_filename() method of the Security class. Here is an example:

          $filename = $this->security->sanitize_filename($this->input->post('filename')); diff --git a/user_guide/libraries/sessions.html b/user_guide/libraries/sessions.html index a6f3c601c..bb8f1fc9b 100644 --- a/user_guide/libraries/sessions.html +++ b/user_guide/libraries/sessions.html @@ -61,7 +61,7 @@ Session Class

          The Session class permits you maintain a user's "state" and track their activity while they browse your site. The Session class stores session information for each user as serialized (and optionally encrypted) data in a cookie. It can also store the session data in a database table for added security, as this permits the session ID in the -user's cookie to be matched against the stored session ID. By default only the cookie is saved. If you choose to +user's cookie to be matched against the stored session ID. By default only the cookie is saved. If you choose to use the database option you'll need to create the session table as indicated below.

          @@ -93,8 +93,8 @@ will cause it to read, create, and update sessions.

          If sessions data does not exist (or if it has expired) a new session will be created and saved in the cookie. If a session does exist, its information will be updated and the cookie will be updated. With each update, the session_id will be regenerated.

          -

          It's important for you to understand that once initialized, the Session class runs automatically. There is nothing -you need to do to cause the above behavior to happen. You can, as you'll see below, work with session data or +

          It's important for you to understand that once initialized, the Session class runs automatically. There is nothing +you need to do to cause the above behavior to happen. You can, as you'll see below, work with session data or even add your own data to a user's session, but the process of reading, writing, and updating a session is automatic.

          @@ -106,7 +106,7 @@ even add your own data to a user's session, but the process of reading, writing,
        • The user's unique Session ID (this is a statistically random string with very strong entropy, hashed with MD5 for portability, and regenerated (by default) every five minutes)
        • The user's IP Address
        • The user's User Agent data (the first 50 characters of the browser data string)
        • -
        • The "last activity" time stamp.
        • +
        • The "last activity" time stamp.

        The above data is stored in a cookie as a serialized array with this prototype:

        @@ -124,7 +124,7 @@ making the data highly secure and impervious to being read or altered by someone can be found here, although the Session class will take care of initializing and encrypting the data automatically.

        -

        Note: Session cookies are only updated every five minutes by default to reduce processor load. If you repeatedly reload a page +

        Note: Session cookies are only updated every five minutes by default to reduce processor load. If you repeatedly reload a page you'll notice that the "last activity" time only updates if five minutes or more has passed since the last time the cookie was written. This time is configurable by changing the $config['sess_time_to_update'] line in your system/config/config.php file.

        @@ -134,7 +134,7 @@ the cookie was written. This time is configurable by changing the $config['sess_ $this->session->userdata('item'); -

        Where item is the array index corresponding to the item you wish to fetch. For example, to fetch the session ID you +

        Where item is the array index corresponding to the item you wish to fetch. For example, to fetch the session ID you will do this:

        $session_id = $this->session->userdata('session_id'); @@ -145,7 +145,7 @@ will do this:

        Adding Custom Session Data

        A useful aspect of the session array is that you can add your own data to it and it will be stored in the user's cookie. -Why would you want to do this? Here's one example:

        +Why would you want to do this? Here's one example:

        Let's say a particular user logs into your site. Once authenticated, you could add their username and email address to the session cookie, making that data globally available to you without @@ -155,7 +155,7 @@ having to run a database query when you need it.

        $this->session->set_userdata($array); -

        Where $array is an associative array containing your new data. Here's an example:

        +

        Where $array is an associative array containing your new data. Here's an example:

        $newdata = array(
        @@ -167,7 +167,7 @@ having to run a database query when you need it.

        $this->session->set_userdata($newdata);

        If you want to add userdata one value at a time, set_userdata() also supports this syntax.

        $this->session->set_userdata('some_name', 'some_value');

        -

        Note: Cookies can only hold 4KB of data, so be careful not to exceed the capacity. The +

        Note: Cookies can only hold 4KB of data, so be careful not to exceed the capacity. The encryption process in particular produces a longer data string than the original so keep careful track of how much data you are storing.

        Retrieving All Session Data

        @@ -179,10 +179,10 @@ encryption process in particular produces a longer data string than the original
         Array
         (
        -    [session_id] => 4a5a5dca22728fb0a84364eeb405b601
        -    [ip_address] => 127.0.0.1
        -    [user_agent] => Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7;
        -    [last_activity] => 1303142623
        +  [session_id] => 4a5a5dca22728fb0a84364eeb405b601
        +  [ip_address] => 127.0.0.1
        +  [user_agent] => Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7;
        +  [last_activity] => 1303142623
         )
         
        @@ -206,20 +206,20 @@ $this->session->unset_userdata($array_items);

        $this->session->keep_flashdata('item');

        Saving Session Data to a Database

        While the session data array stored in the user's cookie contains a Session ID, -unless you store session data in a database there is no way to validate it. For some applications that require little or no -security, session ID validation may not be needed, but if your application requires security, validation is mandatory. Otherwise, an old session +unless you store session data in a database there is no way to validate it. For some applications that require little or no +security, session ID validation may not be needed, but if your application requires security, validation is mandatory. Otherwise, an old session could be restored by a user modifying their cookies.

        When session data is available in a database, every time a valid session is found in the user's cookie, a database -query is performed to match it. If the session ID does not match, the session is destroyed. Session IDs can never +query is performed to match it. If the session ID does not match, the session is destroyed. Session IDs can never be updated, they can only be generated when a new session is created.

        -

        In order to store sessions, you must first create a database table for this purpose. Here is the basic +

        In order to store sessions, you must first create a database table for this purpose. Here is the basic prototype (for MySQL) required by the session class:

        -

        Note: In the above code we are using a "url helper". You can find more information in the Helpers Functions page.

        +

        Note: In the above code we are using a "url helper". You can find more information in the Helpers Functions page.

        The Server

        @@ -381,7 +381,7 @@ class Xmlrpc_server extends CI_Controller { $response = array( array( - 'you_said' => $parameters['0'], + 'you_said' => $parameters['0'], 'i_respond' => 'Not bad at all.'), 'struct'); @@ -452,7 +452,7 @@ The Server receives the request and maps it to the "process" function, where a r $this->xmlrpc->request($request);

        $this->xmlrpc->send_request()

        -

        The request sending function. Returns boolean TRUE or FALSE based on success for failure, enabling it to be used conditionally.

        +

        The request sending function. Returns boolean TRUE or FALSE based on success for failure, enabling it to be used conditionally.

        $this->xmlrpc->set_debug(TRUE);

        Enables debugging, which will display a variety of information and error data helpful during development.

        @@ -463,7 +463,7 @@ $this->xmlrpc->request($request); echo $this->xmlrpc->display_error();

        $this->xmlrpc->display_response()

        -

        Returns the response from the remote server once request is received. The response will typically be an associative array.

        +

        Returns the response from the remote server once request is received. The response will typically be an associative array.

        $this->xmlrpc->display_response();

        $this->xmlrpc->send_error_message()

        diff --git a/user_guide/libraries/zip.html b/user_guide/libraries/zip.html index 031126603..2fc5fd81b 100644 --- a/user_guide/libraries/zip.html +++ b/user_guide/libraries/zip.html @@ -81,7 +81,7 @@ $this->zip->add_data($name, $data);
        // Write the zip file to a folder on your server. Name it "my_backup.zip"
        $this->zip->archive('/path/to/directory/my_backup.zip');

        - // Download the file to your desktop. Name it "my_backup.zip"
        + // Download the file to your desktop. Name it "my_backup.zip"
        $this->zip->download('my_backup.zip'); @@ -100,7 +100,7 @@ $this->zip->add_data($name, $data);

        You are allowed multiple calls to this function in order to -add several files to your archive. Example:

        +add several files to your archive. Example:

        $name = 'mydata1.txt';
        @@ -139,8 +139,8 @@ $this->zip->add_data($name, $data);

        $this->zip->add_dir()

        -

        Permits you to add a directory. Usually this function is unnecessary since you can place your data into folders when -using $this->zip->add_data(), but if you would like to create an empty folder you can do so. Example:

        +

        Permits you to add a directory. Usually this function is unnecessary since you can place your data into folders when +using $this->zip->add_data(), but if you would like to create an empty folder you can do so. Example:

        $this->zip->add_dir('myfolder'); // Creates a folder called "myfolder" @@ -148,49 +148,49 @@ using $this->zip->add_data(), but if you would like to create an empt

        $this->zip->read_file()

        -

        Permits you to compress a file that already exists somewhere on your server. Supply a file path and the zip class will +

        Permits you to compress a file that already exists somewhere on your server. Supply a file path and the zip class will read it and add it to the archive:

        $path = '/path/to/photo.jpg';

        $this->zip->read_file($path);

        - // Download the file to your desktop. Name it "my_backup.zip"
        + // Download the file to your desktop. Name it "my_backup.zip"
        $this->zip->download('my_backup.zip');

        If you would like the Zip archive to maintain the directory structure of the file in it, pass TRUE (boolean) in the -second parameter. Example:

        +second parameter. Example:

        $path = '/path/to/photo.jpg';

        $this->zip->read_file($path, TRUE);

        - // Download the file to your desktop. Name it "my_backup.zip"
        + // Download the file to your desktop. Name it "my_backup.zip"
        $this->zip->download('my_backup.zip');
        -

        In the above example, photo.jpg will be placed inside two folders: path/to/

        +

        In the above example, photo.jpg will be placed inside two folders: path/to/

        $this->zip->read_dir()

        -

        Permits you to compress a folder (and its contents) that already exists somewhere on your server. Supply a file path to the -directory and the zip class will recursively read it and recreate it as a Zip archive. All files contained within the -supplied path will be encoded, as will any sub-folders contained within it. Example:

        +

        Permits you to compress a folder (and its contents) that already exists somewhere on your server. Supply a file path to the +directory and the zip class will recursively read it and recreate it as a Zip archive. All files contained within the +supplied path will be encoded, as will any sub-folders contained within it. Example:

        $path = '/path/to/your/directory/';

        $this->zip->read_dir($path);

        - // Download the file to your desktop. Name it "my_backup.zip"
        + // Download the file to your desktop. Name it "my_backup.zip"
        $this->zip->download('my_backup.zip');

        By default the Zip archive will place all directories listed in the first parameter inside the zip. If you want the tree preceding the target folder to be ignored -you can pass FALSE (boolean) in the second parameter. Example:

        +you can pass FALSE (boolean) in the second parameter. Example:

        $path = '/path/to/your/directory/';

        @@ -204,7 +204,7 @@ $this->zip->read_dir($path, FALSE);

        $this->zip->archive()

        -

        Writes the Zip-encoded file to a directory on your server. Submit a valid server path ending in the file name. Make sure the +

        Writes the Zip-encoded file to a directory on your server. Submit a valid server path ending in the file name. Make sure the directory is writable (666 or 777 is usually OK). Example:

        $this->zip->archive('/path/to/folder/myarchive.zip'); // Creates a file named myarchive.zip @@ -223,7 +223,7 @@ that cause the download to happen and the file to be treated as binary.

        $this->zip->get_zip()

        -

        Returns the Zip-compressed file data. Generally you will not need this function unless you want to do something unique with the data. +

        Returns the Zip-compressed file data. Generally you will not need this function unless you want to do something unique with the data. Example:

        diff --git a/user_guide/license.html b/user_guide/license.html index 8f53851a7..ecc5b500d 100644 --- a/user_guide/license.html +++ b/user_guide/license.html @@ -63,7 +63,7 @@ License Agreement

        Copyright (c) 2008 - 2011, EllisLab, Inc.
        All rights reserved.

        -

        This license is a legal agreement between you and EllisLab Inc. for the use of CodeIgniter Software (the "Software"). By obtaining the Software you agree to comply with the terms and conditions of this license.

        +

        This license is a legal agreement between you and EllisLab Inc. for the use of CodeIgniter Software (the "Software"). By obtaining the Software you agree to comply with the terms and conditions of this license.

        Permitted Use

        You are permitted to use, copy, modify, and distribute the Software and its documentation, with or without modification, for any purpose, provided that the following conditions are met:

        diff --git a/user_guide/nav/hacks.txt b/user_guide/nav/hacks.txt index 8c17f008a..183481b78 100644 --- a/user_guide/nav/hacks.txt +++ b/user_guide/nav/hacks.txt @@ -1,6 +1,6 @@ I did the following hack in moo.fx.js: -At line 79 in the toggle: function() function, I added: +At line 79 in the toggle: function() function, I added: document.getElementById('nav').style.display = 'block'; diff --git a/user_guide/nav/moo.fx.js b/user_guide/nav/moo.fx.js index 256371d19..b21ee20e0 100755 --- a/user_guide/nav/moo.fx.js +++ b/user_guide/nav/moo.fx.js @@ -25,8 +25,8 @@ fx.Base.prototype = { }, step: function() { - var time = (new Date).getTime(); - var Tpos = (time - this.startTime) / (this.duration); + var time = (new Date).getTime(); + var Tpos = (time - this.startTime) / (this.duration); if (time >= this.duration+this.startTime) { this.now = this.to; clearInterval (this.timer); diff --git a/user_guide/nav/prototype.lite.js b/user_guide/nav/prototype.lite.js index e6c362279..857faae4d 100755 --- a/user_guide/nav/prototype.lite.js +++ b/user_guide/nav/prototype.lite.js @@ -1,9 +1,9 @@ -/* Prototype JavaScript framework - * (c) 2005 Sam Stephenson +/* Prototype JavaScript framework + * (c) 2005 Sam Stephenson * - * Prototype is freely distributable under the terms of an MIT-style license. + * Prototype is freely distributable under the terms of an MIT-style license. * - * For details, see the Prototype web site: http://prototype.conio.net/ + * For details, see the Prototype web site: http://prototype.conio.net/ * /*--------------------------------------------------------------------------*/ @@ -11,117 +11,117 @@ //note: this is a stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net). var Class = { - create: function() { + create: function() { return function() { - this.initialize.apply(this, arguments); + this.initialize.apply(this, arguments); } - } + } } Object.extend = function(destination, source) { - for (property in source) { + for (property in source) { destination[property] = source[property]; - } - return destination; + } + return destination; } Function.prototype.bind = function(object) { - var __method = this; - return function() { + var __method = this; + return function() { return __method.apply(object, arguments); - } + } } function $() { - var elements = new Array(); + var elements = new Array(); - for (var i = 0; i < arguments.length; i++) { + for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') - element = document.getElementById(element); + element = document.getElementById(element); if (arguments.length == 1) - return element; + return element; elements.push(element); - } + } - return elements; + return elements; } //------------------------- document.getElementsByClassName = function(className) { - var children = document.getElementsByTagName('*') || document.all; - var elements = new Array(); + var children = document.getElementsByTagName('*') || document.all; + var elements = new Array(); - for (var i = 0; i < children.length; i++) { + for (var i = 0; i < children.length; i++) { var child = children[i]; var classNames = child.className.split(' '); for (var j = 0; j < classNames.length; j++) { - if (classNames[j] == className) { + if (classNames[j] == className) { elements.push(child); break; - } + } } - } + } - return elements; + return elements; } //------------------------- if (!window.Element) { - var Element = new Object(); + var Element = new Object(); } Object.extend(Element, { - remove: function(element) { + remove: function(element) { element = $(element); element.parentNode.removeChild(element); - }, + }, - hasClassName: function(element, className) { + hasClassName: function(element, className) { element = $(element); if (!element) - return; + return; var a = element.className.split(' '); for (var i = 0; i < a.length; i++) { - if (a[i] == className) + if (a[i] == className) return true; } return false; - }, + }, - addClassName: function(element, className) { + addClassName: function(element, className) { element = $(element); Element.removeClassName(element, className); element.className += ' ' + className; - }, + }, - removeClassName: function(element, className) { + removeClassName: function(element, className) { element = $(element); if (!element) - return; + return; var newClassName = ''; var a = element.className.split(' '); for (var i = 0; i < a.length; i++) { - if (a[i] != className) { + if (a[i] != className) { if (i > 0) - newClassName += ' '; + newClassName += ' '; newClassName += a[i]; - } + } } element.className = newClassName; - }, + }, - // removes whitespace-only text node children - cleanWhitespace: function(element) { + // removes whitespace-only text node children + cleanWhitespace: function(element) { element = $(element); for (var i = 0; i < element.childNodes.length; i++) { - var node = element.childNodes[i]; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + var node = element.childNodes[i]; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node); } - } + } }); \ No newline at end of file diff --git a/user_guide/overview/appflow.html b/user_guide/overview/appflow.html index bcbc43ff8..3b1c42e4c 100644 --- a/user_guide/overview/appflow.html +++ b/user_guide/overview/appflow.html @@ -67,7 +67,7 @@ Appflow
      • The index.php serves as the front controller, initializing the base resources needed to run CodeIgniter.
      • The Router examines the HTTP request to determine what should be done with it.
      • If a cache file exists, it is sent directly to the browser, bypassing the normal system execution.
      • -
      • Security. Before the application controller is loaded, the HTTP request and any user submitted data is filtered for security.
      • +
      • Security. Before the application controller is loaded, the HTTP request and any user submitted data is filtered for security.
      • The Controller loads the model, core libraries, helpers, and any other resources needed to process the specific request.
      • The finalized View is rendered then sent to the web browser to be seen. If caching is enabled, the view is cached first so that on subsequent requests it can be served.
      • diff --git a/user_guide/overview/at_a_glance.html b/user_guide/overview/at_a_glance.html index b6b81d760..1175e7f42 100644 --- a/user_guide/overview/at_a_glance.html +++ b/user_guide/overview/at_a_glance.html @@ -60,7 +60,7 @@ What is CodeIgniter?

        CodeIgniter is an Application Framework

        -

        CodeIgniter is a toolkit for people who build web applications using PHP. Its goal is to enable you to develop projects much faster than you could if you were writing code +

        CodeIgniter is a toolkit for people who build web applications using PHP. Its goal is to enable you to develop projects much faster than you could if you were writing code from scratch, by providing a rich set of libraries for commonly needed tasks, as well as a simple interface and logical structure to access these libraries. CodeIgniter lets you creatively focus on your project by minimizing the amount of code needed for a given task.

        @@ -70,7 +70,7 @@ minimizing the amount of code needed for a given task.

        For more information please read the license agreement.

        CodeIgniter is Light Weight

        -

        Truly light weight. The core system requires only a few very small libraries. This is in stark contrast to many frameworks that require significantly more resources. +

        Truly light weight. The core system requires only a few very small libraries. This is in stark contrast to many frameworks that require significantly more resources. Additional libraries are loaded dynamically upon request, based on your needs for a given process, so the base system is very lean and quite fast.

        @@ -84,7 +84,7 @@ is very lean and quite fast. This is particularly good for projects in which designers are working with your template files, as the code these file contain will be minimized. We describe MVC in more detail on its own page.

        CodeIgniter Generates Clean URLs

        -

        The URLs generated by CodeIgniter are clean and search-engine friendly. Rather than using the standard "query string" +

        The URLs generated by CodeIgniter are clean and search-engine friendly. Rather than using the standard "query string" approach to URLs that is synonymous with dynamic systems, CodeIgniter uses a segment-based approach:

        example.com/news/article/345 @@ -92,7 +92,7 @@ approach to URLs that is synonymous with dynamic systems, CodeIgniter uses a seg

        Note: By default the index.php file is included in the URL but it can be removed using a simple .htaccess file.

        CodeIgniter Packs a Punch

        -

        CodeIgniter comes with full-range of libraries that enable the most commonly needed web development tasks, +

        CodeIgniter comes with full-range of libraries that enable the most commonly needed web development tasks, like accessing a database, sending email, validating form data, maintaining sessions, manipulating images, working with XML-RPC data and much more.

        @@ -104,7 +104,7 @@ much more.

        Although CodeIgniter does come with a simple template parser that can be optionally used, it does not force you to use one. Template engines simply can not match the performance of native PHP, and the syntax that must be learned to use a template -engine is usually only marginally easier than learning the basics of PHP. Consider this block of PHP code:

        +engine is usually only marginally easier than learning the basics of PHP. Consider this block of PHP code:

        <ul>

        @@ -133,7 +133,7 @@ back into PHP to run. Since one of our goals is maximum performance, we

        CodeIgniter is Thoroughly Documented

        -

        Programmers love to code and hate to write documentation. We're no different, of course, but +

        Programmers love to code and hate to write documentation. We're no different, of course, but since documentation is as important as the code itself, we are committed to doing it. Our source code is extremely clean and well commented as well.

        diff --git a/user_guide/overview/features.html b/user_guide/overview/features.html index e20219e0f..4209463b1 100644 --- a/user_guide/overview/features.html +++ b/user_guide/overview/features.html @@ -59,10 +59,10 @@ Features

        CodeIgniter Features

        Features in and of themselves are a very poor way to judge an application since they tell you nothing -about the user experience, or how intuitively or intelligently it is designed. Features +about the user experience, or how intuitively or intelligently it is designed. Features don't reveal anything about the quality of the code, or the performance, or the attention to detail, or security practices. The only way to really judge an app is to try it and get to know the code. Installing -CodeIgniter is child's play so we encourage you to do just that. In the mean time here's a list of CodeIgniter's main features.

        +CodeIgniter is child's play so we encourage you to do just that. In the mean time here's a list of CodeIgniter's main features.

        • Model-View-Controller Based System
        • @@ -73,7 +73,7 @@ CodeIgniter is child's play so we encourage you to do just that. In the mean ti
        • Security and XSS Filtering
        • Session Management
        • Email Sending Class. Supports Attachments, HTML/Text email, multiple protocols (sendmail, SMTP, and Mail) and more.
        • -
        • Image Manipulation Library (cropping, resizing, rotating, etc.). Supports GD, ImageMagick, and NetPBM
        • +
        • Image Manipulation Library (cropping, resizing, rotating, etc.). Supports GD, ImageMagick, and NetPBM
        • File Uploading Class
        • FTP Class
        • Localization
        • diff --git a/user_guide/overview/getting_started.html b/user_guide/overview/getting_started.html index f120913f4..168332644 100644 --- a/user_guide/overview/getting_started.html +++ b/user_guide/overview/getting_started.html @@ -57,7 +57,7 @@ Getting Started

          Getting Started With CodeIgniter

          -

          Any software application requires some effort to learn. We've done our best to minimize the learning +

          Any software application requires some effort to learn. We've done our best to minimize the learning curve while making the process as enjoyable as possible.

          diff --git a/user_guide/overview/goals.html b/user_guide/overview/goals.html index 754ecaae0..7f1f7678e 100644 --- a/user_guide/overview/goals.html +++ b/user_guide/overview/goals.html @@ -67,9 +67,9 @@ rejecting anything that doesn't further the stated objective.

          From a technical and architectural standpoint, CodeIgniter was created with the following objectives:

            -
          • Dynamic Instantiation. In CodeIgniter, components are loaded and routines executed only when requested, rather than globally. No assumptions are made by the system regarding what may be needed beyond the minimal core resources, so the system is very light-weight by default. The events, as triggered by the HTTP request, and the controllers and views you design will determine what is invoked.
          • -
          • Loose Coupling. Coupling is the degree to which components of a system rely on each other. The less components depend on each other the more reusable and flexible the system becomes. Our goal was a very loosely coupled system.
          • -
          • Component Singularity. Singularity is the degree to which components have a narrowly focused purpose. In CodeIgniter, each class and its functions are highly autonomous in order to allow maximum usefulness.
          • +
          • Dynamic Instantiation. In CodeIgniter, components are loaded and routines executed only when requested, rather than globally. No assumptions are made by the system regarding what may be needed beyond the minimal core resources, so the system is very light-weight by default. The events, as triggered by the HTTP request, and the controllers and views you design will determine what is invoked.
          • +
          • Loose Coupling. Coupling is the degree to which components of a system rely on each other. The less components depend on each other the more reusable and flexible the system becomes. Our goal was a very loosely coupled system.
          • +
          • Component Singularity. Singularity is the degree to which components have a narrowly focused purpose. In CodeIgniter, each class and its functions are highly autonomous in order to allow maximum usefulness.

          CodeIgniter is a dynamically instantiated, loosely coupled system with high component singularity. It strives for simplicity, flexibility, and high performance in a small footprint package.

          diff --git a/user_guide/overview/mvc.html b/user_guide/overview/mvc.html index 91cf64977..9eb327a95 100644 --- a/user_guide/overview/mvc.html +++ b/user_guide/overview/mvc.html @@ -60,12 +60,12 @@ MVC

          CodeIgniter is based on the Model-View-Controller development pattern. -MVC is a software approach that separates application logic from presentation. In practice, it permits your web pages to contain minimal scripting since the presentation is separate from the PHP scripting.

          +MVC is a software approach that separates application logic from presentation. In practice, it permits your web pages to contain minimal scripting since the presentation is separate from the PHP scripting.

          • The Model represents your data structures. Typically your model classes will contain functions that help you -retrieve, insert, and update information in your database.
          • -
          • The View is the information that is being presented to a user. A View will normally be a web page, but +retrieve, insert, and update information in your database.
          • +
          • The View is the information that is being presented to a user. A View will normally be a web page, but in CodeIgniter, a view can also be a page fragment like a header or footer. It can also be an RSS page, or any other type of "page".
          • The Controller serves as an intermediary between the Model, the View, and any other resources needed to process the HTTP request and generate a web page.
          • diff --git a/user_guide/userguide.css b/user_guide/userguide.css index f93ff0d75..b08f4fb00 100644 --- a/user_guide/userguide.css +++ b/user_guide/userguide.css @@ -391,7 +391,7 @@ form { .select { background-color: #fff; - font-size: 11px; + font-size: 11px; font-weight: normal; color: #333; padding: 0; -- cgit v1.2.3-24-g4f1b From e70e92bab1de57a0749a31f2889b55cafb46d58e Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Mon, 25 Apr 2011 10:50:53 -0500 Subject: Fixing up a tabs vs spaces inconsistency in DB_Result --- system/database/DB_result.php | 83 +++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/system/database/DB_result.php b/system/database/DB_result.php index 06eec5124..e83228386 100644 --- a/system/database/DB_result.php +++ b/system/database/DB_result.php @@ -32,7 +32,7 @@ class CI_DB_result { var $result_id = NULL; var $result_array = array(); var $result_object = array(); - var $custom_result_object = array(); + var $custom_result_object = array(); var $current_row = 0; var $num_rows = 0; var $row_data = NULL; @@ -47,47 +47,52 @@ class CI_DB_result { */ function result($type = 'object') { - if ($type == 'array') return $this->result_array(); - else if ($type == 'object') return $this->result_object(); - else return $this->custom_result_object($type); + if ($type == 'array') return $this->result_array(); + else if ($type == 'object') return $this->result_object(); + else return $this->custom_result_object($type); } // -------------------------------------------------------------------- - /** - * Custom query result. - * - * @param class_name A string that represents the type of object you want back - * @return array of objects - */ - function custom_result_object($class_name) - { - if (array_key_exists($class_name, $this->custom_result_object)) - { - return $this->custom_result_object[$class_name]; - } - - if ($this->result_id === FALSE OR $this->num_rows() == 0) - { - return array(); - } - - // add the data to the object - $this->_data_seek(0); - $result_object = array(); + /** + * Custom query result. + * + * @param class_name A string that represents the type of object you want back + * @return array of objects + */ + function custom_result_object($class_name) + { + if (array_key_exists($class_name, $this->custom_result_object)) + { + return $this->custom_result_object[$class_name]; + } + + if ($this->result_id === FALSE OR $this->num_rows() == 0) + { + return array(); + } + + // add the data to the object + $this->_data_seek(0); + $result_object = array(); + while ($row = $this->_fetch_object()) - { - $object = new $class_name(); - foreach ($row as $key => $value) - { - $object->$key = $value; - } + { + $object = new $class_name(); + + foreach ($row as $key => $value) + { + $object->$key = $value; + } + $result_object[] = $object; } - // return the array - return $this->custom_result_object[$class_name] = $result_object; - } + // return the array + return $this->custom_result_object[$class_name] = $result_object; + } + + // -------------------------------------------------------------------- /** * Query result. "object" version. @@ -180,9 +185,9 @@ class CI_DB_result { $n = 0; } - if ($type == 'object') return $this->row_object($n); - else if ($type == 'array') return $this->row_array($n); - else return $this->custom_row_object($n, $type); + if ($type == 'object') return $this->row_object($n); + else if ($type == 'array') return $this->row_array($n); + else return $this->custom_row_object($n, $type); } // -------------------------------------------------------------------- @@ -219,7 +224,7 @@ class CI_DB_result { // -------------------------------------------------------------------- - /** + /** * Returns a single result row - custom object version * * @access public @@ -242,7 +247,7 @@ class CI_DB_result { return $result[$this->current_row]; } - /** + /** * Returns a single result row - object version * * @access public -- cgit v1.2.3-24-g4f1b From db60d240226468b19d656c4ba026bc992e4c3034 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 15 Apr 2011 11:31:30 +0900 Subject: add "Using CodeIgniter Drivers" and "Creating Your Own Driver" in TOC --- user_guide/nav/nav.js | 2 ++ user_guide/toc.html | 2 ++ 2 files changed, 4 insertions(+) diff --git a/user_guide/nav/nav.js b/user_guide/nav/nav.js index ce783fc27..b44994d4d 100644 --- a/user_guide/nav/nav.js +++ b/user_guide/nav/nav.js @@ -50,6 +50,8 @@ function create_menu(basepath) '
          • Helpers
          • ' + '
          • Using CodeIgniter Libraries
          • ' + '
          • Creating Your Own Libraries
          • ' + + '
          • Using CodeIgniter Drivers
          • ' + + '
          • Creating Your Own Drivers
          • ' + '
          • Creating Core Classes
          • ' + '
          • Hooks - Extending the Core
          • ' + '
          • Auto-loading Resources
          • ' + diff --git a/user_guide/toc.html b/user_guide/toc.html index 4b4ab1001..f6a5fe0ec 100644 --- a/user_guide/toc.html +++ b/user_guide/toc.html @@ -103,6 +103,8 @@ Table of Contents
          • Helpers
          • Using CodeIgniter Libraries
          • Creating Your Own Libraries
          • +
          • Using CodeIgniter Drivers
          • +
          • Creating Your Own Drivers
          • Creating Core Classes
          • Hooks - Extending the Core
          • Auto-loading Resources
          • -- cgit v1.2.3-24-g4f1b From e7bdd2260e6be61d3ed37e517f35ba017beee5f3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 15 Apr 2011 11:33:53 +0900 Subject: update Prev/Next Topic link on user_guide/database/index.html --- user_guide/database/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide/database/index.html b/user_guide/database/index.html index 594de80dd..1f0a1da7d 100644 --- a/user_guide/database/index.html +++ b/user_guide/database/index.html @@ -86,7 +86,7 @@ structures and Active Record patterns. The database functions offer clear, simpl -- cgit v1.2.3-24-g4f1b From 4c6ceb067ca15228c547770354023f826f552036 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 15 Apr 2011 11:35:43 +0900 Subject: update Prev/Next Topic link on user_guide/helpers/array_helper.html --- user_guide/helpers/array_helper.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide/helpers/array_helper.html b/user_guide/helpers/array_helper.html index 88e8384d5..139bbe2b5 100644 --- a/user_guide/helpers/array_helper.html +++ b/user_guide/helpers/array_helper.html @@ -159,10 +159,10 @@ $this->post_model->update(elements(array('id', 'title', 'content'), $_POST)); -- cgit v1.2.3-24-g4f1b From 33095c29a638c127928faa5b0360abd3ac5254f9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 15 Apr 2011 11:36:10 +0900 Subject: update Prev/Next Topic link on user_guide/helpers/captcha_helper.html --- user_guide/helpers/captcha_helper.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/user_guide/helpers/captcha_helper.html b/user_guide/helpers/captcha_helper.html index 3c6fa1188..c80c2fbe5 100644 --- a/user_guide/helpers/captcha_helper.html +++ b/user_guide/helpers/captcha_helper.html @@ -183,11 +183,11 @@ if ($row->count == 0)
            -- cgit v1.2.3-24-g4f1b From 49e31258bc85245b087d6b7b5ac02edb1b680bc6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 15 Apr 2011 11:37:15 +0900 Subject: update Prev/Next Topic link on user_guide/helpers/cookie_helper.html --- user_guide/helpers/cookie_helper.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide/helpers/cookie_helper.html b/user_guide/helpers/cookie_helper.html index 9879653c1..889c3346e 100644 --- a/user_guide/helpers/cookie_helper.html +++ b/user_guide/helpers/cookie_helper.html @@ -95,7 +95,7 @@ of values in the first parameter or you can set discrete parameters.

            -- cgit v1.2.3-24-g4f1b From 26eebddda5438c3967bad74a05c3e990528e1182 Mon Sep 17 00:00:00 2001 From: Eric Barnes Date: Sun, 17 Apr 2011 23:45:41 -0400 Subject: Changed server check to ensure SCRIPT_NAME is defined. Fixes #57 --- system/core/URI.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/system/core/URI.php b/system/core/URI.php index 80dc62e58..d56548654 100644 --- a/system/core/URI.php +++ b/system/core/URI.php @@ -120,7 +120,7 @@ class CI_URI { $path = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri); $this->_set_uri_string($path); } - + // -------------------------------------------------------------------- /** @@ -133,7 +133,7 @@ class CI_URI { { // 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; } @@ -151,7 +151,7 @@ class CI_URI { */ private function _detect_uri() { - if ( ! isset($_SERVER['REQUEST_URI'])) + if ( ! isset($_SERVER['REQUEST_URI']) OR ! isset($_SERVER['SCRIPT_NAME'])) { return ''; } @@ -184,12 +184,12 @@ class CI_URI { $_SERVER['QUERY_STRING'] = ''; $_GET = array(); } - + if ($uri == '/' || empty($uri)) { return '/'; } - + $uri = parse_url($uri, PHP_URL_PATH); // Do some final cleaning of the URI and return it -- cgit v1.2.3-24-g4f1b From c31b3729da50eaade365451f49dac7d462684702 Mon Sep 17 00:00:00 2001 From: Eric Barnes Date: Sun, 17 Apr 2011 23:58:40 -0400 Subject: Added ENVIRONMENT to reserved constants. Fixes #196 --- user_guide/changelog.html | 17 +++++++++++++++++ user_guide/general/reserved_names.html | 1 + 2 files changed, 18 insertions(+) diff --git a/user_guide/changelog.html b/user_guide/changelog.html index f24d8110c..0ebe74ae6 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -59,6 +59,23 @@ Change Log

            The Reactor Marker indicates items that were contributed to CodeIgniter via CodeIgniter Reactor.

            +

            Version 2.0.3

            +

            Release Date: Not Released

            + +
              +
            • General Changes +
                +
              • +
              +
            • +
            + +

            Bug fixes for 2.0.3

            +
              +
            • Added ENVIRONMENT to reserved constants. (Reactor #196)
            • +
            • Changed server check to ensure SCRIPT_NAME is defined. (Reactor #57)
            • +
            +

            Version 2.0.2

            Release Date: April 7, 2011
            Hg Tag: v2.0.2

            diff --git a/user_guide/general/reserved_names.html b/user_guide/general/reserved_names.html index d1ee2955b..00bebff61 100644 --- a/user_guide/general/reserved_names.html +++ b/user_guide/general/reserved_names.html @@ -90,6 +90,7 @@ is a list of reserved names. Do not name your controller any of these:

          Constants

            +
          • ENVIRONMENT
          • EXT
          • FCPATH
          • SELF
          • -- cgit v1.2.3-24-g4f1b From bffb7769c6f31b7a47355d4eb66f5ac1d85c2a2e Mon Sep 17 00:00:00 2001 From: Eric Barnes Date: Mon, 18 Apr 2011 00:03:31 -0400 Subject: Changed path in footer comment of cache dummy. --- system/libraries/Cache/drivers/Cache_dummy.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/system/libraries/Cache/drivers/Cache_dummy.php b/system/libraries/Cache/drivers/Cache_dummy.php index de47acb43..f96a68e27 100644 --- a/system/libraries/Cache/drivers/Cache_dummy.php +++ b/system/libraries/Cache/drivers/Cache_dummy.php @@ -10,29 +10,29 @@ * @license http://codeigniter.com/user_guide/license.html * @link http://codeigniter.com * @since Version 2.0 - * @filesource + * @filesource */ // ------------------------------------------------------------------------ /** - * CodeIgniter Dummy Caching Class + * CodeIgniter Dummy Caching Class * * @package CodeIgniter * @subpackage Libraries * @category Core * @author ExpressionEngine Dev Team - * @link + * @link */ class CI_Cache_dummy extends CI_Driver { /** - * Get + * Get * * Since this is the dummy class, it's always going to return FALSE. * - * @param string + * @param string * @return Boolean FALSE */ public function get($id) @@ -40,8 +40,8 @@ class CI_Cache_dummy extends CI_Driver { return FALSE; } - // ------------------------------------------------------------------------ - + // ------------------------------------------------------------------------ + /** * Cache Save * @@ -55,7 +55,7 @@ class CI_Cache_dummy extends CI_Driver { { return TRUE; } - + // ------------------------------------------------------------------------ /** @@ -112,7 +112,7 @@ class CI_Cache_dummy extends CI_Driver { /** * Is this caching driver supported on the system? * Of course this one is. - * + * * @return TRUE; */ public function is_supported() @@ -121,9 +121,9 @@ class CI_Cache_dummy extends CI_Driver { } // ------------------------------------------------------------------------ - + } // End Class -/* End of file Cache_apc.php */ -/* Location: ./system/libraries/Cache/drivers/Cache_apc.php */ \ No newline at end of file +/* End of file Cache_dummy.php */ +/* Location: ./system/libraries/Cache/drivers/Cache_dummy.php */ \ No newline at end of file -- cgit v1.2.3-24-g4f1b From 826429cf40a9624788b92d2e6e4b7659e1b0d8a1 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Mon, 18 Apr 2011 09:40:19 -0500 Subject: Added an optional third parameter to heading() which allows adding html attributes to the rendered heading tag. --- system/helpers/html_helper.php | 5 +++-- user_guide/changelog.html | 5 +++++ user_guide/helpers/html_helper.html | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php index c6103ab6f..a29204391 100644 --- a/system/helpers/html_helper.php +++ b/system/helpers/html_helper.php @@ -40,9 +40,10 @@ */ if ( ! function_exists('heading')) { - function heading($data = '', $h = '1') + function heading($data = '', $h = '1', $attributes = '') { - return "".$data.""; + $attributes = ($attributes != '') ? ' '.$attributes : $attributes; + return "".$data.""; } } diff --git a/user_guide/changelog.html b/user_guide/changelog.html index 0ebe74ae6..0afc5b822 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -68,6 +68,11 @@ Change Log
          +
        • Helpers +
            +
          • Added an optional third parameter to heading() which allows adding html attributes to the rendered heading tag.
          • +
          +

        Bug fixes for 2.0.3

        diff --git a/user_guide/helpers/html_helper.html b/user_guide/helpers/html_helper.html index 1a0529f7b..308013d51 100644 --- a/user_guide/helpers/html_helper.html +++ b/user_guide/helpers/html_helper.html @@ -89,6 +89,11 @@ second the size of the heading. Example:

        echo heading('Welcome!', 3);

        The above would produce: <h3>Welcome!</h3>

        +

        Additionally, in order to add attributes to the heading tag such as HTML classes, ids or inline styles, a third parameter is available.

        +echo heading('Welcome!', 3, 'class="pink"') +

        The above code produces: <h3 class="pink">Welcome!<<h3>

        + +

        img()

        Lets you create HTML <img /> tags. The first parameter contains the image source. Example:

        echo img('images/picture.jpg');
        -- cgit v1.2.3-24-g4f1b From 62df13125bd9ab22ff0c7f2565a42a6de13ed7e4 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Mon, 18 Apr 2011 11:18:02 -0500 Subject: Added Session Class userdata to the output profiler. Additionally, added a show/hide toggle on HTTP Headers, Session Data and Config Variables. --- system/language/english/profiler_lang.php | 3 +++ system/libraries/Profiler.php | 45 ++++++++++++++++++++++++++----- user_guide/changelog.html | 2 +- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/system/language/english/profiler_lang.php b/system/language/english/profiler_lang.php index b6460fb83..1111158c8 100644 --- a/system/language/english/profiler_lang.php +++ b/system/language/english/profiler_lang.php @@ -9,6 +9,7 @@ $lang['profiler_post_data'] = 'POST DATA'; $lang['profiler_uri_string'] = 'URI STRING'; $lang['profiler_memory_usage'] = 'MEMORY USAGE'; $lang['profiler_config'] = 'CONFIG VARIABLES'; +$lang['profiler_session_data'] = 'SESSION DATA'; $lang['profiler_headers'] = 'HTTP HEADERS'; $lang['profiler_no_db'] = 'Database driver is not currently loaded'; $lang['profiler_no_queries'] = 'No queries were run'; @@ -17,6 +18,8 @@ $lang['profiler_no_get'] = 'No GET data exists'; $lang['profiler_no_uri'] = 'No URI data exists'; $lang['profiler_no_memory'] = 'Memory Usage Unavailable'; $lang['profiler_no_profiles'] = 'No Profile data - all Profiler sections have been disabled.'; +$lang['profiler_section_hide'] = 'Hide'; +$lang['profiler_section_show'] = 'Show'; /* End of file profiler_lang.php */ /* Location: ./system/language/english/profiler_lang.php */ \ No newline at end of file diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php index 8a1f18ced..d1828b984 100644 --- a/system/libraries/Profiler.php +++ b/system/libraries/Profiler.php @@ -32,7 +32,7 @@ */ class CI_Profiler { - var $CI; + private $CI; protected $_available_sections = array( 'benchmarks', @@ -43,6 +43,7 @@ class CI_Profiler { 'controller_info', 'queries', 'http_headers', + 'session_data', 'config' ); @@ -410,10 +411,10 @@ class CI_Profiler { $output = "\n\n"; $output .= '
        '; $output .= "\n"; - $output .= '  '.$this->CI->lang->line('profiler_headers').'  '; + $output .= '  '.$this->CI->lang->line('profiler_headers').'  ('.$this->CI->lang->line('profiler_section_show').')'; $output .= "\n"; - $output .= "\n\n\n"; + $output .= "\n\n
        \n"; foreach (array('HTTP_ACCEPT', 'HTTP_USER_AGENT', 'HTTP_CONNECTION', 'SERVER_PORT', 'SERVER_NAME', 'REMOTE_ADDR', 'SERVER_SOFTWARE', 'HTTP_ACCEPT_LANGUAGE', 'SCRIPT_NAME', 'REQUEST_METHOD',' HTTP_HOST', 'REMOTE_HOST', 'CONTENT_TYPE', 'SERVER_PROTOCOL', 'QUERY_STRING', 'HTTP_ACCEPT_ENCODING', 'HTTP_X_FORWARDED_FOR') as $header) { @@ -441,10 +442,10 @@ class CI_Profiler { $output = "\n\n"; $output .= '
        '; $output .= "\n"; - $output .= '  '.$this->CI->lang->line('profiler_config').'  '; + $output .= '  '.$this->CI->lang->line('profiler_config').'  ('.$this->CI->lang->line('profiler_section_show').')'; $output .= "\n"; - $output .= "\n\n
        \n"; + $output .= "\n\n
        \n"; foreach ($this->CI->config->config as $config=>$val) { @@ -464,6 +465,39 @@ class CI_Profiler { // -------------------------------------------------------------------- + /** + * Compile session userdata + * + * @return string + */ + private function _compile_session_data() + { + if ( ! isset($this->CI->session)) + { + return; + } + + $output = '
        '; + $output .= '  '.$this->CI->lang->line('profiler_session_data').'  ('.$this->CI->lang->line('profiler_section_show').')'; + $output .= "
        "; + + foreach ($this->CI->session->all_userdata() as $key => $val) + { + if (is_array($val)) + { + $val = print_r($val, TRUE); + } + + $output .= "\n"; + } + + $output .= ''; + $output .= "
        "; + return $output; + } + + // -------------------------------------------------------------------- + /** * Run the Profiler * @@ -493,7 +527,6 @@ class CI_Profiler { return $output; } - } // END CI_Profiler class diff --git a/user_guide/changelog.html b/user_guide/changelog.html index 0afc5b822..9890f602c 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -65,7 +65,7 @@ Change Log
        • General Changes
            -
          • +
          • Added Session Class userdata to the output profiler. Additionally, added a show/hide toggle on HTTP Headers, Session Data and Config Variables.
        • Helpers -- cgit v1.2.3-24-g4f1b From 3403366d0f457c1dd449076b4177d1aff5cb176c Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Mon, 18 Apr 2011 11:18:09 -0500 Subject: changeset: 2202:06a75a1bd622 tag: tip user: Greg Aker date: Mon Apr 18 11:10:37 2011 -0500 summary: Tweak to session class all_userdata() to just return the userdata array. Also documented previously undocumented all_userdata() method. --- system/libraries/Session.php | 4 ++-- user_guide/libraries/sessions.html | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/system/libraries/Session.php b/system/libraries/Session.php index 182294059..32317c2e6 100644 --- a/system/libraries/Session.php +++ b/system/libraries/Session.php @@ -435,11 +435,11 @@ class CI_Session { * Fetch all session data * * @access public - * @return mixed + * @return array */ function all_userdata() { - return ( ! isset($this->userdata)) ? FALSE : $this->userdata; + return $this->userdata; } // -------------------------------------------------------------------- diff --git a/user_guide/libraries/sessions.html b/user_guide/libraries/sessions.html index 600d301c9..8d9c14eb6 100644 --- a/user_guide/libraries/sessions.html +++ b/user_guide/libraries/sessions.html @@ -170,6 +170,23 @@ having to run a database query when you need it.

          Note: Cookies can only hold 4KB of data, so be careful not to exceed the capacity. The encryption process in particular produces a longer data string than the original so keep careful track of how much data you are storing.

          +

          Retrieving All Session Data

          +

          An array of all userdata can be retrieved as follows:

          +$this->session->all_userdata() + +

          And returns an associative array like the following:

          + +
          +Array
          +(
          +    [session_id] => 4a5a5dca22728fb0a84364eeb405b601
          +    [ip_address] => 127.0.0.1
          +    [user_agent] => Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7;
          +    [last_activity] => 1303142623
          +)
          +
          + +

          Removing Session Data

          Just as set_userdata() can be used to add information into a session, unset_userdata() can be used to remove it, by passing the session key. For example, if you wanted to remove 'some_name' from your session information:

          $this->session->unset_userdata('some_name');

          -- cgit v1.2.3-24-g4f1b From e6e6e64ab078205153513af24dd4163157efb148 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Mon, 18 Apr 2011 15:54:13 -0500 Subject: changeset: 2204:37301a84c8be tag: tip user: Greg Aker date: Mon Apr 18 15:51:28 2011 -0500 summary: Adding toggle show/hide on database queries in the output profiler. Added a profiler config item to set a threshold of when to hide the queries by default. Additionally, fixed a bug I created earlier today by marking the $CI class var in CI_Profiler as private. --- system/libraries/Profiler.php | 35 ++++++++++--- user_guide/general/profiling.html | 103 ++++++++++++++++++++------------------ 2 files changed, 83 insertions(+), 55 deletions(-) diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php index d1828b984..b73ddaf0d 100644 --- a/system/libraries/Profiler.php +++ b/system/libraries/Profiler.php @@ -32,8 +32,6 @@ */ class CI_Profiler { - private $CI; - protected $_available_sections = array( 'benchmarks', 'get', @@ -46,12 +44,24 @@ class CI_Profiler { 'session_data', 'config' ); + + protected $_query_toggle_count = 25; + + protected $CI; + // -------------------------------------------------------------------- + public function __construct($config = array()) { $this->CI =& get_instance(); $this->CI->load->language('profiler'); + if (isset($config['query_toggle_count'])) + { + $this->_query_toggle_count = (int) $config['query_toggle_count']; + unset($config['query_toggle_count']); + } + // default all sections to display foreach ($this->_available_sections as $section) { @@ -163,7 +173,7 @@ class CI_Profiler { $output .= "\n"; $output .= '  '.$this->CI->lang->line('profiler_queries').'  '; $output .= "\n"; - $output .= "\n\n\n"; + $output .= "\n\n
          \n"; $output .="\n"; $output .= "
          ".$this->CI->lang->line('profiler_no_db')."
          \n"; $output .= ""; @@ -178,14 +188,27 @@ class CI_Profiler { $highlight = array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'AND', 'LEFT JOIN', 'ORDER BY', 'GROUP BY', 'LIMIT', 'INSERT', 'INTO', 'VALUES', 'UPDATE', 'OR ', 'HAVING', 'OFFSET', 'NOT IN', 'IN', 'LIKE', 'NOT LIKE', 'COUNT', 'MAX', 'MIN', 'ON', 'AS', 'AVG', 'SUM', '(', ')'); $output = "\n\n"; - + + $count = 0; + foreach ($dbs as $db) { + $count++; + + $hide_queries = (count($db->queries) > $this->_query_toggle_count) ? ' display:none' : ''; + + $show_hide_js = '('.$this->CI->lang->line('profiler_section_hide').')'; + + if ($hide_queries != '') + { + $show_hide_js = '('.$this->CI->lang->line('profiler_section_show').')'; + } + $output .= '
          '; $output .= "\n"; - $output .= '  '.$this->CI->lang->line('profiler_database').':  '.$db->database.'   '.$this->CI->lang->line('profiler_queries').': '.count($db->queries).'   '; + $output .= '  '.$this->CI->lang->line('profiler_database').':  '.$db->database.'   '.$this->CI->lang->line('profiler_queries').': '.count($db->queries).'  '.$show_hide_js.''; $output .= "\n"; - $output .= "\n\n\n"; + $output .= "\n\n
          \n"; if (count($db->queries) == 0) { diff --git a/user_guide/general/profiling.html b/user_guide/general/profiling.html index f3ea0c6fd..78ece7dcd 100644 --- a/user_guide/general/profiling.html +++ b/user_guide/general/profiling.html @@ -105,55 +105,60 @@ This information can be useful during development in order to help with debuggin
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          KeyDescriptionDefault
          benchmarksElapsed time of Benchmark points and total execution timeTRUE
          configCodeIgniter Config variablesTRUE
          controller_infoThe Controller class and method requestedTRUE
          getAny GET data passed in the requestTRUE
          http_headersThe HTTP headers for the current requestTRUE
          memory_usageAmount of memory consumed by the current request, in bytesTRUE
          postAny POST data passed in the requestTRUE
          queriesListing of all database queries executed, including execution timeTRUE
          uri_stringThe URI of the current requestTRUE
          KeyDescriptionDefault
          benchmarksElapsed time of Benchmark points and total execution timeTRUE
          configCodeIgniter Config variablesTRUE
          controller_infoThe Controller class and method requestedTRUE
          getAny GET data passed in the requestTRUE
          http_headersThe HTTP headers for the current requestTRUE
          memory_usageAmount of memory consumed by the current request, in bytesTRUE
          postAny POST data passed in the requestTRUE
          queriesListing of all database queries executed, including execution timeTRUE
          uri_stringThe URI of the current requestTRUE
          query_toggle_countThe number of queries after which the query block will default to hidden.25
          -- cgit v1.2.3-24-g4f1b From 3a746655e92ec59ee7e731c3535673a9aedc5d3e Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Tue, 19 Apr 2011 10:59:47 -0500 Subject: Removing internal references to the EXT constant. Additionally, marked the constant as deprecated. Use ".php" instead. Also adding upgrade notes from 2.0.2 to 2.0.3. --- index.php | 3 +- system/core/CodeIgniter.php | 22 +++---- system/core/Common.php | 14 ++--- system/core/Config.php | 6 +- system/core/Exceptions.php | 4 +- system/core/Hooks.php | 8 +-- system/core/Lang.php | 4 +- system/core/Loader.php | 64 +++++++++---------- system/core/Output.php | 6 +- system/core/Router.php | 14 ++--- system/database/DB.php | 12 ++-- system/database/DB_driver.php | 6 +- system/helpers/download_helper.php | 8 +-- system/helpers/file_helper.php | 8 +-- system/helpers/html_helper.php | 8 +-- system/helpers/smiley_helper.php | 8 +-- system/helpers/text_helper.php | 8 +-- system/libraries/Calendar.php | 2 +- system/libraries/Driver.php | 2 +- system/libraries/Encrypt.php | 2 +- system/libraries/Log.php | 2 +- system/libraries/Upload.php | 8 +-- system/libraries/User_agent.php | 8 +-- user_guide/changelog.html | 1 + user_guide/installation/upgrade_203.html | 102 +++++++++++++++++++++++++++++++ user_guide/installation/upgrading.html | 1 + 26 files changed, 218 insertions(+), 113 deletions(-) create mode 100644 user_guide/installation/upgrade_203.html diff --git a/index.php b/index.php index 6e67c2db5..a8d58b2d9 100644 --- a/index.php +++ b/index.php @@ -163,6 +163,7 @@ if (defined('ENVIRONMENT')) define('SELF', pathinfo(__FILE__, PATHINFO_BASENAME)); // The PHP file extension + // this global constant is deprecated. define('EXT', '.php'); // Path to the system folder @@ -198,7 +199,7 @@ if (defined('ENVIRONMENT')) * And away we go... * */ -require_once BASEPATH.'core/CodeIgniter'.EXT; +require_once BASEPATH.'core/CodeIgniter.php'; /* End of file index.php */ /* Location: ./index.php */ \ No newline at end of file diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index e022e1b46..03b25ab9e 100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -46,20 +46,20 @@ * Load the global functions * ------------------------------------------------------ */ - require(BASEPATH.'core/Common'.EXT); + require(BASEPATH.'core/Common.php'); /* * ------------------------------------------------------ * Load the framework constants * ------------------------------------------------------ */ - if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants'.EXT)) + if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php')) { - require(APPPATH.'config/'.ENVIRONMENT.'/constants'.EXT); + require(APPPATH.'config/'.ENVIRONMENT.'/constants.php'); } else { - require(APPPATH.'config/constants'.EXT); + require(APPPATH.'config/constants.php'); } /* @@ -224,7 +224,7 @@ * */ // Load the base controller class - require BASEPATH.'core/Controller'.EXT; + require BASEPATH.'core/Controller.php'; function &get_instance() { @@ -232,20 +232,20 @@ } - if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller'.EXT)) + if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php')) { - require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller'.EXT; + require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'; } // Load the local application controller // Note: The Router class automatically validates the controller path using the router->_validate_request(). // If this include fails it means that the default controller in the Routes.php file is not resolving to something valid. - if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().EXT)) + if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php')) { show_error('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.'); } - include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().EXT); + include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->fetch_class().'.php'); // Set a mark point for benchmarking $BM->mark('loading_time:_base_classes_end'); @@ -318,12 +318,12 @@ $method = (isset($x[1]) ? $x[1] : 'index'); if ( ! class_exists($class)) { - if ( ! file_exists(APPPATH.'controllers/'.$class.EXT)) + if ( ! file_exists(APPPATH.'controllers/'.$class.'.php')) { show_404("{$class}/{$method}"); } - include_once(APPPATH.'controllers/'.$class.EXT); + include_once(APPPATH.'controllers/'.$class.'.php'); unset($CI); $CI = new $class(); } diff --git a/system/core/Common.php b/system/core/Common.php index 1aca809ab..d1e8e77e9 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -128,13 +128,13 @@ // thenin the local application/libraries folder foreach (array(BASEPATH, APPPATH) as $path) { - if (file_exists($path.$directory.'/'.$class.EXT)) + if (file_exists($path.$directory.'/'.$class.'.php')) { $name = $prefix.$class; if (class_exists($name) === FALSE) { - require($path.$directory.'/'.$class.EXT); + require($path.$directory.'/'.$class.'.php'); } break; @@ -142,13 +142,13 @@ } // Is the request a class extension? If so we load it too - if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.EXT)) + if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php')) { $name = config_item('subclass_prefix').$class; if (class_exists($name) === FALSE) { - require(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.EXT); + require(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'); } } @@ -157,7 +157,7 @@ { // Note: We use exit() rather then show_error() in order to avoid a // self-referencing loop with the Excptions class - exit('Unable to locate the specified class: '.$class.EXT); + exit('Unable to locate the specified class: '.$class.'.php'); } // Keep track of what we just loaded @@ -209,9 +209,9 @@ } // Is the config file in the environment folder? - if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config'.EXT)) + if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php')) { - $file_path = APPPATH.'config/config'.EXT; + $file_path = APPPATH.'config/config.php'; } // Fetch the config file diff --git a/system/core/Config.php b/system/core/Config.php index 863c5ef4b..4493ff266 100644 --- a/system/core/Config.php +++ b/system/core/Config.php @@ -80,7 +80,7 @@ class CI_Config { */ function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) { - $file = ($file == '') ? 'config' : str_replace(EXT, '', $file); + $file = ($file == '') ? 'config' : str_replace('.php', '', $file); $found = FALSE; $loaded = FALSE; @@ -92,7 +92,7 @@ class CI_Config { foreach ($check_locations as $location) { - $file_path = $path.'config/'.$location.EXT; + $file_path = $path.'config/'.$location.'.php'; if (in_array($file_path, $this->is_loaded, TRUE)) { @@ -152,7 +152,7 @@ class CI_Config { { return FALSE; } - show_error('The configuration file '.$file.EXT.' does not exist.'); + show_error('The configuration file '.$file.'.php'.' does not exist.'); } return TRUE; diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php index f5659561c..bff86a92f 100644 --- a/system/core/Exceptions.php +++ b/system/core/Exceptions.php @@ -128,7 +128,7 @@ class CI_Exceptions { ob_end_flush(); } ob_start(); - include(APPPATH.'errors/'.$template.EXT); + include(APPPATH.'errors/'.$template.'.php'); $buffer = ob_get_contents(); ob_end_clean(); return $buffer; @@ -164,7 +164,7 @@ class CI_Exceptions { ob_end_flush(); } ob_start(); - include(APPPATH.'errors/error_php'.EXT); + include(APPPATH.'errors/error_php.php'); $buffer = ob_get_contents(); ob_end_clean(); echo $buffer; diff --git a/system/core/Hooks.php b/system/core/Hooks.php index 24fa1055b..fd6380f0a 100644 --- a/system/core/Hooks.php +++ b/system/core/Hooks.php @@ -65,13 +65,13 @@ class CI_Hooks { // Grab the "hooks" definition file. // If there are no hooks, we're done. - if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/hooks'.EXT)) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/hooks.php')) { - include(APPPATH.'config/'.ENVIRONMENT.'/hooks'.EXT); + include(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'); } - elseif (is_file(APPPATH.'config/hooks'.EXT)) + elseif (is_file(APPPATH.'config/hooks.php')) { - include(APPPATH.'config/hooks'.EXT); + include(APPPATH.'config/hooks.php'); } diff --git a/system/core/Lang.php b/system/core/Lang.php index cdadc7f41..170e6c725 100644 --- a/system/core/Lang.php +++ b/system/core/Lang.php @@ -51,14 +51,14 @@ class CI_Lang { */ function load($langfile = '', $idiom = '', $return = FALSE, $add_suffix = TRUE, $alt_path = '') { - $langfile = str_replace(EXT, '', $langfile); + $langfile = str_replace('.php', '', $langfile); if ($add_suffix == TRUE) { $langfile = str_replace('_lang.', '', $langfile).'_lang'; } - $langfile .= EXT; + $langfile .= '.php'; if (in_array($langfile, $this->is_loaded, TRUE)) { diff --git a/system/core/Loader.php b/system/core/Loader.php index e75805d0e..59415b72a 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -161,7 +161,7 @@ class CI_Loader { foreach ($this->_ci_model_paths as $mod_path) { - if ( ! file_exists($mod_path.'models/'.$path.$model.EXT)) + if ( ! file_exists($mod_path.'models/'.$path.$model.'.php')) { continue; } @@ -181,7 +181,7 @@ class CI_Loader { load_class('Model', 'core'); } - require_once($mod_path.'models/'.$path.$model.EXT); + require_once($mod_path.'models/'.$path.$model.'.php'); $model = ucfirst($model); @@ -217,7 +217,7 @@ class CI_Loader { return FALSE; } - require_once(BASEPATH.'database/DB'.EXT); + require_once(BASEPATH.'database/DB.php'); if ($return === TRUE) { @@ -253,8 +253,8 @@ class CI_Loader { // this use is deprecated and strongly discouraged $CI->load->dbforge(); - require_once(BASEPATH.'database/DB_utility'.EXT); - require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_utility'.EXT); + require_once(BASEPATH.'database/DB_utility.php'); + require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_utility.php'); $class = 'CI_DB_'.$CI->db->dbdriver.'_utility'; $CI->dbutil = new $class(); @@ -277,8 +277,8 @@ class CI_Loader { $CI =& get_instance(); - require_once(BASEPATH.'database/DB_forge'.EXT); - require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge'.EXT); + require_once(BASEPATH.'database/DB_forge.php'); + require_once(BASEPATH.'database/drivers/'.$CI->db->dbdriver.'/'.$CI->db->dbdriver.'_forge.php'); $class = 'CI_DB_'.$CI->db->dbdriver.'_forge'; $CI->dbforge = new $class(); @@ -375,16 +375,16 @@ class CI_Loader { continue; } - $ext_helper = APPPATH.'helpers/'.config_item('subclass_prefix').$helper.EXT; + $ext_helper = APPPATH.'helpers/'.config_item('subclass_prefix').$helper.'.php'; // Is this a helper extension request? if (file_exists($ext_helper)) { - $base_helper = BASEPATH.'helpers/'.$helper.EXT; + $base_helper = BASEPATH.'helpers/'.$helper.'.php'; if ( ! file_exists($base_helper)) { - show_error('Unable to load the requested file: helpers/'.$helper.EXT); + show_error('Unable to load the requested file: helpers/'.$helper.'.php'); } include_once($ext_helper); @@ -398,9 +398,9 @@ class CI_Loader { // Try to load the helper foreach ($this->_ci_helper_paths as $path) { - if (file_exists($path.'helpers/'.$helper.EXT)) + if (file_exists($path.'helpers/'.$helper.'.php')) { - include_once($path.'helpers/'.$helper.EXT); + include_once($path.'helpers/'.$helper.'.php'); $this->_ci_helpers[$helper] = TRUE; log_message('debug', 'Helper loaded: '.$helper); @@ -411,7 +411,7 @@ class CI_Loader { // unable to load the helper if ( ! isset($this->_ci_helpers[$helper])) { - show_error('Unable to load the requested file: helpers/'.$helper.EXT); + show_error('Unable to load the requested file: helpers/'.$helper.'.php'); } } } @@ -490,7 +490,7 @@ class CI_Loader { if ( ! class_exists('CI_Driver_Library')) { // we aren't instantiating an object here, that'll be done by the Library itself - require BASEPATH.'libraries/Driver'.EXT; + require BASEPATH.'libraries/Driver.php'; } // We can save the loader some time since Drivers will *always* be in a subfolder, @@ -616,7 +616,7 @@ class CI_Loader { if ($_ci_path == '') { $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION); - $_ci_file = ($_ci_ext == '') ? $_ci_view.EXT : $_ci_view; + $_ci_file = ($_ci_ext == '') ? $_ci_view.'.php' : $_ci_view; $_ci_path = $this->_ci_view_path.$_ci_file; } else @@ -732,7 +732,7 @@ class CI_Loader { // Get the class name, and while we're at it trim any slashes. // The directory path can be included as part of the class name, // but we don't want a leading slash - $class = str_replace(EXT, '', trim($class, '/')); + $class = str_replace('.php', '', trim($class, '/')); // Was the path included with the class name? // We look for a slash to determine this @@ -749,12 +749,12 @@ class CI_Loader { // We'll test for both lowercase and capitalized versions of the file name foreach (array(ucfirst($class), strtolower($class)) as $class) { - $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.EXT; + $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php'; // Is this a class extension request? if (file_exists($subclass)) { - $baseclass = BASEPATH.'libraries/'.ucfirst($class).EXT; + $baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php'; if ( ! file_exists($baseclass)) { @@ -793,7 +793,7 @@ class CI_Loader { $is_duplicate = FALSE; foreach ($this->_ci_library_paths as $path) { - $filepath = $path.'libraries/'.$subdir.$class.EXT; + $filepath = $path.'libraries/'.$subdir.$class.'.php'; // Does the file exist? No? Bummer... if ( ! file_exists($filepath)) @@ -872,24 +872,24 @@ 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 (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).EXT)) + if (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php')) { - include_once($path .'config/'.ENVIRONMENT.'/'.strtolower($class).EXT); + include_once($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'); break; } - elseif (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).EXT)) + elseif (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php')) { - include_once($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).EXT); + include_once($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'); break; } - elseif (file_exists($path .'config/'.strtolower($class).EXT)) + elseif (file_exists($path .'config/'.strtolower($class).'.php')) { - include_once($path .'config/'.strtolower($class).EXT); + include_once($path .'config/'.strtolower($class).'.php'); break; } - elseif (file_exists($path .'config/'.ucfirst(strtolower($class)).EXT)) + elseif (file_exists($path .'config/'.ucfirst(strtolower($class)).'.php')) { - include_once($path .'config/'.ucfirst(strtolower($class)).EXT); + include_once($path .'config/'.ucfirst(strtolower($class)).'.php'); break; } } @@ -965,13 +965,13 @@ class CI_Loader { */ function _ci_autoloader() { - if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload'.EXT)) + if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php')) { - include_once(APPPATH.'config/'.ENVIRONMENT.'/autoload'.EXT); + include_once(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'); } else { - include_once(APPPATH.'config/autoload'.EXT); + include_once(APPPATH.'config/autoload.php'); } @@ -1084,13 +1084,13 @@ class CI_Loader { { if ( ! is_array($filename)) { - return array(strtolower(str_replace(EXT, '', str_replace($extension, '', $filename)).$extension)); + return array(strtolower(str_replace('.php', '', str_replace($extension, '', $filename)).$extension)); } else { foreach ($filename as $key => $val) { - $filename[$key] = strtolower(str_replace(EXT, '', str_replace($extension, '', $val)).$extension); + $filename[$key] = strtolower(str_replace('.php', '', str_replace($extension, '', $val)).$extension); } return $filename; diff --git a/system/core/Output.php b/system/core/Output.php index 45a82f3cb..05ace919c 100644 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -42,13 +42,13 @@ class CI_Output { $this->_zlib_oc = @ini_get('zlib.output_compression'); // Get mime types for later - if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT)) + if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) { - include APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT; + include APPPATH.'config/'.ENVIRONMENT.'/mimes.php'; } else { - include APPPATH.'config/mimes'.EXT; + include APPPATH.'config/mimes.php'; } diff --git a/system/core/Router.php b/system/core/Router.php index d451aab68..5e92a04b1 100644 --- a/system/core/Router.php +++ b/system/core/Router.php @@ -87,13 +87,13 @@ class CI_Router { } // Load the routes.php file. - if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/routes'.EXT)) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/routes.php')) { - include(APPPATH.'config/'.ENVIRONMENT.'/routes'.EXT); + include(APPPATH.'config/'.ENVIRONMENT.'/routes.php'); } - elseif (is_file(APPPATH.'config/routes'.EXT)) + elseif (is_file(APPPATH.'config/routes.php')) { - include(APPPATH.'config/routes'.EXT); + include(APPPATH.'config/routes.php'); } $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route; @@ -227,7 +227,7 @@ class CI_Router { } // Does the requested controller exist in the root folder? - if (file_exists(APPPATH.'controllers/'.$segments[0].EXT)) + if (file_exists(APPPATH.'controllers/'.$segments[0].'.php')) { return $segments; } @@ -242,7 +242,7 @@ class CI_Router { if (count($segments) > 0) { // Does the requested controller exist in the sub-folder? - if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT)) + if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php')) { show_404($this->fetch_directory().$segments[0]); } @@ -264,7 +264,7 @@ class CI_Router { } // Does the default controller exist in the sub-folder? - if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT)) + if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php')) { $this->directory = ''; return array(); diff --git a/system/database/DB.php b/system/database/DB.php index 8bf1ba8ba..33207d885 100644 --- a/system/database/DB.php +++ b/system/database/DB.php @@ -28,11 +28,11 @@ function &DB($params = '', $active_record_override = NULL) if (is_string($params) AND strpos($params, '://') === FALSE) { // Is the config file in the environment folder? - if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/database'.EXT)) + if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/database.php')) { - if ( ! file_exists($file_path = APPPATH.'config/database'.EXT)) + if ( ! file_exists($file_path = APPPATH.'config/database.php')) { - show_error('The configuration file database'.EXT.' does not exist.'); + show_error('The configuration file database.php does not exist.'); } } @@ -116,11 +116,11 @@ function &DB($params = '', $active_record_override = NULL) $active_record = $active_record_override; } - require_once(BASEPATH.'database/DB_driver'.EXT); + require_once(BASEPATH.'database/DB_driver.php'); if ( ! isset($active_record) OR $active_record == TRUE) { - require_once(BASEPATH.'database/DB_active_rec'.EXT); + require_once(BASEPATH.'database/DB_active_rec.php'); if ( ! class_exists('CI_DB')) { @@ -135,7 +135,7 @@ function &DB($params = '', $active_record_override = NULL) } } - require_once(BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver'.EXT); + require_once(BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php'); // Instantiate the DB adapter $driver = 'CI_DB_'.$params['dbdriver'].'_driver'; diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index e7a9de475..10e8ed0c0 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -424,8 +424,8 @@ class CI_DB_driver { if ( ! class_exists($driver)) { - include_once(BASEPATH.'database/DB_result'.EXT); - include_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result'.EXT); + include_once(BASEPATH.'database/DB_result.php'); + include_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result.php'); } return $driver; @@ -1115,7 +1115,7 @@ class CI_DB_driver { if ( ! class_exists('CI_DB_Cache')) { - if ( ! @include(BASEPATH.'database/DB_cache'.EXT)) + if ( ! @include(BASEPATH.'database/DB_cache.php')) { return $this->cache_off(); } diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php index f8073d238..1145688ae 100644 --- a/system/helpers/download_helper.php +++ b/system/helpers/download_helper.php @@ -58,13 +58,13 @@ if ( ! function_exists('force_download')) $extension = end($x); // Load the mime types - if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT)) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) { - include(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT); + include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'); } - elseif (is_file(APPPATH.'config/mimes'.EXT)) + elseif (is_file(APPPATH.'config/mimes.php')) { - include(APPPATH.'config/mimes'.EXT); + include(APPPATH.'config/mimes.php'); } // Set a default mime if we can't find it diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php index 44344947e..3931667fd 100644 --- a/system/helpers/file_helper.php +++ b/system/helpers/file_helper.php @@ -352,13 +352,13 @@ if ( ! function_exists('get_mime_by_extension')) if ( ! is_array($mimes)) { - if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT)) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) { - include(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT); + include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'); } - elseif (is_file(APPPATH.'config/mimes'.EXT)) + elseif (is_file(APPPATH.'config/mimes.php')) { - include(APPPATH.'config/mimes'.EXT); + include(APPPATH.'config/mimes.php'); } if ( ! is_array($mimes)) diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php index a29204391..080f622dd 100644 --- a/system/helpers/html_helper.php +++ b/system/helpers/html_helper.php @@ -259,13 +259,13 @@ if ( ! function_exists('doctype')) if ( ! is_array($_doctypes)) { - if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/doctypes'.EXT)) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/doctypes.php')) { - include(APPPATH.'config/'.ENVIRONMENT.'/doctypes'.EXT); + include(APPPATH.'config/'.ENVIRONMENT.'/doctypes.php'); } - elseif (is_file(APPPATH.'config/doctypes'.EXT)) + elseif (is_file(APPPATH.'config/doctypes.php')) { - include(APPPATH.'config/doctypes'.EXT); + include(APPPATH.'config/doctypes.php'); } if ( ! is_array($_doctypes)) diff --git a/system/helpers/smiley_helper.php b/system/helpers/smiley_helper.php index a2d1031b3..6d8889354 100644 --- a/system/helpers/smiley_helper.php +++ b/system/helpers/smiley_helper.php @@ -229,13 +229,13 @@ if ( ! function_exists('_get_smiley_array')) { function _get_smiley_array() { - if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/smileys'.EXT)) + if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/smileys.php')) { - include(APPPATH.'config/'.ENVIRONMENT.'/smileys'.EXT); + include(APPPATH.'config/'.ENVIRONMENT.'/smileys.php'); } - elseif (file_exists(APPPATH.'config/smileys'.EXT)) + elseif (file_exists(APPPATH.'config/smileys.php')) { - include(APPPATH.'config/smileys'.EXT); + include(APPPATH.'config/smileys.php'); } if (isset($smileys) AND is_array($smileys)) diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php index cca093976..33d7fa2fd 100644 --- a/system/helpers/text_helper.php +++ b/system/helpers/text_helper.php @@ -366,13 +366,13 @@ if ( ! function_exists('convert_accented_characters')) { function convert_accented_characters($str) { - if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars'.EXT)) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php')) { - include(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars'.EXT); + include(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php'); } - elseif (is_file(APPPATH.'config/foreign_chars'.EXT)) + elseif (is_file(APPPATH.'config/foreign_chars.php')) { - include(APPPATH.'config/foreign_chars'.EXT); + include(APPPATH.'config/foreign_chars.php'); } if ( ! isset($foreign_characters)) diff --git a/system/libraries/Calendar.php b/system/libraries/Calendar.php index 72d228e73..df0fd6eeb 100644 --- a/system/libraries/Calendar.php +++ b/system/libraries/Calendar.php @@ -47,7 +47,7 @@ class CI_Calendar { { $this->CI =& get_instance(); - if ( ! in_array('calendar_lang'.EXT, $this->CI->lang->is_loaded, TRUE)) + if ( ! in_array('calendar_lang.php', $this->CI->lang->is_loaded, TRUE)) { $this->CI->lang->load('calendar'); } diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php index b942f539f..d1925c0ec 100644 --- a/system/libraries/Driver.php +++ b/system/libraries/Driver.php @@ -59,7 +59,7 @@ class CI_Driver_Library { // loves me some nesting! foreach (array(ucfirst($driver_name), $driver_name) as $class) { - $filepath = $path.'libraries/'.$lib_name.'/drivers/'.$class.EXT; + $filepath = $path.'libraries/'.$lib_name.'/drivers/'.$class.'.php'; if (file_exists($filepath)) { diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php index e5f65878a..b30a8cf0b 100644 --- a/system/libraries/Encrypt.php +++ b/system/libraries/Encrypt.php @@ -524,7 +524,7 @@ class CI_Encrypt { { if ( ! function_exists('mhash')) { - require_once(BASEPATH.'libraries/Sha1'.EXT); + require_once(BASEPATH.'libraries/Sha1.php'); $SH = new CI_SHA; return $SH->generate($str); } diff --git a/system/libraries/Log.php b/system/libraries/Log.php index fb2c5a49b..9f1db76ba 100644 --- a/system/libraries/Log.php +++ b/system/libraries/Log.php @@ -83,7 +83,7 @@ class CI_Log { return FALSE; } - $filepath = $this->_log_path.'log-'.date('Y-m-d').EXT; + $filepath = $this->_log_path.'log-'.date('Y-m-d').'.php'; $message = ''; if ( ! file_exists($filepath)) diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php index e80049fa4..3177424c4 100644 --- a/system/libraries/Upload.php +++ b/system/libraries/Upload.php @@ -945,13 +945,13 @@ class CI_Upload { if (count($this->mimes) == 0) { - if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT)) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) { - include(APPPATH.'config/'.ENVIRONMENT.'/mimes'.EXT); + include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'); } - elseif (is_file(APPPATH.'config/mimes'.EXT)) + elseif (is_file(APPPATH.'config/mimes.php')) { - include(APPPATH.'config//mimes'.EXT); + include(APPPATH.'config//mimes.php'); } else { diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php index 04cda7312..016102a2a 100644 --- a/system/libraries/User_agent.php +++ b/system/libraries/User_agent.php @@ -84,13 +84,13 @@ class CI_User_agent { */ private function _load_agent_file() { - if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/user_agents'.EXT)) + if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php')) { - include(APPPATH.'config/'.ENVIRONMENT.'/user_agents'.EXT); + include(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php'); } - elseif (is_file(APPPATH.'config/user_agents'.EXT)) + elseif (is_file(APPPATH.'config/user_agents.php')) { - include(APPPATH.'config/user_agents'.EXT); + include(APPPATH.'config/user_agents.php'); } else { diff --git a/user_guide/changelog.html b/user_guide/changelog.html index 9890f602c..945b10497 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -66,6 +66,7 @@ Change Log
        • General Changes
          • Added Session Class userdata to the output profiler. Additionally, added a show/hide toggle on HTTP Headers, Session Data and Config Variables.
          • +
          • Removed internal usage of the EXT constant.
        • Helpers diff --git a/user_guide/installation/upgrade_203.html b/user_guide/installation/upgrade_203.html new file mode 100644 index 000000000..4937cf257 --- /dev/null +++ b/user_guide/installation/upgrade_203.html @@ -0,0 +1,102 @@ + + + + + +Upgrading from 2.0.2 to 2.0.3 : CodeIgniter User Guide + + + + + + + + + + + + + + + + + + + + + +
          + + + + + +

          CodeIgniter User Guide Version 2.0.3

          +
          + + + + + + + + + +
          + + +
          + + + +
          + +

          Upgrading from 2.0.2 to 2.0.3

          + +

          Before performing an update you should take your site offline by replacing the index.php file with a static one.

          + + +

          Step 1: Update your CodeIgniter files

          + +

          Replace all files and directories in your "system" folder and replace your index.php file. If any modifications were made to your index.php they will need to be made fresh in this new one.

          + +

          Note: If you have any custom developed files in these folders please make copies of them first.

          + +

          Step 2: Update CodeIgniter files

          + +

          Replace the files and directories in your "system" folder with the new versions:

          + +

          Step 3: Update your main index.php file

          + +

          If you are running a stock index.php file simply replace your version with the new one.

          + +

          If your index.php file has internal modifications, please add your modifications to the new file and use it.

          + +

          Step 4: Replace config/user_agents.php

          + +

          This config file has been updated to contain more user agent types, please copy it to application/config/user_agents.php.

          + +

          Step 5: Change references of the EXT constant to ".php"

          +

          Note: The EXT Constant has been marked as deprecated, but has not been removed from the application. You are encouraged to make the changes sooner rather than later.

          + +
          + + + + + + + \ No newline at end of file diff --git a/user_guide/installation/upgrading.html b/user_guide/installation/upgrading.html index 1c4eb882d..014ffa3f3 100644 --- a/user_guide/installation/upgrading.html +++ b/user_guide/installation/upgrading.html @@ -60,6 +60,7 @@ Upgrading from a Previous Version

          Please read the upgrade notes corresponding to the version you are upgrading from.

            +
          • Upgrading from 2.0.2 to 2.0.3
          • Upgrading from 2.0.1 to 2.0.2
          • Upgrading from 2.0 to 2.0.1
          • Upgrading from 1.7.2 to 2.0
          • -- cgit v1.2.3-24-g4f1b From 9ce4385cfc976e309ee12c53726abfd4f066ac3f Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Tue, 19 Apr 2011 12:58:52 -0500 Subject: 1/2 reverting a previous change to the form_helper. Wrapping hidden form elements in
            instead of an empty div. If a user is styling form div {} they can run into display issues, so something is needed. --- system/helpers/form_helper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php index bca0ff0c9..a5cd97b82 100644 --- a/system/helpers/form_helper.php +++ b/system/helpers/form_helper.php @@ -72,7 +72,7 @@ if ( ! function_exists('form_open')) if (is_array($hidden) AND count($hidden) > 0) { - $form .= sprintf("\n
            %s
            ", form_hidden($hidden)); + $form .= sprintf("
            %s
            ", form_hidden($hidden)); } return $form; -- cgit v1.2.3-24-g4f1b From 4488538665d37b07a08d7fe4ce6f4156a9899211 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Tue, 19 Apr 2011 15:28:40 -0500 Subject: Removed APPPATH.'third_party' from the packages autoloader to negate needless file stats if no packages exist or if the developer does not load any other packages by default. --- application/config/autoload.php | 2 +- user_guide/changelog.html | 1 + user_guide/installation/upgrade_203.html | 12 ++++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/application/config/autoload.php b/application/config/autoload.php index 90b1a808f..53129c9c6 100644 --- a/application/config/autoload.php +++ b/application/config/autoload.php @@ -37,7 +37,7 @@ | */ -$autoload['packages'] = array(APPPATH.'third_party'); +$autoload['packages'] = array(); /* diff --git a/user_guide/changelog.html b/user_guide/changelog.html index 945b10497..3a17edd90 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -80,6 +80,7 @@ Change Log
            • Added ENVIRONMENT to reserved constants. (Reactor #196)
            • Changed server check to ensure SCRIPT_NAME is defined. (Reactor #57)
            • +
            • Removed APPPATH.'third_party' from the packages autoloader to negate needless file stats if no packages exist or if the developer does not load any other packages by default.

            Version 2.0.2

            diff --git a/user_guide/installation/upgrade_203.html b/user_guide/installation/upgrade_203.html index 4937cf257..38cfb72c9 100644 --- a/user_guide/installation/upgrade_203.html +++ b/user_guide/installation/upgrade_203.html @@ -83,6 +83,18 @@ Upgrading from 2.0.2 to 2.0.3

            Step 5: Change references of the EXT constant to ".php"

            Note: The EXT Constant has been marked as deprecated, but has not been removed from the application. You are encouraged to make the changes sooner rather than later.

            +

            Step 6: Remove APPPATH.'third_party' from autoload.php

            + +

            Open application/autoload.php, and look for the following:

            + +$autoload['packages'] = array(APPPATH.'third_party'); + +

            If you have not chosen to load any additional packages, that line can be changed to:

            +$autoload['packages'] = array(); + +

            Which should provide for nominal performance gains if not autoloading packages.

            + + -- cgit v1.2.3-24-g4f1b From 6ae70cc8499499b5d77d77ec8974f95873edb861 Mon Sep 17 00:00:00 2001 From: Derek Jones Date: Tue, 19 Apr 2011 16:13:48 -0500 Subject: modified MySQL and MySQLi drivers to address a potential SQL injection attack vector when multi-byte character set connections are employed. (Does not impact Latin-1, UTF-8, etc. encodings) --- application/config/database.php | 6 ++++++ system/database/drivers/mysql/mysql_driver.php | 17 ++++++++++++++++- system/database/drivers/mysqli/mysqli_driver.php | 17 ++++++++++++++++- user_guide/changelog.html | 4 ++++ user_guide/database/configuration.html | 2 +- 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/application/config/database.php b/application/config/database.php index 24d611ac5..fa541a734 100644 --- a/application/config/database.php +++ b/application/config/database.php @@ -26,6 +26,12 @@ | ['cachedir'] The path to the folder where cache files should be stored | ['char_set'] The character set used in communicating with the database | ['dbcollat'] The character collation used in communicating with the database +| NOTE: For MySQL and MySQLi databases, this setting is only used +| as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7. +| There is an incompatibility in PHP with mysql_real_escape_string() which +| can make your site vulnerable to SQL injection if you are using a +| multi-byte character set and are running versions lower than these. +| Sites using Latin-1 or UTF-8 database character set and collation are unaffected. | ['swap_pre'] A default table prefix that should be swapped with the dbprefix | ['autoinit'] Whether or not to automatically initialize the database. | ['stricton'] TRUE/FALSE - forces 'Strict Mode' connections diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php index 4ff9b0a11..b7d547cc0 100644 --- a/system/database/drivers/mysql/mysql_driver.php +++ b/system/database/drivers/mysql/mysql_driver.php @@ -132,7 +132,22 @@ class CI_DB_mysql_driver extends CI_DB { */ function db_set_charset($charset, $collation) { - return @mysql_query("SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'", $this->conn_id); + static $use_set_names; + + if ( ! isset($use_set_names)) + { + // mysql_set_charset() requires PHP >= 5.2.3 and MySQL >= 5.0.7, use SET NAMES as fallback + $use_set_names = (version_compare(PHP_VERSION, '5.2.3', '>=') && version_compare(mysql_get_server_info(), '5.0.7', '>=')) ? FALSE : TRUE; + } + + if ($use_set_names) + { + return @mysql_query("SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'", $this->conn_id); + } + else + { + return @mysql_set_charset($charset, $this->conn_id); + } } // -------------------------------------------------------------------- diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php index ccdabce1a..1949acb6e 100644 --- a/system/database/drivers/mysqli/mysqli_driver.php +++ b/system/database/drivers/mysqli/mysqli_driver.php @@ -132,7 +132,22 @@ class CI_DB_mysqli_driver extends CI_DB { */ function _db_set_charset($charset, $collation) { - return @mysqli_query($this->conn_id, "SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'"); + static $use_set_names; + + if ( ! isset($use_set_names)) + { + // mysqli_set_charset() requires MySQL >= 5.0.7, use SET NAMES as fallback + $use_set_names = (version_compare(mysql_get_server_info(), '5.0.7', '>=')) ? FALSE : TRUE; + } + + if ($use_set_names) + { + return @mysqli_query($this->conn_id, "SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'"); + } + else + { + return @mysqli_set_charset($this->conn_id, $charset); + } } // -------------------------------------------------------------------- diff --git a/user_guide/changelog.html b/user_guide/changelog.html index 945b10497..6eb80b38e 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -63,6 +63,10 @@ Change Log

            Release Date: Not Released

              +
            • Security +
                +
              • An improvement was made to the MySQL and MySQLi drivers to prevent exposing a potential vector for SQL injection on sites using multi-byte character sets in the database client connection.

                An incompatibility in PHP versions < 5.2.3 and MySQL < 5.0.7 with mysql_set_charset() creates a situation where using multi-byte character sets on these environments may potentially expose a SQL injection attack vector. Latin-1, UTF-8, and other "low ASCII" character sets are unaffected on all environments.

                If you are running or considering running a multi-byte character set for your database connection, please pay close attention to the server environment you are deploying on to ensure you are not vulnerable.

              • +
            • General Changes
              • Added Session Class userdata to the output profiler. Additionally, added a show/hide toggle on HTTP Headers, Session Data and Config Variables.
              • diff --git a/user_guide/database/configuration.html b/user_guide/database/configuration.html index fdeae0ee2..51d11c9f2 100644 --- a/user_guide/database/configuration.html +++ b/user_guide/database/configuration.html @@ -132,7 +132,7 @@ for the primary connection, but it too can be renamed to something more relevant
              • cache_on - TRUE/FALSE (boolean) - Whether database query caching is enabled, see also Database Caching Class.
              • cachedir - The absolute server path to your database query cache directory.
              • char_set - The character set used in communicating with the database.
              • -
              • dbcollat - The character collation used in communicating with the database.
              • +
              • dbcollat - The character collation used in communicating with the database.

                Note: For MySQL and MySQLi databases, this setting is only used as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7. There is an incompatibility in PHP with mysql_real_escape_string() which can make your site vulnerable to SQL injection if you are using a multi-byte character set and are running versions lower than these. Sites using Latin-1 or UTF-8 database character set and collation are unaffected.

              • swap_pre - A default table prefix that should be swapped with dbprefix. This is useful for distributed applications where you might run manually written queries, and need the prefix to still be customizable by the end user.
              • autoinit - Whether or not to automatically connect to the database when the library loads. If set to false, the connection will take place prior to executing the first query.
              • stricton - TRUE/FALSE (boolean) - Whether to force "Strict Mode" connections, good for ensuring strict SQL while developing an application.
              • -- cgit v1.2.3-24-g4f1b From f5c840241084e03d49e521bfcb62d2adbe9fce7d Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Tue, 19 Apr 2011 17:13:03 -0500 Subject: Altering the loader to be able to load views from packages when adding the package path with add_package_path(). --- system/core/Controller.php | 2 +- system/core/Loader.php | 110 ++++++++++++++++++++++++--------------------- 2 files changed, 59 insertions(+), 53 deletions(-) diff --git a/system/core/Controller.php b/system/core/Controller.php index 469663f09..fd9c8b580 100644 --- a/system/core/Controller.php +++ b/system/core/Controller.php @@ -50,7 +50,7 @@ class CI_Controller { $this->load->_base_classes =& is_loaded(); - $this->load->_ci_autoloader(); + $this->load->ci_autoloader(); log_message('debug', "Controller Class Initialized"); diff --git a/system/core/Loader.php b/system/core/Loader.php index 59415b72a..8146cd563 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -30,8 +30,8 @@ class CI_Loader { // All these are set automatically. Don't mess with them. var $_ci_ob_level; - var $_ci_view_path = ''; - var $_ci_library_paths = array(); + var $_ci_view_paths = array(); + protected $_ci_library_paths = array(); var $_ci_model_paths = array(); var $_ci_helper_paths = array(); var $_base_classes = array(); // Set by the controller class @@ -47,17 +47,15 @@ class CI_Loader { * Constructor * * Sets the path to the view files and gets the initial output buffering level - * - * @access public */ - function __construct() + public function __construct() { - $this->_ci_view_path = APPPATH.'views/'; $this->_ci_ob_level = ob_get_level(); $this->_ci_library_paths = array(APPPATH, BASEPATH); $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"); } @@ -107,13 +105,12 @@ class CI_Loader { * * This function lets users load and instantiate models. * - * @access public * @param string the name of the class * @param string name for the model * @param bool database connection * @return void */ - function model($model, $name = '', $db_conn = FALSE) + public function model($model, $name = '', $db_conn = FALSE) { if (is_array($model)) { @@ -200,13 +197,12 @@ class CI_Loader { /** * Database Loader * - * @access public * @param string the DB credentials * @param bool whether to return the DB object * @param bool whether to enable active record (this allows us to override the config setting) * @return object */ - function database($params = '', $return = FALSE, $active_record = NULL) + public function database($params = '', $return = FALSE, $active_record = NULL) { // Grab the super object $CI =& get_instance(); @@ -237,10 +233,9 @@ class CI_Loader { /** * Load the Utilities Class * - * @access public * @return string */ - function dbutil() + public function dbutil() { if ( ! class_exists('CI_DB')) { @@ -265,10 +260,9 @@ class CI_Loader { /** * Load the Database Forge Class * - * @access public * @return string */ - function dbforge() + public function dbforge() { if ( ! class_exists('CI_DB')) { @@ -297,13 +291,12 @@ class CI_Loader { * some cases it's advantageous to be able to return data so that * a developer can process it in some way. * - * @access public * @param string * @param array * @param bool * @return void */ - function view($view, $vars = array(), $return = FALSE) + public function view($view, $vars = array(), $return = FALSE) { return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return)); } @@ -315,12 +308,11 @@ class CI_Loader { * * This is a generic file loader * - * @access public * @param string * @param bool * @return string */ - function file($path, $return = FALSE) + public function file($path, $return = FALSE) { return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return)); } @@ -333,11 +325,10 @@ class CI_Loader { * Once variables are set they become available within * the controller class and its "view" files. * - * @access public * @param array * @return void */ - function vars($vars = array(), $val = '') + public function vars($vars = array(), $val = '') { if ($val != '' AND is_string($vars)) { @@ -362,11 +353,10 @@ class CI_Loader { * * This function loads the specified helper file. * - * @access public * @param mixed * @return void */ - function helper($helpers = array()) + public function helper($helpers = array()) { foreach ($this->_ci_prep_filename($helpers, '_helper') as $helper) { @@ -424,11 +414,10 @@ class CI_Loader { * This is simply an alias to the above function in case the * user has written the plural form of this function. * - * @access public * @param array * @return void */ - function helpers($helpers = array()) + public function helpers($helpers = array()) { $this->helper($helpers); } @@ -438,12 +427,11 @@ class CI_Loader { /** * Loads a language file * - * @access public * @param array * @param string * @return void */ - function language($file = array(), $lang = '') + public function language($file = array(), $lang = '') { $CI =& get_instance(); @@ -463,11 +451,10 @@ class CI_Loader { /** * Loads a config file * - * @access public * @param string * @return void */ - function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) + public function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) { $CI =& get_instance(); $CI->config->load($file, $use_sections, $fail_gracefully); @@ -485,7 +472,7 @@ class CI_Loader { * @param string an optional object name * @return void */ - function driver($library = '', $params = NULL, $object_name = NULL) + public function driver($library = '', $params = NULL, $object_name = NULL) { if ( ! class_exists('CI_Driver_Library')) { @@ -510,18 +497,20 @@ class CI_Loader { * * Prepends a parent path to the library, model, helper, and config path arrays * - * @access public * @param string + * @param boolean * @return void */ - function add_package_path($path) + 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); + $this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths; + // Add config file path $config =& $this->_ci_get_component('config'); array_unshift($config->_config_paths, $path); @@ -534,11 +523,10 @@ class CI_Loader { * * Return a list of all package paths, by default it will ignore BASEPATH. * - * @access public * @param string * @return void */ - function get_package_paths($include_base = FALSE) + public function get_package_paths($include_base = FALSE) { return $include_base === TRUE ? $this->_ci_library_paths : $this->_ci_model_paths; } @@ -551,11 +539,10 @@ class CI_Loader { * Remove a path from the library, model, and helper path arrays if it exists * If no path is provided, the most recently added path is removed. * - * @access public * @param type * @return type */ - function remove_package_path($path = '', $remove_config_path = TRUE) + public function remove_package_path($path = '', $remove_config_path = TRUE) { $config =& $this->_ci_get_component('config'); @@ -564,12 +551,12 @@ class CI_Loader { $void = array_shift($this->_ci_library_paths); $void = array_shift($this->_ci_model_paths); $void = array_shift($this->_ci_helper_paths); + $void = array_shift($this->_ci_view_paths); $void = array_shift($config->_config_paths); } else { $path = rtrim($path, '/').'/'; - foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var) { if (($key = array_search($path, $this->{$var})) !== FALSE) @@ -577,6 +564,11 @@ class CI_Loader { unset($this->{$var}[$key]); } } + + if (isset($this->_ci_view_paths[$path.'views/'])) + { + unset($this->_ci_view_paths[$path.'views/']); + } if (($key = array_search($path, $config->_config_paths)) !== FALSE) { @@ -588,6 +580,7 @@ class CI_Loader { $this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH))); $this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH))); $this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH))); + $this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE)); $config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH))); } @@ -600,24 +593,39 @@ class CI_Loader { * Variables are prefixed with _ci_ to avoid symbol collision with * variables made available to view files * - * @access private * @param array * @return void */ - function _ci_load($_ci_data) + protected function _ci_load($_ci_data) { // Set the default data variables foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val) { $$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val]; } + + $file_exists = FALSE; // Set the path to the requested file if ($_ci_path == '') { $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION); $_ci_file = ($_ci_ext == '') ? $_ci_view.'.php' : $_ci_view; - $_ci_path = $this->_ci_view_path.$_ci_file; + + foreach ($this->_ci_view_paths as $view_file => $cascade) + { + if (file_exists($view_file.$_ci_file)) + { + $_ci_path = $view_file.$_ci_file; + $file_exists = TRUE; + break; + } + + if ( ! $cascade) + { + break; + } + } } else { @@ -625,7 +633,7 @@ class CI_Loader { $_ci_file = end($_ci_x); } - if ( ! file_exists($_ci_path)) + if ( ! $file_exists && ! file_exists($_ci_path)) { show_error('Unable to load the requested file: '.$_ci_file); } @@ -721,13 +729,12 @@ class CI_Loader { * * This function loads the requested class. * - * @access private * @param string the item that is being loaded * @param mixed any additional parameters * @param string an optional object name * @return void */ - function _ci_load_class($class, $params = NULL, $object_name = NULL) + protected function _ci_load_class($class, $params = NULL, $object_name = NULL) { // Get the class name, and while we're at it trim any slashes. // The directory path can be included as part of the class name, @@ -959,11 +966,13 @@ class CI_Loader { * The config/autoload.php file contains an array that permits sub-systems, * libraries, and helpers to be loaded automatically. * - * @access private + * 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 */ - function _ci_autoloader() + public function ci_autoloader() { if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php')) { @@ -1046,11 +1055,10 @@ class CI_Loader { * * Takes an object as input and converts the class variables to array key/vals * - * @access private * @param object * @return array */ - function _ci_object_to_array($object) + protected function _ci_object_to_array($object) { return (is_object($object)) ? get_object_vars($object) : $object; } @@ -1060,10 +1068,9 @@ class CI_Loader { /** * Get a reference to a specific library or model * - * @access private * @return bool */ - function &_ci_get_component($component) + protected function &_ci_get_component($component) { $CI =& get_instance(); return $CI->$component; @@ -1076,11 +1083,10 @@ class CI_Loader { * * This function preps the name of various items to make loading them more reliable. * - * @access private * @param mixed * @return array */ - function _ci_prep_filename($filename, $extension) + protected function _ci_prep_filename($filename, $extension) { if ( ! is_array($filename)) { -- cgit v1.2.3-24-g4f1b From b3e614d8b2293c079bcfb9cfdf071c041cbc4722 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Tue, 19 Apr 2011 20:19:17 -0500 Subject: Change in core/Security.php to match coding standards. --- system/core/Security.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/core/Security.php b/system/core/Security.php index 4f91572ed..3617cadcc 100644 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -68,7 +68,8 @@ class CI_Security { } // Append application specific cookie prefix - if (config_item('cookie_prefix')) { + if (config_item('cookie_prefix')) + { $this->_csrf_cookie_name = config_item('cookie_prefix').$this->_csrf_cookie_name; } -- cgit v1.2.3-24-g4f1b From 0c9ee4a348a9e0c9ee6d6c0085e463e098e453f4 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Wed, 20 Apr 2011 09:40:17 -0500 Subject: Refactoring the loader to set protected class variables. Moved _ci_autoload(), which is used in CI_Controller to be a public method. Also added CI_Loader::set_base_classes() to be called in the controller so we're not setting protected vars in another class. Also refactored in the form_helper so it's not trying to access protected vars in CI_Loader. Added the is_loaded() method to the loader to take care of the checks that were being done there. --- system/core/Controller.php | 7 ++-- system/core/Loader.php | 75 +++++++++++++++++++++++++++++++----------- system/helpers/form_helper.php | 24 +++++++------- 3 files changed, 69 insertions(+), 37 deletions(-) diff --git a/system/core/Controller.php b/system/core/Controller.php index fd9c8b580..ec86b7920 100644 --- a/system/core/Controller.php +++ b/system/core/Controller.php @@ -48,12 +48,9 @@ class CI_Controller { $this->load =& load_class('Loader', 'core'); - $this->load->_base_classes =& is_loaded(); - - $this->load->ci_autoloader(); - + $this->load->set_base_classes()->ci_autoloader(); + log_message('debug', "Controller Class Initialized"); - } public static function &get_instance() diff --git a/system/core/Loader.php b/system/core/Loader.php index 8146cd563..a52ef288a 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -29,19 +29,19 @@ class CI_Loader { // All these are set automatically. Don't mess with them. - var $_ci_ob_level; - var $_ci_view_paths = array(); + protected $_ci_ob_level; + protected $_ci_view_paths = array(); protected $_ci_library_paths = array(); - var $_ci_model_paths = array(); - var $_ci_helper_paths = array(); - var $_base_classes = array(); // Set by the controller class - var $_ci_cached_vars = array(); - var $_ci_classes = array(); - var $_ci_loaded_files = array(); - var $_ci_models = array(); - var $_ci_helpers = array(); - var $_ci_varmap = array('unit_test' => 'unit', 'user_agent' => 'agent'); - + protected $_ci_model_paths = array(); + protected $_ci_helper_paths = array(); + protected $_base_classes = array(); // Set by the controller class + protected $_ci_cached_vars = array(); + protected $_ci_classes = array(); + protected $_ci_loaded_files = array(); + protected $_ci_models = array(); + protected $_ci_helpers = array(); + protected $_ci_varmap = array('unit_test' => 'unit', + 'user_agent' => 'agent'); /** * Constructor @@ -59,6 +59,47 @@ class CI_Loader { log_message('debug', "Loader Class Initialized"); } + // -------------------------------------------------------------------- + + /** + * Set _base_classes variable + * + * This method is called once in CI_Controller. + * + * @param array + * @return object + */ + public function set_base_classes() + { + $this->_base_classes =& is_loaded(); + + return $this; + } + + // -------------------------------------------------------------------- + + /** + * Is Loaded + * + * A utility function to test if a class is in the self::$_ci_classes array. + * This function returns the object name if the class tested for is loaded, + * and returns FALSE if it isn't. + * + * It is mainly used in the form_helper -> _get_validation_object() + * + * @param string class being checked for + * @return mixed class object name on the CI SuperObject or FALSE + */ + public function is_loaded($class) + { + if (isset($this->_ci_classes[$class])) + { + return $this->_ci_classes[$class]; + } + + return FALSE; + } + // -------------------------------------------------------------------- /** @@ -67,13 +108,12 @@ class CI_Loader { * This function lets users load and instantiate classes. * It is designed to be called from a user's app controllers. * - * @access public * @param string the name of the class * @param mixed the optional parameters * @param string an optional object name * @return void */ - function library($library = '', $params = NULL, $object_name = NULL) + public function library($library = '', $params = NULL, $object_name = NULL) { if (is_array($library)) { @@ -856,13 +896,12 @@ class CI_Loader { /** * Instantiates a class * - * @access private * @param string * @param string * @param string an optional object name * @return null */ - function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL) + protected function _ci_init_class($class, $prefix = '', $config = FALSE, $object_name = NULL) { // Is there an associated config file for this class? Note: these should always be lowercase if ($config === NULL) @@ -1102,9 +1141,7 @@ class CI_Loader { return $filename; } } - - } /* End of file Loader.php */ -/* Location: ./system/core/Loader.php */ +/* Location: ./system/core/Loader.php */ \ No newline at end of file diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php index a5cd97b82..51a9c6ca3 100644 --- a/system/helpers/form_helper.php +++ b/system/helpers/form_helper.php @@ -1032,22 +1032,20 @@ if ( ! function_exists('_get_validation_object')) { $CI =& get_instance(); - // We set this as a variable since we're returning by reference + // We set this as a variable since we're returning by reference. $return = FALSE; - - if ( ! isset($CI->load->_ci_classes) OR ! isset($CI->load->_ci_classes['form_validation'])) - { - return $return; - } - - $object = $CI->load->_ci_classes['form_validation']; - - if ( ! isset($CI->$object) OR ! is_object($CI->$object)) + + if ( ! ($object = $CI->load->is_loaded('form_validation'))) { - return $return; + if ( ! isset($CI->$object) OR ! is_object($CI->$object)) + { + return $return; + } + + return $CI->$object; } - - return $CI->$object; + + return $return; } } -- cgit v1.2.3-24-g4f1b From e08c527aa0a8a05836b05763d859eb3d2970f62f Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Wed, 20 Apr 2011 09:54:47 -0500 Subject: Updating Documentation on package view loading --- user_guide/libraries/loader.html | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/user_guide/libraries/loader.html b/user_guide/libraries/loader.html index 42f8cf94f..1d93af5ed 100644 --- a/user_guide/libraries/loader.html +++ b/user_guide/libraries/loader.html @@ -231,17 +231,22 @@ $this->load->library('foo_bar');

                Package view files

                -

                @todo - package view file interface is not complete. It can be experimentally used by first saving the Loader's original view path, setting the view path to the package's view path, and when finished, setting back to the original view path.

                - -// ... save the original view path, and set to our Foo Bar package view folder
                -$orig_view_path = $this->load->_ci_view_path;
                -$this->load->_ci_view_path = APPPATH.'third_party/foo_bar/views/';
                -
                -// ... code using the package's view files
                -
                -// ... then return the view path to the application's original view path
                -$this->load->_ci_view_path = $orig_view_path;
                +

                By Default, package view files paths are set when add_package_path() is called. View paths are looped through, and once a match is encountered that view is loaded.

                +

                In this instance, it is possible for view naming collisions within packages to occur, and possibly the incorrect package being loaded. To ensure against this, set an optional second parameter of FALSE when calling add_package_path().

                + +$this->load->add_package_path(APPPATH.'my_app', TRUE);
                +$this->load->view('my_app_index'); // Loads
                +$this->load->view('welcome_message'); // Will not load the default welcome_message b/c the second param to add_package_path is TRUE
                +
                +// Reset things
                +$this->load->remove_package_path(APPPATH.'my_app');
                +
                +// Again without the second parameter:
                +$this->load->add_package_path(APPPATH.'my_app', TRUE);
                +$this->load->view('my_app_index'); // Loads
                +$this->load->view('welcome_message'); // Loads
                +
                -- cgit v1.2.3-24-g4f1b From 1cdb0fd21e0c5ac38a75712806ed10b08f0909cc Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Wed, 20 Apr 2011 11:11:47 -0500 Subject: Visual updates to the welcome_message view file and default error templates. Thanks to danijelb for the pull request. --- application/errors/error_404.php | 58 +++++++++++++----- application/errors/error_db.php | 58 +++++++++++++----- application/errors/error_general.php | 58 +++++++++++++----- application/views/welcome_message.php | 108 +++++++++++++++++++++------------- user_guide/changelog.html | 1 + 5 files changed, 196 insertions(+), 87 deletions(-) diff --git a/application/errors/error_404.php b/application/errors/error_404.php index a304f4561..792726a67 100644 --- a/application/errors/error_404.php +++ b/application/errors/error_404.php @@ -1,32 +1,60 @@ - + + 404 Page Not Found -
                +

                diff --git a/application/errors/error_db.php b/application/errors/error_db.php index 181de960b..b396cda9f 100644 --- a/application/errors/error_db.php +++ b/application/errors/error_db.php @@ -1,32 +1,60 @@ - + + Database Error -
                +

                diff --git a/application/errors/error_general.php b/application/errors/error_general.php index 7734d34c7..fd63ce2c5 100644 --- a/application/errors/error_general.php +++ b/application/errors/error_general.php @@ -1,32 +1,60 @@ - + + Error -
                +

                diff --git a/application/views/welcome_message.php b/application/views/welcome_message.php index ca68fc101..0bf5a8d2e 100644 --- a/application/views/welcome_message.php +++ b/application/views/welcome_message.php @@ -4,61 +4,85 @@ Welcome to CodeIgniter - + code { + font-family: Consolas, Monaco, Courier New, Courier, monospace; + font-size: 12px; + background-color: #f9f9f9; + border: 1px solid #D0D0D0; + color: #002166; + display: block; + margin: 14px 0 14px 0; + padding: 12px 10px 12px 10px; + } + + #body{ + margin: 0 15px 0 15px; + } + + p.footer{ + text-align: right; + font-size: 11px; + border-top: 1px solid #D0D0D0; + line-height: 32px; + padding: 0 10px 0 10px; + margin: 20px 0 0 0; + } + + #container{ + margin: 10px; + border: 1px solid #D0D0D0; + -webkit-box-shadow: 0 0 8px #D0D0D0; + } + -

                Welcome to CodeIgniter!

                - -

                The page you are looking at is being generated dynamically by CodeIgniter.

                +
                +

                Welcome to CodeIgniter!

                -

                If you would like to edit this page you'll find it located at:

                -application/views/welcome_message.php +
                +

                The page you are looking at is being generated dynamically by CodeIgniter.

                -

                The corresponding controller for this page is found at:

                -application/controllers/welcome.php +

                If you would like to edit this page you'll find it located at:

                + application/views/welcome_message.php -

                If you are exploring CodeIgniter for the very first time, you should start by reading the User Guide.

                +

                The corresponding controller for this page is found at:

                + application/controllers/welcome.php +

                If you are exploring CodeIgniter for the very first time, you should start by reading the User Guide.

                +
                -


                Page rendered in {elapsed_time} seconds

                + +
                \ No newline at end of file diff --git a/user_guide/changelog.html b/user_guide/changelog.html index b889152ad..bbdbbbd19 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -71,6 +71,7 @@ Change Log
                • Added Session Class userdata to the output profiler. Additionally, added a show/hide toggle on HTTP Headers, Session Data and Config Variables.
                • Removed internal usage of the EXT constant.
                • +
                • Visual updates to the welcome_message view file and default error templates. Thanks to danijelb for the pull request.
              • Helpers -- cgit v1.2.3-24-g4f1b From 882b76bda8b701a8718960b8d639f060ae79e998 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Wed, 20 Apr 2011 11:22:09 -0500 Subject: Fixed a bug (Reactor #231) where Sessions Library database table example SQL did not contain an index on last_activity. See Upgrade Notes Fixed a bug (Reactor #229) where the Sessions Library example SQL in the documentation contained incorrect SQL. --- user_guide/changelog.html | 4 +++- user_guide/installation/upgrade_203.html | 10 ++++++++++ user_guide/libraries/sessions.html | 18 ++++++++++-------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/user_guide/changelog.html b/user_guide/changelog.html index bbdbbbd19..70db33d48 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -78,7 +78,7 @@ Change Log
                • Added an optional third parameter to heading() which allows adding html attributes to the rendered heading tag.
                -
              • +

              Bug fixes for 2.0.3

              @@ -86,6 +86,8 @@ Change Log
            • Added ENVIRONMENT to reserved constants. (Reactor #196)
            • Changed server check to ensure SCRIPT_NAME is defined. (Reactor #57)
            • Removed APPPATH.'third_party' from the packages autoloader to negate needless file stats if no packages exist or if the developer does not load any other packages by default.
            • +
            • Fixed a bug (Reactor #231) where Sessions Library database table example SQL did not contain an index on last_activity. See Upgrade Notes.
            • +
            • Fixed a bug (Reactor #229) where the Sessions Library example SQL in the documentation contained incorrect SQL.

            Version 2.0.2

            diff --git a/user_guide/installation/upgrade_203.html b/user_guide/installation/upgrade_203.html index 38cfb72c9..d7c0fae3a 100644 --- a/user_guide/installation/upgrade_203.html +++ b/user_guide/installation/upgrade_203.html @@ -94,6 +94,16 @@ Upgrading from 2.0.2 to 2.0.3

            Which should provide for nominal performance gains if not autoloading packages.

            +

            Update Sessions Database Tables

            + +

            If you are using database sessions with the CI Session Library, please update your ci_sessions database table as follows:

            + + + CREATE INDEX last_activity_idx ON ci_sessions(last_activity); + + + + diff --git a/user_guide/libraries/sessions.html b/user_guide/libraries/sessions.html index 8d9c14eb6..6048f4809 100644 --- a/user_guide/libraries/sessions.html +++ b/user_guide/libraries/sessions.html @@ -218,15 +218,17 @@ be updated, they can only be generated when a new session is created.

            In order to store sessions, you must first create a database table for this purpose. Here is the basic prototype (for MySQL) required by the session class:

            - + session_id varchar(40) DEFAULT '0' NOT NULL, + ip_address varchar(16) DEFAULT '0' NOT NULL, + user_agent varchar(50) NOT NULL, + last_activity int(10) unsigned DEFAULT 0 NOT NULL, + user_data text NOT NULL, + PRIMARY KEY (session_id), + KEY `last_activity_idx` (`last_activity`) +); +

            Note: By default the table is called ci_sessions, but you can name it anything you want as long as you update the application/config/config.php file so that it contains the name you have chosen. -- cgit v1.2.3-24-g4f1b From 50671cf8d67c805692fec49eda33d21227a21ec2 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Wed, 20 Apr 2011 11:36:45 -0500 Subject: Altered Session to use a longer match against the user_agent string. See upgrade notes if using database sessions.sess_match_useragent == TRUE AND trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 50))) + if ($this->sess_match_useragent == TRUE AND trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 120))) { $this->sess_destroy(); return FALSE; @@ -316,7 +316,7 @@ class CI_Session { $this->userdata = array( 'session_id' => md5(uniqid($sessid, TRUE)), 'ip_address' => $this->CI->input->ip_address(), - 'user_agent' => substr($this->CI->input->user_agent(), 0, 50), + 'user_agent' => substr($this->CI->input->user_agent(), 0, 120), 'last_activity' => $this->now ); diff --git a/user_guide/changelog.html b/user_guide/changelog.html index 70db33d48..7ff71d07a 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -79,6 +79,11 @@ Change Log

          • Added an optional third parameter to heading() which allows adding html attributes to the rendered heading tag.
        • +
        • Libraries +
            +
          • Altered Session to use a longer match against the user_agent string. See upgrade notes if using database sessions.
          • +
          +

        Bug fixes for 2.0.3

        diff --git a/user_guide/installation/upgrade_203.html b/user_guide/installation/upgrade_203.html index d7c0fae3a..7dbc907ea 100644 --- a/user_guide/installation/upgrade_203.html +++ b/user_guide/installation/upgrade_203.html @@ -98,8 +98,9 @@ Upgrading from 2.0.2 to 2.0.3

        If you are using database sessions with the CI Session Library, please update your ci_sessions database table as follows:

        - + CREATE INDEX last_activity_idx ON ci_sessions(last_activity); + ALTER TABLE ci_sessions MODIFY user_agent VARCHAR(120); diff --git a/user_guide/libraries/sessions.html b/user_guide/libraries/sessions.html index 6048f4809..a6f3c601c 100644 --- a/user_guide/libraries/sessions.html +++ b/user_guide/libraries/sessions.html @@ -222,7 +222,7 @@ prototype (for MySQL) required by the session class:

        CREATE TABLE IF NOT EXISTS `ci_sessions` ( session_id varchar(40) DEFAULT '0' NOT NULL, ip_address varchar(16) DEFAULT '0' NOT NULL, - user_agent varchar(50) NOT NULL, + user_agent varchar(120) NOT NULL, last_activity int(10) unsigned DEFAULT 0 NOT NULL, user_data text NOT NULL, PRIMARY KEY (session_id), -- cgit v1.2.3-24-g4f1b From fc779cef54a5cefc3f0d7f404a408a935d717966 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Wed, 20 Apr 2011 12:25:17 -0500 Subject: Fix #224 Error in primary index.php $routing instructions --- index.php | 2 +- user_guide/changelog.html | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index a8d58b2d9..f4ac11a72 100644 --- a/index.php +++ b/index.php @@ -98,7 +98,7 @@ if (defined('ENVIRONMENT')) // if your controller is not in a sub-folder within the "controllers" folder // $routing['directory'] = ''; - // The controller class file name. Example: Mycontroller.php + // The controller class file name. Example: Mycontroller // $routing['controller'] = ''; // The controller function you wish to be called. diff --git a/user_guide/changelog.html b/user_guide/changelog.html index 7ff71d07a..7ad566733 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -69,6 +69,7 @@ Change Log
    • General Changes
        +
      • Fixed a bug where there was a misspelling within a code comment in the index.php file.
      • Added Session Class userdata to the output profiler. Additionally, added a show/hide toggle on HTTP Headers, Session Data and Config Variables.
      • Removed internal usage of the EXT constant.
      • Visual updates to the welcome_message view file and default error templates. Thanks to danijelb for the pull request.
      • -- cgit v1.2.3-24-g4f1b From e5c8812f4165bf145e550a2f4c0354685c5bdb74 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Wed, 20 Apr 2011 12:33:11 -0500 Subject: Fixing download links for reactor -- thanks kenjis for the patch --- user_guide/installation/downloads.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide/installation/downloads.html b/user_guide/installation/downloads.html index 54fff5a28..f452ba471 100644 --- a/user_guide/installation/downloads.html +++ b/user_guide/installation/downloads.html @@ -59,8 +59,8 @@ Downloading CodeIgniter
        • CodeIgniter V 2.0.2 (Current version)
        • -
        • CodeIgniter V 2.0.1
        • -
        • CodeIgniter V 2.0.0
        • +
        • CodeIgniter V 2.0.1
        • +
        • CodeIgniter V 2.0.0
        • CodeIgniter V 1.7.3
        • CodeIgniter V 1.7.2
        • CodeIgniter V 1.7.1
        • -- cgit v1.2.3-24-g4f1b From e156c6eb4a018a91d3cfcaa2d1fd3b3e67dc2808 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Wed, 20 Apr 2011 16:03:04 -0500 Subject: Fixed a bug (Core #340) where when passing in the second parameter to $this->db->select(), column names in subsequent queries would not be properly escaped. --- system/database/DB_active_rec.php | 20 ++++++++------------ user_guide/changelog.html | 1 + 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php index db8471364..9ceac0b76 100644 --- a/system/database/DB_active_rec.php +++ b/system/database/DB_active_rec.php @@ -58,6 +58,8 @@ class CI_DB_active_record extends CI_DB_driver { var $ar_cache_having = array(); var $ar_cache_orderby = array(); var $ar_cache_set = array(); + + var $ar_no_escape = array(); // -------------------------------------------------------------------- @@ -73,12 +75,6 @@ class CI_DB_active_record extends CI_DB_driver { */ function select($select = '*', $escape = NULL) { - // Set the global value if this was sepecified - if (is_bool($escape)) - { - $this->_protect_identifiers = $escape; - } - if (is_string($select)) { $select = explode(',', $select); @@ -91,6 +87,7 @@ class CI_DB_active_record extends CI_DB_driver { if ($val != '') { $this->ar_select[] = $val; + $this->ar_no_escape[] = $escape; if ($this->ar_caching === TRUE) { @@ -441,10 +438,10 @@ class CI_DB_active_record extends CI_DB_driver { $v = ' '.$this->escape($v); } - + if ( ! $this->_has_operator($k)) { - $k .= ' ='; + $k .= ' = '; } } else @@ -1718,7 +1715,7 @@ class CI_DB_active_record extends CI_DB_driver { // is because until the user calls the from() function we don't know if there are aliases foreach ($this->ar_select as $key => $val) { - $this->ar_select[$key] = $this->_protect_identifiers($val); + $this->ar_select[$key] = $this->_protect_identifiers($val, FALSE, $this->ar_no_escape[$key]); } $sql .= implode(', ', $this->ar_select); @@ -1753,9 +1750,7 @@ class CI_DB_active_record extends CI_DB_driver { if (count($this->ar_where) > 0 OR count($this->ar_like) > 0) { - $sql .= "\n"; - - $sql .= "WHERE "; + $sql .= "\nWHERE "; } $sql .= implode("\n", $this->ar_where); @@ -2032,6 +2027,7 @@ class CI_DB_active_record extends CI_DB_driver { 'ar_orderby' => array(), 'ar_wherein' => array(), 'ar_aliased_tables' => array(), + 'ar_no_escape' => array(), 'ar_distinct' => FALSE, 'ar_limit' => FALSE, 'ar_offset' => FALSE, diff --git a/user_guide/changelog.html b/user_guide/changelog.html index 7ad566733..76f9e5dd9 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -94,6 +94,7 @@ Change Log
        • Removed APPPATH.'third_party' from the packages autoloader to negate needless file stats if no packages exist or if the developer does not load any other packages by default.
        • Fixed a bug (Reactor #231) where Sessions Library database table example SQL did not contain an index on last_activity. See Upgrade Notes.
        • Fixed a bug (Reactor #229) where the Sessions Library example SQL in the documentation contained incorrect SQL.
        • +
        • Fixed a bug (Core #340) where when passing in the second parameter to $this->db->select(), column names in subsequent queries would not be properly escaped.

        Version 2.0.2

        -- cgit v1.2.3-24-g4f1b From 8807be35fe02a39624e62a412889e938b6a37691 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Thu, 21 Apr 2011 13:06:15 -0500 Subject: Flipping around contents of a conditional in _ci_load() so the small bits are on top. --- system/core/Loader.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/system/core/Loader.php b/system/core/Loader.php index a52ef288a..721c196cc 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -647,7 +647,12 @@ class CI_Loader { $file_exists = FALSE; // Set the path to the requested file - if ($_ci_path == '') + if ($_ci_path != '') + { + $_ci_x = explode('/', $_ci_path); + $_ci_file = end($_ci_x); + } + else { $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION); $_ci_file = ($_ci_ext == '') ? $_ci_view.'.php' : $_ci_view; @@ -667,11 +672,6 @@ class CI_Loader { } } } - else - { - $_ci_x = explode('/', $_ci_path); - $_ci_file = end($_ci_x); - } if ( ! $file_exists && ! file_exists($_ci_path)) { -- cgit v1.2.3-24-g4f1b From 1d3021a26e3d542137ceddc6c0f4a08a4f80a096 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Thu, 21 Apr 2011 15:19:17 -0500 Subject: Fix #235 error in form_helper docs. --- user_guide/helpers/form_helper.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide/helpers/form_helper.html b/user_guide/helpers/form_helper.html index f82c669ca..87e3c28b0 100644 --- a/user_guide/helpers/form_helper.html +++ b/user_guide/helpers/form_helper.html @@ -281,7 +281,7 @@ echo form_fieldset_close();
        which will be added below the tag. For example:

        $string = "</div></div>";

        -echo fieldset_close($string);
        +echo form_fieldset_close($string);

        // Would produce:
        </fieldset>
        -- cgit v1.2.3-24-g4f1b From 28bda7fd05d5261e0da1702e789cfedc6ab423b4 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Mon, 25 Apr 2011 15:00:45 -0500 Subject: swapping out preg_replace() in the driver library where str_replace() works just fine. --- system/libraries/Driver.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php index b90b5aba6..1e01fcc1f 100644 --- a/system/libraries/Driver.php +++ b/system/libraries/Driver.php @@ -43,11 +43,11 @@ class CI_Driver_Library { // The class will be prefixed with the parent lib $child_class = $this->lib_name.'_'.$child; - + // Remove the CI_ prefix and lowercase - $lib_name = ucfirst(strtolower(preg_replace('/^CI_/', '', $this->lib_name))); - $driver_name = strtolower(preg_replace('/^CI_/', '', $child_class)); - + $lib_name = ucfirst(strtolower(str_replace('CI_', '', $this->lib_name))); + $driver_name = strtolower(str_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 -- cgit v1.2.3-24-g4f1b From d97e12cb0e9c8b5e78e67780d1a9227da35e0da4 Mon Sep 17 00:00:00 2001 From: Eric Barnes Date: Tue, 26 Apr 2011 09:59:29 -0400 Subject: Automatic base_url generation was missing a ending slash. --- system/core/Config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/core/Config.php b/system/core/Config.php index fa71f4d3d..55c623b3c 100644 --- a/system/core/Config.php +++ b/system/core/Config.php @@ -55,7 +55,7 @@ class CI_Config { { $base_url = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http'; $base_url .= '://'. $_SERVER['HTTP_HOST']; - $base_url .= str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); + $base_url .= str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']).'/'; } else -- cgit v1.2.3-24-g4f1b From 32dbac2695490fb751fc8da645bba945bc8da718 Mon Sep 17 00:00:00 2001 From: Eric Barnes Date: Tue, 26 Apr 2011 22:51:32 -0400 Subject: Reverting last change. Don't know what I was thinking. :( --- system/core/Config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/core/Config.php b/system/core/Config.php index 55c623b3c..fa71f4d3d 100644 --- a/system/core/Config.php +++ b/system/core/Config.php @@ -55,7 +55,7 @@ class CI_Config { { $base_url = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http'; $base_url .= '://'. $_SERVER['HTTP_HOST']; - $base_url .= str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']).'/'; + $base_url .= str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); } else -- cgit v1.2.3-24-g4f1b From 25d495b4a2598f771a858108a2cd2e96f0130412 Mon Sep 17 00:00:00 2001 From: Eric Barnes Date: Tue, 26 Apr 2011 23:02:44 -0400 Subject: Removed the GET, POST, and COOKIE Data from security since we now allow $_GET data. Fixes #48 --- user_guide/general/security.html | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/user_guide/general/security.html b/user_guide/general/security.html index bcbb36c6f..31dd7978c 100644 --- a/user_guide/general/security.html +++ b/user_guide/general/security.html @@ -76,15 +76,9 @@ minimize the possibility that malicious data can be passed to your application.
      • Dash: -
      -

      GET, POST, and COOKIE Data

      - -

      GET data is simply disallowed by CodeIgniter since the system utilizes URI segments rather than traditional URL query strings (unless -you have the query string option enabled in your config file). The global GET -array is unset by the Input class during system initialization.

      -

      Register_globals

      -

      During system initialization all global variables are unset, except those found in the $_POST and $_COOKIE arrays. The unsetting +

      During system initialization all global variables are unset, except those found in the $_GET, $_POST, and $_COOKIE arrays. The unsetting routine is effectively the same as register_globals = off.

      -- cgit v1.2.3-24-g4f1b From 60ef4ea72e169e174ff8dbb421609a178a3c0c48 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Wed, 27 Apr 2011 01:45:38 -0500 Subject: Added insert_batch() function to the PostgreSQL database driver. Thanks to epallerols for the patch. --- system/database/drivers/postgre/postgre_driver.php | 18 ++++++++++++++++++ user_guide/changelog.html | 1 + 2 files changed, 19 insertions(+) diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php index 47ff36246..140396885 100644 --- a/system/database/drivers/postgre/postgre_driver.php +++ b/system/database/drivers/postgre/postgre_driver.php @@ -553,6 +553,24 @@ class CI_DB_postgre_driver extends CI_DB { // -------------------------------------------------------------------- + /** + * Insert_batch statement + * + * Generates a platform-specific insert string from the supplied data + * + * @access public + * @param string the table name + * @param array the insert keys + * @param array the insert values + * @return string + */ + function _insert_batch($table, $keys, $values) + { + return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values); + } + + // -------------------------------------------------------------------- + /** * Update statement * diff --git a/user_guide/changelog.html b/user_guide/changelog.html index 76f9e5dd9..206322e11 100644 --- a/user_guide/changelog.html +++ b/user_guide/changelog.html @@ -73,6 +73,7 @@ Change Log
    • Added Session Class userdata to the output profiler. Additionally, added a show/hide toggle on HTTP Headers, Session Data and Config Variables.
    • Removed internal usage of the EXT constant.
    • Visual updates to the welcome_message view file and default error templates. Thanks to danijelb for the pull request.
    • +
    • Added insert_batch() function to the PostgreSQL database driver. Thanks to epallerols for the patch.
  • Helpers -- cgit v1.2.3-24-g4f1b From 02958b5b78835a484c1038d77f4bcfc5ae273a2d Mon Sep 17 00:00:00 2001 From: Phil Sturgeon Date: Thu, 28 Apr 2011 17:49:33 +0100 Subject: hg flow init, add .hgflow file --- .hgflow | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .hgflow diff --git a/.hgflow b/.hgflow new file mode 100644 index 000000000..ad6e56e0f --- /dev/null +++ b/.hgflow @@ -0,0 +1,8 @@ +[Basic] +develop = develop +feature = feature/ +version_tag = +publish = default +release = release/ +hotfix = hotfix/ + -- cgit v1.2.3-24-g4f1b From 2e1837a3afabe7e6c71fc88d7a4f5e430fa96744 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Fri, 6 May 2011 12:17:04 -0500 Subject: Fix #275 -- regression in db::_compile_select(). Thanks @patwork for the patch --- system/database/DB_active_rec.php | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php index 508f6bedf..d94d4a13c 100644 --- a/system/database/DB_active_rec.php +++ b/system/database/DB_active_rec.php @@ -60,7 +60,7 @@ class CI_DB_active_record extends CI_DB_driver { var $ar_cache_set = array(); var $ar_no_escape = array(); - + var $ar_cache_no_escape = array(); // -------------------------------------------------------------------- @@ -93,6 +93,7 @@ class CI_DB_active_record extends CI_DB_driver { { $this->ar_cache_select[] = $val; $this->ar_cache_exists[] = 'select'; + $this->ar_cache_no_escape[] = $escape; } } } @@ -1933,16 +1934,17 @@ class CI_DB_active_record extends CI_DB_driver { { $this->_reset_run( array( - 'ar_cache_select' => array(), - 'ar_cache_from' => array(), - 'ar_cache_join' => array(), - 'ar_cache_where' => array(), - 'ar_cache_like' => array(), - 'ar_cache_groupby' => array(), - 'ar_cache_having' => array(), - 'ar_cache_orderby' => array(), - 'ar_cache_set' => array(), - 'ar_cache_exists' => array() + 'ar_cache_select' => array(), + 'ar_cache_from' => array(), + 'ar_cache_join' => array(), + 'ar_cache_where' => array(), + 'ar_cache_like' => array(), + 'ar_cache_groupby' => array(), + 'ar_cache_having' => array(), + 'ar_cache_orderby' => array(), + 'ar_cache_set' => array(), + 'ar_cache_exists' => array(), + 'ar_cache_no_escape' => array() ) ); } @@ -1984,6 +1986,8 @@ class CI_DB_active_record extends CI_DB_driver { { $this->_track_aliases($this->ar_from); } + + $this->ar_no_escape = $this->ar_cache_no_escape; } // -------------------------------------------------------------------- -- cgit v1.2.3-24-g4f1b From 3ef65bd7491f847fecdab1acc9687f0e90eee09b Mon Sep 17 00:00:00 2001 From: Dan Horrigan Date: Sun, 8 May 2011 11:06:44 -0400 Subject: Wrapped all common functions to check if it already exists. This allows anyone to override a lot more of the core by simply defining these function prior to loading them. --- system/core/Common.php | 61 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/system/core/Common.php b/system/core/Common.php index eb9e14425..e50f7794a 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -39,6 +39,8 @@ * @param string * @return bool TRUE if the current version is $version or higher */ +if ( ! function_exists('is_php')) +{ function is_php($version = '5.0.0') { static $_is_php; @@ -51,6 +53,7 @@ return $_is_php[$version]; } +} // ------------------------------------------------------------------------ @@ -64,6 +67,8 @@ * @access private * @return void */ +if ( ! function_exists('is_really_writable')) +{ function is_really_writable($file) { // If we're on a Unix server with safe_mode off we call is_writable @@ -96,6 +101,7 @@ fclose($fp); return TRUE; } +} // ------------------------------------------------------------------------ @@ -112,6 +118,8 @@ * @param string the class name prefix * @return object */ +if ( ! function_exists('load_class')) +{ function &load_class($class, $directory = 'libraries', $prefix = 'CI_') { static $_classes = array(); @@ -166,6 +174,7 @@ $_classes[$class] = new $name(); return $_classes[$class]; } +} // -------------------------------------------------------------------- @@ -176,6 +185,8 @@ * @access public * @return array */ +if ( ! function_exists('is_loaded')) +{ function is_loaded($class = '') { static $_is_loaded = array(); @@ -187,6 +198,7 @@ return $_is_loaded; } +} // ------------------------------------------------------------------------ @@ -199,6 +211,8 @@ * @access private * @return array */ +if ( ! function_exists('get_config')) +{ function &get_config($replace = array()) { static $_config; @@ -242,6 +256,7 @@ return $_config[0] =& $config; } +} // ------------------------------------------------------------------------ @@ -251,6 +266,8 @@ * @access public * @return mixed */ +if ( ! function_exists('config_item')) +{ function config_item($item) { static $_config_item = array(); @@ -268,6 +285,7 @@ return $_config_item[$item]; } +} // ------------------------------------------------------------------------ @@ -283,12 +301,15 @@ * @access public * @return void */ +if ( ! function_exists('show_error')) +{ function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered') { $_error =& load_class('Exceptions', 'core'); echo $_error->show_error($heading, $message, 'error_general', $status_code); exit; } +} // ------------------------------------------------------------------------ @@ -302,12 +323,15 @@ * @access public * @return void */ +if ( ! function_exists('show_404')) +{ function show_404($page = '', $log_error = TRUE) { $_error =& load_class('Exceptions', 'core'); $_error->show_404($page, $log_error); exit; } +} // ------------------------------------------------------------------------ @@ -320,6 +344,8 @@ * @access public * @return void */ +if ( ! function_exists('log_message')) +{ function log_message($level = 'error', $message, $php_error = FALSE) { static $_log; @@ -332,6 +358,7 @@ $_log =& load_class('Log'); $_log->write_log($level, $message, $php_error); } +} // ------------------------------------------------------------------------ @@ -343,6 +370,8 @@ * @param string * @return void */ +if ( ! function_exists('set_status_header')) +{ function set_status_header($code = 200, $text = '') { $stati = array( @@ -417,6 +446,7 @@ header("HTTP/1.1 {$code} {$text}", TRUE, $code); } } +} // -------------------------------------------------------------------- @@ -434,6 +464,8 @@ * @access private * @return void */ +if ( ! function_exists('_exception_handler')) +{ function _exception_handler($severity, $message, $filepath, $line) { // We don't bother with "strict" notices since they tend to fill up @@ -463,19 +495,22 @@ $_error->log_exception($severity, $message, $filepath, $line); } +} - // -------------------------------------------------------------------- - - /** - * Remove Invisible Characters - * - * This prevents sandwiching null characters - * between ascii characters, like Java\0script. - * - * @access public - * @param string - * @return string - */ +// -------------------------------------------------------------------- + +/** + * Remove Invisible Characters + * + * This prevents sandwiching null characters + * between ascii characters, like Java\0script. + * + * @access public + * @param string + * @return string + */ +if ( ! function_exists('remove_invisible_characters')) +{ function remove_invisible_characters($str, $url_encoded = TRUE) { $non_displayables = array(); @@ -499,7 +534,7 @@ return $str; } - +} /* End of file Common.php */ /* Location: ./system/core/Common.php */ \ No newline at end of file -- cgit v1.2.3-24-g4f1b