summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--application/config/database.php2
-rw-r--r--index.php2
-rw-r--r--readme.rst4
-rw-r--r--system/core/Common.php3
-rwxr-xr-xsystem/core/Input.php67
-rwxr-xr-xsystem/database/DB.php1
-rw-r--r--system/database/DB_driver.php27
-rw-r--r--system/database/drivers/pdo/pdo_driver.php272
-rw-r--r--system/database/drivers/pdo/pdo_forge.php12
-rw-r--r--system/database/drivers/pdo/pdo_result.php67
-rw-r--r--system/libraries/Session.php133
-rw-r--r--user_guide_src/source/changelog.rst4
-rw-r--r--user_guide_src/source/database/configuration.rst4
13 files changed, 410 insertions, 188 deletions
diff --git a/application/config/database.php b/application/config/database.php
index 7eac59b23..bd68db1d8 100644
--- a/application/config/database.php
+++ b/application/config/database.php
@@ -37,6 +37,7 @@
| EXPLANATION OF VARIABLES
| -------------------------------------------------------------------
|
+| ['dsn'] The full DSN string describe a connection to the database.
| ['hostname'] The hostname of your database server.
| ['username'] The username used to connect to the database
| ['password'] The password used to connect to the database
@@ -74,6 +75,7 @@
$active_group = 'default';
$active_record = TRUE;
+$db['default']['dsn'] = '';
$db['default']['hostname'] = 'localhost';
$db['default']['username'] = '';
$db['default']['password'] = '';
diff --git a/index.php b/index.php
index 1712a7d66..a37826690 100644
--- a/index.php
+++ b/index.php
@@ -218,6 +218,7 @@ if (defined('ENVIRONMENT'))
{
if ( ! is_dir(BASEPATH.$application_folder.'/'))
{
+ header('HTTP/1.1 503 Service Unavailable.', TRUE, '503');
exit('Your application folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF);
}
@@ -233,6 +234,7 @@ if (defined('ENVIRONMENT'))
{
if ( ! is_dir(APPPATH.'views/'))
{
+ header('HTTP/1.1 503 Service Unavailable.', TRUE, '503');
exit('Your view folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF);
}
diff --git a/readme.rst b/readme.rst
index 26e04ceac..2369a8ddb 100644
--- a/readme.rst
+++ b/readme.rst
@@ -23,7 +23,7 @@ Changelog and New Features
**************************
You can find a list of all changes for each release in the `user
-guide change log <https://github.com/EllisLab/CodeIgniter/blob/develop/user_guide/changelog.html>`_.
+guide change log <https://github.com/EllisLab/CodeIgniter/blob/develop/user_guide_src/source/changelog.rst>`_.
*******************
Server Requirements
@@ -193,4 +193,4 @@ Acknowledgement
***************
The EllisLab team and The Reactor Engineers would like to thank all the
-contributors to the CodeIgniter project and you, the CodeIgniter user. \ No newline at end of file
+contributors to the CodeIgniter project and you, the CodeIgniter user.
diff --git a/system/core/Common.php b/system/core/Common.php
index 2f9c4ff43..225227d17 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -177,6 +177,7 @@ if ( ! function_exists('load_class'))
{
// Note: We use exit() rather then show_error() in order to avoid a
// self-referencing loop with the Excptions class
+ set_status_header(503);
exit('Unable to locate the specified class: '.$class.'.php');
}
@@ -243,6 +244,7 @@ if ( ! function_exists('get_config'))
// Fetch the config file
if ( ! file_exists($file_path))
{
+ set_status_header(503);
exit('The configuration file does not exist.');
}
@@ -251,6 +253,7 @@ if ( ! function_exists('get_config'))
// Does the $config array exist in the file?
if ( ! isset($config) OR ! is_array($config))
{
+ set_status_header(503);
exit('Your config file does not appear to be formatted correctly.');
}
diff --git a/system/core/Input.php b/system/core/Input.php
index 7a16e51ab..ee15f4013 100755
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -25,8 +25,6 @@
* @filesource
*/
-// ------------------------------------------------------------------------
-
/**
* Input Class
*
@@ -152,7 +150,7 @@ class CI_Input {
public function get($index = NULL, $xss_clean = FALSE)
{
// Check if a field has been provided
- if ($index === NULL AND ! empty($_GET))
+ if ($index === NULL && ! empty($_GET))
{
$get = array();
@@ -179,7 +177,7 @@ class CI_Input {
public function post($index = NULL, $xss_clean = FALSE)
{
// Check if a field has been provided
- if ($index === NULL AND ! empty($_POST))
+ if ($index === NULL && ! empty($_POST))
{
$post = array();
@@ -206,9 +204,9 @@ class CI_Input {
*/
public function get_post($index = '', $xss_clean = FALSE)
{
- return ( ! isset($_POST[$index]))
- ? $this->get($index, $xss_clean)
- : $this->post($index, $xss_clean);
+ return isset($_POST[$index])
+ ? $this->post($index, $xss_clean)
+ : $this->get($index, $xss_clean);
}
// --------------------------------------------------------------------
@@ -256,19 +254,19 @@ class CI_Input {
}
}
- if ($prefix == '' AND config_item('cookie_prefix') != '')
+ if ($prefix == '' && config_item('cookie_prefix') != '')
{
$prefix = config_item('cookie_prefix');
}
- if ($domain == '' AND config_item('cookie_domain') != '')
+ if ($domain == '' && config_item('cookie_domain') != '')
{
$domain = config_item('cookie_domain');
}
- if ($path == '/' AND config_item('cookie_path') != '/')
+ if ($path == '/' && config_item('cookie_path') !== '/')
{
$path = config_item('cookie_path');
}
- if ($secure == FALSE AND config_item('cookie_secure') != FALSE)
+ if ($secure == FALSE && config_item('cookie_secure') != FALSE)
{
$secure = config_item('cookie_secure');
}
@@ -320,11 +318,11 @@ class CI_Input {
$this->ip_address = in_array($_SERVER['REMOTE_ADDR'], $proxies) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
}
- elseif ( ! $this->server('HTTP_CLIENT_IP') AND $this->server('REMOTE_ADDR'))
+ elseif ( ! $this->server('HTTP_CLIENT_IP') && $this->server('REMOTE_ADDR'))
{
$this->ip_address = $_SERVER['REMOTE_ADDR'];
}
- elseif ($this->server('REMOTE_ADDR') AND $this->server('HTTP_CLIENT_IP'))
+ elseif ($this->server('REMOTE_ADDR') && $this->server('HTTP_CLIENT_IP'))
{
$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
}
@@ -414,7 +412,7 @@ class CI_Input {
return $this->user_agent;
}
- return $this->user_agent = ( ! isset($_SERVER['HTTP_USER_AGENT'])) ? FALSE : $_SERVER['HTTP_USER_AGENT'];
+ return $this->user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : FALSE;
}
// --------------------------------------------------------------------
@@ -469,19 +467,16 @@ class CI_Input {
{
$_GET = array();
}
- else
+ elseif (is_array($_GET) && count($_GET) > 0)
{
- if (is_array($_GET) AND count($_GET) > 0)
+ foreach ($_GET as $key => $val)
{
- foreach ($_GET as $key => $val)
- {
- $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
- }
+ $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
}
}
// Clean $_POST Data
- if (is_array($_POST) AND count($_POST) > 0)
+ if (is_array($_POST) && count($_POST) > 0)
{
foreach ($_POST as $key => $val)
{
@@ -490,7 +485,7 @@ class CI_Input {
}
// Clean $_COOKIE Data
- if (is_array($_COOKIE) AND count($_COOKIE) > 0)
+ if (is_array($_COOKIE) && count($_COOKIE) > 0)
{
// Also get rid of specially treated cookies that might be set by a server
// or silly application, that are of no use to a CI application anyway
@@ -568,7 +563,7 @@ class CI_Input {
}
// Standardize newlines if needed
- if ($this->_standardize_newlines == TRUE AND strpos($str, "\r") !== FALSE)
+ if ($this->_standardize_newlines == TRUE && strpos($str, "\r") !== FALSE)
{
return str_replace(array("\r\n", "\r", "\r\n\n"), PHP_EOL, $str);
}
@@ -592,6 +587,7 @@ class CI_Input {
{
if ( ! preg_match('/^[a-z0-9:_\/-]+$/i', $str))
{
+ set_status_header(503);
exit('Disallowed Key Characters.');
}
@@ -624,7 +620,7 @@ class CI_Input {
}
else
{
- $headers['Content-Type'] = (isset($_SERVER['CONTENT_TYPE'])) ? $_SERVER['CONTENT_TYPE'] : @getenv('CONTENT_TYPE');
+ $headers['Content-Type'] = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : @getenv('CONTENT_TYPE');
foreach ($_SERVER as $key => $val)
{
@@ -654,9 +650,9 @@ class CI_Input {
*
* Returns the value of a single member of the headers class member
*
- * @param string array key for $this->headers
- * @param boolean XSS Clean or not
- * @return mixed FALSE on failure, string on success
+ * @param string array key for $this->headers
+ * @param bool XSS Clean or not
+ * @return mixed FALSE on failure, string on success
*/
public function get_request_header($index, $xss_clean = FALSE)
{
@@ -670,12 +666,9 @@ class CI_Input {
return FALSE;
}
- if ($xss_clean === TRUE)
- {
- return $this->security->xss_clean($this->headers[$index]);
- }
-
- return $this->headers[$index];
+ return ($xss_clean === TRUE)
+ ? $this->security->xss_clean($this->headers[$index])
+ : $this->headers[$index];
}
// --------------------------------------------------------------------
@@ -685,11 +678,11 @@ class CI_Input {
*
* Test to see if a request contains the HTTP_X_REQUESTED_WITH header
*
- * @return boolean
+ * @return bool
*/
public function is_ajax_request()
{
- return ($this->server('HTTP_X_REQUESTED_WITH') === 'XMLHttpRequest');
+ return ( ! empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
}
// --------------------------------------------------------------------
@@ -699,11 +692,11 @@ class CI_Input {
*
* Test to see if a request was made from the command line
*
- * @return boolean
+ * @return bool
*/
public function is_cli_request()
{
- return (php_sapi_name() === 'cli') or defined('STDIN');
+ return (php_sapi_name() === 'cli' OR defined('STDIN'));
}
}
diff --git a/system/database/DB.php b/system/database/DB.php
index ed6afd7ed..d06ffb40e 100755
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -82,6 +82,7 @@ function &DB($params = '', $active_record_override = NULL)
$params = array(
'dbdriver' => $dns['scheme'],
'hostname' => (isset($dns['host'])) ? rawurldecode($dns['host']) : '',
+ 'port' => (isset($dns['port'])) ? rawurldecode($dns['port']) : '',
'username' => (isset($dns['user'])) ? rawurldecode($dns['user']) : '',
'password' => (isset($dns['pass'])) ? rawurldecode($dns['pass']) : '',
'database' => (isset($dns['path'])) ? rawurldecode(substr($dns['path'], 1)) : ''
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 566779d0e..9c9fdac85 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -81,8 +81,7 @@ class CI_DB_driver {
var $stmt_id;
var $curs_id;
var $limit_used;
-
-
+
/**
* Constructor. Accepts one parameter containing the database
@@ -814,20 +813,23 @@ class CI_DB_driver {
if ($query->num_rows() > 0)
{
- foreach ($query->result_array() as $row)
+ $table = FALSE;
+ $rows = $query->result_array();
+ $key = (($row = current($rows)) && in_array('table_name', array_map('strtolower', array_keys($row))));
+
+ if ($key)
{
- if (isset($row['TABLE_NAME']))
- {
- $retval[] = $row['TABLE_NAME'];
- }
- else
- {
- $retval[] = array_shift($row);
- }
+ $table = array_key_exists('TABLE_NAME', $row) ? 'TABLE_NAME' : 'table_name';
+ }
+
+ foreach ($rows as $row)
+ {
+ $retval[] = ( ! $table) ? current($row) : $row[$table];
}
}
$this->data_cache['table_names'] = $retval;
+
return $this->data_cache['table_names'];
}
@@ -1436,10 +1438,7 @@ class CI_DB_driver {
return $item.$alias;
}
-
-
}
-
/* End of file DB_driver.php */
/* Location: ./system/database/DB_driver.php */
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index 4f4f44ba7..fc378daeb 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -46,9 +46,10 @@ class CI_DB_pdo_driver extends CI_DB {
// the character used to excape - not necessary for PDO
var $_escape_char = '';
+
+ // clause and character used for LIKE escape sequences
var $_like_escape_str;
var $_like_escape_chr;
-
/**
* The syntax to count rows is slightly different across different
@@ -57,29 +58,36 @@ class CI_DB_pdo_driver extends CI_DB {
*/
var $_count_string = "SELECT COUNT(*) AS ";
var $_random_keyword;
-
+
+ // need to track the pdo DSN, driver and options
+ var $dsn;
+ var $pdodriver;
var $options = array();
function __construct($params)
{
parent::__construct($params);
-
+
+ if (preg_match('/([^;]+):/', $this->dsn, $match) && count($match) == 2)
+ {
+ // If there is a minimum valid dsn string pattern found, we're done
+ // This is for general PDO users, who tend to have a full DSN string.
+ $this->pdodriver = end($match);
+ }
+ else
+ {
+ // Try to build a complete DSN string from params
+ $this->_connect_string($params);
+ }
+
// clause and character used for LIKE escape sequences
- if (strpos($this->hostname, 'mysql') !== FALSE)
+ // this one depends on the driver being used
+ if ($this->pdodriver == 'mysql')
{
$this->_like_escape_str = '';
$this->_like_escape_chr = '';
-
- //Prior to this version, the charset can't be set in the dsn
- if(is_php('5.3.6'))
- {
- $this->hostname .= ";charset={$this->char_set}";
- }
-
- //Set the charset with the connection options
- $this->options['PDO::MYSQL_ATTR_INIT_COMMAND'] = "SET NAMES {$this->char_set}";
}
- else if (strpos($this->hostname, 'odbc') !== FALSE)
+ elseif ($this->pdodriver == 'odbc')
{
$this->_like_escape_str = " {escape '%s'} ";
$this->_like_escape_chr = '!';
@@ -90,14 +98,85 @@ class CI_DB_pdo_driver extends CI_DB {
$this->_like_escape_chr = '!';
}
- if (strpos($this->hostname, 'sqlite') === FALSE)
+ $this->trans_enabled = FALSE;
+ $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
+ }
+
+ /**
+ * Connection String
+ *
+ * @access private
+ * @param array
+ * @return void
+ */
+ function _connect_string($params)
+ {
+ if (strpos($this->hostname, ':'))
{
- $this->hostname .= ";dbname=".$this->database;
+ // hostname generally would have this prototype
+ // $db['hostname'] = 'pdodriver:host(/Server(/DSN))=hostname(/DSN);';
+ // We need to get the prefix (pdodriver used by PDO).
+ $this->dsn = $this->hostname;
+ $this->pdodriver = substr($this->hostname, 0, strpos($this->hostname, ':'));
}
-
- $this->trans_enabled = FALSE;
+ else
+ {
+ // Invalid DSN, display an error
+ if ( ! array_key_exists('pdodriver', $params))
+ {
+ show_error('Invalid DB Connection String for PDO');
+ }
- $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
+ // Assuming that the following DSN string format is used:
+ // $dsn = 'pdo://username:password@hostname:port/database?pdodriver=pgsql';
+ $this->dsn = $this->pdodriver.':';
+
+ // Add hostname to the DSN for databases that need it
+ if ( ! empty($this->hostname) && in_array($this->pdodriver, array('informix', 'mysql', 'pgsql', 'sybase', 'mssql', 'dblib', 'cubrid')))
+ {
+ $this->dsn .= 'host='.$this->hostname.';';
+ }
+
+ // Add a port to the DSN for databases that can use it
+ if ( ! empty($this->port) && in_array($this->pdodriver, array('informix', 'mysql', 'pgsql', 'ibm', 'cubrid')))
+ {
+ $this->dsn .= 'port='.$this->port.';';
+ }
+ }
+
+ // Add the database name to the DSN, if needed
+ if (stripos($this->dsn, 'dbname') === FALSE
+ && in_array($this->pdodriver, array('4D', 'pgsql', 'mysql', 'firebird', 'sybase', 'mssql', 'dblib', 'cubrid')))
+ {
+ $this->dsn .= 'dbname='.$this->database.';';
+ }
+ elseif (stripos($this->dsn, 'database') === FALSE && in_array($this->pdodriver, array('ibm', 'sqlsrv')))
+ {
+ if (stripos($this->dsn, 'dsn') === FALSE)
+ {
+ $this->dsn .= 'database='.$this->database.';';
+ }
+ }
+ elseif ($this->pdodriver === 'sqlite' && $this->dsn === 'sqlite:')
+ {
+ if ($this->database !== ':memory')
+ {
+ if ( ! file_exists($this->database))
+ {
+ show_error('Invalid DB Connection string for PDO SQLite');
+ }
+
+ $this->dsn .= (strpos($this->database, DIRECTORY_SEPARATOR) !== 0) ? DIRECTORY_SEPARATOR : '';
+ }
+
+ $this->dsn .= $this->database;
+ }
+
+ // Add charset to the DSN, if needed
+ if ( ! empty($this->char_set) && in_array($this->pdodriver, array('4D', 'mysql', 'sybase', 'mssql', 'dblib', 'oci')))
+ {
+ $this->dsn .= 'charset='.$this->char_set.';';
+ }
}
/**
@@ -108,9 +187,9 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function db_connect()
{
- $this->options['PDO::ATTR_ERRMODE'] = PDO::ERRMODE_SILENT;
-
- return new PDO($this->hostname, $this->username, $this->password, $this->options);
+ $this->options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_SILENT;
+
+ return $this->pdo_connect();
}
// --------------------------------------------------------------------
@@ -123,10 +202,44 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function db_pconnect()
{
- $this->options['PDO::ATTR_ERRMODE'] = PDO::ERRMODE_SILENT;
- $this->options['PDO::ATTR_PERSISTENT'] = TRUE;
+ $this->options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_SILENT;
+ $this->options[PDO::ATTR_PERSISTENT] = TRUE;
- return new PDO($this->hostname, $this->username, $this->password, $this->options);
+ return $this->pdo_connect();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * PDO connection
+ *
+ * @access private called by the PDO driver class
+ * @return resource
+ */
+ function pdo_connect()
+ {
+ // Refer : http://php.net/manual/en/ref.pdo-mysql.connection.php
+ if ($this->pdodriver == 'mysql' && is_php('5.3.6'))
+ {
+ $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = "SET NAMES $this->char_set COLLATE '$this->dbcollat'";
+ }
+
+ // Connecting...
+ try
+ {
+ $db = new PDO($this->dsn, $this->username, $this->password, $this->options);
+ }
+ catch (PDOException $e)
+ {
+ if ($this->db_debug && empty($this->failover))
+ {
+ $this->display_error($e->getMessage(), '', TRUE);
+ }
+
+ return FALSE;
+ }
+
+ return $db;
}
// --------------------------------------------------------------------
@@ -146,6 +259,7 @@ class CI_DB_pdo_driver extends CI_DB {
{
return $this->db->display_error('db_unsuported_feature');
}
+
return FALSE;
}
@@ -175,7 +289,6 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function db_set_charset($charset, $collation)
{
- // @todo - add support if needed
return TRUE;
}
@@ -204,6 +317,7 @@ class CI_DB_pdo_driver extends CI_DB {
function _execute($sql)
{
$sql = $this->_prep_query($sql);
+
$result_id = $this->conn_id->query($sql);
if (is_object($result_id))
@@ -231,6 +345,17 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function _prep_query($sql)
{
+ if ($this->pdodriver === 'pgsql')
+ {
+ // Change the backtick(s) for Postgre
+ $sql = str_replace('`', '"', $sql);
+ }
+ elseif ($this->pdodriver === 'sqlite')
+ {
+ // Change the backtick(s) for SQLite
+ $sql = str_replace('`', '', $sql);
+ }
+
return $sql;
}
@@ -285,6 +410,7 @@ class CI_DB_pdo_driver extends CI_DB {
}
$ret = $this->conn->commit();
+
return $ret;
}
@@ -310,6 +436,7 @@ class CI_DB_pdo_driver extends CI_DB {
}
$ret = $this->conn_id->rollBack();
+
return $ret;
}
@@ -348,7 +475,9 @@ class CI_DB_pdo_driver extends CI_DB {
if ($like === TRUE)
{
$str = str_replace( array('%', '_', $this->_like_escape_chr),
- array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
+ array($this->_like_escape_chr.'%',
+ $this->_like_escape_chr.'_',
+ $this->_like_escape_chr.$this->_like_escape_chr),
$str);
}
@@ -378,9 +507,9 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function insert_id($name=NULL)
{
- //Convenience method for postgres insertid
- if (strpos($this->hostname, 'pgsql') !== FALSE)
+ if ($this->pdodriver == 'pgsql')
{
+ //Convenience method for postgres insertid
$v = $this->_version();
$table = func_num_args() > 0 ? func_get_arg(0) : NULL;
@@ -389,8 +518,10 @@ class CI_DB_pdo_driver extends CI_DB {
{
$sql='SELECT LASTVAL() as ins_id';
}
+
$query = $this->query($sql);
- $row = $query->row();
+ $row = $query->row();
+
return $row->ins_id;
}
else
@@ -418,7 +549,9 @@ class CI_DB_pdo_driver extends CI_DB {
return 0;
}
- $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
+ $sql = $this->_count_string.$this->_protect_identifiers('numrows').' FROM ';
+ $sql .= $this->_protect_identifiers($table, TRUE, NULL, FALSE);
+ $query = $this->query($sql);
if ($query->num_rows() == 0)
{
@@ -427,6 +560,7 @@ class CI_DB_pdo_driver extends CI_DB {
$row = $query->row();
$this->_reset_select();
+
return (int) $row->numrows;
}
@@ -443,12 +577,19 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function _list_tables($prefix_limit = FALSE)
{
- $sql = "SHOW TABLES FROM `".$this->database."`";
+ if ($this->pdodriver == 'pgsql')
+ {
+ // Analog function to show all tables in postgre
+ $sql = "SELECT * FROM information_schema.tables WHERE table_schema = 'public'";
+ }
+ else
+ {
+ $sql = "SHOW TABLES FROM `".$this->database."`";
+ }
if ($prefix_limit !== FALSE AND $this->dbprefix != '')
{
- //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
- return FALSE; // not currently supported
+ return FALSE;
}
return $sql;
@@ -467,7 +608,7 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function _list_columns($table = '')
{
- return "SHOW COLUMNS FROM ".$table;
+ return 'SHOW COLUMNS FROM '.$this->_from_tables($table);
}
// --------------------------------------------------------------------
@@ -483,7 +624,7 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function _field_data($table)
{
- return "SELECT TOP 1 FROM ".$table;
+ return 'SELECT TOP 1 FROM '.$this->_from_tables($table);
}
// --------------------------------------------------------------------
@@ -497,6 +638,7 @@ class CI_DB_pdo_driver extends CI_DB {
function _error_message()
{
$error_array = $this->conn_id->errorInfo();
+
return $error_array[2];
}
@@ -544,8 +686,8 @@ class CI_DB_pdo_driver extends CI_DB {
if (strpos($item, '.') !== FALSE)
{
- $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
-
+ $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
+ $str .= $this->_escape_char;
}
else
{
@@ -575,7 +717,7 @@ class CI_DB_pdo_driver extends CI_DB {
$tables = array($tables);
}
- return (count($tables) == 1) ? $tables[0] : '('.implode(', ', $tables).')';
+ return (count($tables) == 1) ? '`'.$tables[0].'`' : '('.implode(', ', $tables).')';
}
// --------------------------------------------------------------------
@@ -593,7 +735,7 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function _insert($table, $keys, $values)
{
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ return 'INSERT INTO '.$this->_from_tables($table).' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
}
// --------------------------------------------------------------------
@@ -611,7 +753,7 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function _insert_batch($table, $keys, $values)
{
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values);
+ return 'INSERT INTO '.$this->_from_tables($table).' ('.implode(', ', $keys).') VALUES '.implode(', ', $values);
}
// --------------------------------------------------------------------
@@ -636,14 +778,11 @@ class CI_DB_pdo_driver extends CI_DB {
$valstr[] = $key." = ".$val;
}
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
- $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
- $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
+ $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
+ $orderby = (count($orderby) >= 1) ? ' ORDER BY '.implode(', ', $orderby) : '';
+ $sql = 'UPDATE '.$this->_from_tables($table).' SET '.implode(', ', $valstr);
+ $sql .= ($where != '' && count($where) >= 1) ? ' WHERE '.implode(' ', $where) : '';
$sql .= $orderby.$limit;
return $sql;
@@ -664,8 +803,8 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function _update_batch($table, $values, $index, $where = NULL)
{
- $ids = array();
- $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
+ $ids = array();
+ $where = ($where != '' && count($where) >=1) ? implode(" ", $where).' AND ' : '';
foreach ($values as $key => $val)
{
@@ -680,12 +819,13 @@ class CI_DB_pdo_driver extends CI_DB {
}
}
- $sql = "UPDATE ".$table." SET ";
+ $sql = 'UPDATE '.$this->_from_tables($table).' SET ';
$cases = '';
foreach ($final as $k => $v)
{
$cases .= $k.' = CASE '."\n";
+
foreach ($v as $row)
{
$cases .= $row."\n";
@@ -695,7 +835,6 @@ class CI_DB_pdo_driver extends CI_DB {
}
$sql .= substr($cases, 0, -2);
-
$sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
return $sql;
@@ -739,19 +878,20 @@ class CI_DB_pdo_driver extends CI_DB {
if (count($where) > 0 OR count($like) > 0)
{
- $conditions = "\nWHERE ";
+ $conditions = "\nWHERE ";
$conditions .= implode("\n", $this->ar_where);
if (count($where) > 0 && count($like) > 0)
{
$conditions .= " AND ";
}
+
$conditions .= implode("\n", $like);
}
$limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
- return "DELETE FROM ".$table.$conditions.$limit;
+ return 'DELETE FROM '.$this->_from_tables($table).$conditions.$limit;
}
// --------------------------------------------------------------------
@@ -769,27 +909,16 @@ class CI_DB_pdo_driver extends CI_DB {
*/
function _limit($sql, $limit, $offset)
{
- if (strpos($this->hostname, 'cubrid') !== FALSE || strpos($this->hostname, 'sqlite') !== FALSE)
+ if ($this->pdodriver == 'cubrid' OR $this->pdodriver == 'sqlite')
{
- if ($offset == 0)
- {
- $offset = '';
- }
- else
- {
- $offset .= ", ";
- }
+ $offset = ($offset == 0) ? '' : $offset.', ';
- return $sql."LIMIT ".$offset.$limit;
+ return $sql.'LIMIT '.$offset.$limit;
}
else
{
- $sql .= "LIMIT ".$limit;
-
- if ($offset > 0)
- {
- $sql .= " OFFSET ".$offset;
- }
+ $sql .= 'LIMIT '.$limit;
+ $sql .= ($offset > 0) ? ' OFFSET '.$offset : '';
return $sql;
}
@@ -809,10 +938,7 @@ class CI_DB_pdo_driver extends CI_DB {
$this->conn_id = null;
}
-
}
-
-
/* End of file pdo_driver.php */
/* Location: ./system/database/drivers/pdo/pdo_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/pdo_forge.php b/system/database/drivers/pdo/pdo_forge.php
index 076415928..478b2dbfb 100644
--- a/system/database/drivers/pdo/pdo_forge.php
+++ b/system/database/drivers/pdo/pdo_forge.php
@@ -96,7 +96,7 @@ class CI_DB_pdo_forge extends CI_DB_forge {
$sql .= 'IF NOT EXISTS ';
}
- $sql .= $this->db->_escape_identifiers($table)." (";
+ $sql .= '`'.$this->db->_escape_identifiers($table).'` (';
$current_field_count = 0;
foreach ($fields as $field=>$attributes)
@@ -111,6 +111,7 @@ class CI_DB_pdo_forge extends CI_DB_forge {
else
{
$attributes = array_change_key_case($attributes, CASE_UPPER);
+ $numeric = array('SERIAL', 'INTEGER');
$sql .= "\n\t".$this->db->_protect_identifiers($field);
@@ -118,7 +119,11 @@ class CI_DB_pdo_forge extends CI_DB_forge {
if (array_key_exists('CONSTRAINT', $attributes))
{
- $sql .= '('.$attributes['CONSTRAINT'].')';
+ // Exception for Postgre numeric which not too happy with constraint within those type
+ if ( ! ($this->db->pdodriver == 'pgsql' && in_array($attributes['TYPE'], $numeric)))
+ {
+ $sql .= '('.$attributes['CONSTRAINT'].')';
+ }
}
if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
@@ -219,7 +224,7 @@ class CI_DB_pdo_forge extends CI_DB_forge {
*/
function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
{
- $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name);
+ $sql = 'ALTER TABLE `'.$this->db->_protect_identifiers($table)."` $alter_type ".$this->db->_protect_identifiers($column_name);
// DROP has everything it needs now.
if ($alter_type == 'DROP')
@@ -271,7 +276,6 @@ class CI_DB_pdo_forge extends CI_DB_forge {
return $sql;
}
-
}
/* End of file pdo_forge.php */
diff --git a/system/database/drivers/pdo/pdo_result.php b/system/database/drivers/pdo/pdo_result.php
index 6b523b001..c333abc40 100644
--- a/system/database/drivers/pdo/pdo_result.php
+++ b/system/database/drivers/pdo/pdo_result.php
@@ -39,6 +39,16 @@
class CI_DB_pdo_result extends CI_DB_result {
/**
+ * @var bool Hold the flag whether a result handler already fetched before
+ */
+ protected $is_fetched = FALSE;
+
+ /**
+ * @var mixed Hold the fetched assoc array of a result handler
+ */
+ protected $result_assoc;
+
+ /**
* Number of rows in the result set
*
* @access public
@@ -46,7 +56,59 @@ class CI_DB_pdo_result extends CI_DB_result {
*/
function num_rows()
{
- return $this->result_id->rowCount();
+ if (empty($this->result_id) OR ! is_object($this->result_id))
+ {
+ // invalid result handler
+ return 0;
+ }
+ elseif (($num_rows = $this->result_id->rowCount()) && $num_rows > 0)
+ {
+ // If rowCount return something, we're done.
+ return $num_rows;
+ }
+
+ // Fetch the result, instead perform another extra query
+ return ($this->is_fetched && is_array($this->result_assoc)) ? count($this->result_assoc) : count($this->result_assoc());
+ }
+
+ /**
+ * Fetch the result handler
+ *
+ * @access public
+ * @return mixed
+ */
+ function result_assoc()
+ {
+ // If the result already fetched before, use that one
+ if (count($this->result_array) > 0 OR $this->is_fetched)
+ {
+ return $this->result_array();
+ }
+
+ // Define the output
+ $output = array('assoc', 'object');
+
+ // Fetch the result
+ foreach ($output as $type)
+ {
+ // Define the method and handler
+ $res_method = '_fetch_'.$type;
+ $res_handler = 'result_'.$type;
+
+ $this->$res_handler = array();
+ $this->_data_seek(0);
+
+ while ($row = $this->$res_method())
+ {
+ $this->{$res_handler}[] = $row;
+ }
+ }
+
+ // Save this as buffer and marked the fetch flag
+ $this->result_array = $this->result_assoc;
+ $this->is_fetched = TRUE;
+
+ return $this->result_assoc;
}
// --------------------------------------------------------------------
@@ -78,6 +140,7 @@ class CI_DB_pdo_result extends CI_DB_result {
{
return $this->db->display_error('db_unsuported_feature');
}
+
return FALSE;
}
@@ -110,6 +173,7 @@ class CI_DB_pdo_result extends CI_DB_result {
{
return $this->db->display_error('db_unsuported_feature');
}
+
return FALSE;
}
}
@@ -178,6 +242,5 @@ class CI_DB_pdo_result extends CI_DB_result {
}
-
/* End of file pdo_result.php */
/* Location: ./system/database/drivers/pdo/pdo_result.php */ \ No newline at end of file
diff --git a/system/libraries/Session.php b/system/libraries/Session.php
index 04103a4d9..66b39a6a2 100644
--- a/system/libraries/Session.php
+++ b/system/libraries/Session.php
@@ -25,8 +25,6 @@
* @filesource
*/
-// ------------------------------------------------------------------------
-
/**
* Session Class
*
@@ -67,7 +65,7 @@ class CI_Session {
*/
public function __construct($params = array())
{
- log_message('debug', "Session Class Initialized");
+ log_message('debug', 'Session Class Initialized');
// Set the super object to a local variable for use throughout the class
$this->CI =& get_instance();
@@ -93,14 +91,14 @@ class CI_Session {
$this->CI->load->library('encrypt');
}
- // Are we using a database? If so, load it
- if ($this->sess_use_database === TRUE AND $this->sess_table_name != '')
+ // Are we using a database? If so, load it
+ if ($this->sess_use_database === TRUE && $this->sess_table_name != '')
{
$this->CI->load->database();
}
- // 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
@@ -114,7 +112,7 @@ class CI_Session {
$this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name;
// Run the Session routine. If a session doesn't exist we'll
- // create a new one. If it does, we'll update it.
+ // create a new one. If it does, we'll update it.
if ( ! $this->sess_read())
{
$this->sess_create();
@@ -133,7 +131,7 @@ class CI_Session {
// Delete expired sessions if necessary
$this->_sess_gc();
- log_message('debug', "Session routines successfully run");
+ log_message('debug', 'Session routines successfully run');
}
// --------------------------------------------------------------------
@@ -166,7 +164,7 @@ class CI_Session {
$hash = substr($session, strlen($session)-32); // get last 32 chars
$session = substr($session, 0, strlen($session)-32);
- // Does the md5 hash match? This is to prevent manipulation of session data in userspace
+ // Does the md5 hash match? This is to prevent manipulation of session data in userspace
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.');
@@ -179,7 +177,7 @@ class CI_Session {
$session = $this->_unserialize($session);
// Is the session data we unserialized an array with the correct format?
- if ( ! is_array($session) OR ! isset($session['session_id']) OR ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_activity']))
+ if ( ! is_array($session) OR ! isset($session['session_id'], $session['ip_address'], $session['user_agent'], $session['last_activity']))
{
$this->sess_destroy();
return FALSE;
@@ -192,15 +190,15 @@ class CI_Session {
return FALSE;
}
- // Does the IP Match?
- if ($this->sess_match_ip == TRUE AND $session['ip_address'] !== $this->CI->input->ip_address())
+ // Does the IP match?
+ if ($this->sess_match_ip == TRUE && $session['ip_address'] !== $this->CI->input->ip_address())
{
$this->sess_destroy();
return FALSE;
}
// Does the User Agent Match?
- if ($this->sess_match_useragent == TRUE AND 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;
@@ -223,7 +221,7 @@ class CI_Session {
$query = $this->CI->db->get($this->sess_table_name);
- // No result? Kill it!
+ // No result? Kill it!
if ($query->num_rows() === 0)
{
$this->sess_destroy();
@@ -232,7 +230,7 @@ class CI_Session {
// Is there custom data? If so, add it to the main session array
$row = $query->row();
- if (isset($row->user_data) AND $row->user_data != '')
+ if (isset($row->user_data) && $row->user_data != '')
{
$custom_data = $this->_unserialize($row->user_data);
@@ -282,7 +280,7 @@ class CI_Session {
$cookie_userdata[$val] = $this->userdata[$val];
}
- // Did we find any custom data? If not, we turn the empty array into a string
+ // 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)
{
@@ -298,7 +296,7 @@ class CI_Session {
$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
+ // 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);
@@ -324,13 +322,12 @@ class CI_Session {
$sessid .= $this->CI->input->ip_address();
$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' => ''
- );
-
+ '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
if ($this->sess_use_database === TRUE)
@@ -357,6 +354,35 @@ class CI_Session {
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);
+ }
+
// Save the old session id so we know which record to
// update in the database if we need it
$old_sessid = $this->userdata['session_id'];
@@ -374,10 +400,6 @@ class CI_Session {
$this->userdata['session_id'] = $new_sessid = md5(uniqid($new_sessid, TRUE));
$this->userdata['last_activity'] = $this->now;
- // _set_cookie() will handle this for us if we aren't using database sessions
- // by pushing all userdata to the cookie.
- $cookie_data = NULL;
-
// Update the session ID and last_activity field in the DB if needed
if ($this->sess_use_database === TRUE)
{
@@ -405,7 +427,7 @@ class CI_Session {
public function sess_destroy()
{
// Kill the session DB row
- if ($this->sess_use_database === TRUE AND isset($this->userdata['session_id']))
+ 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);
@@ -413,13 +435,13 @@ class CI_Session {
// Kill the cookie
setcookie(
- $this->sess_cookie_name,
- addslashes(serialize(array())),
- ($this->now - 31500000),
- $this->cookie_path,
- $this->cookie_domain,
- 0
- );
+ $this->sess_cookie_name,
+ addslashes(serialize(array())),
+ ($this->now - 31500000),
+ $this->cookie_path,
+ $this->cookie_domain,
+ 0
+ );
}
// --------------------------------------------------------------------
@@ -535,7 +557,7 @@ class CI_Session {
*/
public function keep_flashdata($key)
{
- // 'old' flashdata gets removed. Here we mark all
+ // 'old' flashdata gets removed. Here we mark all
// flashdata as 'new' to preserve it from _flashdata_sweep()
// Note the function will return FALSE if the $key
// provided cannot be found
@@ -586,7 +608,6 @@ class CI_Session {
*
* @return void
*/
-
protected function _flashdata_sweep()
{
$userdata = $this->all_userdata();
@@ -609,13 +630,9 @@ class CI_Session {
*/
protected function _get_time()
{
- if (strtolower($this->time_reference) === 'gmt')
- {
- $now = time();
- return mktime(gmdate('H', $now), gmdate('i', $now), gmdate('s', $now), gmdate('m', $now), gmdate('d', $now), gmdate('Y', $now));
- }
-
- return time();
+ return (strtolower($this->time_reference) === 'gmt')
+ ? mktime(gmdate('H'), gmdate('i'), gmdate('s'), gmdate('m'), gmdate('d'), gmdate('Y'))
+ : time();
}
// --------------------------------------------------------------------
@@ -649,13 +666,13 @@ class CI_Session {
// Set the cookie
setcookie(
- $this->sess_cookie_name,
- $cookie_data,
- $expire,
- $this->cookie_path,
- $this->cookie_domain,
- $this->cookie_secure
- );
+ $this->sess_cookie_name,
+ $cookie_data,
+ $expire,
+ $this->cookie_path,
+ $this->cookie_domain,
+ $this->cookie_secure
+ );
}
// --------------------------------------------------------------------
@@ -687,8 +704,11 @@ class CI_Session {
*
* This function converts any slashes found into a temporary marker
*
+ * @param string
+ * @param string
+ * @return void
*/
- function _escape_slashes(&$val, $key)
+ protected function _escape_slashes(&$val, $key)
{
if (is_string($val))
{
@@ -725,6 +745,9 @@ class CI_Session {
*
* This function converts any slash markers back into actual slashes
*
+ * @param string
+ * @param string
+ * @return void
*/
protected function _unescape_slashes(&$val, $key)
{
@@ -763,9 +786,7 @@ class CI_Session {
}
}
-
}
-// END Session Class
/* End of file Session.php */
/* Location: ./system/libraries/Session.php */
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 10f5507eb..649616e8d 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -49,6 +49,8 @@ Release Date: Not Released
- Adding $escape parameter to the order_by function, this enables ordering by custom fields.
- MySQLi driver now uses mysqli_get_server_info() for server version checking.
- MySQLi driver now supports persistent connections when running on PHP >= 5.3.
+ - Added dsn if the group connections in the config use PDO or any driver which need DSN.
+ - Improved PDO database support.
- Libraries
@@ -100,6 +102,8 @@ Bug fixes for 3.0
- Fixed a bug (#561) - Errors in :doc:`XML-RPC Library <libraries/xmlrpc>` were not properly escaped.
- Fixed a bug (#904) - ``CI_Loader::initialize()`` caused a PHP Fatal error to be triggered if error level E_STRICT is used.
- Fixed a hosting edge case where an empty $_SERVER['HTTPS'] variable would evaluate to 'on'
+- Fixed a bug (#154) - ``CI_Session::sess_update()`` caused the session to be destroyed on pages where multiple AJAX requests were executed at once.
+- Fixed a possible bug in ``CI_Input::is_ajax_request()`` where some clients might not send the X-Requested-With HTTP header value exactly as 'XmlHttpRequest'.
Version 2.1.0
=============
diff --git a/user_guide_src/source/database/configuration.rst b/user_guide_src/source/database/configuration.rst
index 4f88c25ab..040e7e33f 100644
--- a/user_guide_src/source/database/configuration.rst
+++ b/user_guide_src/source/database/configuration.rst
@@ -28,6 +28,10 @@ prototype::
$db['default']['autoinit'] = TRUE;
$db['default']['stricton'] = FALSE;
+If you use PDO as your dbdriver, you can specify the full DSN string describe a connection to the database like this::
+
+ $db['default']['dsn'] = 'pgsql:host=localhost;port=5432;dbname=database_name';
+
You can also specify failovers for the situation when the main connection cannot connect for some reason.
These failovers can be specified by setting the failover for a connection like this::