summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--composer.json2
-rw-r--r--system/core/CodeIgniter.php2
-rw-r--r--system/core/Common.php2
-rw-r--r--system/core/Exceptions.php2
-rw-r--r--system/core/Loader.php7
-rw-r--r--system/core/Output.php95
-rw-r--r--system/core/compat/mbstring.php2
-rw-r--r--system/database/DB_driver.php23
-rw-r--r--system/database/DB_forge.php6
-rw-r--r--system/database/DB_query_builder.php2
-rw-r--r--system/database/drivers/ibase/ibase_forge.php2
-rw-r--r--system/database/drivers/oci8/oci8_forge.php2
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_oci_forge.php2
-rw-r--r--system/helpers/form_helper.php10
-rw-r--r--system/libraries/Email.php213
-rw-r--r--system/libraries/Form_validation.php78
-rw-r--r--system/libraries/Session/drivers/Session_memcached_driver.php5
-rw-r--r--system/libraries/Session/drivers/Session_redis_driver.php8
-rw-r--r--system/libraries/Table.php2
-rw-r--r--tests/codeigniter/core/Loader_test.php21
-rw-r--r--tests/codeigniter/database/query_builder/count_test.php10
-rw-r--r--tests/codeigniter/libraries/Form_validation_test.php27
-rw-r--r--user_guide_src/source/changelog.rst32
-rw-r--r--user_guide_src/source/database/db_driver_reference.rst5
-rw-r--r--user_guide_src/source/general/ancillary_classes.rst2
-rw-r--r--user_guide_src/source/helpers/form_helper.rst2
-rw-r--r--user_guide_src/source/installation/downloads.rst3
-rw-r--r--user_guide_src/source/installation/upgrade_316.rst14
-rw-r--r--user_guide_src/source/installation/upgrading.rst1
-rw-r--r--user_guide_src/source/libraries/email.rst12
-rw-r--r--user_guide_src/source/libraries/form_validation.rst21
-rw-r--r--user_guide_src/source/libraries/security.rst2
32 files changed, 340 insertions, 277 deletions
diff --git a/composer.json b/composer.json
index 0a898d2c1..fea8f1f85 100644
--- a/composer.json
+++ b/composer.json
@@ -11,7 +11,7 @@
"source": "https://github.com/bcit-ci/CodeIgniter"
},
"require": {
- "php": ">=5.2.4"
+ "php": ">=5.4.8"
},
"suggest": {
"paragonie/random_compat": "Provides better randomness in PHP 5.x"
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 8eed52eb7..c97ff2bbb 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -383,7 +383,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* ReflectionMethod::isConstructor() is the ONLY reliable check,
* knowing which method will be executed as a constructor.
*/
- elseif ( ! is_callable(array($class, $method)) && strcasecmp($class, $method) === 0)
+ elseif ( ! is_callable(array($class, $method)))
{
$reflection = new ReflectionMethod($class, $method);
if ( ! $reflection->isPublic() OR $reflection->isConstructor())
diff --git a/system/core/Common.php b/system/core/Common.php
index c4f6dd30b..bf9924df5 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -134,7 +134,7 @@ if ( ! function_exists('load_class'))
*
* @param string the class name being requested
* @param string the directory where the class should be found
- * @param string an optional argument to pass to the class constructor
+ * @param mixed an optional argument to pass to the class constructor
* @return object
*/
function &load_class($class, $directory = 'libraries', $param = NULL)
diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php
index 806598921..399b1bd63 100644
--- a/system/core/Exceptions.php
+++ b/system/core/Exceptions.php
@@ -239,7 +239,7 @@ class CI_Exceptions {
* @param string $message Error message
* @param string $filepath File path
* @param int $line Line number
- * @return string Error page output
+ * @return void
*/
public function show_php_error($severity, $message, $filepath, $line)
{
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 7279e8833..6374558ad 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -182,7 +182,7 @@ class CI_Loader {
* Loads and instantiates libraries.
* Designed to be called from application controllers.
*
- * @param string $library Library name
+ * @param mixed $library Library name
* @param array $params Optional parameters to pass to the library class constructor
* @param string $object_name An optional object name to assign to
* @return object
@@ -344,9 +344,10 @@ class CI_Loader {
throw new RuntimeException('Unable to locate the model you have specified: '.$model);
}
}
- elseif ( ! is_subclass_of($model, 'CI_Model'))
+
+ if ( ! is_subclass_of($model, 'CI_Model'))
{
- throw new RuntimeException("Class ".$model." already exists and doesn't extend CI_Model");
+ throw new RuntimeException("Class ".$model." doesn't extend CI_Model");
}
$this->_ci_models[] = $name;
diff --git a/system/core/Output.php b/system/core/Output.php
index c684c94c9..2dabb2445 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -586,62 +586,59 @@ class CI_Output {
return;
}
- if (flock($fp, LOCK_EX))
+ if ( ! flock($fp, LOCK_EX))
{
- // If output compression is enabled, compress the cache
- // itself, so that we don't have to do that each time
- // we're serving it
- if ($this->_compress_output === TRUE)
- {
- $output = gzencode($output);
+ log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
+ fclose($fp);
+ return;
+ }
- if ($this->get_header('content-type') === NULL)
- {
- $this->set_content_type($this->mime_type);
- }
+ // If output compression is enabled, compress the cache
+ // itself, so that we don't have to do that each time
+ // we're serving it
+ if ($this->_compress_output === TRUE)
+ {
+ $output = gzencode($output);
+
+ if ($this->get_header('content-type') === NULL)
+ {
+ $this->set_content_type($this->mime_type);
}
+ }
- $expire = time() + ($this->cache_expiration * 60);
+ $expire = time() + ($this->cache_expiration * 60);
- // Put together our serialized info.
- $cache_info = serialize(array(
- 'expire' => $expire,
- 'headers' => $this->headers
- ));
+ // Put together our serialized info.
+ $cache_info = serialize(array(
+ 'expire' => $expire,
+ 'headers' => $this->headers
+ ));
- $output = $cache_info.'ENDCI--->'.$output;
+ $output = $cache_info.'ENDCI--->'.$output;
- for ($written = 0, $length = self::strlen($output); $written < $length; $written += $result)
+ for ($written = 0, $length = self::strlen($output); $written < $length; $written += $result)
+ {
+ if (($result = fwrite($fp, self::substr($output, $written))) === FALSE)
{
- if (($result = fwrite($fp, self::substr($output, $written))) === FALSE)
- {
- break;
- }
+ break;
}
-
- flock($fp, LOCK_UN);
- }
- else
- {
- log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
- return;
}
+ flock($fp, LOCK_UN);
fclose($fp);
- if (is_int($result))
- {
- chmod($cache_path, 0640);
- log_message('debug', 'Cache file written: '.$cache_path);
-
- // Send HTTP cache-control headers to browser to match file cache settings.
- $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
- }
- else
+ if ( ! is_int($result))
{
@unlink($cache_path);
log_message('error', 'Unable to write the complete cache content at: '.$cache_path);
+ return;
}
+
+ chmod($cache_path, 0640);
+ log_message('debug', 'Cache file written: '.$cache_path);
+
+ // Send HTTP cache-control headers to browser to match file cache settings.
+ $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
}
// --------------------------------------------------------------------
@@ -708,11 +705,9 @@ class CI_Output {
log_message('debug', 'Cache file has expired. File deleted.');
return FALSE;
}
- else
- {
- // Or else send the HTTP cache control headers.
- $this->set_cache_header($last_modified, $expire);
- }
+
+ // Send the HTTP cache control headers
+ $this->set_cache_header($last_modified, $expire);
// Add headers from cache file.
foreach ($cache_info['headers'] as $header)
@@ -798,13 +793,11 @@ class CI_Output {
$this->set_status_header(304);
exit;
}
- else
- {
- header('Pragma: public');
- header('Cache-Control: max-age='.$max_age.', public');
- header('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT');
- header('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT');
- }
+
+ header('Pragma: public');
+ header('Cache-Control: max-age='.$max_age.', public');
+ header('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT');
+ header('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT');
}
// --------------------------------------------------------------------
diff --git a/system/core/compat/mbstring.php b/system/core/compat/mbstring.php
index f466e1c34..1b2f2c63b 100644
--- a/system/core/compat/mbstring.php
+++ b/system/core/compat/mbstring.php
@@ -68,7 +68,7 @@ if ( ! function_exists('mb_strlen'))
* @link http://php.net/mb_strlen
* @param string $str
* @param string $encoding
- * @return string
+ * @return int
*/
function mb_strlen($str, $encoding = NULL)
{
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index de599a675..1dc23d72e 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -1320,10 +1320,11 @@ abstract class CI_DB_driver {
*
* This function escapes column and table names
*
- * @param mixed
+ * @param mixed $item Identifier to escape
+ * @param bool $split Whether to split identifiers when a dot is encountered
* @return mixed
*/
- public function escape_identifiers($item)
+ public function escape_identifiers($item, $split = TRUE)
{
if ($this->_escape_char === '' OR empty($item) OR in_array($item, $this->_reserved_identifiers))
{
@@ -1344,22 +1345,22 @@ abstract class CI_DB_driver {
return $item;
}
- static $preg_ec = array();
+ static $preg_ec;
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], '/'),
+ preg_quote($this->_escape_char[0]),
+ preg_quote($this->_escape_char[1]),
$this->_escape_char[0],
$this->_escape_char[1]
);
}
else
{
- $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char, '/');
+ $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char);
$preg_ec[2] = $preg_ec[3] = $this->_escape_char;
}
}
@@ -1368,11 +1369,13 @@ abstract class CI_DB_driver {
{
if (strpos($item, '.'.$id) !== FALSE)
{
- return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?\./i', $preg_ec[2].'$1'.$preg_ec[3].'.', $item);
+ return preg_replace('#'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?\.#i', $preg_ec[2].'$1'.$preg_ec[3].'.', $item);
}
}
- return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?(\.)?/i', $preg_ec[2].'$1'.$preg_ec[3].'$2', $item);
+ $dot = ($split !== FALSE) ? '\.' : '';
+
+ return preg_replace('#'.$preg_ec[0].'?([^'.$preg_ec[1].$dot.']+)'.$preg_ec[1].'?(\.)?#i', $preg_ec[2].'$1'.$preg_ec[3].'$2', $item);
}
// --------------------------------------------------------------------
@@ -1786,14 +1789,14 @@ abstract class CI_DB_driver {
if ($offset = strripos($item, ' AS '))
{
$alias = ($protect_identifiers)
- ? substr($item, $offset, 4).$this->escape_identifiers(substr($item, $offset + 4))
+ ? substr($item, $offset, 4).$this->escape_identifiers(substr($item, $offset + 4), FALSE)
: substr($item, $offset);
$item = substr($item, 0, $offset);
}
elseif ($offset = strrpos($item, ' '))
{
$alias = ($protect_identifiers)
- ? ' '.$this->escape_identifiers(substr($item, $offset + 1))
+ ? ' '.$this->escape_identifiers(substr($item, $offset + 1), FALSE)
: substr($item, $offset);
$item = substr($item, 0, $offset);
}
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index b52d1fb2b..31fae43cf 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -488,7 +488,7 @@ abstract class CI_DB_forge {
*
* @param string $table Table name
* @param bool $if_exists Whether to add an IF EXISTS condition
- * @return string
+ * @return mixed (Returns a platform-specific DROP table string, or TRUE to indicate there's nothing to do)
*/
protected function _drop_table($table, $if_exists)
{
@@ -991,8 +991,8 @@ abstract class CI_DB_forge {
/**
* Process indexes
*
- * @param string $table
- * @return string
+ * @param string $table Table name
+ * @return string[] list of SQL statements
*/
protected function _process_indexes($table)
{
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index ef375227c..102ff4ac0 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -1488,7 +1488,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$this->qb_orderby = NULL;
}
- $result = ($this->qb_distinct === TRUE OR ! empty($this->qb_groupby) OR ! empty($this->qb_cache_groupby))
+ $result = ($this->qb_distinct === TRUE OR ! empty($this->qb_groupby) OR ! empty($this->qb_cache_groupby) OR $this->qb_limit OR $this->qb_offset)
? $this->query($this->_count_string.$this->protect_identifiers('numrows')."\nFROM (\n".$this->_compile_select()."\n) CI_count_all_results")
: $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows')));
diff --git a/system/database/drivers/ibase/ibase_forge.php b/system/database/drivers/ibase/ibase_forge.php
index 44bb24e68..31352f128 100644
--- a/system/database/drivers/ibase/ibase_forge.php
+++ b/system/database/drivers/ibase/ibase_forge.php
@@ -91,7 +91,7 @@ class CI_DB_ibase_forge extends CI_DB_forge {
* Create database
*
* @param string $db_name
- * @return string
+ * @return bool
*/
public function create_database($db_name)
{
diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php
index 867a94341..724a76df4 100644
--- a/system/database/drivers/oci8/oci8_forge.php
+++ b/system/database/drivers/oci8/oci8_forge.php
@@ -124,7 +124,7 @@ class CI_DB_oci8_forge extends CI_DB_forge {
if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name']))
{
$sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
- .' '.$this->db->escape_identifiers($field[$i]['new_name']);
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
}
$field[$i] = "\n\t".$field[$i]['_literal'];
diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
index c8983ee56..813207b8e 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
@@ -117,7 +117,7 @@ class CI_DB_pdo_oci_forge extends CI_DB_pdo_forge {
if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name']))
{
$sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
- .' '.$this->db->escape_identifiers($field[$i]['new_name']);
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
}
}
}
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
index 4a4a7c89f..0c7ee4a40 100644
--- a/system/helpers/form_helper.php
+++ b/system/helpers/form_helper.php
@@ -596,7 +596,7 @@ if ( ! function_exists('form_label'))
*
* @param string The text to appear onscreen
* @param string The id the label applies to
- * @param array Additional attributes
+ * @param mixed Additional attributes
* @return string
*/
function form_label($label_text = '', $id = '', $attributes = array())
@@ -609,13 +609,7 @@ if ( ! function_exists('form_label'))
$label .= ' for="'.$id.'"';
}
- if (is_array($attributes) && count($attributes) > 0)
- {
- foreach ($attributes as $key => $val)
- {
- $label .= ' '.$key.'="'.$val.'"';
- }
- }
+ $label .= _attributes_to_string($attributes);
return $label.'>'.$label_text.'</label>';
}
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index d7178f321..1dcafeddd 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -893,18 +893,13 @@ class CI_Email {
/**
* Get Mail Protocol
*
- * @param bool
* @return mixed
*/
- protected function _get_protocol($return = TRUE)
+ protected function _get_protocol()
{
$this->protocol = strtolower($this->protocol);
in_array($this->protocol, $this->_protocols, TRUE) OR $this->protocol = 'mail';
-
- if ($return === TRUE)
- {
- return $this->protocol;
- }
+ return $this->protocol;
}
// --------------------------------------------------------------------
@@ -912,25 +907,21 @@ class CI_Email {
/**
* Get Mail Encoding
*
- * @param bool
* @return string
*/
- protected function _get_encoding($return = TRUE)
+ protected function _get_encoding()
{
in_array($this->_encoding, $this->_bit_depths) OR $this->_encoding = '8bit';
foreach ($this->_base_charsets as $charset)
{
- if (strpos($charset, $this->charset) === 0)
+ if (strpos($this->charset, $charset) === 0)
{
$this->_encoding = '7bit';
}
}
- if ($return === TRUE)
- {
- return $this->_encoding;
- }
+ return $this->_encoding;
}
// --------------------------------------------------------------------
@@ -1244,7 +1235,7 @@ class CI_Email {
/**
* Build Final Body and attachments
*
- * @return bool
+ * @return void
*/
protected function _build_message()
{
@@ -1411,8 +1402,6 @@ class CI_Email {
$this->_finalbody = ($this->_get_protocol() === 'mail')
? $body
: $hdr.$this->newline.$this->newline.$body;
-
- return TRUE;
}
// --------------------------------------------------------------------
@@ -1674,8 +1663,8 @@ class CI_Email {
$this->reply_to($this->_headers['From']);
}
- if ( ! isset($this->_recipients) && ! isset($this->_headers['To'])
- && ! isset($this->_bcc_array) && ! isset($this->_headers['Bcc'])
+ if (empty($this->_recipients) && ! isset($this->_headers['To'])
+ && empty($this->_bcc_array) && ! isset($this->_headers['Bcc'])
&& ! isset($this->_headers['Cc']))
{
$this->_set_error_message('lang:email_no_recipients');
@@ -1686,21 +1675,17 @@ class CI_Email {
if ($this->bcc_batch_mode && count($this->_bcc_array) > $this->bcc_batch_size)
{
- $result = $this->batch_bcc_send();
+ $this->batch_bcc_send();
- if ($result && $auto_clear)
+ if ($auto_clear)
{
$this->clear();
}
- return $result;
- }
-
- if ($this->_build_message() === FALSE)
- {
- return FALSE;
+ return TRUE;
}
+ $this->_build_message();
$result = $this->_spool_email();
if ($result && $auto_clear)
@@ -1759,11 +1744,7 @@ class CI_Email {
$this->_bcc_array = $bcc;
}
- if ($this->_build_message() === FALSE)
- {
- return FALSE;
- }
-
+ $this->_build_message();
$this->_spool_email();
}
}
@@ -1809,14 +1790,15 @@ class CI_Email {
{
$this->_unwrap_specials();
- $method = '_send_with_'.$this->_get_protocol();
+ $protocol = $this->_get_protocol();
+ $method = '_send_with_'.$protocol;
if ( ! $this->$method())
{
- $this->_set_error_message('lang:email_send_failure_'.($this->_get_protocol() === 'mail' ? 'phpmail' : $this->_get_protocol()));
+ $this->_set_error_message('lang:email_send_failure_'.($protocol === 'mail' ? 'phpmail' : $protocol));
return FALSE;
}
- $this->_set_error_message('lang:email_sent', $this->_get_protocol());
+ $this->_set_error_message('lang:email_sent', $protocol);
return TRUE;
}
@@ -1953,27 +1935,21 @@ class CI_Email {
}
}
- if (count($this->_cc_array) > 0)
+ foreach ($this->_cc_array as $val)
{
- foreach ($this->_cc_array as $val)
+ if ($val !== '' && ! $this->_send_command('to', $val))
{
- if ($val !== '' && ! $this->_send_command('to', $val))
- {
- $this->_smtp_end();
- return FALSE;
- }
+ $this->_smtp_end();
+ return FALSE;
}
}
- if (count($this->_bcc_array) > 0)
+ foreach ($this->_bcc_array as $val)
{
- foreach ($this->_bcc_array as $val)
+ if ($val !== '' && ! $this->_send_command('to', $val))
{
- if ($val !== '' && ! $this->_send_command('to', $val))
- {
- $this->_smtp_end();
- return FALSE;
- }
+ $this->_smtp_end();
+ return FALSE;
}
}
@@ -1987,7 +1963,6 @@ class CI_Email {
$this->_send_data($this->_header_str.preg_replace('/^\./m', '..$1', $this->_finalbody));
$this->_send_data('.');
-
$reply = $this->_get_smtp_data();
$this->_set_error_message($reply);
@@ -2013,9 +1988,7 @@ class CI_Email {
*/
protected function _smtp_end()
{
- ($this->smtp_keepalive)
- ? $this->_send_command('reset')
- : $this->_send_command('quit');
+ $this->_send_command($this->smtp_keepalive ? 'reset' : 'quit');
}
// --------------------------------------------------------------------
@@ -2034,11 +2007,13 @@ class CI_Email {
$ssl = ($this->smtp_crypto === 'ssl') ? 'ssl://' : '';
- $this->_smtp_connect = fsockopen($ssl.$this->smtp_host,
- $this->smtp_port,
- $errno,
- $errstr,
- $this->smtp_timeout);
+ $this->_smtp_connect = fsockopen(
+ $ssl.$this->smtp_host,
+ $this->smtp_port,
+ $errno,
+ $errstr,
+ $this->smtp_timeout
+ );
if ( ! is_resource($this->_smtp_connect))
{
@@ -2079,57 +2054,49 @@ class CI_Email {
{
switch ($cmd)
{
- case 'hello' :
-
- if ($this->_smtp_auth OR $this->_get_encoding() === '8bit')
- {
- $this->_send_data('EHLO '.$this->_get_hostname());
- }
- else
- {
- $this->_send_data('HELO '.$this->_get_hostname());
- }
-
- $resp = 250;
- break;
- case 'starttls' :
-
- $this->_send_data('STARTTLS');
- $resp = 220;
- break;
- case 'from' :
-
- $this->_send_data('MAIL FROM:<'.$data.'>');
- $resp = 250;
- break;
- case 'to' :
-
- if ($this->dsn)
- {
- $this->_send_data('RCPT TO:<'.$data.'> NOTIFY=SUCCESS,DELAY,FAILURE ORCPT=rfc822;'.$data);
- }
- else
- {
- $this->_send_data('RCPT TO:<'.$data.'>');
- }
-
- $resp = 250;
- break;
- case 'data' :
-
- $this->_send_data('DATA');
- $resp = 354;
- break;
- case 'reset':
-
- $this->_send_data('RSET');
- $resp = 250;
- break;
- case 'quit' :
+ case 'hello':
+ if ($this->_smtp_auth OR $this->_get_encoding() === '8bit')
+ {
+ $this->_send_data('EHLO '.$this->_get_hostname());
+ }
+ else
+ {
+ $this->_send_data('HELO '.$this->_get_hostname());
+ }
- $this->_send_data('QUIT');
- $resp = 221;
- break;
+ $resp = 250;
+ break;
+ case 'starttls':
+ $this->_send_data('STARTTLS');
+ $resp = 220;
+ break;
+ case 'from':
+ $this->_send_data('MAIL FROM:<'.$data.'>');
+ $resp = 250;
+ break;
+ case 'to':
+ if ($this->dsn)
+ {
+ $this->_send_data('RCPT TO:<'.$data.'> NOTIFY=SUCCESS,DELAY,FAILURE ORCPT=rfc822;'.$data);
+ }
+ else
+ {
+ $this->_send_data('RCPT TO:<'.$data.'>');
+ }
+ $resp = 250;
+ break;
+ case 'data':
+ $this->_send_data('DATA');
+ $resp = 354;
+ break;
+ case 'reset':
+ $this->_send_data('RSET');
+ $resp = 250;
+ break;
+ case 'quit':
+ $this->_send_data('QUIT');
+ $resp = 221;
+ break;
}
$reply = $this->_get_smtp_data();
@@ -2171,7 +2138,6 @@ class CI_Email {
}
$this->_send_data('AUTH LOGIN');
-
$reply = $this->_get_smtp_data();
if (strpos($reply, '503') === 0) // Already authenticated
@@ -2185,7 +2151,6 @@ class CI_Email {
}
$this->_send_data(base64_encode($this->smtp_user));
-
$reply = $this->_get_smtp_data();
if (strpos($reply, '334') !== 0)
@@ -2195,7 +2160,6 @@ class CI_Email {
}
$this->_send_data(base64_encode($this->smtp_pass));
-
$reply = $this->_get_smtp_data();
if (strpos($reply, '235') !== 0)
@@ -2318,34 +2282,15 @@ class CI_Email {
*/
public function print_debugger($include = array('headers', 'subject', 'body'))
{
- $msg = '';
-
- if (count($this->_debug_msg) > 0)
- {
- foreach ($this->_debug_msg as $val)
- {
- $msg .= $val;
- }
- }
+ $msg = implode('', $this->_debug_msg);
// Determine which parts of our raw data needs to be printed
$raw_data = '';
is_array($include) OR $include = array($include);
- if (in_array('headers', $include, TRUE))
- {
- $raw_data = htmlspecialchars($this->_header_str)."\n";
- }
-
- if (in_array('subject', $include, TRUE))
- {
- $raw_data .= htmlspecialchars($this->_subject)."\n";
- }
-
- if (in_array('body', $include, TRUE))
- {
- $raw_data .= htmlspecialchars($this->_finalbody);
- }
+ in_array('headers', $include, TRUE) && $raw_data = htmlspecialchars($this->_header_str)."\n";
+ in_array('subject', $include, TRUE) && $raw_data .= htmlspecialchars($this->_subject)."\n";
+ in_array('body', $include, TRUE) && $raw_data .= htmlspecialchars($this->_finalbody);
return $msg.($raw_data === '' ? '' : '<pre>'.$raw_data.'</pre>');
}
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index 7be0b949d..c1cfcdb8f 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -105,13 +105,6 @@ class CI_Form_validation {
protected $error_string = '';
/**
- * Whether the form data has been validated as safe
- *
- * @var bool
- */
- protected $_safe_form_data = FALSE;
-
- /**
* Custom data to validate
*
* @var array
@@ -414,10 +407,11 @@ class CI_Form_validation {
*
* This function does all the work.
*
- * @param string $group
+ * @param string $config
+ * @param array $data
* @return bool
*/
- public function run($group = '')
+ public function run($config = NULL, &$data = NULL)
{
$validation_array = empty($this->validation_data)
? $_POST
@@ -428,19 +422,19 @@ class CI_Form_validation {
if (count($this->_field_data) === 0)
{
// No validation rules? We're done...
- if (count($this->_config_rules) === 0)
+ if (empty($this->_config_rules))
{
return FALSE;
}
- if (empty($group))
+ if (empty($config))
{
// Is there a validation rule for the particular URI being accessed?
- $group = trim($this->CI->uri->ruri_string(), '/');
- isset($this->_config_rules[$group]) OR $group = $this->CI->router->class.'/'.$this->CI->router->method;
+ $config = trim($this->CI->uri->ruri_string(), '/');
+ isset($this->_config_rules[$config]) OR $config = $this->CI->router->class.'/'.$this->CI->router->method;
}
- $this->set_rules(isset($this->_config_rules[$group]) ? $this->_config_rules[$group] : $this->_config_rules);
+ $this->set_rules(isset($this->_config_rules[$config]) ? $this->_config_rules[$config] : $this->_config_rules);
// Were we able to set the rules correctly?
if (count($this->_field_data) === 0)
@@ -482,17 +476,22 @@ class CI_Form_validation {
$this->_execute($row, $row['rules'], $row['postdata']);
}
- // Did we end up with any errors?
- $total_errors = count($this->_error_array);
- if ($total_errors > 0)
+ if ( ! empty($this->_error_array))
{
- $this->_safe_form_data = TRUE;
+ return FALSE;
}
- // Now we need to re-set the POST data with the new, processed data
- empty($this->validation_data) && $this->_reset_post_array();
+ // Fill $data if requested, otherwise modify $_POST, as long as
+ // set_data() wasn't used (yea, I know it sounds confusing)
+ if (func_num_args() >= 2)
+ {
+ $data = empty($this->validation_data) ? $_POST : $this->validation_data;
+ $this->_reset_data_array($data);
+ return TRUE;
+ }
- return ($total_errors === 0);
+ empty($this->validation_data) && $this->_reset_data_array($_POST);
+ return TRUE;
}
// --------------------------------------------------------------------
@@ -580,7 +579,7 @@ class CI_Form_validation {
*
* @return void
*/
- protected function _reset_post_array()
+ protected function _reset_data_array(&$data)
{
foreach ($this->_field_data as $field => $row)
{
@@ -588,27 +587,24 @@ class CI_Form_validation {
{
if ($row['is_array'] === FALSE)
{
- isset($_POST[$field]) && $_POST[$field] = $row['postdata'];
+ isset($data[$field]) && $data[$field] = $row['postdata'];
}
else
{
- // start with a reference
- $post_ref =& $_POST;
-
// before we assign values, make a reference to the right POST key
if (count($row['keys']) === 1)
{
- $post_ref =& $post_ref[current($row['keys'])];
+ $data_ref =& $data[current($row['keys'])];
}
else
{
foreach ($row['keys'] as $val)
{
- $post_ref =& $post_ref[$val];
+ $data_ref =& $data_ref[$val];
}
}
- $post_ref = $row['postdata'];
+ $data_ref = $row['postdata'];
}
}
}
@@ -627,11 +623,13 @@ class CI_Form_validation {
*/
protected function _execute($row, $rules, $postdata = NULL, $cycles = 0)
{
+ $allow_arrays = in_array('is_array', $rules, TRUE);
+
// If the $_POST data is an array we will run a recursive call
//
// Note: We MUST check if the array is empty or not!
// Otherwise empty arrays will always pass validation.
- if (is_array($postdata) && ! empty($postdata))
+ if ($allow_arrays === FALSE && is_array($postdata) && ! empty($postdata))
{
foreach ($postdata as $key => $val)
{
@@ -660,14 +658,16 @@ class CI_Form_validation {
$postdata = $this->_field_data[$row['field']]['postdata'][$cycles];
$_in_array = TRUE;
}
+ // If we get an array field, but it's not expected - then it is most likely
+ // somebody messing with the form on the client side, so we'll just consider
+ // it an empty field
+ elseif ($allow_arrays === FALSE && is_array($this->_field_data[$row['field']]['postdata']))
+ {
+ $postdata = NULL;
+ }
else
{
- // If we get an array field, but it's not expected - then it is most likely
- // somebody messing with the form on the client side, so we'll just consider
- // it an empty field
- $postdata = is_array($this->_field_data[$row['field']]['postdata'])
- ? NULL
- : $this->_field_data[$row['field']]['postdata'];
+ $postdata = $this->_field_data[$row['field']]['postdata'];
}
// Is the rule a callback?
@@ -702,7 +702,7 @@ class CI_Form_validation {
// Ignore empty, non-required inputs with a few exceptions ...
if (
- ($postdata === NULL OR $postdata === '')
+ ($postdata === NULL OR ($allow_arrays === FALSE && $postdata === ''))
&& $callback === FALSE
&& $callable === FALSE
&& ! in_array($rule, array('required', 'isset', 'matches'), TRUE)
@@ -1233,9 +1233,9 @@ class CI_Form_validation {
*/
public function valid_email($str)
{
- if (function_exists('idn_to_ascii') && sscanf($str, '%[^@]@%s', $name, $domain) === 2)
+ if (function_exists('idn_to_ascii') && preg_match('#\A([^@]+)@(.+)\z#', $str, $matches))
{
- $str = $name.'@'.idn_to_ascii($domain);
+ $str = $matches[1].'@'.idn_to_ascii($matches[2]);
}
return (bool) filter_var($str, FILTER_VALIDATE_EMAIL);
diff --git a/system/libraries/Session/drivers/Session_memcached_driver.php b/system/libraries/Session/drivers/Session_memcached_driver.php
index 2556bf0f7..5e90539d7 100644
--- a/system/libraries/Session/drivers/Session_memcached_driver.php
+++ b/system/libraries/Session/drivers/Session_memcached_driver.php
@@ -310,7 +310,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa
if ( ! $this->_memcached->replace($this->_lock_key, time(), 300))
{
return ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND)
- ? $this->_memcached->set($this->_lock_key, time(), 300)
+ ? $this->_memcached->add($this->_lock_key, time(), 300)
: FALSE;
}
}
@@ -326,7 +326,8 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa
continue;
}
- if ( ! $this->_memcached->set($lock_key, time(), 300))
+ $method = ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND) ? 'add' : 'set';
+ if ( ! $this->_memcached->$method($lock_key, time(), 300))
{
log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);
return FALSE;
diff --git a/system/libraries/Session/drivers/Session_redis_driver.php b/system/libraries/Session/drivers/Session_redis_driver.php
index 5313de04c..76bddffd3 100644
--- a/system/libraries/Session/drivers/Session_redis_driver.php
+++ b/system/libraries/Session/drivers/Session_redis_driver.php
@@ -51,7 +51,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
/**
* phpRedis instance
*
- * @var resource
+ * @var Redis
*/
protected $_redis;
@@ -365,7 +365,11 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
continue;
}
- if ( ! $this->_redis->setex($lock_key, 300, time()))
+ $result = ($ttl === -2)
+ ? $this->_redis->set($lock_key, time(), array('nx', 'ex' => 300))
+ : $this->_redis->setex($lock_key, 300, time());
+
+ if ( ! $result)
{
log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);
return FALSE;
diff --git a/system/libraries/Table.php b/system/libraries/Table.php
index dc309890b..ba096836b 100644
--- a/system/libraries/Table.php
+++ b/system/libraries/Table.php
@@ -436,7 +436,7 @@ class CI_Table {
/**
* Set table data from a database result object
*
- * @param CI_DB_result $db_result Database result object
+ * @param CI_DB_result $object Database result object
* @return void
*/
protected function _set_from_db_result($object)
diff --git a/tests/codeigniter/core/Loader_test.php b/tests/codeigniter/core/Loader_test.php
index 241c415b3..3b6a7e16c 100644
--- a/tests/codeigniter/core/Loader_test.php
+++ b/tests/codeigniter/core/Loader_test.php
@@ -269,6 +269,25 @@ class Loader_test extends CI_TestCase {
// --------------------------------------------------------------------
+ public function test_invalid_model()
+ {
+ $this->ci_set_core_class('model', 'CI_Model');
+
+ // Create model in VFS
+ $model = 'Unit_test_invalid_model';
+ $content = '<?php class '.$model.' {} ';
+ $this->ci_vfs_create($model, $content, $this->ci_app_root, 'models');
+
+ // Test no extending
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'Class '.$model.' doesn\'t extend CI_Model'
+ );
+ $this->load->model($model);
+ }
+
+ // --------------------------------------------------------------------
+
// public function testDatabase()
// {
// $this->assertInstanceOf('CI_Loader', $this->load->database());
@@ -544,7 +563,7 @@ class Loader_test extends CI_TestCase {
$dir = 'testdir';
$path = APPPATH.$dir.'/';
$model = 'Automod';
- $this->ci_vfs_create($model, '<?php class '.$model.' { }', $this->ci_app_root, array($dir, 'models'));
+ $this->ci_vfs_create($model, '<?php class '.$model.' extends CI_Model { }', $this->ci_app_root, array($dir, 'models'));
// Create autoloader config
$cfg = array(
diff --git a/tests/codeigniter/database/query_builder/count_test.php b/tests/codeigniter/database/query_builder/count_test.php
index 90ac5283e..da312d866 100644
--- a/tests/codeigniter/database/query_builder/count_test.php
+++ b/tests/codeigniter/database/query_builder/count_test.php
@@ -35,4 +35,14 @@ class Count_test extends CI_TestCase {
$this->assertEquals(2, $this->db->like('name', 'ian')->count_all_results('job'));
}
+ // ------------------------------------------------------------------------
+
+ /**
+ * @see ./mocks/schema/skeleton.php
+ */
+ public function test_count_all_results_limit()
+ {
+ $this->assertEquals(1, $this->db->like('name', 'ian')->limit(1)->count_all_results('job'));
+ }
+
} \ No newline at end of file
diff --git a/tests/codeigniter/libraries/Form_validation_test.php b/tests/codeigniter/libraries/Form_validation_test.php
index 035410724..ebb14983e 100644
--- a/tests/codeigniter/libraries/Form_validation_test.php
+++ b/tests/codeigniter/libraries/Form_validation_test.php
@@ -43,7 +43,6 @@ class Form_validation_test extends CI_TestCase {
// Empty, not required
$this->assertTrue($this->run_rules($rules, array('foo' => '')));
-
// Not required, but also not empty
$this->assertTrue($this->run_rules($rules, array('foo' => '123')));
$this->assertFalse($this->run_rules($rules, array('foo' => 'bar')));
@@ -56,6 +55,13 @@ class Form_validation_test extends CI_TestCase {
$this->assertFalse($this->run_rules($rules, array('foo' => 'bar')));
}
+ public function test_rule_is_array()
+ {
+ $rules = array(array('field' => 'foo', 'label' => 'Foo', 'rules' => 'is_array'));
+ $this->assertTrue($this->run_rules($rules, array('foo' => array('1', '2'))));
+ $this->assertFalse($this->run_rules($rules, array('foo' => '')));
+ }
+
public function test_rule_matches()
{
$rules = array(
@@ -268,6 +274,7 @@ class Form_validation_test extends CI_TestCase {
public function test_rule_valid_email()
{
$this->assertTrue($this->form_validation->valid_email('email@sample.com'));
+ $this->assertFalse($this->form_validation->valid_email('email@sample.com foo bar'));
$this->assertFalse($this->form_validation->valid_email('valid_email', '@sample.com'));
}
@@ -603,6 +610,24 @@ class Form_validation_test extends CI_TestCase {
$this->assertEquals('?&gt;', $this->form_validation->encode_php_tags('?>'));
}
+ public function test_validated_data_assignment()
+ {
+ $_POST = $post_original = array('foo' => ' bar ', 'bar' => 'baz');
+
+ $this->form_validation->set_data($_POST);
+ $this->form_validation->set_rules('foo', 'Foo', 'required|trim');
+
+ $data_processed = NULL;
+ $validation_result = $this->form_validation->run('', $data_processed);
+
+ $this->assertTrue($validation_result);
+ $this->assertEquals($post_original, $_POST);
+ $this->assertEquals(array('foo' => 'bar', 'bar' => 'baz'), $data_processed);
+
+ $this->form_validation->reset_validation();
+ $_POST = array();
+ }
+
/**
* Run rules
*
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 767b2486d..c25c70e64 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -20,6 +20,7 @@ Release Date: Not Released
- Removed previously deprecated :doc:`Routing Class <general/routing>` methods ``fetch_directory()``, ``fetch_class()`` and ``fetch_method()`` (use the respective class properties instead).
- Removed previously deprecated :doc:`Config Library <libraries/config>` method ``system_url()`` (encourages insecure practices).
- Changed :doc:`URI Library <libraries/uri>` to ignore the ``$config['url_suffix']``, ``$config['permitted_uri_chars']`` configuration settings for CLI requests.
+ - Changed :doc:`Loader <libraries/loader>` method ``model()`` to always check if the loaded class extends ``CI_Model``.
- :doc:`Input Library <libraries/input>` changes include:
@@ -50,6 +51,8 @@ Release Date: Not Released
- Removed previously deprecated method ``prep_for_form()`` / rule *prep_for_form*.
- Changed method ``set_rules()`` to throw a ``BadMethodCallException`` when its first parameter is not an array and the ``$rules`` one is unused.
- Added rule **valid_mac**, which replicates PHP's native ``filter_var()`` with ``FILTER_VALIDATE_MAC``.
+ - Added ability to validate entire arrays at once, if ``is_array`` is within the list of rules.
+ - Added ability to fetch processed data via a second parameter to ``run()``.
- :doc:`HTML Table Library <libraries/table>` changes include:
@@ -58,6 +61,7 @@ Release Date: Not Released
- :doc:`Email Library <libraries/email>` changes include:
- Changed the default value of the **validate** option to ``TRUE``.
+ - Changed the ``send()`` method to always return ``TRUE`` when sending multiple batches of emails.
- :doc:`Database <database/index>` changes include:
@@ -73,6 +77,7 @@ Release Date: Not Released
- :doc:`Query Builder <database/query_builder>`:
- Added methods ``having_in()``, ``or_having_in()``, ``not_having_in()``, ``or_not_having_in()``.
+ - Updated logic to allow dots in alias names.
- Helpers
@@ -107,16 +112,39 @@ Release Date: Not Released
- Removed the second (out of three) parameter from the :php:func:`form_upload()` function (it was never used).
-Version 3.1.5
+Version 3.1.6
=============
Release Date: Not Released
+Version 3.1.5
+=============
+
+Release Date: Jun 19, 2017
+
+- **Security**
+
+ - :doc:`Form Validation Library <libraries/form_validation>` rule ``valid_email`` could be bypassed if ``idn_to_ascii()`` is available.
+
+- General Changes
+
+ - Updated :doc:`Form Helper <helpers/form_helper>` function :php:func:`form_label()` to accept HTML attributes as a string.
+
+Bug fixes for 3.1.5
+-------------------
+
+- Fixed a bug (#5070) - :doc:`Email Library <libraries/email>` didn't properly detect 7-bit encoding.
+- Fixed a bug (#5084) - :doc:`XML-RPC Library <libraries/xmlrpc>` errored because of a variable name typo.
+- Fixed a bug (#5108) - :doc:`Inflector Helper <helpers/inflector_helper>` function :php:func:`singular()` didn't properly handle 'quizzes'.
+- Fixed a regression (#5131) - private controller methods triggered PHP errors instead of a 404 response.
+- Fixed a bug (#5150) - :doc:`Database Forge <database/forge>` method ``modify_column()`` triggered an error while renaming columns with the 'oci8', 'pdo/oci' drivers.
+- Fixed a bug (#5155) - :doc:`Query Builder <database/query_builder>` method ``count_all_results()`` returned incorrect result for queries using ``LIMIT``, ``OFFSET``.
+
Version 3.1.4
=============
-Release Date: March 20, 2017
+Release Date: Mar 20, 2017
- **Security**
diff --git a/user_guide_src/source/database/db_driver_reference.rst b/user_guide_src/source/database/db_driver_reference.rst
index 6f2fa5fb1..c240526e0 100644
--- a/user_guide_src/source/database/db_driver_reference.rst
+++ b/user_guide_src/source/database/db_driver_reference.rst
@@ -305,9 +305,10 @@ This article is intended to be a reference for them.
Gets a list containing field data about a table.
- .. php:method:: escape_identifiers($item)
+ .. php:method:: escape_identifiers($item, $split = TRUE)
:param mixed $item: The item or array of items to escape
+ :param bool $split: Whether to split identifiers when a dot is encountered
:returns: The input item(s), escaped
:rtype: mixed
@@ -428,4 +429,4 @@ This article is intended to be a reference for them.
insert the table prefix (if it exists) in the proper
position, and escape only the correct identifiers.
- This method is used extensively by the Query Builder class. \ No newline at end of file
+ This method is used extensively by the Query Builder class.
diff --git a/user_guide_src/source/general/ancillary_classes.rst b/user_guide_src/source/general/ancillary_classes.rst
index f1285d931..4d6528aae 100644
--- a/user_guide_src/source/general/ancillary_classes.rst
+++ b/user_guide_src/source/general/ancillary_classes.rst
@@ -19,7 +19,7 @@ access CodeIgniter's native resources** simply by using the
``get_instance()`` function. This function returns the main
CodeIgniter object.
-Normally, to call any of the available CodeIgniter methods requires
+Normally, to call any of the available methods, CodeIgniter requires
you to use the ``$this`` construct::
$this->load->helper('url');
diff --git a/user_guide_src/source/helpers/form_helper.rst b/user_guide_src/source/helpers/form_helper.rst
index 97595c90b..43a20e18c 100644
--- a/user_guide_src/source/helpers/form_helper.rst
+++ b/user_guide_src/source/helpers/form_helper.rst
@@ -485,7 +485,7 @@ The following functions are available:
:param string $label_text: Text to put in the <label> tag
:param string $id: ID of the form element that we're making a label for
- :param string $attributes: HTML attributes
+ :param mixed $attributes: HTML attributes
:returns: An HTML field label tag
:rtype: string
diff --git a/user_guide_src/source/installation/downloads.rst b/user_guide_src/source/installation/downloads.rst
index f36857e57..fb9222df9 100644
--- a/user_guide_src/source/installation/downloads.rst
+++ b/user_guide_src/source/installation/downloads.rst
@@ -3,7 +3,8 @@ Downloading CodeIgniter
#######################
- `CodeIgniter v3.2.0-dev (Current version) <https://codeload.github.com/bcit-ci/CodeIgniter/zip/develop>`_
-- `CodeIgniter v3.1.5-dev <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1-stable>`_
+- `CodeIgniter v3.1.6-dev <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1-stable>`_
+- `CodeIgniter v3.1.5 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.5>`_
- `CodeIgniter v3.1.4 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.4>`_
- `CodeIgniter v3.1.3 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.3>`_
- `CodeIgniter v3.1.2 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/3.1.2>`_
diff --git a/user_guide_src/source/installation/upgrade_316.rst b/user_guide_src/source/installation/upgrade_316.rst
new file mode 100644
index 000000000..e382c20ab
--- /dev/null
+++ b/user_guide_src/source/installation/upgrade_316.rst
@@ -0,0 +1,14 @@
+#############################
+Upgrading from 3.1.5 to 3.1.6
+#############################
+
+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.
diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst
index b76392d05..3383796d0 100644
--- a/user_guide_src/source/installation/upgrading.rst
+++ b/user_guide_src/source/installation/upgrading.rst
@@ -9,6 +9,7 @@ upgrading from.
:titlesonly:
Upgrading from 3.1.3+ to 3.2.x <upgrade_320>
+ Upgrading from 3.1.5 to 3.1.6 <upgrade_316>
Upgrading from 3.1.4 to 3.1.5 <upgrade_315>
Upgrading from 3.1.3 to 3.1.4 <upgrade_314>
Upgrading from 3.1.2 to 3.1.3 <upgrade_313>
diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst
index bd416ba3b..81ca00e50 100644
--- a/user_guide_src/source/libraries/email.rst
+++ b/user_guide_src/source/libraries/email.rst
@@ -312,14 +312,18 @@ Class Reference
This method will automatically clear all parameters if the request was
successful. To stop this behaviour pass FALSE::
- if ($this->email->send(FALSE))
- {
- // Parameters won't be cleared
- }
+ if ($this->email->send(FALSE))
+ {
+ // Parameters won't be cleared
+ }
.. note:: In order to use the ``print_debugger()`` method, you need
to avoid clearing the email parameters.
+ .. note:: If ``batch_bcc_mode`` is enabled, and there are more than
+ ``batch_bcc_size`` recipients, this method will always return
+ boolean ``TRUE``.
+
.. php:method:: attach($filename[, $disposition = ''[, $newname = NULL[, $mime = '']]])
:param string $filename: File name
diff --git a/user_guide_src/source/libraries/form_validation.rst b/user_guide_src/source/libraries/form_validation.rst
index 6a92cc983..fd2f3af94 100644
--- a/user_guide_src/source/libraries/form_validation.rst
+++ b/user_guide_src/source/libraries/form_validation.rst
@@ -881,6 +881,24 @@ When a rule group is named identically to a controller class/method it
will be used automatically when the ``run()`` method is invoked from that
class/method.
+Accessing validated/processed data
+==================================
+
+By default, validation will be performed directly on the ``$_POST`` array,
+and any possible modifications (like trimming whitespace, for example)
+would be written back onto it.
+However, if you want to keep the original input data intact, or have used
+``set_data()`` to pass a custom set of inputs, you would likely want to
+fetch the now-modified data. In order to do that, you can pass a variable
+as the second parameter to ``run()``::
+
+ $input = array('name' => ' White Space ');
+ $output = NULL;
+
+ $this->form_validation->set_rules('name', 'Name', 'required|trim');
+ $this->form_validation->run(NULL, $output);
+ // $output will now contain: array('name' => 'White Space');
+
.. _using-arrays-as-field-names:
***************************
@@ -1043,9 +1061,10 @@ Class Reference
- :ref:`setting-validation-rules`
- :ref:`saving-groups`
- .. php:method:: run([$group = ''])
+ .. php:method:: run([$config = NULL[, $data = NULL]])
:param string $group: The name of the validation group to run
+ :param mixed $data: Optional variable to assign validated data to
:returns: TRUE on success, FALSE if validation failed
:rtype: bool
diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst
index fc5cba19d..868112684 100644
--- a/user_guide_src/source/libraries/security.rst
+++ b/user_guide_src/source/libraries/security.rst
@@ -107,7 +107,7 @@ Class Reference
If the optional second parameter is set to true, it will return boolean TRUE if
the image is safe to use and FALSE if malicious data was detected in it.
- .. important:: This method is not suitable for filtering HTML attribute vales!
+ .. important:: This method is not suitable for filtering HTML attribute values!
Use :php:func:`html_escape()` for that instead.
.. php:method:: sanitize_filename($str[, $relative_path = FALSE])