Merge remote-tracking branch 'upstream/develop' into develop
diff --git a/.travis.yml b/.travis.yml
index 4f56044..258ad76 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,7 @@
- 5.4
- 5.5
- 5.6
+ - 7
- hhvm
env:
@@ -31,11 +32,14 @@
allow_failures:
- php: 5.2
- php: hhvm
+ - php: 7
exclude:
- php: hhvm
env: DB=pgsql
- php: hhvm
env: DB=pdo/pgsql
+ - php: 7
+ env: DB=mysql
- php: 5.2
env: DB=sqlite
- php: 5.2
diff --git a/application/cache/index.html b/application/cache/index.html
index c942a79..b702fbc 100644
--- a/application/cache/index.html
+++ b/application/cache/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/config/config.php b/application/config/config.php
index 306fc2c..f78371f 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -37,17 +37,16 @@
|--------------------------------------------------------------------------
|
| This item determines which server global should be used to retrieve the
-| URI string. The default setting of 'AUTO' works for most servers.
+| URI string. The default setting of 'REQUEST_URI' works for most servers.
| If your links do not seem to work, try one of the other delicious flavors:
|
-| 'AUTO' Default - auto detects
-| 'CLI' or 'argv' Uses $_SERVER['argv'] (for php-cli only)
-| 'PATH_INFO' Uses $_SERVER['PATH_INFO']
-| 'REQUEST_URI' Uses $_SERVER['REQUEST_URI']
-| 'QUERY_STRING' Uses $_SERVER['QUERY_STRING']
+| 'REQUEST_URI' Uses $_SERVER['REQUEST_URI']
+| 'QUERY_STRING' Uses $_SERVER['QUERY_STRING']
+| 'PATH_INFO' Uses $_SERVER['PATH_INFO']
|
+| WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded!
*/
-$config['uri_protocol'] = 'AUTO';
+$config['uri_protocol'] = 'REQUEST_URI';
/*
|--------------------------------------------------------------------------
@@ -204,7 +203,7 @@
| 3 = Informational Messages
| 4 = All Messages
|
-| You can also pass in a array with threshold levels to show individual error types
+| You can also pass an array with threshold levels to show individual error types
|
| array(2) = Debug Messages, without Error Messages
|
@@ -331,6 +330,8 @@
| The location to save sessions to, driver dependant.
|
| For the 'files' driver, it's a path to a writable directory.
+| WARNING: Only absolute paths are supported!
+|
| For the 'database' driver, it's a table name.
| Please read up the manual for the format with other session drivers.
|
@@ -405,6 +406,9 @@
| Determines whether the XSS filter is always active when GET, POST or
| COOKIE data is encountered
|
+| WARNING: This feature is DEPRECATED and currently available only
+| for backwards compatibility purposes!
+|
*/
$config['global_xss_filtering'] = FALSE;
diff --git a/application/config/database.php b/application/config/database.php
index 5ee2af4..925b3e5 100644
--- a/application/config/database.php
+++ b/application/config/database.php
@@ -39,7 +39,6 @@
| multi-byte character set and are running versions lower than these.
| Sites using Latin-1 or UTF-8 database character set and collation are unaffected.
| ['swap_pre'] A default table prefix that should be swapped with the dbprefix
-| ['autoinit'] Whether or not to automatically initialize the database.
| ['encrypt'] Whether or not to use an encrypted connection.
| ['compress'] Whether or not to use client compression (MySQL only)
| ['stricton'] TRUE/FALSE - forces 'Strict Mode' connections
@@ -78,7 +77,6 @@
'char_set' => 'utf8',
'dbcollat' => 'utf8_general_ci',
'swap_pre' => '',
- 'autoinit' => TRUE,
'encrypt' => FALSE,
'compress' => FALSE,
'stricton' => FALSE,
diff --git a/application/config/index.html b/application/config/index.html
index c942a79..b702fbc 100644
--- a/application/config/index.html
+++ b/application/config/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/config/user_agents.php b/application/config/user_agents.php
index 68d7853..6f3295a 100644
--- a/application/config/user_agents.php
+++ b/application/config/user_agents.php
@@ -12,6 +12,7 @@
*/
$platforms = array(
+ 'windows nt 10.0' => 'Windows 10',
'windows nt 6.3' => 'Windows 8.1',
'windows nt 6.2' => 'Windows 8',
'windows nt 6.1' => 'Windows 7',
diff --git a/application/controllers/index.html b/application/controllers/index.html
index c942a79..b702fbc 100644
--- a/application/controllers/index.html
+++ b/application/controllers/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/core/index.html b/application/core/index.html
index c942a79..b702fbc 100644
--- a/application/core/index.html
+++ b/application/core/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/helpers/index.html b/application/helpers/index.html
index c942a79..b702fbc 100644
--- a/application/helpers/index.html
+++ b/application/helpers/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/hooks/index.html b/application/hooks/index.html
index c942a79..b702fbc 100644
--- a/application/hooks/index.html
+++ b/application/hooks/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/index.html b/application/index.html
index c942a79..b702fbc 100644
--- a/application/index.html
+++ b/application/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/language/english/index.html b/application/language/english/index.html
index c942a79..b702fbc 100644
--- a/application/language/english/index.html
+++ b/application/language/english/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/language/index.html b/application/language/index.html
index c942a79..b702fbc 100644
--- a/application/language/index.html
+++ b/application/language/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/libraries/index.html b/application/libraries/index.html
index c942a79..b702fbc 100644
--- a/application/libraries/index.html
+++ b/application/libraries/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/logs/index.html b/application/logs/index.html
index c942a79..b702fbc 100644
--- a/application/logs/index.html
+++ b/application/logs/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/models/index.html b/application/models/index.html
index c942a79..b702fbc 100644
--- a/application/models/index.html
+++ b/application/models/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/third_party/index.html b/application/third_party/index.html
index c942a79..b702fbc 100644
--- a/application/third_party/index.html
+++ b/application/third_party/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/views/errors/cli/index.html b/application/views/errors/cli/index.html
index c942a79..b702fbc 100644
--- a/application/views/errors/cli/index.html
+++ b/application/views/errors/cli/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/views/errors/html/index.html b/application/views/errors/html/index.html
index c942a79..b702fbc 100644
--- a/application/views/errors/html/index.html
+++ b/application/views/errors/html/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/views/errors/index.html b/application/views/errors/index.html
index c942a79..b702fbc 100644
--- a/application/views/errors/index.html
+++ b/application/views/errors/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/application/views/index.html b/application/views/index.html
index c942a79..b702fbc 100644
--- a/application/views/index.html
+++ b/application/views/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/readme.rst b/readme.rst
index dd59fd8..640dd24 100644
--- a/readme.rst
+++ b/readme.rst
@@ -54,13 +54,16 @@
*********
- `User Guide <http://www.codeigniter.com/docs>`_
+- `Language File Translations <https://github.com/bcit-ci/codeigniter3-translations>`_
- `Community Forums <http://forum.codeigniter.com/>`_
- `Community Wiki <https://github.com/bcit-ci/CodeIgniter/wiki>`_
- `Community IRC <http://www.codeigniter.com/irc>`_
+Report security issues to our `Security Panel <mailto:security@codeigniter.com>`_, thank you.
+
***************
Acknowledgement
***************
-The EllisLab team and The Reactor Engineers would like to thank all the
+The CodeIgniter team would like to thank EllisLab, all the
contributors to the CodeIgniter project and you, the CodeIgniter user.
\ No newline at end of file
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index d830c18..ddf3227 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -55,7 +55,7 @@
* @var string
*
*/
- define('CI_VERSION', '3.0-dev');
+ define('CI_VERSION', '3.0.1-dev');
/*
* ------------------------------------------------------
diff --git a/system/core/Common.php b/system/core/Common.php
index 9f50974..f28272b 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -492,59 +492,63 @@
*/
function set_status_header($code = 200, $text = '')
{
- $stati = array(
- 200 => 'OK',
- 201 => 'Created',
- 202 => 'Accepted',
- 203 => 'Non-Authoritative Information',
- 204 => 'No Content',
- 205 => 'Reset Content',
- 206 => 'Partial Content',
-
- 300 => 'Multiple Choices',
- 301 => 'Moved Permanently',
- 302 => 'Found',
- 303 => 'See Other',
- 304 => 'Not Modified',
- 305 => 'Use Proxy',
- 307 => 'Temporary Redirect',
-
- 400 => 'Bad Request',
- 401 => 'Unauthorized',
- 403 => 'Forbidden',
- 404 => 'Not Found',
- 405 => 'Method Not Allowed',
- 406 => 'Not Acceptable',
- 407 => 'Proxy Authentication Required',
- 408 => 'Request Timeout',
- 409 => 'Conflict',
- 410 => 'Gone',
- 411 => 'Length Required',
- 412 => 'Precondition Failed',
- 413 => 'Request Entity Too Large',
- 414 => 'Request-URI Too Long',
- 415 => 'Unsupported Media Type',
- 416 => 'Requested Range Not Satisfiable',
- 417 => 'Expectation Failed',
- 422 => 'Unprocessable Entity',
-
- 500 => 'Internal Server Error',
- 501 => 'Not Implemented',
- 502 => 'Bad Gateway',
- 503 => 'Service Unavailable',
- 504 => 'Gateway Timeout',
- 505 => 'HTTP Version Not Supported'
- );
+ if (is_cli())
+ {
+ return;
+ }
if (empty($code) OR ! is_numeric($code))
{
show_error('Status codes must be numeric', 500);
}
- is_int($code) OR $code = (int) $code;
-
if (empty($text))
{
+ is_int($code) OR $code = (int) $code;
+ $stati = array(
+ 200 => 'OK',
+ 201 => 'Created',
+ 202 => 'Accepted',
+ 203 => 'Non-Authoritative Information',
+ 204 => 'No Content',
+ 205 => 'Reset Content',
+ 206 => 'Partial Content',
+
+ 300 => 'Multiple Choices',
+ 301 => 'Moved Permanently',
+ 302 => 'Found',
+ 303 => 'See Other',
+ 304 => 'Not Modified',
+ 305 => 'Use Proxy',
+ 307 => 'Temporary Redirect',
+
+ 400 => 'Bad Request',
+ 401 => 'Unauthorized',
+ 403 => 'Forbidden',
+ 404 => 'Not Found',
+ 405 => 'Method Not Allowed',
+ 406 => 'Not Acceptable',
+ 407 => 'Proxy Authentication Required',
+ 408 => 'Request Timeout',
+ 409 => 'Conflict',
+ 410 => 'Gone',
+ 411 => 'Length Required',
+ 412 => 'Precondition Failed',
+ 413 => 'Request Entity Too Large',
+ 414 => 'Request-URI Too Long',
+ 415 => 'Unsupported Media Type',
+ 416 => 'Requested Range Not Satisfiable',
+ 417 => 'Expectation Failed',
+ 422 => 'Unprocessable Entity',
+
+ 500 => 'Internal Server Error',
+ 501 => 'Not Implemented',
+ 502 => 'Bad Gateway',
+ 503 => 'Service Unavailable',
+ 504 => 'Gateway Timeout',
+ 505 => 'HTTP Version Not Supported'
+ );
+
if (isset($stati[$code]))
{
$text = $stati[$code];
@@ -737,6 +741,11 @@
*/
function html_escape($var, $double_encode = TRUE)
{
+ if (empty($var))
+ {
+ return $var;
+ }
+
if (is_array($var))
{
return array_map('html_escape', $var, array_fill(0, count($var), $double_encode));
diff --git a/system/core/Config.php b/system/core/Config.php
index a191a77..d07000a 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -123,10 +123,9 @@
foreach ($this->_config_paths as $path)
{
- foreach (array($file, ENVIRONMENT.'/'.$file) as $location)
+ foreach (array($file, ENVIRONMENT.DIRECTORY_SEPARATOR.$file) as $location)
{
$file_path = $path.'config/'.$location.'.php';
-
if (in_array($file_path, $this->is_loaded, TRUE))
{
return TRUE;
@@ -165,14 +164,13 @@
$loaded = TRUE;
log_message('debug', 'Config file loaded: '.$file_path);
}
-
- if ($loaded === TRUE)
- {
- return TRUE;
- }
}
- if ($fail_gracefully === TRUE)
+ if ($loaded === TRUE)
+ {
+ return TRUE;
+ }
+ elseif ($fail_gracefully === TRUE)
{
return FALSE;
}
diff --git a/system/core/Hooks.php b/system/core/Hooks.php
index 08479b1..3b4fb22 100644
--- a/system/core/Hooks.php
+++ b/system/core/Hooks.php
@@ -46,7 +46,7 @@
* @subpackage Libraries
* @category Libraries
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/encryption.html
+ * @link http://codeigniter.com/user_guide/general/hooks.html
*/
class CI_Hooks {
diff --git a/system/core/Input.php b/system/core/Input.php
index fae3b6c..12332cf 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -55,7 +55,7 @@
*
* @var string
*/
- public $ip_address = FALSE;
+ protected $ip_address = FALSE;
/**
* Allow GET array flag
@@ -104,14 +104,28 @@
protected $headers = array();
/**
- * Input stream data
+ * Raw input stream data
+ *
+ * Holds a cache of php://input contents
+ *
+ * @var string
+ */
+ protected $_raw_input_stream;
+
+ /**
+ * Parsed input stream data
*
* Parsed from php://input at runtime
*
* @see CI_Input::input_stream()
* @var array
*/
- protected $_input_stream = NULL;
+ protected $_input_stream;
+
+ protected $security;
+ protected $uni;
+
+ // --------------------------------------------------------------------
/**
* Class constructor
@@ -313,7 +327,8 @@
// so we'll need to check if we have already done that first.
if ( ! is_array($this->_input_stream))
{
- parse_str(file_get_contents('php://input'), $this->_input_stream);
+ // $this->raw_input_stream will trigger __get().
+ parse_str($this->raw_input_stream, $this->_input_stream);
is_array($this->_input_stream) OR $this->_input_stream = array();
}
@@ -475,9 +490,9 @@
)
);
- for ($i = 0; $i < 8; $i++)
+ for ($j = 0; $j < 8; $j++)
{
- $ip[$i] = intval($ip[$i], 16);
+ $ip[$j] = intval($ip[$j], 16);
}
$sprintf = '%016b%016b%016b%016b%016b%016b%016b%016b';
@@ -846,4 +861,27 @@
: strtolower($this->server('REQUEST_METHOD'));
}
+ // ------------------------------------------------------------------------
+
+ /**
+ * Magic __get()
+ *
+ * Allows read access to protected properties
+ *
+ * @param string $name
+ * @return mixed
+ */
+ public function __get($name)
+ {
+ if ($name === 'raw_input_stream')
+ {
+ isset($this->_raw_input_stream) OR $this->_raw_input_stream = file_get_contents('php://input');
+ return $this->_raw_input_stream;
+ }
+ elseif ($name === 'ip_address')
+ {
+ return $this->ip_address;
+ }
+ }
+
}
diff --git a/system/core/Loader.php b/system/core/Loader.php
index b2eeb3b..9205ad1 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -1079,17 +1079,26 @@
log_message('debug', $library_name.' class already loaded. Second attempt ignored.');
return;
}
- elseif (file_exists(APPPATH.'libraries/'.$file_path.$library_name.'.php'))
+
+ $paths = $this->_ci_library_paths;
+ array_pop($paths); // BASEPATH
+ array_pop($paths); // APPPATH (needs to be the first path checked)
+ array_unshift($paths, APPPATH);
+
+ foreach ($paths as $path)
{
- // Override
- include_once(APPPATH.'libraries/'.$file_path.$library_name.'.php');
- if (class_exists($prefix.$library_name, FALSE))
+ if (file_exists($path = $path.'libraries/'.$file_path.$library_name.'.php'))
{
- return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
- }
- else
- {
- log_message('debug', APPPATH.'libraries/'.$file_path.$library_name.'.php exists, but does not declare '.$prefix.$library_name);
+ // Override
+ include_once($path);
+ if (class_exists($prefix.$library_name, FALSE))
+ {
+ return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
+ }
+ else
+ {
+ log_message('debug', $path.' exists, but does not declare '.$prefix.$library_name);
+ }
}
}
@@ -1097,16 +1106,20 @@
// Check for extensions
$subclass = config_item('subclass_prefix').$library_name;
- if (file_exists(APPPATH.'libraries/'.$file_path.$subclass.'.php'))
+ foreach ($paths as $path)
{
- include_once(APPPATH.'libraries/'.$file_path.$subclass.'.php');
- if (class_exists($subclass, FALSE))
+ if (file_exists($path = $path.'libraries/'.$file_path.$subclass.'.php'))
{
- $prefix = config_item('subclass_prefix');
- }
- else
- {
- log_message('debug', APPPATH.'libraries/'.$file_path.$subclass.'.php exists, but does not declare '.$subclass);
+ include_once($path);
+ if (class_exists($subclass, FALSE))
+ {
+ $prefix = config_item('subclass_prefix');
+ break;
+ }
+ else
+ {
+ log_message('debug', $path.' exists, but does not declare '.$subclass);
+ }
}
}
@@ -1294,10 +1307,7 @@
}
// Load all other libraries
- foreach ($autoload['libraries'] as $item)
- {
- $this->library($item);
- }
+ $this->library($autoload['libraries']);
}
// Autoload models
diff --git a/system/core/Log.php b/system/core/Log.php
index 8333162..e8cb401 100644
--- a/system/core/Log.php
+++ b/system/core/Log.php
@@ -70,13 +70,6 @@
protected $_threshold = 1;
/**
- * Highest level of logging
- *
- * @var int
- */
- protected $_threshold_max = 0;
-
- /**
* Array of threshold levels to log
*
* @var array
@@ -139,7 +132,7 @@
}
elseif (is_array($config['log_threshold']))
{
- $this->_threshold = $this->_threshold_max;
+ $this->_threshold = 0;
$this->_threshold_array = array_flip($config['log_threshold']);
}
diff --git a/system/core/Security.php b/system/core/Security.php
index 7c18c74..9cef424 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -639,7 +639,7 @@
$str_compare = $str;
// Decode standard entities, avoiding false positives
- if ($c = preg_match_all('/&[a-z]{2,}(?![a-z;])/i', $str, $matches))
+ if (preg_match_all('/&[a-z]{2,}(?![a-z;])/i', $str, $matches))
{
if ( ! isset($_entities))
{
@@ -656,7 +656,7 @@
{
$_entities[':'] = ':';
$_entities['('] = '(';
- $_entities[')'] = '&rpar';
+ $_entities[')'] = ')';
$_entities["\n"] = '&newline;';
$_entities["\t"] = '&tab;';
}
@@ -664,11 +664,11 @@
$replace = array();
$matches = array_unique(array_map('strtolower', $matches[0]));
- for ($i = 0; $i < $c; $i++)
+ foreach ($matches as &$match)
{
- if (($char = array_search($matches[$i].';', $_entities, TRUE)) !== FALSE)
+ if (($char = array_search($match.';', $_entities, TRUE)) !== FALSE)
{
- $replace[$matches[$i]] = $char;
+ $replace[$match] = $char;
}
}
@@ -772,7 +772,7 @@
*/
protected function _remove_evil_attributes($str, $is_image)
{
- $evil_attributes = array('on\w*', 'style', 'xmlns', 'formaction', 'form', 'xlink:href');
+ $evil_attributes = array('on\w*', 'style', 'xmlns', 'formaction', 'form', 'xlink:href', 'FSCommand', 'seekSegmentTime');
if ($is_image === TRUE)
{
@@ -784,30 +784,15 @@
}
do {
- $count = 0;
- $attribs = array();
+ $count = $temp_count = 0;
- // find occurrences of illegal attribute strings with quotes (042 and 047 are octal quotes)
- preg_match_all('/(?<!\w)('.implode('|', $evil_attributes).')\s*=\s*(\042|\047)([^\\2]*?)(\\2)/is', $str, $matches, PREG_SET_ORDER);
-
- foreach ($matches as $attr)
- {
- $attribs[] = preg_quote($attr[0], '/');
- }
+ // replace occurrences of illegal attribute strings with quotes (042 and 047 are octal quotes)
+ $str = preg_replace('/(<[^>]+)(?<!\w)('.implode('|', $evil_attributes).')\s*=\s*(\042|\047)([^\\2]*?)(\\2)/is', '$1[removed]', $str, -1, $temp_count);
+ $count += $temp_count;
// find occurrences of illegal attribute strings without quotes
- preg_match_all('/(?<!\w)('.implode('|', $evil_attributes).')\s*=\s*([^\s>]*)/is', $str, $matches, PREG_SET_ORDER);
-
- foreach ($matches as $attr)
- {
- $attribs[] = preg_quote($attr[0], '/');
- }
-
- // replace illegal attribute strings that are inside an html tag
- if (count($attribs) > 0)
- {
- $str = preg_replace('/(<?)(\/?[^><]+?)([^A-Za-z<>\-])(.*?)('.implode('|', $attribs).')(.*?)([\s><]?)([><]*)/i', '$1$2 $4$6$7$8', $str, -1, $count);
- }
+ $str = preg_replace('/(<[^>]+)(?<!\w)('.implode('|', $evil_attributes).')\s*=\s*([^\s>]*)/is', '$1[removed]', $str, -1, $temp_count);
+ $count += $temp_count;
}
while ($count);
diff --git a/system/core/URI.php b/system/core/URI.php
index 9bc34ac..2211e36 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -107,37 +107,34 @@
$this->_permitted_uri_chars = $this->config->item('permitted_uri_chars');
// If it's a CLI request, ignore the configuration
- if (is_cli() OR ($protocol = strtoupper($this->config->item('uri_protocol'))) === 'CLI')
+ if (is_cli())
{
- $this->_set_uri_string($this->_parse_argv());
- }
- elseif ($protocol === 'AUTO')
- {
- // Is there a PATH_INFO variable? This should be the easiest solution.
- if (isset($_SERVER['PATH_INFO']))
- {
- $this->_set_uri_string($_SERVER['PATH_INFO']);
- }
- // No PATH_INFO? Let's try REQUST_URI or QUERY_STRING then
- elseif (($uri = $this->_parse_request_uri()) !== '' OR ($uri = $this->_parse_query_string()) !== '')
- {
- $this->_set_uri_string($uri);
- }
- // As a last ditch effor, let's try using the $_GET array
- elseif (is_array($_GET) && count($_GET) === 1 && trim(key($_GET), '/') !== '')
- {
- $this->_set_uri_string(key($_GET));
- }
- }
- elseif (method_exists($this, ($method = '_parse_'.strtolower($protocol))))
- {
- $this->_set_uri_string($this->$method());
+ $uri = $this->_parse_argv();
}
else
{
- $uri = isset($_SERVER[$protocol]) ? $_SERVER[$protocol] : @getenv($protocol);
- $this->_set_uri_string($uri);
+ $protocol = $this->config->item('uri_protocol');
+ empty($protocol) && $protocol = 'REQUEST_URI';
+
+ switch ($protocol)
+ {
+ case 'AUTO': // For BC purposes only
+ case 'REQUEST_URI':
+ $uri = $this->_parse_request_uri();
+ break;
+ case 'QUERY_STRING':
+ $uri = $this->_parse_query_string();
+ break;
+ case 'PATH_INFO':
+ default:
+ $uri = isset($_SERVER[$protocol])
+ ? $_SERVER[$protocol]
+ : $this->_parse_request_uri();
+ break;
+ }
}
+
+ $this->_set_uri_string($uri);
}
log_message('info', 'URI Class Initialized');
@@ -206,15 +203,18 @@
$uri = parse_url($_SERVER['REQUEST_URI']);
$query = isset($uri['query']) ? $uri['query'] : '';
- $uri = isset($uri['path']) ? rawurldecode($uri['path']) : '';
+ $uri = isset($uri['path']) ? $uri['path'] : '';
- if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
+ if (isset($_SERVER['SCRIPT_NAME'][0]))
{
- $uri = (string) substr($uri, strlen($_SERVER['SCRIPT_NAME']));
- }
- elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
- {
- $uri = (string) substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
+ if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
+ {
+ $uri = (string) substr($uri, strlen($_SERVER['SCRIPT_NAME']));
+ }
+ elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
+ {
+ $uri = (string) substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
+ }
}
// This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct
@@ -222,7 +222,7 @@
if (trim($uri, '/') === '' && strncmp($query, '/', 1) === 0)
{
$query = explode('?', $query, 2);
- $uri = rawurldecode($query[0]);
+ $uri = $query[0];
$_SERVER['QUERY_STRING'] = isset($query[1]) ? $query[1] : '';
}
else
@@ -262,7 +262,7 @@
{
$uri = explode('?', $uri, 2);
$_SERVER['QUERY_STRING'] = isset($uri[1]) ? $uri[1] : '';
- $uri = rawurldecode($uri[0]);
+ $uri = $uri[0];
}
parse_str($_SERVER['QUERY_STRING'], $_GET);
diff --git a/system/core/compat/hash.php b/system/core/compat/hash.php
index 477535d..1595455 100644
--- a/system/core/compat/hash.php
+++ b/system/core/compat/hash.php
@@ -174,9 +174,56 @@
}
$hash_length = strlen(hash($algo, NULL, TRUE));
- if (empty($length))
+ empty($length) && $length = $hash_length;
+
+ // Pre-hash password inputs longer than the algorithm's block size
+ // (i.e. prepare HMAC key) to mitigate potential DoS attacks.
+ static $block_sizes;
+ empty($block_sizes) && $block_sizes = array(
+ 'gost' => 32,
+ 'haval128,3' => 128,
+ 'haval160,3' => 128,
+ 'haval192,3' => 128,
+ 'haval224,3' => 128,
+ 'haval256,3' => 128,
+ 'haval128,4' => 128,
+ 'haval160,4' => 128,
+ 'haval192,4' => 128,
+ 'haval224,4' => 128,
+ 'haval256,4' => 128,
+ 'haval128,5' => 128,
+ 'haval160,5' => 128,
+ 'haval192,5' => 128,
+ 'haval224,5' => 128,
+ 'haval256,5' => 128,
+ 'md2' => 16,
+ 'md4' => 64,
+ 'md5' => 64,
+ 'ripemd128' => 64,
+ 'ripemd160' => 64,
+ 'ripemd256' => 64,
+ 'ripemd320' => 64,
+ 'salsa10' => 64,
+ 'salsa20' => 64,
+ 'sha1' => 64,
+ 'sha224' => 64,
+ 'sha256' => 64,
+ 'sha384' => 128,
+ 'sha512' => 128,
+ 'snefru' => 32,
+ 'snefru256' => 32,
+ 'tiger128,3' => 64,
+ 'tiger160,3' => 64,
+ 'tiger192,3' => 64,
+ 'tiger128,4' => 64,
+ 'tiger160,4' => 64,
+ 'tiger192,4' => 64,
+ 'whirlpool' => 64
+ );
+
+ if (isset($block_sizes[$algo]) && strlen($password) > $block_sizes[$algo])
{
- $length = $hash_length;
+ $password = hash($algo, $password, TRUE);
}
$hash = '';
diff --git a/system/core/compat/index.html b/system/core/compat/index.html
index c942a79..b702fbc 100644
--- a/system/core/compat/index.html
+++ b/system/core/compat/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/core/compat/mbstring.php b/system/core/compat/mbstring.php
index ddb2bae..e335c85 100644
--- a/system/core/compat/mbstring.php
+++ b/system/core/compat/mbstring.php
@@ -92,7 +92,7 @@
* WARNING: This function WILL fall-back to strpos()
* if iconv is not available!
*
- * @link http://php.net/mb_strpos()
+ * @link http://php.net/mb_strpos
* @param string $haystack
* @param string $needle
* @param int $offset
diff --git a/system/core/index.html b/system/core/index.html
index c942a79..b702fbc 100644
--- a/system/core/index.html
+++ b/system/core/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/DB.php b/system/database/DB.php
index 8ea7ca6..0c7cf54 100644
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -213,10 +213,6 @@
}
}
- if ($DB->autoinit === TRUE)
- {
- $DB->initialize();
- }
-
+ $DB->initialize();
return $DB;
}
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index bbe65b4..3d35c2d 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -124,15 +124,6 @@
public $dbcollat = 'utf8_general_ci';
/**
- * Auto-init flag
- *
- * Whether to automatically initialize the DB connection.
- *
- * @var bool
- */
- public $autoinit = TRUE;
-
- /**
* Encryption flag/data
*
* @var mixed
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index 79cbfb3..a77ed57 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -925,6 +925,9 @@
? $this->_group_get_type('') : $this->_group_get_type($type);
$v = $this->escape_like_str($v);
+
+ // lowercase $side for in case of UPPERCASE string
+ $side = strtolower($side);
if ($side === 'none')
{
@@ -1353,9 +1356,10 @@
* returned by an Query Builder query.
*
* @param string
+ * @param bool the reset clause
* @return int
*/
- public function count_all_results($table = '')
+ public function count_all_results($table = '', $reset = TRUE)
{
if ($table !== '')
{
@@ -1366,7 +1370,11 @@
$result = ($this->qb_distinct === TRUE)
? $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')));
- $this->_reset_select();
+
+ if ($reset === TRUE)
+ {
+ $this->_reset_select();
+ }
if ($result->num_rows() === 0)
{
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
index 4021179..f80b4db 100644
--- a/system/database/drivers/cubrid/cubrid_driver.php
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -163,10 +163,6 @@
{
return $this->data_cache['version'];
}
- elseif ( ! $this->conn_id)
- {
- $this->initialize();
- }
return ( ! $this->conn_id OR ($version = cubrid_get_server_info($this->conn_id)) === FALSE)
? FALSE
diff --git a/system/database/drivers/cubrid/index.html b/system/database/drivers/cubrid/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/cubrid/index.html
+++ b/system/database/drivers/cubrid/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/ibase/index.html b/system/database/drivers/ibase/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/ibase/index.html
+++ b/system/database/drivers/ibase/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/index.html b/system/database/drivers/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/index.html
+++ b/system/database/drivers/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/mssql/index.html b/system/database/drivers/mssql/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/mssql/index.html
+++ b/system/database/drivers/mssql/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/mysql/index.html b/system/database/drivers/mysql/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/mysql/index.html
+++ b/system/database/drivers/mysql/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index f8e9b6d..df0f249 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -223,10 +223,6 @@
{
return $this->data_cache['version'];
}
- elseif ( ! $this->conn_id)
- {
- $this->initialize();
- }
if ( ! $this->conn_id OR ($version = mysql_get_server_info($this->conn_id)) === FALSE)
{
diff --git a/system/database/drivers/mysqli/index.html b/system/database/drivers/mysqli/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/mysqli/index.html
+++ b/system/database/drivers/mysqli/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index 22a8ba6..e953db0 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -204,10 +204,6 @@
{
return $this->data_cache['version'];
}
- elseif ( ! $this->conn_id)
- {
- $this->initialize();
- }
return $this->data_cache['version'] = $this->conn_id->server_info;
}
diff --git a/system/database/drivers/oci8/index.html b/system/database/drivers/oci8/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/oci8/index.html
+++ b/system/database/drivers/oci8/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index b87b411..4010995 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -243,10 +243,6 @@
{
return $this->data_cache['version'];
}
- elseif ( ! $this->conn_id)
- {
- $this->initialize();
- }
if ( ! $this->conn_id OR ($version = oci_server_version($this->conn_id)) === FALSE)
{
diff --git a/system/database/drivers/odbc/index.html b/system/database/drivers/odbc/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/odbc/index.html
+++ b/system/database/drivers/odbc/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/pdo/index.html b/system/database/drivers/pdo/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/pdo/index.html
+++ b/system/database/drivers/pdo/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index 68aeb0e..cc77e95 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -156,10 +156,6 @@
{
return $this->data_cache['version'];
}
- elseif ( ! $this->conn_id)
- {
- $this->initialize();
- }
// Not all subdrivers support the getAttribute() method
try
diff --git a/system/database/drivers/pdo/subdrivers/index.html b/system/database/drivers/pdo/subdrivers/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/pdo/subdrivers/index.html
+++ b/system/database/drivers/pdo/subdrivers/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/postgre/index.html b/system/database/drivers/postgre/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/postgre/index.html
+++ b/system/database/drivers/postgre/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 3f3e3f0..7be07c3 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -213,10 +213,6 @@
{
return $this->data_cache['version'];
}
- elseif ( ! $this->conn_id)
- {
- $this->initialize();
- }
if ( ! $this->conn_id OR ($pg_version = pg_version($this->conn_id)) === FALSE)
{
diff --git a/system/database/drivers/sqlite/index.html b/system/database/drivers/sqlite/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/sqlite/index.html
+++ b/system/database/drivers/sqlite/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/sqlite3/index.html b/system/database/drivers/sqlite3/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/sqlite3/index.html
+++ b/system/database/drivers/sqlite3/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/sqlsrv/index.html b/system/database/drivers/sqlsrv/index.html
index c942a79..b702fbc 100644
--- a/system/database/drivers/sqlsrv/index.html
+++ b/system/database/drivers/sqlsrv/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index 8f17c8f..16f77fa 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -292,10 +292,6 @@
{
return $this->data_cache['version'];
}
- elseif ( ! $this->conn_id)
- {
- $this->initialize();
- }
if ( ! $this->conn_id OR ($info = sqlsrv_server_info($this->conn_id)) === FALSE)
{
diff --git a/system/database/index.html b/system/database/index.html
index c942a79..b702fbc 100644
--- a/system/database/index.html
+++ b/system/database/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/fonts/index.html b/system/fonts/index.html
index c942a79..b702fbc 100644
--- a/system/fonts/index.html
+++ b/system/fonts/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/helpers/index.html b/system/helpers/index.html
index c942a79..b702fbc 100644
--- a/system/helpers/index.html
+++ b/system/helpers/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/index.html b/system/index.html
index c942a79..b702fbc 100644
--- a/system/index.html
+++ b/system/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/language/english/index.html b/system/language/english/index.html
index c942a79..b702fbc 100644
--- a/system/language/english/index.html
+++ b/system/language/english/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/language/index.html b/system/language/index.html
index c942a79..b702fbc 100644
--- a/system/language/index.html
+++ b/system/language/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php
index f2a41cc..a35fbf6 100644
--- a/system/libraries/Cache/drivers/Cache_redis.php
+++ b/system/libraries/Cache/drivers/Cache_redis.php
@@ -111,7 +111,7 @@
{
if (is_array($data) OR is_object($data))
{
- if ( ! $this->_redis->sAdd('_ci_redis_serialized', $id))
+ if ( ! $this->_redis->sIsMember('_ci_redis_serialized', $id) && ! $this->_redis->sAdd('_ci_redis_serialized', $id))
{
return FALSE;
}
@@ -243,15 +243,13 @@
*/
public function is_supported()
{
- if (extension_loaded('redis'))
- {
- return $this->_setup_redis();
- }
- else
+ if ( ! extension_loaded('redis'))
{
log_message('debug', 'The Redis extension must be loaded to use Redis cache.');
return FALSE;
}
+
+ return $this->_setup_redis();
}
// ------------------------------------------------------------------------
diff --git a/system/libraries/Cache/drivers/Cache_wincache.php b/system/libraries/Cache/drivers/Cache_wincache.php
index 528b2b9..9cc6ff0 100644
--- a/system/libraries/Cache/drivers/Cache_wincache.php
+++ b/system/libraries/Cache/drivers/Cache_wincache.php
@@ -194,7 +194,7 @@
*/
public function is_supported()
{
- if ( ! extension_loaded('wincache'))
+ if ( ! extension_loaded('wincache') OR ! ini_get('wincache.ucenabled'))
{
log_message('debug', 'The Wincache PHP extension must be loaded to use Wincache Cache.');
return FALSE;
diff --git a/system/libraries/Cache/drivers/index.html b/system/libraries/Cache/drivers/index.html
index c942a79..b702fbc 100644
--- a/system/libraries/Cache/drivers/index.html
+++ b/system/libraries/Cache/drivers/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/libraries/Cache/index.html b/system/libraries/Cache/index.html
index c942a79..b702fbc 100644
--- a/system/libraries/Cache/index.html
+++ b/system/libraries/Cache/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/libraries/Calendar.php b/system/libraries/Calendar.php
index 014daac..f6a0c39 100644
--- a/system/libraries/Calendar.php
+++ b/system/libraries/Calendar.php
@@ -130,11 +130,7 @@
public function __construct($config = array())
{
$this->CI =& get_instance();
-
- if ( ! in_array('calendar_lang.php', $this->CI->lang->is_loaded, TRUE))
- {
- $this->CI->lang->load('calendar');
- }
+ $this->CI->lang->load('calendar');
empty($config) OR $this->initialize($config);
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index 45c5c09..66b5803 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -405,7 +405,7 @@
* @param array $config = array()
* @return void
*/
- public function __construct($config = array())
+ public function __construct(array $config = array())
{
$this->charset = config_item('charset');
diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php
index e3e6813..f3e0398 100644
--- a/system/libraries/Encryption.php
+++ b/system/libraries/Encryption.php
@@ -121,7 +121,7 @@
);
/**
- * List of supported HMAC algorightms
+ * List of supported HMAC algorithms
*
* name => digest size pairs
*
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index f161b40..05de596 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -831,7 +831,7 @@
// DEPRECATED support for non-prefixed keys
&& FALSE === ($line = $this->CI->lang->line($rule, FALSE)))
{
- $line = $this->CI->lang->line('form_validation_error_message_not_set');
+ $line = $this->CI->lang->line('form_validation_error_message_not_set').'('.$rule.')';
}
}
else
@@ -1151,9 +1151,7 @@
return FALSE;
}
- return (MB_ENABLED === TRUE)
- ? ($val <= mb_strlen($str))
- : ($val <= strlen($str));
+ return ($val <= mb_strlen($str));
}
// --------------------------------------------------------------------
@@ -1172,9 +1170,7 @@
return FALSE;
}
- return (MB_ENABLED === TRUE)
- ? ($val >= mb_strlen($str))
- : ($val >= strlen($str));
+ return ($val >= mb_strlen($str));
}
// --------------------------------------------------------------------
@@ -1193,9 +1189,7 @@
return FALSE;
}
- return (MB_ENABLED === TRUE)
- ? (mb_strlen($str) === (int) $val)
- : (strlen($str) === (int) $val);
+ return (mb_strlen($str) === (int) $val);
}
// --------------------------------------------------------------------
diff --git a/system/libraries/Javascript/index.html b/system/libraries/Javascript/index.html
index c942a79..b702fbc 100644
--- a/system/libraries/Javascript/index.html
+++ b/system/libraries/Javascript/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
index de9b1e8..0549fef 100644
--- a/system/libraries/Session/Session.php
+++ b/system/libraries/Session/Session.php
@@ -94,10 +94,7 @@
$this->_driver = 'database';
}
- if (($class = $this->_ci_load_classes($this->_driver)) === FALSE)
- {
- return;
- }
+ $class = $this->_ci_load_classes($this->_driver);
// Configuration ...
$this->_configure($params);
@@ -230,8 +227,7 @@
if ( ! class_exists('CI_'.$class, FALSE) && ! class_exists($class, FALSE))
{
- log_message('error', "Session: Configured driver '".$driver."' was not found. Aborting.");
- return FALSE;
+ throw new UnexpectedValueException("Session: Configured driver '".$driver."' was not found. Aborting.");
}
}
@@ -314,7 +310,7 @@
$this->_config = $params;
// Security is king
- ini_set('session.use_trans_id', 0);
+ ini_set('session.use_trans_sid', 0);
ini_set('session.use_strict_mode', 1);
ini_set('session.use_cookies', 1);
ini_set('session.use_only_cookies', 1);
@@ -873,7 +869,7 @@
public function set_tempdata($data, $value = NULL, $ttl = 300)
{
$this->set_userdata($data, $value);
- $this->mark_as_temp($data, $ttl);
+ $this->mark_as_temp(is_array($data) ? array_keys($data) : $data, $ttl);
}
// ------------------------------------------------------------------------
diff --git a/system/libraries/Session/drivers/Session_database_driver.php b/system/libraries/Session/drivers/Session_database_driver.php
index 20cec00..1d01c29 100644
--- a/system/libraries/Session/drivers/Session_database_driver.php
+++ b/system/libraries/Session/drivers/Session_database_driver.php
@@ -93,6 +93,10 @@
{
throw new Exception('Configured database connection is persistent. Aborting.');
}
+ elseif ($this->_db->cache_on)
+ {
+ throw new Exception('Configured database connection has cache enabled. Aborting.');
+ }
$db_driver = $this->_db->dbdriver.(empty($this->_db->subdriver) ? '' : '_'.$this->_db->subdriver);
if (strpos($db_driver, 'mysql') !== FALSE)
@@ -122,7 +126,7 @@
public function open($save_path, $name)
{
return empty($this->_db->conn_id)
- ? ( ! $this->_db->autoinit && $this->_db->db_connect())
+ ? (bool) $this->_db->db_connect()
: TRUE;
}
@@ -319,7 +323,7 @@
if ($this->_platform === 'mysql')
{
$arg = $session_id.($this->_config['match_ip'] ? '_'.$_SERVER['REMOTE_ADDR'] : '');
- if ($this->_db->query("SELECT GET_LOCK('".$arg."', 10) AS ci_session_lock")->row()->ci_session_lock)
+ if ($this->_db->query("SELECT GET_LOCK('".$arg."', 300) AS ci_session_lock")->row()->ci_session_lock)
{
$this->_lock = $arg;
return TRUE;
diff --git a/system/libraries/Session/drivers/Session_files_driver.php b/system/libraries/Session/drivers/Session_files_driver.php
index 5852277..45da91c 100644
--- a/system/libraries/Session/drivers/Session_files_driver.php
+++ b/system/libraries/Session/drivers/Session_files_driver.php
@@ -299,7 +299,9 @@
{
if ($this->close())
{
- return unlink($this->_file_path.$session_id) && $this->_cookie_destroy();
+ return file_exists($this->_file_path.$session_id)
+ ? (unlink($this->_file_path.$session_id) && $this->_cookie_destroy())
+ : TRUE;
}
elseif ($this->_file_path !== NULL)
{
@@ -324,7 +326,7 @@
*/
public function gc($maxlifetime)
{
- if ( ! is_dir($this->_config['save_path']) OR ($files = scandir($this->_config['save_path'])) === FALSE)
+ if ( ! is_dir($this->_config['save_path']) OR ($directory = opendir($this->_config['save_path'])) === FALSE)
{
log_message('debug', "Session: Garbage collector couldn't list files under directory '".$this->_config['save_path']."'.");
return FALSE;
@@ -338,7 +340,7 @@
($this->_config['match_ip'] === TRUE ? 72 : 40)
);
- foreach ($files as $file)
+ while (($file = readdir($directory)) !== FALSE)
{
// If the filename doesn't match this pattern, it's either not a session file or is not ours
if ( ! preg_match($pattern, $file)
@@ -352,6 +354,8 @@
unlink($this->_config['save_path'].DIRECTORY_SEPARATOR.$file);
}
+ closedir($directory);
+
return TRUE;
}
diff --git a/system/libraries/Session/drivers/Session_memcached_driver.php b/system/libraries/Session/drivers/Session_memcached_driver.php
index 600b8ca..c7185ee 100644
--- a/system/libraries/Session/drivers/Session_memcached_driver.php
+++ b/system/libraries/Session/drivers/Session_memcached_driver.php
@@ -204,7 +204,7 @@
if (isset($this->_lock_key))
{
- $this->_memcached->replace($this->_lock_key, time(), 5);
+ $this->_memcached->replace($this->_lock_key, time(), 300);
if ($this->_fingerprint !== ($fingerprint = md5($session_data)))
{
if ($this->_memcached->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration']))
@@ -299,34 +299,21 @@
{
if (isset($this->_lock_key))
{
- return $this->_memcached->replace($this->_lock_key, time(), 5);
+ return $this->_memcached->replace($this->_lock_key, time(), 300);
}
+ // 30 attempts to obtain a lock, in case another request already has it
$lock_key = $this->_key_prefix.$session_id.':lock';
- if ( ! ($ts = $this->_memcached->get($lock_key)))
- {
- if ( ! $this->_memcached->set($lock_key, TRUE, 5))
- {
- log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);
- return FALSE;
- }
-
- $this->_lock_key = $lock_key;
- $this->_lock = TRUE;
- return TRUE;
- }
-
- // Another process has the lock, we'll try to wait for it to free itself ...
$attempt = 0;
- while ($attempt++ < 5)
+ do
{
- usleep(((time() - $ts) * 1000000) - 20000);
- if (($ts = $this->_memcached->get($lock_key)) < time())
+ if ($this->_memcached->get($lock_key))
{
+ sleep(1);
continue;
}
- if ( ! $this->_memcached->set($lock_key, time(), 5))
+ if ( ! $this->_memcached->set($lock_key, time(), 300))
{
log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);
return FALSE;
@@ -335,10 +322,11 @@
$this->_lock_key = $lock_key;
break;
}
+ while ($attempt++ < 30);
- if ($attempt === 5)
+ if ($attempt === 30)
{
- log_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 5 attempts, aborting.');
+ log_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 30 attempts, aborting.');
return FALSE;
}
@@ -361,7 +349,7 @@
{
if ( ! $this->_memcached->delete($this->_lock_key) && $this->_memcached->getResultCode() !== Memcached::RES_NOTFOUND)
{
- log_message('error', 'Session: Error while trying to free lock for '.$this->_key_prefix.$session_id);
+ log_message('error', 'Session: Error while trying to free lock for '.$this->_lock_key);
return FALSE;
}
diff --git a/system/libraries/Session/drivers/Session_redis_driver.php b/system/libraries/Session/drivers/Session_redis_driver.php
index c3c75b3..1ce101d 100644
--- a/system/libraries/Session/drivers/Session_redis_driver.php
+++ b/system/libraries/Session/drivers/Session_redis_driver.php
@@ -205,7 +205,7 @@
if (isset($this->_lock_key))
{
- $this->_redis->setTimeout($this->_lock_key, 5);
+ $this->_redis->setTimeout($this->_lock_key, 300);
if ($this->_fingerprint !== ($fingerprint = md5($session_data)))
{
if ($this->_redis->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration']))
@@ -272,7 +272,7 @@
{
if (isset($this->_redis, $this->_lock_key))
{
- if ($this->_redis->delete($this->_key_prefix.$session_id) !== 1)
+ if (($result = $this->_redis->delete($this->_key_prefix.$session_id)) !== 1)
{
log_message('debug', 'Session: Redis::delete() expected to return 1, got '.var_export($result, TRUE).' instead.');
}
@@ -313,40 +313,21 @@
{
if (isset($this->_lock_key))
{
- return $this->_redis->setTimeout($this->_lock_key, 5);
+ return $this->_redis->setTimeout($this->_lock_key, 300);
}
+ // 30 attempts to obtain a lock, in case another request already has it
$lock_key = $this->_key_prefix.$session_id.':lock';
- if (($ttl = $this->_redis->ttl($lock_key)) < 1)
- {
- if ( ! $this->_redis->setex($lock_key, 5, time()))
- {
- log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);
- return FALSE;
- }
-
- $this->_lock_key = $lock_key;
-
- if ($ttl === -1)
- {
- log_message('debug', 'Session: Lock for '.$this->_key_prefix.$session_id.' had no TTL, overriding.');
- }
-
- $this->_lock = TRUE;
- return TRUE;
- }
-
- // Another process has the lock, we'll try to wait for it to free itself ...
$attempt = 0;
- while ($attempt++ < 5)
+ do
{
- usleep(($ttl * 1000000) - 20000);
if (($ttl = $this->_redis->ttl($lock_key)) > 0)
{
+ sleep(1);
continue;
}
- if ( ! $this->_redis->setex($lock_key, 5, time()))
+ if ( ! $this->_redis->setex($lock_key, 300, time()))
{
log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);
return FALSE;
@@ -355,12 +336,17 @@
$this->_lock_key = $lock_key;
break;
}
+ while ($attempt++ < 30);
- if ($attempt === 5)
+ if ($attempt === 30)
{
- log_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 5 attempts, aborting.');
+ log_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 30 attempts, aborting.');
return FALSE;
}
+ elseif ($ttl === -1)
+ {
+ log_message('debug', 'Session: Lock for '.$this->_key_prefix.$session_id.' had no TTL, overriding.');
+ }
$this->_lock = TRUE;
return TRUE;
@@ -381,7 +367,7 @@
{
if ( ! $this->_redis->delete($this->_lock_key))
{
- log_message('error', 'Session: Error while trying to free lock for '.$this->_key_prefix.$session_id);
+ log_message('error', 'Session: Error while trying to free lock for '.$this->_lock_key);
return FALSE;
}
diff --git a/system/libraries/Session/drivers/index.html b/system/libraries/Session/drivers/index.html
index c942a79..b702fbc 100644
--- a/system/libraries/Session/drivers/index.html
+++ b/system/libraries/Session/drivers/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/libraries/Session/index.html b/system/libraries/Session/index.html
index c942a79..b702fbc 100644
--- a/system/libraries/Session/index.html
+++ b/system/libraries/Session/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php
index af70413..00d1fec 100644
--- a/system/libraries/Xmlrpcs.php
+++ b/system/libraries/Xmlrpcs.php
@@ -223,7 +223,7 @@
$CI =& get_instance();
if ($CI->input->method() === 'post')
{
- $data = http_build_query($CI->input->input_stream(NULL, FALSE));
+ $data = $CI->input->raw_input_stream;
}
}
@@ -233,14 +233,15 @@
$parser = xml_parser_create($this->xmlrpc_defencoding);
$parser_object = new XML_RPC_Message('filler');
+ $pname = (string) $parser;
- $parser_object->xh[$parser] = array(
- 'isf' => 0,
- 'isf_reason' => '',
- 'params' => array(),
- 'stack' => array(),
- 'valuestack' => array(),
- 'method' => ''
+ $parser_object->xh[$pname] = array(
+ 'isf' => 0,
+ 'isf_reason' => '',
+ 'params' => array(),
+ 'stack' => array(),
+ 'valuestack' => array(),
+ 'method' => ''
);
xml_set_object($parser, $parser_object);
@@ -263,7 +264,7 @@
xml_get_current_line_number($parser)));
xml_parser_free($parser);
}
- elseif ($parser_object->xh[$parser]['isf'])
+ elseif ($parser_object->xh[$pname]['isf'])
{
return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
}
@@ -271,17 +272,17 @@
{
xml_parser_free($parser);
- $m = new XML_RPC_Message($parser_object->xh[$parser]['method']);
+ $m = new XML_RPC_Message($parser_object->xh[$pname]['method']);
$plist = '';
- for ($i = 0, $c = count($parser_object->xh[$parser]['params']); $i < $c; $i++)
+ for ($i = 0, $c = count($parser_object->xh[$pname]['params']); $i < $c; $i++)
{
if ($this->debug === TRUE)
{
- $plist .= $i.' - '.print_r(get_object_vars($parser_object->xh[$parser]['params'][$i]), TRUE).";\n";
+ $plist .= $i.' - '.print_r(get_object_vars($parser_object->xh[$pname]['params'][$i]), TRUE).";\n";
}
- $m->addParam($parser_object->xh[$parser]['params'][$i]);
+ $m->addParam($parser_object->xh[$pname]['params'][$i]);
}
if ($this->debug === TRUE)
diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php
index f2f1714..3e98ac5 100644
--- a/system/libraries/Zip.php
+++ b/system/libraries/Zip.php
@@ -352,7 +352,7 @@
// Set the original directory root for child dir's to use as relative
if ($root_path === NULL)
{
- $root_path = dirname($path).DIRECTORY_SEPARATOR;
+ $root_path = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, dirname($path)).DIRECTORY_SEPARATOR;
}
while (FALSE !== ($file = readdir($fp)))
diff --git a/system/libraries/index.html b/system/libraries/index.html
index c942a79..b702fbc 100644
--- a/system/libraries/index.html
+++ b/system/libraries/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/tests/codeigniter/core/Input_test.php b/tests/codeigniter/core/Input_test.php
index 21ff6d8..c56900d 100644
--- a/tests/codeigniter/core/Input_test.php
+++ b/tests/codeigniter/core/Input_test.php
@@ -134,6 +134,14 @@
$this->assertEquals('bar', $foo);
$this->assertEquals("Hello, i try to <script>alert('Hack');</script> your site", $harm);
$this->assertEquals("Hello, i try to [removed]alert('Hack');[removed] your site", $harmless);
+
+ $_SERVER['REQUEST_METHOD'] = 'POST';
+ $_POST['foo']['bar'] = 'baz';
+ $barArray = array('bar' => 'baz');
+
+ $this->assertEquals('baz', $this->input->post('foo[bar]'));
+ $this->assertEquals($barArray, $this->input->post('foo[]'));
+ $this->assertNull($this->input->post('foo[baz]'));
}
// --------------------------------------------------------------------
@@ -198,9 +206,22 @@
$this->markTestSkipped('TODO: Find a way to test HTTP headers');
}
+ // --------------------------------------------------------------------
+
+ public function test_get_request_header()
+ {
+ $this->markTestSkipped('TODO: Find a way to test HTTP headers');
+ }
+
+ // --------------------------------------------------------------------
+
public function test_ip_address()
{
+ $this->input->ip_address = '127.0.0.1';
+ $this->assertEquals('127.0.0.1', $this->input->ip_address());
+
// 127.0.0.1 is set in our Bootstrap file
+ $this->input->ip_address = FALSE;
$this->assertEquals('127.0.0.1', $this->input->ip_address());
// Invalid
@@ -208,10 +229,47 @@
$this->input->ip_address = FALSE; // reset cached value
$this->assertEquals('0.0.0.0', $this->input->ip_address());
- // TODO: Add proxy_ips tests
+ $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
- // Back to reality
+ // Proxy_ips tests
+ $this->input->ip_address = FALSE;
+ $this->ci_set_config('proxy_ips', '127.0.0.3, 127.0.0.4, 127.0.0.2');
+ $_SERVER['HTTP_CLIENT_IP'] = '127.0.0.2';
+ $this->assertEquals('127.0.0.1', $this->input->ip_address());
+
+ // Invalid spoof
+ $this->input->ip_address = FALSE;
+ $this->ci_set_config('proxy_ips', 'invalid_ip_address');
+ $_SERVER['HTTP_CLIENT_IP'] = 'invalid_ip_address';
+ $this->assertEquals('127.0.0.1', $this->input->ip_address());
+
+ $this->input->ip_address = FALSE;
+ $this->ci_set_config('proxy_ips', 'http://foo/bar/baz, 127.0.0.1/1');
+ $_SERVER['HTTP_CLIENT_IP'] = '127.0.0.1';
+ $this->assertEquals('127.0.0.1', $this->input->ip_address());
+
+ $this->input->ip_address = FALSE;
+ $this->ci_set_config('proxy_ips', 'http://foo/bar/baz, 127.0.0.2');
+ $_SERVER['HTTP_CLIENT_IP'] = '127.0.0.2';
+ $_SERVER['REMOTE_ADDR'] = '127.0.0.2';
+ $this->assertEquals('127.0.0.2', $this->input->ip_address());
+
+ //IPv6
+ $this->input->ip_address = FALSE;
+ $this->ci_set_config('proxy_ips', 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329/1, FE80:0000:0000:0000:0202:B3FF:FE1E:8300/2');
+ $_SERVER['HTTP_CLIENT_IP'] = 'FE80:0000:0000:0000:0202:B3FF:FE1E:8300';
+ $_SERVER['REMOTE_ADDR'] = 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329';
+ $this->assertEquals('FE80:0000:0000:0000:0202:B3FF:FE1E:8300', $this->input->ip_address());
+
+ $this->input->ip_address = FALSE;
$_SERVER['REMOTE_ADDR'] = '127.0.0.1'; // back to reality
}
-}
\ No newline at end of file
+ // --------------------------------------------------------------------
+
+ public function test_user_agent()
+ {
+ $_SERVER['HTTP_USER_AGENT'] = 'test';
+ $this->assertEquals('test', $this->input->user_agent());
+ }
+}
diff --git a/tests/codeigniter/core/Lang_test.php b/tests/codeigniter/core/Lang_test.php
index 87a71c8..d2dd759 100644
--- a/tests/codeigniter/core/Lang_test.php
+++ b/tests/codeigniter/core/Lang_test.php
@@ -32,7 +32,7 @@
// A language other than english
$this->ci_vfs_clone('system/language/english/email_lang.php', 'system/language/german/');
$this->assertTrue($this->lang->load('email', 'german'));
- $this->assertEquals('german', $this->lang->is_loaded['email_lang.php'] );
+ $this->assertEquals('german', $this->lang->is_loaded['email_lang.php']);
// Non-alpha idiom (should act the same as unspecified language)
$this->ci_vfs_clone('system/language/english/number_lang.php');
@@ -49,6 +49,32 @@
// --------------------------------------------------------------------
+ public function test_multiple_file_load()
+ {
+ // Multiple files
+ $this->ci_vfs_clone('system/language/english/profiler_lang.php');
+ $files = array(
+ 0 => 'profiler',
+ 1 => 'nonexistent'
+ );
+ $this->setExpectedException(
+ 'RuntimeException',
+ 'CI Error: Unable to load the requested language file: language/english/nonexistent_lang.php'
+ );
+ $this->lang->load($files, 'english');
+ }
+
+ // --------------------------------------------------------------------
+
+ public function test_alternative_path_load()
+ {
+ // Alternative Path
+ $this->ci_vfs_clone('system/language/english/profiler_lang.php');
+ $this->assertTrue($this->lang->load('profiler', 'english', FALSE, TRUE, 'vfs://system/'));
+ }
+
+ // --------------------------------------------------------------------
+
/**
* @depends test_load
*/
@@ -60,5 +86,4 @@
$this->assertFalse($this->lang->line('nonexistent_string'));
$this->assertFalse($this->lang->line(NULL));
}
-
}
diff --git a/tests/codeigniter/core/Loader_test.php b/tests/codeigniter/core/Loader_test.php
index 9e2092e..cfaf6c7 100644
--- a/tests/codeigniter/core/Loader_test.php
+++ b/tests/codeigniter/core/Loader_test.php
@@ -22,6 +22,9 @@
public function test_library()
{
+ // Test getting CI_Loader object
+ $this->assertInstanceOf('CI_Loader', $this->load->library(NULL));
+
// Create library in VFS
$lib = 'unit_test_lib';
$class = 'CI_'.ucfirst($lib);
@@ -35,6 +38,13 @@
$this->assertTrue(class_exists($class), $class.' does not exist');
$this->assertAttributeInstanceOf($class, $lib, $this->ci_obj);
+ // Create library in VFS
+ $lib = array('unit_test_lib' => 'unit_test_lib');
+
+ // Test loading as an array (int).
+ $this->assertInstanceOf('CI_Loader', $this->load->library($lib));
+ $this->assertTrue(class_exists($class), $class.' does not exist');
+
// Test a string given to params
$this->assertInstanceOf('CI_Loader', $this->load->library($lib, ' '));
@@ -319,6 +329,24 @@
// --------------------------------------------------------------------
+ public function test_clear_vars()
+ {
+ $key1 = 'foo';
+ $val1 = 'bar';
+ $key2 = 'boo';
+ $val2 = 'hoo';
+ $this->assertInstanceOf('CI_Loader', $this->load->vars(array($key1 => $val1)));
+ $this->assertInstanceOf('CI_Loader', $this->load->vars($key2, $val2));
+ $this->assertEquals($val1, $this->load->get_var($key1));
+ $this->assertEquals(array($key1 => $val1, $key2 => $val2), $this->load->get_vars());
+
+ $this->assertInstanceOf('CI_Loader', $this->load->clear_vars());
+ $this->assertEquals('', $this->load->get_var($key1));
+ $this->assertEquals('', $this->load->get_var($key2));
+ }
+
+ // --------------------------------------------------------------------
+
public function test_helper()
{
// Create helper in VFS
@@ -443,6 +471,24 @@
// --------------------------------------------------------------------
+ public function test_remove_package_path()
+ {
+ $dir = 'third-party';
+ $path = APPPATH.$dir.'/';
+ $path2 = APPPATH.'another/';
+ $paths = $this->load->get_package_paths(TRUE);
+
+ $this->assertInstanceOf('CI_Loader', $this->load->add_package_path($path));
+ $this->assertInstanceOf('CI_Loader', $this->load->remove_package_path($path));
+ $this->assertEquals($paths, $this->load->get_package_paths(TRUE));
+
+ $this->assertInstanceOf('CI_Loader', $this->load->add_package_path($path2));
+ $this->assertInstanceOf('CI_Loader', $this->load->remove_package_path());
+ $this->assertNotContains($path2, $this->load->get_package_paths(TRUE));
+ }
+
+ // --------------------------------------------------------------------
+
public function test_load_config()
{
$cfg = 'someconfig';
@@ -511,5 +557,4 @@
// Verify config calls
$this->assertEquals($cfg['config'], $this->ci_obj->config->loaded);
}
-
-}
\ No newline at end of file
+}
diff --git a/tests/codeigniter/core/Security_test.php b/tests/codeigniter/core/Security_test.php
index 402422f..3acd2a5 100644
--- a/tests/codeigniter/core/Security_test.php
+++ b/tests/codeigniter/core/Security_test.php
@@ -71,6 +71,47 @@
$this->assertEquals("Hello, i try to [removed]alert('Hack');[removed] your site", $harmless_string);
}
+ // --------------------------------------------------------------------
+
+ public function test_xss_clean_string_array()
+ {
+ $harm_strings = array(
+ "Hello, i try to <script>alert('Hack');</script> your site",
+ "Simple clean string",
+ "Hello, i try to <script>alert('Hack');</script> your site"
+ );
+
+ $harmless_strings = $this->security->xss_clean($harm_strings);
+
+ $this->assertEquals("Hello, i try to [removed]alert('Hack');[removed] your site", $harmless_strings[0]);
+ $this->assertEquals("Simple clean string", $harmless_strings[1]);
+ $this->assertEquals("Hello, i try to [removed]alert('Hack');[removed] your site", $harmless_strings[2]);
+ }
+
+ // --------------------------------------------------------------------
+
+ public function test_xss_clean_image_valid()
+ {
+ $harm_string = '<img src="test.png">';
+
+ $xss_clean_return = $this->security->xss_clean($harm_string, TRUE);
+
+ $this->assertTrue($xss_clean_return);
+ }
+
+ // --------------------------------------------------------------------
+
+ public function test_xss_clean_image_invalid()
+ {
+ $harm_string = '<img src=javascript:alert(String.fromCharCode(88,83,83))>';
+
+ $xss_clean_return = $this->security->xss_clean($harm_string, TRUE);
+
+ $this->assertFalse($xss_clean_return);
+ }
+
+ // --------------------------------------------------------------------
+
public function test_xss_clean_entity_double_encoded()
{
$input = '<a href="&#106&#97&#118&#97&#115&#99&#114&#105&#112&#116&#58&#99&#111&#110&#102&#105&#114&#109&#40&#49&#41">Clickhere</a>';
@@ -79,6 +120,36 @@
// --------------------------------------------------------------------
+ public function test_xss_clean_js_img_removal()
+ {
+ $input = '<img src="&#106&#97&#118&#97&#115&#99&#114&#105&#112&#116&#58&#99&#111&#110&#102&#105&#114&#109&#40&#49&#41">Clickhere';
+ $this->assertEquals('<img >', $this->security->xss_clean($input));
+ }
+
+ // --------------------------------------------------------------------
+
+ public function test_xss_clean_sanitize_naughty_html()
+ {
+ $input = '<blink>';
+ $this->assertEquals('<blink>', $this->security->xss_clean($input));
+ }
+
+ // --------------------------------------------------------------------
+
+ public function test_remove_evil_attributes()
+ {
+ $this->assertEquals('<foo [removed]>', $this->security->remove_evil_attributes('<foo onAttribute="bar">', FALSE));
+ $this->assertEquals('<foo [removed]>', $this->security->remove_evil_attributes('<foo onAttributeNoQuotes=bar>', FALSE));
+ $this->assertEquals('<foo [removed]>', $this->security->remove_evil_attributes('<foo onAttributeWithSpaces = bar>', FALSE));
+ $this->assertEquals('<foo prefixOnAttribute="bar">', $this->security->remove_evil_attributes('<foo prefixOnAttribute="bar">', FALSE));
+ $this->assertEquals('<foo>onOutsideOfTag=test</foo>', $this->security->remove_evil_attributes('<foo>onOutsideOfTag=test</foo>', FALSE));
+ $this->assertEquals('onNoTagAtAll = true', $this->security->remove_evil_attributes('onNoTagAtAll = true', FALSE));
+ $this->assertEquals('<foo [removed]>', $this->security->remove_evil_attributes('<foo fscommand=case-insensitive>', FALSE));
+ $this->assertEquals('<foo [removed]>', $this->security->remove_evil_attributes('<foo seekSegmentTime=whatever>', FALSE));
+ }
+
+ // --------------------------------------------------------------------
+
public function test_xss_hash()
{
$this->assertEmpty($this->security->xss_hash);
@@ -91,6 +162,17 @@
// --------------------------------------------------------------------
+ public function test_get_random_bytes()
+ {
+ $length = "invalid";
+ $this->assertFalse($this->security->get_random_bytes($length));
+
+ $length = 10;
+ $this->assertNotEmpty($this->security->get_random_bytes($length));
+ }
+
+ // --------------------------------------------------------------------
+
public function test_entity_decode()
{
$encoded = '<div>Hello <b>Booya</b></div>';
@@ -115,4 +197,54 @@
$this->assertEquals('foo', $safe_filename);
}
-}
\ No newline at end of file
+ // --------------------------------------------------------------------
+
+ public function test_strip_image_tags()
+ {
+ $imgtags = array(
+ '<img src="smiley.gif" alt="Smiley face" height="42" width="42">',
+ '<img alt="Smiley face" height="42" width="42" src="smiley.gif">',
+ '<img src="http://www.w3schools.com/images/w3schools_green.jpg">',
+ '<img src="/img/sunset.gif" height="100%" width="100%">',
+ '<img src="mdn-logo-sm.png" alt="MD Logo" srcset="mdn-logo-HD.png 2x, mdn-logo-small.png 15w, mdn-banner-HD.png 100w 2x" />',
+ '<img sqrc="/img/sunset.gif" height="100%" width="100%">',
+ '<img srqc="/img/sunset.gif" height="100%" width="100%">',
+ '<img srcq="/img/sunset.gif" height="100%" width="100%">'
+ );
+
+ $urls = array(
+ 'smiley.gif',
+ 'smiley.gif',
+ 'http://www.w3schools.com/images/w3schools_green.jpg',
+ '/img/sunset.gif',
+ 'mdn-logo-sm.png',
+ '<img sqrc="/img/sunset.gif" height="100%" width="100%">',
+ '<img srqc="/img/sunset.gif" height="100%" width="100%">',
+ '<img srcq="/img/sunset.gif" height="100%" width="100%">'
+ );
+
+ for ($i = 0; $i < count($imgtags); $i++)
+ {
+ $this->assertEquals($urls[$i], $this->security->strip_image_tags($imgtags[$i]));
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ public function test_csrf_set_hash()
+ {
+ // Set cookie for security test
+ $_COOKIE['ci_csrf_cookie'] = md5(uniqid(mt_rand(), TRUE));
+
+ // Set config for Security class
+ $this->ci_set_config('csrf_protection', TRUE);
+ $this->ci_set_config('csrf_token_name', 'ci_csrf_token');
+
+ // leave csrf_cookie_name as blank to test _csrf_set_hash function
+ $this->ci_set_config('csrf_cookie_name', '');
+
+ $this->security = new Mock_Core_Security();
+
+ $this->assertNotEmpty($this->security->get_csrf_hash());
+ }
+}
diff --git a/tests/codeigniter/core/compat/password_test.php b/tests/codeigniter/core/compat/password_test.php
index c37c6ac..8a507d1 100644
--- a/tests/codeigniter/core/compat/password_test.php
+++ b/tests/codeigniter/core/compat/password_test.php
@@ -132,7 +132,7 @@
$this->assertFalse(password_needs_rehash('$2y$10$MTIzNDU2Nzg5MDEyMzQ1Nej0NmcAWSLR.oP7XOR9HD/vjUuOj100y', PASSWORD_BCRYPT, array('cost' => 10, 'foo' => 3)));
// invalid: different (lower) cost
- $this->assertTrue(password_needs_rehash('$2y$10$MTIzNDU2Nzg5MDEyMzQ1Nej0NmcAWSLR.oP7XOR9HD/vjUuOj100y', PASSWORD_BCRYPT, array('cost' => 09)));
+ $this->assertTrue(password_needs_rehash('$2y$10$MTIzNDU2Nzg5MDEyMzQ1Nej0NmcAWSLR.oP7XOR9HD/vjUuOj100y', PASSWORD_BCRYPT, array('cost' => 9)));
// invalid: different (higher) cost
$this->assertTrue(password_needs_rehash('$2y$10$MTIzNDU2Nzg5MDEyMzQ1Nej0NmcAWSLR.oP7XOR9HD/vjUuOj100y', PASSWORD_BCRYPT, array('cost' => 11)));
diff --git a/tests/codeigniter/database/DB_driver_test.php b/tests/codeigniter/database/DB_driver_test.php
index c04c42b..26416d3 100644
--- a/tests/codeigniter/database/DB_driver_test.php
+++ b/tests/codeigniter/database/DB_driver_test.php
@@ -6,7 +6,7 @@
{
$config = Mock_Database_DB::config(DB_DRIVER);
sscanf(DB_DRIVER, '%[^/]/', $driver_name);
- $driver = $this->$driver_name($config[DB_DRIVER]);
+ $driver = $this->{$driver_name}($config[DB_DRIVER]);
$this->assertTrue($driver->initialize());
}
diff --git a/tests/codeigniter/database/DB_test.php b/tests/codeigniter/database/DB_test.php
index d5c0dea..dc4fae9 100644
--- a/tests/codeigniter/database/DB_test.php
+++ b/tests/codeigniter/database/DB_test.php
@@ -15,7 +15,7 @@
),
));
- $this->setExpectedException('InvalidArgumentException', 'CI Error: Invalid DB driver');
+ $this->setExpectedException('RuntimeException', 'CI Error: Invalid DB driver');
Mock_Database_DB::DB($connection->set_dsn('undefined'), TRUE);
}
@@ -26,6 +26,14 @@
{
$config = Mock_Database_DB::config(DB_DRIVER);
$connection = new Mock_Database_DB($config);
+
+ // E_DEPRECATED notices thrown by mysql_connect(), mysql_pconnect()
+ // on PHP 5.5+ cause the tests to fail
+ if (DB_DRIVER === 'mysql' && version_compare(PHP_VERSION, '5.5', '>='))
+ {
+ error_reporting(E_ALL & ~E_DEPRECATED);
+ }
+
$db = Mock_Database_DB::DB($connection->set_dsn(DB_DRIVER), TRUE);
$this->assertTrue($db instanceof CI_DB);
@@ -34,6 +42,11 @@
// ------------------------------------------------------------------------
+/*
+ This test is unusable, because whoever wrote it apparently thought that
+ an E_WARNING should equal an Exception and based the whole test suite
+ around that bogus assumption.
+
public function test_db_failover()
{
$config = Mock_Database_DB::config(DB_DRIVER);
@@ -43,5 +56,6 @@
$this->assertTrue($db instanceof CI_DB);
$this->assertTrue($db instanceof CI_DB_Driver);
}
+*/
}
\ No newline at end of file
diff --git a/tests/codeigniter/libraries/Form_validation_test.php b/tests/codeigniter/libraries/Form_validation_test.php
new file mode 100644
index 0000000..26d82ec
--- /dev/null
+++ b/tests/codeigniter/libraries/Form_validation_test.php
@@ -0,0 +1,593 @@
+<?php
+
+class Form_validation_test extends CI_TestCase {
+
+ public function set_up()
+ {
+ $_SERVER['REQUEST_METHOD'] = 'POST';
+
+ // Create a mock loader since load->helper() looks in the wrong directories for unit tests,
+ // We'll use CI_TestCase->helper() instead
+ $loader = $this->getMock('CI_Loader', array('helper'));
+
+ // Same applies for lang
+ $lang = $this->getMock('CI_Lang', array('load'));
+
+ $this->ci_set_config('charset', 'UTF-8');
+ $utf8 = new Mock_Core_Utf8();
+ $security = new Mock_Core_Security();
+ $input = new Mock_Core_Input($security, $utf8);
+
+ $this->ci_instance_var('lang', $lang);
+ $this->ci_instance_var('load', $loader);
+ $this->ci_instance_var('input', $input);
+
+ $this->lang('form_validation');
+ $this->helper('form');
+
+ $this->form_validation = new CI_Form_validation();
+ }
+
+ public function test_rule_required()
+ {
+ $rules = array(array('field' => 'foo', 'label' => 'foo_label', 'rules' => 'required'));
+ $this->assertTrue($this->run_rules($rules, array('foo' => 'bar')));
+
+ $this->assertFalse($this->run_rules($rules, array('foo' => '')));
+ $this->assertFalse($this->run_rules($rules, array('foo' => ' ')));
+ }
+
+ public function test_rule_matches()
+ {
+ $rules = array(
+ array('field' => 'foo', 'label' => 'label', 'rules' => 'required'),
+ array('field' => 'bar', 'label' => 'label2', 'rules' => 'matches[foo]')
+ );
+ $values_base = array('foo' => 'sample');
+
+ $this->assertTrue($this->run_rules($rules, array_merge($values_base, array('bar' => ''))));
+ $this->assertTrue($this->run_rules($rules, array_merge($values_base, array('bar' => 'sample'))));
+
+ $this->assertFalse($this->run_rules($rules, array_merge($values_base, array('bar' => 'Sample'))));
+ $this->assertFalse($this->run_rules($rules, array_merge($values_base, array('bar' => ' sample'))));
+ }
+
+ public function test_rule_differs()
+ {
+ $rules = array(
+ array('field' => 'foo', 'label' => 'label', 'rules' => 'required'),
+ array('field' => 'bar', 'label' => 'label2', 'rules' => 'differs[foo]')
+ );
+ $values_base = array('foo' => 'sample');
+
+ $this->assertTrue($this->run_rules($rules, array_merge($values_base, array('bar' => 'does_not_match'))));
+ $this->assertTrue($this->run_rules($rules, array_merge($values_base, array('bar' => 'Sample'))));
+ $this->assertTrue($this->run_rules($rules, array_merge($values_base, array('bar' => ' sample'))));
+
+ $this->assertFalse($this->run_rules($rules, array_merge($values_base, array('bar' => 'sample'))));
+ }
+
+ public function test_rule_min_length()
+ {
+ $this->assertTrue($this->form_validation->min_length('12345', '5'));
+ $this->assertTrue($this->form_validation->min_length('test', '0'));
+
+ $this->assertFalse($this->form_validation->min_length('123', '4'));
+ $this->assertFalse($this->form_validation->min_length('should_fail', 'A'));
+ $this->assertFalse($this->form_validation->min_length('', '4'));
+ }
+
+ public function test_rule_max_length()
+ {
+ $this->assertTrue($this->form_validation->max_length('', '4'));
+ $this->assertTrue($this->form_validation->max_length('1234', '4'));
+
+ $this->assertFalse($this->form_validation->max_length('12345', '4'));
+ $this->assertFalse($this->form_validation->max_length('should_fail', 'A'));
+ }
+
+ public function test_rule_exact_length()
+ {
+ $this->assertTrue($this->form_validation->exact_length('1234', '4'));
+
+ $this->assertFalse($this->form_validation->exact_length('', '3'));
+ $this->assertFalse($this->form_validation->exact_length('12345', '4'));
+ $this->assertFalse($this->form_validation->exact_length('123', '4'));
+ $this->assertFalse($this->form_validation->exact_length('should_fail', 'A'));
+ }
+
+ public function test_rule_greater_than()
+ {
+ $this->assertTrue($this->form_validation->greater_than('-10', '-11'));
+ $this->assertTrue($this->form_validation->greater_than('10', '9'));
+
+ $this->assertFalse($this->form_validation->greater_than('10', '10'));
+ $this->assertFalse($this->form_validation->greater_than('10', 'a'));
+ $this->assertFalse($this->form_validation->greater_than('10a', '10'));
+ }
+
+ public function test_rule_greater_than_equal_to()
+ {
+ $this->assertTrue($this->form_validation->greater_than_equal_to('0', '0'));
+ $this->assertTrue($this->form_validation->greater_than_equal_to('1', '0'));
+
+ $this->assertFalse($this->form_validation->greater_than_equal_to('-1', '0'));
+ $this->assertFalse($this->form_validation->greater_than_equal_to('10a', '0'));
+ }
+
+ public function test_rule_less_than()
+ {
+ $this->assertTrue($this->form_validation->less_than('4', '5'));
+ $this->assertTrue($this->form_validation->less_than('-1', '0'));
+
+ $this->assertFalse($this->form_validation->less_than('4', '4'));
+ $this->assertFalse($this->form_validation->less_than('10a', '5'));
+ }
+
+ public function test_rule_less_than_equal_to()
+ {
+ $this->assertTrue($this->form_validation->less_than_equal_to('-1', '0'));
+ $this->assertTrue($this->form_validation->less_than_equal_to('-1', '-1'));
+ $this->assertTrue($this->form_validation->less_than_equal_to('4', '4'));
+
+ $this->assertFalse($this->form_validation->less_than_equal_to('0', '-1'));
+ $this->assertFalse($this->form_validation->less_than_equal_to('10a', '0'));
+ }
+
+ public function test_rule_in_list()
+ {
+ $this->assertTrue($this->form_validation->in_list('red', 'red,Blue,123'));
+ $this->assertTrue($this->form_validation->in_list('Blue', 'red,Blue,123'));
+ $this->assertTrue($this->form_validation->in_list('123', 'red,Blue,123'));
+
+ $this->assertFalse($this->form_validation->in_list('Red', 'red,Blue,123'));
+ $this->assertFalse($this->form_validation->in_list(' red', 'red,Blue,123'));
+ $this->assertFalse($this->form_validation->in_list('1234', 'red,Blue,123'));
+ }
+
+ public function test_rule_alpha()
+ {
+ $this->assertTrue($this->form_validation->alpha('abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ'));
+
+ $this->assertFalse($this->form_validation->alpha('abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ '));
+ $this->assertFalse($this->form_validation->alpha('abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ1'));
+ $this->assertFalse($this->form_validation->alpha('abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ*'));
+ }
+
+ public function test_rule_alpha_numeric()
+ {
+ $this->assertTrue($this->form_validation->alpha_numeric('abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ0123456789'));
+
+ $this->assertFalse($this->form_validation->alpha_numeric('abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ0123456789\ '));
+ $this->assertFalse($this->form_validation->alpha_numeric('abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ0123456789_'));
+ }
+
+ public function test_rule_alpha_numeric_spaces()
+ {
+ $this->assertTrue($this->form_validation->alpha_numeric_spaces(' abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ0123456789'));
+
+ $this->assertFalse($this->form_validation->alpha_numeric_spaces(' abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ0123456789_'));
+ }
+
+ public function test_rule_alpha_dash()
+ {
+ $this->assertTrue($this->form_validation->alpha_dash('abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ0123456789-_'));
+
+ $this->assertFalse($this->form_validation->alpha_dash('abcdefghijklmnopqrstuvwxyzABCDEFGHLIJKLMNOPQRSTUVWXYZ0123456789-_\ '));
+ }
+
+ public function test_rule_numeric()
+ {
+ $this->assertTrue($this->form_validation->numeric('0'));
+ $this->assertTrue($this->form_validation->numeric('12314'));
+ $this->assertTrue($this->form_validation->numeric('-42'));
+
+ $this->assertFalse($this->form_validation->numeric('123a'));
+ $this->assertFalse($this->form_validation->numeric('--1'));
+ }
+
+ public function test_rule_integer()
+ {
+ $this->assertTrue($this->form_validation->integer('0'));
+ $this->assertTrue($this->form_validation->integer('42'));
+ $this->assertTrue($this->form_validation->integer('-1'));
+
+ $this->assertFalse($this->form_validation->integer('124a'));
+ $this->assertFalse($this->form_validation->integer('1.9'));
+ $this->assertFalse($this->form_validation->integer('--1'));
+ }
+
+ public function test_rule_decimal()
+ {
+ $this->assertTrue($this->form_validation->decimal('1.0'));
+ $this->assertTrue($this->form_validation->decimal('-0.98'));
+
+ $this->assertFalse($this->form_validation->decimal('0'));
+ $this->assertFalse($this->form_validation->decimal('1.0a'));
+ $this->assertFalse($this->form_validation->decimal('-i'));
+ $this->assertFalse($this->form_validation->decimal('--1'));
+ }
+
+ public function test_rule_is_natural()
+ {
+ $this->assertTrue($this->form_validation->is_natural('0'));
+ $this->assertTrue($this->form_validation->is_natural('12'));
+
+ $this->assertFalse($this->form_validation->is_natural('42a'));
+ $this->assertFalse($this->form_validation->is_natural('-1'));
+ }
+
+ public function test_rule_is_natural_no_zero()
+ {
+ $this->assertTrue($this->form_validation->is_natural_no_zero('42'));
+
+ $this->assertFalse($this->form_validation->is_natural_no_zero('0'));
+ $this->assertFalse($this->form_validation->is_natural_no_zero('42a'));
+ $this->assertFalse($this->form_validation->is_natural_no_zero('-1'));
+ }
+
+ public function test_rule_valid_url()
+ {
+ $this->assertTrue($this->form_validation->valid_url('www.codeigniter.com'));
+ $this->assertTrue($this->form_validation->valid_url('http://codeigniter.eu'));
+
+ $this->assertFalse($this->form_validation->valid_url('htt://www.codeIgniter.com'));
+ $this->assertFalse($this->form_validation->valid_url(''));
+ $this->assertFalse($this->form_validation->valid_url('code igniter'));
+ }
+
+ public function test_rule_valid_email()
+ {
+ $this->assertTrue($this->form_validation->valid_email('email@sample.com'));
+
+ $this->assertFalse($this->form_validation->valid_email('valid_email', '@sample.com'));
+ }
+
+ public function test_rule_valid_emails()
+ {
+ $this->assertTrue($this->form_validation->valid_emails('1@sample.com,2@sample.com'));
+ $this->assertTrue($this->form_validation->valid_emails('email@sample.com'));
+
+ $this->assertFalse($this->form_validation->valid_emails('valid_email', '@sample.com'));
+ $this->assertFalse($this->form_validation->valid_emails('@sample.com,2@sample.com,validemail@email.ca'));
+ }
+
+ public function test_rule_valid_ip()
+ {
+ $this->assertTrue($this->form_validation->valid_ip('127.0.0.1'));
+ $this->assertTrue($this->form_validation->valid_ip('127.0.0.1', 'ipv4'));
+ $this->assertTrue($this->form_validation->valid_ip('2001:0db8:85a3:0000:0000:8a2e:0370:7334'));
+ $this->assertTrue($this->form_validation->valid_ip('2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'ipv6'));
+
+ $this->assertFalse($this->form_validation->valid_ip('2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'ipv4'));
+ $this->assertFalse($this->form_validation->valid_ip('127.0.0.1', 'ipv6'));
+ $this->assertFalse($this->form_validation->valid_ip('H001:0db8:85a3:0000:0000:8a2e:0370:7334'));
+ $this->assertFalse($this->form_validation->valid_ip('127.0.0.259'));
+ }
+
+ public function test_rule_valid_base64()
+ {
+ $this->assertTrue($this->form_validation->valid_base64(base64_encode('string')));
+
+ $this->assertFalse($this->form_validation->valid_base64('FA08GG'));
+ }
+
+ public function test_set_data()
+ {
+ // Reset test environment
+ $_POST = array();
+ $this->form_validation->reset_validation();
+ $data = array('field' => 'some_data');
+ $this->form_validation->set_data($data);
+ $this->form_validation->set_rules('field', 'label', 'required');
+ $this->assertTrue($this->form_validation->run());
+
+ // Test with empty array
+ $_POST = array();
+ $this->form_validation->reset_validation();
+ $data = array('field' => 'some_data');
+ $this->form_validation->set_data($data);
+ // This should do nothing. Old data will still be used
+ $this->form_validation->set_data(array());
+ $this->form_validation->set_rules('field', 'label', 'required');
+ $this->assertTrue($this->form_validation->run());
+ }
+
+ public function test_set_message()
+ {
+ // Reset test environment
+ $_POST = array();
+ $this->form_validation->reset_validation();
+ $err_message = 'What a terrible error!';
+ $rules = array(
+ array(
+ 'field' => 'req_field',
+ 'label' => 'label',
+ 'rules' => 'required'
+ )
+ );
+ $errorless_data = array('req_field' => 'some text');
+ $erroneous_data = array('req_field' => '');
+
+ $this->form_validation->set_message('required', $err_message);
+ $this->form_validation->set_data($erroneous_data);
+ $this->form_validation->set_rules($rules);
+ $this->form_validation->run();
+ $this->assertEquals('<p>'.$err_message.'</p>', $this->form_validation->error('req_field'));
+
+ $this->form_validation->reset_validation();
+ $this->form_validation->set_message('required', $err_message);
+ $this->form_validation->set_data($errorless_data);
+ $this->form_validation->set_rules($rules);
+ $this->form_validation->run();
+ $this->assertEquals('', $this->form_validation->error('req_field'));
+ }
+
+ public function test_set_error_delimiters()
+ {
+ $this->form_validation->reset_validation();
+ $prefix = '<div class="error">';
+ $suffix = '</div>';
+ $this->form_validation->set_error_delimiters($prefix, $suffix);
+ $this->form_validation->set_rules('foo', 'label', 'required');
+ $_POST = array('foo' => '');
+ $this->form_validation->run();
+ $error_msg = $this->form_validation->error('foo');
+
+ $this->assertTrue(strrpos($error_msg, $prefix) === 0);
+ $this->assertTrue(strrpos($error_msg, $suffix, -strlen($suffix)) === (strlen($error_msg) - strlen($suffix)));
+ }
+
+ public function test_error_array()
+ {
+ $this->form_validation->reset_validation();
+ $error_message = 'What a terrible error!';
+ $this->form_validation->set_message('required', $error_message);
+ $this->form_validation->set_rules('foo', 'label', 'required');
+ $_POST = array('foo' => '');
+ $this->form_validation->run();
+ $error_array = $this->form_validation->error_array();
+ $this->assertEquals($error_message, $error_array['foo']);
+ }
+
+ public function test_error_string()
+ {
+ $this->form_validation->reset_validation();
+ $error_message = 'What a terrible error!';
+ $prefix_default = '<foo>';
+ $suffix_default = '</foo>';
+ $prefix_test = '<bar>';
+ $suffix_test = '</bar>';
+ $this->form_validation->set_error_delimiters($prefix_default, $suffix_default);
+ $this->form_validation->set_message('required', $error_message);
+ $this->form_validation->set_rules('foo', 'label', 'required');
+ $_POST = array('foo' => '');
+ $this->form_validation->run();
+
+ $this->assertEquals($prefix_default.$error_message.$suffix_default."\n", $this->form_validation->error_string());
+ $this->assertEquals($prefix_test.$error_message.$suffix_default."\n", $this->form_validation->error_string($prefix_test, ''));
+ $this->assertEquals($prefix_default.$error_message.$suffix_test."\n", $this->form_validation->error_string('', $suffix_test));
+ $this->assertEquals($prefix_test.$error_message.$suffix_test."\n", $this->form_validation->error_string($prefix_test, $suffix_test));
+
+ $this->form_validation->reset_validation();
+ $this->form_validation->set_rules('foo', 'label', 'required');
+ $_POST = array('foo' => 'bar');
+ $this->form_validation->run();
+ $this->assertEquals('', $this->form_validation->error_string());
+ }
+
+ public function test_run()
+ {
+ // form_validation->run() is tested in many of the other unit tests
+ // This test will only test run(group='') when group is not empty
+ $config = array(
+ 'pass' => array(
+ array(
+ 'field' => 'username',
+ 'label' => 'user',
+ 'rules' => 'alpha_numeric'
+ )
+ ),
+ 'fail' => array(
+ array(
+ 'field' => 'username',
+ 'label' => 'user',
+ 'rules' => 'alpha'
+ )
+ )
+ );
+ $_POST = array('username' => 'foo42');
+ $form_validation = new CI_Form_validation($config);
+ $this->assertTrue($form_validation->run('pass'));
+
+ $form_validation = new CI_Form_validation($config);
+ $this->assertFalse($form_validation->run('fail'));
+ }
+
+ public function test_has_rule()
+ {
+ $this->form_validation->reset_validation();
+ $this->form_validation->set_rules('foo', 'label', 'required');
+
+ $this->assertTrue($this->form_validation->has_rule('foo'));
+ $this->assertFalse($this->form_validation->has_rule('bar'));
+ }
+
+ public function test_set_value()
+ {
+ $this->form_validation->reset_validation();
+ $default = 'default';
+ $this->form_validation->set_rules('foo', 'label', 'required');
+ $this->form_validation->set_rules('bar[]', 'label', 'required');
+
+ // No post data yet: should return the default value provided
+ $this->assertEquals($default, $this->form_validation->set_value('foo', $default));
+ $_POST = array('foo' => 'foo', 'bar' => array('bar1', 'bar2'));
+ $this->form_validation->run();
+ $this->assertEquals('foo', $this->form_validation->set_value('foo', $default));
+ $this->assertEquals('bar1', $this->form_validation->set_value('bar[]', $default));
+ $this->assertEquals('bar2', $this->form_validation->set_value('bar[]', $default));
+ }
+
+ public function test_set_select()
+ {
+ // Test 1: No options selected
+ $this->form_validation->reset_validation();
+ $_POST = array();
+ $this->form_validation->run();
+
+ $this->assertEquals('', $this->form_validation->set_select('select', 'foo'));
+ $this->assertEquals(' selected="selected"', $this->form_validation->set_select('select', 'bar', TRUE));
+
+ // Test 2: 1 option selected
+ $this->form_validation->reset_validation();
+ $this->form_validation->set_rules('select', 'label', 'alpha_numeric');
+ $_POST = array('select' => 'foo');
+ $this->form_validation->run();
+
+ $this->assertEquals(' selected="selected"', $this->form_validation->set_select('select', 'foo'));
+ $this->assertEquals(' selected="selected"', $this->form_validation->set_select('select', 'foo', TRUE));
+ $this->assertEquals('', $this->form_validation->set_select('select', 'bar'));
+ $this->assertEquals('', $this->form_validation->set_select('select', 'bar', TRUE));
+
+ // Test 3: Multiple options selected
+ $this->form_validation->reset_validation();
+ $this->form_validation->set_rules('select[]', 'label', 'alpha_numeric');
+ $_POST = array('select' => array('foo', 'bar'));
+ $this->form_validation->run();
+
+ $this->assertEquals(' selected="selected"', $this->form_validation->set_select('select[]', 'foo'));
+ $this->assertEquals(' selected="selected"', $this->form_validation->set_select('select[]', 'foo', TRUE));
+ $this->assertEquals(' selected="selected"', $this->form_validation->set_select('select[]', 'bar'));
+ $this->assertEquals(' selected="selected"', $this->form_validation->set_select('select[]', 'bar', TRUE));
+ $this->assertEquals('', $this->form_validation->set_select('select[]', 'foobar'));
+ $this->assertEquals('', $this->form_validation->set_select('select[]', 'foobar', TRUE));
+ }
+
+ public function test_set_radio()
+ {
+ // Test 1: No options selected
+ $this->form_validation->reset_validation();
+ $_POST = array();
+ $this->form_validation->run();
+
+ $this->assertEquals('', $this->form_validation->set_radio('select', 'foo'));
+ // Default should only work when no rules are set
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_radio('select', 'bar', TRUE));
+
+ // Test 2: 1 option selected
+ $this->form_validation->reset_validation();
+ $this->form_validation->set_rules('select', 'label', 'alpha_numeric');
+ $_POST = array('select' => 'foo');
+ $this->form_validation->run();
+
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_radio('select', 'foo'));
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_radio('select', 'foo', TRUE));
+ $this->assertEquals('', $this->form_validation->set_radio('select', 'bar'));
+ $this->assertEquals('', $this->form_validation->set_radio('select', 'bar', TRUE));
+
+ // Test 3: Multiple options checked
+ $this->form_validation->reset_validation();
+ $this->form_validation->set_rules('select[]', 'label', 'alpha_numeric');
+ $_POST = array('select' => array('foo', 'bar'));
+ $this->form_validation->run();
+
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_radio('select[]', 'foo'));
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_radio('select[]', 'foo', TRUE));
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_radio('select[]', 'bar'));
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_radio('select[]', 'bar', TRUE));
+ $this->assertEquals('', $this->form_validation->set_radio('select[]', 'foobar'));
+ $this->assertEquals('', $this->form_validation->set_radio('select[]', 'foobar', TRUE));
+ }
+
+ public function test_set_checkbox()
+ {
+ // Test 1: No options selected
+ $this->form_validation->reset_validation();
+ $_POST = array();
+ $this->form_validation->run();
+
+ $this->assertEquals('', $this->form_validation->set_checkbox('select', 'foo'));
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_checkbox('select', 'bar', TRUE));
+
+ // Test 2: 1 option selected
+ $this->form_validation->reset_validation();
+ $this->form_validation->set_rules('select', 'label', 'alpha_numeric');
+ $_POST = array('select' => 'foo');
+ $this->form_validation->run();
+
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_checkbox('select', 'foo'));
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_checkbox('select', 'foo', TRUE));
+ $this->assertEquals('', $this->form_validation->set_checkbox('select', 'bar'));
+ $this->assertEquals('', $this->form_validation->set_checkbox('select', 'bar', TRUE));
+
+ // Test 3: Multiple options selected
+ $this->form_validation->reset_validation();
+ $this->form_validation->set_rules('select[]', 'label', 'alpha_numeric');
+ $_POST = array('select' => array('foo', 'bar'));
+ $this->form_validation->run();
+
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_checkbox('select[]', 'foo'));
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_checkbox('select[]', 'foo', TRUE));
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_checkbox('select[]', 'bar'));
+ $this->assertEquals(' checked="checked"', $this->form_validation->set_checkbox('select[]', 'bar', TRUE));
+ $this->assertEquals('', $this->form_validation->set_checkbox('select[]', 'foobar'));
+ $this->assertEquals('', $this->form_validation->set_checkbox('select[]', 'foobar', TRUE));
+ }
+
+ public function test_regex_match()
+ {
+ $regex = '/f[a-zA-Z]+/';
+ $this->assertTrue($this->form_validation->regex_match('foo', $regex));
+ $this->assertFalse($this->form_validation->regex_match('bar', $regex));
+ }
+
+ public function test_prep_for_form()
+ {
+ $this->form_validation->reset_validation();
+ $error_msg_unprepped = '<error =\'foobar\'">';
+ $error_msg_prepped = '<error ='foobar'">';
+ $this->form_validation->set_rules('foo', 'label', 'required', array('required' => $error_msg_unprepped));
+ $_POST = array('foo' => '');
+ $this->form_validation->run();
+ $error_arr = $this->form_validation->error_array();
+
+ $this->assertEquals('', $this->form_validation->prep_for_form(''));
+ $this->assertEquals(array('foo' => $error_msg_prepped), $this->form_validation->prep_for_form($error_arr));
+ }
+
+ public function test_prep_url()
+ {
+ $this->assertEquals('', $this->form_validation->prep_url(''));
+ $this->assertEquals('http://codeigniter.com', $this->form_validation->prep_url('codeigniter.com'));
+ $this->assertEquals('https://codeigniter.com', $this->form_validation->prep_url('https://codeigniter.com'));
+ $this->assertEquals('http://codeigniter.com', $this->form_validation->prep_url('http://codeigniter.com'));
+ $this->assertEquals('http://www.codeigniter.com', $this->form_validation->prep_url('www.codeigniter.com'));
+ }
+
+ public function test_encode_php_tags()
+ {
+ $this->assertEquals("<?php", $this->form_validation->encode_php_tags('<?php'));
+ $this->assertEquals('?>', $this->form_validation->encode_php_tags('?>'));
+ }
+
+ /**
+ * Run rules
+ *
+ * Helper method to set rules and run them at once, not
+ * an actual test case.
+ */
+ public function run_rules($rules, $values)
+ {
+ $this->form_validation->reset_validation();
+ $_POST = array();
+
+ $this->form_validation->set_rules($rules);
+ foreach ($values as $field => $value)
+ {
+ $_POST[$field] = $value;
+ }
+
+ return $this->form_validation->run();
+ }
+}
diff --git a/tests/mocks/core/input.php b/tests/mocks/core/input.php
index 0d18738..40e2744 100644
--- a/tests/mocks/core/input.php
+++ b/tests/mocks/core/input.php
@@ -38,4 +38,12 @@
return FALSE;
}
+ public function __set($name, $value)
+ {
+ if ($name === 'ip_address')
+ {
+ $this->ip_address = $value;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/tests/mocks/core/security.php b/tests/mocks/core/security.php
index a21fc5c..6cff858 100644
--- a/tests/mocks/core/security.php
+++ b/tests/mocks/core/security.php
@@ -16,6 +16,11 @@
return isset($this->{'_'.$property}) ? $this->{'_'.$property} : NULL;
}
+ public function remove_evil_attributes($str, $is_image)
+ {
+ return $this->_remove_evil_attributes($str, $is_image);
+ }
+
// Override inaccessible protected method
public function __call($method, $params)
{
diff --git a/tests/mocks/database/db.php b/tests/mocks/database/db.php
index 968476d..00dd884 100644
--- a/tests/mocks/database/db.php
+++ b/tests/mocks/database/db.php
@@ -56,8 +56,7 @@
'char_set' => 'utf8',
'dbcollat' => 'utf8_general_ci',
'swap_pre' => '',
- 'autoinit' => TRUE,
- 'stricton' => FALSE,
+ 'stricton' => FALSE
);
$config = array_merge($this->config[$group], $params);
@@ -134,7 +133,7 @@
}
catch (Exception $e)
{
- throw new InvalidArgumentException($e->getMessage());
+ throw new RuntimeException($e->getMessage());
}
return $db;
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index bc3ea34..8fa4d1e 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -2,11 +2,25 @@
Change Log
##########
-Version 3.0 (planned)
-=======================
+Version 3.0.1
+=============
Release Date: Not Released
+- Core
+
+ - Added DoS mitigation to :php:func:`hash_pbkdf2()` :doc:`compatibility function <general/compatibility_functions>`.
+
+Bug fixes for 3.0.1
+-------------------
+
+- Fixed a bug (#3733) - Autoloading of libraries with aliases didn't work, although it was advertised to.
+
+Version 3.0.0
+=============
+
+Release Date: March 30, 2015
+
- License
- CodeIgniter has been relicensed with the `MIT License <http://opensource.org/licenses/MIT>`_, eliminating its old proprietary licensing.
@@ -56,7 +70,7 @@
- Added availability checks where usage of dangerous functions like ``eval()`` and ``exec()`` is required.
- Added support for changing the file extension of log files using ``$config['log_file_extension']``.
- Added support for turning newline standardization on/off via ``$config['standardize_newlines']`` and set it to FALSE by default.
- - Added configuration setting ``$config['composer_autoload']`` to enable loading of a `Composer <https://getcomposer.org/>`_ auto-loader.
+ - Added configuration setting ``$config['composer_autoload']`` to enable loading of a `Composer <https://getcomposer.org>`_ auto-loader.
- Removed the automatic conversion of 'programmatic characters' to HTML entities from the :doc:`URI Library <libraries/uri>`.
- Changed log messages that say a class or file was loaded to "info" level instead of "debug", so that they don't pollute log files when ``$config['log_threshold']`` is set to 2 (debug).
@@ -67,7 +81,7 @@
- Added an optional third parameter to :php:func:`timespan()` that constrains the number of time units displayed.
- Added an optional parameter to :php:func:`timezone_menu()` that allows more attributes to be added to the generated select tag.
- Added function :php:func:`date_range()` that generates a list of dates between a specified period.
- - Deprecated ``standard_date()``, which now just uses the native ``date()`` with `DateTime constants <http://www.php.net/manual/en/class.datetime.php#datetime.constants.types>`_.
+ - Deprecated ``standard_date()``, which now just uses the native ``date()`` with `DateTime constants <http://php.net/manual/en/class.datetime.php#datetime.constants.types>`_.
- Changed :php:func:`now()` to work with all timezone strings supported by PHP.
- Changed :php:func:`days_in_month()` to use the native ``cal_days_in_month()`` PHP function, if available.
@@ -155,6 +169,8 @@
- DEPRECATED the 'mysql', 'sqlite', 'mssql' and 'pdo/dblib' (also known as 'pdo/mssql' or 'pdo/sybase') drivers.
- Added **dsn** configuration setting for drivers that support DSN strings (PDO, PostgreSQL, Oracle, ODBC, CUBRID).
- Added **schema** configuration setting (defaults to *public*) for drivers that might need it (currently used by PostgreSQL and ODBC).
+ - Added **save_queries** configuration setting to *application/config/database.php* (defaults to ``TRUE``).
+ - Removed **autoinit** configuration setting as it doesn't make sense to instantiate the database class but not connect to the database.
- Added subdrivers support (currently only used by PDO).
- Added an optional database name parameter to ``db_select()``.
- Removed ``protect_identifiers()`` and renamed internal method ``_protect_identifiers()`` to it instead - it was just an alias.
@@ -173,7 +189,6 @@
- Added support for SQLite3 database driver.
- Added Interbase/Firebird database support via the *ibase* driver.
- Added ODBC support for ``create_database()``, ``drop_database()`` and ``drop_table()`` in :doc:`Database Forge <database/forge>`.
- - Added **save_queries** configuration setting to *application/config/database.php* (defaults to ``TRUE``).
- Added support to binding arrays as ``IN()`` sets in ``query()``.
- :doc:`Query Builder <database/query_builder>` changes include:
@@ -191,6 +206,7 @@
- Methods ``insert_batch()`` and ``update_batch()`` now return an integer representing the number of rows affected by them.
- Methods ``where()``, ``or_where()``, ``having()`` and ``or_having()`` now convert trailing ``=`` and ``<>``, ``!=`` SQL operators to ``IS NULL`` and ``IS NOT NULL`` respectively when the supplied comparison value is ``NULL``.
- Added method chaining support to ``reset_query()``, ``start_cache()``, ``stop_cache()`` and ``flush_cache()``.
+ - Added an optional second parameter to ``count_all_results()`` to disable resetting of QB values.
- :doc:`Database Results <database/results>` changes include:
@@ -361,6 +377,7 @@
- Added support for custom error messages per field rule.
- Added support for callable rules when they are passed as an array.
- Added support for non-ASCII domains in **valid_email** rule, depending on the Intl extension.
+ - Changed the debug message about an error message not being set to include the rule name it is about.
- :doc:`Caching Library <libraries/caching>` changes include:
@@ -459,7 +476,7 @@
- Renamed internal method ``_detect_uri()`` to ``_parse_request_uri()``.
- Changed ``_parse_request_uri()`` to accept absolute URIs for compatibility with HTTP/1.1 as per `RFC2616 <http://www.ietf.org/rfc/rfc2616.txt>`.
- Added protected method ``_parse_query_string()`` to URI paths in the the **QUERY_STRING** value, like ``_parse_request_uri()`` does.
- - Changed URI string detection logic to try the **PATH_INFO** variable first when auto-detecting.
+ - Changed URI string detection logic to always default to **REQUEST_URI** unless configured otherwise or under CLI.
- Removed methods ``_remove_url_suffix()``, ``_explode_segments()`` and moved their logic into ``_set_uri_string()``.
- Removed method ``_fetch_uri_string()`` and moved its logic into the class constructor.
- Removed method ``_reindex_segments()``.
@@ -479,6 +496,7 @@
- :doc:`Input Library <libraries/input>` changes include:
+ - Deprecated the ``$config['global_xss_filtering']`` setting.
- Added ``method()`` to retrieve ``$_SERVER['REQUEST_METHOD']``.
- Added support for arrays and network addresses (e.g. 192.168.1.1/24) for use with the *proxy_ips* setting.
- Added method ``input_stream()`` to aid in using **php://input** stream data such as one passed via PUT, DELETE and PATCH requests.
@@ -492,6 +510,7 @@
- Added an option for ``_clean_input_keys()`` to return FALSE instead of terminating the whole script.
- Deprecated the ``is_cli_request()`` method, it is now an alias for the new :php:func:`is_cli()` common function.
- Added an ``$xss_clean`` parameter to method ``user_agent()`` and removed the ``$user_agent`` property.
+ - Added property ``$raw_input_stream`` to access **php://input** data.
- :doc:`Common functions <general/common_functions>` changes include:
@@ -507,7 +526,8 @@
- Changed internal function ``load_class()`` to accept a constructor parameter instead of (previously unused) class name prefix.
- Removed default parameter value of :php:func:`is_php()`.
- Added a second argument ``$double_encode`` to :php:func:`html_escape()`.
- - Changed function ``config_item()`` to return NULL instead of FALSE when no value is found.
+ - Changed function :php:func:`config_item()` to return NULL instead of FALSE when no value is found.
+ - Changed function :php:func:`set_status_header()` to return immediately when run under CLI.
- :doc:`Output Library <libraries/output>` changes include:
@@ -559,7 +579,7 @@
- Changed the library constructor to try to create the **log_path** directory if it doesn't exist.
- Added support for microseconds ("u" date format character) in ``$config['log_date_format']``.
- - Added `compatibility layers <general/compatibility_functions>` for:
+ - Added :doc:`compatibility layers <general/compatibility_functions>` for:
- `Multibyte String <http://php.net/mbstring>`_ (limited support).
- `Hash <http://php.net/hash>`_ (``hash_equals()``, ``hash_pbkdf2()``).
@@ -573,7 +593,7 @@
Bug fixes for 3.0
-------------------
+-----------------
- Fixed a bug where ``unlink()`` raised an error if cache file did not exist when you try to delete it.
- Fixed a bug (#181) - a typo in the form validation language file.
@@ -660,7 +680,6 @@
- Fixed a bug (#10) - :doc:`URI Library <libraries/uri>` internal method ``_detect_uri()`` failed with paths containing a colon.
- Fixed a bug (#1387) - :doc:`Query Builder <database/query_builder>` method ``from()`` didn't escape table aliases.
- Fixed a bug (#520) - :doc:`Date Helper <helpers/date_helper>` function :php:func:``nice_date()`` failed when the optional second parameter is not passed.
-- Fixed a bug (#167) - ``$config['permitted_uri_chars']`` didn't affect URL-encoded characters.
- Fixed a bug (#318) - :doc:`Profiling Library <general/profiling>` setting *query_toggle_count* was not settable as described in the manual.
- Fixed a bug (#938) - :doc:`Config Library <libraries/config>` method ``site_url()`` added a question mark to the URL string when query strings are enabled even if it already existed.
- Fixed a bug (#999) - :doc:`Config Library <libraries/config>` method ``site_url()`` always appended ``$config['url_suffix']`` to the end of the URL string, regardless of whether a query string exists in it.
@@ -705,7 +724,6 @@
- Fixed a bug (#50) - :doc:`Session Library <libraries/sessions>` unnecessarily stripped slashed from serialized data, making it impossible to read objects in a namespace.
- Fixed a bug (#658) - :doc:`Routing <general/routing>` wildcard **:any** didn't work as advertised and matched multiple URI segments instead of all characters within a single segment.
- Fixed a bug (#1938) - :doc:`Email Library <libraries/email>` removed multiple spaces inside a pre-formatted plain text message.
-- Fixed a bug (#388, #705) - :doc:`URI Library <libraries/uri>` didn't apply URL-decoding to URI segments that it got from **REQUEST_URI** and/or **QUERY_STRING**.
- Fixed a bug (#122) - :doc:`URI Library <libraries/uri>` method ``ruri_string()`` didn't include a directory if one is used.
- Fixed a bug - :doc:`Routing Library <general/routing>` didn't properly handle *default_controller* in a subdirectory when a method is also specified.
- Fixed a bug (#953) - :doc:`post_controller_constructor hook <general/hooks>` wasn't called with a *404_override*.
@@ -768,6 +786,7 @@
- Fixed a bug (#3161) - :doc:`Cache Library <libraries/caching>` methods `increment()`, `decrement()` didn't auto-create non-existent items when using redis and/or file storage.
- Fixed a bug (#3189) - :doc:`Parser Library <libraries/parser>` used double replacement on ``key->value`` pairs, exposing a potential template injection vulnerability.
- 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.1
=============
@@ -1132,12 +1151,8 @@
class <libraries/input>`.
- Added form_validation_lang entries for decimal, less_than and
greater_than.
-- `Fixed issue
- #153 <https://bitbucket.org/ellislab/codeigniter-reactor/issue/153/escape-str-bug-in-mssql-driver>`_
- Escape Str Bug in MSSQL driver.
-- `Fixed issue
- #172 <https://bitbucket.org/ellislab/codeigniter-reactor/issue/172/bug-in-chrome-and-form_open-in-201>`_
- Google Chrome 11 posts incorrectly when action is empty.
+- Fixed issue #153 Escape Str Bug in MSSQL driver.
+- Fixed issue #172 Google Chrome 11 posts incorrectly when action is empty.
Version 2.0.1
=============
@@ -1230,8 +1245,7 @@
libraries, models, config files, etc. in a single "package"
directory. See the :doc:`Loader class <libraries/loader>`
documentation for more details.
- - In-development code is now hosted at
- `BitBucket <http://bitbucket.org/ellislab/codeigniter-reactor/>`_.
+ - In-development code is now hosted at BitBucket .
- Removed the deprecated Validation Class.
- Added CI\_ Prefix to all core classes.
- Package paths can now be set in application/config/autoload.php.
@@ -1373,7 +1387,7 @@
precision.
- Added alpha, and sha1 string types to random_string() in the
:doc:`String Helper <helpers/string_helper>`.
- - Modified prep_url() so as to not prepend http:// if the supplied
+ - Modified prep_url() so as to not prepend http:// if the supplied
string already has a scheme.
- Modified get_file_info in the file helper, changing filectime()
to filemtime() for dates.
@@ -2113,7 +2127,7 @@
instantiating new Language and Exception objects, and not using the
error heading.
- Fixed a bug (#4413) where a URI containing slashes only e.g.
- 'http://example.com/index.php?//' would result in PHP errors
+ 'http://example.com/index.php?//' would result in PHP errors
- Fixed an array to string conversion error in the Validation library
(#4425)
- Fixed bug (#4451, #4299, #4339) where failed transactions will not
@@ -2765,8 +2779,7 @@
the core files.
- Added the ability to organize controller files :doc:`into
sub-folders <general/controllers>`. Kudos to Marco for
- `suggesting <http://codeigniter.com/forums/viewthread/627/>`_ this
- (and the next two) feature.
+ suggesting this (and the next two) feature.
- Added regular expressions support for :doc:`routing
rules <./general/routing>`.
- Added the ability to :doc:`remap function
diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py
index d65fe0d..1704654 100644
--- a/user_guide_src/source/conf.py
+++ b/user_guide_src/source/conf.py
@@ -48,9 +48,9 @@
# built documents.
#
# The short X.Y version.
-version = '3.0'
+version = '3.0.1'
# The full version, including alpha/beta/rc tags.
-release = '3.0-dev'
+release = '3.0.0-dev'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/user_guide_src/source/contributing/index.rst b/user_guide_src/source/contributing/index.rst
index e881477..0112ca0 100644
--- a/user_guide_src/source/contributing/index.rst
+++ b/user_guide_src/source/contributing/index.rst
@@ -10,9 +10,8 @@
CodeIgniter is a community driven project and accepts contributions of code
and documentation from the community. These contributions are made in the form
-of Issues or `Pull Requests <http://help.github.com/send-pull-requests/>`_ on
-the `CodeIgniter repository
-<https://github.com/bcit-ci/CodeIgniter>`_ on GitHub.
+of Issues or `Pull Requests <https://help.github.com/articles/using-pull-requests/>`_
+on the `CodeIgniter repository <https://github.com/bcit-ci/CodeIgniter>`_ on GitHub.
Issues are a quick way to point out a bug. If you find a bug or documentation
error in CodeIgniter then please check a few things first:
@@ -75,7 +74,7 @@
=========
All code must meet the `Style Guide
-<http://codeigniter.com/user_guide/general/styleguide.html>`_, which is
+<http://www.codeigniter.com/userguide3/general/styleguide.html>`_, which is
essentially the `Allman indent style
<http://en.wikipedia.org/wiki/Indent_style#Allman_style>`_, underscores and
readable operators. This makes certain that all code is the same format as the
diff --git a/user_guide_src/source/database/configuration.rst b/user_guide_src/source/database/configuration.rst
index 0747256..d21c79e 100644
--- a/user_guide_src/source/database/configuration.rst
+++ b/user_guide_src/source/database/configuration.rst
@@ -27,7 +27,6 @@
'char_set' => 'utf8',
'dbcollat' => 'utf8_general_ci',
'swap_pre' => '',
- 'autoinit' => TRUE,
'encrypt' => FALSE,
'compress' => FALSE,
'stricton' => FALSE,
@@ -70,7 +69,6 @@
'char_set' => 'utf8',
'dbcollat' => 'utf8_general_ci',
'swap_pre' => '',
- 'autoinit' => TRUE,
'encrypt' => FALSE,
'compress' => FALSE,
'stricton' => FALSE
@@ -89,7 +87,6 @@
'char_set' => 'utf8',
'dbcollat' => 'utf8_general_ci',
'swap_pre' => '',
- 'autoinit' => TRUE,
'encrypt' => FALSE,
'compress' => FALSE,
'stricton' => FALSE
@@ -120,7 +117,6 @@
'char_set' => 'utf8',
'dbcollat' => 'utf8_general_ci',
'swap_pre' => '',
- 'autoinit' => TRUE,
'compress' => FALSE,
'encrypt' => FALSE,
'stricton' => FALSE,
@@ -181,8 +177,6 @@
**swap_pre** A default table prefix that should be swapped with dbprefix. This is useful for distributed
applications where you might run manually written queries, and need the prefix to still be
customizable by the end user.
-**autoinit** Whether or not to automatically connect to the database when the library loads. If set to false,
- the connection will take place prior to executing the first query.
**schema** The database schema, defaults to 'public'. Used by PostgreSQL and ODBC drivers.
**encrypt** Whether or not to use an encrypted connection.
**compress** Whether or not to use client compression (MySQL only).
diff --git a/user_guide_src/source/database/forge.rst b/user_guide_src/source/database/forge.rst
index 89fac02..a4edada 100644
--- a/user_guide_src/source/database/forge.rst
+++ b/user_guide_src/source/database/forge.rst
@@ -227,7 +227,7 @@
$this->dbforge->drop_table('table_name');
// Produces: DROP TABLE IF EXISTS table_name
- $this->dbforge->drop_table('table_name');
+ $this->dbforge->drop_table('table_name',TRUE);
Renaming a table
@@ -405,4 +405,4 @@
:returns: TRUE on success, FALSE on failure
:rtype: bool
- Renames a table. Usage: See `Renaming a table`_.
\ No newline at end of file
+ Renames a table. Usage: See `Renaming a table`_.
diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst
index fa1e903..0a6d987 100644
--- a/user_guide_src/source/database/query_builder.rst
+++ b/user_guide_src/source/database/query_builder.rst
@@ -520,13 +520,19 @@
Permits you to determine the number of rows in a particular Active
Record query. Queries will accept Query Builder restrictors such as
-where(), or_where(), like(), or_like(), etc. Example::
+``where()``, ``or_where()``, ``like()``, ``or_like()``, etc. Example::
echo $this->db->count_all_results('my_table'); // Produces an integer, like 25
$this->db->like('title', 'match');
$this->db->from('my_table');
echo $this->db->count_all_results(); // Produces an integer, like 17
+However, this method also resets any field values that you may have passed
+to ``select()``. If you need to keep them, you can pass ``FALSE`` as the
+second parameter::
+
+ echo $this->db->count_all_results('my_table', FALSE);
+
**$this->db->count_all()**
Permits you to determine the number of rows in a particular table.
@@ -1091,9 +1097,10 @@
Prepends a database prefix, if one exists in configuration.
- .. php:method:: count_all_results([$table = ''])
+ .. php:method:: count_all_results([$table = '', [$reset = TRUE]])
:param string $table: Table name
+ :param bool $reset: Whether to reset values for SELECTs
:returns: Number of rows in the query result
:rtype: int
@@ -1221,7 +1228,7 @@
:param string $key: The field to search
:param array $values: The values searched on
- :param boolean $escape: Whether to escape values and identifiers
+ :param boolean $escape: Whether to escape identifiers
:returns: DB_query_builder instance
:rtype: object
@@ -1232,7 +1239,7 @@
:param string $key: The field to search
:param array $values: The values searched on
- :param boolean $escape: Whether to escape values and identifiers
+ :param boolean $escape: Whether to escape identifiers
:returns: DB_query_builder instance
:rtype: object
@@ -1243,7 +1250,7 @@
:param string $key: Name of field to examine
:param array $values: Array of target values
- :param boolean $escape: Whether to escape values and identifiers
+ :param boolean $escape: Whether to escape identifiers
:returns: DB_query_builder instance
:rtype: object
@@ -1254,7 +1261,7 @@
:param string $key: Name of field to examine
:param array $values: Array of target values
- :param boolean $escape: Whether to escape values and identifiers
+ :param boolean $escape: Whether to escape 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 a22c2e8..ac44566 100644
--- a/user_guide_src/source/database/results.rst
+++ b/user_guide_src/source/database/results.rst
@@ -102,7 +102,7 @@
to instantiate the row with::
$query = $this->db->query("SELECT * FROM users LIMIT 1;");
- $query->row(0, 'User');
+ $row = $query->row(0, 'User');
echo $row->name; // access attributes
echo $row->reverse_name(); // or methods defined on the 'User' class
@@ -431,4 +431,4 @@
:rtype: array
Returns an array containing the field names in the
- result set.
\ No newline at end of file
+ result set.
diff --git a/user_guide_src/source/database/utilities.rst b/user_guide_src/source/database/utilities.rst
index bafa08e..cc4aeb0 100644
--- a/user_guide_src/source/database/utilities.rst
+++ b/user_guide_src/source/database/utilities.rst
@@ -295,7 +295,7 @@
Repairs a database table.
- .. php:method:: csv_from_results($query[, $delim = ','[, $newline = "\n"[, $enclosure = '"']]])
+ .. php:method:: csv_from_result($query[, $delim = ','[, $newline = "\n"[, $enclosure = '"']]])
:param object $query: A database result object
:param string $delim: The CSV field delimiter to use
@@ -306,11 +306,11 @@
Translates a database result object into a CSV document.
- .. php:method:: xml_from_results($query[, $params = array()])
+ .. php:method:: xml_from_result($query[, $params = array()])
:param object $query: A database result object
:param array $params: An associative array of preferences
:returns: The generated XML document as a string
:rtype: string
- Translates a database result object into an XML document.
\ No newline at end of file
+ Translates a database result object into an XML document.
diff --git a/user_guide_src/source/general/ancillary_classes.rst b/user_guide_src/source/general/ancillary_classes.rst
index 6a64742..f1285d9 100644
--- a/user_guide_src/source/general/ancillary_classes.rst
+++ b/user_guide_src/source/general/ancillary_classes.rst
@@ -11,7 +11,8 @@
.. php:function:: get_instance()
- :returns: object of class CI_Controller
+ :returns: Reference to your controller's instance
+ :rtype: CI_Controller
**Any class that you instantiate within your controller methods can
access CodeIgniter's native resources** simply by using the
@@ -44,17 +45,9 @@
$CI->config->item('base_url');
// etc.
-.. note:: You'll notice that the above get_instance() ``function`` is being
- passed by reference::
-
- $CI =& get_instance();
-
- This is very important. Assigning by reference allows you to use the
- original CodeIgniter object rather than creating a copy of it.
-
-Furthermore, if you'll be using ``get_instance()`` inside another class,
-then it would be better if you assign it to a property. This way, you
-won't need to call ``get_instance()`` in every single method.
+If you'll be using ``get_instance()`` inside another class, then it would
+be better if you assign it to a property. This way, you won't need to call
+``get_instance()`` in every single method.
Example::
@@ -80,9 +73,8 @@
{
$this->CI->config->item('base_url');
}
-
}
In the above example, both methods ``foo()`` and ``bar()`` will work
after you instantiate the Example class, without the need to call
-``get_instance()`` in each of them.
\ No newline at end of file
+``get_instance()`` in each of them.
diff --git a/user_guide_src/source/general/credits.rst b/user_guide_src/source/general/credits.rst
index d22e3a9..d0f14b3 100644
--- a/user_guide_src/source/general/credits.rst
+++ b/user_guide_src/source/general/credits.rst
@@ -2,17 +2,17 @@
Credits
#######
-CodeIgniter was originally developed by `Rick Ellis <http://www.ellislab.com/>`_
-(CEO of `EllisLab, Inc. <http://ellislab.com/>`_). The framework was written for
+CodeIgniter was originally developed by `Rick Ellis <https://ellislab.com/>`_
+(CEO of `EllisLab, Inc. <https://ellislab.com/>`_). The framework was written for
performance in the real world, with many of the class libraries, helpers, and
sub-systems borrowed from the code-base of `ExpressionEngine
-<http://www.expressionengine.com/>`_.
+<https://ellislab.com/expressionengine>`_.
It was, for years, developed and maintained by EllisLab, the ExpressionEngine
Development Team and a group of community members called the Reactor Team.
In 2014, CodeIgniter was acquired by the `British Columbia Institute of Technology
-<http://bcit.ca/>`_ and was then officially announced as a community-maintained
+<http://www.bcit.ca/>`_ and was then officially announced as a community-maintained
project.
Bleeding edge development is spearheaded by the handpicked contributors
diff --git a/user_guide_src/source/general/environments.rst b/user_guide_src/source/general/environments.rst
index 1ce4fde..f5a4f61 100644
--- a/user_guide_src/source/general/environments.rst
+++ b/user_guide_src/source/general/environments.rst
@@ -48,5 +48,5 @@
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 `Config
-Class <../libraries/config.html#environments>`_ documentation.
\ No newline at end of file
+more detail in the environment section of the :doc:`Config
+Class <../libraries/config#environments>`_ documentation.
\ No newline at end of file
diff --git a/user_guide_src/source/general/requirements.rst b/user_guide_src/source/general/requirements.rst
index e3f73db..f90cdd3 100644
--- a/user_guide_src/source/general/requirements.rst
+++ b/user_guide_src/source/general/requirements.rst
@@ -2,7 +2,7 @@
Server Requirements
###################
-`PHP <http://www.php.net/>`_ version 5.4 or newer is recommended.
+`PHP <http://php.net/>`_ version 5.4 or newer is recommended.
It should work on 5.2.4 as well, but we strongly advise you NOT to run
such old versions of PHP, because of potential security and performance
diff --git a/user_guide_src/source/general/security.rst b/user_guide_src/source/general/security.rst
index 0c58f96..fcfe4c2 100644
--- a/user_guide_src/source/general/security.rst
+++ b/user_guide_src/source/general/security.rst
@@ -133,17 +133,25 @@
provides them for you as long as you're running at least PHP version
5.3.7 (and if you don't meet that requirement - please, upgrade).
+ If you're one of the really unlucky people who can't even upgrade to a
+ more recent PHP version, use `hash_pbkdf() <http://php.net/hash_pbkdf2>`,
+ which we also provide in our compatibility layer.
+
- DO NOT ever display or send a password in plain-text format!
Even to the password's owner, if you need a "Forgotten password"
feature, just randomly generate a new, one-time (this is also important)
password and send that instead.
-- DO NOT put artificial limits on your users' passwords.
+- DO NOT put unnecessary limits on your users' passwords.
- There's no point in forcing a rule that a password can only be up to
- a number of characters, or that it can't contain a certain set of
- special characters.
+ If you're using a hashing algorithm other than BCrypt (which has a limit
+ of 72 characters), you should set a relatively high limit on password
+ lengths in order to mitigate DoS attacks - say, 1024 characters.
+
+ Other than that however, there's no point in forcing a rule that a
+ password can only be up to a number of characters, or that it can't
+ contain a certain set of special characters.
Not only does this **reduce** security instead of improving it, but
there's literally no reason to do it. No technical limitations and
diff --git a/user_guide_src/source/helpers/date_helper.rst b/user_guide_src/source/helpers/date_helper.rst
index bed3b32..e0f9f00 100644
--- a/user_guide_src/source/helpers/date_helper.rst
+++ b/user_guide_src/source/helpers/date_helper.rst
@@ -50,7 +50,7 @@
:returns: MySQL-formatted date
:rtype: string
- This function is identical to PHP's `date() <http://www.php.net/date>`_
+ This function is identical to PHP's `date() <http://php.net/manual/en/function.date.php>`_
function, except that it lets you use MySQL style date codes, where each
code letter is preceded with a percent sign, e.g. `%Y %m %d`
@@ -84,7 +84,7 @@
.. note:: This function is DEPRECATED. Use the native ``date()`` combined with
`DateTime's format constants
- <http://www.php.net/manual/en/class.datetime.php#datetime.constants.types>`_
+ <http://php.net/manual/en/class.datetime.php#datetime.constants.types>`_
instead::
echo date(DATE_RFC822, time());
diff --git a/user_guide_src/source/helpers/email_helper.rst b/user_guide_src/source/helpers/email_helper.rst
index 6852269..1ee97d9 100644
--- a/user_guide_src/source/helpers/email_helper.rst
+++ b/user_guide_src/source/helpers/email_helper.rst
@@ -62,7 +62,7 @@
:returns: TRUE if the mail was successfully sent, FALSE in case of an error
:rtype: bool
- Sends an email using PHP's native `mail() <http://www.php.net/function.mail>`_
+ Sends an email using PHP's native `mail() <http://php.net/function.mail>`_
function.
.. note:: All that this function does is to use PHP's native ``mail``
diff --git a/user_guide_src/source/helpers/file_helper.rst b/user_guide_src/source/helpers/file_helper.rst
index 92cb31a..833cdde 100644
--- a/user_guide_src/source/helpers/file_helper.rst
+++ b/user_guide_src/source/helpers/file_helper.rst
@@ -76,7 +76,7 @@
write_file('./path/to/file.php', $data, 'r+');
- The default mode is 'wb'. Please see the `PHP user guide <http://php.net/fopen>`_
+ The default mode is 'wb'. Please see the `PHP user guide <http://php.net/manual/en/function.fopen.php>`_
for mode options.
.. note: In order for this function to write data to a file, its permissions must
diff --git a/user_guide_src/source/helpers/form_helper.rst b/user_guide_src/source/helpers/form_helper.rst
index 4706ee7..9ddca89 100644
--- a/user_guide_src/source/helpers/form_helper.rst
+++ b/user_guide_src/source/helpers/form_helper.rst
@@ -571,10 +571,11 @@
// Would produce: </form> </div></div>
-.. php:function:: set_value($field[, $default = ''])
+.. php:function:: set_value($field[, $default = ''[, $html_escape = TRUE]])
:param string $field: Field name
:param string $default: Default value
+ :param bool $html_escape: Whether to turn off HTML escaping of the value
:returns: Field value
:rtype: string
diff --git a/user_guide_src/source/helpers/html_helper.rst b/user_guide_src/source/helpers/html_helper.rst
index d35be39..8861101 100644
--- a/user_guide_src/source/helpers/html_helper.rst
+++ b/user_guide_src/source/helpers/html_helper.rst
@@ -29,7 +29,7 @@
:param string $data: Content
:param string $h: Heading level
- :param array $attributes: HTML attributes
+ :param mixed $attributes: HTML attributes
:returns: HTML heading tag
:rtype: string
@@ -41,15 +41,18 @@
The above would produce: <h3>Welcome!</h3>
Additionally, in order to add attributes to the heading tag such as HTML
- classes, ids or inline styles, a third parameter is available::
+ classes, ids or inline styles, a third parameter accepts either a string
+ or an array::
- echo heading('Welcome!', 3, 'class="pink"')
+ echo heading('Welcome!', 3, 'class="pink"');
+ echo heading('How are you?', 4, array('id' => 'question', 'class' => 'green'));
The above code produces:
.. code-block:: html
<h3 class="pink">Welcome!<h3>
+ <h4 id="question" class="green">How are you?</h4>
.. php:function:: img([$src = ''[, $index_page = FALSE[, $attributes = '']]])
@@ -401,4 +404,4 @@
.. note:: This function is DEPRECATED. Use the native ``str_repeat()``
- in combination with `` `` instead.
\ No newline at end of file
+ in combination with `` `` instead.
diff --git a/user_guide_src/source/helpers/smiley_helper.rst b/user_guide_src/source/helpers/smiley_helper.rst
index 978d11e..3e76699 100644
--- a/user_guide_src/source/helpers/smiley_helper.rst
+++ b/user_guide_src/source/helpers/smiley_helper.rst
@@ -43,7 +43,7 @@
View as described.
.. important:: Before you begin, please `download the smiley images
- <http://ellislab.com/asset/ci_download_files/smileys.zip>`_
+ <https://ellislab.com/asset/ci_download_files/smileys.zip>`_
and put them in a publicly accessible place on your server.
This helper also assumes you have the smiley replacement array
located at `application/config/smileys.php`
diff --git a/user_guide_src/source/helpers/string_helper.rst b/user_guide_src/source/helpers/string_helper.rst
index 9d0d890..a1acb21 100644
--- a/user_guide_src/source/helpers/string_helper.rst
+++ b/user_guide_src/source/helpers/string_helper.rst
@@ -124,7 +124,7 @@
:rtype: string
Converts double slashes in a string to a single slash, except those
- found in URL protocol prefixes (e.g. http://).
+ found in URL protocol prefixes (e.g. http://).
Example::
diff --git a/user_guide_src/source/helpers/url_helper.rst b/user_guide_src/source/helpers/url_helper.rst
index 83864d9..64deae2 100644
--- a/user_guide_src/source/helpers/url_helper.rst
+++ b/user_guide_src/source/helpers/url_helper.rst
@@ -144,7 +144,7 @@
be a string or an array.
.. note:: If you are building links that are internal to your application
- do not include the base URL (http://...). This will be added
+ do not include the base URL (http://...). This will be added
automatically from the information specified in your config file.
Include only the URI segments you wish appended to the URL.
@@ -317,7 +317,7 @@
:returns: Protocol-prefixed URL string
:rtype: string
- This function will add http:// in the event that a protocol prefix
+ This function will add http:// in the event that a protocol prefix
is missing from a URL.
Pass the URL string to the function like this::
diff --git a/user_guide_src/source/installation/downloads.rst b/user_guide_src/source/installation/downloads.rst
index 3b4ebe6..e2b6a9c 100644
--- a/user_guide_src/source/installation/downloads.rst
+++ b/user_guide_src/source/installation/downloads.rst
@@ -2,14 +2,14 @@
Downloading CodeIgniter
#######################
-- `CodeIgniter v3.0.0 (Current version) <https://github.com/bcit-ci/CodeIgniter/archive/develop.zip>`_
-- `CodeIgniter v2.2.1 <https://github.com/bcit-ci/CodeIgniter/archive/2.2.1.zip>`_
-- `CodeIgniter v2.2.0 <https://github.com/bcit-ci/CodeIgniter/archive/2.2.0.zip>`_
-- `CodeIgniter v2.1.4 <https://github.com/bcit-ci/CodeIgniter/archive/2.1.4.zip>`_
-- `CodeIgniter v2.1.3 <https://github.com/bcit-ci/CodeIgniter/archive/2.1.3.zip>`_
-- `CodeIgniter v2.1.2 <https://github.com/bcit-ci/CodeIgniter/archive/2.1.2.zip>`_
-- `CodeIgniter v2.1.1 <https://github.com/bcit-ci/CodeIgniter/archive/2.1.1.zip>`_
-- `CodeIgniter v2.1.0 <https://github.com/bcit-ci/CodeIgniter/archive/v2.1.0.zip>`_
+- `CodeIgniter v3.0.0 (Current version) <https://codeload.github.com/bcit-ci/CodeIgniter/zip/develop>`_
+- `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>`_
+- `CodeIgniter v2.1.3 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/2.1.3>`_
+- `CodeIgniter v2.1.2 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/2.1.2>`_
+- `CodeIgniter v2.1.1 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/2.1.1>`_
+- `CodeIgniter v2.1.0 <https://codeload.github.com/bcit-ci/CodeIgniter/zip/v2.1.0>`_
******
GitHub
diff --git a/user_guide_src/source/installation/troubleshooting.rst b/user_guide_src/source/installation/troubleshooting.rst
index 0dfd408..e874bb0 100644
--- a/user_guide_src/source/installation/troubleshooting.rst
+++ b/user_guide_src/source/installation/troubleshooting.rst
@@ -4,16 +4,15 @@
If you find that no matter what you put in your URL only your default
page is loading, it might be that your server does not support the
-PATH_INFO variable needed to serve search-engine friendly URLs. As a
+REQUEST_URI variable needed to serve search-engine friendly URLs. As a
first step, open your application/config/config.php file and look for
the URI Protocol information. It will recommend that you try a couple
alternate settings. If it still doesn't work after you've tried this
you'll need to force CodeIgniter to add a question mark to your URLs. To
-do this open your application/config/config.php file and change this::
+do this open your **application/config/config.php** file and change this::
$config['index_page'] = "index.php";
To this::
$config['index_page'] = "index.php?";
-
diff --git a/user_guide_src/source/installation/upgrade_200.rst b/user_guide_src/source/installation/upgrade_200.rst
index ca2c6c1..03b8ff4 100644
--- a/user_guide_src/source/installation/upgrade_200.rst
+++ b/user_guide_src/source/installation/upgrade_200.rst
@@ -64,8 +64,8 @@
replace stale encrypted data with fresh in your applications, either on
the fly or en masse.
-Please read `how to use this
-method <../libraries/encrypt.html#legacy>`_ in the Encrypt library
+Please read :doc:`how to use this
+method <../libraries/encrypt>` in the Encrypt library
documentation.
Step 5: Remove loading calls for the compatibility helper.
diff --git a/user_guide_src/source/installation/upgrade_300.rst b/user_guide_src/source/installation/upgrade_300.rst
index 8983f3d..a3d7124 100644
--- a/user_guide_src/source/installation/upgrade_300.rst
+++ b/user_guide_src/source/installation/upgrade_300.rst
@@ -1,9 +1,7 @@
#############################
-Upgrading from 2.2.1 to 3.0.0
+Upgrading from 2.2.x to 3.0.0
#############################
-.. note:: These upgrade notes are for a version that is yet to be released.
-
Before performing an update you should take your site offline by replacing the index.php file with a static one.
*************************************
@@ -212,26 +210,63 @@
It is safe to move your old templates from _application/errors* to _application/views/errors/html*,
but you'll have to copy the new _application/views/errors/cli* directory from the CodeIgniter archive.
-*******************************************************
-Step 9: Update your config/routes.php containing (:any)
-*******************************************************
+******************************************
+Step 9: Update your config/routes.php file
+******************************************
-Historically, CodeIgniter has always provided the **:any** wildcard in routing,
-with the intention of providing a way to match any character **within** an URI segment.
+Routes containing :any
+======================
-However, the **:any** wildcard is actually just an alias for a regular expression
-and used to be executed in that manner as **.+**. This is considered a bug, as it
-also matches the / (forward slash) character, which is the URI segment delimiter
-and that was never the intention. In CodeIgniter 3, the **:any** wildcard will now
-represent **[^/]+**, so that it will not match a forward slash.
+Historically, CodeIgniter has always provided the **:any** wildcard in
+routing, with the intention of providing a way to match any character
+**within** an URI segment.
-There are certainly many developers that have utilized this bug as an actual feature.
-If you're one of them and want to match a forward slash, please use the **.+**
-regular expression::
+However, the **:any** wildcard is actually just an alias for a regular
+expression and used to be executed in that manner as **.+**. This is
+considered a bug, as it also matches the / (forward slash) character, which
+is the URI segment delimiter and that was never the intention.
+
+In CodeIgniter 3, the **:any** wildcard will now represent **[^/]+**, so
+that it will not match a forward slash.
+
+There are certainly many developers that have utilized this bug as an actual
+feature. If you're one of them and want to match a forward slash, please use
+the **.+** regular expression::
(.+) // matches ANYTHING
(:any) // matches any character, except for '/'
+Directories and 'default_controller', '404_override'
+====================================================
+
+As you should know, the ``$route['default_controller']`` and
+``$route['404_override']`` settings accept not only a controller name, but
+also *controller/method* pairs. However, a bug in the routing logic has
+made it possible for some users to use that as *directory/controller*
+instead.
+
+As already said, this behavior was incidental and was never intended, nor
+documented. If you've relied on it, your application will break with
+CodeIgniter 3.0.
+
+Another notable change in version 3 is that 'default_controller' and
+'404_override' are now applied *per directory*. To explain what this means,
+let's take the following example::
+
+ $route['default_controller'] = 'main';
+
+Now, assuming that your website is located at *example.com*, you already
+know that if a user visits ``http://example.com/``, the above setting will
+cause your 'Main' controller to be loaded.
+
+However, what happens if you have an *application/controllers/admin/*
+directory and the user visits ``http://example.com/admin/``?
+In CodeIgniter 3, the router will look for a 'Main' controller under the
+admin/ directory as well. If not found, it will fallback to the parent
+(*application/controllers/*) directory, like in version 2.x.
+
+The same rule applies to the '404_override' setting.
+
*************************************************************************
Step 10: Many functions now return NULL instead of FALSE on missing items
*************************************************************************
@@ -514,6 +549,22 @@
.. note:: This function is still available, but you're strongly encouraged to remove its usage sooner
rather than later.
+The $config['global_xss_filtering'] setting
+===========================================
+
+As already explained above, XSS filtering should not be done on input data,
+but on output instead. Therefore, the ``$config['global_xss_filtering']``,
+which automatically filters *input* data, is considered a bad practice and
+is now deprecated.
+
+Instead, you should manually escape any user-provided data via the
+:php:func:`xss_clean()` function when you need to output it, or use a
+library like `HTML Purifier <http://htmlpurifier.org/>`_ that does that
+for you.
+
+.. note:: The setting is still available, but you're strongly encouraged to
+ remove its usage sooner rather than later.
+
File helper read_file()
=======================
@@ -574,7 +625,7 @@
===========================
:doc:`Date Helper <../helpers/date_helper>` function ``standard_date()`` is being deprecated due
-to the availability of native PHP `constants <http://www.php.net/manual/en/class.datetime.php#datetime.constants.types>`_,
+to the availability of native PHP `constants <http://php.net/manual/en/class.datetime.php#datetime.constants.types>`_,
which when combined with ``date()`` provide the same functionality. Furthermore, they have the
exact same names as the ones supported by ``standard_date()``. Here are examples of how to replace
its usage:
@@ -758,7 +809,7 @@
sooner rather than later.
***********************************************************
-Step 18: Check your usage of Text helper highlight_phrase()
+Step 20: Check your usage of Text helper highlight_phrase()
***********************************************************
The default HTML tag used by :doc:`Text Helper <../helpers/text_helper>` function
diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst
index ab36e9b..89e90e7 100644
--- a/user_guide_src/source/installation/upgrading.rst
+++ b/user_guide_src/source/installation/upgrading.rst
@@ -8,7 +8,7 @@
.. toctree::
:titlesonly:
- Upgrading from 2.2.1 to 3.0.0 <upgrade_300>
+ Upgrading from 2.2.x to 3.0.0 <upgrade_300>
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.3 to 2.1.4 <upgrade_214>
diff --git a/user_guide_src/source/libraries/caching.rst b/user_guide_src/source/libraries/caching.rst
index 86439b4..f54de5f 100644
--- a/user_guide_src/source/libraries/caching.rst
+++ b/user_guide_src/source/libraries/caching.rst
@@ -250,8 +250,7 @@
=============
Redis is an in-memory key-value store which can operate in LRU cache mode.
-To use it, you need Redis server and phpredis PHP extension
-`https://github.com/nicolasff/phpredis <https://github.com/nicolasff/phpredis>`_.
+To use it, you need `Redis server and phpredis PHP extension <https://github.com/phpredis/phpredis>`_.
Config options to connect to redis server must be stored in the application/config/redis.php file.
Available options are::
diff --git a/user_guide_src/source/libraries/encryption.rst b/user_guide_src/source/libraries/encryption.rst
index d445bf4..599be4d 100644
--- a/user_guide_src/source/libraries/encryption.rst
+++ b/user_guide_src/source/libraries/encryption.rst
@@ -2,6 +2,11 @@
Encryption Library
##################
+.. important:: DO NOT use this or any other *encryption* library for
+ user password storage! Passwords must be *hashed* instead, and you
+ should do that via PHP's own `Password Hashing extension
+ <http://php.net/password>`_.
+
The Encryption Library provides two-way data encryption. To do so in
a cryptographically secure way, it utilizes PHP extensions that are
unfortunately not always available on all systems.
@@ -106,6 +111,18 @@
$config['encryption_key'] = 'YOUR KEY';
+You'll notice that the ``create_key()`` method outputs binary data, which
+is hard to deal with (i.e. a copy-paste may damage it), so you may use
+``bin2hex()``, ``hex2bin()`` or Base64-encoding to work with the key in
+a more friendly manner. For example::
+
+ // Get a hex-encoded representation of the key:
+ $key = bin2hex($this->encryption->create_key(16));
+
+ // Put the same value in your config with hex2bin(),
+ // so that it is still passed as binary to the library:
+ $config['encryption_key'] = hex2bin(<your hex-encoded key>);
+
.. _ciphers-and-modes:
Supported encryption ciphers and modes
@@ -465,7 +482,7 @@
MD5 or SHA1 is that they are no longer considered secure enough
and as such, we don't want to encourage their usage.
If you absolutely need to use them, it is easy to do so via PHP's
-native `hash_hmac() <http://php.net/hash_hmac()>`_ function.
+native `hash_hmac() <http://php.net/manual/en/function.hash-hmac.php>`_ function.
Stronger algorithms of course will be added in the future as they
appear and become widely available.
@@ -525,6 +542,15 @@
Please refer to the :ref:`custom-parameters` secrion for information
on the optional parameters.
+ .. php:method:: create_key($length)
+
+ :param int $length: Output length
+ :returns: A pseudo-random cryptographic key with the specified length, or FALSE on failure
+ :rtype: string
+
+ Creates a cryptographic key by fetching random data from
+ the operating system's sources (i.e. /dev/urandom).
+
.. php:method:: hkdf($key[, $digest = 'sha512'[, $salt = NULL[, $length = NULL[, $info = '']]]])
:param string $key: Input key material
diff --git a/user_guide_src/source/libraries/input.rst b/user_guide_src/source/libraries/input.rst
index 967f69d..d9c6c2d 100644
--- a/user_guide_src/source/libraries/input.rst
+++ b/user_guide_src/source/libraries/input.rst
@@ -53,6 +53,10 @@
Please refer to the :doc:`Security class <security>` documentation for
information on using XSS Filtering in your application.
+.. important:: The 'global_xss_filtering' setting is DEPRECATED and kept
+ solely for backwards-compatibility purposes. XSS escaping should
+ be performed on *output*, not *input*!
+
*******************
Accessing form data
*******************
@@ -91,8 +95,14 @@
and access multiple variables without caring that you might only have
one shot at all of the POST data.
-CodeIgniter will take care of that for you, and you can access data
-from the **php://input** stream at any time, just by calling the
+CodeIgniter will take care of that for you, and you can read the data
+from the **php://input** stream at any time, just by using the
+``$raw_input_stream`` property::
+
+ $this->input->raw_input_stream;
+
+Additionally if the input stream is form-encoded like $_POST you can
+access its values by calling the
``input_stream()`` method::
$this->input->input_stream('key');
@@ -114,6 +124,12 @@
.. php:class:: CI_Input
+ .. attribute:: $raw_input_stream
+
+ Read only property that will return php://input data as is.
+
+ The property can be read multiple times.
+
.. php:method:: post([$index = NULL[, $xss_clean = NULL]])
:param mixed $index: POST parameter name
diff --git a/user_guide_src/source/libraries/javascript.rst b/user_guide_src/source/libraries/javascript.rst
index 7f83b2f..e91b9ad 100644
--- a/user_guide_src/source/libraries/javascript.rst
+++ b/user_guide_src/source/libraries/javascript.rst
@@ -135,7 +135,7 @@
keydown, keyup, load, mousedown, mouseup, mouseover, mouseup, resize,
scroll, or unload.
- "element_path" is any valid `jQuery selector
- <http://docs.jquery.com/Selectors>`_. Due to jQuery's unique
+ <http://api.jquery.com/category/selectors/>`_. Due to jQuery's unique
selector syntax, this is usually an element id, or CSS selector. For
example "#notice_area" would effect ``<div id="notice_area">``, and
"#content a.notice" would effect all anchors with a class of "notice"
@@ -147,7 +147,7 @@
=======
The query library supports a powerful
-`Effects <http://docs.jquery.com/Effects>`_ repertoire. Before an effect
+`Effects <http://api.jquery.com/category/effects/>`_ repertoire. Before an effect
can be used, it must be loaded::
$this->jquery->effect([optional path] plugin name); // for example $this->jquery->effect('bounce');
@@ -201,7 +201,7 @@
other additional information.
For a full summary, see
-`http://docs.jquery.com/Effects/animate <http://docs.jquery.com/Effects/animate>`_
+`http://api.jquery.com/animate/ <http://api.jquery.com/animate/>`_
Here is an example of an animate() called on a div with an id of "note",
and triggered by a click using the jQuery library's click() event.
@@ -288,7 +288,7 @@
--------
Used to add distinct corners to page elements. For full details see
-`http://www.malsup.com/jquery/corner/ <http://www.malsup.com/jquery/corner/>`_
+`http://malsup.com/jquery/corner/ <http://malsup.com/jquery/corner/>`_
::
diff --git a/user_guide_src/source/libraries/language.rst b/user_guide_src/source/libraries/language.rst
index ee1cefc..de17c82 100644
--- a/user_guide_src/source/libraries/language.rst
+++ b/user_guide_src/source/libraries/language.rst
@@ -19,7 +19,7 @@
The CodeIgniter framework comes with a set of language files for the "english" idiom.
Additional approved translations for different idioms may be found in the
-`CodeIgniter 3 Translations repositories <https://github.com/codeigniter3-translations>`_.
+`CodeIgniter 3 Translations repositories <https://github.com/bcit-ci/codeigniter3-translations>`_.
Each repository deals with a single idiom.
When CodeIgniter loads language files, it will load the one in **system/language/**
diff --git a/user_guide_src/source/libraries/loader.rst b/user_guide_src/source/libraries/loader.rst
index efa9d51..228d5e4 100644
--- a/user_guide_src/source/libraries/loader.rst
+++ b/user_guide_src/source/libraries/loader.rst
@@ -238,7 +238,7 @@
The second **optional** parameter can take an associative array or an
object as input, which it runs through the PHP
- `extract() <http://www.php.net/extract>`_ function to convert to variables
+ `extract() <http://php.net/extract>`_ function to convert to variables
that can be used in your view files. Again, read the
:doc:`Views <../general/views>` page to learn how this might be useful.
@@ -259,7 +259,7 @@
:rtype: CI_Loader
This method takes an associative array as input and generates
- variables using the PHP `extract() <http://www.php.net/extract>`_
+ variables using the PHP `extract() <http://php.net/extract>`_
function. This method produces the same result as using the second
parameter of the ``$this->load->view()`` method above. The reason you
might want to use this method independently is if you would like to
diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst
index 27e6e56..ac56fc5 100644
--- a/user_guide_src/source/libraries/security.rst
+++ b/user_guide_src/source/libraries/security.rst
@@ -41,9 +41,6 @@
$config['global_xss_filtering'] = TRUE;
-.. note:: If you use the form validation class, it gives you the option of
- XSS filtering as well.
-
An optional second parameter, *is_image*, allows this function to be used
to test images for potential XSS attacks, useful for file upload
security. When this second parameter is set to TRUE, instead of
diff --git a/user_guide_src/source/libraries/sessions.rst b/user_guide_src/source/libraries/sessions.rst
index c8a1f19..2034ed2 100644
--- a/user_guide_src/source/libraries/sessions.rst
+++ b/user_guide_src/source/libraries/sessions.rst
@@ -363,7 +363,7 @@
.. important:: The ``userdata()`` method will NOT return tempdata items.
-Or if you want to be sure that you're reading "flashdata" (and not any
+Or if you want to be sure that you're reading "tempdata" (and not any
other kind), you can also use the ``tempdata()`` method::
$this->session->tempdata('item');
@@ -569,9 +569,10 @@
- Only your **default** database connection (or the one that you access
as ``$this->db`` from your controllers) can be used.
- - You can NOT use a persistent connection.
- You must have the :doc:`Query Builder </database/query_builder>`
enabled.
+ - You can NOT use a persistent connection.
+ - You can NOT use a connection with the *cache_on* setting enabled.
In order to use the 'database' session driver, you must also create this
table that we already mentioned and then set it as your
@@ -596,7 +597,7 @@
`id` varchar(40) NOT NULL,
`ip_address` varchar(45) NOT NULL,
`timestamp` int(10) unsigned DEFAULT 0 NOT NULL,
- `data` blob DEFAULT '' NOT NULL,
+ `data` blob NOT NULL,
PRIMARY KEY (id),
KEY `ci_sessions_timestamp` (`timestamp`)
);
@@ -630,12 +631,16 @@
Redis Driver
------------
+.. note:: Since Redis doesn't have a locking mechanism exposed, locks for
+ this driver are emulated by a separate value that is kept for up
+ to 300 seconds.
+
Redis is a storage engine typically used for caching and popular because
of its high performance, which is also probably your reason to use the
'redis' session driver.
The downside is that it is not as ubiquitous as relational databases and
-requires the `phpredis <https://github.com/nicolasff/phpredis>`_ PHP
+requires the `phpredis <https://github.com/phpredis/phpredis>`_ PHP
extension to be installed on your system, and that one doesn't come
bundled with PHP.
Chances are, you're only be using the 'redis' driver only if you're already
@@ -663,6 +668,10 @@
Memcached Driver
----------------
+.. note:: Since Memcache doesn't have a locking mechanism exposed, locks
+ for this driver are emulated by a separate value that is kept for
+ up to 300 seconds.
+
The 'memcached' driver is very similar to the 'redis' one in all of its
properties, except perhaps for availability, because PHP's `Memcached
<http://php.net/memcached>`_ extension is distributed via PECL and some
@@ -828,7 +837,7 @@
.. note:: This method is DEPRECATED. Use ``userdata()``
with no parameters instead.
- .. php:method:: &get_usedata()
+ .. php:method:: &get_userdata()
:returns: A reference to ``$_SESSION``
:rtype: array
@@ -1045,4 +1054,4 @@
$this->session->foo = 'bar';
// Results in:
- // $_SESSION['foo'] = 'bar';
\ No newline at end of file
+ // $_SESSION['foo'] = 'bar';
diff --git a/user_guide_src/source/libraries/uri.rst b/user_guide_src/source/libraries/uri.rst
index ae56184..4d38c1d 100644
--- a/user_guide_src/source/libraries/uri.rst
+++ b/user_guide_src/source/libraries/uri.rst
@@ -110,7 +110,7 @@
:returns: Associative URI segments array
:rtype: array
- This method lets you turn URI segments into and associative array of
+ This method lets you turn URI segments into an associative array of
key/value pairs. Consider this URI::
index.php/user/search/name/joe/location/UK/gender/male
@@ -230,4 +230,4 @@
This method is identical to ``segment_array()``, except that it returns
the array of segments in your re-routed URI in the event you are using
- CodeIgniter's :doc:`URI Routing <../general/routing>` feature.
\ No newline at end of file
+ CodeIgniter's :doc:`URI Routing <../general/routing>` feature.
diff --git a/user_guide_src/source/overview/features.rst b/user_guide_src/source/overview/features.rst
index 8c27b14..b230be9 100644
--- a/user_guide_src/source/overview/features.rst
+++ b/user_guide_src/source/overview/features.rst
@@ -8,7 +8,7 @@
anything about the quality of the code, or the performance, or the
attention to detail, or security practices. The only way to really judge
an app is to try it and get to know the code.
-`Installing <../installation/>`_ CodeIgniter is child's play so we
+:doc:`Installing <../installation/>`_ CodeIgniter is child's play so we
encourage you to do just that. In the mean time here's a list of
CodeIgniter's main features.
diff --git a/user_guide_src/source/tutorial/create_news_items.rst b/user_guide_src/source/tutorial/create_news_items.rst
index 1f4a96d..71d2080 100644
--- a/user_guide_src/source/tutorial/create_news_items.rst
+++ b/user_guide_src/source/tutorial/create_news_items.rst
@@ -37,16 +37,16 @@
There are only two things here that probably look unfamiliar to you: the
form_open() function and the validation_errors() function.
-The first function is provided by the `form
-helper <../helpers/form_helper.html>`_ and renders the form element and
-adds extra functionality, like adding a hidden `CSRF prevention
-field <../libraries/security.html>`_. The latter is used to report
+The first function is provided by the :doc:`form
+helper <../helpers/form_helper>` and renders the form element and
+adds extra functionality, like adding a hidden :doc:`CSRF prevention
+field <../libraries/security>`. The latter is used to report
errors related to form validation.
Go back to your news controller. You're going to do two things here,
check whether the form was submitted and whether the submitted data
-passed the validation rules. You'll use the `form
-validation <../libraries/form_validation.html>`_ library to do this.
+passed the validation rules. You'll use the :doc:`form
+validation <../libraries/form_validation>` library to do this.
::
@@ -81,14 +81,14 @@
the rule. In this case the title and text fields are required.
CodeIgniter has a powerful form validation library as demonstrated
-above. You can read `more about this library
-here <../libraries/form_validation.html>`_.
+above. You can read :doc:`more about this library
+here <../libraries/form_validation>`.
Continuing down, you can see a condition that checks whether the form
validation ran successfully. If it did not, the form is displayed, if it
was submitted **and** passed all the rules, the model is called. After
this, a view is loaded to display a success message. Create a view at
-application/view/news/success.php and write a success message.
+application/views/news/success.php and write a success message.
Model
-----
@@ -117,7 +117,7 @@
This new method takes care of inserting the news item into the database.
The third line contains a new function, url\_title(). This function -
-provided by the `URL helper <../helpers/url_helper.html>`_ - strips down
+provided by the :doc:`URL helper <../helpers/url_helper>` - strips down
the string you pass it, replacing all spaces by dashes (-) and makes
sure everything is in lowercase characters. This leaves you with a nice
slug, perfect for creating URIs.
@@ -125,8 +125,8 @@
Let's continue with preparing the record that is going to be inserted
later, inside the $data array. Each element corresponds with a column in
the database table created earlier. You might notice a new method here,
-namely the post() method from the `input
-library <../libraries/input.html>`_. This method makes sure the data is
+namely the post() method from the :doc:`input
+library <../libraries/input>`. This method makes sure the data is
sanitized, protecting you from nasty attacks from others. The input
library is loaded by default. At last, you insert our $data array into
our database.
diff --git a/user_guide_src/source/tutorial/index.rst b/user_guide_src/source/tutorial/index.rst
index b1ab331..91f99c7 100644
--- a/user_guide_src/source/tutorial/index.rst
+++ b/user_guide_src/source/tutorial/index.rst
@@ -24,13 +24,13 @@
- Introduction, this page, which gives you an overview of what to
expect.
-- `Static pages <static_pages.html>`_, which will teach you the basics
+- :doc:`Static pages <static_pages>`, which will teach you the basics
of controllers, views and routing.
-- `News section <news_section.html>`_, where you'll start using models
+- :doc:`News section <news_section>`, where you'll start using models
and will be doing some basic database operations.
-- `Create news items <create_news_items.html>`_, which will introduce
+- :doc:`Create news items <create_news_items>`, which will introduce
more advanced database operations and form validation.
-- `Conclusion <conclusion.html>`_, which will give you some pointers on
+- :doc:`Conclusion <conclusion>`, which will give you some pointers on
further reading and other resources.
Enjoy your exploration of the CodeIgniter framework.
diff --git a/user_guide_src/source/tutorial/news_section.rst b/user_guide_src/source/tutorial/news_section.rst
index 80938de..d8ebac4 100644
--- a/user_guide_src/source/tutorial/news_section.rst
+++ b/user_guide_src/source/tutorial/news_section.rst
@@ -18,7 +18,7 @@
Open up the application/models directory and create a new file called
News_model.php and add the following code. Make sure you've configured
your database properly as described
-`here <../database/configuration.html>`_.
+:doc:`here <../database/configuration>`.
::
@@ -53,10 +53,10 @@
Now that the database and a model have been set up, you'll need a method
to get all of our posts from our database. To do this, the database
-abstraction layer that is included with CodeIgniter — `Active
-Record <../database/query_builder.html>`_ — is used. This makes it
-possible to write your 'queries' once and make them work on `all
-supported database systems <../general/requirements.html>`_. Add the
+abstraction layer that is included with CodeIgniter —
+:doc:`Query Builder <../database/query_builder>` — is used. This makes it
+possible to write your 'queries' once and make them work on :doc:`all
+supported database systems <../general/requirements>`. Add the
following code to your model.
::
@@ -151,14 +151,14 @@
<div class="main">
<?php echo $news_item['text'] ?>
</div>
- <p><a href="news/<?php echo $news_item['slug'] ?>">View article</a></p>
+ <p><a href="<?php echo $news_item['slug'] ?>">View article</a></p>
<?php endforeach ?>
Here, each news item is looped and displayed to the user. You can see we
wrote our template in PHP mixed with HTML. If you prefer to use a
-template language, you can use CodeIgniter's `Template
-Parser <../libraries/parser>`_ class or a third party parser.
+template language, you can use CodeIgniter's :doc:`Template
+Parser <../libraries/parser>` class or a third party parser.
The news overview page is now done, but a page to display individual
news items is still absent. The model created earlier is made in such
diff --git a/user_guide_src/source/tutorial/static_pages.rst b/user_guide_src/source/tutorial/static_pages.rst
index 36bcd2d..62b3469 100644
--- a/user_guide_src/source/tutorial/static_pages.rst
+++ b/user_guide_src/source/tutorial/static_pages.rst
@@ -3,7 +3,7 @@
############
**Note:** This tutorial assumes you've downloaded CodeIgniter and
-`installed the framework <../installation/index.html>`_ in your
+:doc:`installed the framework <../installation/index>` in your
development environment.
The first thing you're going to do is set up a **controller** to handle
@@ -11,12 +11,16 @@
It is the glue of your web application.
For example, when a call is made to:
-``http://example.com/news/latest/10`` We might imagine that there is a
-controller named "news". The method being called on news would be
-"latest". The news method's job could be to grab 10 news items, and
-render them on the page. Very often in MVC, you'll see URL patterns that
-match:
-``http://example.com/[controller-class]/[controller-method]/[arguments]``
+
+ http://example.com/news/latest/10
+
+We might imagine that there is a controller named "news". The method
+being called on news would be "latest". The news method's job could be to
+grab 10 news items, and render them on the page. Very often in MVC,
+you'll see URL patterns that match:
+
+ http://example.com/[controller-class]/[controller-method]/[arguments]
+
As URL schemes become more complex, this may change. But for now, this
is all we will need to know.
@@ -25,15 +29,13 @@
::
- <?php
- class Pages extends CI_Controller {
+ <?php
+ class Pages extends CI_Controller {
- public function view($page = 'home')
- {
-
- }
-
- }
+ public function view($page = 'home')
+ {
+ }
+ }
You have created a class named "pages", with a view method that accepts
one argument named $page. The pages class is extending the
@@ -56,13 +58,13 @@
::
- <html>
- <head>
- <title>CodeIgniter Tutorial</title>
- </head>
- <body>
+ <html>
+ <head>
+ <title>CodeIgniter Tutorial</title>
+ </head>
+ <body>
- <h1>CodeIgniter Tutorial</h1>
+ <h1><?php echo $title ?></h1>
The header contains the basic HTML code that you'll want to display
before loading the main view, together with a heading. It will also
@@ -72,16 +74,16 @@
::
- <em>© 2014</em>
- </body>
- <html>
+ <em>© 2014</em>
+ </body>
+ </html>
Adding logic to the controller
------------------------------
-Earlier you set up a controller with a view() method. The method accepts
-one parameter, which is the name of the page to be loaded. The static
-page templates will be located in the application/views/pages/
+Earlier you set up a controller with a ``view()`` method. The method
+accepts one parameter, which is the name of the page to be loaded. The
+static page templates will be located in the application/views/pages/
directory.
In that directory, create two files named home.php and about.php. Within
@@ -93,43 +95,40 @@
::
- <?php
- public function view($page = 'home')
- {
-
- if ( ! file_exists(APPPATH.'/views/pages/'.$page.'.php'))
- {
- // Whoops, we don't have a page for that!
- show_404();
- }
-
- $data['title'] = ucfirst($page); // Capitalize the first letter
-
- $this->load->view('templates/header', $data);
- $this->load->view('pages/'.$page, $data);
- $this->load->view('templates/footer', $data);
+ public function view($page = 'home')
+ {
+ if ( ! file_exists(APPPATH.'/views/pages/'.$page.'.php'))
+ {
+ // Whoops, we don't have a page for that!
+ show_404();
+ }
- }
+ $data['title'] = ucfirst($page); // Capitalize the first letter
+
+ $this->load->view('templates/header', $data);
+ $this->load->view('pages/'.$page, $data);
+ $this->load->view('templates/footer', $data);
+ }
Now, when the page does exist, it is loaded, including the header and
footer, and displayed to the user. If the page doesn't exist, a "404
Page not found" error is shown.
The first line in this method checks whether the page actually exists.
-PHP's native file\_exists() function is used to check whether the file
-is where it's expected to be. show\_404() is a built-in CodeIgniter
+PHP's native ``file_exists()`` function is used to check whether the file
+is where it's expected to be. ``show_404()`` is a built-in CodeIgniter
function that renders the default error page.
-In the header template, the $title variable was used to customize the
+In the header template, the ``$title`` variable was used to customize the
page title. The value of title is defined in this method, but instead of
assigning the value to a variable, it is assigned to the title element
in the $data array.
The last thing that has to be done is loading the views in the order
-they should be displayed. The second parameter in the view() method is
-used to pass values to the view. Each value in the $data array is
+they should be displayed. The second parameter in the ``view()`` method is
+used to pass values to the view. Each value in the ``$data`` array is
assigned to a variable with the name of its key. So the value of
-$data['title'] in the controller is equivalent to $title in the view.
+``$data['title']`` in the controller is equivalent to $title in the view.
Routing
-------
@@ -149,8 +148,8 @@
::
- $route['default_controller'] = 'pages/view';
- $route['(:any)'] = 'pages/view/$1';
+ $route['default_controller'] = 'pages/view';
+ $route['(:any)'] = 'pages/view/$1';
CodeIgniter reads its routing rules from top to bottom and routes the
request to the first matching rule. Each rule is a regular expression
@@ -160,11 +159,11 @@
arguments.
More information about routing can be found in the URI Routing
-`documentation <../general/routing.html>`_.
+:doc:`documentation <../general/routing>`.
Here, the second rule in the $routes array matches **any** request using
-the wildcard string (:any). and passes the parameter to the view()
+the wildcard string (:any). and passes the parameter to the ``view()``
method of the pages class.
-Now visit index.php/about. Did it get routed correctly to the view()
+Now visit index.php/about. Did it get routed correctly to the ``view()``
method in the pages controller? Awesome!