diff options
author | Timothy Warren <tim@timshomepage.net> | 2012-06-27 14:02:13 +0200 |
---|---|---|
committer | Timothy Warren <tim@timshomepage.net> | 2012-06-27 14:02:13 +0200 |
commit | 13077951b63cf9858dc14ec9cab7f2b53ec88a3e (patch) | |
tree | e1fc50ddb8c0a4103c945f15d674d85c6655231b /system | |
parent | 9128231452f3ccea857a848b61bd0e6e9e319737 (diff) | |
parent | b66664b5decd68de50ae6c239c8d995d6c088d94 (diff) |
Merge branch 'develop' of git://github.com/EllisLab/CodeIgniter into email
Diffstat (limited to 'system')
43 files changed, 731 insertions, 529 deletions
diff --git a/system/core/Common.php b/system/core/Common.php index 1708653e7..c309d4192 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -431,6 +431,7 @@ if ( ! function_exists('set_status_header')) 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', + 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', @@ -462,18 +463,23 @@ if ( ! function_exists('set_status_header')) 505 => 'HTTP Version Not Supported' ); - if ($code == '' OR ! is_numeric($code)) + if (empty($code) OR ! is_numeric($code)) { show_error('Status codes must be numeric', 500); } - elseif (isset($stati[$code]) && $text === '') - { - $text = $stati[$code]; - } - if ($text === '') + is_int($code) OR $code = (int) $code; + + if (empty($text)) { - show_error('No status text available. Please check your status code number or supply your own message text.', 500); + if (isset($stati[$code])) + { + $text = $stati[$code]; + } + else + { + show_error('No status text available. Please check your status code number or supply your own message text.', 500); + } } $server_protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : FALSE; diff --git a/system/core/Config.php b/system/core/Config.php index 3de1bcb96..4b4e5a7ba 100644 --- a/system/core/Config.php +++ b/system/core/Config.php @@ -225,25 +225,39 @@ class CI_Config { * Site URL * Returns base_url . index_page [. uri_string] * - * @param string the URI string + * @param mixed the URI string or an array of segments * @return string */ public function site_url($uri = '') { - if ($uri === '') + if (empty($uri)) { return $this->slash_item('base_url').$this->item('index_page'); } + $uri = $this->_uri_string($uri); + if ($this->item('enable_query_strings') === FALSE) { $suffix = ($this->item('url_suffix') === FALSE) ? '' : $this->item('url_suffix'); - return $this->slash_item('base_url').$this->slash_item('index_page').$this->_uri_string($uri).$suffix; + + if ($suffix !== '' && ($offset = strpos($uri, '?')) !== FALSE) + { + $uri = substr($uri, 0, $offset).$suffix.substr($uri, $offset); + } + else + { + $uri .= $suffix; + } + + return $this->slash_item('base_url').$this->slash_item('index_page').$uri; } - else + elseif (strpos($uri, '?') === FALSE) { - return $this->slash_item('base_url').$this->item('index_page').'?'.$this->_uri_string($uri); + $uri = '?'.$uri; } + + return $this->slash_item('base_url').$this->item('index_page').$uri; } // ------------------------------------------------------------- @@ -280,15 +294,7 @@ class CI_Config { } elseif (is_array($uri)) { - $i = 0; - $str = ''; - foreach ($uri as $key => $val) - { - $prefix = ($i === 0) ? '' : '&'; - $str .= $prefix.$key.'='.$val; - $i++; - } - return $str; + return http_build_query($uri); } return $uri; diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php index 8c32085fe..bd9178dbd 100644 --- a/system/core/Exceptions.php +++ b/system/core/Exceptions.php @@ -143,7 +143,7 @@ class CI_Exceptions { ob_end_flush(); } ob_start(); - include(APPPATH.'views/errors/'.$template.'.php'); + include(VIEWPATH.'errors/'.$template.'.php'); $buffer = ob_get_contents(); ob_end_clean(); return $buffer; @@ -177,7 +177,7 @@ class CI_Exceptions { ob_end_flush(); } ob_start(); - include(APPPATH.'views/errors/error_php.php'); + include(VIEWPATH.'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 29fd88201..afbf4b453 100644 --- a/system/core/Hooks.php +++ b/system/core/Hooks.php @@ -39,7 +39,7 @@ class CI_Hooks { /** - * Determines wether hooks are enabled + * Determines whether hooks are enabled * * @var bool */ @@ -53,7 +53,7 @@ class CI_Hooks { public $hooks = array(); /** - * Determines wether hook is in progress, used to prevent infinte loops + * Determines whether hook is in progress, used to prevent infinte loops * * @var bool */ diff --git a/system/core/Output.php b/system/core/Output.php index 5588ffe8e..5ec8c4bc0 100644 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -67,7 +67,14 @@ class CI_Output { public $mimes = array(); /** - * Determines wether profiler is enabled + * Mime-type for the current page + * + * @var string + */ + protected $mime_type = 'text/html'; + + /** + * Determines whether profiler is enabled * * @var book */ @@ -78,7 +85,7 @@ class CI_Output { * * @var bool */ - protected $_zlib_oc = FALSE; + protected $_zlib_oc = FALSE; /** * List of profiler sections @@ -174,7 +181,7 @@ class CI_Output { * how to permit header data to be saved with the cache data... * * @param string - * @param bool + * @param bool * @return void */ public function set_header($header, $replace = TRUE) @@ -218,6 +225,8 @@ class CI_Output { } } + $this->mime_type = $mime_type; + if (empty($charset)) { $charset = config_item('charset'); @@ -292,6 +301,12 @@ class CI_Output { */ public function set_profiler_sections($sections) { + if (isset($sections['query_toggle_count'])) + { + $this->_profiler_sections['query_toggle_count'] = (int) $sections['query_toggle_count']; + unset($sections['query_toggle_count']); + } + foreach ($sections as $section => $enable) { $this->_profiler_sections[$section] = ($enable !== FALSE); @@ -327,7 +342,7 @@ class CI_Output { * with any server headers and profile data. It also stops the * benchmark timer so the page rendering speed and memory usage can be shown. * - * @param string + * @param string * @return mixed */ public function _display($output = '') @@ -353,6 +368,15 @@ class CI_Output { // -------------------------------------------------------------------- + // Is minify requested? + if ($CFG->item('minify_output') === TRUE) + { + $output = $this->minify($output, $this->mime_type); + } + + + // -------------------------------------------------------------------- + // Do we need to write a cache file? Only if the controller does not have its // own _output() method and we are not dealing with a cache file, which we // can determine by the existence of the $CI object above @@ -450,7 +474,7 @@ class CI_Output { /** * Write a Cache File * - * @param string + * @param string * @return void */ public function _write_cache($output) @@ -493,6 +517,9 @@ class CI_Output { @chmod($cache_path, FILE_WRITE_MODE); log_message('debug', 'Cache file written: '.$cache_path); + + // Send HTTP cache-control headers to browser to match file cache settings. + $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire); } // -------------------------------------------------------------------- @@ -500,8 +527,8 @@ class CI_Output { /** * Update/serve a cached file * - * @param object config class - * @param object uri class + * @param object config class + * @param object uri class * @return bool */ public function _display_cache(&$CFG, &$URI) @@ -530,13 +557,22 @@ class CI_Output { return FALSE; } - // Has the file expired? If so we'll delete it. - if (time() >= trim(str_replace('TS--->', '', $match[1])) && is_really_writable($cache_path)) + $last_modified = filemtime($cache_path); + $expire = trim(str_replace('TS--->', '', $match[1])); + + // Has the file expired? + if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path)) { + // If so we'll delete it. @unlink($filepath); log_message('debug', 'Cache file has expired. File deleted.'); return FALSE; } + else + { + // Or else send the HTTP cache control headers. + $this->set_cache_header($last_modified, $expire); + } // Display the cache $this->_display(str_replace($match[0], '', $cache)); @@ -544,6 +580,140 @@ class CI_Output { return TRUE; } + // -------------------------------------------------------------------- + + /** + * Set the HTTP headers to match the server-side file cache settings + * in order to reduce bandwidth. + * + * @param int timestamp of when the page was last modified + * @param int timestamp of when should the requested page expire from cache + * @return void + */ + public function set_cache_header($last_modified, $expiration) + { + $max_age = $expiration - $_SERVER['REQUEST_TIME']; + + if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $last_modified <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) + { + $this->set_status_header(304); + exit; + } + else + { + header('Pragma: public'); + header('Cache-Control: max-age=' . $max_age . ', public'); + header('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT'); + header('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT'); + } + } + + // -------------------------------------------------------------------- + + /** + * Reduce excessive size of HTML content. + * + * @param string + * @param string + * @return string + */ + public function minify($output, $type = 'text/html') + { + switch ($type) + { + case 'text/html': + + $size_before = strlen($output); + + if ($size_before === 0) + { + return ''; + } + + // Find all the <pre>,<code>,<textarea>, and <javascript> tags + // We'll want to return them to this unprocessed state later. + preg_match_all('{<pre.+</pre>}msU', $output, $pres_clean); + preg_match_all('{<code.+</code>}msU', $output, $codes_clean); + preg_match_all('{<textarea.+</textarea>}msU', $output, $textareas_clean); + preg_match_all('{<script.+</script>}msU', $output, $javascript_clean); + + // Minify the CSS in all the <style> tags. + preg_match_all('{<style.+</style>}msU', $output, $style_clean); + foreach ($style_clean[0] as $s) + { + $output = str_replace($s, $this->minify($s, 'text/css'), $output); + } + + // Minify the javascript in <script> tags. + foreach ($javascript_clean[0] as $s) + { + $javascript_mini[] = $this->minify($s, 'text/javascript'); + } + + // Replace multiple spaces with a single space. + $output = preg_replace('!\s{2,}!', ' ', $output); + + // Remove comments (non-MSIE conditionals) + $output = preg_replace('{\s*<!--[^\[].*-->\s*}msU', '', $output); + + // Remove spaces around block-level elements. + $output = preg_replace('/\s*(<\/?(html|head|title|meta|script|link|style|body|h[1-6]|div|p|br)[^>]*>)\s*/is', '$1', $output); + + // Replace mangled <pre> etc. tags with unprocessed ones. + + if ( ! empty($pres_clean)) + { + preg_match_all('{<pre.+</pre>}msU', $output, $pres_messed); + $output = str_replace($pres_messed[0], $pres_clean[0], $output); + } + + if ( ! empty($codes_clean)) + { + preg_match_all('{<code.+</code>}msU', $output, $codes_messed); + $output = str_replace($codes_messed[0], $codes_clean[0], $output); + } + + if ( ! empty($codes_clean)) + { + preg_match_all('{<textarea.+</textarea>}msU', $output, $textareas_messed); + $output = str_replace($textareas_messed[0], $textareas_clean[0], $output); + } + + if (isset($javascript_mini)) + { + preg_match_all('{<script.+</script>}msU', $output, $javascript_messed); + $output = str_replace($javascript_messed[0], $javascript_mini, $output); + } + + $size_removed = $size_before - strlen($output); + $savings_percent = round(($size_removed / $size_before * 100)); + + log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.'); + + break; + + case 'text/css': + + //Remove CSS comments + $output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $output); + + // Remove spaces around curly brackets, colons, + // semi-colons, parenthesis, commas + $output = preg_replace('!\s*(:|;|,|}|{|\(|\))\s*!', '$1', $output); + + break; + + case 'text/javascript': + + // Currently leaves JavaScript untouched. + break; + + default: break; + } + + return $output; + } + } /* End of file Output.php */ diff --git a/system/core/Security.php b/system/core/Security.php index 4593a1090..227217e75 100644 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -561,6 +561,19 @@ class CI_Security { // ---------------------------------------------------------------- /** + * Strip Image Tags + * + * @param string + * @return string + */ + public function strip_image_tags($str) + { + return preg_replace(array('#<img\s+.*?src\s*=\s*["\'](.+?)["\'].*?\>#', '#<img\s+.*?src\s*=\s*(.+?).*?\>#'), '\\1', $str); + } + + // ---------------------------------------------------------------- + + /** * Compact Exploded Words * * Callback function for xss_clean() to remove whitespace from diff --git a/system/core/URI.php b/system/core/URI.php index a997525ee..6a8b1a5ac 100644 --- a/system/core/URI.php +++ b/system/core/URI.php @@ -278,7 +278,7 @@ class CI_URI { { // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern - if ( ! preg_match('|^['.str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-')).']+$|i', $str)) + if ( ! preg_match('|^['.str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-')).']+$|i', urldecode($str))) { show_error('The URI you submitted has disallowed characters.', 400); } @@ -302,9 +302,11 @@ class CI_URI { */ public function _remove_url_suffix() { - if ($this->config->item('url_suffix') !== '') + $suffix = (string) $this->config->item('url_suffix'); + + if ($suffix !== '' && ($offset = strrpos($this->uri_string, $suffix)) !== FALSE) { - $this->uri_string = preg_replace('|'.preg_quote($this->config->item('url_suffix')).'$|', '', $this->uri_string); + $this->uri_string = substr_replace($this->uri_string, '', $offset, strlen($suffix)); } } diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index d056bdb90..739b25187 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -295,7 +295,7 @@ abstract class CI_DB_driver { * @param array An array of binding data * @return mixed */ - public function query($sql, $binds = FALSE, $return_object = TRUE) + public function query($sql, $binds = FALSE, $return_object = NULL) { if ($sql === '') { @@ -303,6 +303,10 @@ abstract class CI_DB_driver { return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE; } + elseif ( ! is_bool($return_object)) + { + $return_object = ! $this->is_write_type($sql); + } // Verify table prefix and replace if necessary if ($this->dbprefix !== '' && $this->swap_pre !== '' && $this->dbprefix !== $this->swap_pre) @@ -319,7 +323,7 @@ abstract class CI_DB_driver { // Is query caching enabled? If the query is a "read type" // we will load the caching class and return the previously // cached query if it exists - if ($this->cache_on === TRUE && stripos($sql, 'SELECT') !== FALSE && $this->_cache_init()) + if ($this->cache_on === TRUE && $return_object === TRUE && $this->_cache_init()) { $this->load_rdriver(); if (FALSE !== ($cache = $this->CACHE->read($sql))) @@ -328,7 +332,7 @@ abstract class CI_DB_driver { } } - // Save the query for debugging + // Save the query for debugging if ($this->save_queries === TRUE) { $this->queries[] = $sql; @@ -352,7 +356,7 @@ abstract class CI_DB_driver { $error = $this->error(); // Log errors - log_message('error', 'Query error: '.$error['message']); + log_message('error', 'Query error: '.$error['message'].' - Invalid query: '.$sql); if ($this->db_debug) { @@ -381,12 +385,10 @@ abstract class CI_DB_driver { // Increment the query counter $this->query_count++; - // Was the query a "write" type? - // If so we'll simply return true - if ($this->is_write_type($sql) === TRUE) + // Will we have a result object instantiated? If not - we'll simply return TRUE + if ($return_object !== TRUE) { - // If caching is enabled we'll auto-cleanup any - // existing files related to this particular URI + // If caching is enabled we'll auto-cleanup any existing files related to this particular URI if ($this->cache_on === TRUE && $this->cache_autodel === TRUE && $this->_cache_init()) { $this->CACHE->delete(); @@ -396,8 +398,6 @@ abstract class CI_DB_driver { } // Return TRUE if we don't need to create a result object - // Currently only the Oracle driver uses this when stored - // procedures are used if ($return_object !== TRUE) { return TRUE; @@ -1086,6 +1086,20 @@ abstract class CI_DB_driver { // -------------------------------------------------------------------- /** + * Returns the SQL string operator + * + * @param string + * @return string + */ + protected function _get_operator($str) + { + return preg_match('/(=|!|<|>| IS NULL| IS NOT NULL| BETWEEN)/i', $str, $match) + ? $match[1] : FALSE; + } + + // -------------------------------------------------------------------- + + /** * Enables a native PHP function to be run, using a platform agnostic wrapper. * * @param string the function name @@ -1267,7 +1281,7 @@ abstract class CI_DB_driver { if (isset($call['file']) && strpos($call['file'], BASEPATH.'database') === FALSE) { // Found it - use a relative path for safety - $message[] = 'Filename: '.str_replace(array(BASEPATH, APPPATH), '', $call['file']); + $message[] = 'Filename: '.str_replace(array(APPPATH, BASEPATH), '', $call['file']); $message[] = 'Line Number: '.$call['line']; break; } @@ -1336,39 +1350,21 @@ abstract class CI_DB_driver { // Convert tabs or multiple spaces into single spaces $item = preg_replace('/\s+/', ' ', $item); - static $preg_ec = array(); - - if (empty($preg_ec)) + // If the item has an alias declaration we remove it and set it aside. + // Note: strripos() is used in order to support spaces in table names + if ($offset = strripos($item, ' AS ')) { - if (is_array($this->_escape_char)) - { - $preg_ec = array(preg_quote($this->_escape_char[0]), preg_quote($this->_escape_char[1])); - } - else - { - $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char); - } + $alias = ($protect_identifiers) + ? substr($item, $offset, 4).$this->escape_identifiers(substr($item, $offset + 4)) + : substr($item, $offset); + $item = substr($item, 0, $offset); } - - // If the item has an alias declaration we remove it and set it aside. - // Basically we remove everything to the right of the first space - preg_match('/^(('.$preg_ec[0].'[^'.$preg_ec[1].']+'.$preg_ec[1].')|([^'.$preg_ec[0].'][^\s]+))( AS)*(.+)*$/i', $item, $matches); - - if (isset($matches[4])) + elseif ($offset = strrpos($item, ' ')) { - $item = $matches[1]; - - // Escape the alias, if needed - if ($protect_identifiers === TRUE) - { - $alias = empty($matches[5]) - ? ' '.$this->escape_identifiers(ltrim($matches[4])) - : $matches[4].' '.$this->escape_identifiers(ltrim($matches[5])); - } - else - { - $alias = $matches[4].$matches[5]; - } + $alias = ($protect_identifiers) + ? ' '.$this->escape_identifiers(substr($item, $offset + 1)) + : substr($item, $offset); + $item = substr($item, 0, $offset); } else { diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php index 9b7639289..91f9d560c 100644 --- a/system/database/DB_forge.php +++ b/system/database/DB_forge.php @@ -231,7 +231,7 @@ abstract class CI_DB_forge { if (($result = $this->db->query($sql)) !== FALSE && ! empty($this->db->data_cache['table_names'])) { - $this->db->data_cache['table_names'][] = $$this->db->dbprefix.$table; + $this->db->data_cache['table_names'][] = $this->db->dbprefix.$table; } return $result; diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index 488b294e4..3982885e8 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -324,10 +324,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param string * @param string the join condition * @param string the type of join - * @param string wether not to try to escape identifiers + * @param string whether not to try to escape identifiers * @return object */ - public function join($table, $cond, $type = '', $escape = TRUE) + public function join($table, $cond, $type = '', $escape = NULL) { if ($type !== '') { @@ -347,6 +347,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // in the protect_identifiers to know whether to add a table prefix $this->_track_aliases($table); + is_bool($escape) OR $escape = $this->_protect_identifiers; + // Split multiple conditions if ($escape === TRUE && preg_match_all('/\sAND\s|\sOR\s/i', $cond, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { @@ -366,12 +368,20 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $newcond .= $m[0][$i][0]; } - $cond = $newcond; + $cond = ' ON '.$newcond; } // Split apart the condition and protect the identifiers elseif ($escape === TRUE && preg_match('/([\[\w\.-]+)([\W\s]+)(.+)/i', $cond, $match)) { - $cond = $this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]); + $cond = ' ON '.$this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]); + } + elseif ( ! $this->_has_operator($cond)) + { + $cond = ' USING ('.($escape ? $this->escape_identifiers($cond) : $cond).')'; + } + else + { + $cond = ' ON '.$cond; } // Do we want to escape the table name? @@ -381,7 +391,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { } // Assemble the JOIN statement - $this->qb_join[] = $join = $type.'JOIN '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' ON '.$cond; + $this->qb_join[] = $join = $type.'JOIN '.$table.$cond; if ($this->qb_caching === TRUE) { @@ -405,7 +415,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param bool * @return object */ - public function where($key, $value = NULL, $escape = TRUE) + public function where($key, $value = NULL, $escape = NULL) { return $this->_where($key, $value, 'AND ', $escape); } @@ -423,7 +433,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param bool * @return object */ - public function or_where($key, $value = NULL, $escape = TRUE) + public function or_where($key, $value = NULL, $escape = NULL) { return $this->_where($key, $value, 'OR ', $escape); } @@ -443,23 +453,26 @@ abstract class CI_DB_query_builder extends CI_DB_driver { */ protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL) { - $type = $this->_group_get_type($type); - if ( ! is_array($key)) { $key = array($key => $value); } // If the escape value was not set will will base it on the global setting - $escape = $this->_protect_identifiers; + is_bool($escape) OR $escape = $this->_protect_identifiers; foreach ($key as $k => $v) { - $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type; + $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) + ? $this->_group_get_type('') + : $this->_group_get_type($type); - $k = $this->_has_operator($k) - ? $this->protect_identifiers(substr($k, 0, strpos(rtrim($k), ' ')), FALSE, $escape).strchr(rtrim($k), ' ') - : $this->protect_identifiers($k, FALSE, $escape); + if ($escape === TRUE) + { + $k = (($op = $this->_get_operator($k)) !== FALSE) + ? $this->escape_identifiers(trim(substr($k, 0, strpos($k, $op)))).' '.strstr($k, $op) + : $this->escape_identifiers(trim($k)); + } if (is_null($v) && ! $this->_has_operator($k)) { @@ -504,9 +517,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param array The values searched on * @return object */ - public function where_in($key = NULL, $values = NULL) + public function where_in($key = NULL, $values = NULL, $escape = NULL) { - return $this->_where_in($key, $values); + return $this->_where_in($key, $values, FALSE, 'AND ', $escape); } // -------------------------------------------------------------------- @@ -521,9 +534,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param array The values searched on * @return object */ - public function or_where_in($key = NULL, $values = NULL) + public function or_where_in($key = NULL, $values = NULL, $escape = NULL) { - return $this->_where_in($key, $values, FALSE, 'OR '); + return $this->_where_in($key, $values, FALSE, 'OR ', $escape); } // -------------------------------------------------------------------- @@ -538,9 +551,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param array The values searched on * @return object */ - public function where_not_in($key = NULL, $values = NULL) + public function where_not_in($key = NULL, $values = NULL, $escape = NULL) { - return $this->_where_in($key, $values, TRUE); + return $this->_where_in($key, $values, TRUE, 'AND ', $escape); } // -------------------------------------------------------------------- @@ -555,9 +568,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param array The values searched on * @return object */ - public function or_where_not_in($key = NULL, $values = NULL) + public function or_where_not_in($key = NULL, $values = NULL, $escape = NULL) { - return $this->_where_in($key, $values, TRUE, 'OR '); + return $this->_where_in($key, $values, TRUE, 'OR ', $escape); } // -------------------------------------------------------------------- @@ -573,20 +586,20 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param string * @return object */ - protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ') + protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ', $escape = NULL) { if ($key === NULL OR $values === NULL) { return $this; } - $type = $this->_group_get_type($type); - if ( ! is_array($values)) { $values = array($values); } + is_bool($escape) OR $escape = $this->_protect_identifiers; + $not = ($not) ? ' NOT' : ''; foreach ($values as $value) @@ -594,8 +607,13 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->qb_wherein[] = $this->escape($value); } - $prefix = (count($this->qb_where) === 0) ? '' : $type; - $this->qb_where[] = $where_in = $prefix.$this->protect_identifiers($key).$not.' IN ('.implode(', ', $this->qb_wherein).') '; + if ($escape === TRUE) + { + $key = $this->escape_identifiers(trim($key)); + } + + $prefix = (count($this->qb_where) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type); + $this->qb_where[] = $where_in = $prefix.$key.$not.' IN ('.implode(', ', $this->qb_wherein).') '; if ($this->qb_caching === TRUE) { @@ -690,8 +708,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver { */ protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '') { - $type = $this->_group_get_type($type); - if ( ! is_array($field)) { $field = array($field => $match); @@ -700,7 +716,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { foreach ($field as $k => $v) { $k = $this->protect_identifiers($k); - $prefix = (count($this->qb_like) === 0) ? '' : $type; + $prefix = (count($this->qb_like) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type); $v = $this->escape_like_str($v); if ($side === 'none') @@ -886,7 +902,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param bool * @return object */ - public function having($key, $value = '', $escape = TRUE) + public function having($key, $value = '', $escape = NULL) { return $this->_having($key, $value, 'AND ', $escape); } @@ -903,7 +919,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param bool * @return object */ - public function or_having($key, $value = '', $escape = TRUE) + public function or_having($key, $value = '', $escape = NULL) { return $this->_having($key, $value, 'OR ', $escape); } @@ -921,21 +937,22 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param bool * @return object */ - protected function _having($key, $value = '', $type = 'AND ', $escape = TRUE) + protected function _having($key, $value = '', $type = 'AND ', $escape = NULL) { if ( ! is_array($key)) { $key = array($key => $value); } + is_bool($escape) OR $escape = $this->_protect_identifiers; + foreach ($key as $k => $v) { $prefix = (count($this->qb_having) === 0) ? '' : $type; - if ($escape === TRUE) - { - $k = $this->protect_identifiers($k); - } + $k = $this->_has_operator($k) + ? $this->protect_identifiers(substr($k, 0, strpos(rtrim($k), ' ')), FALSE, $escape).strchr(rtrim($k), ' ') + : $this->protect_identifiers($k, FALSE, $escape); if ( ! $this->_has_operator($k)) { @@ -968,7 +985,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param bool enable field name escaping * @return object */ - public function order_by($orderby, $direction = '', $escape = TRUE) + public function order_by($orderby, $direction = '', $escape = NULL) { if (strtolower($direction) === 'random') { @@ -980,8 +997,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $direction = in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE) ? ' '.$direction : ' ASC'; } + is_bool($escape) OR $escape = $this->_protect_identifiers; - if ((strpos($orderby, ',') !== FALSE) && $escape === TRUE) + if ($escape === TRUE && strpos($orderby, ',') !== FALSE) { $temp = array(); foreach (explode(',', $orderby) as $part) @@ -1028,12 +1046,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver { */ public function limit($value, $offset = NULL) { - $this->qb_limit = (int) $value; - - if ( ! empty($offset)) - { - $this->qb_offset = (int) $offset; - } + is_null($value) OR $this->qb_limit = (int) $value; + empty($offset) OR $this->qb_offset = (int) $offset; return $this; } @@ -1048,21 +1062,40 @@ abstract class CI_DB_query_builder extends CI_DB_driver { */ public function offset($offset) { - $this->qb_offset = (int) $offset; + empty($offset) OR $this->qb_offset = (int) $offset; return $this; } // -------------------------------------------------------------------- /** - * The "set" function. Allows key/value pairs to be set for inserting or updating + * Limit string + * + * Generates a platform-specific LIMIT clause + * + * @param string the sql query string + * @param int the number of rows to limit the query to + * @param int the offset value + * @return string + */ + protected function _limit($sql, $limit, $offset) + { + return $sql.' LIMIT '.($offset ? $offset.', ' : '').$limit; + } + + // -------------------------------------------------------------------- + + /** + * The "set" function. + * + * Allows key/value pairs to be set for inserting or updating * * @param mixed * @param string * @param bool * @return object */ - public function set($key, $value = '', $escape = TRUE) + public function set($key, $value = '', $escape = NULL) { $key = $this->_object_to_array($key); @@ -1071,16 +1104,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $key = array($key => $value); } + is_bool($escape) OR $escape = $this->_protect_identifiers; + foreach ($key as $k => $v) { - if ($escape === FALSE) - { - $this->qb_set[$this->protect_identifiers($k)] = $v; - } - else - { - $this->qb_set[$this->protect_identifiers($k, FALSE, TRUE)] = $this->escape($v); - } + $this->qb_set[$this->protect_identifiers($k, FALSE, $escape)] = ($escape) + ? $this->escape($v) : $v; } return $this; @@ -1189,7 +1218,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param string the offset clause * @return object */ - public function get_where($table = '', $where = null, $limit = null, $offset = null) + public function get_where($table = '', $where = NULL, $limit = NULL, $offset = NULL) { if ($table !== '') { @@ -1286,7 +1315,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param bool * @return object */ - public function set_insert_batch($key, $value = '', $escape = TRUE) + public function set_insert_batch($key, $value = '', $escape = NULL) { $key = $this->_object_to_array_batch($key); @@ -1295,6 +1324,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $key = array($key => $value); } + is_bool($escape) OR $escape = $this->_protect_identifiers; + $keys = array_keys($this->_object_to_array(current($key))); sort($keys); @@ -1326,7 +1357,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { foreach ($keys as $k) { - $this->qb_keys[] = $this->protect_identifiers($k); + $this->qb_keys[] = $this->protect_identifiers($k, FALSE, $escape); } return $this; @@ -1725,7 +1756,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param bool * @return object */ - public function set_update_batch($key, $index = '', $escape = TRUE) + public function set_update_batch($key, $index = '', $escape = NULL) { $key = $this->_object_to_array_batch($key); @@ -1734,6 +1765,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // @todo error } + is_bool($escape) OR $escape = $this->_protect_identifiers; + foreach ($key as $k => $v) { $index_set = FALSE; @@ -1745,7 +1778,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $index_set = TRUE; } - $clean[$this->protect_identifiers($k2)] = ($escape === FALSE) ? $v2 : $this->escape($v2); + $clean[$this->protect_identifiers($k2, FALSE, $escape)] = ($escape === FALSE) ? $v2 : $this->escape($v2); } if ($index_set === FALSE) diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php index 6b67b7546..7496ee42f 100644 --- a/system/database/drivers/cubrid/cubrid_driver.php +++ b/system/database/drivers/cubrid/cubrid_driver.php @@ -437,23 +437,6 @@ class CI_DB_cubrid_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Limit string - * - * Generates a platform-specific LIMIT clause - * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value - * @return string - */ - protected function _limit($sql, $limit, $offset) - { - return $sql.'LIMIT '.($offset == 0 ? '' : $offset.', ').$limit; - } - - // -------------------------------------------------------------------- - - /** * Close DB Connection * * @return void diff --git a/system/database/drivers/interbase/interbase_driver.php b/system/database/drivers/interbase/interbase_driver.php index 5a03607ee..38d30962c 100644 --- a/system/database/drivers/interbase/interbase_driver.php +++ b/system/database/drivers/interbase/interbase_driver.php @@ -235,7 +235,7 @@ class CI_DB_interbase_driver extends CI_DB { * @param int $inc_by * @return int */ - public function insert_id($generator_name, $inc_by=0) + public function insert_id($generator_name, $inc_by = 0) { //If a generator hasn't been used before it will return 0 return ibase_gen_id('"'.$generator_name.'"', $inc_by); @@ -257,7 +257,8 @@ class CI_DB_interbase_driver extends CI_DB { if ($prefix_limit !== FALSE && $this->dbprefix !== '') { - return $sql.' AND "RDB$RELATION_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + return $sql.' AND "RDB$RELATION_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' " + .sprintf($this->_like_escape_str, $this->_like_escape_chr); } return $sql; @@ -275,7 +276,7 @@ class CI_DB_interbase_driver extends CI_DB { */ protected function _list_columns($table = '') { - return 'SELECT "RDB$FIELD_NAME" FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = \''.$this->escape_str($table)."'"; + return 'SELECT "RDB$FIELD_NAME" FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = '.$this->escape($table); } // -------------------------------------------------------------------- @@ -290,10 +291,7 @@ class CI_DB_interbase_driver extends CI_DB { */ protected function _field_data($table) { - // Need to find a more efficient way to do this - // but Interbase/Firebird seems to lack the - // limit clause - return 'SELECT * FROM '.$table; + return $this->_limit('SELECT * FROM '.$this->protect_identifiers($table), 1, NULL); } // -------------------------------------------------------------------- @@ -361,7 +359,6 @@ class CI_DB_interbase_driver extends CI_DB { .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : ''); } - // -------------------------------------------------------------------- /** @@ -421,12 +418,12 @@ class CI_DB_interbase_driver extends CI_DB { if (stripos($this->version(), 'firebird') !== FALSE) { $select = 'FIRST '. (int) $limit - .($offset > 0 ? ' SKIP '. (int) $offset : ''); + .($offset ? ' SKIP '. (int) $offset : ''); } else { $select = 'ROWS ' - .($offset > 0 ? (int) $offset.' TO '.($limit + $offset) : (int) $limit); + .($offset ? (int) $offset.' TO '.($limit + $offset) : (int) $limit); } return preg_replace('`SELECT`i', 'SELECT '.$select, $sql); diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index 47dc55844..7634be2bb 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -124,7 +124,7 @@ class CI_DB_mssql_driver extends CI_DB { // Determine how identifiers are escaped $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi'); $query = $query->row_array(); - $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query->qi; + $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi']; $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']'); return $conn_id; @@ -288,7 +288,7 @@ class CI_DB_mssql_driver extends CI_DB { */ public function insert_id() { - $query = (self::_parse_major_version($this->version()) > 7) + $query = version_compare($this->version(), '8', '>=') ? 'SELECT SCOPE_IDENTITY() AS last_id' : 'SELECT @@IDENTITY AS last_id'; @@ -300,23 +300,6 @@ class CI_DB_mssql_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Parse major version - * - * Grabs the major version number from the - * database server version string passed in. - * - * @param string $version - * @return int major version number - */ - protected function _parse_major_version($version) - { - preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $version, $ver_info); - return $ver_info[1]; // return the major version b/c that's all we're interested in. - } - - // -------------------------------------------------------------------- - - /** * Version number query string * * @return string @@ -338,16 +321,17 @@ class CI_DB_mssql_driver extends CI_DB { */ protected function _list_tables($prefix_limit = FALSE) { - $sql = "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name"; + $sql = 'SELECT '.$this->escape_identifiers('name') + .' FROM '.$this->escape_identifiers('sysobjects') + .' WHERE '.$this->escape_identifiers('type')." = 'U'"; - // for future compatibility if ($prefix_limit !== FALSE AND $this->dbprefix !== '') { - //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); - return FALSE; // not currently supported + $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' " + .sprintf($this->_like_escape_str, $this->_like_escape_chr); } - return $sql; + return $sql.' ORDER BY '.$this->escape_identifiers('name'); } // -------------------------------------------------------------------- @@ -377,7 +361,7 @@ class CI_DB_mssql_driver extends CI_DB { */ protected function _field_data($table) { - return 'SELECT TOP 1 * FROM '.$table; + return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php index 8938d22b5..d11f015a6 100644 --- a/system/database/drivers/mysql/mysql_driver.php +++ b/system/database/drivers/mysql/mysql_driver.php @@ -64,6 +64,12 @@ class CI_DB_mysql_driver extends CI_DB { */ public $delete_hack = TRUE; + /** + * Constructor + * + * @param array + * @return void + */ public function __construct($params) { parent::__construct($params); @@ -74,6 +80,8 @@ class CI_DB_mysql_driver extends CI_DB { } } + // -------------------------------------------------------------------- + /** * Non-persistent database connection * @@ -335,7 +343,7 @@ class CI_DB_mysql_driver extends CI_DB { */ protected function _list_tables($prefix_limit = FALSE) { - $sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char; + $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database); if ($prefix_limit !== FALSE && $this->dbprefix !== '') { @@ -355,7 +363,7 @@ class CI_DB_mysql_driver extends CI_DB { * @param string the table name * @return string */ - public function _list_columns($table = '') + protected function _list_columns($table = '') { return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE); } @@ -453,23 +461,6 @@ class CI_DB_mysql_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Limit string - * - * Generates a platform-specific LIMIT clause - * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value - * @return string - */ - protected function _limit($sql, $limit, $offset) - { - return $sql.' LIMIT '.($offset == 0 ? '' : $offset.', ').$limit; - } - - // -------------------------------------------------------------------- - - /** * Close DB Connection * * @return void diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php index d22454d84..2ac75bad2 100644 --- a/system/database/drivers/mysql/mysql_forge.php +++ b/system/database/drivers/mysql/mysql_forge.php @@ -62,7 +62,7 @@ class CI_DB_mysql_forge extends CI_DB_forge { $sql .= "\n\t".$this->db->escape_identifiers($field); - empty($attributes['NAME']) OR ' '.$this->db->escape_identifiers($attributes['NAME']).' '; + empty($attributes['NAME']) OR $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' '; if ( ! empty($attributes['TYPE'])) { diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php index d3fb77a22..d1581bf1a 100644 --- a/system/database/drivers/mysqli/mysqli_driver.php +++ b/system/database/drivers/mysqli/mysqli_driver.php @@ -335,7 +335,7 @@ class CI_DB_mysqli_driver extends CI_DB { */ protected function _list_tables($prefix_limit = FALSE) { - $sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char; + $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database); if ($prefix_limit !== FALSE && $this->dbprefix !== '') { @@ -455,24 +455,6 @@ class CI_DB_mysqli_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Limit string - * - * Generates a platform-specific LIMIT clause - * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value - * @return string - */ - protected function _limit($sql, $limit, $offset) - { - return $sql.' LIMIT '.$limit - .($offset > 0 ? ' OFFSET '.$offset : ''); - } - - // -------------------------------------------------------------------- - - /** * Close DB Connection * * @return void diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php index e78091614..67bb0403b 100644 --- a/system/database/drivers/oci8/oci8_driver.php +++ b/system/database/drivers/oci8/oci8_driver.php @@ -66,6 +66,8 @@ class CI_DB_oci8_driver extends CI_DB { protected $_count_string = 'SELECT COUNT(1) AS '; protected $_random_keyword = ' ASC'; // not currently supported + protected $_reserved_identifiers = array('*', 'rownum'); + // Set "auto commit" by default public $commit_mode = OCI_COMMIT_ON_SUCCESS; @@ -464,11 +466,12 @@ class CI_DB_oci8_driver extends CI_DB { */ protected function _list_tables($prefix_limit = FALSE) { - $sql = 'SELECT TABLE_NAME FROM ALL_TABLES'; + $sql = 'SELECT "TABLE_NAME" FROM "ALL_TABLES"'; if ($prefix_limit !== FALSE && $this->dbprefix !== '') { - return $sql." WHERE TABLE_NAME LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + return $sql.' WHERE "TABLE_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' " + .sprintf($this->_like_escape_str, $this->_like_escape_chr); } return $sql; @@ -486,7 +489,7 @@ class CI_DB_oci8_driver extends CI_DB { */ protected function _list_columns($table = '') { - return 'SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = \''.$table.'\''; + return 'SELECT "COLUMN_NAME" FROM "all_tab_columns" WHERE "TABLE_NAME" = '.$this->escape($table); } // -------------------------------------------------------------------- @@ -501,7 +504,7 @@ class CI_DB_oci8_driver extends CI_DB { */ protected function _field_data($table) { - return 'SELECT * FROM '.$table.' WHERE rownum = 1'; + return 'SELECT * FROM '.$this->protect_identifiers($table).' WHERE rownum = 1'; } // -------------------------------------------------------------------- @@ -634,7 +637,7 @@ class CI_DB_oci8_driver extends CI_DB { { $this->limit_used = TRUE; return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit).')' - .($offset !== 0 ? ' WHERE rnum >= '.$offset : ''); + .($offset ? ' WHERE rnum >= '.$offset : ''); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php index 222c311c0..bd5759289 100644 --- a/system/database/drivers/odbc/odbc_driver.php +++ b/system/database/drivers/odbc/odbc_driver.php @@ -331,23 +331,6 @@ class CI_DB_odbc_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Limit string - * - * Generates a platform-specific LIMIT clause - * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value - * @return string - */ - protected function _limit($sql, $limit, $offset) - { - return $sql.($offset == 0 ? '' : $offset.', ').$limit; - } - - // -------------------------------------------------------------------- - - /** * Close DB Connection * * @return void diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php index e25013a52..a3ad46900 100644 --- a/system/database/drivers/pdo/pdo_driver.php +++ b/system/database/drivers/pdo/pdo_driver.php @@ -599,19 +599,12 @@ class CI_DB_pdo_driver extends CI_DB { */ protected function _limit($sql, $limit, $offset) { - if ($this->pdodriver === 'cubrid' OR $this->pdodriver === 'sqlite') + if ($this->pdodriver === 'pgsql') { - $offset = ($offset == 0) ? '' : $offset.', '; - - return $sql.'LIMIT '.$offset.$limit; + return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : ''); } - else - { - $sql .= 'LIMIT '.$limit; - $sql .= ($offset > 0) ? ' OFFSET '.$offset : ''; - return $sql; - } + return $sql.' LIMIT '.($offset ? $offset.', ' : '').$limit; } } diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php index ad9ac9000..e73122bc7 100644 --- a/system/database/drivers/postgre/postgre_driver.php +++ b/system/database/drivers/postgre/postgre_driver.php @@ -399,11 +399,13 @@ class CI_DB_postgre_driver extends CI_DB { */ protected function _list_tables($prefix_limit = FALSE) { - $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'"; + $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \'public\''; if ($prefix_limit !== FALSE && $this->dbprefix !== '') { - return $sql." AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + return $sql.' AND "table_name" LIKE \'' + .$this->escape_like_str($this->dbprefix)."%' " + .sprintf($this->_like_escape_str, $this->_like_escape_chr); } return $sql; @@ -421,7 +423,7 @@ class CI_DB_postgre_driver extends CI_DB { */ protected function _list_columns($table = '') { - return "SELECT column_name FROM information_schema.columns WHERE table_name = '".$table."'"; + return 'SELECT "column_name" FROM "information_schema"."columns" WHERE "table_name" = '.$this->escape($table); } // -------------------------------------------------------------------- @@ -580,7 +582,7 @@ class CI_DB_postgre_driver extends CI_DB { */ protected function _limit($sql, $limit, $offset) { - return $sql.' LIMIT '.$limit.($offset == 0 ? '' : ' OFFSET '.$offset); + return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : ''); } // -------------------------------------------------------------------- @@ -593,31 +595,31 @@ class CI_DB_postgre_driver extends CI_DB { * @param mixed * @param mixed * @param string + * @param mixed * @return object - * */ protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL) { - $type = $this->_group_get_type($type); - if ( ! is_array($key)) { $key = array($key => $value); } // If the escape value was not set will will base it on the global setting - if ( ! is_bool($escape)) - { - $escape = $this->_protect_identifiers; - } + is_bool($escape) OR $escape = $this->_protect_identifiers; foreach ($key as $k => $v) { - $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type; + $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) + ? $this->_group_get_type('') + : $this->_group_get_type($type); - $k = $this->_has_operator($k) - ? $this->protect_identifiers(substr($k, 0, strpos(rtrim($k), ' ')), FALSE, $escape).strchr(rtrim($k), ' ') - : $this->protect_identifiers($k, FALSE, $escape); + if ($escape === TRUE) + { + $k = (($op = $this->_get_operator($k)) !== FALSE) + ? $this->escape_identifiers(trim(substr($k, 0, strpos($k, $op)))).' '.strstr($k, $op) + : $this->escape_identifiers(trim($k)); + } if (is_null($v) && ! $this->_has_operator($k)) { diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php index 3305f6030..87be7a54a 100644 --- a/system/database/drivers/sqlite/sqlite_driver.php +++ b/system/database/drivers/sqlite/sqlite_driver.php @@ -360,23 +360,6 @@ class CI_DB_sqlite_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Limit string - * - * Generates a platform-specific LIMIT clause - * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value - * @return string - */ - protected function _limit($sql, $limit, $offset) - { - return $sql.'LIMIT '.($offset == 0 ? '' : $offset.', ').$limit; - } - - // -------------------------------------------------------------------- - - /** * Close DB Connection * * @return void diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php index bed61891b..1c6533f22 100644 --- a/system/database/drivers/sqlite3/sqlite3_driver.php +++ b/system/database/drivers/sqlite3/sqlite3_driver.php @@ -353,23 +353,6 @@ class CI_DB_sqlite3_driver extends CI_DB { // -------------------------------------------------------------------- /** - * Limit string - * - * Generates a platform-specific LIMIT clause - * - * @param string the sql query string - * @param int the number of rows to limit the query to - * @param int the offset value - * @return string - */ - protected function _limit($sql, $limit, $offset) - { - return $sql.' LIMIT '.($offset ? $offset.',' : '').$limit; - } - - // -------------------------------------------------------------------- - - /** * Close DB Connection * * @return void diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php index 825c02452..4fdc4aae0 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_driver.php +++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php @@ -91,7 +91,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { // Determine how identifiers are escaped $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi'); $query = $query->row_array(); - $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query->qi; + $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi']; $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']'); return $conn_id; @@ -284,7 +284,17 @@ class CI_DB_sqlsrv_driver extends CI_DB { */ protected function _list_tables($prefix_limit = FALSE) { - return "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name"; + $sql = 'SELECT '.$this->escape_identifiers('name') + .' FROM '.$this->escape_identifiers('sysobjects') + .' WHERE '.$this->escape_identifiers('type')." = 'U'"; + + if ($prefix_limit === TRUE && $this->dbprefix !== '') + { + $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' " + .sprintf($this->_escape_like_str, $this->_escape_like_chr); + } + + return $sql.' ORDER BY '.$this->escape_identifiers('name'); } // -------------------------------------------------------------------- @@ -314,7 +324,7 @@ class CI_DB_sqlsrv_driver extends CI_DB { */ protected function _field_data($table) { - return 'SELECT TOP 1 * FROM '.$table; + return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table); } // -------------------------------------------------------------------- diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php index d5036f645..fc790c585 100644 --- a/system/helpers/date_helper.php +++ b/system/helpers/date_helper.php @@ -93,8 +93,10 @@ if ( ! function_exists('mdate')) { return ''; } - - $time = ($time === '') ? now() : $time; + elseif (empty($time)) + { + $time = now(); + } $datestr = str_replace( '%\\', @@ -122,24 +124,19 @@ if ( ! function_exists('standard_date')) function standard_date($fmt = 'DATE_RFC822', $time = '') { $formats = array( - 'DATE_ATOM' => '%Y-%m-%dT%H:%i:%s%O', - 'DATE_COOKIE' => '%l, %d-%M-%y %H:%i:%s UTC', - 'DATE_ISO8601' => '%Y-%m-%dT%H:%i:%s%O', - 'DATE_RFC822' => '%D, %d %M %y %H:%i:%s %O', - 'DATE_RFC850' => '%l, %d-%M-%y %H:%i:%s UTC', - 'DATE_RFC1036' => '%D, %d %M %y %H:%i:%s %O', - 'DATE_RFC1123' => '%D, %d %M %Y %H:%i:%s %O', - 'DATE_RFC2822' => '%D, %d %M %Y %H:%i:%s %O', - 'DATE_RSS' => '%D, %d %M %Y %H:%i:%s %O', - 'DATE_W3C' => '%Y-%m-%dT%H:%i:%s%O' - ); - - if ( ! isset($formats[$fmt])) - { - return FALSE; - } - - return mdate($formats[$fmt], $time); + 'DATE_ATOM' => '%Y-%m-%dT%H:%i:%s%O', + 'DATE_COOKIE' => '%l, %d-%M-%y %H:%i:%s UTC', + 'DATE_ISO8601' => '%Y-%m-%dT%H:%i:%s%O', + 'DATE_RFC822' => '%D, %d %M %y %H:%i:%s %O', + 'DATE_RFC850' => '%l, %d-%M-%y %H:%i:%s UTC', + 'DATE_RFC1036' => '%D, %d %M %y %H:%i:%s %O', + 'DATE_RFC1123' => '%D, %d %M %Y %H:%i:%s %O', + 'DATE_RFC2822' => '%D, %d %M %Y %H:%i:%s %O', + 'DATE_RSS' => '%D, %d %M %Y %H:%i:%s %O', + 'DATE_W3C' => '%Y-%m-%dT%H:%i:%s%O' + ); + + return isset($formats[$fmt]) ? mdate($formats[$fmt], $time) : FALSE; } } @@ -163,20 +160,9 @@ if ( ! function_exists('timespan')) $CI =& get_instance(); $CI->lang->load('date'); - if ( ! is_numeric($seconds)) - { - $seconds = 1; - } - - if ( ! is_numeric($time)) - { - $time = time(); - } - - if ( ! is_numeric($units)) - { - $units = 7; - } + is_numeric($seconds) OR $seconds = 1; + is_numeric($time) OR $time = time(); + is_numeric($units) OR $units = 7; $seconds = ($time <= $seconds) ? 1 : $time - $seconds; @@ -185,7 +171,7 @@ if ( ! function_exists('timespan')) if ($years > 0) { - $str[] = $years.' '.$CI->lang->line((($years > 1) ? 'date_years' : 'date_year')); + $str[] = $years.' '.$CI->lang->line($years > 1 ? 'date_years' : 'date_year'); } $seconds -= $years * 31557600; @@ -195,7 +181,7 @@ if ( ! function_exists('timespan')) { if ($months > 0) { - $str[] = $months.' '.$CI->lang->line((($months > 1) ? 'date_months' : 'date_month')); + $str[] = $months.' '.$CI->lang->line($months > 1 ? 'date_months' : 'date_month'); } $seconds -= $months * 2629743; @@ -207,7 +193,7 @@ if ( ! function_exists('timespan')) { if ($weeks > 0) { - $str[] = $weeks.' '.$CI->lang->line((($weeks > 1) ? 'date_weeks' : 'date_week')); + $str[] = $weeks.' '.$CI->lang->line($weeks > 1 ? 'date_weeks' : 'date_week'); } $seconds -= $weeks * 604800; @@ -219,7 +205,7 @@ if ( ! function_exists('timespan')) { if ($days > 0) { - $str[] = $days.' '.$CI->lang->line((($days > 1) ? 'date_days' : 'date_day')); + $str[] = $days.' '.$CI->lang->line($days > 1 ? 'date_days' : 'date_day'); } $seconds -= $days * 86400; @@ -231,7 +217,7 @@ if ( ! function_exists('timespan')) { if ($hours > 0) { - $str[] = $hours.' '.$CI->lang->line((($hours > 1) ? 'date_hours' : 'date_hour')); + $str[] = $hours.' '.$CI->lang->line($hours > 1 ? 'date_hours' : 'date_hour'); } $seconds -= $hours * 3600; @@ -243,7 +229,7 @@ if ( ! function_exists('timespan')) { if ($minutes > 0) { - $str[] = $minutes.' '.$CI->lang->line((($minutes > 1) ? 'date_minutes' : 'date_minute')); + $str[] = $minutes.' '.$CI->lang->line($minutes > 1 ? 'date_minutes' : 'date_minute'); } $seconds -= $minutes * 60; @@ -251,7 +237,7 @@ if ( ! function_exists('timespan')) if (count($str) === 0) { - $str[] = $seconds.' '.$CI->lang->line((($seconds > 1) ? 'date_seconds' : 'date_second')); + $str[] = $seconds.' '.$CI->lang->line($seconds > 1 ? 'date_seconds' : 'date_second'); } return implode(', ', $str); @@ -278,12 +264,16 @@ if ( ! function_exists('days_in_month')) { return 0; } - - if ( ! is_numeric($year) OR strlen($year) !== 4) + elseif ( ! is_numeric($year) OR strlen($year) !== 4) { $year = date('Y'); } + if ($year >= 1970) + { + return (int) date('t', mktime(12, 0, 0, $month, 1, $year)); + } + if ($month == 2) { if ($year % 400 === 0 OR ($year % 4 === 0 && $year % 100 !== 0)) @@ -314,13 +304,13 @@ if ( ! function_exists('local_to_gmt')) $time = time(); } - return gmmktime( - date('H', $time), - date('i', $time), - date('s', $time), - date('m', $time), - date('d', $time), - date('Y', $time) + return mktime( + gmdate('G', $time), + gmdate('i', $time), + gmdate('s', $time), + gmdate('n', $time), + gmdate('j', $time), + gmdate('Y', $time) ); } } @@ -350,12 +340,7 @@ if ( ! function_exists('gmt_to_local')) $time += timezones($timezone) * 3600; - if ($dst === TRUE) - { - $time += 3600; - } - - return $time; + return ($dst === TRUE) ? $time + 3600 : $time; } } @@ -405,7 +390,7 @@ if ( ! function_exists('unix_to_human')) */ function unix_to_human($time = '', $seconds = FALSE, $fmt = 'us') { - $r = date('Y', $time).'-'.date('m', $time).'-'.date('d', $time).' '; + $r = date('Y', $time).'-'.date('m', $time).'-'.date('d', $time).' '; if ($fmt === 'us') { @@ -423,7 +408,7 @@ if ( ! function_exists('unix_to_human')) if ($fmt === 'us') { - $r .= ' '.date('A', $time); + return $r.' '.date('A', $time); } return $r; @@ -451,51 +436,33 @@ if ( ! function_exists('human_to_unix')) $datestr = preg_replace('/\040+/', ' ', trim($datestr)); - if ( ! preg_match('/^[0-9]{2,4}\-[0-9]{1,2}\-[0-9]{1,2}\s[0-9]{1,2}:[0-9]{1,2}(?::[0-9]{1,2})?(?:\s[AP]M)?$/i', $datestr)) + if ( ! preg_match('/^(\d{2}|\d{4})\-[0-9]{1,2}\-[0-9]{1,2}\s[0-9]{1,2}:[0-9]{1,2}(?::[0-9]{1,2})?(?:\s[AP]M)?$/i', $datestr)) { return FALSE; } $split = explode(' ', $datestr); - $ex = explode('-', $split['0']); - - $year = (strlen($ex[0]) === 2) ? '20'.$ex[0] : $ex[0]; - $month = (strlen($ex[1]) === 1) ? '0'.$ex[1] : $ex[1]; - $day = (strlen($ex[2]) === 1) ? '0'.$ex[2] : $ex[2]; + list($year, $month, $day) = explode('-', $split[0]); $ex = explode(':', $split['1']); - $hour = (strlen($ex[0]) === 1) ? '0'.$ex[0] : $ex[0]; - $min = (strlen($ex[1]) === 1) ? '0'.$ex[1] : $ex[1]; - - if (isset($ex[2]) && preg_match('/[0-9]{1,2}/', $ex[2])) - { - $sec = (strlen($ex[2]) === 1) ? '0'.$ex[2] : $ex[2]; - } - else - { - // Unless specified, seconds get set to zero. - $sec = '00'; - } + $hour = (int) $ex[0]; + $min = (int) $ex[1]; + $sec = ( ! empty($ex[2]) && preg_match('/[0-9]{1,2}/', $ex[2])) + ? (int) $ex[2] : 0; if (isset($split[2])) { $ampm = strtolower($split[2]); - if (substr($ampm, 0, 1) === 'p' && $hour < 12) + if ($ampm[0] === 'p' && $hour < 12) { $hour += 12; } - - if (substr($ampm, 0, 1) === 'a' && $hour == 12) - { - $hour = '00'; - } - - if (strlen($hour) === 1) + elseif ($ampm[0] === 'a' && $hour === 12) { - $hour = '0'.$hour; + $hour = 0; } } @@ -521,9 +488,13 @@ if ( ! function_exists('nice_date')) { return 'Unknown'; } + elseif (empty($format)) + { + $format = 'U'; + } // Date like: YYYYMM - if (preg_match('/^\d{6}$/', $bad_date)) + if (preg_match('/^\d{6}$/i', $bad_date)) { if (in_array(substr($bad_date, 0, 2), array('19', '20'))) { @@ -540,20 +511,15 @@ if ( ! function_exists('nice_date')) } // Date Like: YYYYMMDD - if (preg_match('/^\d{8}$/', $bad_date)) + if (preg_match('/^(\d{2})\d{2}(\d{4})$/i', $bad_date, $matches)) { - $month = substr($bad_date, 0, 2); - $day = substr($bad_date, 2, 2); - $year = substr($bad_date, 4, 4); - - return date($format, strtotime($month.'/01/'.$year)); + return date($format, strtotime($matches[1].'/01/'.$matches[2])); } // Date Like: MM-DD-YYYY __or__ M-D-YYYY (or anything in between) - if (preg_match('/^\d{1,2}-\d{1,2}-\d{4}$/', $bad_date)) + if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/i', $bad_date, $matches)) { - list($m, $d, $y) = explode('-', $bad_date); - return date($format, strtotime($y.'-'.$m.'-'.$d)); + return date($format, strtotime($matches[3].'-'.$matches[1].'-'.$matches[2])); } // Any other kind of string, when converted into UNIX time, @@ -581,9 +547,10 @@ if ( ! function_exists('timezone_menu')) * @param string timezone * @param string classname * @param string menu name + * @param mixed attributes * @return string */ - function timezone_menu($default = 'UTC', $class = '', $name = 'timezones') + function timezone_menu($default = 'UTC', $class = '', $name = 'timezones', $attributes = '') { $CI =& get_instance(); $CI->lang->load('date'); @@ -597,7 +564,22 @@ if ( ! function_exists('timezone_menu')) $menu .= ' class="'.$class.'"'; } - $menu .= ">\n"; + // Generate a string from the attributes submitted, if any + if (is_array($attributes)) + { + $atts = ''; + foreach ($attributes as $key => $val) + { + $atts .= ' '.$key.'="'.$val.'"'; + } + $attributes = $atts; + } + elseif (is_string($attributes) && strlen($attributes) > 0) + { + $attributes = ' '.$attributes; + } + + $menu .= $attributes.">\n"; foreach (timezones() as $key => $val) { @@ -675,8 +657,6 @@ if ( ! function_exists('timezones')) return $zones; } - $tz = ($tz === 'GMT') ? 'UTC' : $tz; - return isset($zones[$tz]) ? $zones[$tz] : 0; } } diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php index 5efbc4930..09c4de578 100644 --- a/system/helpers/download_helper.php +++ b/system/helpers/download_helper.php @@ -46,7 +46,7 @@ if ( ! function_exists('force_download')) * * @param string filename * @param mixed the data to be downloaded - * @param bool wether to try and send the actual file MIME type + * @param bool whether to try and send the actual file MIME type * @return void */ function force_download($filename = '', $data = '', $set_mime = FALSE) diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php index be616f62d..7270ee32c 100644 --- a/system/helpers/file_helper.php +++ b/system/helpers/file_helper.php @@ -47,6 +47,7 @@ if ( ! function_exists('read_file')) * This function is DEPRECATED and should be removed in * CodeIgniter 3.1+. Use file_get_contents() instead. * + * @deprecated * @param string path to file * @return string */ diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php index 984634315..0c5d55037 100644 --- a/system/helpers/form_helper.php +++ b/system/helpers/form_helper.php @@ -62,9 +62,11 @@ if ( ! function_exists('form_open')) { $action = $CI->config->site_url($action); } - - // If no action is provided then set to the current url - $action OR $action = $CI->config->site_url($CI->uri->uri_string()); + elseif ( ! $action) + { + // If no action is provided then set to the current url + $action = $CI->config->site_url($CI->uri->uri_string()); + } $form = '<form action="'.$action.'"'._attributes_to_string($attributes, TRUE).">\n"; @@ -76,7 +78,7 @@ if ( ! function_exists('form_open')) if (is_array($hidden) && count($hidden) > 0) { - $form .= sprintf('<div style="display:none;">%s</div>', form_hidden($hidden)); + $form .= '<div style="display:none;">'.form_hidden($hidden).'</div>'; } return $form; diff --git a/system/helpers/security_helper.php b/system/helpers/security_helper.php index 3e6e91435..0e8e9f93d 100644 --- a/system/helpers/security_helper.php +++ b/system/helpers/security_helper.php @@ -80,6 +80,7 @@ if ( ! function_exists('do_hash')) * This function is DEPRECATED and should be removed in * CodeIgniter 3.1+. Use hash() instead. * + * @deprecated * @param string * @param string * @return string @@ -107,7 +108,8 @@ if ( ! function_exists('strip_image_tags')) */ function strip_image_tags($str) { - return preg_replace(array('#<img\s+.*?src\s*=\s*["\'](.+?)["\'].*?\>#', '#<img\s+.*?src\s*=\s*(.+?).*?\>#'), '\\1', $str); + $CI =& get_instance(); + return $CI->security->strip_image_tags($str); } } @@ -123,7 +125,7 @@ if ( ! function_exists('encode_php_tags')) */ function encode_php_tags($str) { - return str_replace(array('<?php', '<?PHP', '<?', '?>'), array('<?php', '<?PHP', '<?', '?>'), $str); + return str_replace(array('<?', '?>'), array('<?', '?>'), $str); } } diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php index 2bd41b04d..39e6343a6 100644 --- a/system/helpers/url_helper.php +++ b/system/helpers/url_helper.php @@ -199,26 +199,33 @@ if ( ! function_exists('anchor_popup')) if ($attributes === FALSE) { - return '<a href="javascript:void(0);" onclick="window.open(\''.$site_url."', '_blank');\">".$title.'</a>'; + return '<a href="'.$site_url.'" onclick="window.open(\''.$site_url."', '_blank'); return false;\">".$title.'</a>'; } if ( ! is_array($attributes)) { - $attributes = array(); + $attributes = array($attributes); + + // Ref: http://www.w3schools.com/jsref/met_win_open.asp + $window_name = '_blank'; + } + elseif ( ! empty($attributes['window_name'])) + { + $window_name = $attributes['window_name']; + unset($attributes['window_name']); } - foreach (array('width' => '800', 'height' => '600', 'scrollbars' => 'yes', 'status' => 'yes', 'resizable' => 'yes', 'screenx' => '0', 'screeny' => '0', ) as $key => $val) + foreach (array('width' => '800', 'height' => '600', 'scrollbars' => 'yes', 'status' => 'yes', 'resizable' => 'yes', 'screenx' => '0', 'screeny' => '0') as $key => $val) { $atts[$key] = isset($attributes[$key]) ? $attributes[$key] : $val; unset($attributes[$key]); } - if ($attributes !== '') - { - $attributes = _parse_attributes($attributes); - } + $attributes = empty($attributes) ? '' : _parse_attributes($attributes); - return '<a href="javascript:void(0);" onclick="window.open(\''.$site_url."', '_blank', '"._parse_attributes($atts, TRUE)."');\"".$attributes.'>'.$title.'</a>'; + return '<a href="'.$site_url + .'" onclick="window.open(\''.$site_url."', '".$window_name."', '"._parse_attributes($atts, TRUE)."'); return false;\"" + .$attributes.'>'.$title.'</a>'; } } @@ -519,7 +526,7 @@ if ( ! function_exists('redirect')) * @param int * @return string */ - function redirect($uri = '', $method = 'auto', $http_response_code = 302) + function redirect($uri = '', $method = 'auto', $code = NULL) { if ( ! preg_match('#^https?://#i', $uri)) { @@ -531,14 +538,22 @@ if ( ! function_exists('redirect')) { $method = 'refresh'; } + elseif ($method !== 'refresh' && (empty($code) OR ! is_numeric($code))) + { + // Reference: http://en.wikipedia.org/wiki/Post/Redirect/Get + $code = (isset($_SERVER['REQUEST_METHOD'], $_SERVER['SERVER_PROTOCOL']) + && $_SERVER['REQUEST_METHOD'] === 'POST' + && $_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.1') + ? 303 : 302; + } - switch($method) + switch ($method) { case 'refresh': header('Refresh:0;url='.$uri); break; default: - header('Location: '.$uri, TRUE, $http_response_code); + header('Location: '.$uri, TRUE, $code); break; } exit; diff --git a/system/language/english/migration_lang.php b/system/language/english/migration_lang.php index 9e3e18807..af920660c 100644 --- a/system/language/english/migration_lang.php +++ b/system/language/english/migration_lang.php @@ -26,7 +26,7 @@ */ $lang['migration_none_found'] = "No migrations were found."; -$lang['migration_not_found'] = "This migration could not be found."; +$lang['migration_not_found'] = "No migration could be found with the version number: %d."; $lang['migration_multiple_version'] = "This are multiple migrations with the same version number: %d."; $lang['migration_class_doesnt_exist'] = "The migration class \"%s\" could not be found."; $lang['migration_missing_up_method'] = "The migration class \"%s\" is missing an 'up' method."; diff --git a/system/libraries/Cache/drivers/Cache_file.php b/system/libraries/Cache/drivers/Cache_file.php index 08231963e..37d77c268 100644 --- a/system/libraries/Cache/drivers/Cache_file.php +++ b/system/libraries/Cache/drivers/Cache_file.php @@ -73,7 +73,7 @@ class CI_Cache_file extends CI_Driver { $data = unserialize(file_get_contents($this->_cache_path.$id)); - if (time() > $data['time'] + $data['ttl']) + if ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl']) { unlink($this->_cache_path.$id); return FALSE; diff --git a/system/libraries/Calendar.php b/system/libraries/Calendar.php index 969a7610a..a49f171b9 100644 --- a/system/libraries/Calendar.php +++ b/system/libraries/Calendar.php @@ -155,7 +155,7 @@ class CI_Calendar { public function generate($year = '', $month = '', $data = array()) { // Set and validate the supplied month/year - if ($year === '') + if (empty($year)) { $year = date('Y', $this->local_time); } @@ -168,7 +168,7 @@ class CI_Calendar { $year = '20'.$year; } - if ($month === '') + if (empty($month)) { $month = date('m', $this->local_time); } diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 09f217530..dd5477e05 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -247,7 +247,7 @@ class CI_Email { $name = $replyto; } - if (strncmp($name, '"', 1) !== 0) + if (strpos($name, '"') !== 0) { $name = '"'.$name.'"'; } @@ -606,7 +606,7 @@ class CI_Email { foreach ($this->_base_charsets as $charset) { - if (strncmp($charset, $this->charset, strlen($charset)) === 0) + if (strpos($charset, $this->charset) === 0) { $this->_encoding = '7bit'; } @@ -651,7 +651,7 @@ class CI_Email { protected function _set_date() { $timezone = date('Z'); - $operator = (strncmp($timezone, '-', 1) === 0) ? '-' : '+'; + $operator = ($timezone[0] === '-') ? '-' : '+'; $timezone = abs($timezone); $timezone = floor($timezone/3600) * 100 + ($timezone % 3600) / 60; @@ -1481,7 +1481,7 @@ class CI_Email { $this->_set_error_message($reply); - if (strncmp($reply, '250', 3) !== 0) + if (strpos($reply, '250') !== 0) { $this->_set_error_message('lang:email_smtp_error', $reply); return FALSE; @@ -1637,7 +1637,7 @@ class CI_Email { $reply = $this->_get_smtp_data(); - if (strncmp($reply, '334', 3) !== 0) + if (strpos($reply, '334') !== 0) { $this->_set_error_message('lang:email_failed_smtp_login', $reply); return FALSE; @@ -1647,7 +1647,7 @@ class CI_Email { $reply = $this->_get_smtp_data(); - if (strncmp($reply, '334', 3) !== 0) + if (strpos($reply, '334') !== 0) { $this->_set_error_message('lang:email_smtp_auth_un', $reply); return FALSE; @@ -1657,7 +1657,7 @@ class CI_Email { $reply = $this->_get_smtp_data(); - if (strncmp($reply, '235', 3) !== 0) + if (strpos($reply, '235') !== 0) { $this->_set_error_message('lang:email_smtp_auth_pw', $reply); return FALSE; diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php index 6cbe032c7..8e03e91f3 100644 --- a/system/libraries/Form_validation.php +++ b/system/libraries/Form_validation.php @@ -571,8 +571,7 @@ class CI_Form_validation { { foreach ($postdata as $key => $val) { - $this->_execute($row, $rules, $val, $cycles); - $cycles++; + $this->_execute($row, $rules, $val, $key); } return; @@ -649,7 +648,12 @@ class CI_Form_validation { } else { - $postdata = $this->_field_data[$row['field']]['postdata']; + // If we get an array field, but it's not expected - then it is most likely + // somebody messing with the form on the client side, so we'll just consider + // it an empty field + $postdata = is_array($this->_field_data[$row['field']]['postdata']) + ? NULL + : $this->_field_data[$row['field']]['postdata']; } // Is the rule a callback? @@ -993,15 +997,19 @@ class CI_Form_validation { * Minimum Length * * @param string - * @param int + * @param string * @return bool */ public function min_length($str, $val) { - if (preg_match('/[^0-9]/', $val)) + if ( ! is_numeric($val)) { return FALSE; } + else + { + $val = (int) $val; + } return (MB_ENABLED === TRUE) ? ($val <= mb_strlen($str)) @@ -1014,15 +1022,19 @@ class CI_Form_validation { * Max Length * * @param string - * @param int + * @param string * @return bool */ public function max_length($str, $val) { - if (preg_match('/[^0-9]/', $val)) + if ( ! is_numeric($val)) { return FALSE; } + else + { + $val = (int) $val; + } return (MB_ENABLED === TRUE) ? ($val >= mb_strlen($str)) @@ -1035,15 +1047,19 @@ class CI_Form_validation { * Exact Length * * @param string - * @param int + * @param string * @return bool */ public function exact_length($str, $val) { - if (preg_match('/[^0-9]/', $val)) + if ( ! is_numeric($val)) { return FALSE; } + else + { + $val = (int) $val; + } return (MB_ENABLED === TRUE) ? (mb_strlen($str) === $val) @@ -1113,7 +1129,7 @@ class CI_Form_validation { */ public function alpha($str) { - return (bool) preg_match('/^[a-z]+$/i', $str); + return ctype_alpha($str); } // -------------------------------------------------------------------- @@ -1126,7 +1142,7 @@ class CI_Form_validation { */ public function alpha_numeric($str) { - return (bool) preg_match('/^[a-z0-9]+$/i', $str); + return ctype_alnum((string) $str); } // -------------------------------------------------------------------- @@ -1248,7 +1264,7 @@ class CI_Form_validation { */ public function is_natural($str) { - return (bool) preg_match('/^[0-9]+$/', $str); + return ctype_digit((string) $str); } // -------------------------------------------------------------------- @@ -1261,7 +1277,7 @@ class CI_Form_validation { */ public function is_natural_no_zero($str) { - return ($str !== 0 && preg_match('/^[0-9]+$/', $str)); + return ($str != 0 && ctype_digit((string) $str)); } // -------------------------------------------------------------------- @@ -1344,7 +1360,7 @@ class CI_Form_validation { */ public function strip_image_tags($str) { - return $this->CI->input->strip_image_tags($str); + return $this->CI->security->strip_image_tags($str); } // -------------------------------------------------------------------- @@ -1370,7 +1386,7 @@ class CI_Form_validation { */ public function encode_php_tags($str) { - return str_replace(array('<?php', '<?PHP', '<?', '?>'), array('<?php', '<?PHP', '<?', '?>'), $str); + return str_replace(array('<?', '?>'), array('<?', '?>'), $str); } // -------------------------------------------------------------------- diff --git a/system/libraries/Ftp.php b/system/libraries/Ftp.php index 461e884fb..76f5e151a 100644 --- a/system/libraries/Ftp.php +++ b/system/libraries/Ftp.php @@ -445,7 +445,7 @@ class CI_FTP { * Set file permissions * * @param string the file path - * @param string the permissions + * @param int the permissions * @return bool */ public function chmod($path, $perm) diff --git a/system/libraries/Javascript.php b/system/libraries/Javascript.php index 98fec61d3..5c8b09217 100644 --- a/system/libraries/Javascript.php +++ b/system/libraries/Javascript.php @@ -620,7 +620,7 @@ class CI_Javascript { $this->_javascript_location = $this->CI->config->item('javascript_location'); } - if ($relative === TRUE OR strncmp($external_file, 'http://', 7) === 0 OR strncmp($external_file, 'https://', 8) === 0) + if ($relative === TRUE OR strpos($external_file, 'http://') === 0 OR strpos($external_file, 'https://') === 0) { $str = $this->_open_script($external_file); } diff --git a/system/libraries/Migration.php b/system/libraries/Migration.php index 4391b235d..3a1e7a0ad 100644 --- a/system/libraries/Migration.php +++ b/system/libraries/Migration.php @@ -179,7 +179,7 @@ class CI_Migration { // We now prepare to actually DO the migrations // But first let's make sure that everything is the way it should be - for ($i = $start; $i !== $stop; $i += $step) + for ($i = $start; $i != $stop; $i += $step) { $f = glob(sprintf($this->_migration_path.'%03d_*.php', $i)); diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php index cdec736ff..75745dd48 100644 --- a/system/libraries/Pagination.php +++ b/system/libraries/Pagination.php @@ -36,39 +36,40 @@ */ class CI_Pagination { - public $base_url = ''; // The page we are linking to - public $prefix = ''; // A custom prefix added to the path. - public $suffix = ''; // A custom suffix added to the path. - public $total_rows = 0; // Total number of items (database results) - public $per_page = 10; // Max number of items you want shown per page - public $num_links = 2; // Number of "digit" links to show before/after the currently viewed page - public $cur_page = 0; // The current page being viewed - public $use_page_numbers = FALSE; // Use page number for segment instead of offset - public $first_link = '‹ First'; - public $next_link = '>'; - public $prev_link = '<'; - public $last_link = 'Last ›'; - public $uri_segment = 3; - public $full_tag_open = ''; - public $full_tag_close = ''; - public $first_tag_open = ''; - public $first_tag_close = ' '; - public $last_tag_open = ' '; - public $last_tag_close = ''; - public $first_url = ''; // Alternative URL for the First Page. - public $cur_tag_open = ' <strong>'; - public $cur_tag_close = '</strong>'; - public $next_tag_open = ' '; - public $next_tag_close = ' '; - public $prev_tag_open = ' '; - public $prev_tag_close = ''; - public $num_tag_open = ' '; - public $num_tag_close = ''; - public $page_query_string = FALSE; - public $query_string_segment = 'per_page'; - public $display_pages = TRUE; - public $anchor_class = ''; - public $attr_rel = TRUE; + protected $base_url = ''; // The page we are linking to + protected $prefix = ''; // A custom prefix added to the path. + protected $suffix = ''; // A custom suffix added to the path. + protected $total_rows = 0; // Total number of items (database results) + protected $per_page = 10; // Max number of items you want shown per page + protected $num_links = 2; // Number of "digit" links to show before/after the currently viewed page + protected $cur_page = 0; // The current page being viewed + protected $use_page_numbers = FALSE; // Use page number for segment instead of offset + protected $first_link = '‹ First'; + protected $next_link = '>'; + protected $prev_link = '<'; + protected $last_link = 'Last ›'; + protected $uri_segment = 3; + protected $full_tag_open = ''; + protected $full_tag_close = ''; + protected $first_tag_open = ''; + protected $first_tag_close = ' '; + protected $last_tag_open = ' '; + protected $last_tag_close = ''; + protected $first_url = ''; // Alternative URL for the First Page. + protected $cur_tag_open = ' <strong>'; + protected $cur_tag_close = '</strong>'; + protected $next_tag_open = ' '; + protected $next_tag_close = ' '; + protected $prev_tag_open = ' '; + protected $prev_tag_close = ''; + protected $num_tag_open = ' '; + protected $num_tag_close = ''; + protected $page_query_string = FALSE; + protected $query_string_segment = 'per_page'; + protected $display_pages = TRUE; + protected $_attributes = ''; + protected $_link_types = array(); + protected $reuse_query_string = FALSE; /** * Constructor @@ -92,15 +93,29 @@ class CI_Pagination { */ public function initialize($params = array()) { + $attributes = array(); + + if (isset($params['attributes']) && is_array($params['attributes'])) + { + $attributes = $params['attributes']; + unset($params['attributes']); + } + + // Deprecated legacy support for the anchor_class option + // Should be removed in CI 3.1+ + if (isset($params['anchor_class'])) + { + empty($params['anchor_class']) OR $attributes['class'] = $params['anchor_class']; + unset($params['anchor_class']); + } + + $this->_parse_attributes($attributes); + if (count($params) > 0) { foreach ($params as $key => $val) { - if ($key === 'anchor_class') - { - $this->anchor_class = ($val) ? 'class="'.$val.'" ' : ''; - } - elseif (isset($this->$key)) + if (isset($this->$key)) { $this->$key = $val; } @@ -208,29 +223,46 @@ class CI_Pagination { // And here we go... $output = ''; + $query_string = ''; + + // Add anything in the query string back to the links + // Note: Nothing to do with query_string_segment or any other query string options + if ($this->reuse_query_string === TRUE) + { + $get = $CI->input->get(); + + // Unset the controll, method, old-school routing options + unset($get['c'], $get['m'], $get[$this->query_string_segment]); + + // Put everything else onto the end + $query_string = (strpos($this->base_url, '&') !== FALSE ? '&' : '?') . http_build_query($get, '', '&'); + + // Add this after the suffix to put it into more links easily + $this->suffix .= $query_string; + } // Render the "First" link if ($this->first_link !== FALSE && $this->cur_page > ($this->num_links + 1)) { $first_url = ($this->first_url === '') ? $this->base_url : $this->first_url; - $output .= $this->first_tag_open.'<a '.$this->anchor_class.'href="'.$first_url.'"'.$this->_attr_rel('start').'>' + $output .= $this->first_tag_open.'<a href="'.$first_url.'"'.$this->_attributes.$this->_attr_rel('start').'>' .$this->first_link.'</a>'.$this->first_tag_close; } // Render the "previous" link - if ($this->prev_link !== FALSE && $this->cur_page !== 1) + if ($this->prev_link !== FALSE && $this->cur_page !== 1) { $i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page; if ($i === $base_page && $this->first_url !== '') { - $output .= $this->prev_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'"'.$this->_attr_rel('prev').'>' + $output .= $this->prev_tag_open.'<a href="'.$this->first_url.$query_string.'"'.$this->_attributes.$this->_attr_rel('prev').'>' .$this->prev_link.'</a>'.$this->prev_tag_close; } else { - $i = ($i === $base_page) ? '' : $this->prefix.$i.$this->suffix; - $output .= $this->prev_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$i.'"'.$this->_attr_rel('prev').'>' + $append = ($i === $base_page) ? $query_string : $this->prefix.$i.$this->suffix; + $output .= $this->prev_tag_open.'<a href="'.$this->base_url.$append.'"'.$this->_attributes.$this->_attr_rel('prev').'>' .$this->prev_link.'</a>'.$this->prev_tag_close; } @@ -243,7 +275,6 @@ class CI_Pagination { for ($loop = $start -1; $loop <= $end; $loop++) { $i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page; - if ($i >= $base_page) { if ($this->cur_page === $loop) @@ -253,17 +284,15 @@ class CI_Pagination { else { $n = ($i === $base_page) ? '' : $i; - - if ($n === '' && $this->first_url !== '') + if ($n === '' && ! empty($this->first_url)) { - $output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'"'.$this->_attr_rel('start').'>' + $output .= $this->num_tag_open.'<a href="'.$this->first_url.$query_string.'"'.$this->_attributes.$this->_attr_rel('start').'>' .$loop.'</a>'.$this->num_tag_close; } else { - $n = ($n === '') ? '' : $this->prefix.$n.$this->suffix; - - $output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$n.'"'.$this->_attr_rel().'>' + $append = ($n === '') ? $query_string : $this->prefix.$n.$this->suffix; + $output .= $this->num_tag_open.'<a href="'.$this->base_url.$append.'"'.$this->_attributes.$this->_attr_rel('start').'>' .$loop.'</a>'.$this->num_tag_close; } } @@ -276,8 +305,8 @@ class CI_Pagination { { $i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page; - $output .= $this->next_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$this->_attr_rel('next').'>' - .$this->next_link.'</a>'.$this->next_tag_close; + $output .= $this->next_tag_open.'<a href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$this->_attributes + .$this->_attr_rel('next').'>'.$this->next_link.'</a>'.$this->next_tag_close; } // Render the "Last" link @@ -285,7 +314,7 @@ class CI_Pagination { { $i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page; - $output .= $this->last_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$this->_attr_rel().'>' + $output .= $this->last_tag_open.'<a href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$this->_attributes.'>' .$this->last_link.'</a>'.$this->last_tag_close; } @@ -300,23 +329,44 @@ class CI_Pagination { // -------------------------------------------------------------------- /** + * Parse attributes + * + * @param array + * @return void + */ + protected function _parse_attributes($attributes) + { + isset($attributes['rel']) OR $attributes['rel'] = TRUE; + $this->_link_types = ($attributes['rel']) + ? array('start' => 'start', 'prev' => 'prev', 'next' => 'next') + : array(); + unset($attributes['rel']); + + $this->_attributes = ''; + foreach ($attributes as $key => $value) + { + $this->_attributes .= ' '.$key.'="'.$value.'"'; + } + } + + // -------------------------------------------------------------------- + + /** * Add "rel" attribute * + * @link http://www.w3.org/TR/html5/links.html#linkTypes * @param string * @return string */ - protected function _attr_rel($value = '') + protected function _attr_rel($type) { - if (empty($this->attr_rel) OR ($this->attr_rel === TRUE && empty($value))) - { - return ''; - } - elseif ( ! is_bool($this->attr_rel)) + if (isset($this->_link_types[$type])) { - $value = $this->attr_rel; + unset($this->_link_types[$type]); + return ' rel="'.$type.'"'; } - return ' rel="'.$value.'"'; + return ''; } } diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php index d96088c14..1e961f6df 100644 --- a/system/libraries/Profiler.php +++ b/system/libraries/Profiler.php @@ -116,6 +116,12 @@ class CI_Profiler { */ public function set_sections($config) { + if (isset($config['query_toggle_count'])) + { + $this->_query_toggle_count = (int) $config['query_toggle_count']; + unset($config['query_toggle_count']); + } + foreach ($config as $method => $enable) { if (in_array($method, $this->_available_sections)) diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php index c96daaf15..d381440cd 100644 --- a/system/libraries/Upload.php +++ b/system/libraries/Upload.php @@ -59,6 +59,7 @@ class CI_Upload { public $error_msg = array(); public $mimes = array(); public $remove_spaces = TRUE; + public $detect_mime = TRUE; public $xss_clean = FALSE; public $temp_prefix = 'temp_file_'; public $client_name = ''; @@ -116,6 +117,7 @@ class CI_Upload { 'image_size_str' => '', 'error_msg' => array(), 'remove_spaces' => TRUE, + 'detect_mime' => TRUE, 'xss_clean' => FALSE, 'temp_prefix' => 'temp_file_', 'client_name' => '' @@ -209,7 +211,13 @@ class CI_Upload { // Set the uploaded data as class variables $this->file_temp = $_FILES[$field]['tmp_name']; $this->file_size = $_FILES[$field]['size']; - $this->_file_mime_type($_FILES[$field]); + + // Skip MIME type detection? + if ($this->detect_mime !== FALSE) + { + $this->_file_mime_type($_FILES[$field]); + } + $this->file_type = preg_replace('/^(.+?);.*$/', '\\1', $this->file_type); $this->file_type = strtolower(trim(stripslashes($this->file_type), '"')); $this->file_name = $this->_prep_filename($_FILES[$field]['name']); @@ -990,7 +998,7 @@ class CI_Upload { */ if (function_exists('finfo_file')) { - $finfo = finfo_open(FILEINFO_MIME); + $finfo = @finfo_open(FILEINFO_MIME); if (is_resource($finfo)) // It is possible that a FALSE value is returned, if there is no magic MIME database file found on the system { $mime = @finfo_file($finfo, $file['tmp_name']); @@ -1021,7 +1029,9 @@ class CI_Upload { */ if (DIRECTORY_SEPARATOR !== '\\') { - $cmd = 'file --brief --mime '.escapeshellarg($file['tmp_name']).' 2>&1'; + $cmd = function_exists('escapeshellarg') + ? 'file --brief --mime '.escapeshellarg($file['tmp_name']).' 2>&1' + : 'file --brief --mime '.$file['tmp_name'].' 2>&1'; if (function_exists('exec')) { diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php index 6f3542333..eac4ac118 100644 --- a/system/libraries/Xmlrpc.php +++ b/system/libraries/Xmlrpc.php @@ -778,7 +778,7 @@ class XML_RPC_Message extends CI_Xmlrpc } // Check for HTTP 200 Response - if (strncmp($data, 'HTTP', 4) === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data)) + if (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data)) { $errstr = substr($data, 0, strpos($data, "\n")-1); return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')'); diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php index be930b0f9..e81f2ca9a 100644 --- a/system/libraries/Xmlrpcs.php +++ b/system/libraries/Xmlrpcs.php @@ -303,7 +303,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc $methName = $m->method_name; // Check to see if it is a system call - $system_call = (strncmp($methName, 'system', 5) === 0); + $system_call = (strpos($methName, 'system') === 0); if ($this->xss_clean === FALSE) { diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php index e0dc637ad..5c4c257f8 100644 --- a/system/libraries/Zip.php +++ b/system/libraries/Zip.php @@ -40,7 +40,7 @@ * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/libraries/zip.html */ -class CI_Zip { +class CI_Zip { /** * Zip data in string form |