summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--application/config/autoload.php10
-rw-r--r--application/config/config.php13
-rw-r--r--application/config/database.php12
-rw-r--r--application/config/mimes.php2
-rw-r--r--application/views/errors/cli/error_exception.php28
-rw-r--r--application/views/errors/cli/error_php.php30
-rw-r--r--system/core/Common.php16
-rw-r--r--system/core/Loader.php40
-rw-r--r--system/core/Output.php35
-rw-r--r--system/core/Router.php45
-rw-r--r--system/core/Security.php2
-rw-r--r--system/core/URI.php4
-rw-r--r--system/database/DB_forge.php4
-rw-r--r--system/database/DB_query_builder.php30
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php49
-rw-r--r--system/database/drivers/oci8/oci8_driver.php43
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php31
-rw-r--r--system/helpers/download_helper.php21
-rw-r--r--system/helpers/file_helper.php2
-rw-r--r--system/helpers/form_helper.php45
-rw-r--r--system/helpers/path_helper.php2
-rw-r--r--system/helpers/text_helper.php2
-rw-r--r--system/helpers/url_helper.php4
-rw-r--r--system/libraries/Encrypt.php2
-rw-r--r--system/libraries/Ftp.php2
-rw-r--r--system/libraries/Javascript/Jquery.php2
-rw-r--r--system/libraries/Pagination.php5
-rw-r--r--system/libraries/Session/Session.php2
-rw-r--r--system/libraries/Unit_test.php54
-rw-r--r--system/libraries/Upload.php28
-rw-r--r--tests/README.md2
-rw-r--r--tests/codeigniter/core/Loader_test.php4
-rw-r--r--user_guide_src/source/_themes/sphinx_rtd_theme/static/css/citheme.css7
-rw-r--r--user_guide_src/source/_themes/sphinx_rtd_theme/theme.conf2
-rw-r--r--user_guide_src/source/changelog.rst48
-rw-r--r--user_guide_src/source/database/configuration.rst20
-rw-r--r--user_guide_src/source/database/forge.rst2
-rw-r--r--user_guide_src/source/database/query_builder.rst44
-rw-r--r--user_guide_src/source/database/results.rst133
-rw-r--r--user_guide_src/source/database/utilities.rst4
-rw-r--r--user_guide_src/source/general/environments.rst2
-rw-r--r--user_guide_src/source/helpers/form_helper.rst40
-rw-r--r--user_guide_src/source/helpers/text_helper.rst6
-rw-r--r--user_guide_src/source/installation/downloads.rst5
-rw-r--r--user_guide_src/source/installation/upgrade_220.rst2
-rw-r--r--user_guide_src/source/installation/upgrade_222.rst14
-rw-r--r--user_guide_src/source/installation/upgrade_223.rst14
-rw-r--r--user_guide_src/source/installation/upgrade_301.rst19
-rw-r--r--user_guide_src/source/installation/upgrading.rst7
-rw-r--r--user_guide_src/source/libraries/form_validation.rst8
-rw-r--r--user_guide_src/source/libraries/output.rst4
51 files changed, 657 insertions, 295 deletions
diff --git a/application/config/autoload.php b/application/config/autoload.php
index 3f0bd24f2..4bc6bf0ad 100644
--- a/application/config/autoload.php
+++ b/application/config/autoload.php
@@ -45,8 +45,9 @@ $autoload['packages'] = array();
| -------------------------------------------------------------------
| Auto-load Libraries
| -------------------------------------------------------------------
-| These are the classes located in the system/libraries folder
-| or in your application/libraries folder.
+| These are the classes located in system/libraries/ or your
+| application/libraries/ directory, with the addition of the
+| 'database' library, which is somewhat of a special case.
|
| Prototype:
|
@@ -63,8 +64,9 @@ $autoload['libraries'] = array();
| -------------------------------------------------------------------
| Auto-load Drivers
| -------------------------------------------------------------------
-| These classes are located in the system/libraries folder or in your
-| application/libraries folder within their own subdirectory. They
+| These classes are located in system/libraries/ or in your
+| application/libraries/ directory, but are also placed inside their
+| own subdirectory and they extend the CI_Driver_Library class. They
| offer multiple interchangeable driver options.
|
| Prototype:
diff --git a/application/config/config.php b/application/config/config.php
index 86ca312b7..a4d883fab 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -284,8 +284,15 @@ $config['cache_path'] = '';
| Cache Include Query String
|--------------------------------------------------------------------------
|
-| Set this to TRUE if you want to use different cache files depending on the
-| URL query string. Please be aware this might result in numerous cache files.
+| Whether to take the URL query string into consideration when generating
+| output cache files. Valid options are:
+|
+| FALSE = Disabled
+| TRUE = Enabled, take all query parameters into account.
+| Please be aware that this may result in numerous cache
+| files generated for the same page over and over again.
+| array('q') = Enabled, but only take into account the specified list
+| of query parameters.
|
*/
$config['cache_query_string'] = FALSE;
@@ -473,6 +480,8 @@ $config['time_reference'] = 'local';
| can rewrite the tags on-the-fly, enabling you to utilize that syntax
| in your view files. Options are TRUE or FALSE (boolean)
|
+| Note: You need to have eval() enabled for this to work.
+|
*/
$config['rewrite_short_tags'] = FALSE;
diff --git a/application/config/database.php b/application/config/database.php
index 84aab9169..bf9857fff 100644
--- a/application/config/database.php
+++ b/application/config/database.php
@@ -40,9 +40,21 @@ defined('BASEPATH') OR exit('No direct script access allowed');
| Sites using Latin-1 or UTF-8 database character set and collation are unaffected.
| ['swap_pre'] A default table prefix that should be swapped with the dbprefix
| ['encrypt'] Whether or not to use an encrypted connection.
+|
+| 'mysql' (deprecated), 'sqlsrv' and 'pdo/sqlsrv' drivers accept TRUE/FALSE
+| 'mysqli' and 'pdo/mysql' drivers accept an array with the following options:
+|
+| 'ssl_key' - Path to the private key file
+| 'ssl_cert' - Path to the public key certificate file
+| 'ssl_ca' - Path to the certificate authority file
+| 'ssl_capath' - Path to a directory containing trusted CA certificats in PEM format
+| 'ssl_cipher' - List of *allowed* ciphers to be used for the encryption, separated by colons (':')
+| 'ssl_verify' - TRUE/FALSE; Whether verify the server certificate or not ('mysqli' only)
+|
| ['compress'] Whether or not to use client compression (MySQL only)
| ['stricton'] TRUE/FALSE - forces 'Strict Mode' connections
| - good for ensuring strict SQL while developing
+| ['ssl_options'] Used to set various SSL options that can be used when making SSL connections.
| ['failover'] array - A array with 0 or more data for connections if the main should fail.
| ['save_queries'] TRUE/FALSE - Whether to "save" all executed queries.
| NOTE: Disabling this will also effectively disable both
diff --git a/application/config/mimes.php b/application/config/mimes.php
index d0e1516ff..1f591ba6b 100644
--- a/application/config/mimes.php
+++ b/application/config/mimes.php
@@ -154,5 +154,5 @@ return array(
'vcf' => 'text/x-vcard',
'srt' => array('text/srt', 'text/plain'),
'vtt' => array('text/vtt', 'text/plain'),
- 'ico' => 'image/x-icon'
+ 'ico' => array('image/x-icon', 'image/x-ico', 'image/vnd.microsoft.icon')
);
diff --git a/application/views/errors/cli/error_exception.php b/application/views/errors/cli/error_exception.php
index 75d7f0fad..efa6a66d1 100644
--- a/application/views/errors/cli/error_exception.php
+++ b/application/views/errors/cli/error_exception.php
@@ -1,25 +1,21 @@
-<?php
-defined('BASEPATH') OR exit('No direct script access allowed');
-?>
+<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?>
An uncaught Exception was encountered
-Type: <?php echo get_class($exception); ?>
-Message: <?php echo $message; ?>
-Filename: <?php echo $exception->getFile(); ?>
+Type: <?php echo get_class($exception), "\n"; ?>
+Message: <?php echo $message, "\n"; ?>
+Filename: <?php echo $exception->getFile(), "\n"; ?>
Line Number: <?php echo $exception->getLine(); ?>
<?php if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?>
Backtrace:
- <?php foreach ($exception->getTrace() as $error): ?>
- <?php if (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?>
+<?php foreach ($exception->getTrace() as $error): ?>
+<?php if (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?>
+ File: <?php echo $error['file'], "\n"; ?>
+ Line: <?php echo $error['line'], "\n"; ?>
+ Function: <?php echo $error['function'], "\n\n"; ?>
+<?php endif ?>
+<?php endforeach ?>
- File: <?php echo $error['file']; ?>
- Line: <?php echo $error['line']; ?>
- Function: <?php echo $error['function']; ?>
-
- <?php endif ?>
-
- <?php endforeach ?>
-<?php endif ?> \ No newline at end of file
+<?php endif ?>
diff --git a/application/views/errors/cli/error_php.php b/application/views/errors/cli/error_php.php
index fec91e54f..8a24b6491 100644
--- a/application/views/errors/cli/error_php.php
+++ b/application/views/errors/cli/error_php.php
@@ -1,25 +1,21 @@
-<?php
-defined('BASEPATH') OR exit('No direct script access allowed');
-?>
+<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?>
A PHP Error was encountered
-Severity: <?php echo $severity;?>
-Message: <?php echo $message;?>
-Filename: <?php echo $filepath;?>
-Line Number: <?php echo $line;?>
+Severity: <?php echo $severity, "\n"; ?>
+Message: <?php echo $message, "\n"; ?>
+Filename: <?php echo $filepath, "\n"; ?>
+Line Number: <?php echo $line; ?>
<?php if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?>
Backtrace:
- <?php foreach (debug_backtrace() as $error): ?>
- <?php if (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?>
+<?php foreach (debug_backtrace() as $error): ?>
+<?php if (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?>
+ File: <?php echo $error['file'], "\n"; ?>
+ Line: <?php echo $error['line'], "\n"; ?>
+ Function: <?php echo $error['function'], "\n\n"; ?>
+<?php endif ?>
+<?php endforeach ?>
- File: <?php echo $error['file'];?>
- Line: <?php echo $error['line'];?>
- Function: <?php echo $error['function'];?>
-
- <?php endif ?>
-
- <?php endforeach ?>
-<?php endif ?> \ No newline at end of file
+<?php endif ?>
diff --git a/system/core/Common.php b/system/core/Common.php
index b850fd39a..ce324a1cc 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -833,19 +833,9 @@ if ( ! function_exists('function_usable'))
{
if ( ! isset($_suhosin_func_blacklist))
{
- if (extension_loaded('suhosin'))
- {
- $_suhosin_func_blacklist = explode(',', trim(ini_get('suhosin.executor.func.blacklist')));
-
- if ( ! in_array('eval', $_suhosin_func_blacklist, TRUE) && ini_get('suhosin.executor.disable_eval'))
- {
- $_suhosin_func_blacklist[] = 'eval';
- }
- }
- else
- {
- $_suhosin_func_blacklist = array();
- }
+ $_suhosin_func_blacklist = extension_loaded('suhosin')
+ ? explode(',', trim(ini_get('suhosin.executor.func.blacklist')))
+ : array();
}
return ! in_array($function_name, $_suhosin_func_blacklist, TRUE);
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 9205ad1b6..1f48c0782 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -272,7 +272,7 @@ class CI_Loader {
$CI =& get_instance();
if (isset($CI->$name))
{
- show_error('The model name you are loading is the name of a resource that is already being used: '.$name);
+ throw new RuntimeException('The model name you are loading is the name of a resource that is already being used: '.$name);
}
if ($db_conn !== FALSE && ! class_exists('CI_DB', FALSE))
@@ -291,23 +291,37 @@ class CI_Loader {
}
$model = ucfirst(strtolower($model));
-
- foreach ($this->_ci_model_paths as $mod_path)
+ if ( ! class_exists($model))
{
- if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))
+ foreach ($this->_ci_model_paths as $mod_path)
{
- continue;
- }
+ if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))
+ {
+ continue;
+ }
- require_once($mod_path.'models/'.$path.$model.'.php');
+ require_once($mod_path.'models/'.$path.$model.'.php');
+ if ( ! class_exists($model, FALSE))
+ {
+ throw new RuntimeException($mod_path."models/".$path.$model.".php exists, but doesn't declare class ".$model);
+ }
- $this->_ci_models[] = $name;
- $CI->$name = new $model();
- return $this;
+ break;
+ }
+
+ if ( ! class_exists($model, FALSE))
+ {
+ throw new RuntimeException('Unable to locate the model you have specified: '.$model);
+ }
+ }
+ elseif ( ! is_subclass_of($model, 'CI_Model'))
+ {
+ throw new RuntimeException("Class ".$model." already exists and doesn't extend CI_Model");
}
- // couldn't find the model
- show_error('Unable to locate the model you have specified: '.$model);
+ $this->_ci_models[] = $name;
+ $CI->$name = new $model();
+ return $this;
}
// --------------------------------------------------------------------
@@ -905,7 +919,7 @@ class CI_Loader {
// If the PHP installation does not support short tags we'll
// do a little string replacement, changing the short tags
// to standard PHP echo statements.
- if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE && function_usable('eval'))
+ if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE)
{
echo eval('?>'.preg_replace('/;*\s*\?>/', '; ?>', str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
}
diff --git a/system/core/Output.php b/system/core/Output.php
index e7d559a1d..76c1329d2 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -556,9 +556,16 @@ class CI_Output {
.$CI->config->item('index_page')
.$CI->uri->uri_string();
- if ($CI->config->item('cache_query_string') && ! empty($_SERVER['QUERY_STRING']))
+ if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
{
- $uri .= '?'.$_SERVER['QUERY_STRING'];
+ if (is_array($cache_query_string))
+ {
+ $uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
+ }
+ else
+ {
+ $uri .= '?'.$_SERVER['QUERY_STRING'];
+ }
}
$cache_path .= md5($uri);
@@ -646,9 +653,16 @@ class CI_Output {
// Build the file path. The file name is an MD5 hash of the full URI
$uri = $CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;
- if ($CFG->item('cache_query_string') && ! empty($_SERVER['QUERY_STRING']))
+ if (($cache_query_string = $CFG->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
{
- $uri .= '?'.$_SERVER['QUERY_STRING'];
+ if (is_array($cache_query_string))
+ {
+ $uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
+ }
+ else
+ {
+ $uri .= '?'.$_SERVER['QUERY_STRING'];
+ }
}
$filepath = $cache_path.md5($uri);
@@ -729,13 +743,20 @@ class CI_Output {
{
$uri = $CI->uri->uri_string();
- if ($CI->config->item('cache_query_string') && ! empty($_SERVER['QUERY_STRING']))
+ if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
{
- $uri .= '?'.$_SERVER['QUERY_STRING'];
+ if (is_array($cache_query_string))
+ {
+ $uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
+ }
+ else
+ {
+ $uri .= '?'.$_SERVER['QUERY_STRING'];
+ }
}
}
- $cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').$uri);
+ $cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').ltrim($uri, '/'));
if ( ! @unlink($cache_path))
{
diff --git a/system/core/Router.php b/system/core/Router.php
index 051000533..ab5246a1f 100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -83,7 +83,7 @@ class CI_Router {
*
* @var string
*/
- public $directory = '';
+ public $directory;
/**
* Default controller (and method if specific)
@@ -126,25 +126,16 @@ class CI_Router {
$this->uri =& load_class('URI', 'core');
$this->enable_query_strings = ( ! is_cli() && $this->config->item('enable_query_strings') === TRUE);
+
+ // If a directory override is configured, it has to be set before any dynamic routing logic
+ is_array($routing) && isset($routing['directory']) && $this->set_directory($routing['directory']);
$this->_set_routing();
// Set any routing overrides that may exist in the main index file
if (is_array($routing))
{
- if (isset($routing['directory']))
- {
- $this->set_directory($routing['directory']);
- }
-
- if ( ! empty($routing['controller']))
- {
- $this->set_class($routing['controller']);
- }
-
- if ( ! empty($routing['function']))
- {
- $this->set_method($routing['function']);
- }
+ empty($routing['controller']) OR $this->set_class($routing['controller']);
+ empty($routing['function']) OR $this->set_method($routing['function']);
}
log_message('info', 'Router Class Initialized');
@@ -167,12 +158,17 @@ class CI_Router {
// If this feature is enabled, we will gather the directory/class/method a little differently
if ($this->enable_query_strings)
{
- $_d = $this->config->item('directory_trigger');
- $_d = isset($_GET[$_d]) ? trim($_GET[$_d], " \t\n\r\0\x0B/") : '';
- if ($_d !== '')
+ // If the directory is set at this time, it means an override exists, so skip the checks
+ if ( ! isset($this->directory))
{
- $this->uri->filter_uri($_d);
- $this->set_directory($_d);
+ $_d = $this->config->item('directory_trigger');
+ $_d = isset($_GET[$_d]) ? trim($_GET[$_d], " \t\n\r\0\x0B/") : '';
+
+ if ($_d !== '')
+ {
+ $this->uri->filter_uri($_d);
+ $this->set_directory($_d);
+ }
}
$_c = trim($this->config->item('controller_trigger'));
@@ -333,6 +329,8 @@ class CI_Router {
protected function _validate_request($segments)
{
$c = count($segments);
+ $directory_override = isset($this->directory);
+
// Loop through our segments and return as soon as a controller
// is found or when such a directory doesn't exist
while ($c-- > 0)
@@ -340,7 +338,10 @@ class CI_Router {
$test = $this->directory
.ucfirst($this->translate_uri_dashes === TRUE ? str_replace('-', '_', $segments[0]) : $segments[0]);
- if ( ! file_exists(APPPATH.'controllers/'.$test.'.php') && is_dir(APPPATH.'controllers/'.$this->directory.$segments[0]))
+ if ( ! file_exists(APPPATH.'controllers/'.$test.'.php')
+ && $directory_override === FALSE
+ && is_dir(APPPATH.'controllers/'.$this->directory.$segments[0])
+ )
{
$this->set_directory(array_shift($segments), TRUE);
continue;
@@ -493,7 +494,7 @@ class CI_Router {
* Set directory name
*
* @param string $dir Directory name
- * @param bool $appent Whether we're appending rather than setting the full value
+ * @param bool $append Whether we're appending rather than setting the full value
* @return void
*/
public function set_directory($dir, $append = FALSE)
diff --git a/system/core/Security.php b/system/core/Security.php
index 9cef42439..7c5199255 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -275,7 +275,7 @@ class CI_Security {
$secure_cookie,
config_item('cookie_httponly')
);
- log_message('info', 'CRSF cookie sent');
+ log_message('info', 'CSRF cookie sent');
return $this;
}
diff --git a/system/core/URI.php b/system/core/URI.php
index 2211e3665..5b658f679 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -201,7 +201,9 @@ class CI_URI {
return '';
}
- $uri = parse_url($_SERVER['REQUEST_URI']);
+ // parse_url() returns false if no host is present, but the path or query string
+ // contains a colon followed by a number
+ $uri = parse_url('http://dummy'.$_SERVER['REQUEST_URI']);
$query = isset($uri['query']) ? $uri['query'] : '';
$uri = isset($uri['path']) ? $uri['path'] : '';
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index d99fd0024..dde285598 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -143,7 +143,7 @@ abstract class CI_DB_forge {
protected $_unsigned = TRUE;
/**
- * NULL value representatin in CREATE/ALTER TABLE statements
+ * NULL value representation in CREATE/ALTER TABLE statements
*
* @var string
*/
@@ -239,7 +239,7 @@ abstract class CI_DB_forge {
*/
public function add_key($key, $primary = FALSE)
{
- if ($primary === TRUE && is_array($key))
+ if (is_array($key))
{
foreach ($key as $one)
{
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index a8b5b3579..293419e23 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -794,10 +794,17 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$not = ($not) ? ' NOT' : '';
- $where_in = array();
- foreach ($values as $value)
+ if ($escape === TRUE)
{
- $where_in[] = $this->escape($value);
+ $where_in = array();
+ foreach ($values as $value)
+ {
+ $where_in[] = $this->escape($value);
+ }
+ }
+ else
+ {
+ $where_in = array_values($values);
}
$prefix = (count($this->qb_where) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type);
@@ -926,7 +933,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
? $this->_group_get_type('') : $this->_group_get_type($type);
- $v = $this->escape_like_str($v);
+ if ($escape === TRUE)
+ {
+ $v = $this->escape_like_str($v);
+ }
if ($side === 'none')
{
@@ -946,7 +956,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
}
// some platforms require an escape sequence definition for LIKE wildcards
- if ($this->_like_escape_str !== '')
+ if ($escape === TRUE && $this->_like_escape_str !== '')
{
$like_statement .= sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
@@ -1294,7 +1304,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* Compiles a SELECT query string and returns the sql.
*
* @param string the table name to select from (optional)
- * @param bool TRUE: resets QB values; FALSE: leave QB vaules alone
+ * @param bool TRUE: resets QB values; FALSE: leave QB values alone
* @return string
*/
public function get_compiled_select($table = '', $reset = TRUE)
@@ -1736,7 +1746,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
return FALSE;
}
- $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set);
+ $sql = $this->_update($this->qb_from[0], $this->qb_set);
if ($reset === TRUE)
{
@@ -1784,7 +1794,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$this->limit($limit);
}
- $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set);
+ $sql = $this->_update($this->qb_from[0], $this->qb_set);
$this->_reset_write();
return $this->query($sql);
}
@@ -1801,7 +1811,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param string the table to update data on
* @return bool
*/
- protected function _validate_update($table = '')
+ protected function _validate_update($table)
{
if (count($this->qb_set) === 0)
{
@@ -1810,7 +1820,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
if ($table !== '')
{
- $this->qb_from[0] = $table;
+ $this->qb_from = array($this->protect_identifiers($table, TRUE, NULL, FALSE));
}
elseif ( ! isset($this->qb_from[0]))
{
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index e953db052..dd3cc77c6 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -102,7 +102,6 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* @param bool $persistent
* @return object
- * @todo SSL support
*/
public function db_connect($persistent = FALSE)
{
@@ -132,8 +131,52 @@ class CI_DB_mysqli_driver extends CI_DB {
$mysqli->options(MYSQLI_INIT_COMMAND, 'SET SESSION sql_mode="STRICT_ALL_TABLES"');
}
- return $mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, $socket, $client_flags)
- ? $mysqli : FALSE;
+ if (is_array($this->encrypt))
+ {
+ $ssl = array();
+ empty($this->encrypt['ssl_key']) OR $ssl['key'] = $this->encrypt['ssl_key'];
+ empty($this->encrypt['ssl_cert']) OR $ssl['cert'] = $this->encrypt['ssl_cert'];
+ empty($this->encrypt['ssl_ca']) OR $ssl['ca'] = $this->encrypt['ssl_ca'];
+ empty($this->encrypt['ssl_capath']) OR $ssl['capath'] = $this->encrypt['ssl_capath'];
+ empty($this->encrypt['ssl_cipher']) OR $ssl['cipher'] = $this->encrypt['ssl_cipher'];
+
+ if ( ! empty($ssl))
+ {
+ if ( ! empty($this->encrypt['ssl_verify']) && defined('MYSQLI_OPT_SSL_VERIFY_SERVER_CERT'))
+ {
+ $mysqli->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, TRUE);
+ }
+
+ $client_flags |= MYSQLI_CLIENT_SSL;
+ $mysqli->ssl_set(
+ isset($ssl['key']) ? $ssl['key'] : NULL,
+ isset($ssl['cert']) ? $ssl['cert'] : NULL,
+ isset($ssl['ca']) ? $ssl['ca'] : NULL,
+ isset($ssl['capath']) ? $ssl['capath'] : NULL,
+ isset($ssl['cipher']) ? $ssl['cipher'] : NULL
+ );
+ }
+ }
+
+ if ($mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, $socket, $client_flags))
+ {
+ // Prior to version 5.7.3, MySQL silently downgrades to an unencrypted connection if SSL setup fails
+ if (
+ ($client_flags & MYSQLI_CLIENT_SSL)
+ && version_compare($mysqli->client_info, '5.7.3', '<=')
+ && empty($mysqli->query("SHOW STATUS LIKE 'ssl_cipher'")->fetch_object()->Value)
+ )
+ {
+ $mysqli->close();
+ $message = 'MySQLi was configured for an SSL connection, but got an unencrypted connection instead!';
+ log_message('error', $message);
+ return ($this->db->db_debug) ? $this->db->display_error($message, '', TRUE) : FALSE;
+ }
+
+ return $mysqli;
+ }
+
+ return FALSE;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index b5cf26536..3c5777751 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -102,6 +102,14 @@ class CI_DB_oci8_driver extends CI_DB {
// --------------------------------------------------------------------
/**
+ * Reset $stmt_id flag
+ *
+ * Used by stored_procedure() to prevent _execute() from
+ * re-setting the statement ID.
+ */
+ protected $_reset_stmt_id = TRUE;
+
+ /**
* List of reserved identifiers
*
* Identifiers that must NOT be escaped.
@@ -265,26 +273,13 @@ class CI_DB_oci8_driver extends CI_DB {
/* Oracle must parse the query before it is run. All of the actions with
* the query are based on the statement id returned by oci_parse().
*/
- $this->stmt_id = FALSE;
- $this->_set_stmt_id($sql);
- oci_set_prefetch($this->stmt_id, 1000);
- return oci_execute($this->stmt_id, $this->commit_mode);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Generate a statement ID
- *
- * @param string $sql an SQL query
- * @return void
- */
- protected function _set_stmt_id($sql)
- {
- if ( ! is_resource($this->stmt_id))
+ if ($this->_reset_stmt_id === TRUE)
{
$this->stmt_id = oci_parse($this->conn_id, $sql);
}
+
+ oci_set_prefetch($this->stmt_id, 1000);
+ return oci_execute($this->stmt_id, $this->commit_mode);
}
// --------------------------------------------------------------------
@@ -318,15 +313,15 @@ class CI_DB_oci8_driver extends CI_DB {
* type yes the type of the parameter
* length yes the max size of the parameter
*/
- public function stored_procedure($package, $procedure, $params)
+ public function stored_procedure($package, $procedure, array $params)
{
- if ($package === '' OR $procedure === '' OR ! is_array($params))
+ if ($package === '' OR $procedure === '')
{
log_message('error', 'Invalid query: '.$package.'.'.$procedure);
return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE;
}
- // build the query string
+ // Build the query string
$sql = 'BEGIN '.$package.'.'.$procedure.'(';
$have_cursor = FALSE;
@@ -341,10 +336,12 @@ class CI_DB_oci8_driver extends CI_DB {
}
$sql = trim($sql, ',').'); END;';
- $this->stmt_id = FALSE;
- $this->_set_stmt_id($sql);
+ $this->_reset_stmt_id = FALSE;
+ $this->stmt_id = oci_parse($this->conn_id, $sql);
$this->_bind_params($params);
- return $this->query($sql, FALSE, $have_cursor);
+ $result = $this->query($sql, FALSE, $have_cursor);
+ $this->_reset_stmt_id = TRUE;
+ return $result;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
index 206d83595..e9d25cebc 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
@@ -119,7 +119,6 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {
*
* @param bool $persistent
* @return object
- * @todo SSL support
*/
public function db_connect($persistent = FALSE)
{
@@ -151,7 +150,35 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {
$this->options[PDO::MYSQL_ATTR_COMPRESS] = TRUE;
}
- return parent::db_connect($persistent);
+ // SSL support was added to PDO_MYSQL in PHP 5.3.7
+ if (is_array($this->encrypt) && is_php('5.3.7'))
+ {
+ $ssl = array();
+ empty($this->encrypt['ssl_key']) OR $ssl[PDO::MYSQL_ATTR_SSL_KEY] = $this->encrypt['ssl_key'];
+ empty($this->encrypt['ssl_cert']) OR $ssl[PDO::MYSQL_ATTR_SSL_CERT] = $this->encrypt['ssl_cert'];
+ empty($this->encrypt['ssl_ca']) OR $ssl[PDO::MYSQL_ATTR_SSL_CA] = $this->encrypt['ssl_ca'];
+ empty($this->encrypt['ssl_capath']) OR $ssl[PDO::MYSQL_ATTR_SSL_CAPATH] = $this->encrypt['ssl_capath'];
+ empty($this->encrypt['ssl_cipher']) OR $ssl[PDO::MYSQL_ATTR_SSL_CIPHER] = $this->encrypt['ssl_cipher'];
+
+ // DO NOT use array_merge() here!
+ // It re-indexes numeric keys and the PDO_MYSQL_ATTR_SSL_* constants are integers.
+ empty($ssl) OR $this->options += $ssl;
+ }
+
+ // Prior to version 5.7.3, MySQL silently downgrades to an unencrypted connection if SSL setup fails
+ if (
+ ($pdo = parent::db_connect($persistent)) !== FALSE
+ && ! empty($ssl)
+ && version_compare($pdo->getAttribute(PDO::ATTR_CLIENT_VERSION), '5.7.3', '<=')
+ && empty($pdo->query("SHOW STATUS LIKE 'ssl_cipher'")->fetchObject()->Value)
+ )
+ {
+ $message = 'PDO_MYSQL was configured for an SSL connection, but got an unencrypted connection instead!';
+ log_message('error', $message);
+ return ($this->db->db_debug) ? $this->db->display_error($message, '', TRUE) : FALSE;
+ }
+
+ return $pdo;
}
// --------------------------------------------------------------------
diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php
index 95c94a1b8..73f6456c4 100644
--- a/system/helpers/download_helper.php
+++ b/system/helpers/download_helper.php
@@ -69,16 +69,14 @@ if ( ! function_exists('force_download'))
}
elseif ($data === NULL)
{
- if (@is_file($filename) && ($filesize = @filesize($filename)) !== FALSE)
- {
- $filepath = $filename;
- $filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename));
- $filename = end($filename);
- }
- else
+ if ( ! @is_file($filename) OR ($filesize = @filesize($filename)) === FALSE)
{
return;
}
+
+ $filepath = $filename;
+ $filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename));
+ $filename = end($filename);
}
else
{
@@ -140,14 +138,7 @@ if ( ! function_exists('force_download'))
header('Expires: 0');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.$filesize);
-
- // Internet Explorer-specific headers
- if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE)
- {
- header('Cache-Control: no-cache, no-store, must-revalidate');
- }
-
- header('Pragma: no-cache');
+ header('Cache-Control: private, no-transform, no-store, must-revalidate');
// If we have raw data - just dump it
if ($data !== NULL)
diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php
index 8b15e60a5..cd1c641ec 100644
--- a/system/helpers/file_helper.php
+++ b/system/helpers/file_helper.php
@@ -54,7 +54,7 @@ if ( ! function_exists('read_file'))
/**
* Read File
*
- * Opens the file specfied in the path and returns it as a string.
+ * Opens the file specified in the path and returns it as a string.
*
* @todo Remove in version 3.1+.
* @deprecated 3.0.0 It is now just an alias for PHP's native file_get_contents().
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
index 53ee8eb11..fd807769a 100644
--- a/system/helpers/form_helper.php
+++ b/system/helpers/form_helper.php
@@ -197,7 +197,7 @@ if ( ! function_exists('form_input'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_input($data = '', $value = '', $extra = '')
@@ -208,7 +208,7 @@ if ( ! function_exists('form_input'))
'value' => $value
);
- return '<input '._parse_form_attributes($data, $defaults).$extra." />\n";
+ return '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra)." />\n";
}
}
@@ -223,7 +223,7 @@ if ( ! function_exists('form_password'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_password($data = '', $value = '', $extra = '')
@@ -245,7 +245,7 @@ if ( ! function_exists('form_upload'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_upload($data = '', $value = '', $extra = '')
@@ -253,7 +253,8 @@ if ( ! function_exists('form_upload'))
$defaults = array('type' => 'file', 'name' => '');
is_array($data) OR $data = array('name' => $data);
$data['type'] = 'file';
- return '<input '._parse_form_attributes($data, $defaults).$extra." />\n";
+
+ return '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra)." />\n";
}
}
@@ -266,7 +267,7 @@ if ( ! function_exists('form_textarea'))
*
* @param mixed $data
* @param string $value
- * @param string $extra
+ * @param mixed $extra
* @return string
*/
function form_textarea($data = '', $value = '', $extra = '')
@@ -287,7 +288,9 @@ if ( ! function_exists('form_textarea'))
unset($data['value']); // textareas don't use the value attribute
}
- return '<textarea '._parse_form_attributes($data, $defaults).$extra.'>'.html_escape($val)."</textarea>\n";
+ return '<textarea '._parse_form_attributes($data, $defaults)._attributes_to_string($extra).'>'
+ .html_escape($val)
+ ."</textarea>\n";
}
}
@@ -301,12 +304,13 @@ if ( ! function_exists('form_multiselect'))
* @param string
* @param array
* @param mixed
- * @param string
+ * @param mixed
* @return string
*/
function form_multiselect($name = '', $options = array(), $selected = array(), $extra = '')
{
- if ( ! strpos($extra, 'multiple'))
+ $extra = _attributes_to_string($extra);
+ if (stripos($extra, 'multiple') === FALSE)
{
$extra .= ' multiple="multiple"';
}
@@ -372,7 +376,7 @@ if ( ! function_exists('form_dropdown'))
$extra = _attributes_to_string($extra);
- $multiple = (count($selected) > 1 && strpos($extra, 'multiple') === FALSE) ? ' multiple="multiple"' : '';
+ $multiple = (count($selected) > 1 && stripos($extra, 'multiple') === FALSE) ? ' multiple="multiple"' : '';
$form = '<select '.rtrim(_parse_form_attributes($data, $defaults)).$extra.$multiple.">\n";
@@ -420,7 +424,7 @@ if ( ! function_exists('form_checkbox'))
* @param mixed
* @param string
* @param bool
- * @param string
+ * @param mixed
* @return string
*/
function form_checkbox($data = '', $value = '', $checked = FALSE, $extra = '')
@@ -450,7 +454,7 @@ if ( ! function_exists('form_checkbox'))
unset($defaults['checked']);
}
- return '<input '._parse_form_attributes($data, $defaults).$extra." />\n";
+ return '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra)." />\n";
}
}
@@ -464,13 +468,14 @@ if ( ! function_exists('form_radio'))
* @param mixed
* @param string
* @param bool
- * @param string
+ * @param mixed
* @return string
*/
function form_radio($data = '', $value = '', $checked = FALSE, $extra = '')
{
is_array($data) OR $data = array('name' => $data);
$data['type'] = 'radio';
+
return form_checkbox($data, $value, $checked, $extra);
}
}
@@ -484,7 +489,7 @@ if ( ! function_exists('form_submit'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_submit($data = '', $value = '', $extra = '')
@@ -495,7 +500,7 @@ if ( ! function_exists('form_submit'))
'value' => $value
);
- return '<input '._parse_form_attributes($data, $defaults).$extra." />\n";
+ return '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra)." />\n";
}
}
@@ -508,7 +513,7 @@ if ( ! function_exists('form_reset'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_reset($data = '', $value = '', $extra = '')
@@ -519,7 +524,7 @@ if ( ! function_exists('form_reset'))
'value' => $value
);
- return '<input '._parse_form_attributes($data, $defaults).$extra." />\n";
+ return '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra)." />\n";
}
}
@@ -532,7 +537,7 @@ if ( ! function_exists('form_button'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_button($data = '', $content = '', $extra = '')
@@ -548,7 +553,9 @@ if ( ! function_exists('form_button'))
unset($data['content']); // content is not an attribute
}
- return '<button '._parse_form_attributes($data, $defaults).$extra.'>'.$content."</button>\n";
+ return '<button '._parse_form_attributes($data, $defaults)._attributes_to_string($extra).'>'
+ .$content
+ ."</button>\n";
}
}
diff --git a/system/helpers/path_helper.php b/system/helpers/path_helper.php
index c23ec6435..c96d0b8b3 100644
--- a/system/helpers/path_helper.php
+++ b/system/helpers/path_helper.php
@@ -61,7 +61,7 @@ if ( ! function_exists('set_realpath'))
function set_realpath($path, $check_existance = FALSE)
{
// Security check to make sure the path is NOT a URL. No remote file inclusion!
- if (preg_match('#^(http:\/\/|https:\/\/|www\.|ftp|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})#i', $path))
+ if (preg_match('#^(http:\/\/|https:\/\/|www\.|ftp)#i', $path) OR filter_var($path, FILTER_VALIDATE_IP) === $path )
{
show_error('The path you submitted must be a local server path, not a URL');
}
diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php
index f2290c895..fb47036f2 100644
--- a/system/helpers/text_helper.php
+++ b/system/helpers/text_helper.php
@@ -254,7 +254,7 @@ if ( ! function_exists('word_censor'))
* word you've submitted.
*
* @param string the text string
- * @param string the array of censoered words
+ * @param string the array of censored words
* @param string the optional replacement value
* @return string
*/
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
index 6a033d6ba..d65f92f1b 100644
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -492,7 +492,7 @@ if ( ! function_exists('url_title'))
$trans = array(
'&.+?;' => '',
- '[^a-z0-9 _-]' => '',
+ '[^\w\d _-]' => '',
'\s+' => $separator,
'('.$q_separator.')+' => $separator
);
@@ -500,7 +500,7 @@ if ( ! function_exists('url_title'))
$str = strip_tags($str);
foreach ($trans as $key => $val)
{
- $str = preg_replace('#'.$key.'#i', $val, $str);
+ $str = preg_replace('#'.$key.'#i'.(UTF8_ENABLED ? 'u' : ''), $val, $str);
}
if ($lowercase === TRUE)
diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php
index 5faf1f206..a46d4f462 100644
--- a/system/libraries/Encrypt.php
+++ b/system/libraries/Encrypt.php
@@ -65,7 +65,7 @@ class CI_Encrypt {
protected $_hash_type = 'sha1';
/**
- * Flag for the existance of mcrypt
+ * Flag for the existence of mcrypt
*
* @var bool
*/
diff --git a/system/libraries/Ftp.php b/system/libraries/Ftp.php
index b53207577..2d345c294 100644
--- a/system/libraries/Ftp.php
+++ b/system/libraries/Ftp.php
@@ -466,7 +466,7 @@ class CI_FTP {
/**
* Delete a folder and recursively delete everything (including sub-folders)
- * containted within it.
+ * contained within it.
*
* @param string $filepath
* @return bool
diff --git a/system/libraries/Javascript/Jquery.php b/system/libraries/Javascript/Jquery.php
index 25acceef7..11f2d2361 100644
--- a/system/libraries/Javascript/Jquery.php
+++ b/system/libraries/Javascript/Jquery.php
@@ -84,7 +84,7 @@ class CI_Jquery extends CI_Javascript {
public $jquery_table_sorter_active = FALSE;
/**
- * JQuery table sorder pager active
+ * JQuery table sorter pager active
*
* @var bool
*/
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
index d63f61df6..5b3aa01f4 100644
--- a/system/libraries/Pagination.php
+++ b/system/libraries/Pagination.php
@@ -353,7 +353,8 @@ class CI_Pagination {
*/
public function initialize(array $params = array())
{
- if (isset($params['attributes']) && is_array($params['attributes']))
+ isset($params['attributes']) OR $params['attributes'] = array();
+ if (is_array($params['attributes']))
{
$this->_parse_attributes($params['attributes']);
unset($params['attributes']);
@@ -644,7 +645,7 @@ class CI_Pagination {
// Kill double slashes. Note: Sometimes we can end up with a double slash
// in the penultimate link so we'll kill all double slashes.
- $output = preg_replace('#([^:])//+#', '\\1/', $output);
+ $output = preg_replace('#([^:"])//+#', '\\1/', $output);
// Add the wrapper HTML if exists
return $this->full_tag_open.$output.$this->full_tag_close;
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
index 0549fef66..05a470d86 100644
--- a/system/libraries/Session/Session.php
+++ b/system/libraries/Session/Session.php
@@ -795,7 +795,7 @@ class CI_Session {
/**
* Set flashdata
*
- * Legacy CI_Session compatibiliy method
+ * Legacy CI_Session compatibility method
*
* @param mixed $data Session data key or an associative array
* @param mixed $value Value to store
diff --git a/system/libraries/Unit_test.php b/system/libraries/Unit_test.php
index 60b046ba0..3f986f3e8 100644
--- a/system/libraries/Unit_test.php
+++ b/system/libraries/Unit_test.php
@@ -55,14 +55,14 @@ class CI_Unit_test {
*
* @var bool
*/
- public $active = TRUE;
+ public $active = TRUE;
/**
* Test results
*
* @var array
*/
- public $results = array();
+ public $results = array();
/**
* Strict comparison flag
@@ -71,21 +71,21 @@ class CI_Unit_test {
*
* @var bool
*/
- public $strict = FALSE;
+ public $strict = FALSE;
/**
* Template
*
* @var string
*/
- protected $_template = NULL;
+ protected $_template = NULL;
/**
* Template rows
*
* @var string
*/
- protected $_template_rows = NULL;
+ protected $_template_rows = NULL;
/**
* List of visible test items
@@ -93,13 +93,13 @@ class CI_Unit_test {
* @var array
*/
protected $_test_items_visible = array(
- 'test_name',
- 'test_datatype',
- 'res_datatype',
- 'result',
- 'file',
- 'line',
- 'notes'
+ 'test_name',
+ 'test_datatype',
+ 'res_datatype',
+ 'result',
+ 'file',
+ 'line',
+ 'notes'
);
// --------------------------------------------------------------------
@@ -167,14 +167,14 @@ class CI_Unit_test {
$back = $this->_backtrace();
$report = array (
- 'test_name' => $test_name,
- 'test_datatype' => gettype($test),
- 'res_datatype' => $extype,
- 'result' => ($result === TRUE) ? 'passed' : 'failed',
- 'file' => $back['file'],
- 'line' => $back['line'],
- 'notes' => $notes
- );
+ 'test_name' => $test_name,
+ 'test_datatype' => gettype($test),
+ 'res_datatype' => $extype,
+ 'result' => ($result === TRUE) ? 'passed' : 'failed',
+ 'file' => $back['file'],
+ 'line' => $back['line'],
+ 'notes' => $notes
+ );
$this->results[] = $report;
@@ -291,10 +291,12 @@ class CI_Unit_test {
{
continue;
}
-
- if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val), FALSE)))
+ elseif (in_array($key, array('test_name', 'test_datatype', 'test_res_datatype', 'result'), TRUE))
{
- $val = $line;
+ if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val), FALSE)))
+ {
+ $val = $line;
+ }
}
$temp[$CI->lang->line('ut_'.$key, FALSE)] = $val;
@@ -334,9 +336,9 @@ class CI_Unit_test {
{
$back = debug_backtrace();
return array(
- 'file' => (isset($back[1]['file']) ? $back[1]['file'] : ''),
- 'line' => (isset($back[1]['line']) ? $back[1]['line'] : '')
- );
+ 'file' => (isset($back[1]['file']) ? $back[1]['file'] : ''),
+ 'line' => (isset($back[1]['line']) ? $back[1]['line'] : '')
+ );
}
// --------------------------------------------------------------------
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
index a1bd14930..20ddfc145 100644
--- a/system/libraries/Upload.php
+++ b/system/libraries/Upload.php
@@ -533,15 +533,9 @@ class CI_Upload {
* If it returns false there was a problem.
*/
$this->orig_name = $this->file_name;
-
- if ($this->overwrite === FALSE)
+ if (FALSE === ($this->file_name = $this->set_filename($this->upload_path, $this->file_name)))
{
- $this->file_name = $this->set_filename($this->upload_path, $this->file_name);
-
- if ($this->file_name === FALSE)
- {
- return FALSE;
- }
+ return FALSE;
}
/*
@@ -656,7 +650,7 @@ class CI_Upload {
$filename = md5(uniqid(mt_rand())).$this->file_ext;
}
- if ( ! file_exists($path.$filename))
+ if ($this->overwrite === TRUE OR ! file_exists($path.$filename))
{
return $filename;
}
@@ -701,6 +695,22 @@ class CI_Upload {
// --------------------------------------------------------------------
/**
+ * Set Maximum File Size
+ *
+ * An internal alias to set_max_filesize() to help with configuration
+ * as initialize() will look for a set_<property_name>() method ...
+ *
+ * @param int $n
+ * @return CI_Upload
+ */
+ protected function set_max_size($n)
+ {
+ return $this->set_max_filesize($n);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Set Maximum File Name Length
*
* @param int $n
diff --git a/tests/README.md b/tests/README.md
index 47b5241d1..04dfbc3d8 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -6,7 +6,7 @@ Status : [![Build Status](https://secure.travis-ci.org/bcit-ci/CodeIgniter.png?b
This is the preliminary CodeIgniter testing documentation. It
will cover both internal as well as external APIs and the reasoning
-behind their implemenation, where appropriate. As with all CodeIgniter
+behind their implementation, where appropriate. As with all CodeIgniter
documentation, this file should maintain a mostly human readable
format to facilitate clean api design. [see http://arrenbrecht.ch/testing/]
diff --git a/tests/codeigniter/core/Loader_test.php b/tests/codeigniter/core/Loader_test.php
index cfaf6c74b..889ab92e4 100644
--- a/tests/codeigniter/core/Loader_test.php
+++ b/tests/codeigniter/core/Loader_test.php
@@ -229,7 +229,7 @@ class Loader_test extends CI_TestCase {
$this->ci_obj->$obj = new stdClass();
$this->setExpectedException(
'RuntimeException',
- 'CI Error: The model name you are loading is the name of a resource that is already being used: '.$obj
+ 'The model name you are loading is the name of a resource that is already being used: '.$obj
);
$this->load->model('not_real', $obj);
}
@@ -240,7 +240,7 @@ class Loader_test extends CI_TestCase {
{
$this->setExpectedException(
'RuntimeException',
- 'CI Error: Unable to locate the model you have specified: Ci_test_nonexistent_model.php'
+ 'Unable to locate the model you have specified: Ci_test_nonexistent_model.php'
);
$this->load->model('ci_test_nonexistent_model.php');
diff --git a/user_guide_src/source/_themes/sphinx_rtd_theme/static/css/citheme.css b/user_guide_src/source/_themes/sphinx_rtd_theme/static/css/citheme.css
new file mode 100644
index 000000000..10e7d04c6
--- /dev/null
+++ b/user_guide_src/source/_themes/sphinx_rtd_theme/static/css/citheme.css
@@ -0,0 +1,7 @@
+@import 'theme.css';
+
+.highlighted {
+ padding: 0px !important;
+ font-weight: inherit !important;
+ background-color: #f1d40f !important;
+} \ No newline at end of file
diff --git a/user_guide_src/source/_themes/sphinx_rtd_theme/theme.conf b/user_guide_src/source/_themes/sphinx_rtd_theme/theme.conf
index dcfbf8c22..5814ac963 100644
--- a/user_guide_src/source/_themes/sphinx_rtd_theme/theme.conf
+++ b/user_guide_src/source/_themes/sphinx_rtd_theme/theme.conf
@@ -1,6 +1,6 @@
[theme]
inherit = basic
-stylesheet = css/theme.css
+stylesheet = css/citheme.css
[options]
typekit_id = hiw1hhg
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 92d8bb164..5d1a3abba 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -14,6 +14,7 @@ Release Date: Not Released
- Database
- Added ``list_fields()`` support for SQLite ('sqlite3' and 'pdo_sqlite' drivers).
+ - Added SSL connection support for the 'mysqli' and 'pdo_mysql' drivers.
- Libraries
@@ -25,6 +26,15 @@ Release Date: Not Released
- Added 'is_resource' to the available expectations in :doc:`Unit Testing Library <libraries/unit_testing>`.
+- Helpers
+
+ - Added Unicode support to :doc:`URL Helper <helpers/url_helper>` function :php:func:`url_title()`.
+ - Added support for passing the "extra" parameter as an array to all :doc:`Form Helper <helpers/form_helper>` functions that use it.
+
+- Core
+
+ - Added support for defining a list of specific query parameters in ``$config['cache_query_string']`` for the :doc:`Output Library <libraries/output>`.
+ - Added class existence and inheritance checks to ``CI_Loader::model()`` in order to ease debugging in case of name collisions.
Bug fixes for 3.0.1
-------------------
@@ -50,6 +60,20 @@ Bug fixes for 3.0.1
- Fixed a bug in :doc:`Query Builder <database/query_builder>` where ``delete()`` didn't properly work on multiple tables with a WHERE condition previously set via ``where()``.
- Fixed a bug (#3952) - :doc:`Database <database/index>` method ``list_fields()`` didn't work with SQLite3.
- Fixed a bug (#3955) - :doc:`Cache Library <libraries/caching>` methods ``increment()`` and ``decrement()`` ignored the 'key_prefix' setting.
+- Fixed a bug (#3963) - :doc:`Unit Testing Library <libraries/unit_testing>` wrongly tried to translate filenames, line numbers and notes values in test results.
+- Fixed a bug (#3965) - :doc:`File Uploading Library <libraries/file_uploading>` ignored the "encrypt_name" setting when "overwrite" is enabled.
+- Fixed a bug (#3968) - :doc:`Database Forge <database/forge>` method ``add_key()`` didn't treat array inputs as composite keys unless it's a PRIMARY KEY.
+- Fixed a bug (#3715) - :doc:`Pagination Library <libraries/pagination>` could generate broken link when a protocol-relative base URL is used.
+- Fixed a bug (#3828) - :doc:`Output Library <libraries/output>` method ``delete_cache()`` couldn't delete index page caches.
+- Fixed a bug (#3704) - :doc:`Database <database/index>` method ``stored_procedure()`` in the 'oci8' driver didn't properly bind parameters.
+- Fixed a bug (#3778) - :doc:`Download Helper <helpers/download_helper>` function :php:func:`force_download()` incorrectly sent a *Pragma* response header.
+- Fixed a bug (#3752) - ``$routing['directory']`` overrides were not properly handled and always resulted in a 404 "Not Found" error.
+- Fixed a bug (#3279) - :doc:`Query Builder <database/query_builder>` methods ``update()`` and ``get_compiled_update()`` did double escaping on the table name if it was provided via ``from()``.
+- Fixed a bug (#3991) - ``$config['rewrite_short_tags']`` never worked due to ``function_exists('eval')`` always returning FALSE.
+- Fixed a bug where the :doc:`File Uploading Library <libraries/file_uploading>` library will not properly configure its maximum file size unless the input value is of type integer.
+- Fixed a bug (#4000) - :doc:`Pagination Library <libraries/pagination>` didn't enable "rel" attributes by default if no attributes-related config options were used.
+- Fixed a bug (#4004) - :doc:`URI Class <libraries/uri>` didn't properly parse the request URI if it contains a colon followed by a digit.
+- Fixed a bug in :doc:`Query Builder <database/query_builder>` where the ``$escape`` parameter for some methods only affected field names.
Version 3.0.0
=============
@@ -823,6 +847,30 @@ Bug fixes for 3.0
- Fixed a bug (#3573) - :doc:`Email Library <libraries/email>` violated `RFC5321 <https://tools.ietf.org/rfc/rfc5321.txt>`_ by sending 'localhost.localdomain' as a hostname.
- Fixed a bug (#3572) - ``CI_Security::_remove_evil_attributes()`` failed for large-sized inputs due to *pcre.backtrack_limit* and didn't properly match HTML tags.
+Version 2.2.3
+=============
+
+Release Date: July 14, 2015
+
+- Security
+
+ - Removed a fallback to ``mysql_escape_string()`` in the 'mysql' database driver (``escape_str()`` method) when there's no active database connection.
+
+Version 2.2.2
+=============
+
+Release Date: April 15, 2015
+
+- General Changes
+
+ - Added HTTP "Host" header character validation to prevent cache poisoning attacks when *base_url* auto-detection is used.
+ - Added *FSCommand* and *seekSegmentTime* to the "evil attributes" list in ``CI_Security::xss_clean()``.
+
+Bug fixes for 2.2.2
+-------------------
+
+- Fixed a bug (#3665) - ``CI_Security::entity_decode()`` triggered warnings under some circumstances.
+
Version 2.2.1
=============
diff --git a/user_guide_src/source/database/configuration.rst b/user_guide_src/source/database/configuration.rst
index d21c79e44..8026be63a 100644
--- a/user_guide_src/source/database/configuration.rst
+++ b/user_guide_src/source/database/configuration.rst
@@ -152,9 +152,9 @@ when the database classes are initialized.
Explanation of Values:
----------------------
-====================== ==================================================================================================
+====================== ===========================================================================================================
Name Config Description
-====================== ==================================================================================================
+====================== ===========================================================================================================
**dsn** The DSN connect string (an all-in-one configuration sequence).
**hostname** The hostname of your database server. Often this is 'localhost'.
**username** The username used to connect to the database.
@@ -179,6 +179,17 @@ Explanation of Values:
customizable by the end user.
**schema** The database schema, defaults to 'public'. Used by PostgreSQL and ODBC drivers.
**encrypt** Whether or not to use an encrypted connection.
+
+ - 'mysql' (deprecated), 'sqlsrv' and 'pdo/sqlsrv' drivers accept TRUE/FALSE
+ - 'mysqli' and 'pdo/mysql' drivers accept an array with the following options:
+
+ - 'ssl_key' - Path to the private key file
+ - 'ssl_cert' - Path to the public key certificate file
+ - 'ssl_ca' - Path to the certificate authority file
+ - 'ssl_capath' - Path to a directory containing trusted CA certificats in PEM format
+ - 'ssl_cipher' - List of *allowed* ciphers to be used for the encryption, separated by colons (':')
+ - 'ssl_verify' - TRUE/FALSE; Whether to verify the server certificate or not ('mysqli' only)
+
**compress** Whether or not to use client compression (MySQL only).
**stricton** TRUE/FALSE (boolean) - Whether to force "Strict Mode" connections, good for ensuring strict SQL
while developing an application.
@@ -186,10 +197,11 @@ Explanation of Values:
::
$db['default']['port'] = 5432;
-====================== ==================================================================================================
+
+====================== ===========================================================================================================
.. note:: Depending on what database platform you are using (MySQL, PostgreSQL,
etc.) not all values will be needed. For example, when using SQLite you
will not need to supply a username or password, and the database name
will be the path to your database file. The information above assumes
- you are using MySQL. \ No newline at end of file
+ you are using MySQL.
diff --git a/user_guide_src/source/database/forge.rst b/user_guide_src/source/database/forge.rst
index a875f7418..646e3a56e 100644
--- a/user_guide_src/source/database/forge.rst
+++ b/user_guide_src/source/database/forge.rst
@@ -143,6 +143,8 @@ string into the field definitions with add_field()
$this->dbforge->add_field("label varchar(100) NOT NULL DEFAULT 'default label'");
+.. note:: Passing raw strings as fields cannot be followed by ``add_key()`` calls on those fields.
+
.. note:: Multiple calls to add_field() are cumulative.
Creating an id field
diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst
index 0a6d98744..9c3ff306f 100644
--- a/user_guide_src/source/database/query_builder.rst
+++ b/user_guide_src/source/database/query_builder.rst
@@ -640,18 +640,18 @@ Example::
$sql = $this->db->set($data)->get_compiled_insert('mytable');
echo $sql;
- // Produces string: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date')
+ // Produces string: INSERT INTO mytable (`title`, `name`, `date`) VALUES ('My title', 'My name', 'My date')
The second parameter enables you to set whether or not the query builder query
will be reset (by default it will be--just like $this->db->insert())::
echo $this->db->set('title', 'My Title')->get_compiled_insert('mytable', FALSE);
- // Produces string: INSERT INTO mytable (title) VALUES ('My Title')
+ // Produces string: INSERT INTO mytable (`title`) VALUES ('My Title')
echo $this->db->set('content', 'My Content')->get_compiled_insert();
- // Produces string: INSERT INTO mytable (title, content) VALUES ('My Title', 'My Content')
+ // Produces string: INSERT INTO mytable (`title`, `content`) VALUES ('My Title', 'My Content')
The key thing to notice in the above example is that the second query did not
utlize `$this->db->from()` nor did it pass a table name into the first
@@ -730,7 +730,7 @@ or update functions:**
::
$this->db->set('name', $name);
- $this->db->insert('mytable'); // Produces: INSERT INTO mytable (name) VALUES ('{$name}')
+ $this->db->insert('mytable'); // Produces: INSERT INTO mytable (`name`) VALUES ('{$name}')
If you use multiple function called they will be assembled properly
based on whether you are doing an insert or an update::
@@ -740,18 +740,20 @@ based on whether you are doing an insert or an update::
$this->db->set('status', $status);
$this->db->insert('mytable');
-**set()** will also accept an optional third parameter ($escape), that
+**set()** will also accept an optional third parameter (``$escape``), that
will prevent data from being escaped if set to FALSE. To illustrate the
-difference, here is set() used both with and without the escape
+difference, here is ``set()`` used both with and without the escape
parameter.
::
$this->db->set('field', 'field+1', FALSE);
- $this->db->insert('mytable'); // gives INSERT INTO mytable (field) VALUES (field+1)
- $this->db->set('field', 'field+1');
- $this->db->insert('mytable'); // gives INSERT INTO mytable (field) VALUES ('field+1')
+ $this->db->where('id', 2);
+ $this->db->update('mytable'); // gives UPDATE mytable SET field = field+1 WHERE id = 2
+ $this->db->set('field', 'field+1');
+ $this->db->where('id', 2);
+ $this->db->update('mytable'); // gives UPDATE `mytable` SET `field` = 'field+1' WHERE `id` = 2
You can also pass an associative array to this function::
@@ -792,7 +794,11 @@ is an example using an array::
$this->db->where('id', $id);
$this->db->update('mytable', $data);
- // Produces: // UPDATE mytable // SET title = '{$title}', name = '{$name}', date = '{$date}' // WHERE id = $id
+ // Produces:
+ //
+ // UPDATE mytable
+ // SET title = '{$title}', name = '{$name}', date = '{$date}'
+ // WHERE id = $id
Or you can supply an object::
@@ -807,7 +813,11 @@ Or you can supply an object::
$object = new Myclass;
$this->db->where('id', $id);
$this->db->update('mytable', $object);
- // Produces: // UPDATE mytable // SET title = '{$title}', name = '{$name}', date = '{$date}' // WHERE id = $id
+ // Produces:
+ //
+ // UPDATE `mytable`
+ // SET `title` = '{$title}', `name` = '{$name}', `date` = '{$date}'
+ // WHERE id = `$id`
.. note:: All values are escaped automatically producing safer queries.
@@ -1206,7 +1216,7 @@ Class Reference
:param mixed $key: Name of field to compare, or associative array
:param mixed $value: If a single key, compared to this value
- :param boolean $escape: Whether to escape values and identifiers
+ :param bool $escape: Whether to escape values and identifiers
:returns: DB_query_builder instance
:rtype: object
@@ -1217,7 +1227,7 @@ Class Reference
:param mixed $key: Name of field to compare, or associative array
:param mixed $value: If a single key, compared to this value
- :param boolean $escape: Whether to escape values and identifiers
+ :param bool $escape: Whether to escape values and identifiers
:returns: DB_query_builder instance
:rtype: object
@@ -1228,7 +1238,7 @@ Class Reference
:param string $key: The field to search
:param array $values: The values searched on
- :param boolean $escape: Whether to escape identifiers
+ :param bool $escape: Whether to escape values and identifiers
:returns: DB_query_builder instance
:rtype: object
@@ -1239,7 +1249,7 @@ Class Reference
:param string $key: The field to search
:param array $values: The values searched on
- :param boolean $escape: Whether to escape identifiers
+ :param bool $escape: Whether to escape values and identifiers
:returns: DB_query_builder instance
:rtype: object
@@ -1250,7 +1260,7 @@ Class Reference
:param string $key: Name of field to examine
:param array $values: Array of target values
- :param boolean $escape: Whether to escape identifiers
+ :param bool $escape: Whether to escape values and identifiers
:returns: DB_query_builder instance
:rtype: object
@@ -1261,7 +1271,7 @@ Class Reference
:param string $key: Name of field to examine
:param array $values: Array of target values
- :param boolean $escape: Whether to escape identifiers
+ :param bool $escape: Whether to escape values and identifiers
:returns: DB_query_builder instance
:rtype: object
diff --git a/user_guide_src/source/database/results.rst b/user_guide_src/source/database/results.rst
index ac44566d3..6fea7c6be 100644
--- a/user_guide_src/source/database/results.rst
+++ b/user_guide_src/source/database/results.rst
@@ -19,7 +19,7 @@ This method returns the query result as an array of **objects**, or
loop, like this::
$query = $this->db->query("YOUR QUERY");
-
+
foreach ($query->result() as $row)
{
echo $row->title;
@@ -29,22 +29,7 @@ loop, like this::
The above method is an alias of ``result_object()``.
-If you run queries that might **not** produce a result, you are
-encouraged to test the result first::
-
- $query = $this->db->query("YOUR QUERY");
-
- if ($query->num_rows() > 0)
- {
- foreach ($query->result() as $row)
- {
- echo $row->title;
- echo $row->name;
- echo $row->body;
- }
- }
-
-You can also pass a string to result() which represents a class to
+You can also pass a string to ``result()`` which represents a class to
instantiate for each result object (note: this class must be loaded)
::
@@ -64,7 +49,7 @@ array when no result is produced. Typically you'll use this in a foreach
loop, like this::
$query = $this->db->query("YOUR QUERY");
-
+
foreach ($query->result_array() as $row)
{
echo $row['title'];
@@ -83,11 +68,11 @@ one row, it returns only the first row. The result is returned as an
**object**. Here's a usage example::
$query = $this->db->query("YOUR QUERY");
-
- if ($query->num_rows() > 0)
+
+ $row = $query->row();
+
+ if (isset($row))
{
- $row = $query->row();
-
echo $row->title;
echo $row->name;
echo $row->body;
@@ -113,11 +98,11 @@ Identical to the above ``row()`` method, except it returns an array.
Example::
$query = $this->db->query("YOUR QUERY");
-
- if ($query->num_rows() > 0)
+
+ $row = $query->row_array();
+
+ if (isset($row))
{
- $row = $query->row_array();
-
echo $row['title'];
echo $row['name'];
echo $row['body'];
@@ -157,7 +142,7 @@ it returns the current row and moves the internal data pointer ahead.
::
$query = $this->db->query("YOUR QUERY");
-
+
while ($row = $query->unbuffered_row())
{
echo $row->title;
@@ -173,6 +158,94 @@ the returned value's type::
$query->unbuffered_row('array'); // associative array
*********************
+Custom Result Objects
+*********************
+
+You can have the results returned as an instance of a custom class instead
+of a ``stdClass`` or array, as the ``result()`` and ``result_array()``
+methods allow. This requires that the class is already loaded into memory.
+The object will have all values returned from the database set as properties.
+If these have been declared and are non-public then you should provide a
+``__set()`` method to allow them to be set.
+
+Example::
+
+ class User {
+
+ public $id;
+ public $email;
+ public $username;
+
+ protected $last_login;
+
+ public function last_login($format)
+ {
+ return $this->last_login->format($format);
+ }
+
+ public function __set($name, $value)
+ {
+ if ($name === 'last_login')
+ {
+ $this->last_login = DateTime::createFromFormat('U', $value);
+ }
+ }
+
+ public function __get($name)
+ {
+ if (isset($this->$name))
+ {
+ return $this->$name;
+ }
+ }
+ }
+
+In addition to the two methods listed below, the following methods also can
+take a class name to return the results as: ``first_row()``, ``last_row()``,
+``next_row()``, and ``previous_row()``.
+
+**custom_result_object()**
+
+Returns the entire result set as an array of instances of the class requested.
+The only parameter is the name of the class to instantiate.
+
+Example::
+
+ $query = $this->db->query("YOUR QUERY");
+
+ $rows = $query->custom_result_object('User');
+
+ foreach ($rows as $row)
+ {
+ echo $row->id;
+ echo $row->email;
+ echo $row->last_login('Y-m-d');
+ }
+
+**custom_row_object()**
+
+Returns a single row from your query results. The first parameter is the row
+number of the results. The second parameter is the class name to instantiate.
+
+Example::
+
+ $query = $this->db->query("YOUR QUERY");
+
+ $row = $query->custom_row_object(0, 'User');
+
+ if (isset($row))
+ {
+ echo $row->email; // access attributes
+ echo $row->last_login('Y-m-d'); // access class methods
+ }
+
+You can also use the ``row()`` method in exactly the same way.
+
+Example::
+
+ $row = $query->custom_row_object(0, 'User');
+
+*********************
Result Helper Methods
*********************
@@ -182,7 +255,7 @@ The number of rows returned by the query. Note: In this example, $query
is the variable that the query result object is assigned to::
$query = $this->db->query('SELECT * FROM my_table');
-
+
echo $query->num_rows();
.. note:: Not all database drivers have a native way of getting the total
@@ -196,7 +269,7 @@ The number of FIELDS (columns) returned by the query. Make sure to call
the method using your query result object::
$query = $this->db->query('SELECT * FROM my_table');
-
+
echo $query->num_fields();
**free_result()**
@@ -210,7 +283,7 @@ result has been generated in order to cut down on memory consumption.
Example::
$query = $this->db->query('SELECT title FROM my_table');
-
+
foreach ($query->result() as $row)
{
echo $row->title;
diff --git a/user_guide_src/source/database/utilities.rst b/user_guide_src/source/database/utilities.rst
index 2fa5239c8..114291f85 100644
--- a/user_guide_src/source/database/utilities.rst
+++ b/user_guide_src/source/database/utilities.rst
@@ -65,7 +65,7 @@ Returns a boolean TRUE/FALSE. Usage example::
// some code...
}
-.. note:: Replace *database_name* with the name of the table you are
+.. note:: Replace *database_name* with the name of the database you are
looking for. This method is case sensitive.
Optimize a Table
@@ -111,7 +111,7 @@ FALSE on failure.
print_r($result);
}
-.. note:: Not all database platforms support table optimization. It
+.. note:: Not all database platforms support database optimization. It
it is mostly for use with MySQL.
Export a Query Result as a CSV File
diff --git a/user_guide_src/source/general/environments.rst b/user_guide_src/source/general/environments.rst
index 7f030b6ef..ac6f3235e 100644
--- a/user_guide_src/source/general/environments.rst
+++ b/user_guide_src/source/general/environments.rst
@@ -49,4 +49,4 @@ Optionally, you can have CodeIgniter load environment-specific
configuration files. This may be useful for managing things like
differing API keys across multiple environments. This is described in
more detail in the environment section of the :doc:`Config Class
-<../libraries/config>`_ documentation. \ No newline at end of file
+<../libraries/config>` documentation. \ No newline at end of file
diff --git a/user_guide_src/source/helpers/form_helper.rst b/user_guide_src/source/helpers/form_helper.rst
index 9ddca89bc..6317f08ed 100644
--- a/user_guide_src/source/helpers/form_helper.rst
+++ b/user_guide_src/source/helpers/form_helper.rst
@@ -191,7 +191,7 @@ The following functions are available:
:param array $data: Field attributes data
:param string $value: Field value
- :param string $extra: Extra attributes to be added to the tag *as is*
+ :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string
:returns: An HTML text input field tag
:rtype: string
@@ -226,11 +226,16 @@ The following functions are available:
$js = 'onClick="some_function()"';
echo form_input('username', 'johndoe', $js);
+ Or you can pass it as an array::
+
+ $js = array('onClick' => 'some_function();');
+ echo form_input('username', 'johndoe', $js);
+
.. php:function:: form_password([$data = ''[, $value = ''[, $extra = '']]])
:param array $data: Field attributes data
:param string $value: Field value
- :param string $extra: Extra attributes to be added to the tag *as is*
+ :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string
:returns: An HTML password input field tag
:rtype: string
@@ -242,7 +247,7 @@ The following functions are available:
:param array $data: Field attributes data
:param string $value: Field value
- :param string $extra: Extra attributes to be added to the tag *as is*
+ :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string
:returns: An HTML file upload input field tag
:rtype: string
@@ -255,7 +260,7 @@ The following functions are available:
:param array $data: Field attributes data
:param string $value: Field value
- :param string $extra: Extra attributes to be added to the tag *as is*
+ :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string
:returns: An HTML textarea tag
:rtype: string
@@ -270,7 +275,7 @@ The following functions are available:
:param string $name: Field name
:param array $options: An associative array of options to be listed
:param array $selected: List of fields to mark with the *selected* attribute
- :param string $extra: Extra attributes to be added to the tag *as is*
+ :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string
:returns: An HTML dropdown select field tag
:rtype: string
@@ -324,6 +329,14 @@ The following functions are available:
$js = 'id="shirts" onChange="some_function();"';
echo form_dropdown('shirts', $options, 'large', $js);
+ Or you can pass it as an array::
+
+ $js = array(
+ 'id' => 'shirts',
+ 'onChange' => 'some_function();'
+ );
+ echo form_dropdown('shirts', $options, 'large', $js);
+
If the array passed as ``$options`` is a multidimensional array, then
``form_dropdown()`` will produce an <optgroup> with the array key as the
label.
@@ -334,7 +347,7 @@ The following functions are available:
:param string $name: Field name
:param array $options: An associative array of options to be listed
:param array $selected: List of fields to mark with the *selected* attribute
- :param string $extra: Extra attributes to be added to the tag *as is*
+ :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string
:returns: An HTML dropdown multiselect field tag
:rtype: string
@@ -417,7 +430,7 @@ The following functions are available:
:param array $data: Field attributes data
:param string $value: Field value
:param bool $checked: Whether to mark the checkbox as being *checked*
- :param string $extra: Extra attributes to be added to the tag *as is*
+ :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string
:returns: An HTML checkbox input tag
:rtype: string
@@ -450,13 +463,18 @@ The following functions are available:
$js = 'onClick="some_function()"';
echo form_checkbox('newsletter', 'accept', TRUE, $js)
+ Or you can pass it as an array::
+
+ $js = array('onClick' => 'some_function();');
+ echo form_checkbox('newsletter', 'accept', TRUE, $js)
+
.. php:function:: form_radio([$data = ''[, $value = ''[, $checked = FALSE[, $extra = '']]]])
:param array $data: Field attributes data
:param string $value: Field value
:param bool $checked: Whether to mark the radio button as being *checked*
- :param string $extra: Extra attributes to be added to the tag *as is*
+ :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string
:returns: An HTML radio input tag
:rtype: string
@@ -495,7 +513,7 @@ The following functions are available:
:param string $data: Button name
:param string $value: Button value
- :param string $extra: Extra attributes to be added to the tag *as is*
+ :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string
:returns: An HTML input submit tag
:rtype: string
@@ -513,7 +531,7 @@ The following functions are available:
:param string $data: Button name
:param string $value: Button value
- :param string $extra: Extra attributes to be added to the tag *as is*
+ :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string
:returns: An HTML input reset button tag
:rtype: string
@@ -525,7 +543,7 @@ The following functions are available:
:param string $data: Button name
:param string $content: Button label
- :param string $extra: Extra attributes to be added to the tag *as is*
+ :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string
:returns: An HTML button tag
:rtype: string
diff --git a/user_guide_src/source/helpers/text_helper.rst b/user_guide_src/source/helpers/text_helper.rst
index d1723c58a..ef47882fb 100644
--- a/user_guide_src/source/helpers/text_helper.rst
+++ b/user_guide_src/source/helpers/text_helper.rst
@@ -193,7 +193,11 @@ The following functions are available:
$string = "Here is a simple string of text that will help us demonstrate this function.";
echo word_wrap($string, 25);
- // Would produce: Here is a simple string of text that will help us demonstrate this function
+ // Would produce:
+ // Here is a simple string
+ // of text that will help us
+ // demonstrate this
+ // function.
.. php:function:: ellipsize($str, $max_length[, $position = 1[, $ellipsis = '&hellip;']])
diff --git a/user_guide_src/source/installation/downloads.rst b/user_guide_src/source/installation/downloads.rst
index e2b6a9c18..16c8e537a 100644
--- a/user_guide_src/source/installation/downloads.rst
+++ b/user_guide_src/source/installation/downloads.rst
@@ -2,7 +2,10 @@
Downloading CodeIgniter
#######################
-- `CodeIgniter v3.0.0 (Current version) <https://codeload.github.com/bcit-ci/CodeIgniter/zip/develop>`_
+- `CodeIgniter v3.0.1-dev (Current version) <https://codeload.github.com/bcit-ci/CodeIgniter/zip/develop>`_
+- `CodeIgniter v3.0.0 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.0.0>`_
+- `CodeIgniter v2.2.3 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/2.2.3>`_
+- `CodeIgniter v2.2.2 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/2.2.2>`_
- `CodeIgniter v2.2.1 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/2.2.1>`_
- `CodeIgniter v2.2.0 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/2.2.0>`_
- `CodeIgniter v2.1.4 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/2.1.4>`_
diff --git a/user_guide_src/source/installation/upgrade_220.rst b/user_guide_src/source/installation/upgrade_220.rst
index b2e943223..91f9e00cd 100644
--- a/user_guide_src/source/installation/upgrade_220.rst
+++ b/user_guide_src/source/installation/upgrade_220.rst
@@ -1,5 +1,5 @@
#############################
-Upgrading from 2.1.4 to 2.2.0
+Upgrading from 2.1.4 to 2.2.x
#############################
.. note:: The :doc:`Encrypt Class </libraries/encrypt>` now requires the
diff --git a/user_guide_src/source/installation/upgrade_222.rst b/user_guide_src/source/installation/upgrade_222.rst
new file mode 100644
index 000000000..9dcc61d0e
--- /dev/null
+++ b/user_guide_src/source/installation/upgrade_222.rst
@@ -0,0 +1,14 @@
+#############################
+Upgrading from 2.2.1 to 2.2.2
+#############################
+
+Before performing an update you should take your site offline by
+replacing the index.php file with a static one.
+
+Step 1: Update your CodeIgniter files
+=====================================
+
+Replace all files and directories in your "system" folder.
+
+.. note:: If you have any custom developed files in these folders please
+ make copies of them first. \ No newline at end of file
diff --git a/user_guide_src/source/installation/upgrade_223.rst b/user_guide_src/source/installation/upgrade_223.rst
new file mode 100644
index 000000000..252318ae1
--- /dev/null
+++ b/user_guide_src/source/installation/upgrade_223.rst
@@ -0,0 +1,14 @@
+#############################
+Upgrading from 2.2.2 to 2.2.3
+#############################
+
+Before performing an update you should take your site offline by
+replacing the index.php file with a static one.
+
+Step 1: Update your CodeIgniter files
+=====================================
+
+Replace all files and directories in your "system" folder.
+
+.. note:: If you have any custom developed files in these folders please
+ make copies of them first. \ No newline at end of file
diff --git a/user_guide_src/source/installation/upgrade_301.rst b/user_guide_src/source/installation/upgrade_301.rst
new file mode 100644
index 000000000..f38d34008
--- /dev/null
+++ b/user_guide_src/source/installation/upgrade_301.rst
@@ -0,0 +1,19 @@
+#############################
+Upgrading from 3.0.0 to 3.0.1
+#############################
+
+Before performing an update you should take your site offline by
+replacing the index.php file with a static one.
+
+Step 1: Update your CodeIgniter files
+=====================================
+
+Replace all files and directories in your *system/* directory.
+
+.. note:: If you have any custom developed files in these directories,
+ please make copies of them first.
+
+Step 2: Update your CLI error templates
+=======================================
+
+Replace all files under your *application/errors/cli/* directory. \ No newline at end of file
diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst
index 89e90e714..e0f0dd5b7 100644
--- a/user_guide_src/source/installation/upgrading.rst
+++ b/user_guide_src/source/installation/upgrading.rst
@@ -8,9 +8,12 @@ upgrading from.
.. toctree::
:titlesonly:
- Upgrading from 2.2.x to 3.0.0 <upgrade_300>
+ Upgrading from 3.0.0 to 3.0.1 <upgrade_301>
+ Upgrading from 2.2.x to 3.0.x <upgrade_300>
+ Upgrading from 2.2.2 to 2.2.3 <upgrade_223>
+ Upgrading from 2.2.1 to 2.2.2 <upgrade_222>
Upgrading from 2.2.0 to 2.2.1 <upgrade_221>
- Upgrading from 2.1.4 to 2.2.0 <upgrade_220>
+ Upgrading from 2.1.4 to 2.2.x <upgrade_220>
Upgrading from 2.1.3 to 2.1.4 <upgrade_214>
Upgrading from 2.1.2 to 2.1.3 <upgrade_213>
Upgrading from 2.1.1 to 2.1.2 <upgrade_212>
diff --git a/user_guide_src/source/libraries/form_validation.rst b/user_guide_src/source/libraries/form_validation.rst
index fa50c6dcf..be6d1f233 100644
--- a/user_guide_src/source/libraries/form_validation.rst
+++ b/user_guide_src/source/libraries/form_validation.rst
@@ -689,8 +689,12 @@ In this case, you can specify the array to be validated::
$this->form_validation->set_data($data);
-Creating validation rules, running the validation, and retrieving error messages works the
-same whether you are validating ``$_POST`` data or an array.
+Creating validation rules, running the validation, and retrieving error
+messages works the same whether you are validating ``$_POST`` data or
+another array of your choice.
+
+.. important:: You have to call the ``set_data()`` method *before* defining
+ any validation rules.
.. important:: If you want to validate more than one array during a single
execution, then you should call the ``reset_validation()`` method
diff --git a/user_guide_src/source/libraries/output.rst b/user_guide_src/source/libraries/output.rst
index 4b36d2a03..84529f766 100644
--- a/user_guide_src/source/libraries/output.rst
+++ b/user_guide_src/source/libraries/output.rst
@@ -160,7 +160,7 @@ Class Reference
Permits you to manually set a server status header. Example::
- $this->output->set_status_header('401');
+ $this->output->set_status_header(401);
// Sets the header as: Unauthorized
`See here <http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html>`_ for a full list of headers.
@@ -230,4 +230,4 @@ Class Reference
->_display();
exit;
- .. note:: Calling this method manually without aborting script execution will result in duplicated output. \ No newline at end of file
+ .. note:: Calling this method manually without aborting script execution will result in duplicated output.