diff options
Diffstat (limited to 'system')
38 files changed, 767 insertions, 169 deletions
diff --git a/system/core/Benchmark.php b/system/core/Benchmark.php index 2fabdf46e..2fabdf46e 100755..100644 --- a/system/core/Benchmark.php +++ b/system/core/Benchmark.php diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index 8159b19f5..8159b19f5 100755..100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php diff --git a/system/core/Common.php b/system/core/Common.php index c08755c91..1708653e7 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -240,7 +240,7 @@ if ( ! function_exists('get_config')) } // Is the config file in the environment folder? - if (defined(ENVIRONMENT) && file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php')) + if (defined('ENVIRONMENT') && file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php')) { require($file_path); } diff --git a/system/core/Config.php b/system/core/Config.php index 3de1bcb96..3de1bcb96 100755..100644 --- a/system/core/Config.php +++ b/system/core/Config.php diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php index 8c32085fe..8c32085fe 100755..100644 --- a/system/core/Exceptions.php +++ b/system/core/Exceptions.php diff --git a/system/core/Hooks.php b/system/core/Hooks.php index 29fd88201..29fd88201 100755..100644 --- a/system/core/Hooks.php +++ b/system/core/Hooks.php diff --git a/system/core/Input.php b/system/core/Input.php index b986c4973..162e40c85 100755..100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -376,14 +376,26 @@ class CI_Input { /** * Validate IP Address * - * Updated version suggested by Geert De Deckere - * * @param string + * @param string 'ipv4' or 'ipv6' * @return bool */ - public function valid_ip($ip) + public function valid_ip($ip, $which = '') { - return (bool) filter_var($ip, FILTER_VALIDATE_IP); + switch (strtolower($which)) + { + case 'ipv4': + $which = FILTER_FLAG_IPV4; + break; + case 'ipv6': + $which = FILTER_FLAG_IPV6; + break; + default: + $which = NULL; + break; + } + + return (bool) filter_var($ip, FILTER_VALIDATE_IP, $which); } // -------------------------------------------------------------------- diff --git a/system/core/Lang.php b/system/core/Lang.php index 3001f1b13..3001f1b13 100755..100644 --- a/system/core/Lang.php +++ b/system/core/Lang.php diff --git a/system/core/Loader.php b/system/core/Loader.php index 09e948714..94739c74a 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -668,7 +668,7 @@ class CI_Loader { * @param bool * @return void */ - public function add_package_path($path, $view_cascade=TRUE) + public function add_package_path($path, $view_cascade = TRUE) { $path = rtrim($path, '/').'/'; diff --git a/system/core/Model.php b/system/core/Model.php index 9bc9f879f..9bc9f879f 100755..100644 --- a/system/core/Model.php +++ b/system/core/Model.php diff --git a/system/core/Output.php b/system/core/Output.php index 5588ffe8e..5588ffe8e 100755..100644 --- a/system/core/Output.php +++ b/system/core/Output.php diff --git a/system/core/Router.php b/system/core/Router.php index 5bc053045..5bc053045 100755..100644 --- a/system/core/Router.php +++ b/system/core/Router.php diff --git a/system/core/Security.php b/system/core/Security.php index 4593a1090..4593a1090 100755..100644 --- a/system/core/Security.php +++ b/system/core/Security.php diff --git a/system/core/URI.php b/system/core/URI.php index a575bc36e..2e661ed4c 100755..100644 --- a/system/core/URI.php +++ b/system/core/URI.php @@ -119,7 +119,7 @@ class CI_URI { } // No PATH_INFO?... What about QUERY_STRING? - $path = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING'); + $path = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING'); if (trim($path, '/') !== '') { $this->_set_uri_string($path); @@ -163,7 +163,7 @@ class CI_URI { * @param string * @return void */ - public function _set_uri_string($str) + protected function _set_uri_string($str) { // Filter out control characters $str = remove_invisible_characters($str, FALSE); @@ -177,8 +177,8 @@ class CI_URI { /** * Detects the URI * - * This function will detect the URI automatically and fix the query string - * if necessary. + * This function will detect the URI automatically + * and fix the query string if necessary. * * @return string */ @@ -189,7 +189,6 @@ class CI_URI { return ''; } - $uri = $_SERVER['REQUEST_URI']; if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0) { $uri = substr($uri, strlen($_SERVER['SCRIPT_NAME'])); @@ -198,14 +197,19 @@ class CI_URI { { $uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME']))); } + else + { + $uri = $_SERVER['REQUEST_URI']; + } // This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct // URI is found, and also fixes the QUERY_STRING server var and $_GET array. - if (strncmp($uri, '?/', 2) === 0) + if (strpos($uri, '?/') === 0) { $uri = substr($uri, 2); } - $parts = preg_split('#\?#i', $uri, 2); + + $parts = explode('?', $uri, 2); $uri = $parts[0]; if (isset($parts[1])) { @@ -223,7 +227,7 @@ class CI_URI { return '/'; } - $uri = parse_url($uri, PHP_URL_PATH); + $uri = parse_url('pseudo://hostname/'.$uri, PHP_URL_PATH); // Do some final cleaning of the URI and return it return str_replace(array('//', '../'), '/', trim($uri, '/')); diff --git a/system/database/DB.php b/system/database/DB.php index 00d14b43e..00d14b43e 100755..100644 --- a/system/database/DB.php +++ b/system/database/DB.php diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index 65f1f18d0..d056bdb90 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -596,35 +596,53 @@ abstract class CI_DB_driver { */ public function compile_binds($sql, $binds) { - if (strpos($sql, $this->bind_marker) === FALSE) + if (empty($binds) OR empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE) { return $sql; } - - if ( ! is_array($binds)) + elseif ( ! is_array($binds)) { $binds = array($binds); + $bind_count = 1; + } + else + { + // Make sure we're using numeric keys + $binds = array_values($binds); + $bind_count = count($binds); } - // Get the sql segments around the bind markers - $segments = explode($this->bind_marker, $sql); + // We'll need the marker length later + $ml = strlen($this->bind_marker); - // The count of bind should be 1 less then the count of segments - // If there are more bind arguments trim it down - if (count($binds) >= count($segments)) + // Make sure not to replace a chunk inside a string that happens to match the bind marker + if ($c = preg_match_all("/'[^']*'/i", $sql, $matches)) { - $binds = array_slice($binds, 0, count($segments)-1); + $c = preg_match_all('/'.preg_quote($this->bind_marker).'/i', + str_replace($matches[0], + str_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]), + $sql, $c), + $matches, PREG_OFFSET_CAPTURE); + + // Bind values' count must match the count of markers in the query + if ($bind_count !== $c) + { + return $sql; + } + } + elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker).'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count) + { + return $sql; } - // Construct the binded query - $result = $segments[0]; - $i = 0; - foreach ($binds as $bind) + do { - $result .= $this->escape($bind).$segments[++$i]; + $c--; + $sql = substr_replace($sql, $this->escape($binds[$c]), $matches[0][$c][1], $ml); } + while ($c !== 0); - return $result; + return $sql; } // -------------------------------------------------------------------- @@ -1062,7 +1080,7 @@ abstract class CI_DB_driver { */ protected function _has_operator($str) { - return (bool) preg_match('/(\s|<|>|!|=|IS NULL|IS NOT NULL)/i', trim($str)); + return (bool) preg_match('/(\s|<|>|!|=|IS NULL|IS NOT NULL|BETWEEN)/i', trim($str)); } // -------------------------------------------------------------------- @@ -1300,36 +1318,63 @@ abstract class CI_DB_driver { $escaped_array = array(); foreach ($item as $k => $v) { - $escaped_array[$this->protect_identifiers($k)] = $this->protect_identifiers($v); + $escaped_array[$this->protect_identifiers($k)] = $this->protect_identifiers($v, $prefix_single, $protect_identifiers, $field_exists); } return $escaped_array; } + // This is basically a bug fix for queries that use MAX, MIN, etc. + // If a parenthesis is found we know that we do not need to + // escape the data or add a prefix. There's probably a more graceful + // way to deal with this, but I'm not thinking of it -- Rick + if (strpos($item, '(') !== FALSE) + { + return $item; + } + // Convert tabs or multiple spaces into single spaces - $item = preg_replace('/[\t ]+/', ' ', $item); + $item = preg_replace('/\s+/', ' ', $item); + + static $preg_ec = array(); + + if (empty($preg_ec)) + { + 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); + } + } // 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 - if (strpos($item, ' ') !== FALSE) + preg_match('/^(('.$preg_ec[0].'[^'.$preg_ec[1].']+'.$preg_ec[1].')|([^'.$preg_ec[0].'][^\s]+))( AS)*(.+)*$/i', $item, $matches); + + if (isset($matches[4])) { - $alias = strstr($item, ' '); - $item = substr($item, 0, - strlen($alias)); + $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]; + } } else { $alias = ''; } - // This is basically a bug fix for queries that use MAX, MIN, etc. - // If a parenthesis is found we know that we do not need to - // escape the data or add a prefix. There's probably a more graceful - // way to deal with this, but I'm not thinking of it -- Rick - if (strpos($item, '(') !== FALSE) - { - return $item.$alias; - } - // Break the string apart if it contains periods, then insert the table prefix // in the correct location, assuming the period doesn't indicate that we're dealing // with an alias. While we're at it, we will escape the components diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php index ff5eb3fe6..9b7639289 100644 --- a/system/database/DB_forge.php +++ b/system/database/DB_forge.php @@ -72,6 +72,11 @@ abstract class CI_DB_forge { return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; } + if ( ! empty($this->db->data_cache['db_names'])) + { + $this->db->data_cache['db_names'][] = $db_name; + } + return TRUE; } @@ -99,6 +104,15 @@ abstract class CI_DB_forge { return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; } + if ( ! empty($this->db->data_cache['db_names'])) + { + $key = array_search(strtolower($db_name), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); + if ($key !== FALSE) + { + unset($this->db->data_cache['db_names'][$key]); + } + } + return TRUE; } @@ -209,7 +223,18 @@ abstract class CI_DB_forge { $sql = $this->_create_table($this->db->dbprefix.$table, $this->fields, $this->primary_keys, $this->keys, $if_not_exists); $this->_reset(); - return is_bool($sql) ? $sql : $this->db->query($sql); + + if (is_bool($sql)) + { + return $sql; + } + + if (($result = $this->db->query($sql)) !== FALSE && ! empty($this->db->data_cache['table_names'])) + { + $this->db->data_cache['table_names'][] = $$this->db->dbprefix.$table; + } + + return $result; } // -------------------------------------------------------------------- @@ -231,7 +256,19 @@ abstract class CI_DB_forge { return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; } - return $this->db->query(sprintf($this->_drop_table, $this->db->escape_identifiers($this->db->dbprefix.$table_name))); + $result = $this->db->query(sprintf($this->_drop_table, $this->db->escape_identifiers($this->db->dbprefix.$table_name))); + + // Update table list cache + if ($result && ! empty($this->db->data_cache['table_names'])) + { + $key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE); + if ($key !== FALSE) + { + unset($this->db->data_cache['table_names'][$key]); + } + } + + return $result; } // -------------------------------------------------------------------- @@ -255,10 +292,21 @@ abstract class CI_DB_forge { return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; } - return $this->db->query(sprintf($this->_rename_table, + $result = $this->db->query(sprintf($this->_rename_table, $this->db->escape_identifiers($this->db->dbprefix.$table_name), $this->db->escape_identifiers($this->db->dbprefix.$new_table_name)) ); + + if ($result && ! empty($this->db->data_cache['table_names'])) + { + $key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE); + if ($key !== FALSE) + { + $this->db->data_cache['table_names'][$key] = $this->db->dbprefix.$new_table_name; + } + } + + return $result; } // -------------------------------------------------------------------- diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index 3ed556212..488b294e4 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -53,7 +53,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver { protected $qb_keys = array(); protected $qb_limit = FALSE; protected $qb_offset = FALSE; - protected $qb_order = FALSE; protected $qb_orderby = array(); protected $qb_set = array(); protected $qb_wherein = array(); @@ -84,6 +83,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * Generates the SELECT portion of the query * * @param string + * @param mixed * @return object */ public function select($select = '*', $escape = NULL) @@ -93,6 +93,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $select = explode(',', $select); } + // If the escape value was not set will will base it on the global setting + is_bool($escape) OR $escape = $this->_protect_identifiers; + foreach ($select as $val) { $val = trim($val); @@ -321,15 +324,16 @@ 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 * @return object */ - public function join($table, $cond, $type = '') + public function join($table, $cond, $type = '', $escape = TRUE) { if ($type !== '') { $type = strtoupper(trim($type)); - if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'))) + if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'), TRUE)) { $type = ''; } @@ -343,12 +347,39 @@ 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); - // Strip apart the condition and protect the identifiers - if (preg_match('/([\[\w\.]+)([\W\s]+)(.+)/', $cond, $match)) + // Split multiple conditions + if ($escape === TRUE && preg_match_all('/\sAND\s|\sOR\s/i', $cond, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) + { + $newcond = ''; + $m[0][] = array('', strlen($cond)); + + for ($i = 0, $c = count($m[0]), $s = 0; + $i < $c; + $s += $m[0][$i][1] + strlen($m[0][$i][0]), $i++) + { + $temp = substr($cond, $s, $m[0][$i][1]); + + $newcond .= preg_match('/([\[\w\.-]+)([\W\s]+)(.+)/i', $temp, $match) + ? $this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]) + : $temp; + + $newcond .= $m[0][$i][0]; + } + + $cond = $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]); } + // Do we want to escape the table name? + if ($escape === TRUE) + { + $table = $this->protect_identifiers($table, TRUE, NULL, FALSE); + } + // Assemble the JOIN statement $this->qb_join[] = $join = $type.'JOIN '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' ON '.$cond; @@ -371,6 +402,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * @param mixed * @param mixed + * @param bool * @return object */ public function where($key, $value = NULL, $escape = TRUE) @@ -388,6 +420,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * @param mixed * @param mixed + * @param bool * @return object */ public function or_where($key, $value = NULL, $escape = TRUE) @@ -405,6 +438,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param mixed * @param mixed * @param string + * @param mixed * @return object */ protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL) @@ -417,15 +451,16 @@ abstract class CI_DB_query_builder extends CI_DB_driver { } // If the escape value was not set will will base it on the global setting - if ( ! is_bool($escape)) - { - $escape = $this->_protect_identifiers; - } + $escape = $this->_protect_identifiers; foreach ($key as $k => $v) { $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $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 (is_null($v) && ! $this->_has_operator($k)) { // value appears not to have been set, assign the test to IS NULL @@ -436,7 +471,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver { { if ($escape === TRUE) { - $k = $this->protect_identifiers($k, FALSE, $escape); $v = ' '.$this->escape($v); } @@ -445,10 +479,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $k .= ' = '; } } - else - { - $k = $this->protect_identifiers($k, FALSE, $escape); - } $this->qb_where[] = $prefix.$k.$v; if ($this->qb_caching === TRUE) @@ -547,7 +577,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { { if ($key === NULL OR $values === NULL) { - return; + return $this; } $type = $this->_group_get_type($type); @@ -853,6 +883,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * @param string * @param string + * @param bool * @return object */ public function having($key, $value = '', $escape = TRUE) @@ -869,6 +900,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * @param string * @param string + * @param bool * @return object */ public function or_having($key, $value = '', $escape = TRUE) @@ -885,6 +917,8 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * @param string * @param string + * @param string + * @param bool * @return object */ protected function _having($key, $value = '', $type = 'AND ', $escape = TRUE) @@ -943,7 +977,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { } elseif (trim($direction) !== '') { - $direction = (in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE)) ? ' '.$direction : ' ASC'; + $direction = in_array(strtoupper(trim($direction)), array('ASC', 'DESC'), TRUE) ? ' '.$direction : ' ASC'; } @@ -955,7 +989,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $part = trim($part); if ( ! in_array($part, $this->qb_aliased_tables)) { - $part = $this->protect_identifiers(trim($part)); + $part = preg_match('/^(.+)\s+(ASC|DESC)$/i', $part, $matches) + ? $this->protect_identifiers(rtrim($matches[1])).' '.$matches[2] + : $this->protect_identifiers($part); } $temp[] = $part; @@ -963,12 +999,11 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $orderby = implode(', ', $temp); } - elseif ($direction !== $this->_random_keyword) + elseif ($direction !== $this->_random_keyword && $escape === TRUE) { - if ($escape === TRUE) - { - $orderby = $this->protect_identifiers($orderby); - } + $orderby = preg_match('/^(.+)\s+(ASC|DESC)$/i', $orderby, $matches) + ? $this->protect_identifiers(rtrim($matches[1])).' '.$matches[2] + : $this->protect_identifiers($orderby); } $this->qb_orderby[] = $orderby_statement = $orderby.$direction; @@ -995,7 +1030,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { { $this->qb_limit = (int) $value; - if ( ! is_null($offset)) + if ( ! empty($offset)) { $this->qb_offset = (int) $offset; } @@ -1070,7 +1105,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->from($table); } - $select = $this->_compile_select(); + $select = $this->_compile_select(); if ($reset === TRUE) { @@ -1093,7 +1128,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param string the offset clause * @return object */ - public function get($table = '', $limit = null, $offset = null) + public function get($table = '', $limit = NULL, $offset = NULL) { if ($table !== '') { @@ -1101,7 +1136,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->from($table); } - if ( ! is_null($limit)) + if ( ! empty($limit)) { $this->limit($limit, $offset); } @@ -1166,7 +1201,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->where($where); } - if ( ! is_null($limit)) + if ( ! empty($limit)) { $this->limit($limit, $offset); } @@ -1275,11 +1310,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { ksort($row); // puts $row in the same order as our keys - if ($escape === FALSE) - { - $this->qb_set[] = '('.implode(',', $row).')'; - } - else + if ($escape !== FALSE) { $clean = array(); foreach ($row as $value) @@ -1287,8 +1318,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $clean[] = $this->escape($value); } - $this->qb_set[] = '('.implode(',', $clean).')'; + $row = $clean; } + + $this->qb_set[] = '('.implode(',', $row).')'; } foreach ($keys as $k) @@ -1553,7 +1586,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->where($where); } - if ($limit != NULL) + if ( ! empty($limit)) { $this->limit($limit); } @@ -1874,7 +1907,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->where($where); } - if ($limit != NULL) + if ( ! empty($limit)) { $this->limit($limit); } @@ -1915,7 +1948,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { return 'DELETE FROM '.$table .(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '') - .($limit ? ' LIMIT '.$limit : ''); + .($limit ? ' LIMIT '.(int) $limit : ''); } // -------------------------------------------------------------------- @@ -1985,7 +2018,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { if (strpos($table, ' ') !== FALSE) { // if the alias is written with the AS keyword, remove it - $table = preg_replace('/ AS /i', ' ', $table); + $table = preg_replace('/\s+AS\s+/i', ' ', $table); // Grab the alias $table = trim(strrchr($table, ' ')); @@ -2088,10 +2121,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver { if (count($this->qb_orderby) > 0) { $sql .= "\nORDER BY ".implode(', ', $this->qb_orderby); - if ($this->qb_order !== FALSE) - { - $sql .= ($this->qb_order === 'desc') ? ' DESC' : ' ASC'; - } } // Write the "LIMIT" portion of the query @@ -2321,8 +2350,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { 'qb_no_escape' => array(), 'qb_distinct' => FALSE, 'qb_limit' => FALSE, - 'qb_offset' => FALSE, - 'qb_order' => FALSE + 'qb_offset' => FALSE ) ); } @@ -2345,8 +2373,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { 'qb_like' => array(), 'qb_orderby' => array(), 'qb_keys' => array(), - 'qb_limit' => FALSE, - 'qb_order' => FALSE + 'qb_limit' => FALSE ) ); } diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php index 02c921834..6a3b40779 100644 --- a/system/database/DB_utility.php +++ b/system/database/DB_utility.php @@ -35,7 +35,6 @@ abstract class CI_DB_utility extends CI_DB_forge { public $db; - public $data_cache = array(); // Platform specific SQL strings // Just setting those defaults to FALSE as they are mostly MySQL-specific @@ -60,29 +59,29 @@ abstract class CI_DB_utility extends CI_DB_forge { public function list_databases() { // Is there a cached result? - if (isset($this->data_cache['db_names'])) + if (isset($this->db->data_cache['db_names'])) { - return $this->data_cache['db_names']; + return $this->db->data_cache['db_names']; } elseif ($this->_list_databases === FALSE) { return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE; } - $this->data_cache['db_names'] = array(); + $this->db->data_cache['db_names'] = array(); $query = $this->db->query($this->_list_databases); if ($query === FALSE) { - return $this->data_cache['db_names']; + return $this->db->data_cache['db_names']; } for ($i = 0, $c = count($query); $i < $c; $i++) { - $this->data_cache['db_names'] = current($query[$i]); + $this->db->data_cache['db_names'] = current($query[$i]); } - return $this->data_cache['db_names']; + return $this->db->data_cache['db_names']; } // -------------------------------------------------------------------- diff --git a/system/database/drivers/cubrid/cubrid_utility.php b/system/database/drivers/cubrid/cubrid_utility.php index c8cee99b6..ea8feb4e2 100644 --- a/system/database/drivers/cubrid/cubrid_utility.php +++ b/system/database/drivers/cubrid/cubrid_utility.php @@ -41,12 +41,12 @@ class CI_DB_cubrid_utility extends CI_DB_utility { */ public function list_databases() { - if (isset($this->data_cache['db_names'])) + if (isset($this->db->data_cache['db_names'])) { - return $this->data_cache['db_names']; + return $this->db->data_cache['db_names']; } - return $this->data_cache['db_names'] = cubrid_list_dbs($this->db->conn_id); + return $this->db->data_cache['db_names'] = cubrid_list_dbs($this->db->conn_id); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/interbase/interbase_forge.php b/system/database/drivers/interbase/interbase_forge.php index 3f9967f1f..d1b006e80 100644 --- a/system/database/drivers/interbase/interbase_forge.php +++ b/system/database/drivers/interbase/interbase_forge.php @@ -67,6 +67,14 @@ class CI_DB_interbase_forge extends CI_DB_forge { { return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; } + elseif ( ! empty($this->db->data_cache['db_names'])) + { + $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); + if ($key !== FALSE) + { + unset($this->db->data_cache['db_names'][$key]); + } + } return TRUE; } diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index 87094e76e..47dc55844 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -504,7 +504,30 @@ class CI_DB_mssql_driver extends CI_DB { */ protected function _limit($sql, $limit, $offset) { - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.($limit + $offset).' ', $sql); + // As of SQL Server 2012 (11.0.*) OFFSET is supported + if (version_compare($this->version(), '11', '>=')) + { + return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY'; + } + + $limit = $offset + $limit; + + // As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported, + // however an ORDER BY clause is required for it to work + if (version_compare($this->version(), '9', '>=') && $offset && ! empty($this->qb_orderby)) + { + $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby); + + // We have to strip the ORDER BY clause + $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby))); + + return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit; + } + + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/mysqli/mysqli_utility.php b/system/database/drivers/mysqli/mysqli_utility.php index 27d4ef817..5d2bdbce0 100644 --- a/system/database/drivers/mysqli/mysqli_utility.php +++ b/system/database/drivers/mysqli/mysqli_utility.php @@ -46,9 +46,124 @@ class CI_DB_mysqli_utility extends CI_DB_utility { */ protected function _backup($params = array()) { - // Currently unsupported - return $this->db->display_error('db_unsuported_feature'); + if (count($params) === 0) + { + return FALSE; + } + + // Extract the prefs for simplicity + extract($params); + + // Build the output + $output = ''; + foreach ( (array) $tables as $table) + { + // Is the table in the "ignore" list? + if (in_array($table, (array) $ignore, TRUE)) + { + continue; + } + + // Get the table schema + $query = $this->db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table)); + + // No result means the table name was invalid + if ($query === FALSE) + { + continue; + } + + // Write out the table schema + $output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline; + + if ($add_drop === TRUE) + { + $output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline; + } + + $i = 0; + $result = $query->result_array(); + foreach ($result[0] as $val) + { + if ($i++ % 2) + { + $output .= $val.';'.$newline.$newline; + } + } + + // If inserts are not needed we're done... + if ($add_insert === FALSE) + { + continue; + } + + // Grab all the data from the current table + $query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table)); + + if ($query->num_rows() === 0) + { + continue; + } + + // Fetch the field names and determine if the field is an + // integer type. We use this info to decide whether to + // surround the data with quotes or not + + $i = 0; + $field_str = ''; + $is_int = array(); + while ($field = $query->result_id->fetch_field()) + { + // Most versions of MySQL store timestamp as a string + $is_int[$i] = in_array(strtolower($field->type), + array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'), + TRUE); + + // Create a string of field names + $field_str .= $this->db->escape_identifiers($field->name).', '; + $i++; + } + + // Trim off the end comma + $field_str = preg_replace('/, $/' , '', $field_str); + + // Build the insert string + foreach ($query->result_array() as $row) + { + $val_str = ''; + + $i = 0; + foreach ($row as $v) + { + // Is the value NULL? + if ($v === NULL) + { + $val_str .= 'NULL'; + } + else + { + // Escape the data if it's not an integer + $val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v; + } + + // Append a comma + $val_str .= ', '; + $i++; + } + + // Remove the comma at the end of the string + $val_str = preg_replace('/, $/' , '', $val_str); + + // Build the INSERT string + $output .= 'INSERT INTO '.$this->db->protect_identifiers($table).' ('.$field_str.') VALUES ('.$val_str.');'.$newline; + } + + $output .= $newline.$newline; + } + + return $output; } + } /* End of file mysqli_utility.php */ diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php index 7375fbf71..ad9ac9000 100644 --- a/system/database/drivers/postgre/postgre_driver.php +++ b/system/database/drivers/postgre/postgre_driver.php @@ -615,6 +615,10 @@ class CI_DB_postgre_driver extends CI_DB { { $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $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 (is_null($v) && ! $this->_has_operator($k)) { // value appears not to have been set, assign the test to IS NULL @@ -625,7 +629,6 @@ class CI_DB_postgre_driver extends CI_DB { { if ($escape === TRUE) { - $k = $this->protect_identifiers($k, FALSE, $escape); $v = ' '.$this->escape($v); } elseif (is_bool($v)) @@ -638,10 +641,6 @@ class CI_DB_postgre_driver extends CI_DB { $k .= ' = '; } } - else - { - $k = $this->protect_identifiers($k, FALSE, $escape); - } $this->qb_where[] = $prefix.$k.$v; if ($this->qb_caching === TRUE) diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php index 71eed7df4..e02e327f3 100644 --- a/system/database/drivers/sqlite/sqlite_forge.php +++ b/system/database/drivers/sqlite/sqlite_forge.php @@ -61,6 +61,14 @@ class CI_DB_sqlite_forge extends CI_DB_forge { { return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; } + elseif ( ! empty($this->db->data_cache['db_names'])) + { + $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); + if ($key !== FALSE) + { + unset($this->db->data_cache['db_names'][$key]); + } + } return TRUE; } diff --git a/system/database/drivers/sqlite3/sqlite3_forge.php b/system/database/drivers/sqlite3/sqlite3_forge.php index f8bd11656..6a76ba929 100644 --- a/system/database/drivers/sqlite3/sqlite3_forge.php +++ b/system/database/drivers/sqlite3/sqlite3_forge.php @@ -66,6 +66,14 @@ class CI_DB_sqlite3_forge extends CI_DB_forge { { return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE; } + elseif ( ! empty($this->db->data_cache['db_names'])) + { + $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); + if ($key !== FALSE) + { + unset($this->db->data_cache['db_names'][$key]); + } + } return TRUE; } diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php index 655a9e90b..825c02452 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_driver.php +++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 1.0 + * @since Version 2.0.3 * @filesource */ @@ -463,9 +463,28 @@ class CI_DB_sqlsrv_driver extends CI_DB { protected function _limit($sql, $limit, $offset) { // As of SQL Server 2012 (11.0.*) OFFSET is supported - return version_compare($this->version(), '11', '>=') - ? $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY' - : preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.($limit + $offset).' ', $sql); + if (version_compare($this->version(), '11', '>=')) + { + return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY'; + } + + $limit = $offset + $limit; + + // An ORDER BY clause is required for ROW_NUMBER() to work + if ($offset && ! empty($this->qb_orderby)) + { + $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby); + + // We have to strip the ORDER BY clause + $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby))); + + return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n" + .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) + ."\n) ".$this->escape_identifiers('CI_subquery') + ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit; + } + + return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); } // -------------------------------------------------------------------- diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php index e6f7e1ac1..ccdb36929 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_forge.php +++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 1.0 + * @since Version 2.0.3 * @filesource */ diff --git a/system/database/drivers/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php index f802383d2..f9d5a0d29 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_result.php +++ b/system/database/drivers/sqlsrv/sqlsrv_result.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 1.0 + * @since Version 2.0.3 * @filesource */ diff --git a/system/database/drivers/sqlsrv/sqlsrv_utility.php b/system/database/drivers/sqlsrv/sqlsrv_utility.php index 5a71b1628..d518cc15a 100644 --- a/system/database/drivers/sqlsrv/sqlsrv_utility.php +++ b/system/database/drivers/sqlsrv/sqlsrv_utility.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com - * @since Version 1.0 + * @since Version 2.0.3 * @filesource */ diff --git a/system/libraries/Cache/Cache.php b/system/libraries/Cache/Cache.php index 53f9f81a7..4395cf411 100644 --- a/system/libraries/Cache/Cache.php +++ b/system/libraries/Cache/Cache.php @@ -41,11 +41,12 @@ class CI_Cache extends CI_Driver_Library { * * @var array */ - protected $valid_drivers = array( + protected $valid_drivers = array( 'cache_apc', + 'cache_dummy', 'cache_file', 'cache_memcached', - 'cache_dummy', + 'cache_redis', 'cache_wincache' ); diff --git a/system/libraries/Cache/drivers/Cache_file.php b/system/libraries/Cache/drivers/Cache_file.php index 5170de821..08231963e 100644 --- a/system/libraries/Cache/drivers/Cache_file.php +++ b/system/libraries/Cache/drivers/Cache_file.php @@ -26,7 +26,7 @@ */ /** - * CodeIgniter Memcached Caching Class + * CodeIgniter File Caching Class * * @package CodeIgniter * @subpackage Libraries @@ -171,13 +171,13 @@ class CI_Cache_file extends CI_Driver { { $mtime = filemtime($this->_cache_path.$id); - if ( ! isset($data['data']['ttl'])) + if ( ! isset($data['ttl'])) { return FALSE; } return array( - 'expire' => $mtime + $data['data']['ttl'], + 'expire' => $mtime + $data['ttl'], 'mtime' => $mtime ); } diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php new file mode 100644 index 000000000..e4a26b5f0 --- /dev/null +++ b/system/libraries/Cache/drivers/Cache_redis.php @@ -0,0 +1,236 @@ +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +/** + * CodeIgniter + * + * An open source application development framework for PHP 5.2.4 or newer + * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to obtain it + * through the world wide web, please send an email to + * licensing@ellislab.com so we can send you a copy immediately. + * + * @package CodeIgniter + * @author EllisLab Dev Team + * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc. + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * @link http://codeigniter.com + * @since Version 3.0 + * @filesource + */ + +/** + * CodeIgniter Redis Caching Class + * + * @package CodeIgniter + * @subpackage Libraries + * @category Core + * @author Anton Lindqvist <anton@qvister.se> + * @link + */ +class CI_Cache_redis extends CI_Driver +{ + /** + * Default config + * + * @static + * @var array + */ + protected static $_default_config = array( + 'host' => '127.0.0.1', + 'password' => NULL, + 'port' => 6379, + 'timeout' => 0 + ); + + /** + * Redis connection + * + * @var Redis + */ + protected $_redis; + + // ------------------------------------------------------------------------ + + /** + * Get cache + * + * @param string Cache key identifier + * @return mixed + */ + public function get($key) + { + return $this->_redis->get($key); + } + + // ------------------------------------------------------------------------ + + /** + * Save cache + * + * @param string Cache key identifier + * @param mixed Data to save + * @param int Time to live + * @return bool + */ + public function save($key, $value, $ttl = NULL) + { + return ($ttl) + ? $this->_redis->setex($key, $ttl, $value) + : $this->_redis->set($key, $value); + } + + // ------------------------------------------------------------------------ + + /** + * Delete from cache + * + * @param string Cache key + * @return bool + */ + public function delete($key) + { + return ($this->_redis->delete($key) === 1); + } + + // ------------------------------------------------------------------------ + + /** + * Clean cache + * + * @return bool + * @see Redis::flushDB() + */ + public function clean() + { + return $this->_redis->flushDB(); + } + + // ------------------------------------------------------------------------ + + /** + * Get cache driver info + * + * @param string Not supported in Redis. + * Only included in order to offer a + * consistent cache API. + * @return array + * @see Redis::info() + */ + public function cache_info($type = NULL) + { + return $this->_redis->info(); + } + + // ------------------------------------------------------------------------ + + /** + * Get cache metadata + * + * @param string Cache key + * @return array + */ + public function get_metadata($key) + { + $value = $this->get($key); + + if ($value) + { + return array( + 'expire' => time() + $this->_redis->ttl($key), + 'data' => $value + ); + } + + return FALSE; + } + + // ------------------------------------------------------------------------ + + /** + * Check if Redis driver is supported + * + * @return bool + */ + public function is_supported() + { + if (extension_loaded('redis')) + { + $this->_setup_redis(); + return TRUE; + } + else + { + log_message('error', 'The Redis extension must be loaded to use Redis cache.'); + return FALSE; + } + } + + // ------------------------------------------------------------------------ + + /** + * Setup Redis config and connection + * + * Loads Redis config file if present. Will halt execution + * if a Redis connection can't be established. + * + * @return bool + * @see Redis::connect() + */ + protected function _setup_redis() + { + $config = array(); + $CI =& get_instance(); + + if ($CI->config->load('redis', TRUE, TRUE)) + { + $config += $CI->config->item('redis'); + } + + $config = array_merge(self::$_default_config, $config); + + $this->_redis = new Redis(); + + try + { + $this->_redis->connect($config['host'], $config['port'], $config['timeout']); + } + catch (RedisException $e) + { + show_error('Redis connection refused. ' . $e->getMessage()); + } + + if (isset($config['password'])) + { + $this->_redis->auth($config['password']); + } + } + + // ------------------------------------------------------------------------ + + /** + + * Class destructor + * + * Closes the connection to Redis if present. + * + * @return void + */ + public function __destruct() + { + if ($this->_redis) + { + $this->_redis->close(); + } + } + +} + +/* End of file Cache_redis.php */ +/* Location: ./system/libraries/Cache/drivers/Cache_redis.php */
\ No newline at end of file diff --git a/system/libraries/Email.php b/system/libraries/Email.php index c70144f7c..09f217530 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -1599,7 +1599,7 @@ class CI_Email { $this->_debug_msg[] = '<pre>'.$cmd.': '.$reply.'</pre>'; - if (substr($reply, 0, 3) !== $resp) + if ( (int) substr($reply, 0, 3) !== $resp) { $this->_set_error_message('lang:email_smtp_error', $reply); return FALSE; diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php index ce5e030b0..8ffd93aea 100644 --- a/system/libraries/Encrypt.php +++ b/system/libraries/Encrypt.php @@ -213,6 +213,7 @@ class CI_Encrypt { $dec = base64_decode($string); if (($dec = $this->mcrypt_decode($dec, $key)) === FALSE) { + $this->set_mode($current_mode); return FALSE; } diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php index 225325d6f..6cbe032c7 100644 --- a/system/libraries/Form_validation.php +++ b/system/libraries/Form_validation.php @@ -187,6 +187,12 @@ class CI_Form_validation { return $this; } + // Convert an array of rules to a string + if (is_array($rules)) + { + $rules = implode('|', $rules); + } + // No fields? Nothing to do... if ( ! is_string($field) OR ! is_string($rules) OR $field === '') { @@ -1089,11 +1095,12 @@ class CI_Form_validation { * Validate IP Address * * @param string + * @param string 'ipv4' or 'ipv6' to validate a specific IP format * @return bool */ - public function valid_ip($ip) + public function valid_ip($ip, $which = '') { - return $this->CI->input->valid_ip($ip); + return $this->CI->input->valid_ip($ip, $which); } // -------------------------------------------------------------------- diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php index a91159c98..cdec736ff 100644 --- a/system/libraries/Pagination.php +++ b/system/libraries/Pagination.php @@ -36,38 +36,39 @@ */ class CI_Pagination { - 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 $anchor_class = ''; + 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; /** * Constructor @@ -97,7 +98,7 @@ class CI_Pagination { { if ($key === 'anchor_class') { - $this->anchor_class = ($val !== '') ? 'class="'.$val.'" ' : ''; + $this->anchor_class = ($val) ? 'class="'.$val.'" ' : ''; } elseif (isset($this->$key)) { @@ -145,7 +146,7 @@ class CI_Pagination { if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE) { - if ($CI->input->get($this->query_string_segment) !== $base_page) + if ($CI->input->get($this->query_string_segment) != $base_page) { $this->cur_page = (int) $CI->input->get($this->query_string_segment); } @@ -212,7 +213,8 @@ class CI_Pagination { 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->first_link.'</a>'.$this->first_tag_close; + $output .= $this->first_tag_open.'<a '.$this->anchor_class.'href="'.$first_url.'"'.$this->_attr_rel('start').'>' + .$this->first_link.'</a>'.$this->first_tag_close; } // Render the "previous" link @@ -222,12 +224,14 @@ class CI_Pagination { if ($i === $base_page && $this->first_url !== '') { - $output .= $this->prev_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'">'.$this->prev_link.'</a>'.$this->prev_tag_close; + $output .= $this->prev_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'"'.$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->prev_link.'</a>'.$this->prev_tag_close; + $output .= $this->prev_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$i.'"'.$this->_attr_rel('prev').'>' + .$this->prev_link.'</a>'.$this->prev_tag_close; } } @@ -252,13 +256,15 @@ class CI_Pagination { if ($n === '' && $this->first_url !== '') { - $output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'">'.$loop.'</a>'.$this->num_tag_close; + $output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'"'.$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.'">'.$loop.'</a>'.$this->num_tag_close; + $output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$n.'"'.$this->_attr_rel().'>' + .$loop.'</a>'.$this->num_tag_close; } } } @@ -270,7 +276,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->next_link.'</a>'.$this->next_tag_close; + $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; } // Render the "Last" link @@ -278,7 +285,8 @@ 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->last_link.'</a>'.$this->last_tag_close; + $output .= $this->last_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$this->_attr_rel().'>' + .$this->last_link.'</a>'.$this->last_tag_close; } // Kill double slashes. Note: Sometimes we can end up with a double slash @@ -289,6 +297,28 @@ class CI_Pagination { return $this->full_tag_open.$output.$this->full_tag_close; } + // -------------------------------------------------------------------- + + /** + * Add "rel" attribute + * + * @param string + * @return string + */ + protected function _attr_rel($value = '') + { + if (empty($this->attr_rel) OR ($this->attr_rel === TRUE && empty($value))) + { + return ''; + } + elseif ( ! is_bool($this->attr_rel)) + { + $value = $this->attr_rel; + } + + return ' rel="'.$value.'"'; + } + } /* End of file Pagination.php */ diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php index 1f6aeeb6b..c96daaf15 100644 --- a/system/libraries/Upload.php +++ b/system/libraries/Upload.php @@ -347,11 +347,12 @@ class CI_Upload { * Returns an associative array containing all of the information * related to the upload, allowing the developer easy access in one array. * - * @return array + * @param string + * @return mixed */ - public function data() + public function data($index = NULL) { - return array( + $data = array( 'file_name' => $this->file_name, 'file_type' => $this->file_type, 'file_path' => $this->upload_path, @@ -367,6 +368,13 @@ class CI_Upload { 'image_type' => $this->image_type, 'image_size_str' => $this->image_size_str, ); + + if ( ! empty($index)) + { + return isset($data[$index]) ? $data[$index] : NULL; + } + + return $data; } // -------------------------------------------------------------------- |