Merge branch 'develop' of git://github.com/EllisLab/CodeIgniter into develop
diff --git a/system/core/Lang.php b/system/core/Lang.php
index 3001f1b..601348a 100644
--- a/system/core/Lang.php
+++ b/system/core/Lang.php
@@ -65,11 +65,11 @@
/**
* Load a language file
*
- * @param mixed the name of the language file to be loaded
- * @param string the language (english, etc.)
- * @param bool return loaded array of translations
- * @param bool add suffix to $langfile
- * @param string alternative path to look for language file
+ * @param mixed $langile the name of the language file to be loaded
+ * @param string $idiom = '' the language (english, etc.)
+ * @param bool $return = FALSE return loaded array of translations
+ * @param bool $add_suffix = TRUE add suffix to $langfile
+ * @param string $alt_path = '' alternative path to look for language file
* @return mixed
*/
public function load($langfile, $idiom = '', $return = FALSE, $add_suffix = TRUE, $alt_path = '')
@@ -83,10 +83,10 @@
$langfile .= '.php';
- if ($idiom === '')
+ if (empty($idiom) OR ! ctype_alpha($idiom))
{
$config =& get_config();
- $idiom = ( ! empty($config['language'])) ? $config['language'] : 'english';
+ $idiom = empty($config['language']) ? 'english' : $config['language'];
}
if ($return === FALSE && isset($this->is_loaded[$langfile]) && $this->is_loaded[$langfile] === $idiom)
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 5de2e5d..b316c8e 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -318,9 +318,9 @@
/**
* Database Loader
*
- * @param string the DB credentials
- * @param bool whether to return the DB object
- * @param bool whether to enable query builder (this allows us to override the config setting)
+ * @param mixed $params = '' the DB settings
+ * @param bool $return = FALSE whether to return the DB object
+ * @param bool $query_builder = NULL whether to enable query builder (overrides the config setting)
* @return object
*/
public function database($params = '', $return = FALSE, $query_builder = NULL)
@@ -329,7 +329,7 @@
$CI =& get_instance();
// Do we even need to load the database class?
- if (class_exists('CI_DB') && $return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db))
+ if ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id))
{
return FALSE;
}
diff --git a/system/core/Security.php b/system/core/Security.php
index 2fbc5b3..d7c8271 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -161,7 +161,7 @@
}
// Do the tokens exist in both the _POST and _COOKIE arrays?
- if ( ! isset($_POST[$this->_csrf_token_name]) OR ! isset($_COOKIE[$this->_csrf_cookie_name])
+ if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
OR $_POST[$this->_csrf_token_name] !== $_COOKIE[$this->_csrf_cookie_name]) // Do the tokens match?
{
$this->csrf_show_error();
diff --git a/system/core/URI.php b/system/core/URI.php
index 15e6a55..72f293c 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -433,9 +433,9 @@
/**
* Generate a key value pair from the URI string or Re-routed URI string
*
- * @param int the starting segment number
- * @param array an array of default values
- * @param string which array we should use
+ * @param int $n = 3 the starting segment number
+ * @param array $default = array() an array of default values
+ * @param string $which = 'segment' which array we should use
* @return array
*/
protected function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
@@ -445,9 +445,11 @@
return $default;
}
- if (isset($this->keyval[$n]))
+ in_array($which, array('segment', 'rsegment'), TRUE) OR $which = 'segment';
+
+ if (isset($this->keyval[$which], $this->keyval[$which][$n]))
{
- return $this->keyval[$n];
+ return $this->keyval[$which][$n];
}
if ($which === 'segment')
@@ -499,7 +501,8 @@
}
// Cache the array for reuse
- $this->keyval[$n] = $retval;
+ isset($this->keyval[$which]) OR $this->keyval[$which] = array();
+ $this->keyval[$which][$n] = $retval;
return $retval;
}
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 7f1434f..e8286aa 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -640,7 +640,7 @@
// Make sure not to replace a chunk inside a string that happens to match the bind marker
if ($c = preg_match_all("/'[^']*'/i", $sql, $matches))
{
- $c = preg_match_all('/'.preg_quote($this->bind_marker).'/i',
+ $c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i',
str_replace($matches[0],
str_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]),
$sql, $c),
@@ -652,7 +652,7 @@
return $sql;
}
}
- elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker).'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count)
+ elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count)
{
return $sql;
}
@@ -1007,13 +1007,13 @@
if (is_array($this->_escape_char))
{
$preg_ec = array(
- preg_quote($this->_escape_char[0]), preg_quote($this->_escape_char[1]),
+ preg_quote($this->_escape_char[0], '/'), preg_quote($this->_escape_char[1], '/'),
$this->_escape_char[0], $this->_escape_char[1]
);
}
else
{
- $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char);
+ $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char, '/');
$preg_ec[2] = $preg_ec[3] = $this->_escape_char;
}
}
@@ -1172,7 +1172,7 @@
if (empty($_operators))
{
$_les = ($this->_like_escape_str !== '')
- ? '\s+'.preg_quote(trim(sprintf($this->_like_escape_str, $this->_like_escape_chr)))
+ ? '\s+'.preg_quote(trim(sprintf($this->_like_escape_str, $this->_like_escape_chr)), '/')
: '';
$_operators = array(
'\s*(?:<|>|!)?=\s*', // =, <=, >=, !=
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index 5ea9643..ed00510 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -2077,7 +2077,7 @@
for ($ci = 0, $cc = count($conditions); $ci < $cc; $ci++)
{
if (($op = $this->_get_operator($conditions[$ci])) === FALSE
- OR ! preg_match('/^(\(?)(.*)('.preg_quote($op).')\s*(.*(?<!\)))?(\)?)$/i', $conditions[$ci], $matches))
+ OR ! preg_match('/^(\(?)(.*)('.preg_quote($op, '/').')\s*(.*(?<!\)))?(\)?)$/i', $conditions[$ci], $matches))
{
continue;
}
diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php
index 0232adf..2c26a36 100644
--- a/system/helpers/download_helper.php
+++ b/system/helpers/download_helper.php
@@ -110,13 +110,10 @@
// Internet Explorer-specific headers
if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE)
{
- header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
- header('Pragma: public');
+ header('Cache-Control: no-cache, no-store, must-revalidate');
}
- else
- {
- header('Pragma: no-cache');
- }
+
+ header('Pragma: no-cache');
exit($data);
}
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
index de5bdec..dc77246 100644
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -489,7 +489,7 @@
$separator = '_';
}
- $q_separator = preg_quote($separator);
+ $q_separator = preg_quote($separator, '#');
$trans = array(
'&.+?;' => '',
diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php
index ff596f0..3387d4a 100644
--- a/system/libraries/User_agent.php
+++ b/system/libraries/User_agent.php
@@ -466,7 +466,13 @@
*/
public function is_referral()
{
- return ! empty($_SERVER['HTTP_REFERER']);
+ if (empty($_SERVER['HTTP_REFERER']))
+ {
+ return FALSE;
+ }
+
+ $referer = parse_url($_SERVER['HTTP_REFERER']);
+ return ! (empty($referer['host']) && strpos(config_item('base_url'), $referer['host']) !== FALSE);
}
// --------------------------------------------------------------------
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 9def99c..c87aebd 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -223,6 +223,7 @@
- :doc:`Encryption Library <libraries/encryption>` changes include:
- Added support for hashing algorithms other than SHA1 and MD5.
- Removed previously deprecated ``sha1()`` method.
+ - Changed :doc:`Language Library <libraries/language>` method ``load()`` to filter the language name with ``ctype_digit()``.
- Core
@@ -401,6 +402,10 @@
- Fixed a bug (#1766) - :doc:`Query Builder <database/query_builder>` didn't always take into account the *dbprefix* setting.
- Fixed a bug (#779) - :doc:`URI Class <libraries/uri>` didn't always trim slashes from the *uri_string* as shown in the documentation.
- Fixed a bug (#134) - :doc:`Database Caching <database/caching>` method ``delete_cache()`` didn't work in some cases due to *cachedir* not being initialized properly.
+- Fixed a bug (#191) - :doc:`Loader Library <libraries/loader>` ignored attempts for (re)loading databases to ``get_instance()->db`` even when the old database connection is dead.
+- Fixed a bug (#1255) - :doc:`User Agent Library <libraries/user_agent>` method ``is_referral()`` only checked if ``$_SERVER['HTTP_REFERER']`` exists.
+- Fixed a bug (#1146) - :doc:`Download Helper <helpers/download_helper>` function ``force_download()`` incorrectly sent *Cache-Control* directives *pre-check* and *post-check* to Internet Explorer.
+- Fixed a bug (#1811) - :doc:`URI Library <libraries/uri>` didn't properly cache segments for ``uri_to_assoc()`` and ``ruri_to_assoc()``.
Version 2.1.3
=============
diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst
index 6ca7291..5380d09 100644
--- a/user_guide_src/source/database/query_builder.rst
+++ b/user_guide_src/source/database/query_builder.rst
@@ -681,6 +681,35 @@
.. note:: All values are escaped automatically producing safer queries.
+$this->db->replace()
+====================
+
+This method executes a REPLACE statement, which is basically the SQL
+standard for (optional) DELETE + INSERT, using *PRIMARY* and *UNIQUE*
+keys as the determining factor.
+In our case, it will save you from the need to implement complex
+logics with different combinations of ``select()``, ``update()``,
+``delete()`` and ``insert()`` calls.
+
+Example::
+
+ $data = array(
+ 'title' => 'My title',
+ 'name' => 'My Name',
+ 'date' => 'My date'
+ );
+
+ $this->db->replace('table', $data);
+
+ // Executes: REPLACE INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date')
+
+In the above example, if we assume that the *title* field is our primary
+key, then if a row containing 'My title' as the *title* value, that row
+will be deleted with our new row data replacing it.
+
+Usage of the ``set()`` method is also allowed and all fields are
+automatically escaped, just like with ``insert()``.
+
$this->db->set()
================
@@ -740,7 +769,6 @@
$this->db->set($object);
$this->db->insert('mytable');
-
*************
Updating Data
*************
@@ -792,6 +820,7 @@
You may also use the $this->db->set() function described above when
performing updates.
+
$this->db->update_batch()
=========================
diff --git a/user_guide_src/source/libraries/language.rst b/user_guide_src/source/libraries/language.rst
index ec678cd..b231f14 100644
--- a/user_guide_src/source/libraries/language.rst
+++ b/user_guide_src/source/libraries/language.rst
@@ -54,7 +54,9 @@
Where filename is the name of the file you wish to load (without the
file extension), and language is the language set containing it (ie,
english). If the second parameter is missing, the default language set
-in your application/config/config.php file will be used.
+in your *application/config/config.php* file will be used.
+
+.. note:: The *language* parameter can only consist of letters.
Fetching a Line of Text
=======================
@@ -67,8 +69,7 @@
Where language_key is the array key corresponding to the line you wish
to show.
-Note: This function simply returns the line. It does not echo it for
-you.
+.. note:: This method simply returns the line. It does not echo it.
Using language lines as form labels
-----------------------------------
diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst
index e7d2555..0555314 100644
--- a/user_guide_src/source/libraries/security.rst
+++ b/user_guide_src/source/libraries/security.rst
@@ -26,7 +26,7 @@
To filter data through the XSS filter use this function:
$this->security->xss_clean()
-=============================
+============================
Here is an usage example::
@@ -56,7 +56,7 @@
}
$this->security->sanitize_filename()
-=====================================
+====================================
When accepting filenames from user input, it is best to sanitize them to
prevent directory traversal and other security related issues. To do so,
@@ -76,16 +76,35 @@
Cross-site request forgery (CSRF)
=================================
-You can enable csrf protection by opening your
+You can enable CSRF protection by opening your
application/config/config.php file and setting this::
$config['csrf_protection'] = TRUE;
-If you use the :doc:`form helper <../helpers/form_helper>` the
-form_open() function will automatically insert a hidden csrf field in
-your forms.
+If you use the :doc:`form helper <../helpers/form_helper>`, then
+``form_open()`` will automatically insert a hidden csrf field in
+your forms. If not, then you can use ``csrf_get_token_name()``
+and ``csrf_get_hash()``
-Tokens may be either regenerated on every submission (default) or kept the same throughout the life of the CSRF cookie. The default regeneration of tokens provides stricter security but may result in usability concerns as other tokens become invalid (back/forward navigation, multiple tabs/windows, asynchronous actions, etc). You may alter this behavior by editing the following config parameter::
+::
+
+ $csrf = array(
+ 'name' => $this->security->csrf_get_token_name(),
+ 'hash' => $this->security->csrf_get_hash()
+ );
+
+ ...
+
+ <input type="hidden" name="<?=$csrf['name'];?>" value="<?=$csrf['hash'];?>" />
+
+Tokens may be either regenerated on every submission (default) or
+kept the same throughout the life of the CSRF cookie. The default
+regeneration of tokens provides stricter security, but may result
+in usability concerns as other tokens become invalid (back/forward
+navigation, multiple tabs/windows, asynchronous actions, etc). You
+may alter this behavior by editing the following config parameter
+
+::
$config['csrf_regeneration'] = TRUE;
@@ -95,3 +114,15 @@
$config['csrf_exclude_uris'] = array('api/person/add');
+$this->security->get_csrf_token_name()
+======================================
+
+Returns the CSRF token name, which is set by
+``$config['csrf_token_name']``.
+
+$this->security->get_csrf_hash()
+================================
+
+Returns the CSRF hash value. Useful in combination with
+``get_csrf_token_name()`` for manually building forms or
+sending valid AJAX POST requests.
\ No newline at end of file