summaryrefslogtreecommitdiffstats
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rw-r--r--system/core/CodeIgniter.php2
-rw-r--r--system/core/Common.php130
-rw-r--r--system/core/Config.php40
-rw-r--r--system/core/Exceptions.php2
-rw-r--r--system/core/Hooks.php2
-rw-r--r--system/core/Input.php92
-rw-r--r--system/core/Loader.php96
-rw-r--r--system/core/Log.php9
-rw-r--r--system/core/Output.php37
-rw-r--r--system/core/Router.php109
-rw-r--r--system/core/Security.php213
-rw-r--r--system/core/URI.php72
-rw-r--r--system/core/compat/hash.php51
-rw-r--r--system/core/compat/index.html3
-rw-r--r--system/core/compat/mbstring.php2
-rw-r--r--system/core/index.html3
-rw-r--r--system/database/DB.php8
-rw-r--r--system/database/DB_driver.php185
-rw-r--r--system/database/DB_forge.php15
-rw-r--r--system/database/DB_query_builder.php53
-rw-r--r--system/database/DB_utility.php7
-rw-r--r--system/database/drivers/cubrid/cubrid_driver.php42
-rw-r--r--system/database/drivers/cubrid/index.html3
-rw-r--r--system/database/drivers/ibase/ibase_driver.php32
-rw-r--r--system/database/drivers/ibase/index.html3
-rw-r--r--system/database/drivers/index.html3
-rw-r--r--system/database/drivers/mssql/index.html3
-rw-r--r--system/database/drivers/mssql/mssql_driver.php46
-rw-r--r--system/database/drivers/mysql/index.html3
-rw-r--r--system/database/drivers/mysql/mysql_driver.php41
-rw-r--r--system/database/drivers/mysqli/index.html3
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php83
-rw-r--r--system/database/drivers/oci8/index.html3
-rw-r--r--system/database/drivers/oci8/oci8_driver.php102
-rw-r--r--system/database/drivers/odbc/index.html3
-rw-r--r--system/database/drivers/odbc/odbc_driver.php34
-rw-r--r--system/database/drivers/pdo/index.html3
-rw-r--r--system/database/drivers/pdo/pdo_driver.php34
-rw-r--r--system/database/drivers/pdo/subdrivers/index.html3
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_4d_driver.php2
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php4
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php2
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php55
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php30
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php1
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php2
-rw-r--r--system/database/drivers/postgre/index.html3
-rw-r--r--system/database/drivers/postgre/postgre_driver.php34
-rw-r--r--system/database/drivers/sqlite/index.html3
-rw-r--r--system/database/drivers/sqlite/sqlite_driver.php39
-rw-r--r--system/database/drivers/sqlite3/index.html3
-rw-r--r--system/database/drivers/sqlite3/sqlite3_driver.php60
-rw-r--r--system/database/drivers/sqlite3/sqlite3_forge.php3
-rw-r--r--system/database/drivers/sqlsrv/index.html3
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_driver.php53
-rw-r--r--system/database/index.html3
-rw-r--r--system/fonts/index.html3
-rw-r--r--system/helpers/array_helper.php4
-rw-r--r--system/helpers/captcha_helper.php89
-rw-r--r--system/helpers/download_helper.php21
-rw-r--r--system/helpers/file_helper.php4
-rw-r--r--system/helpers/form_helper.php45
-rw-r--r--system/helpers/index.html3
-rw-r--r--system/helpers/inflector_helper.php1
-rw-r--r--system/helpers/path_helper.php2
-rw-r--r--system/helpers/string_helper.php2
-rw-r--r--system/helpers/text_helper.php2
-rw-r--r--system/helpers/url_helper.php8
-rw-r--r--system/index.html3
-rw-r--r--system/language/english/index.html3
-rw-r--r--system/language/index.html3
-rw-r--r--system/libraries/Cache/Cache.php31
-rw-r--r--system/libraries/Cache/drivers/Cache_file.php2
-rw-r--r--system/libraries/Cache/drivers/Cache_memcached.php148
-rw-r--r--system/libraries/Cache/drivers/Cache_redis.php139
-rw-r--r--system/libraries/Cache/drivers/Cache_wincache.php2
-rw-r--r--system/libraries/Cache/drivers/index.html3
-rw-r--r--system/libraries/Cache/index.html3
-rw-r--r--system/libraries/Calendar.php6
-rw-r--r--system/libraries/Email.php76
-rw-r--r--system/libraries/Encrypt.php2
-rw-r--r--system/libraries/Encryption.php2
-rw-r--r--system/libraries/Form_validation.php54
-rw-r--r--system/libraries/Ftp.php4
-rw-r--r--system/libraries/Image_lib.php44
-rw-r--r--system/libraries/Javascript/Jquery.php2
-rw-r--r--system/libraries/Javascript/index.html3
-rw-r--r--system/libraries/Migration.php6
-rw-r--r--system/libraries/Pagination.php17
-rw-r--r--system/libraries/Profiler.php6
-rw-r--r--system/libraries/Session/Session.php16
-rw-r--r--system/libraries/Session/drivers/Session_database_driver.php12
-rw-r--r--system/libraries/Session/drivers/Session_files_driver.php20
-rw-r--r--system/libraries/Session/drivers/Session_memcached_driver.php34
-rw-r--r--system/libraries/Session/drivers/Session_redis_driver.php44
-rw-r--r--system/libraries/Session/drivers/index.html3
-rw-r--r--system/libraries/Session/index.html3
-rw-r--r--system/libraries/Unit_test.php56
-rw-r--r--system/libraries/Upload.php75
-rw-r--r--system/libraries/Xmlrpc.php22
-rw-r--r--system/libraries/Xmlrpcs.php29
-rw-r--r--system/libraries/Zip.php2
-rw-r--r--system/libraries/index.html3
103 files changed, 1580 insertions, 1357 deletions
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index d830c1829..fece65bde 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -55,7 +55,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @var string
*
*/
- define('CI_VERSION', '3.0-dev');
+ define('CI_VERSION', '3.1.0-dev');
/*
* ------------------------------------------------------
diff --git a/system/core/Common.php b/system/core/Common.php
index 9f509745f..3ab98cf6d 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -181,7 +181,7 @@ if ( ! function_exists('load_class'))
// Did we find the class?
if ($name === FALSE)
{
- // Note: We use exit() rather then show_error() in order to avoid a
+ // Note: We use exit() rather than show_error() in order to avoid a
// self-referencing loop with the Exceptions class
set_status_header(503);
echo 'Unable to locate the specified class: '.$class.'.php';
@@ -492,59 +492,67 @@ if ( ! function_exists('set_status_header'))
*/
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(
+ 100 => 'Continue',
+ 101 => 'Switching Protocols',
+
+ 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',
+ 402 => 'Payment Required',
+ 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];
@@ -669,7 +677,7 @@ if ( ! function_exists('_shutdown_handler'))
* of CodeIgniter.php. The main reason we use this is to simulate
* a complete custom exception handler.
*
- * E_STRICT is purposivly neglected because such events may have
+ * E_STRICT is purposively neglected because such events may have
* been caught. Duplication or none? None is preferred for now.
*
* @link http://insomanic.me.uk/post/229851073/php-trick-catching-fatal-errors-e-error-with-a
@@ -737,9 +745,19 @@ if ( ! function_exists('html_escape'))
*/
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));
+ foreach (array_keys($var) as $key)
+ {
+ $var[$key] = html_escape($var[$key], $double_encode);
+ }
+
+ return $var;
}
return htmlspecialchars($var, ENT_QUOTES, config_item('charset'), $double_encode);
@@ -820,19 +838,9 @@ if ( ! function_exists('function_usable'))
{
if ( ! isset($_suhosin_func_blacklist))
{
- if (extension_loaded('suhosin'))
- {
- $_suhosin_func_blacklist = explode(',', trim(ini_get('suhosin.executor.func.blacklist')));
-
- if ( ! in_array('eval', $_suhosin_func_blacklist, TRUE) && ini_get('suhosin.executor.disable_eval'))
- {
- $_suhosin_func_blacklist[] = 'eval';
- }
- }
- else
- {
- $_suhosin_func_blacklist = array();
- }
+ $_suhosin_func_blacklist = extension_loaded('suhosin')
+ ? explode(',', trim(ini_get('suhosin.executor.func.blacklist')))
+ : array();
}
return ! in_array($function_name, $_suhosin_func_blacklist, TRUE);
diff --git a/system/core/Config.php b/system/core/Config.php
index a191a7727..0264776f9 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -88,11 +88,9 @@ class CI_Config {
// Set the base_url automatically if none was provided
if (empty($this->config['base_url']))
{
- // The regular expression is only a basic validation for a valid "Host" header.
- // It's not exhaustive, only checks for valid characters.
- if (isset($_SERVER['HTTP_HOST']) && preg_match('/^((\[[0-9a-f:]+\])|(\d{1,3}(\.\d{1,3}){3})|[a-z0-9\-\.]+)(:\d+)?$/i', $_SERVER['HTTP_HOST']))
+ if (isset($_SERVER['SERVER_ADDR']))
{
- $base_url = (is_https() ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST']
+ $base_url = (is_https() ? 'https' : 'http').'://'.$_SERVER['SERVER_ADDR']
.substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], basename($_SERVER['SCRIPT_FILENAME'])));
}
else
@@ -123,10 +121,9 @@ class CI_Config {
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 +162,13 @@ class CI_Config {
$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;
}
@@ -240,7 +236,15 @@ class CI_Config {
if (isset($protocol))
{
- $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ // For protocol-relative links
+ if ($protocol === '')
+ {
+ $base_url = substr($base_url, strpos($base_url, '//'));
+ }
+ else
+ {
+ $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ }
}
if (empty($uri))
@@ -295,7 +299,15 @@ class CI_Config {
if (isset($protocol))
{
- $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ // For protocol-relative links
+ if ($protocol === '')
+ {
+ $base_url = substr($base_url, strpos($base_url, '//'));
+ }
+ else
+ {
+ $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ }
}
return $base_url.ltrim($this->_uri_string($uri), '/');
diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php
index fc25f57e6..d8f62c0fe 100644
--- a/system/core/Exceptions.php
+++ b/system/core/Exceptions.php
@@ -187,7 +187,7 @@ class CI_Exceptions {
// --------------------------------------------------------------------
- public function show_exception(Exception $exception)
+ public function show_exception($exception)
{
$templates_path = config_item('error_views_path');
if (empty($templates_path))
diff --git a/system/core/Hooks.php b/system/core/Hooks.php
index 08479b133..3b4fb2250 100644
--- a/system/core/Hooks.php
+++ b/system/core/Hooks.php
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @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 72425c1c1..4e7a4e95e 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -55,7 +55,7 @@ class CI_Input {
*
* @var string
*/
- public $ip_address = FALSE;
+ protected $ip_address = FALSE;
/**
* Allow GET array flag
@@ -104,14 +104,28 @@ class CI_Input {
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
@@ -139,6 +153,12 @@ class CI_Input {
// Sanitize global arrays
$this->_sanitize_globals();
+ // CSRF Protection check
+ if ($this->_enable_csrf === TRUE && ! is_cli())
+ {
+ $this->security->csrf_verify();
+ }
+
log_message('info', 'Input Class Initialized');
}
@@ -313,7 +333,8 @@ class CI_Input {
// 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 +496,9 @@ class CI_Input {
)
);
- 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';
@@ -585,7 +606,7 @@ class CI_Input {
{
$_GET = array();
}
- elseif (is_array($_GET) && count($_GET) > 0)
+ elseif (is_array($_GET))
{
foreach ($_GET as $key => $val)
{
@@ -594,7 +615,7 @@ class CI_Input {
}
// Clean $_POST Data
- if (is_array($_POST) && count($_POST) > 0)
+ if (is_array($_POST))
{
foreach ($_POST as $key => $val)
{
@@ -603,7 +624,7 @@ class CI_Input {
}
// Clean $_COOKIE Data
- if (is_array($_COOKIE) && count($_COOKIE) > 0)
+ if (is_array($_COOKIE))
{
// Also get rid of specially treated cookies that might be set by a server
// or silly application, that are of no use to a CI application anyway
@@ -632,12 +653,6 @@ class CI_Input {
// Sanitize PHP_SELF
$_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
- // CSRF Protection check
- if ($this->_enable_csrf === TRUE && ! is_cli())
- {
- $this->security->csrf_verify();
- }
-
log_message('debug', 'Global POST, GET and COOKIE data sanitized');
}
@@ -667,7 +682,7 @@ class CI_Input {
/* We strip slashes if magic quotes is on to keep things consistent
NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and
- it will probably not exist in future versions at all.
+ it will probably not exist in future versions at all.
*/
if ( ! is_php('5.4') && get_magic_quotes_gpc())
{
@@ -702,7 +717,7 @@ class CI_Input {
* only named with alpha-numeric text and a few other items.
*
* @param string $str Input string
- * @param string $fatal Whether to terminate script exection
+ * @param bool $fatal Whether to terminate script exection
* or to return FALSE if an invalid
* key is encountered
* @return string|bool
@@ -784,19 +799,27 @@ class CI_Input {
*/
public function get_request_header($index, $xss_clean = FALSE)
{
- if (empty($this->headers))
+ static $headers;
+
+ if ( ! isset($headers))
{
- $this->request_headers();
+ empty($this->headers) && $this->request_headers();
+ foreach ($this->headers as $key => $value)
+ {
+ $headers[strtolower($key)] = $value;
+ }
}
- if ( ! isset($this->headers[$index]))
+ $index = strtolower($index);
+
+ if ( ! isset($headers[$index]))
{
return NULL;
}
return ($xss_clean === TRUE)
- ? $this->security->xss_clean($this->headers[$index])
- : $this->headers[$index];
+ ? $this->security->xss_clean($headers[$index])
+ : $headers[$index];
}
// --------------------------------------------------------------------
@@ -821,7 +844,7 @@ class CI_Input {
* Test to see if a request was made from the command line.
*
* @deprecated 3.0.0 Use is_cli() instead
- * @return bool
+ * @return bool
*/
public function is_cli_request()
{
@@ -846,4 +869,27 @@ class CI_Input {
: 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 b2eeb3b1d..18e4c5287 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -272,7 +272,7 @@ class CI_Loader {
$CI =& get_instance();
if (isset($CI->$name))
{
- show_error('The model name you are loading is the name of a resource that is already being used: '.$name);
+ throw new RuntimeException('The model name you are loading is the name of a resource that is already being used: '.$name);
}
if ($db_conn !== FALSE && ! class_exists('CI_DB', FALSE))
@@ -290,24 +290,38 @@ class CI_Loader {
load_class('Model', 'core');
}
- $model = ucfirst(strtolower($model));
-
- foreach ($this->_ci_model_paths as $mod_path)
+ $model = ucfirst($model);
+ if ( ! class_exists($model))
{
- if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))
+ foreach ($this->_ci_model_paths as $mod_path)
{
- continue;
- }
+ if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))
+ {
+ continue;
+ }
- require_once($mod_path.'models/'.$path.$model.'.php');
+ require_once($mod_path.'models/'.$path.$model.'.php');
+ if ( ! class_exists($model, FALSE))
+ {
+ throw new RuntimeException($mod_path."models/".$path.$model.".php exists, but doesn't declare class ".$model);
+ }
- $this->_ci_models[] = $name;
- $CI->$name = new $model();
- return $this;
+ break;
+ }
+
+ if ( ! class_exists($model, FALSE))
+ {
+ throw new RuntimeException('Unable to locate the model you have specified: '.$model);
+ }
+ }
+ elseif ( ! is_subclass_of($model, 'CI_Model'))
+ {
+ throw new RuntimeException("Class ".$model." already exists and doesn't extend CI_Model");
}
- // couldn't find the model
- show_error('Unable to locate the model you have specified: '.$model);
+ $this->_ci_models[] = $name;
+ $CI->$name = new $model();
+ return $this;
}
// --------------------------------------------------------------------
@@ -500,7 +514,7 @@ class CI_Loader {
*
* Clears the cached variables.
*
- * @return object
+ * @return CI_Loader
*/
public function clear_vars()
{
@@ -905,7 +919,7 @@ class CI_Loader {
// If the PHP installation does not support short tags we'll
// do a little string replacement, changing the short tags
// to standard PHP echo statements.
- if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE && function_usable('eval'))
+ if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE)
{
echo eval('?>'.preg_replace('/;*\s*\?>/', '; ?>', str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
}
@@ -1079,17 +1093,26 @@ class CI_Loader {
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))
- {
- return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
- }
- else
+ if (file_exists($path = $path.'libraries/'.$file_path.$library_name.'.php'))
{
- 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 +1120,20 @@ class CI_Loader {
// 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))
- {
- $prefix = config_item('subclass_prefix');
- }
- else
+ if (file_exists($path = $path.'libraries/'.$file_path.$subclass.'.php'))
{
- 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 +1321,7 @@ class CI_Loader {
}
// 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 833316273..e8cb401f5 100644
--- a/system/core/Log.php
+++ b/system/core/Log.php
@@ -70,13 +70,6 @@ class CI_Log {
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 @@ class CI_Log {
}
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/Output.php b/system/core/Output.php
index 02f66936c..76c1329d2 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -556,9 +556,16 @@ class CI_Output {
.$CI->config->item('index_page')
.$CI->uri->uri_string();
- if ($CI->config->item('cache_query_string') && ! empty($_SERVER['QUERY_STRING']))
+ if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
{
- $uri .= '?'.$_SERVER['QUERY_STRING'];
+ if (is_array($cache_query_string))
+ {
+ $uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
+ }
+ else
+ {
+ $uri .= '?'.$_SERVER['QUERY_STRING'];
+ }
}
$cache_path .= md5($uri);
@@ -646,9 +653,16 @@ class CI_Output {
// Build the file path. The file name is an MD5 hash of the full URI
$uri = $CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;
- if ($CFG->item('cache_query_string') && ! empty($_SERVER['QUERY_STRING']))
+ if (($cache_query_string = $CFG->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
{
- $uri .= '?'.$_SERVER['QUERY_STRING'];
+ if (is_array($cache_query_string))
+ {
+ $uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
+ }
+ else
+ {
+ $uri .= '?'.$_SERVER['QUERY_STRING'];
+ }
}
$filepath = $cache_path.md5($uri);
@@ -674,7 +688,7 @@ class CI_Output {
$cache_info = unserialize($match[1]);
$expire = $cache_info['expire'];
- $last_modified = filemtime($cache_path);
+ $last_modified = filemtime($filepath);
// Has the file expired?
if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path))
@@ -729,13 +743,20 @@ class CI_Output {
{
$uri = $CI->uri->uri_string();
- if ($CI->config->item('cache_query_string') && ! empty($_SERVER['QUERY_STRING']))
+ if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
{
- $uri .= '?'.$_SERVER['QUERY_STRING'];
+ if (is_array($cache_query_string))
+ {
+ $uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
+ }
+ else
+ {
+ $uri .= '?'.$_SERVER['QUERY_STRING'];
+ }
}
}
- $cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').$uri);
+ $cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').ltrim($uri, '/'));
if ( ! @unlink($cache_path))
{
diff --git a/system/core/Router.php b/system/core/Router.php
index eb3da2285..a84be1f1d 100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -83,7 +83,7 @@ class CI_Router {
*
* @var string
*/
- public $directory = '';
+ public $directory;
/**
* Default controller (and method if specific)
@@ -105,7 +105,7 @@ class CI_Router {
/**
* Enable query strings flag
*
- * Determines wether to use GET parameters or segment URIs
+ * Determines whether to use GET parameters or segment URIs
*
* @var bool
*/
@@ -126,25 +126,16 @@ class CI_Router {
$this->uri =& load_class('URI', 'core');
$this->enable_query_strings = ( ! is_cli() && $this->config->item('enable_query_strings') === TRUE);
+
+ // If a directory override is configured, it has to be set before any dynamic routing logic
+ is_array($routing) && isset($routing['directory']) && $this->set_directory($routing['directory']);
$this->_set_routing();
// Set any routing overrides that may exist in the main index file
if (is_array($routing))
{
- if (isset($routing['directory']))
- {
- $this->set_directory($routing['directory']);
- }
-
- if ( ! empty($routing['controller']))
- {
- $this->set_class($routing['controller']);
- }
-
- if ( ! empty($routing['function']))
- {
- $this->set_method($routing['function']);
- }
+ empty($routing['controller']) OR $this->set_class($routing['controller']);
+ empty($routing['function']) OR $this->set_method($routing['function']);
}
log_message('info', 'Router Class Initialized');
@@ -162,17 +153,44 @@ class CI_Router {
*/
protected function _set_routing()
{
+ // Load the routes.php file. It would be great if we could
+ // skip this for enable_query_strings = TRUE, but then
+ // default_controller would be empty ...
+ if (file_exists(APPPATH.'config/routes.php'))
+ {
+ include(APPPATH.'config/routes.php');
+ }
+
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
+ {
+ include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
+ }
+
+ // Validate & get reserved routes
+ if (isset($route) && is_array($route))
+ {
+ isset($route['default_controller']) && $this->default_controller = $route['default_controller'];
+ isset($route['translate_uri_dashes']) && $this->translate_uri_dashes = $route['translate_uri_dashes'];
+ unset($route['default_controller'], $route['translate_uri_dashes']);
+ $this->routes = $route;
+ }
+
// Are query strings enabled in the config file? Normally CI doesn't utilize query strings
// since URI segments are more search-engine friendly, but they can optionally be used.
// If this feature is enabled, we will gather the directory/class/method a little differently
if ($this->enable_query_strings)
{
- $_d = $this->config->item('directory_trigger');
- $_d = isset($_GET[$_d]) ? trim($_GET[$_d], " \t\n\r\0\x0B/") : '';
- if ($_d !== '')
+ // If the directory is set at this time, it means an override exists, so skip the checks
+ if ( ! isset($this->directory))
{
- $this->uri->filter_uri($_d);
- $this->set_directory($_d);
+ $_d = $this->config->item('directory_trigger');
+ $_d = isset($_GET[$_d]) ? trim($_GET[$_d], " \t\n\r\0\x0B/") : '';
+
+ if ($_d !== '')
+ {
+ $this->uri->filter_uri($_d);
+ $this->set_directory($_d);
+ }
}
$_c = trim($this->config->item('controller_trigger'));
@@ -203,26 +221,6 @@ class CI_Router {
return;
}
- // Load the routes.php file.
- if (file_exists(APPPATH.'config/routes.php'))
- {
- include(APPPATH.'config/routes.php');
- }
-
- if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
- {
- include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
- }
-
- // Validate & get reserved routes
- if (isset($route) && is_array($route))
- {
- isset($route['default_controller']) && $this->default_controller = $route['default_controller'];
- isset($route['translate_uri_dashes']) && $this->translate_uri_dashes = $route['translate_uri_dashes'];
- unset($route['default_controller'], $route['translate_uri_dashes']);
- $this->routes = $route;
- }
-
// Is there anything to parse?
if ($this->uri->uri_string !== '')
{
@@ -333,6 +331,8 @@ class CI_Router {
protected function _validate_request($segments)
{
$c = count($segments);
+ $directory_override = isset($this->directory);
+
// Loop through our segments and return as soon as a controller
// is found or when such a directory doesn't exist
while ($c-- > 0)
@@ -340,7 +340,10 @@ class CI_Router {
$test = $this->directory
.ucfirst($this->translate_uri_dashes === TRUE ? str_replace('-', '_', $segments[0]) : $segments[0]);
- if ( ! file_exists(APPPATH.'controllers/'.$test.'.php') && is_dir(APPPATH.'controllers/'.$this->directory.$segments[0]))
+ if ( ! file_exists(APPPATH.'controllers/'.$test.'.php')
+ && $directory_override === FALSE
+ && is_dir(APPPATH.'controllers/'.$this->directory.$segments[0])
+ )
{
$this->set_directory(array_shift($segments), TRUE);
continue;
@@ -371,29 +374,13 @@ class CI_Router {
// Get HTTP verb
$http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';
- // Is there a literal match? If so we're done
- if (isset($this->routes[$uri]))
- {
- // Check default routes format
- if (is_string($this->routes[$uri]))
- {
- $this->_set_request(explode('/', $this->routes[$uri]));
- return;
- }
- // Is there a matching http verb?
- elseif (is_array($this->routes[$uri]) && isset($this->routes[$uri][$http_verb]))
- {
- $this->_set_request(explode('/', $this->routes[$uri][$http_verb]));
- return;
- }
- }
-
// Loop through the route array looking for wildcards
foreach ($this->routes as $key => $val)
{
- // Check if route format is using http verb
+ // Check if route format is using HTTP verbs
if (is_array($val))
{
+ $val = array_change_key_case($val, CASE_LOWER);
if (isset($val[$http_verb]))
{
$val = $val[$http_verb];
@@ -493,7 +480,7 @@ class CI_Router {
* Set directory name
*
* @param string $dir Directory name
- * @param bool $appent Whether we're appending rather then setting the full value
+ * @param bool $append Whether we're appending rather than setting the full value
* @return void
*/
public function set_directory($dir, $append = FALSE)
diff --git a/system/core/Security.php b/system/core/Security.php
index 7c18c7406..36dea4cf2 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -275,7 +275,7 @@ class CI_Security {
$secure_cookie,
config_item('cookie_httponly')
);
- log_message('info', 'CRSF cookie sent');
+ log_message('info', 'CSRF cookie sent');
return $this;
}
@@ -436,7 +436,7 @@ class CI_Security {
$words = array(
'javascript', 'expression', 'vbscript', 'jscript', 'wscript',
'vbs', 'script', 'base64', 'applet', 'alert', 'document',
- 'write', 'cookie', 'window', 'confirm', 'prompt'
+ 'write', 'cookie', 'window', 'confirm', 'prompt', 'eval'
);
foreach ($words as $word)
@@ -480,12 +480,8 @@ class CI_Security {
}
}
while ($original !== $str);
-
unset($original);
- // Remove evil attributes such as style, onclick and xmlns
- $str = $this->_remove_evil_attributes($str, $is_image);
-
/*
* Sanitize naughty HTML elements
*
@@ -495,8 +491,29 @@ class CI_Security {
* So this: <blink>
* Becomes: &lt;blink&gt;
*/
- $naughty = 'alert|prompt|confirm|applet|audio|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|button|select|isindex|layer|link|meta|keygen|object|plaintext|style|script|textarea|title|math|video|svg|xml|xss';
- $str = preg_replace_callback('#<(/*\s*)('.$naughty.')([^><]*)([><]*)#is', array($this, '_sanitize_naughty_html'), $str);
+ $pattern = '#'
+ .'<((?<slash>/*\s*)(?<tagName>[a-z0-9]+)(?=[^a-z0-9]|$)' // tag start and name, followed by a non-tag character
+ .'[^\s\042\047a-z0-9>/=]*' // a valid attribute character immediately after the tag would count as a separator
+ // optional attributes
+ .'(?<attributes>(?:[\s\042\047/=]*' // non-attribute characters, excluding > (tag close) for obvious reasons
+ .'[^\s\042\047>/=]+' // attribute characters
+ // optional attribute-value
+ .'(?:\s*=' // attribute-value separator
+ .'(?:[^\s\042\047=><`]+|\s*\042[^\042]*\042|\s*\047[^\047]*\047|\s*(?U:[^\s\042\047=><`]*))' // single, double or non-quoted value
+ .')?' // end optional attribute-value group
+ .')*)' // end optional attributes group
+ .'[^>]*)(?<closeTag>\>)?#isS';
+
+ // Note: It would be nice to optimize this for speed, BUT
+ // only matching the naughty elements here results in
+ // false positives and in turn - vulnerabilities!
+ do
+ {
+ $old_str = $str;
+ $str = preg_replace_callback($pattern, array($this, '_sanitize_naughty_html'), $str);
+ }
+ while ($old_str !== $str);
+ unset($old_str);
/*
* Sanitize naughty scripting elements
@@ -510,9 +527,11 @@ class CI_Security {
* For example: eval('some code')
* Becomes: eval&#40;'some code'&#41;
*/
- $str = preg_replace('#(alert|prompt|confirm|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si',
- '\\1\\2&#40;\\3&#41;',
- $str);
+ $str = preg_replace(
+ '#(alert|prompt|confirm|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si',
+ '\\1\\2&#40;\\3&#41;',
+ $str
+ );
// Final clean up
// This adds a bit of extra precaution in case
@@ -639,7 +658,7 @@ class CI_Security {
$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 +675,7 @@ class CI_Security {
{
$_entities[':'] = '&colon;';
$_entities['('] = '&lpar;';
- $_entities[')'] = '&rpar';
+ $_entities[')'] = '&rpar;';
$_entities["\n"] = '&newline;';
$_entities["\t"] = '&tab;';
}
@@ -664,11 +683,11 @@ class CI_Security {
$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;
}
}
@@ -750,86 +769,92 @@ class CI_Security {
// --------------------------------------------------------------------
/**
- * Remove Evil HTML Attributes (like event handlers and style)
- *
- * It removes the evil attribute and either:
- *
- * - Everything up until a space. For example, everything between the pipes:
- *
- * <code>
- * <a |style=document.write('hello');alert('world');| class=link>
- * </code>
- *
- * - Everything inside the quotes. For example, everything between the pipes:
+ * Sanitize Naughty HTML
*
- * <code>
- * <a |style="document.write('hello'); alert('world');"| class="link">
- * </code>
+ * Callback method for xss_clean() to remove naughty HTML elements.
*
- * @param string $str The string to check
- * @param bool $is_image Whether the input is an image
- * @return string The string with the evil attributes removed
+ * @used-by CI_Security::xss_clean()
+ * @param array $matches
+ * @return string
*/
- protected function _remove_evil_attributes($str, $is_image)
+ protected function _sanitize_naughty_html($matches)
{
- $evil_attributes = array('on\w*', 'style', 'xmlns', 'formaction', 'form', 'xlink:href');
+ static $naughty_tags = array(
+ 'alert', 'prompt', 'confirm', 'applet', 'audio', 'basefont', 'base', 'behavior', 'bgsound',
+ 'blink', 'body', 'embed', 'expression', 'form', 'frameset', 'frame', 'head', 'html', 'ilayer',
+ 'iframe', 'input', 'button', 'select', 'isindex', 'layer', 'link', 'meta', 'keygen', 'object',
+ 'plaintext', 'style', 'script', 'textarea', 'title', 'math', 'video', 'svg', 'xml', 'xss'
+ );
- if ($is_image === TRUE)
+ static $evil_attributes = array(
+ 'on\w+', 'style', 'xmlns', 'formaction', 'form', 'xlink:href', 'FSCommand', 'seekSegmentTime'
+ );
+
+ // First, escape unclosed tags
+ if (empty($matches['closeTag']))
{
- /*
- * Adobe Photoshop puts XML metadata into JFIF images,
- * including namespacing, so we have to allow this for images.
- */
- unset($evil_attributes[array_search('xmlns', $evil_attributes)]);
+ return '&lt;'.$matches[1];
}
+ // Is the element that we caught naughty? If so, escape it
+ elseif (in_array(strtolower($matches['tagName']), $naughty_tags, TRUE))
+ {
+ return '&lt;'.$matches[1].'&gt;';
+ }
+ // For other tags, see if their attributes are "evil" and strip those
+ elseif (isset($matches['attributes']))
+ {
+ // We'll store the already fitlered attributes here
+ $attributes = array();
- do {
- $count = 0;
- $attribs = array();
+ // Attribute-catching pattern
+ $attributes_pattern = '#'
+ .'(?<name>[^\s\042\047>/=]+)' // attribute characters
+ // optional attribute-value
+ .'(?:\s*=(?<value>[^\s\042\047=><`]+|\s*\042[^\042]*\042|\s*\047[^\047]*\047|\s*(?U:[^\s\042\047=><`]*)))' // attribute-value separator
+ .'#i';
- // 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);
+ // Blacklist pattern for evil attribute names
+ $is_evil_pattern = '#^('.implode('|', $evil_attributes).')$#i';
- foreach ($matches as $attr)
+ // Each iteration filters a single attribute
+ do
{
- $attribs[] = preg_quote($attr[0], '/');
- }
+ // Strip any non-alpha characters that may preceed an attribute.
+ // Browsers often parse these incorrectly and that has been a
+ // of numerous XSS issues we've had.
+ $matches['attributes'] = preg_replace('#^[^a-z]+#i', '', $matches['attributes']);
- // find occurrences of illegal attribute strings without quotes
- preg_match_all('/(?<!\w)('.implode('|', $evil_attributes).')\s*=\s*([^\s>]*)/is', $str, $matches, PREG_SET_ORDER);
+ if ( ! preg_match($attributes_pattern, $matches['attributes'], $attribute, PREG_OFFSET_CAPTURE))
+ {
+ // No (valid) attribute found? Discard everything else inside the tag
+ break;
+ }
- foreach ($matches as $attr)
- {
- $attribs[] = preg_quote($attr[0], '/');
- }
+ if (
+ // Is it indeed an "evil" attribute?
+ preg_match($is_evil_pattern, $attribute['name'][0])
+ // Or does it have an equals sign, but no value and not quoted? Strip that too!
+ OR (trim($attribute['value'][0]) === '')
+ )
+ {
+ $attributes[] = 'xss=removed';
+ }
+ else
+ {
+ $attributes[] = $attribute[0][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);
+ $matches['attributes'] = substr($matches['attributes'], $attribute[0][1] + strlen($attribute[0][0]));
}
+ while ($matches['attributes'] !== '');
+
+ $attributes = empty($attributes)
+ ? ''
+ : ' '.implode(' ', $attributes);
+ return '<'.$matches['slash'].$matches['tagName'].$attributes.'>';
}
- while ($count);
- return $str;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Sanitize Naughty HTML
- *
- * Callback method for xss_clean() to remove naughty HTML elements.
- *
- * @used-by CI_Security::xss_clean()
- * @param array $matches
- * @return string
- */
- protected function _sanitize_naughty_html($matches)
- {
- return '&lt;'.$matches[1].$matches[2].$matches[3] // encode opening brace
- // encode captured opening or closing brace to prevent recursive vectors:
- .str_replace(array('>', '<'), array('&gt;', '&lt;'), $matches[4]);
+ return $matches[0];
}
// --------------------------------------------------------------------
@@ -849,12 +874,15 @@ class CI_Security {
*/
protected function _js_link_removal($match)
{
- return str_replace($match[1],
- preg_replace('#href=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
- '',
- $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
- ),
- $match[0]);
+ return str_replace(
+ $match[1],
+ preg_replace(
+ '#href=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
+ '',
+ $this->_filter_attributes($match[1])
+ ),
+ $match[0]
+ );
}
// --------------------------------------------------------------------
@@ -874,12 +902,15 @@ class CI_Security {
*/
protected function _js_img_removal($match)
{
- return str_replace($match[1],
- preg_replace('#src=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
- '',
- $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
- ),
- $match[0]);
+ return str_replace(
+ $match[1],
+ preg_replace(
+ '#src=.*?(?:(?:alert|prompt|confirm|eval)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
+ '',
+ $this->_filter_attributes($match[1])
+ ),
+ $match[0]
+ );
}
// --------------------------------------------------------------------
diff --git a/system/core/URI.php b/system/core/URI.php
index 9bc34ace7..5b658f679 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -107,37 +107,34 @@ class CI_URI {
$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());
+ $uri = $this->_parse_argv();
}
- elseif ($protocol === 'AUTO')
+ else
{
- // 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), '/') !== '')
+ $protocol = $this->config->item('uri_protocol');
+ empty($protocol) && $protocol = 'REQUEST_URI';
+
+ switch ($protocol)
{
- $this->_set_uri_string(key($_GET));
+ 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;
}
}
- elseif (method_exists($this, ($method = '_parse_'.strtolower($protocol))))
- {
- $this->_set_uri_string($this->$method());
- }
- else
- {
- $uri = isset($_SERVER[$protocol]) ? $_SERVER[$protocol] : @getenv($protocol);
- $this->_set_uri_string($uri);
- }
+
+ $this->_set_uri_string($uri);
}
log_message('info', 'URI Class Initialized');
@@ -204,17 +201,22 @@ class CI_URI {
return '';
}
- $uri = parse_url($_SERVER['REQUEST_URI']);
+ // parse_url() returns false if no host is present, but the path or query string
+ // contains a colon followed by a number
+ $uri = parse_url('http://dummy'.$_SERVER['REQUEST_URI']);
$query = isset($uri['query']) ? $uri['query'] : '';
- $uri = isset($uri['path']) ? rawurldecode($uri['path']) : '';
+ $uri = isset($uri['path']) ? $uri['path'] : '';
- if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
- {
- $uri = (string) substr($uri, strlen($_SERVER['SCRIPT_NAME']));
- }
- elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
+ if (isset($_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 +224,7 @@ class CI_URI {
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 +264,7 @@ class CI_URI {
{
$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 477535dca..15954559c 100644
--- a/system/core/compat/hash.php
+++ b/system/core/compat/hash.php
@@ -174,9 +174,56 @@ if ( ! function_exists('hash_pbkdf2'))
}
$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 c942a79ce..b702fbc39 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 ddb2bae47..e335c85f7 100644
--- a/system/core/compat/mbstring.php
+++ b/system/core/compat/mbstring.php
@@ -92,7 +92,7 @@ if ( ! function_exists('mb_strpos'))
* 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 c942a79ce..b702fbc39 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 8ea7ca6fa..23de414b5 100644
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -82,7 +82,7 @@ function &DB($params = '', $query_builder_override = NULL)
}
}
- if ( ! isset($db) OR count($db) === 0)
+ if (empty($db))
{
show_error('No database connection settings were found in the database config file.');
}
@@ -213,10 +213,6 @@ function &DB($params = '', $query_builder_override = NULL)
}
}
- 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 bbe65b410..0ea679432 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -124,15 +124,6 @@ abstract class CI_DB_driver {
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
@@ -460,7 +451,7 @@ abstract class CI_DB_driver {
*
* This is just a dummy method that all drivers will override.
*
- * @return mixed
+ * @return mixed
*/
public function db_connect()
{
@@ -490,7 +481,7 @@ abstract class CI_DB_driver {
* This is just a dummy method to allow drivers without such
* functionality to not declare it, while others will override it.
*
- * @return void
+ * @return void
*/
public function reconnect()
{
@@ -504,7 +495,7 @@ abstract class CI_DB_driver {
* This is just a dummy method to allow drivers without such
* functionality to not declare it, while others will override it.
*
- * @return bool
+ * @return bool
*/
public function db_select()
{
@@ -656,7 +647,10 @@ abstract class CI_DB_driver {
}
// This will trigger a rollback if transactions are being used
- $this->_trans_status = FALSE;
+ if ($this->_trans_depth !== 0)
+ {
+ $this->_trans_status = FALSE;
+ }
// Grab the error now, as we might run some additional queries before displaying the error
$error = $this->error();
@@ -674,7 +668,13 @@ abstract class CI_DB_driver {
{
do
{
+ $trans_depth = $this->_trans_depth;
$this->trans_complete();
+ if ($trans_depth === $this->_trans_depth)
+ {
+ log_message('error', 'Database: Failure during an automated transaction commit/rollback!');
+ break;
+ }
}
while ($this->_trans_depth !== 0);
}
@@ -797,10 +797,13 @@ abstract class CI_DB_driver {
/**
* Enable/disable Transaction Strict Mode
+ *
* When strict mode is enabled, if you are running multiple groups of
- * transactions, if one group fails all groups will be rolled back.
- * If strict mode is disabled, each group is treated autonomously, meaning
- * a failure of one group will not affect any others
+ * transactions, if one group fails all subsequent groups will be
+ * rolled back.
+ *
+ * If strict mode is disabled, each group is treated autonomously,
+ * meaning a failure of one group will not affect any others
*
* @param bool $mode = TRUE
* @return void
@@ -816,24 +819,16 @@ abstract class CI_DB_driver {
* Start Transaction
*
* @param bool $test_mode = FALSE
- * @return void
+ * @return bool
*/
public function trans_start($test_mode = FALSE)
{
if ( ! $this->trans_enabled)
{
- return;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- $this->_trans_depth += 1;
- return;
+ return FALSE;
}
- $this->trans_begin($test_mode);
- $this->_trans_depth += 1;
+ return $this->trans_begin($test_mode);
}
// --------------------------------------------------------------------
@@ -850,25 +845,14 @@ abstract class CI_DB_driver {
return FALSE;
}
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 1)
- {
- $this->_trans_depth -= 1;
- return TRUE;
- }
- else
- {
- $this->_trans_depth = 0;
- }
-
// The query() function will set this flag to FALSE in the event that a query failed
if ($this->_trans_status === FALSE OR $this->_trans_failure === TRUE)
{
$this->trans_rollback();
// If we are NOT running in strict mode, we will reset
- // the _trans_status flag so that subsequent groups of transactions
- // will be permitted.
+ // the _trans_status flag so that subsequent groups of
+ // transactions will be permitted.
if ($this->trans_strict === FALSE)
{
$this->_trans_status = TRUE;
@@ -878,8 +862,7 @@ abstract class CI_DB_driver {
return FALSE;
}
- $this->trans_commit();
- return TRUE;
+ return $this->trans_commit();
}
// --------------------------------------------------------------------
@@ -897,6 +880,87 @@ abstract class CI_DB_driver {
// --------------------------------------------------------------------
/**
+ * Begin Transaction
+ *
+ * @param bool $test_mode
+ * @return bool
+ */
+ public function trans_begin($test_mode = FALSE)
+ {
+ if ( ! $this->trans_enabled)
+ {
+ return FALSE;
+ }
+ // When transactions are nested we only begin/commit/rollback the outermost ones
+ elseif ($this->_trans_depth > 0)
+ {
+ $this->_trans_depth++;
+ return TRUE;
+ }
+
+ // Reset the transaction failure flag.
+ // If the $test_mode flag is set to TRUE transactions will be rolled back
+ // even if the queries produce a successful result.
+ $this->_trans_failure = ($test_mode === TRUE);
+
+ if ($this->_trans_begin())
+ {
+ $this->_trans_depth++;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Commit Transaction
+ *
+ * @return bool
+ */
+ public function trans_commit()
+ {
+ if ( ! $this->trans_enabled OR $this->_trans_depth === 0)
+ {
+ return FALSE;
+ }
+ // When transactions are nested we only begin/commit/rollback the outermost ones
+ elseif ($this->_trans_depth > 1 OR $this->_trans_commit())
+ {
+ $this->_trans_depth--;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Rollback Transaction
+ *
+ * @return bool
+ */
+ public function trans_rollback()
+ {
+ if ( ! $this->trans_enabled OR $this->_trans_depth === 0)
+ {
+ return FALSE;
+ }
+ // When transactions are nested we only begin/commit/rollback the outermost ones
+ elseif ($this->_trans_depth > 1 OR $this->_trans_rollback())
+ {
+ $this->_trans_depth--;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Compile Bindings
*
* @param string the sql statement
@@ -1227,7 +1291,7 @@ abstract class CI_DB_driver {
/**
* Fetch Field Names
*
- * @param string the table name
+ * @param string $table Table name
* @return array
*/
public function list_fields($table)
@@ -1486,18 +1550,18 @@ abstract class CI_DB_driver {
? '\s+'.preg_quote(trim(sprintf($this->_like_escape_str, $this->_like_escape_chr)), '/')
: '';
$_operators = array(
- '\s*(?:<|>|!)?=\s*', // =, <=, >=, !=
- '\s*<>?\s*', // <, <>
- '\s*>\s*', // >
- '\s+IS NULL', // IS NULL
- '\s+IS NOT NULL', // IS NOT NULL
- '\s+EXISTS\s*\([^\)]+\)', // EXISTS(sql)
- '\s+NOT EXISTS\s*\([^\)]+\)', // NOT EXISTS(sql)
- '\s+BETWEEN\s+\S+\s+AND\s+\S+', // BETWEEN value AND value
- '\s+IN\s*\([^\)]+\)', // IN(list)
- '\s+NOT IN\s*\([^\)]+\)', // NOT IN (list)
- '\s+LIKE\s+\S+'.$_les, // LIKE 'expr'[ ESCAPE '%s']
- '\s+NOT LIKE\s+\S+'.$_les // NOT LIKE 'expr'[ ESCAPE '%s']
+ '\s*(?:<|>|!)?=\s*', // =, <=, >=, !=
+ '\s*<>?\s*', // <, <>
+ '\s*>\s*', // >
+ '\s+IS NULL', // IS NULL
+ '\s+IS NOT NULL', // IS NOT NULL
+ '\s+EXISTS\s*\([^\)]+\)', // EXISTS(sql)
+ '\s+NOT EXISTS\s*\([^\)]+\)', // NOT EXISTS(sql)
+ '\s+BETWEEN\s+', // BETWEEN value AND value
+ '\s+IN\s*\([^\)]+\)', // IN(list)
+ '\s+NOT IN\s*\([^\)]+\)', // NOT IN (list)
+ '\s+LIKE\s+\S.*('.$_les.')?', // LIKE 'expr'[ ESCAPE '%s']
+ '\s+NOT LIKE\s+\S.*('.$_les.')?' // NOT LIKE 'expr'[ ESCAPE '%s']
);
}
@@ -1760,13 +1824,13 @@ abstract class CI_DB_driver {
//
// Added exception for single quotes as well, we don't want to alter
// literal strings. -- Narf
- if (strpos($item, '(') !== FALSE OR strpos($item, "'") !== FALSE)
+ if (strcspn($item, "()'") !== strlen($item))
{
return $item;
}
// Convert tabs or multiple spaces into single spaces
- $item = preg_replace('/\s+/', ' ', $item);
+ $item = preg_replace('/\s+/', ' ', trim($item));
// If the item has an alias declaration we remove it and set it aside.
// Note: strripos() is used in order to support spaces in table names
@@ -1794,12 +1858,15 @@ abstract class CI_DB_driver {
// with an alias. While we're at it, we will escape the components
if (strpos($item, '.') !== FALSE)
{
- $parts = explode('.', $item);
+ $parts = explode('.', $item);
// Does the first segment of the exploded item match
// one of the aliases previously identified? If so,
// we have nothing more to do other than escape the item
- if (in_array($parts[0], $this->qb_aliased_tables))
+ //
+ // NOTE: The ! empty() condition prevents this method
+ // from breaking when QB isn't enabled.
+ if ( ! empty($this->qb_aliased_tables) && in_array($parts[0], $this->qb_aliased_tables))
{
if ($protect_identifiers === TRUE)
{
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index f6ee2a63a..f9cf76a14 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -143,7 +143,7 @@ abstract class CI_DB_forge {
protected $_unsigned = TRUE;
/**
- * NULL value representatin in CREATE/ALTER TABLE statements
+ * NULL value representation in CREATE/ALTER TABLE statements
*
* @var string
*/
@@ -239,6 +239,12 @@ abstract class CI_DB_forge {
*/
public function add_key($key, $primary = FALSE)
{
+ // DO NOT change this! This condition is only applicable
+ // for PRIMARY keys because you can only have one such,
+ // and therefore all fields you add to it will be included
+ // in the same, composite PRIMARY KEY.
+ //
+ // It's not the same for regular indexes.
if ($primary === TRUE && is_array($key))
{
foreach ($key as $one)
@@ -453,12 +459,7 @@ abstract class CI_DB_forge {
return ($this->db->db_debug) ? $this->db->display_error('db_table_name_required') : FALSE;
}
- $query = $this->_drop_table($this->db->dbprefix.$table_name, $if_exists);
- if ($query === FALSE)
- {
- return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
- }
- elseif ($query === TRUE)
+ if (($query = $this->_drop_table($this->db->dbprefix.$table_name, $if_exists)) === TRUE)
{
return TRUE;
}
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index 79cbfb3ad..cf1100d27 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -794,13 +794,23 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$not = ($not) ? ' NOT' : '';
- $where_in = array();
- foreach ($values as $value)
+ if ($escape === TRUE)
{
- $where_in[] = $this->escape($value);
+ $where_in = array();
+ foreach ($values as $value)
+ {
+ $where_in[] = $this->escape($value);
+ }
}
+ else
+ {
+ $where_in = array_values($values);
+ }
+
+ $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
+ ? $this->_group_get_type('')
+ : $this->_group_get_type($type);
- $prefix = (count($this->qb_where) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type);
$where_in = array(
'condition' => $prefix.$key.$not.' IN('.implode(', ', $where_in).')',
'escape' => $escape
@@ -918,13 +928,18 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
}
is_bool($escape) OR $escape = $this->_protect_identifiers;
+ // lowercase $side in case somebody writes e.g. 'BEFORE' instead of 'before' (doh)
+ $side = strtolower($side);
foreach ($field as $k => $v)
{
$prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
? $this->_group_get_type('') : $this->_group_get_type($type);
- $v = $this->escape_like_str($v);
+ if ($escape === TRUE)
+ {
+ $v = $this->escape_like_str($v);
+ }
if ($side === 'none')
{
@@ -944,7 +959,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
}
// some platforms require an escape sequence definition for LIKE wildcards
- if ($this->_like_escape_str !== '')
+ if ($escape === TRUE && $this->_like_escape_str !== '')
{
$like_statement .= sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
@@ -1292,7 +1307,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* Compiles a SELECT query string and returns the sql.
*
* @param string the table name to select from (optional)
- * @param bool TRUE: resets QB values; FALSE: leave QB vaules alone
+ * @param bool TRUE: resets QB values; FALSE: leave QB values alone
* @return string
*/
public function get_compiled_select($table = '', $reset = TRUE)
@@ -1353,9 +1368,10 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* 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 +1382,11 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$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)
{
@@ -1729,7 +1749,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
return FALSE;
}
- $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set);
+ $sql = $this->_update($this->qb_from[0], $this->qb_set);
if ($reset === TRUE)
{
@@ -1777,7 +1797,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$this->limit($limit);
}
- $sql = $this->_update($this->protect_identifiers($this->qb_from[0], TRUE, NULL, FALSE), $this->qb_set);
+ $sql = $this->_update($this->qb_from[0], $this->qb_set);
$this->_reset_write();
return $this->query($sql);
}
@@ -1794,7 +1814,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* @param string the table to update data on
* @return bool
*/
- protected function _validate_update($table = '')
+ protected function _validate_update($table)
{
if (count($this->qb_set) === 0)
{
@@ -1803,7 +1823,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
if ($table !== '')
{
- $this->qb_from[0] = $table;
+ $this->qb_from = array($this->protect_identifiers($table, TRUE, NULL, FALSE));
}
elseif ( ! isset($this->qb_from[0]))
{
@@ -2085,10 +2105,13 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
}
elseif (is_array($table))
{
+ empty($where) && $reset_data = FALSE;
+
foreach ($table as $single_table)
{
$this->delete($single_table, $where, $limit, $reset_data);
}
+
return;
}
else
@@ -2248,7 +2271,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
else
{
// Cycle through the "select" portion of the query and prep each column name.
- // The reason we protect identifiers here rather then in the select() function
+ // The reason we protect identifiers here rather than in the select() function
// is because until the user calls the from() function we don't know if there are aliases
foreach ($this->qb_select as $key => $val)
{
@@ -2319,7 +2342,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
// Split multiple conditions
$conditions = preg_split(
- '/(\s*AND\s+|\s*OR\s+)/i',
+ '/((?:^|\s+)AND\s+|(?:^|\s+)OR\s+)/i',
$this->{$qb_key}[$i]['condition'],
-1,
PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php
index 57356ac53..b51893e18 100644
--- a/system/database/DB_utility.php
+++ b/system/database/DB_utility.php
@@ -249,16 +249,17 @@ abstract class CI_DB_utility {
$out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $name).$enclosure.$delim;
}
- $out = substr(rtrim($out), 0, -strlen($delim)).$newline;
+ $out = substr($out, 0, -strlen($delim)).$newline;
// Next blast through the result array and build out the rows
while ($row = $query->unbuffered_row('array'))
{
+ $line = array();
foreach ($row as $item)
{
- $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $item).$enclosure.$delim;
+ $line[] = $enclosure.str_replace($enclosure, $enclosure.$enclosure, $item).$enclosure;
}
- $out = substr(rtrim($out), 0, -strlen($delim)).$newline;
+ $out .= implode($delim, $line).$newline;
}
return $out;
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
index 402117978..65f4adb3f 100644
--- a/system/database/drivers/cubrid/cubrid_driver.php
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -163,10 +163,6 @@ class CI_DB_cubrid_driver extends CI_DB {
{
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
@@ -191,25 +187,17 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+ if (($autocommit = cubrid_get_autocommit($this->conn_id)) === NULL)
{
- return TRUE;
+ return FALSE;
}
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
- if (cubrid_get_autocommit($this->conn_id))
+ elseif ($autocommit === TRUE)
{
- cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_FALSE);
+ return cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_FALSE);
}
return TRUE;
@@ -222,19 +210,16 @@ class CI_DB_cubrid_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+ if ( ! cubrid_commit($this->conn_id))
{
- return TRUE;
+ return FALSE;
}
- cubrid_commit($this->conn_id);
-
if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
{
- cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
+ return cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
}
return TRUE;
@@ -247,16 +232,13 @@ class CI_DB_cubrid_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+ if ( ! cubrid_rollback($this->conn_id))
{
- return TRUE;
+ return FALSE;
}
- cubrid_rollback($this->conn_id);
-
if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
{
cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
diff --git a/system/database/drivers/cubrid/index.html b/system/database/drivers/cubrid/index.html
index c942a79ce..b702fbc39 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/ibase_driver.php b/system/database/drivers/ibase/ibase_driver.php
index 529c320cd..82550d51b 100644
--- a/system/database/drivers/ibase/ibase_driver.php
+++ b/system/database/drivers/ibase/ibase_driver.php
@@ -134,24 +134,16 @@ class CI_DB_ibase_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+ if (($trans_handle = ibase_trans($this->conn_id)) === FALSE)
{
- return TRUE;
+ return FALSE;
}
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
- $this->_ibase_trans = ibase_trans($this->conn_id);
-
+ $this->_ibase_trans = $trans_handle;
return TRUE;
}
@@ -162,15 +154,15 @@ class CI_DB_ibase_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans->depth > 0)
+ if (ibase_commit($this->_ibase_trans))
{
+ $this->_ibase_trans = NULL;
return TRUE;
}
- return ibase_commit($this->_ibase_trans);
+ return FALSE;
}
// --------------------------------------------------------------------
@@ -180,15 +172,15 @@ class CI_DB_ibase_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+ if (ibase_rollback($this->_ibase_trans))
{
+ $this->_ibase_trans = NULL;
return TRUE;
}
- return ibase_rollback($this->_ibase_trans);
+ return FALSE;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/ibase/index.html b/system/database/drivers/ibase/index.html
index c942a79ce..b702fbc39 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 c942a79ce..b702fbc39 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 c942a79ce..b702fbc39 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/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 8f15d8d69..883973ae1 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -182,22 +182,10 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
return $this->simple_query('BEGIN TRAN');
}
@@ -208,14 +196,8 @@ class CI_DB_mssql_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
return $this->simple_query('COMMIT TRAN');
}
@@ -226,14 +208,8 @@ class CI_DB_mssql_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
return $this->simple_query('ROLLBACK TRAN');
}
@@ -381,9 +357,19 @@ class CI_DB_mssql_driver extends CI_DB {
*/
public function error()
{
- $query = $this->query('SELECT @@ERROR AS code');
- $query = $query->row();
- return array('code' => $query->code, 'message' => mssql_get_last_message());
+ // We need this because the error info is discarded by the
+ // server the first time you request it, and query() already
+ // calls error() once for logging purposes when a query fails.
+ static $error = array('code' => 0, 'message' => NULL);
+
+ $message = mssql_get_last_message();
+ if ( ! empty($message))
+ {
+ $error['code'] = $this->query('SELECT @@ERROR AS code')->row()->code;
+ $error['message'] = $message;
+ }
+
+ return $error;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysql/index.html b/system/database/drivers/mysql/index.html
index c942a79ce..b702fbc39 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 f8e9b6d61..9c630d0d6 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -223,10 +223,6 @@ class CI_DB_mysql_driver extends CI_DB {
{
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)
{
@@ -276,25 +272,12 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
$this->simple_query('SET AUTOCOMMIT=0');
- $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
- return TRUE;
+ return $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
}
// --------------------------------------------------------------------
@@ -304,17 +287,15 @@ class CI_DB_mysql_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+ if ($this->simple_query('COMMIT'))
{
+ $this->simple_query('SET AUTOCOMMIT=1');
return TRUE;
}
- $this->simple_query('COMMIT');
- $this->simple_query('SET AUTOCOMMIT=1');
- return TRUE;
+ return FALSE;
}
// --------------------------------------------------------------------
@@ -324,17 +305,15 @@ class CI_DB_mysql_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+ if ($this->simple_query('ROLLBACK'))
{
+ $this->simple_query('SET AUTOCOMMIT=1');
return TRUE;
}
- $this->simple_query('ROLLBACK');
- $this->simple_query('SET AUTOCOMMIT=1');
- return TRUE;
+ return FALSE;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysqli/index.html b/system/database/drivers/mysqli/index.html
index c942a79ce..b702fbc39 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 22a8ba678..827470078 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -102,7 +102,6 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* @param bool $persistent
* @return object
- * @todo SSL support
*/
public function db_connect($persistent = FALSE)
{
@@ -132,8 +131,52 @@ class CI_DB_mysqli_driver extends CI_DB {
$mysqli->options(MYSQLI_INIT_COMMAND, 'SET SESSION sql_mode="STRICT_ALL_TABLES"');
}
- return $mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, $socket, $client_flags)
- ? $mysqli : FALSE;
+ if (is_array($this->encrypt))
+ {
+ $ssl = array();
+ empty($this->encrypt['ssl_key']) OR $ssl['key'] = $this->encrypt['ssl_key'];
+ empty($this->encrypt['ssl_cert']) OR $ssl['cert'] = $this->encrypt['ssl_cert'];
+ empty($this->encrypt['ssl_ca']) OR $ssl['ca'] = $this->encrypt['ssl_ca'];
+ empty($this->encrypt['ssl_capath']) OR $ssl['capath'] = $this->encrypt['ssl_capath'];
+ empty($this->encrypt['ssl_cipher']) OR $ssl['cipher'] = $this->encrypt['ssl_cipher'];
+
+ if ( ! empty($ssl))
+ {
+ if ( ! empty($this->encrypt['ssl_verify']) && defined('MYSQLI_OPT_SSL_VERIFY_SERVER_CERT'))
+ {
+ $mysqli->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, TRUE);
+ }
+
+ $client_flags |= MYSQLI_CLIENT_SSL;
+ $mysqli->ssl_set(
+ isset($ssl['key']) ? $ssl['key'] : NULL,
+ isset($ssl['cert']) ? $ssl['cert'] : NULL,
+ isset($ssl['ca']) ? $ssl['ca'] : NULL,
+ isset($ssl['capath']) ? $ssl['capath'] : NULL,
+ isset($ssl['cipher']) ? $ssl['cipher'] : NULL
+ );
+ }
+ }
+
+ if ($mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, $socket, $client_flags))
+ {
+ // Prior to version 5.7.3, MySQL silently downgrades to an unencrypted connection if SSL setup fails
+ if (
+ ($client_flags & MYSQLI_CLIENT_SSL)
+ && version_compare($mysqli->client_info, '5.7.3', '<=')
+ && empty($mysqli->query("SHOW STATUS LIKE 'ssl_cipher'")->fetch_object()->Value)
+ )
+ {
+ $mysqli->close();
+ $message = 'MySQLi was configured for an SSL connection, but got an unencrypted connection instead!';
+ log_message('error', $message);
+ return ($this->db->db_debug) ? $this->db->display_error($message, '', TRUE) : FALSE;
+ }
+
+ return $mysqli;
+ }
+
+ return FALSE;
}
// --------------------------------------------------------------------
@@ -204,10 +247,6 @@ class CI_DB_mysqli_driver extends CI_DB {
{
return $this->data_cache['version'];
}
- elseif ( ! $this->conn_id)
- {
- $this->initialize();
- }
return $this->data_cache['version'] = $this->conn_id->server_info;
}
@@ -252,22 +291,10 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
$this->conn_id->autocommit(FALSE);
return is_php('5.5')
? $this->conn_id->begin_transaction()
@@ -281,14 +308,8 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
if ($this->conn_id->commit())
{
$this->conn_id->autocommit(TRUE);
@@ -305,14 +326,8 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
if ($this->conn_id->rollback())
{
$this->conn_id->autocommit(TRUE);
diff --git a/system/database/drivers/oci8/index.html b/system/database/drivers/oci8/index.html
index c942a79ce..b702fbc39 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 b87b41112..916ddeb90 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -102,6 +102,14 @@ class CI_DB_oci8_driver extends CI_DB {
// --------------------------------------------------------------------
/**
+ * Reset $stmt_id flag
+ *
+ * Used by stored_procedure() to prevent _execute() from
+ * re-setting the statement ID.
+ */
+ protected $_reset_stmt_id = TRUE;
+
+ /**
* List of reserved identifiers
*
* Identifiers that must NOT be escaped.
@@ -243,10 +251,6 @@ class CI_DB_oci8_driver extends CI_DB {
{
return $this->data_cache['version'];
}
- elseif ( ! $this->conn_id)
- {
- $this->initialize();
- }
if ( ! $this->conn_id OR ($version = oci_server_version($this->conn_id)) === FALSE)
{
@@ -269,26 +273,13 @@ class CI_DB_oci8_driver extends CI_DB {
/* Oracle must parse the query before it is run. All of the actions with
* the query are based on the statement id returned by oci_parse().
*/
- $this->stmt_id = FALSE;
- $this->_set_stmt_id($sql);
- oci_set_prefetch($this->stmt_id, 1000);
- return oci_execute($this->stmt_id, $this->commit_mode);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Generate a statement ID
- *
- * @param string $sql an SQL query
- * @return void
- */
- protected function _set_stmt_id($sql)
- {
- if ( ! is_resource($this->stmt_id))
+ if ($this->_reset_stmt_id === TRUE)
{
$this->stmt_id = oci_parse($this->conn_id, $sql);
}
+
+ oci_set_prefetch($this->stmt_id, 1000);
+ return oci_execute($this->stmt_id, $this->commit_mode);
}
// --------------------------------------------------------------------
@@ -315,22 +306,22 @@ class CI_DB_oci8_driver extends CI_DB {
*
* params array keys
*
- * KEY OPTIONAL NOTES
- * name no the name of the parameter should be in :<param_name> format
- * value no the value of the parameter. If this is an OUT or IN OUT parameter,
- * this should be a reference to a variable
- * type yes the type of the parameter
- * length yes the max size of the parameter
+ * KEY OPTIONAL NOTES
+ * name no the name of the parameter should be in :<param_name> format
+ * value no the value of the parameter. If this is an OUT or IN OUT parameter,
+ * this should be a reference to a variable
+ * type yes the type of the parameter
+ * length yes the max size of the parameter
*/
- public function stored_procedure($package, $procedure, $params)
+ public function stored_procedure($package, $procedure, array $params)
{
- if ($package === '' OR $procedure === '' OR ! is_array($params))
+ if ($package === '' OR $procedure === '')
{
log_message('error', 'Invalid query: '.$package.'.'.$procedure);
return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE;
}
- // build the query string
+ // Build the query string
$sql = 'BEGIN '.$package.'.'.$procedure.'(';
$have_cursor = FALSE;
@@ -345,10 +336,12 @@ class CI_DB_oci8_driver extends CI_DB {
}
$sql = trim($sql, ',').'); END;';
- $this->stmt_id = FALSE;
- $this->_set_stmt_id($sql);
+ $this->_reset_stmt_id = FALSE;
+ $this->stmt_id = oci_parse($this->conn_id, $sql);
$this->_bind_params($params);
- return $this->query($sql, FALSE, $have_cursor);
+ $result = $this->query($sql, FALSE, $have_cursor);
+ $this->_reset_stmt_id = TRUE;
+ return $result;
}
// --------------------------------------------------------------------
@@ -385,27 +378,10 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
$this->commit_mode = is_php('5.3.2') ? OCI_NO_AUTO_COMMIT : OCI_DEFAULT;
return TRUE;
}
@@ -417,20 +393,10 @@ class CI_DB_oci8_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
$this->commit_mode = OCI_COMMIT_ON_SUCCESS;
+
return oci_commit($this->conn_id);
}
@@ -441,14 +407,8 @@ class CI_DB_oci8_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
$this->commit_mode = OCI_COMMIT_ON_SUCCESS;
return oci_rollback($this->conn_id);
}
@@ -577,7 +537,7 @@ class CI_DB_oci8_driver extends CI_DB {
{
$default = '';
}
- $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ $retval[$i]->default = $default;
}
return $retval;
diff --git a/system/database/drivers/odbc/index.html b/system/database/drivers/odbc/index.html
index c942a79ce..b702fbc39 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/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index f5d77a147..409284b44 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -143,22 +143,10 @@ class CI_DB_odbc_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
return odbc_autocommit($this->conn_id, FALSE);
}
@@ -169,17 +157,15 @@ class CI_DB_odbc_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+ if (odbc_commit($this->conn_id))
{
+ odbc_autocommit($this->conn_id, TRUE);
return TRUE;
}
- $ret = odbc_commit($this->conn_id);
- odbc_autocommit($this->conn_id, TRUE);
- return $ret;
+ return FALSE;
}
// --------------------------------------------------------------------
@@ -189,17 +175,15 @@ class CI_DB_odbc_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+ if (odbc_rollback($this->conn_id))
{
+ odbc_autocommit($this->conn_id, TRUE);
return TRUE;
}
- $ret = odbc_rollback($this->conn_id);
- odbc_autocommit($this->conn_id, TRUE);
- return $ret;
+ return FALSE;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/pdo/index.html b/system/database/drivers/pdo/index.html
index c942a79ce..b702fbc39 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 68aeb0eef..8c5a5e7e3 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -156,10 +156,6 @@ class CI_DB_pdo_driver extends CI_DB {
{
return $this->data_cache['version'];
}
- elseif ( ! $this->conn_id)
- {
- $this->initialize();
- }
// Not all subdrivers support the getAttribute() method
try
@@ -190,22 +186,10 @@ class CI_DB_pdo_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
return $this->conn_id->beginTransaction();
}
@@ -216,14 +200,8 @@ class CI_DB_pdo_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
return $this->conn_id->commit();
}
@@ -234,14 +212,8 @@ class CI_DB_pdo_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
return $this->conn_id->rollBack();
}
diff --git a/system/database/drivers/pdo/subdrivers/index.html b/system/database/drivers/pdo/subdrivers/index.html
index c942a79ce..b702fbc39 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/pdo/subdrivers/pdo_4d_driver.php b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
index cf5a0c77f..7a767ef40 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
@@ -158,7 +158,7 @@ class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver {
* @param string $table
* @param array $values
* @return string
- */
+ */
protected function _update($table, $values)
{
$this->qb_limit = FALSE;
diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
index c8d7c770d..ae2b9983b 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
@@ -154,7 +154,7 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver {
*/
protected function _list_tables($prefix_limit = FALSE)
{
- return 'SELECT '.$this->escape_identifiers('name')
+ $sql = 'SELECT '.$this->escape_identifiers('name')
.' FROM '.$this->escape_identifiers('sysobjects')
.' WHERE '.$this->escape_identifiers('type')." = 'U'";
@@ -227,7 +227,7 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver {
* @param string $table
* @param array $values
* @return string
- */
+ */
protected function _update($table, $values)
{
$this->qb_limit = FALSE;
diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
index 3bd5c9354..0bafde861 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
@@ -211,7 +211,7 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver {
*
* @param string $table
* @return string
- */
+ */
protected function _truncate($table)
{
return 'DELETE FROM '.$table;
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
index 67dc5f5ec..e9d25cebc 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
@@ -119,7 +119,6 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {
*
* @param bool $persistent
* @return object
- * @todo SSL support
*/
public function db_connect($persistent = FALSE)
{
@@ -151,7 +150,59 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {
$this->options[PDO::MYSQL_ATTR_COMPRESS] = TRUE;
}
- return parent::db_connect($persistent);
+ // SSL support was added to PDO_MYSQL in PHP 5.3.7
+ if (is_array($this->encrypt) && is_php('5.3.7'))
+ {
+ $ssl = array();
+ empty($this->encrypt['ssl_key']) OR $ssl[PDO::MYSQL_ATTR_SSL_KEY] = $this->encrypt['ssl_key'];
+ empty($this->encrypt['ssl_cert']) OR $ssl[PDO::MYSQL_ATTR_SSL_CERT] = $this->encrypt['ssl_cert'];
+ empty($this->encrypt['ssl_ca']) OR $ssl[PDO::MYSQL_ATTR_SSL_CA] = $this->encrypt['ssl_ca'];
+ empty($this->encrypt['ssl_capath']) OR $ssl[PDO::MYSQL_ATTR_SSL_CAPATH] = $this->encrypt['ssl_capath'];
+ empty($this->encrypt['ssl_cipher']) OR $ssl[PDO::MYSQL_ATTR_SSL_CIPHER] = $this->encrypt['ssl_cipher'];
+
+ // DO NOT use array_merge() here!
+ // It re-indexes numeric keys and the PDO_MYSQL_ATTR_SSL_* constants are integers.
+ empty($ssl) OR $this->options += $ssl;
+ }
+
+ // Prior to version 5.7.3, MySQL silently downgrades to an unencrypted connection if SSL setup fails
+ if (
+ ($pdo = parent::db_connect($persistent)) !== FALSE
+ && ! empty($ssl)
+ && version_compare($pdo->getAttribute(PDO::ATTR_CLIENT_VERSION), '5.7.3', '<=')
+ && empty($pdo->query("SHOW STATUS LIKE 'ssl_cipher'")->fetchObject()->Value)
+ )
+ {
+ $message = 'PDO_MYSQL was configured for an SSL connection, but got an unencrypted connection instead!';
+ log_message('error', $message);
+ return ($this->db->db_debug) ? $this->db->display_error($message, '', TRUE) : FALSE;
+ }
+
+ return $pdo;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select the database
+ *
+ * @param string $database
+ * @return bool
+ */
+ public function db_select($database = '')
+ {
+ if ($database === '')
+ {
+ $database = $this->database;
+ }
+
+ if (FALSE !== $this->simple_query('USE '.$this->escape_identifiers($database)))
+ {
+ $this->database = $database;
+ return TRUE;
+ }
+
+ return FALSE;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php
index f07f49f84..409e6501b 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php
@@ -121,17 +121,31 @@ class CI_DB_pdo_sqlite_driver extends CI_DB_pdo_driver {
// --------------------------------------------------------------------
/**
- * Show column query
+ * Fetch Field Names
*
- * Generates a platform-specific query string so that the column names can be fetched
- *
- * @param string $table
- * @return string
+ * @param string $table Table name
+ * @return array
*/
- protected function _list_columns($table = '')
+ public function list_fields($table)
{
- // Not supported
- return FALSE;
+ // Is there a cached result?
+ if (isset($this->data_cache['field_names'][$table]))
+ {
+ return $this->data_cache['field_names'][$table];
+ }
+
+ if (($result = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
+ {
+ return FALSE;
+ }
+
+ $this->data_cache['field_names'][$table] = array();
+ foreach ($result->result_array() as $row)
+ {
+ $this->data_cache['field_names'][$table][] = $row['name'];
+ }
+
+ return $this->data_cache['field_names'][$table];
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php b/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php
index 28faaddb7..15afbdef5 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php
@@ -89,6 +89,7 @@ class CI_DB_pdo_sqlite_forge extends CI_DB_pdo_forge {
if (version_compare($this->db->version(), '3.3', '<'))
{
$this->_create_table_if = FALSE;
+ $this->_drop_table_if = FALSE;
}
}
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
index b5bdbf91a..f8ae5f6db 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
@@ -183,7 +183,7 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver {
*/
protected function _list_tables($prefix_limit = FALSE)
{
- return 'SELECT '.$this->escape_identifiers('name')
+ $sql = 'SELECT '.$this->escape_identifiers('name')
.' FROM '.$this->escape_identifiers('sysobjects')
.' WHERE '.$this->escape_identifiers('type')." = 'U'";
diff --git a/system/database/drivers/postgre/index.html b/system/database/drivers/postgre/index.html
index c942a79ce..b702fbc39 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 3f3e3f018..b1df326f7 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -213,10 +213,6 @@ class CI_DB_postgre_driver extends CI_DB {
{
return $this->data_cache['version'];
}
- elseif ( ! $this->conn_id)
- {
- $this->initialize();
- }
if ( ! $this->conn_id OR ($pg_version = pg_version($this->conn_id)) === FALSE)
{
@@ -251,22 +247,10 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
return (bool) pg_query($this->conn_id, 'BEGIN');
}
@@ -277,14 +261,8 @@ class CI_DB_postgre_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
return (bool) pg_query($this->conn_id, 'COMMIT');
}
@@ -295,14 +273,8 @@ class CI_DB_postgre_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
return (bool) pg_query($this->conn_id, 'ROLLBACK');
}
diff --git a/system/database/drivers/sqlite/index.html b/system/database/drivers/sqlite/index.html
index c942a79ce..b702fbc39 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/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index 9d9caa0b4..e000a8e50 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -122,24 +122,11 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
- $this->simple_query('BEGIN TRANSACTION');
- return TRUE;
+ return $this->simple_query('BEGIN TRANSACTION');
}
// --------------------------------------------------------------------
@@ -149,16 +136,9 @@ class CI_DB_sqlite_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- $this->simple_query('COMMIT');
- return TRUE;
+ return $this->simple_query('COMMIT');
}
// --------------------------------------------------------------------
@@ -168,16 +148,9 @@ class CI_DB_sqlite_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- $this->simple_query('ROLLBACK');
- return TRUE;
+ return $this->simple_query('ROLLBACK');
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlite3/index.html b/system/database/drivers/sqlite3/index.html
index c942a79ce..b702fbc39 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/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php
index fdbe94939..73e453785 100644
--- a/system/database/drivers/sqlite3/sqlite3_driver.php
+++ b/system/database/drivers/sqlite3/sqlite3_driver.php
@@ -134,22 +134,10 @@ class CI_DB_sqlite3_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
return $this->conn_id->exec('BEGIN TRANSACTION');
}
@@ -160,14 +148,8 @@ class CI_DB_sqlite3_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
return $this->conn_id->exec('END TRANSACTION');
}
@@ -178,14 +160,8 @@ class CI_DB_sqlite3_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
return $this->conn_id->exec('ROLLBACK');
}
@@ -247,17 +223,31 @@ class CI_DB_sqlite3_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Show column query
+ * Fetch Field Names
*
- * Generates a platform-specific query string so that the column names can be fetched
- *
- * @param string $table
- * @return string
+ * @param string $table Table name
+ * @return array
*/
- protected function _list_columns($table = '')
+ public function list_fields($table)
{
- // Not supported
- return FALSE;
+ // Is there a cached result?
+ if (isset($this->data_cache['field_names'][$table]))
+ {
+ return $this->data_cache['field_names'][$table];
+ }
+
+ if (($result = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
+ {
+ return FALSE;
+ }
+
+ $this->data_cache['field_names'][$table] = array();
+ foreach ($result->result_array() as $row)
+ {
+ $this->data_cache['field_names'][$table][] = $row['name'];
+ }
+
+ return $this->data_cache['field_names'][$table];
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlite3/sqlite3_forge.php b/system/database/drivers/sqlite3/sqlite3_forge.php
index 69f65b6f3..24690ba20 100644
--- a/system/database/drivers/sqlite3/sqlite3_forge.php
+++ b/system/database/drivers/sqlite3/sqlite3_forge.php
@@ -74,7 +74,8 @@ class CI_DB_sqlite3_forge extends CI_DB_forge {
if (version_compare($this->db->version(), '3.3', '<'))
{
- $this->create_table_if = FALSE;
+ $this->_create_table_if = FALSE;
+ $this->_drop_table_if = FALSE;
}
}
diff --git a/system/database/drivers/sqlsrv/index.html b/system/database/drivers/sqlsrv/index.html
index c942a79ce..b702fbc39 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 8f17c8f96..414669a4b 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -141,13 +141,14 @@ class CI_DB_sqlsrv_driver extends CI_DB {
unset($connection['UID'], $connection['PWD']);
}
- $this->conn_id = sqlsrv_connect($this->hostname, $connection);
-
- // Determine how identifiers are escaped
- $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
- $query = $query->row_array();
- $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
- $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
+ if (FALSE !== ($this->conn_id = sqlsrv_connect($this->hostname, $connection)))
+ {
+ // Determine how identifiers are escaped
+ $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
+ $query = $query->row_array();
+ $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
+ $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
+ }
return $this->conn_id;
}
@@ -196,22 +197,10 @@ class CI_DB_sqlsrv_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool $test_mode
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE);
-
return sqlsrv_begin_transaction($this->conn_id);
}
@@ -222,14 +211,8 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
return sqlsrv_commit($this->conn_id);
}
@@ -240,14 +223,8 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
- {
- return TRUE;
- }
-
return sqlsrv_rollback($this->conn_id);
}
@@ -274,9 +251,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
public function insert_id()
{
- $query = $this->query('SELECT @@IDENTITY AS insert_id');
- $query = $query->row();
- return $query->insert_id;
+ return $this->query('SELECT SCOPE_IDENTITY() AS insert_id')->row()->insert_id;
}
// --------------------------------------------------------------------
@@ -292,10 +267,6 @@ class CI_DB_sqlsrv_driver extends CI_DB {
{
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 c942a79ce..b702fbc39 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 c942a79ce..b702fbc39 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/array_helper.php b/system/helpers/array_helper.php
index e07b52bb5..2ce55b9c4 100644
--- a/system/helpers/array_helper.php
+++ b/system/helpers/array_helper.php
@@ -62,7 +62,7 @@ if ( ! function_exists('element'))
* @param mixed
* @return mixed depends on what the array contains
*/
- function element($item, $array, $default = NULL)
+ function element($item, array $array, $default = NULL)
{
return array_key_exists($item, $array) ? $array[$item] : $default;
}
@@ -99,7 +99,7 @@ if ( ! function_exists('elements'))
* @param mixed
* @return mixed depends on what the array contains
*/
- function elements($items, $array, $default = NULL)
+ function elements($items, array $array, $default = NULL)
{
$return = array();
diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php
index 201987ac8..85bcfb5a0 100644
--- a/system/helpers/captcha_helper.php
+++ b/system/helpers/captcha_helper.php
@@ -125,9 +125,94 @@ if ( ! function_exists('create_captcha'))
if (empty($word))
{
$word = '';
- for ($i = 0, $mt_rand_max = strlen($pool) - 1; $i < $word_length; $i++)
+ $pool_length = strlen($pool);
+ $rand_max = $pool_length - 1;
+
+ // PHP7 or a suitable polyfill
+ if (function_exists('random_int'))
+ {
+ try
+ {
+ for ($i = 0; $i < $word_length; $i++)
+ {
+ $word .= $pool[random_int(0, $rand_max)];
+ }
+ }
+ catch (Exception $e)
+ {
+ // This means fallback to the next possible
+ // alternative to random_int()
+ $word = '';
+ }
+ }
+ }
+
+ if (empty($word))
+ {
+ // Nobody will have a larger character pool than
+ // 256 characters, but let's handle it just in case ...
+ //
+ // No, I do not care that the fallback to mt_rand() can
+ // handle it; if you trigger this, you're very obviously
+ // trying to break it. -- Narf
+ if ($pool_length > 256)
+ {
+ return FALSE;
+ }
+
+ // We'll try using the operating system's PRNG first,
+ // which we can access through CI_Security::get_random_bytes()
+ $security = get_instance()->security;
+
+ // To avoid numerous get_random_bytes() calls, we'll
+ // just try fetching as much bytes as we need at once.
+ if (($bytes = $security->get_random_bytes($pool_length)) !== FALSE)
+ {
+ $byte_index = $word_index = 0;
+ while ($word_index < $word_length)
+ {
+ if (($rand_index = unpack('C', $bytes[$byte_index++])) > $rand_max)
+ {
+ // Was this the last byte we have?
+ // If so, try to fetch more.
+ if ($byte_index === $pool_length)
+ {
+ // No failures should be possible if
+ // the first get_random_bytes() call
+ // didn't return FALSE, but still ...
+ for ($i = 0; $i < 5; $i++)
+ {
+ if (($bytes = $security->get_random_bytes($pool_length)) === FALSE)
+ {
+ continue;
+ }
+
+ $byte_index = 0;
+ break;
+ }
+
+ if ($bytes === FALSE)
+ {
+ // Sadly, this means fallback to mt_rand()
+ $word = '';
+ break;
+ }
+ }
+
+ continue;
+ }
+
+ $word .= $pool[$rand_index];
+ $word_index++;
+ }
+ }
+ }
+
+ if (empty($word))
+ {
+ for ($i = 0; $i < $word_length; $i++)
{
- $word .= $pool[mt_rand(0, $mt_rand_max)];
+ $word .= $pool[mt_rand(0, $rand_max)];
}
}
elseif ( ! is_string($word))
diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php
index 95c94a1b8..73f6456c4 100644
--- a/system/helpers/download_helper.php
+++ b/system/helpers/download_helper.php
@@ -69,16 +69,14 @@ if ( ! function_exists('force_download'))
}
elseif ($data === NULL)
{
- if (@is_file($filename) && ($filesize = @filesize($filename)) !== FALSE)
- {
- $filepath = $filename;
- $filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename));
- $filename = end($filename);
- }
- else
+ if ( ! @is_file($filename) OR ($filesize = @filesize($filename)) === FALSE)
{
return;
}
+
+ $filepath = $filename;
+ $filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename));
+ $filename = end($filename);
}
else
{
@@ -140,14 +138,7 @@ if ( ! function_exists('force_download'))
header('Expires: 0');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.$filesize);
-
- // Internet Explorer-specific headers
- if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE)
- {
- header('Cache-Control: no-cache, no-store, must-revalidate');
- }
-
- header('Pragma: no-cache');
+ header('Cache-Control: private, no-transform, no-store, must-revalidate');
// If we have raw data - just dump it
if ($data !== NULL)
diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php
index 8b15e60a5..f6cb1629a 100644
--- a/system/helpers/file_helper.php
+++ b/system/helpers/file_helper.php
@@ -54,7 +54,7 @@ if ( ! function_exists('read_file'))
/**
* Read File
*
- * Opens the file specfied in the path and returns it as a string.
+ * Opens the file specified in the path and returns it as a string.
*
* @todo Remove in version 3.1+.
* @deprecated 3.0.0 It is now just an alias for PHP's native file_get_contents().
@@ -343,7 +343,7 @@ if ( ! function_exists('get_mime_by_extension'))
if ( ! is_array($mimes))
{
- $mimes =& get_mimes();
+ $mimes = get_mimes();
if (empty($mimes))
{
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
index 53ee8eb11..fd807769a 100644
--- a/system/helpers/form_helper.php
+++ b/system/helpers/form_helper.php
@@ -197,7 +197,7 @@ if ( ! function_exists('form_input'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_input($data = '', $value = '', $extra = '')
@@ -208,7 +208,7 @@ if ( ! function_exists('form_input'))
'value' => $value
);
- return '<input '._parse_form_attributes($data, $defaults).$extra." />\n";
+ return '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra)." />\n";
}
}
@@ -223,7 +223,7 @@ if ( ! function_exists('form_password'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_password($data = '', $value = '', $extra = '')
@@ -245,7 +245,7 @@ if ( ! function_exists('form_upload'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_upload($data = '', $value = '', $extra = '')
@@ -253,7 +253,8 @@ if ( ! function_exists('form_upload'))
$defaults = array('type' => 'file', 'name' => '');
is_array($data) OR $data = array('name' => $data);
$data['type'] = 'file';
- return '<input '._parse_form_attributes($data, $defaults).$extra." />\n";
+
+ return '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra)." />\n";
}
}
@@ -266,7 +267,7 @@ if ( ! function_exists('form_textarea'))
*
* @param mixed $data
* @param string $value
- * @param string $extra
+ * @param mixed $extra
* @return string
*/
function form_textarea($data = '', $value = '', $extra = '')
@@ -287,7 +288,9 @@ if ( ! function_exists('form_textarea'))
unset($data['value']); // textareas don't use the value attribute
}
- return '<textarea '._parse_form_attributes($data, $defaults).$extra.'>'.html_escape($val)."</textarea>\n";
+ return '<textarea '._parse_form_attributes($data, $defaults)._attributes_to_string($extra).'>'
+ .html_escape($val)
+ ."</textarea>\n";
}
}
@@ -301,12 +304,13 @@ if ( ! function_exists('form_multiselect'))
* @param string
* @param array
* @param mixed
- * @param string
+ * @param mixed
* @return string
*/
function form_multiselect($name = '', $options = array(), $selected = array(), $extra = '')
{
- if ( ! strpos($extra, 'multiple'))
+ $extra = _attributes_to_string($extra);
+ if (stripos($extra, 'multiple') === FALSE)
{
$extra .= ' multiple="multiple"';
}
@@ -372,7 +376,7 @@ if ( ! function_exists('form_dropdown'))
$extra = _attributes_to_string($extra);
- $multiple = (count($selected) > 1 && strpos($extra, 'multiple') === FALSE) ? ' multiple="multiple"' : '';
+ $multiple = (count($selected) > 1 && stripos($extra, 'multiple') === FALSE) ? ' multiple="multiple"' : '';
$form = '<select '.rtrim(_parse_form_attributes($data, $defaults)).$extra.$multiple.">\n";
@@ -420,7 +424,7 @@ if ( ! function_exists('form_checkbox'))
* @param mixed
* @param string
* @param bool
- * @param string
+ * @param mixed
* @return string
*/
function form_checkbox($data = '', $value = '', $checked = FALSE, $extra = '')
@@ -450,7 +454,7 @@ if ( ! function_exists('form_checkbox'))
unset($defaults['checked']);
}
- return '<input '._parse_form_attributes($data, $defaults).$extra." />\n";
+ return '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra)." />\n";
}
}
@@ -464,13 +468,14 @@ if ( ! function_exists('form_radio'))
* @param mixed
* @param string
* @param bool
- * @param string
+ * @param mixed
* @return string
*/
function form_radio($data = '', $value = '', $checked = FALSE, $extra = '')
{
is_array($data) OR $data = array('name' => $data);
$data['type'] = 'radio';
+
return form_checkbox($data, $value, $checked, $extra);
}
}
@@ -484,7 +489,7 @@ if ( ! function_exists('form_submit'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_submit($data = '', $value = '', $extra = '')
@@ -495,7 +500,7 @@ if ( ! function_exists('form_submit'))
'value' => $value
);
- return '<input '._parse_form_attributes($data, $defaults).$extra." />\n";
+ return '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra)." />\n";
}
}
@@ -508,7 +513,7 @@ if ( ! function_exists('form_reset'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_reset($data = '', $value = '', $extra = '')
@@ -519,7 +524,7 @@ if ( ! function_exists('form_reset'))
'value' => $value
);
- return '<input '._parse_form_attributes($data, $defaults).$extra." />\n";
+ return '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra)." />\n";
}
}
@@ -532,7 +537,7 @@ if ( ! function_exists('form_button'))
*
* @param mixed
* @param string
- * @param string
+ * @param mixed
* @return string
*/
function form_button($data = '', $content = '', $extra = '')
@@ -548,7 +553,9 @@ if ( ! function_exists('form_button'))
unset($data['content']); // content is not an attribute
}
- return '<button '._parse_form_attributes($data, $defaults).$extra.'>'.$content."</button>\n";
+ return '<button '._parse_form_attributes($data, $defaults)._attributes_to_string($extra).'>'
+ .$content
+ ."</button>\n";
}
}
diff --git a/system/helpers/index.html b/system/helpers/index.html
index c942a79ce..b702fbc39 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/helpers/inflector_helper.php b/system/helpers/inflector_helper.php
index d8ed45df9..f2890059f 100644
--- a/system/helpers/inflector_helper.php
+++ b/system/helpers/inflector_helper.php
@@ -133,6 +133,7 @@ if ( ! function_exists('plural'))
}
$plural_rules = array(
+ '/(quiz)$/' => '\1zes', // quizzes
'/^(ox)$/' => '\1\2en', // ox
'/([m|l])ouse$/' => '\1ice', // mouse, louse
'/(matr|vert|ind)ix|ex$/' => '\1ices', // matrix, vertex, index
diff --git a/system/helpers/path_helper.php b/system/helpers/path_helper.php
index c23ec6435..c96d0b8b3 100644
--- a/system/helpers/path_helper.php
+++ b/system/helpers/path_helper.php
@@ -61,7 +61,7 @@ if ( ! function_exists('set_realpath'))
function set_realpath($path, $check_existance = FALSE)
{
// Security check to make sure the path is NOT a URL. No remote file inclusion!
- if (preg_match('#^(http:\/\/|https:\/\/|www\.|ftp|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})#i', $path))
+ if (preg_match('#^(http:\/\/|https:\/\/|www\.|ftp)#i', $path) OR filter_var($path, FILTER_VALIDATE_IP) === $path )
{
show_error('The path you submitted must be a local server path, not a URL');
}
diff --git a/system/helpers/string_helper.php b/system/helpers/string_helper.php
index 5860e15fb..637835160 100644
--- a/system/helpers/string_helper.php
+++ b/system/helpers/string_helper.php
@@ -253,7 +253,7 @@ if ( ! function_exists('increment_string'))
*/
function increment_string($str, $separator = '_', $first = 1)
{
- preg_match('/(.+)'.$separator.'([0-9]+)$/', $str, $match);
+ preg_match('/(.+)'.preg_quote($separator, '/').'([0-9]+)$/', $str, $match);
return isset($match[2]) ? $match[1].$separator.($match[2] + 1) : $str.$separator.$first;
}
}
diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php
index f2290c895..fb47036f2 100644
--- a/system/helpers/text_helper.php
+++ b/system/helpers/text_helper.php
@@ -254,7 +254,7 @@ if ( ! function_exists('word_censor'))
* word you've submitted.
*
* @param string the text string
- * @param string the array of censoered words
+ * @param string the array of censored words
* @param string the optional replacement value
* @return string
*/
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
index bf623b000..d65f92f1b 100644
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -161,7 +161,7 @@ if ( ! function_exists('anchor'))
$site_url = is_array($uri)
? site_url($uri)
- : preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri);
+ : (preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri));
if ($title === '')
{
@@ -474,7 +474,7 @@ if ( ! function_exists('url_title'))
* @param string $str Input string
* @param string $separator Word separator
* (usually '-' or '_')
- * @param bool $lowercase Wether to transform the output string to lowercase
+ * @param bool $lowercase Whether to transform the output string to lowercase
* @return string
*/
function url_title($str, $separator = '-', $lowercase = FALSE)
@@ -492,7 +492,7 @@ if ( ! function_exists('url_title'))
$trans = array(
'&.+?;' => '',
- '[^a-z0-9 _-]' => '',
+ '[^\w\d _-]' => '',
'\s+' => $separator,
'('.$q_separator.')+' => $separator
);
@@ -500,7 +500,7 @@ if ( ! function_exists('url_title'))
$str = strip_tags($str);
foreach ($trans as $key => $val)
{
- $str = preg_replace('#'.$key.'#i', $val, $str);
+ $str = preg_replace('#'.$key.'#i'.(UTF8_ENABLED ? 'u' : ''), $val, $str);
}
if ($lowercase === TRUE)
diff --git a/system/index.html b/system/index.html
index c942a79ce..b702fbc39 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 c942a79ce..b702fbc39 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 c942a79ce..b702fbc39 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/Cache.php b/system/libraries/Cache/Cache.php
index 40ac70103..0c87a5628 100644
--- a/system/libraries/Cache/Cache.php
+++ b/system/libraries/Cache/Cache.php
@@ -100,28 +100,10 @@ class CI_Cache extends CI_Driver_Library {
*/
public function __construct($config = array())
{
- $default_config = array(
- 'adapter',
- 'memcached'
- );
-
- foreach ($default_config as $key)
- {
- if (isset($config[$key]))
- {
- $param = '_'.$key;
-
- $this->{$param} = $config[$key];
- }
- }
-
+ isset($config['adapter']) && $this->_adapter = $config['adapter'];
+ isset($config['backup']) && $this->_backup_driver = $config['backup'];
isset($config['key_prefix']) && $this->key_prefix = $config['key_prefix'];
- if (isset($config['backup']) && in_array($config['backup'], $this->valid_drivers))
- {
- $this->_backup_driver = $config['backup'];
- }
-
// If the specified adapter isn't available, check the backup.
if ( ! $this->is_supported($this->_adapter))
{
@@ -196,7 +178,7 @@ class CI_Cache extends CI_Driver_Library {
*/
public function increment($id, $offset = 1)
{
- return $this->{$this->_adapter}->increment($id, $offset);
+ return $this->{$this->_adapter}->increment($this->key_prefix.$id, $offset);
}
// ------------------------------------------------------------------------
@@ -210,7 +192,7 @@ class CI_Cache extends CI_Driver_Library {
*/
public function decrement($id, $offset = 1)
{
- return $this->{$this->_adapter}->decrement($id, $offset);
+ return $this->{$this->_adapter}->decrement($this->key_prefix.$id, $offset);
}
// ------------------------------------------------------------------------
@@ -261,14 +243,13 @@ class CI_Cache extends CI_Driver_Library {
*/
public function is_supported($driver)
{
- static $support = array();
+ static $support;
- if ( ! isset($support[$driver]))
+ if ( ! isset($support, $support[$driver]))
{
$support[$driver] = $this->{$driver}->is_supported();
}
return $support[$driver];
}
-
}
diff --git a/system/libraries/Cache/drivers/Cache_file.php b/system/libraries/Cache/drivers/Cache_file.php
index 68bc1ec96..c046f3b7d 100644
--- a/system/libraries/Cache/drivers/Cache_file.php
+++ b/system/libraries/Cache/drivers/Cache_file.php
@@ -267,7 +267,7 @@ class CI_Cache_file extends CI_Driver {
*/
protected function _get($id)
{
- if ( ! file_exists($this->_cache_path.$id))
+ if ( ! is_file($this->_cache_path.$id))
{
return FALSE;
}
diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php
index b90b561c9..59cf4685d 100644
--- a/system/libraries/Cache/drivers/Cache_memcached.php
+++ b/system/libraries/Cache/drivers/Cache_memcached.php
@@ -68,6 +68,76 @@ class CI_Cache_memcached extends CI_Driver {
)
);
+ // ------------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Setup Memcache(d)
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ // Try to load memcached server info from the config file.
+ $CI =& get_instance();
+ $defaults = $this->_memcache_conf['default'];
+
+ if ($CI->config->load('memcached', TRUE, TRUE))
+ {
+ if (is_array($CI->config->config['memcached']))
+ {
+ $this->_memcache_conf = array();
+
+ foreach ($CI->config->config['memcached'] as $name => $conf)
+ {
+ $this->_memcache_conf[$name] = $conf;
+ }
+ }
+ }
+
+ if (class_exists('Memcached', FALSE))
+ {
+ $this->_memcached = new Memcached();
+ }
+ elseif (class_exists('Memcache', FALSE))
+ {
+ $this->_memcached = new Memcache();
+ }
+ else
+ {
+ log_message('error', 'Cache: Failed to create Memcache(d) object; extension not loaded?');
+ }
+
+ foreach ($this->_memcache_conf as $cache_server)
+ {
+ isset($cache_server['hostname']) OR $cache_server['hostname'] = $defaults['host'];
+ isset($cache_server['port']) OR $cache_server['port'] = $defaults['port'];
+ isset($cache_server['weight']) OR $cache_server['weight'] = $defaults['weight'];
+
+ if (get_class($this->_memcached) === 'Memcache')
+ {
+ // Third parameter is persistance and defaults to TRUE.
+ $this->_memcached->addServer(
+ $cache_server['hostname'],
+ $cache_server['port'],
+ TRUE,
+ $cache_server['weight']
+ );
+ }
+ else
+ {
+ $this->_memcached->addServer(
+ $cache_server['hostname'],
+ $cache_server['port'],
+ $cache_server['weight']
+ );
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
/**
* Fetch from cache
*
@@ -205,75 +275,6 @@ class CI_Cache_memcached extends CI_Driver {
// ------------------------------------------------------------------------
/**
- * Setup memcached.
- *
- * @return bool
- */
- protected function _setup_memcached()
- {
- // Try to load memcached server info from the config file.
- $CI =& get_instance();
- $defaults = $this->_memcache_conf['default'];
-
- if ($CI->config->load('memcached', TRUE, TRUE))
- {
- if (is_array($CI->config->config['memcached']))
- {
- $this->_memcache_conf = array();
-
- foreach ($CI->config->config['memcached'] as $name => $conf)
- {
- $this->_memcache_conf[$name] = $conf;
- }
- }
- }
-
- if (class_exists('Memcached', FALSE))
- {
- $this->_memcached = new Memcached();
- }
- elseif (class_exists('Memcache', FALSE))
- {
- $this->_memcached = new Memcache();
- }
- else
- {
- log_message('error', 'Failed to create object for Memcached Cache; extension not loaded?');
- return FALSE;
- }
-
- foreach ($this->_memcache_conf as $cache_server)
- {
- isset($cache_server['hostname']) OR $cache_server['hostname'] = $defaults['host'];
- isset($cache_server['port']) OR $cache_server['port'] = $defaults['port'];
- isset($cache_server['weight']) OR $cache_server['weight'] = $defaults['weight'];
-
- if (get_class($this->_memcached) === 'Memcache')
- {
- // Third parameter is persistance and defaults to TRUE.
- $this->_memcached->addServer(
- $cache_server['hostname'],
- $cache_server['port'],
- TRUE,
- $cache_server['weight']
- );
- }
- else
- {
- $this->_memcached->addServer(
- $cache_server['hostname'],
- $cache_server['port'],
- $cache_server['weight']
- );
- }
- }
-
- return TRUE;
- }
-
- // ------------------------------------------------------------------------
-
- /**
* Is supported
*
* Returns FALSE if memcached is not supported on the system.
@@ -283,13 +284,6 @@ class CI_Cache_memcached extends CI_Driver {
*/
public function is_supported()
{
- if ( ! extension_loaded('memcached') && ! extension_loaded('memcache'))
- {
- log_message('debug', 'The Memcached Extension must be loaded to use Memcached Cache.');
- return FALSE;
- }
-
- return $this->_setup_memcached();
+ return (extension_loaded('memcached') OR extension_loaded('memcache'));
}
-
}
diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php
index f2a41cc67..ea0059ff7 100644
--- a/system/libraries/Cache/drivers/Cache_redis.php
+++ b/system/libraries/Cache/drivers/Cache_redis.php
@@ -79,6 +79,63 @@ class CI_Cache_redis extends CI_Driver
// ------------------------------------------------------------------------
/**
+ * Class constructor
+ *
+ * Setup Redis
+ *
+ * Loads Redis config file if present. Will halt execution
+ * if a Redis connection can't be established.
+ *
+ * @return void
+ * @see Redis::connect()
+ */
+ public function __construct()
+ {
+ $config = array();
+ $CI =& get_instance();
+
+ if ($CI->config->load('redis', TRUE, TRUE))
+ {
+ $config = $CI->config->item('redis');
+ }
+
+ $config = array_merge(self::$_default_config, $config);
+ $this->_redis = new Redis();
+
+ try
+ {
+ if ($config['socket_type'] === 'unix')
+ {
+ $success = $this->_redis->connect($config['socket']);
+ }
+ else // tcp socket
+ {
+ $success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);
+ }
+
+ if ( ! $success)
+ {
+ log_message('error', 'Cache: Redis connection failed. Check your configuration.');
+ }
+
+ if (isset($config['password']) && ! $this->_redis->auth($config['password']))
+ {
+ log_message('error', 'Cache: Redis authentication failed.');
+ }
+ }
+ catch (RedisException $e)
+ {
+ log_message('error', 'Cache: Redis connection refused ('.$e->getMessage().')');
+ }
+
+ // Initialize the index of serialized values.
+ $serialized = $this->_redis->sMembers('_ci_redis_serialized');
+ empty($serialized) OR $this->_serialized = array_flip($serialized);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
* Get cache
*
* @param string Cache ID
@@ -111,7 +168,7 @@ class CI_Cache_redis extends CI_Driver
{
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;
}
@@ -125,9 +182,7 @@ class CI_Cache_redis extends CI_Driver
$this->_redis->sRemove('_ci_redis_serialized', $id);
}
- return ($ttl)
- ? $this->_redis->setex($id, $ttl, $data)
- : $this->_redis->set($id, $data);
+ return $this->_redis->set($id, $data, $ttl);
}
// ------------------------------------------------------------------------
@@ -223,7 +278,7 @@ class CI_Cache_redis extends CI_Driver
{
$value = $this->get($key);
- if ($value)
+ if ($value !== FALSE)
{
return array(
'expire' => time() + $this->_redis->ttl($key),
@@ -243,78 +298,7 @@ class CI_Cache_redis extends CI_Driver
*/
public function is_supported()
{
- if (extension_loaded('redis'))
- {
- return $this->_setup_redis();
- }
- else
- {
- log_message('debug', 'The Redis extension must be loaded to use Redis cache.');
- return FALSE;
- }
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Setup Redis config and connection
- *
- * Loads Redis config file if present. Will halt execution
- * if a Redis connection can't be established.
- *
- * @return bool
- * @see Redis::connect()
- */
- protected function _setup_redis()
- {
- $config = array();
- $CI =& get_instance();
-
- if ($CI->config->load('redis', TRUE, TRUE))
- {
- $config += $CI->config->item('redis');
- }
-
- $config = array_merge(self::$_default_config, $config);
-
- $this->_redis = new Redis();
-
- try
- {
- if ($config['socket_type'] === 'unix')
- {
- $success = $this->_redis->connect($config['socket']);
- }
- else // tcp socket
- {
- $success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);
- }
-
- if ( ! $success)
- {
- log_message('debug', 'Cache: Redis connection refused. Check the config.');
- return FALSE;
- }
- }
- catch (RedisException $e)
- {
- log_message('debug', 'Cache: Redis connection refused ('.$e->getMessage().')');
- return FALSE;
- }
-
- if (isset($config['password']))
- {
- $this->_redis->auth($config['password']);
- }
-
- // Initialize the index of serialized values.
- $serialized = $this->_redis->sMembers('_ci_redis_serialized');
- if ( ! empty($serialized))
- {
- $this->_serialized = array_flip($serialized);
- }
-
- return TRUE;
+ return extension_loaded('redis');
}
// ------------------------------------------------------------------------
@@ -333,5 +317,4 @@ class CI_Cache_redis extends CI_Driver
$this->_redis->close();
}
}
-
}
diff --git a/system/libraries/Cache/drivers/Cache_wincache.php b/system/libraries/Cache/drivers/Cache_wincache.php
index 528b2b9bf..9cc6ff016 100644
--- a/system/libraries/Cache/drivers/Cache_wincache.php
+++ b/system/libraries/Cache/drivers/Cache_wincache.php
@@ -194,7 +194,7 @@ class CI_Cache_wincache extends CI_Driver {
*/
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 c942a79ce..b702fbc39 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 c942a79ce..b702fbc39 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 014daac58..f6a0c39c4 100644
--- a/system/libraries/Calendar.php
+++ b/system/libraries/Calendar.php
@@ -130,11 +130,7 @@ class CI_Calendar {
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 4e0e0cd9f..ebff7567a 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -405,7 +405,7 @@ class CI_Email {
* @param array $config = array()
* @return void
*/
- public function __construct($config = array())
+ public function __construct(array $config = array())
{
$this->charset = config_item('charset');
@@ -804,11 +804,12 @@ class CI_Email {
*
* @param string
* @param string
- * @return void
+ * @return CI_Email
*/
public function set_header($header, $value)
{
$this->_headers[$header] = str_replace(array("\n", "\r"), '', $value);
+ return $this;
}
// --------------------------------------------------------------------
@@ -1562,11 +1563,10 @@ class CI_Email {
if ($this->charset === 'UTF-8')
{
- if (MB_ENABLED === TRUE)
- {
- return mb_encode_mimeheader($str, $this->charset, 'Q', $this->crlf);
- }
- elseif (ICONV_ENABLED === TRUE)
+ // Note: We used to have mb_encode_mimeheader() as the first choice
+ // here, but it turned out to be buggy and unreliable. DO NOT
+ // re-add it! -- Narf
+ if (ICONV_ENABLED === TRUE)
{
$output = @iconv_mime_encode('', $str,
array(
@@ -1589,6 +1589,10 @@ class CI_Email {
$chars = iconv_strlen($str, 'UTF-8');
}
+ elseif (MB_ENABLED === TRUE)
+ {
+ $chars = mb_strlen($str, 'UTF-8');
+ }
}
// We might already have this set for UTF-8
@@ -1868,20 +1872,26 @@ class CI_Email {
return FALSE;
}
- $this->_send_command('from', $this->clean_email($this->_headers['From']));
+ if ( ! $this->_send_command('from', $this->clean_email($this->_headers['From'])))
+ {
+ return FALSE;
+ }
foreach ($this->_recipients as $val)
{
- $this->_send_command('to', $val);
+ if ( ! $this->_send_command('to', $val))
+ {
+ return FALSE;
+ }
}
if (count($this->_cc_array) > 0)
{
foreach ($this->_cc_array as $val)
{
- if ($val !== '')
+ if ($val !== '' && ! $this->_send_command('to', $val))
{
- $this->_send_command('to', $val);
+ return FALSE;
}
}
}
@@ -1890,14 +1900,17 @@ class CI_Email {
{
foreach ($this->_bcc_array as $val)
{
- if ($val !== '')
+ if ($val !== '' && ! $this->_send_command('to', $val))
{
- $this->_send_command('to', $val);
+ return FALSE;
}
}
}
- $this->_send_command('data');
+ if ( ! $this->_send_command('data'))
+ {
+ return FALSE;
+ }
// perform dot transformation on any lines that begin with a dot
$this->_send_data($this->_header_str.preg_replace('/^\./m', '..$1', $this->_finalbody));
@@ -2126,12 +2139,32 @@ class CI_Email {
protected function _send_data($data)
{
$data .= $this->newline;
- for ($written = 0, $length = strlen($data); $written < $length; $written += $result)
+ for ($written = $timestamp = 0, $length = strlen($data); $written < $length; $written += $result)
{
if (($result = fwrite($this->_smtp_connect, substr($data, $written))) === FALSE)
{
break;
}
+ // See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951
+ elseif ($result === 0)
+ {
+ if ($timestamp === 0)
+ {
+ $timestamp = time();
+ }
+ elseif ($timestamp < (time() - $this->smtp_timeout))
+ {
+ $result = FALSE;
+ break;
+ }
+
+ usleep(250000);
+ continue;
+ }
+ else
+ {
+ $timestamp = 0;
+ }
}
if ($result === FALSE)
@@ -2172,11 +2205,22 @@ class CI_Email {
/**
* Get Hostname
*
+ * There are only two legal types of hostname - either a fully
+ * qualified domain name (eg: "mail.example.com") or an IP literal
+ * (eg: "[1.2.3.4]").
+ *
+ * @link https://tools.ietf.org/html/rfc5321#section-2.3.5
+ * @link http://cbl.abuseat.org/namingproblems.html
* @return string
*/
protected function _get_hostname()
{
- return isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain';
+ if (isset($_SERVER['SERVER_NAME']))
+ {
+ return $_SERVER['SERVER_NAME'];
+ }
+
+ return isset($_SERVER['SERVER_ADDR']) ? '['.$_SERVER['SERVER_ADDR'].']' : '[127.0.0.1]';
}
// --------------------------------------------------------------------
diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php
index 5faf1f206..a46d4f462 100644
--- a/system/libraries/Encrypt.php
+++ b/system/libraries/Encrypt.php
@@ -65,7 +65,7 @@ class CI_Encrypt {
protected $_hash_type = 'sha1';
/**
- * Flag for the existance of mcrypt
+ * Flag for the existence of mcrypt
*
* @var bool
*/
diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php
index e3e68139a..f3e039881 100644
--- a/system/libraries/Encryption.php
+++ b/system/libraries/Encryption.php
@@ -121,7 +121,7 @@ class CI_Encryption {
);
/**
- * 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 f161b40e7..a158225ee 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -198,22 +198,20 @@ class CI_Form_validation {
return $this;
}
- // No fields? Nothing to do...
- if ( ! is_string($field) OR $field === '')
+ // No fields or no rules? Nothing to do...
+ if ( ! is_string($field) OR $field === '' OR empty($rules))
{
return $this;
}
elseif ( ! is_array($rules))
{
// BC: Convert pipe-separated rules string to an array
- if (is_string($rules))
- {
- $rules = explode('|', $rules);
- }
- else
+ if ( ! is_string($rules))
{
return $this;
}
+
+ $rules = preg_split('/\|(?![^\[]*\])/', $rules);
}
// If the field label wasn't passed we use the field name
@@ -463,7 +461,7 @@ class CI_Form_validation {
{
$this->_field_data[$field]['postdata'] = $this->_reduce_array($validation_array, $row['keys']);
}
- elseif (isset($validation_array[$field]) && $validation_array[$field] !== '')
+ elseif (isset($validation_array[$field]))
{
$this->_field_data[$field]['postdata'] = $validation_array[$field];
}
@@ -620,6 +618,12 @@ class CI_Form_validation {
$rules = array(1 => $rule);
break;
}
+ elseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1]))
+ {
+ $callback = TRUE;
+ $rules = array(array($rule[0], $rule[1]));
+ break;
+ }
}
if ( ! $callback)
@@ -817,11 +821,10 @@ class CI_Form_validation {
// Callable rules might not have named error messages
if ( ! is_string($rule))
{
- return;
+ $line = $this->CI->lang->line('form_validation_error_message_not_set').'(Anonymous function)';
}
-
// Check if a custom message is defined
- if (isset($this->_field_data[$row['field']]['errors'][$rule]))
+ elseif (isset($this->_field_data[$row['field']]['errors'][$rule]))
{
$line = $this->_field_data[$row['field']]['errors'][$rule];
}
@@ -831,7 +834,7 @@ class CI_Form_validation {
// 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
@@ -872,17 +875,11 @@ class CI_Form_validation {
*/
protected function _translate_fieldname($fieldname)
{
- // Do we need to translate the field name?
- // We look for the prefix lang: to determine this
- if (sscanf($fieldname, 'lang:%s', $line) === 1)
+ // Do we need to translate the field name? We look for the prefix 'lang:' to determine this
+ // If we find one, but there's no translation for the string - just return it
+ if (sscanf($fieldname, 'lang:%s', $line) === 1 && FALSE === ($fieldname = $this->CI->lang->line($line, FALSE)))
{
- // Were we able to translate the field name? If not we use $line
- if (FALSE === ($fieldname = $this->CI->lang->line('form_validation_'.$line))
- // DEPRECATED support for non-prefixed keys
- && FALSE === ($fieldname = $this->CI->lang->line($line, FALSE)))
- {
- return $line;
- }
+ return $line;
}
return $fieldname;
@@ -1151,9 +1148,7 @@ class CI_Form_validation {
return FALSE;
}
- return (MB_ENABLED === TRUE)
- ? ($val <= mb_strlen($str))
- : ($val <= strlen($str));
+ return ($val <= mb_strlen($str));
}
// --------------------------------------------------------------------
@@ -1172,9 +1167,7 @@ class CI_Form_validation {
return FALSE;
}
- return (MB_ENABLED === TRUE)
- ? ($val >= mb_strlen($str))
- : ($val >= strlen($str));
+ return ($val >= mb_strlen($str));
}
// --------------------------------------------------------------------
@@ -1193,9 +1186,7 @@ class CI_Form_validation {
return FALSE;
}
- return (MB_ENABLED === TRUE)
- ? (mb_strlen($str) === (int) $val)
- : (strlen($str) === (int) $val);
+ return (mb_strlen($str) === (int) $val);
}
// --------------------------------------------------------------------
@@ -1595,7 +1586,6 @@ class CI_Form_validation {
public function reset_validation()
{
$this->_field_data = array();
- $this->_config_rules = array();
$this->_error_array = array();
$this->_error_messages = array();
$this->error_string = '';
diff --git a/system/libraries/Ftp.php b/system/libraries/Ftp.php
index af45bb55f..2d345c294 100644
--- a/system/libraries/Ftp.php
+++ b/system/libraries/Ftp.php
@@ -466,7 +466,7 @@ class CI_FTP {
/**
* Delete a folder and recursively delete everything (including sub-folders)
- * containted within it.
+ * contained within it.
*
* @param string $filepath
* @return bool
@@ -490,7 +490,7 @@ class CI_FTP {
// so we'll recursively call delete_dir()
if ( ! preg_match('#/\.\.?$#', $list[$i]) && ! @ftp_delete($this->conn_id, $list[$i]))
{
- $this->delete_dir($list[$i]);
+ $this->delete_dir($filepath.$list[$i]);
}
}
}
diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php
index e056654bb..e813efd89 100644
--- a/system/libraries/Image_lib.php
+++ b/system/libraries/Image_lib.php
@@ -779,7 +779,7 @@ class CI_Image_lib {
$this->y_axis = 0;
}
- // Create the image handle
+ // Create the image handle
if ( ! ($src_img = $this->image_create_gd()))
{
return FALSE;
@@ -845,7 +845,7 @@ class CI_Image_lib {
*/
public function image_process_imagemagick($action = 'resize')
{
- // Do we have a vaild library path?
+ // Do we have a vaild library path?
if ($this->library_path === '')
{
$this->set_error('imglib_libpath_invalid');
@@ -1010,7 +1010,7 @@ class CI_Image_lib {
// going to have to figure out how to determine the color
// of the alpha channel in a future release.
- $white = imagecolorallocate($src_img, 255, 255, 255);
+ $white = imagecolorallocate($src_img, 255, 255, 255);
// Rotate it!
$dst_img = imagerotate($src_img, $this->rotation_angle, $white);
@@ -1055,8 +1055,11 @@ class CI_Image_lib {
if ($this->rotation_angle === 'hor')
{
- for ($i = 0; $i < $height; $i++, $left = 0, $right = $width-1)
+ for ($i = 0; $i < $height; $i++)
{
+ $left = 0;
+ $right = $width - 1;
+
while ($left < $right)
{
$cl = imagecolorat($src_img, $left, $i);
@@ -1072,18 +1075,21 @@ class CI_Image_lib {
}
else
{
- for ($i = 0; $i < $width; $i++, $top = 0, $bot = $height-1)
+ for ($i = 0; $i < $width; $i++)
{
- while ($top < $bot)
+ $top = 0;
+ $bottom = $height - 1;
+
+ while ($top < $bottom)
{
$ct = imagecolorat($src_img, $i, $top);
- $cb = imagecolorat($src_img, $i, $bot);
+ $cb = imagecolorat($src_img, $i, $bottom);
imagesetpixel($src_img, $i, $top, $cb);
- imagesetpixel($src_img, $i, $bot, $ct);
+ imagesetpixel($src_img, $i, $bottom, $ct);
$top++;
- $bot--;
+ $bottom--;
}
}
}
@@ -1189,7 +1195,7 @@ class CI_Image_lib {
$x_axis += $this->orig_width - $wm_width;
}
- // Build the finalized image
+ // Build the finalized image
if ($wm_img_type === 3 && function_exists('imagealphablending'))
{
@imagealphablending($src_img, TRUE);
@@ -1327,7 +1333,7 @@ class CI_Image_lib {
{
$y_axis += $this->orig_height - $fontheight - $this->wm_shadow_distance - ($fontheight / 2);
}
-
+
// Set horizontal alignment
if ($this->wm_hor_alignment === 'R')
{
@@ -1337,13 +1343,13 @@ class CI_Image_lib {
{
$x_axis += floor(($this->orig_width - ($fontwidth * strlen($this->wm_text))) / 2);
}
-
+
if ($this->wm_use_drop_shadow)
{
// Offset from text
$x_shad = $x_axis + $this->wm_shadow_distance;
$y_shad = $y_axis + $this->wm_shadow_distance;
-
+
/* Set RGB values for shadow
*
* First character is #, so we don't really need it.
@@ -1352,7 +1358,7 @@ class CI_Image_lib {
*/
$drp_color = str_split(substr($this->wm_shadow_color, 1, 6), 2);
$drp_color = imagecolorclosest($src_img, hexdec($drp_color[0]), hexdec($drp_color[1]), hexdec($drp_color[2]));
-
+
// Add the shadow to the source image
if ($this->wm_use_truetype)
{
@@ -1363,7 +1369,7 @@ class CI_Image_lib {
imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);
}
}
-
+
/* Set RGB values for text
*
* First character is #, so we don't really need it.
@@ -1382,7 +1388,7 @@ class CI_Image_lib {
{
imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);
}
-
+
// We can preserve transparency for PNG images
if ($this->image_type === 3)
{
@@ -1431,7 +1437,7 @@ class CI_Image_lib {
switch ($image_type)
{
- case 1 :
+ case 1:
if ( ! function_exists('imagecreatefromgif'))
{
$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
@@ -1439,7 +1445,7 @@ class CI_Image_lib {
}
return imagecreatefromgif($path);
- case 2 :
+ case 2:
if ( ! function_exists('imagecreatefromjpeg'))
{
$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
@@ -1447,7 +1453,7 @@ class CI_Image_lib {
}
return imagecreatefromjpeg($path);
- case 3 :
+ case 3:
if ( ! function_exists('imagecreatefrompng'))
{
$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
diff --git a/system/libraries/Javascript/Jquery.php b/system/libraries/Javascript/Jquery.php
index 25acceef7..11f2d2361 100644
--- a/system/libraries/Javascript/Jquery.php
+++ b/system/libraries/Javascript/Jquery.php
@@ -84,7 +84,7 @@ class CI_Jquery extends CI_Javascript {
public $jquery_table_sorter_active = FALSE;
/**
- * JQuery table sorder pager active
+ * JQuery table sorter pager active
*
* @var bool
*/
diff --git a/system/libraries/Javascript/index.html b/system/libraries/Javascript/index.html
index c942a79ce..b702fbc39 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/Migration.php b/system/libraries/Migration.php
index ae36a3b45..45a3cbbce 100644
--- a/system/libraries/Migration.php
+++ b/system/libraries/Migration.php
@@ -191,7 +191,7 @@ class CI_Migration {
* choice
*
* @param string $target_version Target schema version
- * @return mixed TRUE if already latest, FALSE if failed, string if upgraded
+ * @return mixed TRUE if no migrations are found, current version string on success, FALSE on failure
*/
public function version($target_version)
{
@@ -294,7 +294,7 @@ class CI_Migration {
/**
* Sets the schema to the latest migration
*
- * @return mixed TRUE if already latest, FALSE if failed, string if upgraded
+ * @return mixed Current version string on success, FALSE on failure
*/
public function latest()
{
@@ -318,7 +318,7 @@ class CI_Migration {
/**
* Sets the schema to the migration version set in config
*
- * @return mixed TRUE if already current, FALSE if failed, string if upgraded
+ * @return mixed TRUE if no migrations are found, current version string on success, FALSE on failure
*/
public function current()
{
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
index d63f61df6..4d18998b9 100644
--- a/system/libraries/Pagination.php
+++ b/system/libraries/Pagination.php
@@ -353,7 +353,8 @@ class CI_Pagination {
*/
public function initialize(array $params = array())
{
- if (isset($params['attributes']) && is_array($params['attributes']))
+ isset($params['attributes']) OR $params['attributes'] = array();
+ if (is_array($params['attributes']))
{
$this->_parse_attributes($params['attributes']);
unset($params['attributes']);
@@ -570,7 +571,7 @@ class CI_Pagination {
{
$i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;
- $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, ($this->cur_page - 1));
if ($i === $base_page)
{
@@ -591,11 +592,11 @@ class CI_Pagination {
if ($this->display_pages !== FALSE)
{
// Write the digit links
- for ($loop = $start -1; $loop <= $end; $loop++)
+ for ($loop = $start - 1; $loop <= $end; $loop++)
{
$i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page;
- $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $loop);
if ($i >= $base_page)
{
@@ -613,7 +614,7 @@ class CI_Pagination {
else
{
$append = $this->prefix.$i.$this->suffix;
- $output .= $this->num_tag_open.'<a href="'.$base_url.$append.'"'.$attributes.$this->_attr_rel('start').'>'
+ $output .= $this->num_tag_open.'<a href="'.$base_url.$append.'"'.$attributes.'>'
.$loop.'</a>'.$this->num_tag_close;
}
}
@@ -625,7 +626,7 @@ class CI_Pagination {
{
$i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page;
- $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $this->cur_page + 1);
$output .= $this->next_tag_open.'<a href="'.$base_url.$this->prefix.$i.$this->suffix.'"'.$attributes
.$this->_attr_rel('next').'>'.$this->next_link.'</a>'.$this->next_tag_close;
@@ -636,7 +637,7 @@ class CI_Pagination {
{
$i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;
- $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
+ $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, $num_pages);
$output .= $this->last_tag_open.'<a href="'.$base_url.$this->prefix.$i.$this->suffix.'"'.$attributes.'>'
.$this->last_link.'</a>'.$this->last_tag_close;
@@ -644,7 +645,7 @@ class CI_Pagination {
// Kill double slashes. Note: Sometimes we can end up with a double slash
// in the penultimate link so we'll kill all double slashes.
- $output = preg_replace('#([^:])//+#', '\\1/', $output);
+ $output = preg_replace('#([^:"])//+#', '\\1/', $output);
// Add the wrapper HTML if exists
return $this->full_tag_open.$output.$this->full_tag_close;
diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php
index f35d23faf..1e464d8b0 100644
--- a/system/libraries/Profiler.php
+++ b/system/libraries/Profiler.php
@@ -100,12 +100,6 @@ class CI_Profiler {
$this->CI =& get_instance();
$this->CI->load->language('profiler');
- if (isset($config['query_toggle_count']))
- {
- $this->_query_toggle_count = (int) $config['query_toggle_count'];
- unset($config['query_toggle_count']);
- }
-
// default all sections to display
foreach ($this->_available_sections as $section)
{
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
index ba1919b44..05a470d86 100644
--- a/system/libraries/Session/Session.php
+++ b/system/libraries/Session/Session.php
@@ -94,10 +94,7 @@ class CI_Session {
$this->_driver = 'database';
}
- if (($class = $this->_ci_load_classes($this->_driver)) === FALSE)
- {
- return;
- }
+ $class = $this->_ci_load_classes($this->_driver);
// Configuration ...
$this->_configure($params);
@@ -153,7 +150,7 @@ class CI_Session {
}
elseif ($_SESSION['__ci_last_regenerate'] < (time() - $regenerate_time))
{
- $this->sess_regenerate(FALSE);
+ $this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));
}
}
// Another work-around ... PHP doesn't seem to send the session cookie
@@ -230,8 +227,7 @@ class CI_Session {
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 @@ class CI_Session {
$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);
@@ -799,7 +795,7 @@ class CI_Session {
/**
* Set flashdata
*
- * Legacy CI_Session compatibiliy method
+ * Legacy CI_Session compatibility method
*
* @param mixed $data Session data key or an associative array
* @param mixed $value Value to store
@@ -873,7 +869,7 @@ class CI_Session {
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 20cec00fd..72b39d12d 100644
--- a/system/libraries/Session/drivers/Session_database_driver.php
+++ b/system/libraries/Session/drivers/Session_database_driver.php
@@ -93,6 +93,10 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan
{
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 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan
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;
}
@@ -155,6 +159,10 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan
if (($result = $this->_db->get()->row()) === NULL)
{
+ // PHP7 will reuse the same SessionHandler object after
+ // ID regeneration, so we need to explicitly set this to
+ // FALSE instead of relying on the default ...
+ $this->_row_exists = FALSE;
$this->_fingerprint = md5('');
return '';
}
@@ -319,7 +327,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan
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 d3ef34acd..45da91c46 100644
--- a/system/libraries/Session/drivers/Session_files_driver.php
+++ b/system/libraries/Session/drivers/Session_files_driver.php
@@ -107,7 +107,7 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle
* Sanitizes the save_path directory.
*
* @param string $save_path Path to session files' directory
- * @param string $name Session cookie name, unused
+ * @param string $name Session cookie name
* @return bool
*/
public function open($save_path, $name)
@@ -299,7 +299,9 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle
{
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 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle
*/
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;
@@ -332,10 +334,16 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle
$ts = time() - $maxlifetime;
- foreach ($files as $file)
+ $pattern = sprintf(
+ '/^%s[0-9a-f]{%d}$/',
+ preg_quote($this->_config['cookie_name'], '/'),
+ ($this->_config['match_ip'] === TRUE ? 72 : 40)
+ );
+
+ 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('/(?:[0-9a-f]{32})?[0-9a-f]{40}$/i', $file)
+ if ( ! preg_match($pattern, $file)
OR ! is_file($this->_config['save_path'].DIRECTORY_SEPARATOR.$file)
OR ($mtime = filemtime($this->_config['save_path'].DIRECTORY_SEPARATOR.$file)) === FALSE
OR $mtime > $ts)
@@ -346,6 +354,8 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle
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 600b8ca66..97b860588 100644
--- a/system/libraries/Session/drivers/Session_memcached_driver.php
+++ b/system/libraries/Session/drivers/Session_memcached_driver.php
@@ -204,7 +204,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa
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 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa
{
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 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa
$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 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa
{
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 c3c75b3b6..b098cc441 100644
--- a/system/libraries/Session/drivers/Session_redis_driver.php
+++ b/system/libraries/Session/drivers/Session_redis_driver.php
@@ -205,7 +205,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
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 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
{
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 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
{
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 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
$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 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle
{
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 c942a79ce..b702fbc39 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 c942a79ce..b702fbc39 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/Unit_test.php b/system/libraries/Unit_test.php
index 7b744adc6..3f986f3e8 100644
--- a/system/libraries/Unit_test.php
+++ b/system/libraries/Unit_test.php
@@ -55,14 +55,14 @@ class CI_Unit_test {
*
* @var bool
*/
- public $active = TRUE;
+ public $active = TRUE;
/**
* Test results
*
* @var array
*/
- public $results = array();
+ public $results = array();
/**
* Strict comparison flag
@@ -71,21 +71,21 @@ class CI_Unit_test {
*
* @var bool
*/
- public $strict = FALSE;
+ public $strict = FALSE;
/**
* Template
*
* @var string
*/
- protected $_template = NULL;
+ protected $_template = NULL;
/**
* Template rows
*
* @var string
*/
- protected $_template_rows = NULL;
+ protected $_template_rows = NULL;
/**
* List of visible test items
@@ -93,13 +93,13 @@ class CI_Unit_test {
* @var array
*/
protected $_test_items_visible = array(
- 'test_name',
- 'test_datatype',
- 'res_datatype',
- 'result',
- 'file',
- 'line',
- 'notes'
+ 'test_name',
+ 'test_datatype',
+ 'res_datatype',
+ 'result',
+ 'file',
+ 'line',
+ 'notes'
);
// --------------------------------------------------------------------
@@ -152,7 +152,7 @@ class CI_Unit_test {
return FALSE;
}
- if (in_array($expected, array('is_object', 'is_string', 'is_bool', 'is_true', 'is_false', 'is_int', 'is_numeric', 'is_float', 'is_double', 'is_array', 'is_null'), TRUE))
+ if (in_array($expected, array('is_object', 'is_string', 'is_bool', 'is_true', 'is_false', 'is_int', 'is_numeric', 'is_float', 'is_double', 'is_array', 'is_null', 'is_resource'), TRUE))
{
$expected = str_replace('is_double', 'is_float', $expected);
$result = $expected($test);
@@ -167,14 +167,14 @@ class CI_Unit_test {
$back = $this->_backtrace();
$report = array (
- 'test_name' => $test_name,
- 'test_datatype' => gettype($test),
- 'res_datatype' => $extype,
- 'result' => ($result === TRUE) ? 'passed' : 'failed',
- 'file' => $back['file'],
- 'line' => $back['line'],
- 'notes' => $notes
- );
+ 'test_name' => $test_name,
+ 'test_datatype' => gettype($test),
+ 'res_datatype' => $extype,
+ 'result' => ($result === TRUE) ? 'passed' : 'failed',
+ 'file' => $back['file'],
+ 'line' => $back['line'],
+ 'notes' => $notes
+ );
$this->results[] = $report;
@@ -291,10 +291,12 @@ class CI_Unit_test {
{
continue;
}
-
- if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val), FALSE)))
+ elseif (in_array($key, array('test_name', 'test_datatype', 'test_res_datatype', 'result'), TRUE))
{
- $val = $line;
+ if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val), FALSE)))
+ {
+ $val = $line;
+ }
}
$temp[$CI->lang->line('ut_'.$key, FALSE)] = $val;
@@ -334,9 +336,9 @@ class CI_Unit_test {
{
$back = debug_backtrace();
return array(
- 'file' => (isset($back[1]['file']) ? $back[1]['file'] : ''),
- 'line' => (isset($back[1]['line']) ? $back[1]['line'] : '')
- );
+ 'file' => (isset($back[1]['file']) ? $back[1]['file'] : ''),
+ 'line' => (isset($back[1]['line']) ? $back[1]['line'] : '')
+ );
}
// --------------------------------------------------------------------
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
index f5534a7f7..8a2dec76a 100644
--- a/system/libraries/Upload.php
+++ b/system/libraries/Upload.php
@@ -397,7 +397,7 @@ class CI_Upload {
if ( ! isset($_file))
{
- $this->set_error('upload_no_file_selected');
+ $this->set_error('upload_no_file_selected', 'debug');
return FALSE;
}
@@ -416,28 +416,28 @@ class CI_Upload {
switch ($error)
{
case UPLOAD_ERR_INI_SIZE:
- $this->set_error('upload_file_exceeds_limit');
+ $this->set_error('upload_file_exceeds_limit', 'info');
break;
case UPLOAD_ERR_FORM_SIZE:
- $this->set_error('upload_file_exceeds_form_limit');
+ $this->set_error('upload_file_exceeds_form_limit', 'info');
break;
case UPLOAD_ERR_PARTIAL:
- $this->set_error('upload_file_partial');
+ $this->set_error('upload_file_partial', 'debug');
break;
case UPLOAD_ERR_NO_FILE:
- $this->set_error('upload_no_file_selected');
+ $this->set_error('upload_no_file_selected', 'debug');
break;
case UPLOAD_ERR_NO_TMP_DIR:
- $this->set_error('upload_no_temp_directory');
+ $this->set_error('upload_no_temp_directory', 'error');
break;
case UPLOAD_ERR_CANT_WRITE:
- $this->set_error('upload_unable_to_write_file');
+ $this->set_error('upload_unable_to_write_file', 'error');
break;
case UPLOAD_ERR_EXTENSION:
- $this->set_error('upload_stopped_by_extension');
+ $this->set_error('upload_stopped_by_extension', 'debug');
break;
default:
- $this->set_error('upload_no_file_selected');
+ $this->set_error('upload_no_file_selected', 'debug');
break;
}
@@ -463,7 +463,7 @@ class CI_Upload {
// Is the file type allowed to be uploaded?
if ( ! $this->is_allowed_filetype())
{
- $this->set_error('upload_invalid_filetype');
+ $this->set_error('upload_invalid_filetype', 'debug');
return FALSE;
}
@@ -485,7 +485,7 @@ class CI_Upload {
if ( ! $this->is_allowed_filetype(TRUE))
{
- $this->set_error('upload_invalid_filetype');
+ $this->set_error('upload_invalid_filetype', 'debug');
return FALSE;
}
}
@@ -499,7 +499,7 @@ class CI_Upload {
// Is the file size within the allowed maximum?
if ( ! $this->is_allowed_filesize())
{
- $this->set_error('upload_invalid_filesize');
+ $this->set_error('upload_invalid_filesize', 'info');
return FALSE;
}
@@ -507,7 +507,7 @@ class CI_Upload {
// Note: This can fail if the server has an open_basedir restriction.
if ( ! $this->is_allowed_dimensions())
{
- $this->set_error('upload_invalid_dimensions');
+ $this->set_error('upload_invalid_dimensions', 'info');
return FALSE;
}
@@ -533,15 +533,9 @@ class CI_Upload {
* If it returns false there was a problem.
*/
$this->orig_name = $this->file_name;
-
- if ($this->overwrite === FALSE)
+ if (FALSE === ($this->file_name = $this->set_filename($this->upload_path, $this->file_name)))
{
- $this->file_name = $this->set_filename($this->upload_path, $this->file_name);
-
- if ($this->file_name === FALSE)
- {
- return FALSE;
- }
+ return FALSE;
}
/*
@@ -552,7 +546,7 @@ class CI_Upload {
*/
if ($this->xss_clean && $this->do_xss_clean() === FALSE)
{
- $this->set_error('upload_unable_to_write_file');
+ $this->set_error('upload_unable_to_write_file', 'error');
return FALSE;
}
@@ -567,7 +561,7 @@ class CI_Upload {
{
if ( ! @move_uploaded_file($this->file_temp, $this->upload_path.$this->file_name))
{
- $this->set_error('upload_destination_error');
+ $this->set_error('upload_destination_error', 'error');
return FALSE;
}
}
@@ -656,7 +650,7 @@ class CI_Upload {
$filename = md5(uniqid(mt_rand())).$this->file_ext;
}
- if ( ! file_exists($path.$filename))
+ if ($this->overwrite === TRUE OR ! file_exists($path.$filename))
{
return $filename;
}
@@ -675,7 +669,7 @@ class CI_Upload {
if ($new_filename === '')
{
- $this->set_error('upload_bad_filename');
+ $this->set_error('upload_bad_filename', 'debug');
return FALSE;
}
else
@@ -701,6 +695,22 @@ class CI_Upload {
// --------------------------------------------------------------------
/**
+ * Set Maximum File Size
+ *
+ * An internal alias to set_max_filesize() to help with configuration
+ * as initialize() will look for a set_<property_name>() method ...
+ *
+ * @param int $n
+ * @return CI_Upload
+ */
+ protected function set_max_size($n)
+ {
+ return $this->set_max_filesize($n);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Set Maximum File Name Length
*
* @param int $n
@@ -875,7 +885,7 @@ class CI_Upload {
if (empty($this->allowed_types) OR ! is_array($this->allowed_types))
{
- $this->set_error('upload_no_file_types');
+ $this->set_error('upload_no_file_types', 'debug');
return FALSE;
}
@@ -974,7 +984,7 @@ class CI_Upload {
{
if ($this->upload_path === '')
{
- $this->set_error('upload_no_filepath');
+ $this->set_error('upload_no_filepath', 'error');
return FALSE;
}
@@ -985,13 +995,13 @@ class CI_Upload {
if ( ! is_dir($this->upload_path))
{
- $this->set_error('upload_no_filepath');
+ $this->set_error('upload_no_filepath', 'error');
return FALSE;
}
if ( ! is_really_writable($this->upload_path))
{
- $this->set_error('upload_not_writable');
+ $this->set_error('upload_not_writable', 'error');
return FALSE;
}
@@ -1013,7 +1023,7 @@ class CI_Upload {
if (count($x) === 1)
{
- return '';
+ return '';
}
$ext = ($this->file_ext_tolower) ? strtolower(end($x)) : end($x);
@@ -1121,17 +1131,16 @@ class CI_Upload {
* @param string $msg
* @return CI_Upload
*/
- public function set_error($msg)
+ public function set_error($msg, $log_level = 'error')
{
$this->_CI->lang->load('upload');
is_array($msg) OR $msg = array($msg);
-
foreach ($msg as $val)
{
$msg = ($this->_CI->lang->line($val) === FALSE) ? $val : $this->_CI->lang->line($val);
$this->error_msg[] = $msg;
- log_message('error', $msg);
+ log_message($log_level, $msg);
}
return $this;
diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php
index 8fbc18f04..55555f56f 100644
--- a/system/libraries/Xmlrpc.php
+++ b/system/libraries/Xmlrpc.php
@@ -735,12 +735,32 @@ class XML_RPC_Client extends CI_Xmlrpc
.'Content-Length: '.strlen($msg->payload).$r.$r
.$msg->payload;
- for ($written = 0, $length = strlen($op); $written < $length; $written += $result)
+ for ($written = $timestamp = 0, $length = strlen($op); $written < $length; $written += $result)
{
if (($result = fwrite($fp, substr($op, $written))) === FALSE)
{
break;
}
+ // See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951
+ elseif ($result === 0)
+ {
+ if ($timestamp === 0)
+ {
+ $timestamp = time();
+ }
+ elseif ($timestamp < (time() - $this->timeout))
+ {
+ $result = FALSE;
+ break;
+ }
+
+ usleep(250000);
+ continue;
+ }
+ else
+ {
+ $timestamp = 0;
+ }
}
if ($result === FALSE)
diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php
index af7041337..00d1feca6 100644
--- a/system/libraries/Xmlrpcs.php
+++ b/system/libraries/Xmlrpcs.php
@@ -223,7 +223,7 @@ class CI_Xmlrpcs extends CI_Xmlrpc {
$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 @@ class CI_Xmlrpcs extends CI_Xmlrpc {
$parser = xml_parser_create($this->xmlrpc_defencoding);
$parser_object = new XML_RPC_Message('filler');
-
- $parser_object->xh[$parser] = array(
- 'isf' => 0,
- 'isf_reason' => '',
- 'params' => array(),
- 'stack' => array(),
- 'valuestack' => array(),
- 'method' => ''
+ $pname = (string) $parser;
+
+ $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 @@ class CI_Xmlrpcs extends CI_Xmlrpc {
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 @@ class CI_Xmlrpcs extends CI_Xmlrpc {
{
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 f2f17148b..3e98ac568 100644
--- a/system/libraries/Zip.php
+++ b/system/libraries/Zip.php
@@ -352,7 +352,7 @@ class CI_Zip {
// 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 c942a79ce..b702fbc39 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>