summaryrefslogtreecommitdiffstats
path: root/system
diff options
context:
space:
mode:
authorBruno Barão <brunobarao@gmail.com>2012-10-08 17:21:36 +0200
committerBruno Barão <brunobarao@gmail.com>2012-10-08 17:21:36 +0200
commit02561acf13f19881f4e3f95cf2fb423665d5ce8b (patch)
treefb88af9da77e37447d9e1513146aad870e65ea5d /system
parentb453e16668c70b0eb02b5ae69cd3196d735421f8 (diff)
parent960e616d18c77f463e7c53f666d98b09f5ca9057 (diff)
Merge remote-tracking branch 'upstream/develop' into develop
Diffstat (limited to 'system')
-rw-r--r--system/core/Common.php19
-rw-r--r--system/core/Config.php2
-rw-r--r--system/core/Input.php22
-rw-r--r--system/core/Loader.php51
-rw-r--r--system/core/Output.php4
-rw-r--r--system/database/DB_driver.php17
-rw-r--r--system/database/DB_query_builder.php20
-rw-r--r--system/database/drivers/cubrid/cubrid_driver.php6
-rw-r--r--system/database/drivers/ibase/ibase_driver.php20
-rw-r--r--system/database/drivers/mssql/mssql_driver.php20
-rw-r--r--system/database/drivers/mysql/mysql_driver.php22
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php34
-rw-r--r--system/database/drivers/oci8/oci8_driver.php20
-rw-r--r--system/database/drivers/odbc/odbc_driver.php18
-rw-r--r--system/database/drivers/pdo/pdo_driver.php4
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_4d_driver.php16
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php4
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php16
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php16
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php16
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_informix_driver.php16
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php4
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_oci_driver.php16
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php17
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php16
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php16
-rw-r--r--system/database/drivers/postgre/postgre_driver.php20
-rw-r--r--system/database/drivers/sqlite/sqlite_driver.php4
-rw-r--r--system/database/drivers/sqlite3/sqlite3_driver.php25
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_driver.php20
-rw-r--r--system/helpers/captcha_helper.php3
-rw-r--r--system/helpers/date_helper.php131
-rw-r--r--system/helpers/directory_helper.php2
-rw-r--r--system/helpers/html_helper.php2
-rw-r--r--system/helpers/text_helper.php3
-rw-r--r--system/helpers/url_helper.php2
-rw-r--r--system/language/english/date_lang.php28
-rw-r--r--system/language/english/form_validation_lang.php4
-rw-r--r--system/libraries/Driver.php22
-rw-r--r--system/libraries/Email.php17
-rw-r--r--system/libraries/Encrypt.php4
-rw-r--r--system/libraries/Image_lib.php7
-rw-r--r--system/libraries/Pagination.php19
-rwxr-xr-xsystem/libraries/Session/Session.php689
-rwxr-xr-x[-rw-r--r--]system/libraries/Session/drivers/Session_cookie.php (renamed from system/libraries/Session.php)721
-rwxr-xr-xsystem/libraries/Session/drivers/Session_native.php232
-rw-r--r--system/libraries/Unit_test.php5
-rwxr-xr-x[-rw-r--r--]system/libraries/Xmlrpc.php10
48 files changed, 1555 insertions, 847 deletions
diff --git a/system/core/Common.php b/system/core/Common.php
index 57374b07d..981af4559 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -488,13 +488,9 @@ if ( ! function_exists('set_status_header'))
{
header('Status: '.$code.' '.$text, TRUE);
}
- elseif ($server_protocol === 'HTTP/1.0')
- {
- header('HTTP/1.0 '.$code.' '.$text, TRUE, $code);
- }
else
{
- header('HTTP/1.1 '.$code.' '.$text, TRUE, $code);
+ header(($server_protocol ? $server_protocol : 'HTTP/1.1').' '.$code.' '.$text, TRUE, $code);
}
}
}
@@ -524,18 +520,17 @@ if ( ! function_exists('_exception_handler'))
{
$_error =& load_class('Exceptions', 'core');
- // Should we display the error? We'll get the current error_reporting
+ // Should we ignore the error? We'll get the current error_reporting
// level and add its bits with the severity bits to find out.
- // And respect display_errors
- if (($severity & error_reporting()) === $severity && (bool) ini_get('display_errors') === TRUE)
+ if (($severity & error_reporting()) !== $severity)
{
- $_error->show_php_error($severity, $message, $filepath, $line);
+ return;
}
- // Should we log the error? No? We're done...
- if (config_item('log_threshold') === 0)
+ // Should we display the error?
+ if ((bool) ini_get('display_errors') === TRUE)
{
- return;
+ $_error->show_php_error($severity, $message, $filepath, $line);
}
$_error->log_exception($severity, $message, $filepath, $line);
diff --git a/system/core/Config.php b/system/core/Config.php
index 2f6a9e085..8e4f998ef 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -102,7 +102,7 @@ class CI_Config {
{
$file = ($file === '') ? 'config' : str_replace('.php', '', $file);
$found = $loaded = FALSE;
-
+
$check_locations = defined('ENVIRONMENT')
? array(ENVIRONMENT.'/'.$file, $file)
: array($file);
diff --git a/system/core/Input.php b/system/core/Input.php
index 968a42a9a..657fce625 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -330,10 +330,10 @@ class CI_Input {
if (config_item('proxy_ips') != '' && $this->server('HTTP_X_FORWARDED_FOR') && $this->server('REMOTE_ADDR'))
{
- $has_ranges = strpos($proxies, '/') !== false;
+ $has_ranges = strpos($proxies, '/') !== FALSE;
$proxies = preg_split('/[\s,]/', config_item('proxy_ips'), -1, PREG_SPLIT_NO_EMPTY);
$proxies = is_array($proxies) ? $proxies : array($proxies);
-
+
if ($has_ranges)
{
$long_ip = ip2long($_SERVER['REMOTE_ADDR']);
@@ -341,21 +341,25 @@ class CI_Input {
// Go through each of the IP Addresses to check for and
// test against range notation
- foreach($proxies as $ip)
+ foreach ($proxies as $ip)
{
- list($address, $mask_length) = explode('/', $ip);
+ list($address, $mask_length) = explode('/', $ip, 2);
// Generate the bitmask for a 32 bit IP Address
- $bitmask = $bit_32 - (1 << (32 - (int)$mask_length));
- if (($long_ip & $bitmask) == $address)
+ $bitmask = $bit_32 - (1 << (32 - (int) $mask_length));
+ if (($long_ip & $bitmask) === $address)
{
$this->ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
break;
}
}
- } else {
- $this->ip_address = in_array($_SERVER['REMOTE_ADDR'], $proxies) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
+ }
+ else
+ {
+ $this->ip_address = in_array($_SERVER['REMOTE_ADDR'], $proxies)
+ ? $_SERVER['HTTP_X_FORWARDED_FOR']
+ : $_SERVER['REMOTE_ADDR'];
}
}
elseif ( ! $this->server('HTTP_CLIENT_IP') && $this->server('REMOTE_ADDR'))
@@ -383,7 +387,7 @@ class CI_Input {
if (strpos($this->ip_address, ',') !== FALSE)
{
$x = explode(',', $this->ip_address);
- $this->ip_address = trim(end($x));
+ $this->ip_address = trim($x[0]);
}
if ( ! $this->valid_ip($this->ip_address))
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 0bc6e844a..75e93608a 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -409,8 +409,8 @@ class CI_Loader {
* 1. The name of the "view" file to be included.
* 2. An associative array of data to be extracted for use in the view.
* 3. TRUE/FALSE - whether to return the data or load it. In
- * some cases it's advantageous to be able to return data so that
- * a developer can process it in some way.
+ * some cases it's advantageous to be able to return data so that
+ * a developer can process it in some way.
*
* @param string
* @param array
@@ -633,13 +633,7 @@ class CI_Loader {
{
$this->driver($driver);
}
- return FALSE;
- }
-
- if ( ! class_exists('CI_Driver_Library'))
- {
- // we aren't instantiating an object here, that'll be done by the Library itself
- require BASEPATH.'libraries/Driver.php';
+ return;
}
if ($library === '')
@@ -785,11 +779,11 @@ class CI_Loader {
$_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
$_ci_file = ($_ci_ext === '') ? $_ci_view.'.php' : $_ci_view;
- foreach ($this->_ci_view_paths as $view_file => $cascade)
+ foreach ($this->_ci_view_paths as $_ci_view_file => $cascade)
{
- if (file_exists($view_file.$_ci_file))
+ if (file_exists($_ci_view_file.$_ci_file))
{
- $_ci_path = $view_file.$_ci_file;
+ $_ci_path = $_ci_view_file.$_ci_file;
$file_exists = TRUE;
break;
}
@@ -837,10 +831,10 @@ class CI_Loader {
* We buffer the output for two reasons:
* 1. Speed. You get a significant speed boost.
* 2. So that the final rendered template can be post-processed by
- * the output class. Why do we need post processing? For one thing,
- * in order to show the elapsed page load time. Unless we can
- * intercept the content right before it's sent to the browser and
- * then stop the timer it won't be accurate.
+ * the output class. Why do we need post processing? For one thing,
+ * in order to show the elapsed page load time. Unless we can
+ * intercept the content right before it's sent to the browser and
+ * then stop the timer it won't be accurate.
*/
ob_start();
@@ -915,6 +909,13 @@ class CI_Loader {
// Get the filename from the path
$class = substr($class, $last_slash);
+
+ // Check for match and driver base class
+ if (strtolower(trim($subdir, '/')) == strtolower($class) && ! class_exists('CI_Driver_Library'))
+ {
+ // We aren't instantiating an object here, just making the base class available
+ require BASEPATH.'libraries/Driver.php';
+ }
}
// We'll test for both lowercase and capitalized versions of the file name
@@ -996,14 +997,19 @@ class CI_Loader {
$this->_ci_loaded_files[] = $filepath;
return $this->_ci_init_class($class, '', $params, $object_name);
}
-
} // END FOREACH
// One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
if ($subdir === '')
{
$path = strtolower($class).'/'.$class;
- return $this->_ci_load_class($path, $params);
+ return $this->_ci_load_class($path, $params, $object_name);
+ }
+ else if (ucfirst($subdir) != $subdir)
+ {
+ // Lowercase subdir failed - retry capitalized
+ $path = ucfirst($subdir).$class;
+ return $this->_ci_load_class($path, $params, $object_name);
}
// If we got this far we were unable to find the requested class.
@@ -1193,6 +1199,15 @@ class CI_Loader {
}
}
+ // Autoload drivers
+ if (isset($autoload['drivers']))
+ {
+ foreach ($autoload['drivers'] as $item)
+ {
+ $this->driver($item);
+ }
+ }
+
// Autoload models
if (isset($autoload['model']))
{
diff --git a/system/core/Output.php b/system/core/Output.php
index 9842f834d..052367ed6 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -552,13 +552,13 @@ class CI_Output {
fclose($fp);
// Strip out the embedded timestamp
- if ( ! preg_match('/\d+TS--->/', $cache, $match))
+ if ( ! preg_match('/^(\d+)TS--->/', $cache, $match))
{
return FALSE;
}
$last_modified = filemtime($cache_path);
- $expire = str_replace('TS--->', '', $match[0]);
+ $expire = $match[1];
// Has the file expired?
if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path))
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index d63a1d955..b12042bde 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -51,6 +51,7 @@ abstract class CI_DB_driver {
public $char_set = 'utf8';
public $dbcollat = 'utf8_general_ci';
public $autoinit = TRUE; // Whether to automatically initialize the DB
+ public $compress = TRUE;
public $swap_pre = '';
public $port = '';
public $pconnect = FALSE;
@@ -78,6 +79,10 @@ abstract class CI_DB_driver {
protected $_protect_identifiers = TRUE;
protected $_reserved_identifiers = array('*'); // Identifiers that should NOT be escaped
+ // clause and character used for LIKE escape sequences
+ protected $_like_escape_str = " ESCAPE '%s' ";
+ protected $_like_escape_chr = '!';
+
/**
* The syntax to count rows is slightly different across different
* database engines, so this string appears in each driver and is
@@ -669,7 +674,7 @@ abstract class CI_DB_driver {
*/
public function is_write_type($sql)
{
- return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD DATA|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql);
+ return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql);
}
// --------------------------------------------------------------------
@@ -1343,7 +1348,7 @@ abstract class CI_DB_driver {
}
else
{
- $message = ( ! is_array($error)) ? array(str_replace('%s', $swap, $LANG->line($error))) : $error;
+ $message = is_array($error) ? $error : array(str_replace('%s', $swap, $LANG->line($error)));
}
// Find the most likely culprit of the error by going through
@@ -1352,7 +1357,13 @@ abstract class CI_DB_driver {
$trace = debug_backtrace();
foreach ($trace as $call)
{
- if (isset($call['file']) && strpos($call['file'], BASEPATH.'database') === FALSE)
+ // We'll need this on Windows, as APPPATH and BASEPATH will always use forward slashes
+ if (DIRECTORY_SEPARATOR !== '/')
+ {
+ $call['file'] = str_replace('\\', '/', $call['file']);
+ }
+
+ if (isset($call['file'], $call['class']) && strpos($call['file'], $basepath.'database') === FALSE && strpos($call['class'], 'Loader') !== FALSE)
{
// Found it - use a relative path for safety
$message[] = 'Filename: '.str_replace(array(APPPATH, BASEPATH), '', $call['file']);
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index 479b7f24a..8bd2ab53c 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -1522,24 +1522,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This public function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- is_array($tables) OR $tables = array($tables);
-
- return (count($tables) === 1) ? $tables[0] : '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Get UPDATE query string
*
* Compiles an update query and returns the sql
@@ -2058,7 +2040,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
// Write the "FROM" portion of the query
if (count($this->qb_from) > 0)
{
- $sql .= "\nFROM ".$this->_from_tables($this->qb_from);
+ $sql .= "\nFROM ".implode(', ', $this->qb_from);
}
// Write the "JOIN" portion of the query
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
index a3d0287f5..28724e0e8 100644
--- a/system/database/drivers/cubrid/cubrid_driver.php
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -45,10 +45,6 @@ class CI_DB_cubrid_driver extends CI_DB {
// The character used for escaping - no need in CUBRID
protected $_escape_char = '`';
- // clause and character used for LIKE escape sequences - not used in CUBRID
- protected $_like_escape_str = '';
- protected $_like_escape_chr = '';
-
protected $_random_keyword = ' RAND()'; // database specific random keyword
// CUBRID-specific properties
@@ -72,6 +68,8 @@ class CI_DB_cubrid_driver extends CI_DB {
}
}
+ // --------------------------------------------------------------------
+
/**
* Non-persistent database connection
*
diff --git a/system/database/drivers/ibase/ibase_driver.php b/system/database/drivers/ibase/ibase_driver.php
index c9027670d..ab1d1b88d 100644
--- a/system/database/drivers/ibase/ibase_driver.php
+++ b/system/database/drivers/ibase/ibase_driver.php
@@ -45,10 +45,6 @@ class CI_DB_ibase_driver extends CI_DB {
// The character used to escape with
protected $_escape_char = '"';
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
-
protected $_random_keyword = ' Random()'; // database specific random keyword
// Keeps track of the resource for the current transaction
@@ -306,22 +302,6 @@ class CI_DB_ibase_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This public function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 1714704a8..a62ea94b3 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -45,10 +45,6 @@ class CI_DB_mssql_driver extends CI_DB {
// The character used for escaping
protected $_escape_char = '"';
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
-
protected $_random_keyword = ' NEWID()';
// MSSQL-specific properties
@@ -366,22 +362,6 @@ class CI_DB_mssql_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index 29db90408..6b4d84dfb 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -45,10 +45,6 @@ class CI_DB_mysql_driver extends CI_DB {
// The character used for escaping
protected $_escape_char = '`';
- // clause and character used for LIKE escape sequences - not used in MySQL
- protected $_like_escape_str = '';
- protected $_like_escape_chr = '\\';
-
protected $_random_keyword = ' RAND()'; // database specific random keyword
/**
@@ -83,7 +79,14 @@ class CI_DB_mysql_driver extends CI_DB {
*/
public function db_connect()
{
- return @mysql_connect($this->hostname, $this->username, $this->password, TRUE);
+ if ($this->compress === TRUE)
+ {
+ return @mysql_connect($this->hostname, $this->username, $this->password, TRUE, MYSQL_CLIENT_COMPRESS);
+ }
+ else
+ {
+ return @mysql_connect($this->hostname, $this->username, $this->password, TRUE);
+ }
}
// --------------------------------------------------------------------
@@ -95,7 +98,14 @@ class CI_DB_mysql_driver extends CI_DB {
*/
public function db_pconnect()
{
- return @mysql_pconnect($this->hostname, $this->username, $this->password);
+ if ($this->compress === TRUE)
+ {
+ return @mysql_pconnect($this->hostname, $this->username, $this->password, MYSQL_CLIENT_COMPRESS);
+ }
+ else
+ {
+ return @mysql_pconnect($this->hostname, $this->username, $this->password);
+ }
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index be61aab20..14949ecda 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -45,10 +45,6 @@ class CI_DB_mysqli_driver extends CI_DB {
// The character used for escaping
protected $_escape_char = '`';
- // clause and character used for LIKE escape sequences - not used in MySQL
- protected $_like_escape_str = '';
- protected $_like_escape_chr = '\\';
-
protected $_random_keyword = ' RAND()'; // database specific random keyword
/**
@@ -65,6 +61,17 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
public function db_connect()
{
+ // Use MySQL client compression?
+ if ($this->compress === TRUE)
+ {
+ $port = empty($this->port) ? NULL : $this->port;
+
+ $mysqli = new mysqli();
+ @$mysqli->real_connect($this->hostname, $this->username, $this->password, $this->database, $port, NULL, MYSQLI_CLIENT_COMPRESS);
+
+ return $mysqli;
+ }
+
return empty($this->port)
? @new mysqli($this->hostname, $this->username, $this->password, $this->database)
: @new mysqli($this->hostname, $this->username, $this->password, $this->database, $this->port);
@@ -85,6 +92,17 @@ class CI_DB_mysqli_driver extends CI_DB {
return $this->db_connect();
}
+ // Use MySQL client compression?
+ if ($this->compress === TRUE)
+ {
+ $port = empty($this->port) ? NULL : $this->port;
+
+ $mysqli = mysqli_init();
+ $mysqli->real_connect('p:'.$this->hostname, $this->username, $this->password, $this->database, $port, NULL, MYSQLI_CLIENT_COMPRESS);
+
+ return $mysqli;
+ }
+
return empty($this->port)
? @new mysqli('p:'.$this->hostname, $this->username, $this->password, $this->database)
: @new mysqli('p:'.$this->hostname, $this->username, $this->password, $this->database, $this->port);
@@ -400,6 +418,14 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
public function error()
{
+ if ( ! empty($this->conn_id->connect_errno))
+ {
+ return array(
+ 'code' => $this->conn_id->connect_errno,
+ 'message' => is_php('5.2.9') ? $this->conn_id->connect_error : mysqli_connect_error()
+ );
+ }
+
return array('code' => $this->conn_id->errno, 'message' => $this->conn_id->error);
}
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index 691247fee..72cbce5c1 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -54,10 +54,6 @@ class CI_DB_oci8_driver extends CI_DB {
// The character used for excaping
protected $_escape_char = '"';
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
-
/**
* The syntax to count rows is slightly different across different
* database engines, so this string appears in each driver and is
@@ -547,22 +543,6 @@ class CI_DB_oci8_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Insert_batch statement
*
* Generates a platform-specific insert string from the supplied data
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index 8f0a474b0..c1f6ccfe2 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -45,9 +45,7 @@ class CI_DB_odbc_driver extends CI_DB {
// the character used to excape - not necessary for ODBC
protected $_escape_char = '';
- // clause and character used for LIKE escape sequences
protected $_like_escape_str = " {escape '%s'} ";
- protected $_like_escape_chr = '!';
protected $_random_keyword;
@@ -291,22 +289,6 @@ class CI_DB_odbc_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Truncate statement
*
* Generates a platform-specific truncate string from the supplied data
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index 705b16560..0ffe3bc13 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -45,10 +45,6 @@ class CI_DB_pdo_driver extends CI_DB {
// The character used to escaping
protected $_escape_char = '"';
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
-
protected $_random_keyword;
public $trans_enabled = FALSE;
diff --git a/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
index e287f5c63..efc0500a5 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
@@ -130,22 +130,6 @@ class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
index 05eeacfe6..eb3714783 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
@@ -44,10 +44,6 @@ class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver {
protected $_escape_char = '`';
- // clause and character used for LIKE escape sequences - not used in CUBRID
- protected $_like_escape_str = '';
- protected $_like_escape_chr = '\\';
-
protected $_random_keyword = ' RAND()';
/**
diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
index 7060c9eb9..2346e683e 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
@@ -153,22 +153,6 @@ class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
index c074a9a78..6fba764a9 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
@@ -139,22 +139,6 @@ class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
index 832c03c96..399182e12 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
@@ -165,22 +165,6 @@ class CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
index a3efc63dc..028121540 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
@@ -159,22 +159,6 @@ class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
index 78afe246c..b6807026d 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
@@ -44,10 +44,6 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {
protected $_escape_char = '`';
- // clause and character used for LIKE escape sequences - not used in MySQL
- protected $_like_escape_str = '';
- protected $_like_escape_chr = '\\';
-
protected $_random_keyword = ' RAND()';
/**
diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
index 56ec1bce1..d584d1f5b 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
@@ -146,22 +146,6 @@ class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Insert_batch statement
*
* @param string the table name
diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
index 392754ff7..e7ab3fd50 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
@@ -46,7 +46,6 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver {
protected $_escape_char = '';
// clause and character used for LIKE escape sequences
- protected $_like_escape_chr = '!';
protected $_like_escape_str = " {escape '%s'} ";
protected $_random_keyword = ' RAND()';
@@ -157,22 +156,6 @@ class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
index 9a476f143..2a687812a 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
@@ -142,22 +142,6 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
index f125b8f50..ee7c1d15a 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
@@ -182,22 +182,6 @@ class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 8c11c477b..2a91a8959 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -44,10 +44,6 @@ class CI_DB_postgre_driver extends CI_DB {
protected $_escape_char = '"';
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
-
protected $_random_keyword = ' RANDOM()'; // database specific random keyword
/**
@@ -461,22 +457,6 @@ class CI_DB_postgre_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index 19824dbbf..2744a63cf 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -45,10 +45,6 @@ class CI_DB_sqlite_driver extends CI_DB {
// The character used to escape with - not needed for SQLite
protected $_escape_char = '"';
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
-
protected $_random_keyword = ' Random()'; // database specific random keyword
/**
diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php
index cc35d319f..d03be15f5 100644
--- a/system/database/drivers/sqlite3/sqlite3_driver.php
+++ b/system/database/drivers/sqlite3/sqlite3_driver.php
@@ -46,10 +46,6 @@ class CI_DB_sqlite3_driver extends CI_DB {
// The character used for escaping
protected $_escape_char = '"';
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = ' ESCAPE \'%s\' ';
- protected $_like_escape_chr = '!';
-
protected $_random_keyword = ' RANDOM()';
/**
@@ -288,25 +284,16 @@ class CI_DB_sqlite3_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * The error message string
+ * Error
*
- * @return string
- */
- protected function _error_message()
- {
- return $this->conn_id->lastErrorMsg();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * The error message number
+ * Returns an array containing code and message of the last
+ * database error that has occured.
*
- * @return int
+ * @return array
*/
- protected function _error_number()
+ public function error()
{
- return $this->conn_id->lastErrorCode();
+ return array('code' => $this->conn_id->lastErrorCode(), 'message' => $this->conn_id->lastErrorMsg());
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index bda450e88..a6739d192 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -45,10 +45,6 @@ class CI_DB_sqlsrv_driver extends CI_DB {
// The character used for escaping
protected $_escape_char = '"';
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
-
protected $_random_keyword = ' NEWID()';
// SQLSRV-specific properties
@@ -362,22 +358,6 @@ class CI_DB_sqlsrv_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php
index a4383c9d3..3aac14db8 100644
--- a/system/helpers/captcha_helper.php
+++ b/system/helpers/captcha_helper.php
@@ -80,8 +80,7 @@ if ( ! function_exists('create_captcha'))
$current_dir = @opendir($img_path);
while ($filename = @readdir($current_dir))
{
- if ($filename !== '.' && $filename !== '..' && $filename !== 'index.html'
- && (str_replace('.jpg', '', $filename) + $expiration) < $now)
+ if (substr($filename, -4) === '.jpg' && (str_replace('.jpg', '', $filename) + $expiration) < $now)
{
@unlink($img_path.$filename);
}
diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php
index a792f09a2..955d74542 100644
--- a/system/helpers/date_helper.php
+++ b/system/helpers/date_helper.php
@@ -657,5 +657,136 @@ if ( ! function_exists('timezones'))
}
}
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('date_range'))
+{
+ /**
+ * Date range
+ *
+ * Returns a list of dates within a specified period.
+ *
+ * @param int unix_start UNIX timestamp of period start date
+ * @param int unix_end|days UNIX timestamp of period end date
+ * or interval in days.
+ * @param mixed is_unix Specifies wether the second parameter
+ * is a UNIX timestamp or a day interval
+ * - TRUE or 'unix' for a timestamp
+ * - FALSE or 'days' for an interval
+ * @param string date_format Output date format, same as in date()
+ * @return array
+ */
+ function date_range($unix_start = '', $mixed = '', $is_unix = TRUE, $format = 'Y-m-d')
+ {
+ if ($unix_start == '' OR $mixed == '' OR $format == '')
+ {
+ return FALSE;
+ }
+
+ $is_unix = ! ( ! $is_unix OR $is_unix === 'days');
+
+ // Validate input and try strtotime() on invalid timestamps/intervals, just in case
+ if ( ( ! preg_match('/^[0-9]+$/', $unix_start) && ($unix_start = @strtotime($unix_time)) === FALSE)
+ OR ( ! preg_match('/^[0-9]+$/', $mixed) && ($is_unix === FALSE OR ($mixed = @strtotime($mixed)) === FALSE))
+ OR ($is_unix === TRUE && $mixed < $unix_start))
+ {
+ return FALSE;
+ }
+
+ if ($is_unix && ($unix_start == $mixed OR date($format, $unix_start) === date($format, $mixed)))
+ {
+ return array($start_date);
+ }
+
+ $range = array();
+
+ /* NOTE: Even though the DateTime object has many useful features, it appears that
+ * it doesn't always handle properly timezones, when timestamps are passed
+ * directly to its constructor. Neither of the following gave proper results:
+ *
+ * new DateTime('<timestamp>')
+ * new DateTime('<timestamp>', '<timezone>')
+ *
+ * --- available in PHP 5.3:
+ *
+ * DateTime::createFromFormat('<format>', '<timestamp>')
+ * DateTime::createFromFormat('<format>', '<timestamp>', '<timezone')
+ *
+ * ... so we'll have to set the timestamp after the object is instantiated.
+ * Furthermore, in PHP 5.3 we can use DateTime::setTimestamp() to do that and
+ * given that we have UNIX timestamps - we should use it.
+ */
+ $from = new DateTime();
+
+ if (is_php('5.3'))
+ {
+ $from->setTimestamp($unix_start);
+ if ($is_unix)
+ {
+ $arg = new DateTime();
+ $arg->setTimestamp($mixed);
+ }
+ else
+ {
+ $arg = (int) $mixed;
+ }
+
+ $period = new DatePeriod($from, new DateInterval('P1D'), $arg);
+ foreach ($period as $date)
+ {
+ $range[] = $date->format($format);
+ }
+
+ /* If a period end date was passed to the DatePeriod constructor, it might not
+ * be in our results. Not sure if this is a bug or it's just possible because
+ * the end date might actually be less than 24 hours away from the previously
+ * generated DateTime object, but either way - we have to append it manually.
+ */
+ if ( ! is_int($arg) && $range[count($range) - 1] !== $arg->format($format))
+ {
+ $range[] = $arg->format($format);
+ }
+
+ return $range;
+ }
+
+ $from->setDate(date('Y', $unix_start), date('n', $unix_start), date('j', $unix_start));
+ $from->setTime(date('G', $unix_start), date('i', $unix_start), date('s', $unix_start));
+ if ($is_unix)
+ {
+ $arg = new DateTime();
+ $arg->setDate(date('Y', $mixed), date('n', $mixed), date('j', $mixed));
+ $arg->setTime(date('G', $mixed), date('i', $mixed), date('s', $mixed));
+ }
+ else
+ {
+ $arg = (int) $mixed;
+ }
+ $range[] = $from->format($format);
+
+ if (is_int($arg)) // Day intervals
+ {
+ do
+ {
+ $from->modify('+1 day');
+ $range[] = $from->format($format);
+ }
+ while (--$arg > 0);
+ }
+ else // end date UNIX timestamp
+ {
+ for ($from->modify('+1 day'), $end_check = $arg->format('Ymd'); $from->format('Ymd') < $end_check; $from->modify('+1 day'))
+ {
+ $range[] = $from->format($format);
+ }
+
+ // Our loop only appended dates prior to our end date
+ $range[] = $arg->format($format);
+ }
+
+ return $range;
+ }
+}
+
/* End of file date_helper.php */
/* Location: ./system/helpers/date_helper.php */ \ No newline at end of file
diff --git a/system/helpers/directory_helper.php b/system/helpers/directory_helper.php
index e7d3b5e8a..7d6b6770e 100644
--- a/system/helpers/directory_helper.php
+++ b/system/helpers/directory_helper.php
@@ -62,7 +62,7 @@ if ( ! function_exists('directory_map'))
while (FALSE !== ($file = readdir($fp)))
{
// Remove '.', '..', and hidden files [optional]
- if ( ! trim($file, '.') OR ($hidden === FALSE && $file[0] === '.'))
+ if ($file === '.' OR $file === '..' OR ($hidden === FALSE && $file[0] === '.'))
{
continue;
}
diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php
index 9843e804e..2372e8174 100644
--- a/system/helpers/html_helper.php
+++ b/system/helpers/html_helper.php
@@ -215,7 +215,7 @@ if ( ! function_exists('img'))
}
}
- return $img._stringify_attributes($attributes).'/>';
+ return $img._stringify_attributes($attributes).' />';
}
}
diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php
index 8a1f01b51..b592f3cc0 100644
--- a/system/helpers/text_helper.php
+++ b/system/helpers/text_helper.php
@@ -89,7 +89,8 @@ if ( ! function_exists('character_limiter'))
return $str;
}
- $str = preg_replace('/\s+/', ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $str));
+ // a bit complicated, but faster than preg_replace with \s+
+ $str = preg_replace('/ {2,}/', ' ', str_replace(array("\r", "\n", "\t", "\x0B", "\x0C"), ' ', $str));
if (strlen($str) <= $n)
{
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
index 57208c948..b1f5eccf1 100644
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -534,7 +534,7 @@ if ( ! function_exists('redirect'))
}
// IIS environment likely? Use 'refresh' for better compatibility
- if (DIRECTORY_SEPARATOR !== '/' && $method === 'auto')
+ if ($method === 'auto' && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== FALSE)
{
$method = 'refresh';
}
diff --git a/system/language/english/date_lang.php b/system/language/english/date_lang.php
index 229d33d2e..6683e4c69 100644
--- a/system/language/english/date_lang.php
+++ b/system/language/english/date_lang.php
@@ -25,20 +25,20 @@
* @filesource
*/
-$lang['date_year'] = "Year";
-$lang['date_years'] = "Years";
-$lang['date_month'] = "Month";
-$lang['date_months'] = "Months";
-$lang['date_week'] = "Week";
-$lang['date_weeks'] = "Weeks";
-$lang['date_day'] = "Day";
-$lang['date_days'] = "Days";
-$lang['date_hour'] = "Hour";
-$lang['date_hours'] = "Hours";
-$lang['date_minute'] = "Minute";
-$lang['date_minutes'] = "Minutes";
-$lang['date_second'] = "Second";
-$lang['date_seconds'] = "Seconds";
+$lang['date_year'] = 'Year';
+$lang['date_years'] = 'Years';
+$lang['date_month'] = 'Month';
+$lang['date_months'] = 'Months';
+$lang['date_week'] = 'Week';
+$lang['date_weeks'] = 'Weeks';
+$lang['date_day'] = 'Day';
+$lang['date_days'] = 'Days';
+$lang['date_hour'] = 'Hour';
+$lang['date_hours'] = 'Hours';
+$lang['date_minute'] = 'Minute';
+$lang['date_minutes'] = 'Minutes';
+$lang['date_second'] = 'Second';
+$lang['date_seconds'] = 'Seconds';
$lang['UM12'] = '(UTC -12:00) Baker/Howland Island';
$lang['UM11'] = '(UTC -11:00) Niue';
diff --git a/system/language/english/form_validation_lang.php b/system/language/english/form_validation_lang.php
index 021776161..cf1b3b503 100644
--- a/system/language/english/form_validation_lang.php
+++ b/system/language/english/form_validation_lang.php
@@ -43,8 +43,8 @@ $lang['integer'] = 'The %s field must contain an integer.';
$lang['regex_match'] = 'The %s field is not in the correct format.';
$lang['matches'] = 'The %s field does not match the %s field.';
$lang['is_unique'] = 'The %s field must contain a unique value.';
-$lang['is_natural'] = 'The %s field must contain only positive numbers.';
-$lang['is_natural_no_zero'] = 'The %s field must contain a number greater than zero.';
+$lang['is_natural'] = 'The %s field must only contain digits.';
+$lang['is_natural_no_zero'] = 'The %s field must only contain digits and must be greater than zero.';
$lang['decimal'] = 'The %s field must contain a decimal number.';
$lang['less_than'] = 'The %s field must contain a number less than %s.';
$lang['less_than_equal_to'] = 'The %s field must contain a number less than or equal to %s.';
diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php
index d67ee2549..1d084c8e4 100644
--- a/system/libraries/Driver.php
+++ b/system/libraries/Driver.php
@@ -54,13 +54,29 @@ class CI_Driver_Library {
protected $lib_name;
/**
+ * Get magic method
+ *
* The first time a child is used it won't exist, so we instantiate it
* subsequents calls will go straight to the proper child.
*
- * @param mixed $child
- * @return mixed
+ * @param string Child class name
+ * @return object Child class
*/
public function __get($child)
+ {
+ // Try to load the driver
+ return $this->load_driver($child);
+ }
+
+ /**
+ * Load driver
+ *
+ * Separate load_driver call to support explicit driver load by library or user
+ *
+ * @param string Child class name
+ * @return object Child class
+ */
+ public function load_driver($child)
{
if ( ! isset($this->lib_name))
{
@@ -268,4 +284,4 @@ class CI_Driver {
}
/* End of file Driver.php */
-/* Location: ./system/libraries/Driver.php */ \ No newline at end of file
+/* Location: ./system/libraries/Driver.php */
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index b922cb1c0..507067f42 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -188,7 +188,7 @@ class CI_Email {
* @param string
* @return object
*/
- public function from($from, $name = '')
+ public function from($from, $name = '', $return_path = '')
{
if (preg_match('/\<(.*)\>/', $from, $match))
{
@@ -198,6 +198,10 @@ class CI_Email {
if ($this->validate)
{
$this->validate_email($this->_str_to_array($from));
+ if ($return_path)
+ {
+ $this->validate_email($this->_str_to_array($return_path));
+ }
}
// prepare the display name
@@ -216,7 +220,12 @@ class CI_Email {
}
$this->set_header('From', $name.' <'.$from.'>');
- $this->set_header('Return-Path', '<'.$from.'>');
+
+ if( ! $return_path)
+ {
+ $return_path = $from;
+ }
+ $this->set_header('Return-Path', '<'.$return_path.'>');
return $this;
}
@@ -1399,7 +1408,7 @@ class CI_Email {
{
// most documentation of sendmail using the "-f" flag lacks a space after it, however
// we've encountered servers that seem to require it to be in place.
- return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, '-f '.$this->clean_email($this->_headers['From']));
+ return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, '-f '.$this->clean_email($this->_headers['Return-Path']));
}
}
@@ -1412,7 +1421,7 @@ class CI_Email {
*/
protected function _send_with_sendmail()
{
- $fp = @popen($this->mailpath.' -oi -f '.$this->clean_email($this->_headers['From']).' -t', 'w');
+ $fp = @popen($this->mailpath.' -oi -f '.$this->clean_email($this->_headers['From']).' -t'.' -r '.$this->clean_email($this->_headers['Return-Path']), 'w');
if ($fp === FALSE OR $fp === NULL)
{
diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php
index 8ffd93aea..679609251 100644
--- a/system/libraries/Encrypt.php
+++ b/system/libraries/Encrypt.php
@@ -484,7 +484,7 @@ class CI_Encrypt {
*/
public function set_hash($type = 'sha1')
{
- $this->_hash_type = ($type !== 'sha1' && $type !== 'md5') ? 'sha1' : $type;
+ $this->_hash_type = in_array($type, hash_algos()) ? $type : 'sha1';
}
// --------------------------------------------------------------------
@@ -497,7 +497,7 @@ class CI_Encrypt {
*/
public function hash($str)
{
- return ($this->_hash_type === 'sha1') ? sha1($str) : md5($str);
+ return hash($this->_hash_type, $str);
}
}
diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php
index 899b995d4..ef4187847 100644
--- a/system/libraries/Image_lib.php
+++ b/system/libraries/Image_lib.php
@@ -1320,6 +1320,13 @@ class CI_Image_lib {
imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);
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)
+ {
+ imagealphablending($src_img, FALSE);
+ imagesavealpha($src_img, TRUE);
+ }
}
// Output the final image
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
index 5573f6407..e1e729bb0 100644
--- a/system/libraries/Pagination.php
+++ b/system/libraries/Pagination.php
@@ -52,20 +52,20 @@ class CI_Pagination {
protected $full_tag_open = '';
protected $full_tag_close = '';
protected $first_tag_open = '';
- protected $first_tag_close = '&nbsp;';
- protected $last_tag_open = '&nbsp;';
+ protected $first_tag_close = '';
+ protected $last_tag_open = '';
protected $last_tag_close = '';
protected $first_url = ''; // Alternative URL for the First Page.
- protected $cur_tag_open = '&nbsp;<strong>';
+ protected $cur_tag_open = '<strong>';
protected $cur_tag_close = '</strong>';
- protected $next_tag_open = '&nbsp;';
- protected $next_tag_close = '&nbsp;';
- protected $prev_tag_open = '&nbsp;';
+ protected $next_tag_open = '';
+ protected $next_tag_close = '';
+ protected $prev_tag_open = '';
protected $prev_tag_close = '';
- protected $num_tag_open = '&nbsp;';
+ protected $num_tag_open = '';
protected $num_tag_close = '';
protected $page_query_string = FALSE;
- protected $query_string_segment = 'per_page';
+ protected $query_string_segment = 'per_page';
protected $display_pages = TRUE;
protected $_attributes = '';
protected $_link_types = array();
@@ -215,7 +215,8 @@ class CI_Pagination {
// string. If post, add a trailing slash to the base URL if needed
if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
{
- $this->base_url = rtrim($this->base_url).'&amp;'.$this->query_string_segment.'=';
+ $segment = (strpos($this->base_url, '?')) ? '&amp;' : '?';
+ $this->base_url = rtrim($this->base_url).$segment.$this->query_string_segment.'=';
}
else
{
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
new file mode 100755
index 000000000..e6f6050c0
--- /dev/null
+++ b/system/libraries/Session/Session.php
@@ -0,0 +1,689 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2006 - 2012 EllisLab, Inc.
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.0
+ * @filesource
+ */
+
+/**
+ * CodeIgniter Session Class
+ *
+ * The user interface defined by EllisLabs, now with puggable drivers to manage different storage mechanisms.
+ * By default, the cookie session driver will load, but the 'sess_driver' config/param item (see above) can be
+ * used to specify the 'native' driver, or any other you might create.
+ * Once loaded, this driver setup is a drop-in replacement for the former CI_Session library, taking its place as the
+ * 'session' member of the global controller framework (e.g.: $CI->session or $this->session).
+ * In keeping with the CI_Driver methodology, multiple drivers may be loaded, although this might be a bit confusing.
+ * The CI_Session library class keeps track of the most recently loaded driver as "current" to call for driver methods.
+ * Ideally, one driver is loaded and all calls go directly through the main library interface. However, any methods
+ * called through the specific driver will switch the "current" driver to itself before invoking the library method
+ * (which will then call back into the driver for low-level operations). So, alternation between two drivers can be
+ * achieved by specifying which driver to use for each call (e.g.: $this->session->native->set_userdata('foo', 'bar');
+ * $this->session->cookie->userdata('foo'); $this->session->native->unset_userdata('foo');). Notice in the previous
+ * example that the _native_ userdata value 'foo' would be set to 'bar', which would NOT be returned by the call for
+ * the _cookie_ userdata 'foo', nor would the _cookie_ value be unset by the call to unset the _native_ 'foo' value.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/libraries/sessions.html
+ */
+class CI_Session extends CI_Driver_Library {
+
+ public $params = array();
+ protected $current = NULL;
+ protected $userdata = array();
+
+ const FLASHDATA_KEY = 'flash';
+ const FLASHDATA_NEW = ':new:';
+ const FLASHDATA_OLD = ':old:';
+ const FLASHDATA_EXP = ':exp:';
+ const EXPIRATION_KEY = '__expirations';
+ const TEMP_EXP_DEF = 300;
+
+ /**
+ * CI_Session constructor
+ *
+ * The constructor loads the configured driver ('sess_driver' in config.php or as a parameter), running
+ * routines in its constructor, and manages flashdata aging.
+ *
+ * @param array Configuration parameters
+ */
+ public function __construct(array $params = array())
+ {
+ log_message('debug', 'CI_Session Class Initialized');
+
+ // Get valid drivers list
+ $CI =& get_instance();
+ $this->valid_drivers = array(
+ 'Session_native',
+ 'Session_cookie'
+ );
+ $key = 'sess_valid_drivers';
+ $drivers = isset($params[$key]) ? $params[$key] : $CI->config->item($key);
+ if ($drivers)
+ {
+ is_array($drivers) OR $drivers = array($drivers);
+
+ // Add driver names to valid list
+ foreach ($drivers as $driver)
+ {
+ if ( ! in_array(strtolower($driver), array_map('strtolower', $this->valid_drivers)))
+ {
+ $this->valid_drivers[] = $driver;
+ }
+ }
+ }
+
+ // Get driver to load
+ $key = 'sess_driver';
+ $driver = isset($params[$key]) ? $params[$key] : $CI->config->item($key);
+ if ( ! $driver)
+ {
+ $driver = 'cookie';
+ }
+
+ if ( ! in_array('session_'.strtolower($driver), array_map('strtolower', $this->valid_drivers)))
+ {
+ $this->valid_drivers[] = 'Session_'.$driver;
+ }
+
+ // Save a copy of parameters in case drivers need access
+ $this->params = $params;
+
+ // Load driver and get array reference
+ $this->load_driver($driver);
+
+ // Delete 'old' flashdata (from last request)
+ $this->_flashdata_sweep();
+
+ // Mark all new flashdata as old (data will be deleted before next request)
+ $this->_flashdata_mark();
+
+ // Delete expired tempdata
+ $this->_tempdata_sweep();
+
+ log_message('debug', 'CI_Session routines successfully run');
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Loads session storage driver
+ *
+ * @param string Driver classname
+ * @return object Loaded driver object
+ */
+ public function load_driver($driver)
+ {
+ // Save reference to most recently loaded driver as library default and sync userdata
+ $this->current = parent::load_driver($driver);
+ $this->userdata =& $this->current->get_userdata();
+ return $this->current;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Select default session storage driver
+ *
+ * @param string Driver classname
+ * @return void
+ */
+ public function select_driver($driver)
+ {
+ // Validate driver name
+ $lowername = strtolower(str_replace('CI_', '', $driver));
+ if (in_array($lowername, array_map('strtolower', $this->valid_drivers)))
+ {
+ // See if driver is loaded
+ $child = str_replace($this->lib_name.'_', '', $driver);
+ if (isset($this->$child))
+ {
+ // See if driver is already current
+ if ($this->$child !== $this->current)
+ {
+ // Make driver current and sync userdata
+ $this->current = $this->$child;
+ $this->userdata =& $this->current->get_userdata();
+ }
+ }
+ else
+ {
+ // Load new driver
+ $this->load_driver($child);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Destroy the current session
+ *
+ * @return void
+ */
+ public function sess_destroy()
+ {
+ // Just call destroy on driver
+ $this->current->sess_destroy();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Regenerate the current session
+ *
+ * @param bool Destroy session data flag (default: false)
+ * @return void
+ */
+ public function sess_regenerate($destroy = FALSE)
+ {
+ // Call regenerate on driver and resync userdata
+ $this->current->sess_regenerate($destroy);
+ $this->userdata =& $this->current->get_userdata();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch a specific item from the session array
+ *
+ * @param string Item key
+ * @return string Item value or NULL if not found
+ */
+ public function userdata($item)
+ {
+ return isset($this->userdata[$item]) ? $this->userdata[$item] : NULL;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch all session data
+ *
+ * @return array User data array
+ */
+ public function all_userdata()
+ {
+ return isset($this->userdata) ? $this->userdata : NULL;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch all flashdata
+ *
+ * @return array Flash data array
+ */
+ public function all_flashdata()
+ {
+ $out = array();
+
+ // loop through all userdata
+ foreach ($this->all_userdata() as $key => $val)
+ {
+ // if it contains flashdata, add it
+ if (strpos($key, self::FLASHDATA_KEY.self::FLASHDATA_OLD) !== FALSE)
+ {
+ $key = str_replace(self::FLASHDATA_KEY.self::FLASHDATA_OLD, '', $key);
+ $out[$key] = $val;
+ }
+ }
+ return $out;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Add or change data in the "userdata" array
+ *
+ * @param mixed Item name or array of items
+ * @param string Item value or empty string
+ * @return void
+ */
+ public function set_userdata($newdata = array(), $newval = '')
+ {
+ // Wrap params as array if singular
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => $newval);
+ }
+
+ // Set each name/value pair
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $this->userdata[$key] = $val;
+ }
+ }
+
+ // Tell driver data changed
+ $this->current->sess_save();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Delete a session variable from the "userdata" array
+ *
+ * @param mixed Item name or array of item names
+ * @return void
+ */
+ public function unset_userdata($newdata = array())
+ {
+ // Wrap single name as array
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => '');
+ }
+
+ // Unset each item name
+ if (count($newdata) > 0)
+ {
+ foreach (array_keys($newdata) as $key)
+ {
+ unset($this->userdata[$key]);
+ }
+ }
+
+ // Tell driver data changed
+ $this->current->sess_save();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Determine if an item exists
+ *
+ * @param string Item name
+ * @return bool
+ */
+ public function has_userdata($item)
+ {
+ return isset($this->userdata[$item]);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Add or change flashdata, only available until the next request
+ *
+ * @param mixed Item name or array of items
+ * @param string Item value or empty string
+ * @return void
+ */
+ public function set_flashdata($newdata = array(), $newval = '')
+ {
+ // Wrap item as array if singular
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => $newval);
+ }
+
+ // Prepend each key name and set value
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_NEW.$key;
+ $this->set_userdata($flashdata_key, $val);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Keeps existing flashdata available to next request.
+ *
+ * @param string Item key
+ * @return void
+ */
+ public function keep_flashdata($key)
+ {
+ // 'old' flashdata gets removed. Here we mark all flashdata as 'new' to preserve it from _flashdata_sweep()
+ // Note the function will return NULL if the $key provided cannot be found
+ $old_flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$key;
+ $value = $this->userdata($old_flashdata_key);
+
+ $new_flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_NEW.$key;
+ $this->set_userdata($new_flashdata_key, $value);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch a specific flashdata item from the session array
+ *
+ * @param string Item key
+ * @return string
+ */
+ public function flashdata($key)
+ {
+ // Prepend key and retrieve value
+ $flashdata_key = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$key;
+ return $this->userdata($flashdata_key);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Add or change tempdata, only available until expiration
+ *
+ * @param mixed Item name or array of items
+ * @param string Item value or empty string
+ * @param int Item lifetime in seconds or 0 for default
+ * @return void
+ */
+ public function set_tempdata($newdata = array(), $newval = '', $expire = 0)
+ {
+ // Set expiration time
+ $expire = time() + ($expire ? $expire : self::TEMP_EXP_DEF);
+
+ // Wrap item as array if singular
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => $newval);
+ }
+
+ // Get or create expiration list
+ $expirations = $this->userdata(self::EXPIRATION_KEY);
+ if ( ! $expirations)
+ {
+ $expirations = array();
+ }
+
+ // Prepend each key name and set value
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key;
+ $expirations[$tempdata_key] = $expire;
+ $this->set_userdata($tempdata_key, $val);
+ }
+ }
+
+ // Update expiration list
+ $this->set_userdata(self::EXPIRATION_KEY, $expirations);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Delete a temporary session variable from the "userdata" array
+ *
+ * @param mixed Item name or array of item names
+ * @return void
+ */
+ public function unset_tempdata($newdata = array())
+ {
+ // Get expirations list
+ $expirations = $this->userdata(self::EXPIRATION_KEY);
+ if (empty($expirations))
+ {
+ // Nothing to do
+ return;
+ }
+
+ // Wrap single name as array
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => '');
+ }
+
+ // Prepend each item name and unset
+ if (count($newdata) > 0)
+ {
+ foreach (array_keys($newdata) as $key)
+ {
+ $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key;
+ unset($expirations[$tempdata_key]);
+ $this->unset_userdata($tempdata_key);
+ }
+ }
+
+ // Update expiration list
+ $this->set_userdata(self::EXPIRATION_KEY, $expirations);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch a specific tempdata item from the session array
+ *
+ * @param string Item key
+ * @return string
+ */
+ public function tempdata($key)
+ {
+ // Prepend key and return value
+ $tempdata_key = self::FLASHDATA_KEY.self::FLASHDATA_EXP.$key;
+ return $this->userdata($tempdata_key);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Identifies flashdata as 'old' for removal
+ * when _flashdata_sweep() runs.
+ *
+ * @return void
+ */
+ protected function _flashdata_mark()
+ {
+ foreach ($this->all_userdata() as $name => $value)
+ {
+ $parts = explode(self::FLASHDATA_NEW, $name);
+ if (is_array($parts) && count($parts) === 2)
+ {
+ $new_name = self::FLASHDATA_KEY.self::FLASHDATA_OLD.$parts[1];
+ $this->set_userdata($new_name, $value);
+ $this->unset_userdata($name);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Removes all flashdata marked as 'old'
+ *
+ * @return void
+ */
+ protected function _flashdata_sweep()
+ {
+ $userdata = $this->all_userdata();
+ foreach (array_keys($userdata) as $key)
+ {
+ if (strpos($key, self::FLASHDATA_OLD))
+ {
+ $this->unset_userdata($key);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Removes all expired tempdata
+ *
+ * @return void
+ */
+ protected function _tempdata_sweep()
+ {
+ // Get expirations list
+ $expirations = $this->userdata(self::EXPIRATION_KEY);
+ if (empty($expirations))
+ {
+ // Nothing to do
+ return;
+ }
+
+ // Unset expired elements
+ $now = time();
+ $userdata = $this->all_userdata();
+ foreach (array_keys($userdata) as $key)
+ {
+ if (strpos($key, self::FLASHDATA_EXP) && $expirations[$key] < $now)
+ {
+ unset($expirations[$key]);
+ $this->unset_userdata($key);
+ }
+ }
+
+ // Update expiration list
+ $this->set_userdata(self::EXPIRATION_KEY, $expirations);
+ }
+
+}
+
+// ------------------------------------------------------------------------
+
+/**
+ * CI_Session_driver Class
+ *
+ * Extend this class to make a new CI_Session driver.
+ * A CI_Session driver basically manages an array of name/value pairs with some sort of storage mechanism.
+ * To make a new driver, derive from (extend) CI_Session_driver. Overload the initialize method and read or create
+ * session data. Then implement a save handler to write changed data to storage (sess_save), a destroy handler
+ * to remove deleted data (sess_destroy), and an access handler to expose the data (get_userdata).
+ * Put your driver in the libraries/Session/drivers folder anywhere in the loader paths. This includes the
+ * application directory, the system directory, or any path you add with $CI->load->add_package_path().
+ * Your driver must be named CI_Session_<name>, and your filename must be Session_<name>.php,
+ * preferably also capitalized. (e.g.: CI_Session_foo in libraries/Session/drivers/Session_foo.php)
+ * Then specify the driver by setting 'sess_driver' in your config file or as a parameter when loading the CI_Session
+ * object. (e.g.: $config['sess_driver'] = 'foo'; OR $CI->load->driver('session', array('sess_driver' => 'foo')); )
+ * Already provided are the Native driver, which manages the native PHP $_SESSION array, and
+ * the Cookie driver, which manages the data in a browser cookie, with optional extra storage in a database table.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author EllisLab Dev Team
+ */
+abstract class CI_Session_driver extends CI_Driver {
+
+ /**
+ * Decorate
+ *
+ * Decorates the child with the parent driver lib's methods and properties
+ *
+ * @param object Parent library object
+ * @return void
+ */
+ public function decorate($parent)
+ {
+ // Call base class decorate first
+ parent::decorate($parent);
+
+ // Call initialize method now that driver has access to $this->_parent
+ $this->initialize();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * __call magic method
+ *
+ * Handles access to the parent driver library's methods
+ *
+ * @param string Library method name
+ * @param array Method arguments (default: none)
+ * @return mixed
+ */
+ public function __call($method, $args = array())
+ {
+ // Make sure the parent library uses this driver
+ $this->_parent->select_driver(get_class($this));
+ return parent::__call($method, $args);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Initialize driver
+ *
+ * @return void
+ */
+ protected function initialize()
+ {
+ // Overload this method to implement initialization
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Save the session data
+ *
+ * Data in the array has changed - perform any storage synchronization
+ * necessary. The child class MUST implement this abstract method!
+ *
+ * @return void
+ */
+ abstract public function sess_save();
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Destroy the current session
+ *
+ * Clean up storage for this session - it has been terminated.
+ * The child class MUST implement this abstract method!
+ *
+ * @return void
+ */
+ abstract public function sess_destroy();
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Regenerate the current session
+ *
+ * Regenerate the session ID.
+ * The child class MUST implement this abstract method!
+ *
+ * @param bool Destroy session data flag (default: false)
+ * @return void
+ */
+ abstract public function sess_regenerate($destroy = FALSE);
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get a reference to user data array
+ *
+ * Give array access to the main CI_Session object.
+ * The child class MUST implement this abstract method!
+ *
+ * @return array Reference to userdata
+ */
+ abstract public function &get_userdata();
+
+}
+
+/* End of file Session.php */
+/* Location: ./system/libraries/Session/Session.php */ \ No newline at end of file
diff --git a/system/libraries/Session.php b/system/libraries/Session/drivers/Session_cookie.php
index af38dc366..4f415cc0d 100644..100755
--- a/system/libraries/Session.php
+++ b/system/libraries/Session/drivers/Session_cookie.php
@@ -9,7 +9,7 @@
* Licensed under the Open Software License version 3.0
*
* This source file is subject to the Open Software License (OSL 3.0) that is
- * bundled with this package in the files license.txt / license.rst. It is
+ * bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
* http://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to obtain it
@@ -26,7 +26,9 @@
*/
/**
- * Session Class
+ * Cookie-based session management driver
+ *
+ * This is the classic CI_Session functionality, as written by EllisLab, abstracted out to a driver.
*
* @package CodeIgniter
* @subpackage Libraries
@@ -34,7 +36,7 @@
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/libraries/sessions.html
*/
-class CI_Session {
+class CI_Session_cookie extends CI_Session_driver {
/**
* Whether to encrypt the session cookie
@@ -69,7 +71,7 @@ class CI_Session {
*
* @var bool
*/
- public $sess_expire_on_close = FALSE;
+ public $sess_expire_on_close = FALSE;
/**
* Whether to match session on ip address
@@ -83,7 +85,7 @@ class CI_Session {
*
* @var bool
*/
- public $sess_match_useragent = TRUE;
+ public $sess_match_useragent = TRUE;
/**
* Name of session cookie
@@ -104,7 +106,7 @@ class CI_Session {
*
* @var string
*/
- public $cookie_path = '';
+ public $cookie_path = '';
/**
* Session cookie domain
@@ -142,26 +144,18 @@ class CI_Session {
public $encryption_key = '';
/**
- * String to indicate flash data cookies
- *
- * @var string
- */
- public $flashdata_key = 'flash';
-
- /**
* Timezone to use for the current time
*
* @var string
*/
public $time_reference = 'local';
-
/**
* Session data
*
* @var array
*/
- public $userdata = array();
+ public $userdata = array();
/**
* Reference to CodeIgniter instance
@@ -178,31 +172,65 @@ class CI_Session {
public $now;
/**
- * Session Constructor
+ * Default userdata keys
*
- * The constructor runs the session routines automatically
- * whenever the class is instantiated.
+ * @var array
+ */
+ protected $defaults = array(
+ 'session_id' => NULL,
+ 'ip_address' => NULL,
+ 'user_agent' => NULL,
+ 'last_activity' => NULL
+ );
+
+ /**
+ * Data needs DB update flag
+ *
+ * @var bool
+ */
+ protected $data_dirty = FALSE;
+
+ /**
+ * Initialize session driver object
*
- * @param array
* @return void
*/
- public function __construct($params = array())
+ protected function initialize()
{
- log_message('debug', 'Session Class Initialized');
-
// Set the super object to a local variable for use throughout the class
$this->CI =& get_instance();
// Set all the session preferences, which can either be set
- // manually via the $params array above or via the config file
- foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_expire_on_close', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key)
+ // manually via the $params array or via the config file
+ $prefs = array(
+ 'sess_encrypt_cookie',
+ 'sess_use_database',
+ 'sess_table_name',
+ 'sess_expiration',
+ 'sess_expire_on_close',
+ 'sess_match_ip',
+ 'sess_match_useragent',
+ 'sess_cookie_name',
+ 'cookie_path',
+ 'cookie_domain',
+ 'cookie_secure',
+ 'cookie_httponly',
+ 'sess_time_to_update',
+ 'time_reference',
+ 'cookie_prefix',
+ 'encryption_key'
+ );
+
+ foreach ($prefs as $key)
{
- $this->$key = isset($params[$key]) ? $params[$key] : $this->CI->config->item($key);
+ $this->$key = isset($this->_parent->params[$key])
+ ? $this->_parent->params[$key]
+ : $this->CI->config->item($key);
}
if ($this->encryption_key === '')
{
- show_error('In order to use the Session class you are required to set an encryption key in your config file.');
+ show_error('In order to use the Cookie Session driver you are required to set an encryption key in your config file.');
}
// Load the string helper so we can use the strip_slashes() function
@@ -214,14 +242,18 @@ class CI_Session {
$this->CI->load->library('encrypt');
}
- // Are we using a database? If so, load it
+ // Check for database
if ($this->sess_use_database === TRUE && $this->sess_table_name !== '')
{
+ // Load database driver
$this->CI->load->database();
+
+ // Register shutdown function
+ register_shutdown_function(array($this, '_update_db'));
}
- // Set the "now" time. Can either be GMT or server time, based on the
- // config prefs. We use this to set the "last activity" time
+ // Set the "now" time. Can either be GMT or server time, based on the config prefs.
+ // We use this to set the "last activity" time
$this->now = $this->_get_time();
// Set the session length. If the session expiration is
@@ -236,59 +268,135 @@ class CI_Session {
// Run the Session routine. If a session doesn't exist we'll
// create a new one. If it does, we'll update it.
- if ( ! $this->sess_read())
+ if ( ! $this->_sess_read())
{
- $this->sess_create();
+ $this->_sess_create();
}
else
{
- $this->sess_update();
+ $this->_sess_update();
}
- // Delete 'old' flashdata (from last request)
- $this->_flashdata_sweep();
-
- // Mark all new flashdata as old (data will be deleted before next request)
- $this->_flashdata_mark();
-
// Delete expired sessions if necessary
$this->_sess_gc();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Write the session data
+ *
+ * @return void
+ */
+ public function sess_save()
+ {
+ // Check for database
+ if ($this->sess_use_database === TRUE)
+ {
+ // Mark custom data as dirty so we know to update the DB
+ $this->data_dirty = TRUE;
+ }
+
+ // Write the cookie
+ $this->_set_cookie();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Destroy the current session
+ *
+ * @return void
+ */
+ public function sess_destroy()
+ {
+ // Kill the session DB row
+ if ($this->sess_use_database === TRUE && isset($this->userdata['session_id']))
+ {
+ $this->CI->db->delete($this->sess_table_name, array('session_id' => $this->userdata['session_id']));
+ $this->data_dirty = FALSE;
+ }
+
+ // Kill the cookie
+ $this->_setcookie($this->sess_cookie_name, addslashes(serialize(array())), ($this->now - 31500000),
+ $this->cookie_path, $this->cookie_domain, 0);
+
+ // Kill session data
+ $this->userdata = array();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Regenerate the current session
+ *
+ * Regenerate the session id
+ *
+ * @param bool Destroy session data flag (default: false)
+ * @return void
+ */
+ public function sess_regenerate($destroy = FALSE)
+ {
+ // Check destroy flag
+ if ($destroy)
+ {
+ // Destroy old session and create new one
+ $this->sess_destroy();
+ $this->_sess_create();
+ }
+ else
+ {
+ // Just force an update to recreate the id
+ $this->_sess_update(TRUE);
+ }
+ }
- log_message('debug', 'Session routines successfully run');
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get a reference to user data array
+ *
+ * @return array Reference to userdata
+ */
+ public function &get_userdata()
+ {
+ return $this->userdata;
}
- // --------------------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
* Fetch the current session data if it exists
*
* @return bool
*/
- public function sess_read()
+ protected function _sess_read()
{
// Fetch the cookie
$session = $this->CI->input->cookie($this->sess_cookie_name);
- // No cookie? Goodbye cruel world!...
+ // No cookie? Goodbye cruel world!...
if ($session === NULL)
{
log_message('debug', 'A session cookie was not found.');
return FALSE;
}
- // Decrypt the cookie data
+ // Check for encryption
if ($this->sess_encrypt_cookie === TRUE)
{
+ // Decrypt the cookie data
$session = $this->CI->encrypt->decode($session);
}
else
{
- // encryption was not used, so we need to check the md5 hash
- $hash = substr($session, strlen($session)-32); // get last 32 chars
- $session = substr($session, 0, strlen($session)-32);
+ // Encryption was not used, so we need to check the md5 hash in the last 32 chars
+ $len = strlen($session)-32;
+ $hash = substr($session, $len);
+ $session = substr($session, 0, $len);
// Does the md5 hash match? This is to prevent manipulation of session data in userspace
- if ($hash !== md5($session.$this->encryption_key))
+ if ($hash !== md5($session.$this->encryption_key))
{
log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
$this->sess_destroy();
@@ -321,7 +429,8 @@ class CI_Session {
}
// Does the User Agent Match?
- if ($this->sess_match_useragent === TRUE && trim($session['user_agent']) !== trim(substr($this->CI->input->user_agent(), 0, 120)))
+ if ($this->sess_match_useragent === TRUE &&
+ trim($session['user_agent']) !== trim(substr($this->CI->input->user_agent(), 0, 120)))
{
$this->sess_destroy();
return FALSE;
@@ -342,8 +451,19 @@ class CI_Session {
$this->CI->db->where('user_agent', $session['user_agent']);
}
+ // Is caching in effect? Turn it off
+ $db_cache = $this->CI->db->cache_on;
+ $this->CI->db->cache_off();
+
$query = $this->CI->db->limit(1)->get($this->sess_table_name);
+ // Was caching in effect?
+ if ($db_cache)
+ {
+ // Turn it back on
+ $this->CI->db->cache_on();
+ }
+
// No result? Kill it!
if ($query->num_rows() === 0)
{
@@ -351,7 +471,7 @@ class CI_Session {
return FALSE;
}
- // Is there custom data? If so, add it to the main session array
+ // Is there custom data? If so, add it to the main session array
$row = $query->row();
if ( ! empty($row->user_data))
{
@@ -359,424 +479,164 @@ class CI_Session {
if (is_array($custom_data))
{
- foreach ($custom_data as $key => $val)
- {
- $session[$key] = $val;
- }
+ $session = $session + $custom_data;
}
}
}
// Session is valid!
$this->userdata = $session;
- unset($session);
-
return TRUE;
}
- // --------------------------------------------------------------------
-
- /**
- * Write the session data
- *
- * @return void
- */
- public function sess_write()
- {
- // Are we saving custom data to the DB? If not, all we do is update the cookie
- if ($this->sess_use_database === FALSE)
- {
- $this->_set_cookie();
- return;
- }
-
- // set the custom userdata, the session data we will set in a second
- $custom_userdata = $this->userdata;
- $cookie_userdata = array();
-
- // Before continuing, we need to determine if there is any custom data to deal with.
- // Let's determine this by removing the default indexes to see if there's anything left in the array
- // and set the session data while we're at it
- foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
- {
- unset($custom_userdata[$val]);
- $cookie_userdata[$val] = $this->userdata[$val];
- }
-
- // Did we find any custom data? If not, we turn the empty array into a string
- // since there's no reason to serialize and store an empty array in the DB
- if (count($custom_userdata) === 0)
- {
- $custom_userdata = '';
- }
- else
- {
- // Serialize the custom data array so we can store it
- $custom_userdata = $this->_serialize($custom_userdata);
- }
-
- // Run the update query
- $this->CI->db->where('session_id', $this->userdata['session_id']);
- $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata));
-
- // Write the cookie. Notice that we manually pass the cookie data array to the
- // _set_cookie() function. Normally that function will store $this->userdata, but
- // in this case that array contains custom data, which we do not want in the cookie.
- $this->_set_cookie($cookie_userdata);
- }
-
- // --------------------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
* Create a new session
*
* @return void
*/
- public function sess_create()
+ protected function _sess_create()
{
- $sessid = '';
- do
- {
- $sessid .= mt_rand(0, mt_getrandmax());
- }
- while (strlen($sessid) < 32);
-
- // To make the session ID even more secure we'll combine it with the user's IP
- $sessid .= $this->CI->input->ip_address();
-
+ // Initialize userdata
$this->userdata = array(
- 'session_id' => md5(uniqid($sessid, TRUE)),
- 'ip_address' => $this->CI->input->ip_address(),
- 'user_agent' => substr($this->CI->input->user_agent(), 0, 120),
- 'last_activity' => $this->now,
- 'user_data' => ''
- );
-
- // Save the data to the DB if needed
+ 'session_id' => $this->_make_sess_id(),
+ 'ip_address' => $this->CI->input->ip_address(),
+ 'user_agent' => substr($this->CI->input->user_agent(), 0, 120),
+ 'last_activity' => $this->now,
+ );
+
+ // Check for database
if ($this->sess_use_database === TRUE)
{
- $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata));
+ // Add empty user_data field and save the data to the DB
+ $this->CI->db->set('user_data', '')->insert($this->sess_table_name, $this->userdata);
}
// Write the cookie
$this->_set_cookie();
}
- // --------------------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
* Update an existing session
*
+ * @param bool Force update flag (default: false)
* @return void
*/
- public function sess_update()
+ protected function _sess_update($force = FALSE)
{
- // We only update the session every five minutes by default
- if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
+ // We only update the session every five minutes by default (unless forced)
+ if ( ! $force && ($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
{
return;
}
- // _set_cookie() will handle this for us if we aren't using database sessions
- // by pushing all userdata to the cookie.
- $cookie_data = NULL;
-
- /* Changing the session ID during an AJAX call causes problems,
- * so we'll only update our last_activity
- */
- if ($this->CI->input->is_ajax_request())
- {
- $this->userdata['last_activity'] = $this->now;
-
- // Update the session ID and last_activity field in the DB if needed
- if ($this->sess_use_database === TRUE)
- {
- // set cookie explicitly to only have our session data
- $cookie_data = array();
- foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
- {
- $cookie_data[$val] = $this->userdata[$val];
- }
-
- $this->CI->db->query($this->CI->db->update_string($this->sess_table_name,
- array('last_activity' => $this->userdata['last_activity']),
- array('session_id' => $this->userdata['session_id'])));
- }
-
- return $this->_set_cookie($cookie_data);
- }
+ // Update last activity to now
+ $this->userdata['last_activity'] = $this->now;
- // Save the old session id so we know which record to
- // update in the database if we need it
+ // Save the old session id so we know which DB record to update
$old_sessid = $this->userdata['session_id'];
- $new_sessid = '';
- do
+
+ // Changing the session ID during an AJAX call causes problems
+ if ( ! $this->CI->input->is_ajax_request())
{
- $new_sessid .= mt_rand(0, mt_getrandmax());
+ // Get new id
+ $this->userdata['session_id'] = $this->_make_sess_id();
}
- while (strlen($new_sessid) < 32);
-
- // To make the session ID even more secure we'll combine it with the user's IP
- $new_sessid .= $this->CI->input->ip_address();
- // Turn it into a hash and update the session data array
- $this->userdata['session_id'] = $new_sessid = md5(uniqid($new_sessid, TRUE));
- $this->userdata['last_activity'] = $this->now;
-
- // Update the session ID and last_activity field in the DB if needed
+ // Check for database
if ($this->sess_use_database === TRUE)
{
- // set cookie explicitly to only have our session data
- $cookie_data = array();
- foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
- {
- $cookie_data[$val] = $this->userdata[$val];
- }
-
- $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid)));
+ // Update the session ID and last_activity field in the DB
+ $this->CI->db->update($this->sess_table_name, array(
+ 'last_activity' => $this->now,
+ 'session_id' => $this->userdata['session_id']
+ ), array('session_id' => $old_sessid));
}
// Write the cookie
- $this->_set_cookie($cookie_data);
+ $this->_set_cookie();
}
- // --------------------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
- * Destroy the current session
+ * Update database with current data
+ *
+ * This gets called from the shutdown function and also
+ * registered with PHP to run at the end of the request
+ * so it's guaranteed to update even when a fatal error
+ * occurs. The first call makes the update and clears the
+ * dirty flag so it won't happen twice.
*
* @return void
*/
- public function sess_destroy()
+ public function _update_db()
{
- // Kill the session DB row
- if ($this->sess_use_database === TRUE && isset($this->userdata['session_id']))
- {
- $this->CI->db->where('session_id', $this->userdata['session_id']);
- $this->CI->db->delete($this->sess_table_name);
- }
-
- // Kill the cookie
- setcookie(
- $this->sess_cookie_name,
- addslashes(serialize(array())),
- ($this->now - 31500000),
- $this->cookie_path,
- $this->cookie_domain,
- 0
+ // Check for database and dirty flag and unsaved
+ if ($this->sess_use_database === TRUE && $this->data_dirty === TRUE)
+ {
+ // Set up activity and data fields to be set
+ // If we don't find custom data, user_data will remain an empty string
+ $set = array(
+ 'last_activity' => $this->userdata['last_activity'],
+ 'user_data' => ''
);
- // Kill session data
- $this->userdata = array();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch a specific item from the session array
- *
- * @param string
- * @return string
- */
- public function userdata($item)
- {
- return isset($this->userdata[$item]) ? $this->userdata[$item] : NULL;
- }
+ // Get the custom userdata, leaving out the defaults
+ // (which get stored in the cookie)
+ $userdata = array_diff_key($this->userdata, $this->defaults);
- // --------------------------------------------------------------------
-
- /**
- * Fetch all session data
- *
- * @return array
- */
- public function all_userdata()
- {
- return $this->userdata;
- }
-
- // --------------------------------------------------------------------------
-
- /**
- * Fetch all flashdata
- *
- * @return array
- */
- public function all_flashdata()
- {
- $out = array();
-
- // loop through all userdata
- foreach ($this->all_userdata() as $key => $val)
- {
- // if it contains flashdata, add it
- if (strpos($key, 'flash:old:') !== FALSE)
+ // Did we find any custom data?
+ if ( ! empty($userdata))
{
- $out[$key] = $val;
+ // Serialize the custom data array so we can store it
+ $set['user_data'] = $this->_serialize($userdata);
}
- }
- return $out;
- }
- // --------------------------------------------------------------------
+ // Run the update query
+ // Any time we change the session id, it gets updated immediately,
+ // so our where clause below is always safe
+ $this->CI->db->update($this->sess_table_name, $set, array('session_id' => $this->userdata['session_id']));
- /**
- * Add or change data in the "userdata" array
- *
- * @param mixed
- * @param string
- * @return void
- */
- public function set_userdata($newdata = array(), $newval = '')
- {
- if (is_string($newdata))
- {
- $newdata = array($newdata => $newval);
- }
-
- if (count($newdata) > 0)
- {
- foreach ($newdata as $key => $val)
- {
- $this->userdata[$key] = $val;
- }
- }
-
- $this->sess_write();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Delete a session variable from the "userdata" array
- *
- * @param array
- * @return void
- */
- public function unset_userdata($newdata = array())
- {
- if (is_string($newdata))
- {
- $newdata = array($newdata => '');
- }
+ // Clear dirty flag to prevent double updates
+ $this->data_dirty = FALSE;
- if (count($newdata) > 0)
- {
- foreach ($newdata as $key => $val)
- {
- unset($this->userdata[$key]);
- }
+ log_message('debug', 'CI_Session Data Saved To DB');
}
-
- $this->sess_write();
}
// ------------------------------------------------------------------------
/**
- * Add or change flashdata, only available
- * until the next request
+ * Generate a new session id
*
- * @param mixed
- * @param string
- * @return void
+ * @return string Hashed session id
*/
- public function set_flashdata($newdata = array(), $newval = '')
+ protected function _make_sess_id()
{
- if (is_string($newdata))
- {
- $newdata = array($newdata => $newval);
- }
-
- if (count($newdata) > 0)
+ $new_sessid = '';
+ do
{
- foreach ($newdata as $key => $val)
- {
- $this->set_userdata($this->flashdata_key.':new:'.$key, $val);
- }
+ $new_sessid .= mt_rand(0, mt_getrandmax());
}
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Keeps existing flashdata available to next request.
- *
- * @param string
- * @return void
- */
- public function keep_flashdata($key)
- {
- // 'old' flashdata gets removed. Here we mark all
- // flashdata as 'new' to preserve it from _flashdata_sweep()
- // Note the function will return NULL if the $key
- // provided cannot be found
- $value = $this->userdata($this->flashdata_key.':old:'.$key);
-
- $this->set_userdata($this->flashdata_key.':new:'.$key, $value);
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Fetch a specific flashdata item from the session array
- *
- * @param string
- * @return string
- */
- public function flashdata($key)
- {
- return $this->userdata($this->flashdata_key.':old:'.$key);
- }
+ while (strlen($new_sessid) < 32);
- // ------------------------------------------------------------------------
+ // To make the session ID even more secure we'll combine it with the user's IP
+ $new_sessid .= $this->CI->input->ip_address();
- /**
- * Identifies flashdata as 'old' for removal
- * when _flashdata_sweep() runs.
- *
- * @return void
- */
- protected function _flashdata_mark()
- {
- $userdata = $this->all_userdata();
- foreach ($userdata as $name => $value)
- {
- $parts = explode(':new:', $name);
- if (is_array($parts) && count($parts) === 2)
- {
- $this->set_userdata($this->flashdata_key.':old:'.$parts[1], $value);
- $this->unset_userdata($name);
- }
- }
+ // Turn it into a hash and return
+ return md5(uniqid($new_sessid, TRUE));
}
// ------------------------------------------------------------------------
/**
- * Removes all flashdata marked as 'old'
- *
- * @return void
- */
- protected function _flashdata_sweep()
- {
- $userdata = $this->all_userdata();
- foreach ($userdata as $key => $value)
- {
- if (strpos($key, ':old:'))
- {
- $this->unset_userdata($key);
- }
- }
-
- }
-
- // --------------------------------------------------------------------
-
- /**
* Get the "now" time
*
- * @return string
+ * @return int Time
*/
protected function _get_time()
{
@@ -791,49 +651,57 @@ class CI_Session {
return mktime($hour, $minute, $second, $month, $day, $year);
}
- // --------------------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
* Write the session cookie
*
- * @param mixed
* @return void
*/
- protected function _set_cookie($cookie_data = NULL)
+ protected function _set_cookie()
{
- if (is_null($cookie_data))
- {
- $cookie_data = $this->userdata;
- }
+ // Get userdata (only defaults if database)
+ $cookie_data = ($this->sess_use_database === TRUE)
+ ? array_intersect_key($this->userdata, $this->defaults)
+ : $this->userdata;
// Serialize the userdata for the cookie
$cookie_data = $this->_serialize($cookie_data);
- if ($this->sess_encrypt_cookie === TRUE)
- {
- $cookie_data = $this->CI->encrypt->encode($cookie_data);
- }
- else
- {
+ $cookie_data = ($this->sess_encrypt_cookie === TRUE)
+ ? $this->CI->encrypt->encode($cookie_data)
// if encryption is not used, we provide an md5 hash to prevent userside tampering
- $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
- }
+ : $cookie_data.md5($cookie_data.$this->encryption_key);
$expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
// Set the cookie
- setcookie(
- $this->sess_cookie_name,
- $cookie_data,
- $expire,
- $this->cookie_path,
- $this->cookie_domain,
- $this->cookie_secure,
- $this->cookie_httponly
- );
+ $this->_setcookie($this->sess_cookie_name, $cookie_data, $expire, $this->cookie_path, $this->cookie_domain,
+ $this->cookie_secure, $this->cookie_httponly);
}
- // --------------------------------------------------------------------
+ // ------------------------------------------------------------------------
+
+ /**
+ * Set a cookie with the system
+ *
+ * This abstraction of the setcookie call allows overriding for unit testing
+ *
+ * @param string Cookie name
+ * @param string Cookie value
+ * @param int Expiration time
+ * @param string Cookie path
+ * @param string Cookie domain
+ * @param bool Secure connection flag
+ * @param bool HTTP protocol only flag
+ * @return void
+ */
+ protected function _setcookie($name, $value = '', $expire = 0, $path = '', $domain = '', $secure = FALSE, $httponly = FALSE)
+ {
+ setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
+ }
+
+ // ------------------------------------------------------------------------
/**
* Serialize an array
@@ -841,8 +709,8 @@ class CI_Session {
* This function first converts any slashes found in the array to a temporary
* marker, so when it gets unserialized the slashes will be preserved
*
- * @param array
- * @return string
+ * @param mixed Data to serialize
+ * @return string Serialized data
*/
protected function _serialize($data)
{
@@ -854,16 +722,19 @@ class CI_Session {
{
$data = str_replace('\\', '{{slash}}', $data);
}
+
return serialize($data);
}
+ // ------------------------------------------------------------------------
+
/**
* Escape slashes
*
* This function converts any slashes found into a temporary marker
*
- * @param string
- * @param string
+ * @param string Value
+ * @param string Key
* @return void
*/
protected function _escape_slashes(&$val, $key)
@@ -874,7 +745,7 @@ class CI_Session {
}
}
- // --------------------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
* Unserialize
@@ -882,8 +753,8 @@ class CI_Session {
* This function unserializes a data string, then converts any
* temporary slash markers back to actual slashes
*
- * @param array
- * @return string
+ * @param mixed Data to unserialize
+ * @return mixed Unserialized data
*/
protected function _unserialize($data)
{
@@ -898,15 +769,15 @@ class CI_Session {
return is_string($data) ? str_replace('{{slash}}', '\\', $data) : $data;
}
- // --------------------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
* Unescape slashes
*
* This function converts any slash markers back into actual slashes
*
- * @param string
- * @param string
+ * @param string Value
+ * @param string Key
* @return void
*/
protected function _unescape_slashes(&$val, $key)
@@ -917,7 +788,7 @@ class CI_Session {
}
}
- // --------------------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
* Garbage collection
@@ -941,9 +812,7 @@ class CI_Session {
if ((mt_rand(0, $divisor) / $divisor) < $probability)
{
$expire = $this->now - $this->sess_expiration;
-
- $this->CI->db->where('last_activity < '.$expire);
- $this->CI->db->delete($this->sess_table_name);
+ $this->CI->db->delete($this->sess_table_name, 'last_activity < '.$expire);
log_message('debug', 'Session garbage collection performed.');
}
@@ -951,5 +820,5 @@ class CI_Session {
}
-/* End of file Session.php */
-/* Location: ./system/libraries/Session.php */ \ No newline at end of file
+/* End of file Session_cookie.php */
+/* Location: ./system/libraries/Session/drivers/Session_cookie.php */ \ No newline at end of file
diff --git a/system/libraries/Session/drivers/Session_native.php b/system/libraries/Session/drivers/Session_native.php
new file mode 100755
index 000000000..c97e15356
--- /dev/null
+++ b/system/libraries/Session/drivers/Session_native.php
@@ -0,0 +1,232 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+/**
+ * Native PHP session management driver
+ *
+ * This is the driver that uses the native PHP $_SESSION array through the Session driver library.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author EllisLab Dev Team
+ */
+class CI_Session_native extends CI_Session_driver {
+
+ /**
+ * Initialize session driver object
+ *
+ * @return void
+ */
+ protected function initialize()
+ {
+ // Get config parameters
+ $config = array();
+ $CI =& get_instance();
+ $prefs = array(
+ 'sess_cookie_name',
+ 'sess_expire_on_close',
+ 'sess_expiration',
+ 'sess_match_ip',
+ 'sess_match_useragent',
+ 'sess_time_to_update',
+ 'cookie_prefix',
+ 'cookie_path',
+ 'cookie_domain'
+ );
+
+ foreach ($prefs as $key)
+ {
+ $config[$key] = isset($this->_parent->params[$key])
+ ? $this->_parent->params[$key]
+ : $CI->config->item($key);
+ }
+
+ // Set session name, if specified
+ if ($config['sess_cookie_name'])
+ {
+ // Differentiate name from cookie driver with '_id' suffix
+ $name = $config['sess_cookie_name'].'_id';
+ if ($config['cookie_prefix'])
+ {
+ // Prepend cookie prefix
+ $name = $config['cookie_prefix'].$name;
+ }
+ session_name($name);
+ }
+
+ // Set expiration, path, and domain
+ $expire = 7200;
+ $path = '/';
+ $domain = '';
+ if ($config['sess_expiration'] !== FALSE)
+ {
+ // Default to 2 years if expiration is "0"
+ $expire = ($config['sess_expiration'] == 0) ? (60*60*24*365*2) : $config['sess_expiration'];
+ }
+
+ if ($config['cookie_path'])
+ {
+ // Use specified path
+ $path = $config['cookie_path'];
+ }
+
+ if ($config['cookie_domain'])
+ {
+ // Use specified domain
+ $domain = $config['cookie_domain'];
+ }
+ session_set_cookie_params($config['sess_expire_on_close'] ? 0 : $expire, $path, $domain);
+
+ // Start session
+ session_start();
+
+ // Check session expiration, ip, and agent
+ $now = time();
+ $destroy = FALSE;
+ if (isset($_SESSION['last_activity']) && ($_SESSION['last_activity'] + $expire) < $now)
+ {
+ // Expired - destroy
+ $destroy = TRUE;
+ }
+ elseif ($config['sess_match_ip'] === TRUE && isset($_SESSION['ip_address'])
+ && $_SESSION['ip_address'] !== $CI->input->ip_address())
+ {
+ // IP doesn't match - destroy
+ $destroy = TRUE;
+ }
+ elseif ($config['sess_match_useragent'] === TRUE && isset($_SESSION['user_agent'])
+ && $_SESSION['user_agent'] !== trim(substr($CI->input->user_agent(), 0, 50)))
+ {
+ // Agent doesn't match - destroy
+ $destroy = TRUE;
+ }
+
+ // Destroy expired or invalid session
+ if ($destroy)
+ {
+ // Clear old session and start new
+ $this->sess_destroy();
+ session_start();
+ }
+
+ // Check for update time
+ if ($config['sess_time_to_update'] && isset($_SESSION['last_activity'])
+ && ($_SESSION['last_activity'] + $config['sess_time_to_update']) < $now)
+ {
+ // Regenerate ID, but don't destroy session
+ $this->sess_regenerate(FALSE);
+ }
+
+ // Set activity time
+ $_SESSION['last_activity'] = $now;
+
+ // Set matching values as required
+ if ($config['sess_match_ip'] === TRUE && ! isset($_SESSION['ip_address']))
+ {
+ // Store user IP address
+ $_SESSION['ip_address'] = $CI->input->ip_address();
+ }
+
+ if ($config['sess_match_useragent'] === TRUE && ! isset($_SESSION['user_agent']))
+ {
+ // Store user agent string
+ $_SESSION['user_agent'] = trim(substr($CI->input->user_agent(), 0, 50));
+ }
+
+ // Make session ID available
+ $_SESSION['session_id'] = session_id();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Save the session data
+ *
+ * @return void
+ */
+ public function sess_save()
+ {
+ // Nothing to do - changes to $_SESSION are automatically saved
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Destroy the current session
+ *
+ * @return void
+ */
+ public function sess_destroy()
+ {
+ // Cleanup session
+ $_SESSION = array();
+ $name = session_name();
+ if (isset($_COOKIE[$name]))
+ {
+ // Clear session cookie
+ $params = session_get_cookie_params();
+ setcookie($name, '', time() - 42000, $params['path'], $params['domain']);
+ unset($_COOKIE[$name]);
+ }
+ session_destroy();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Regenerate the current session
+ *
+ * Regenerate the session id
+ *
+ * @param bool Destroy session data flag (default: FALSE)
+ * @return void
+ */
+ public function sess_regenerate($destroy = FALSE)
+ {
+ // Just regenerate id, passing destroy flag
+ session_regenerate_id($destroy);
+ $_SESSION['session_id'] = session_id();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get a reference to user data array
+ *
+ * @return array Reference to userdata
+ */
+ public function &get_userdata()
+ {
+ // Just return reference to $_SESSION
+ return $_SESSION;
+ }
+
+}
+
+/* End of file Session_native.php */
+/* Location: ./system/libraries/Session/drivers/Session_native.php */ \ No newline at end of file
diff --git a/system/libraries/Unit_test.php b/system/libraries/Unit_test.php
index 70ad8dc41..c2c01758e 100644
--- a/system/libraries/Unit_test.php
+++ b/system/libraries/Unit_test.php
@@ -240,6 +240,11 @@ class CI_Unit_test {
{
foreach ($val as $k => $v)
{
+ if ( ! in_array($k, $this->_test_items_visible))
+ {
+ continue;
+ }
+
if (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$v))))
{
$v = $line;
diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php
index cbb91c40a..dc5d27f8c 100644..100755
--- a/system/libraries/Xmlrpc.php
+++ b/system/libraries/Xmlrpc.php
@@ -1317,15 +1317,15 @@ class XML_RPC_Values extends CI_Xmlrpc
{
$type = $type === '' ? 'string' : $type;
- if ($this->xmlrpcTypes[$type] === 1)
+ if ($this->xmlrpcTypes[$type] == 1)
{
$this->addScalar($val,$type);
}
- elseif ($this->xmlrpcTypes[$type] === 2)
+ elseif ($this->xmlrpcTypes[$type] == 2)
{
$this->addArray($val);
}
- elseif ($this->xmlrpcTypes[$type] === 3)
+ elseif ($this->xmlrpcTypes[$type] == 3)
{
$this->addStruct($val);
}
@@ -1351,7 +1351,7 @@ class XML_RPC_Values extends CI_Xmlrpc
return 0;
}
- if ($typeof !== 1)
+ if ($typeof != 1)
{
echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
return 0;
@@ -1359,7 +1359,7 @@ class XML_RPC_Values extends CI_Xmlrpc
if ($type === $this->xmlrpcBoolean)
{
- $val = (int) (strcasecmp($val,'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
+ $val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
}
if ($this->mytype === 2)