Merge pull request #2768 from porquero/patch-1

Added post-increment for $count
diff --git a/application/views/errors/html/error_404.php b/application/views/errors/html/error_404.php
index 21ff6db..11b8d99 100644
--- a/application/views/errors/html/error_404.php
+++ b/application/views/errors/html/error_404.php
@@ -74,8 +74,6 @@
 	margin: 10px;
 	border: 1px solid #D0D0D0;
 	box-shadow: 0 0 8px #D0D0D0;
-	-moz-box-shadow: 0 0 8px #D0D0D0;
-	-webkit-box-shadow: 0 0 8px #D0D0D0;
 }
 
 p {
diff --git a/application/views/errors/html/error_db.php b/application/views/errors/html/error_db.php
index a251e1c..f376e09 100644
--- a/application/views/errors/html/error_db.php
+++ b/application/views/errors/html/error_db.php
@@ -74,8 +74,6 @@
 	margin: 10px;
 	border: 1px solid #D0D0D0;
 	box-shadow: 0 0 8px #D0D0D0;
-	-moz-box-shadow: 0 0 8px #D0D0D0;
-	-webkit-box-shadow: 0 0 8px #D0D0D0;
 }
 
 p {
diff --git a/application/views/errors/html/error_general.php b/application/views/errors/html/error_general.php
index b9d5438..df435b3 100644
--- a/application/views/errors/html/error_general.php
+++ b/application/views/errors/html/error_general.php
@@ -74,8 +74,6 @@
 	margin: 10px;
 	border: 1px solid #D0D0D0;
 	box-shadow: 0 0 8px #D0D0D0;
-	-moz-box-shadow: 0 0 8px #D0D0D0;
-	-webkit-box-shadow: 0 0 8px #D0D0D0;
 }
 
 p {
diff --git a/application/views/welcome_message.php b/application/views/welcome_message.php
index 2466a83..341a8d0 100644
--- a/application/views/welcome_message.php
+++ b/application/views/welcome_message.php
@@ -87,8 +87,7 @@
 	#container {
 		margin: 10px;
 		border: 1px solid #D0D0D0;
-		-moz-box-shadow: 0 0 8px #D0D0D0;
-		-webkit-box-shadow: 0 0 8px #D0D0D0;
+		box-shadow: 0 0 8px #D0D0D0;
 	}
 	</style>
 </head>
diff --git a/readme.rst b/readme.rst
index 619c7ae..b4984ea 100644
--- a/readme.rst
+++ b/readme.rst
@@ -50,8 +50,8 @@
 *********
 
 -  `User Guide <http://ellislab.com/codeigniter/user_guide/>`_
--  `Community Forums <http://ellislab.com/codeigniter/forums/>`_
--  `Community Wiki <http://ellislab.com/codeigniter/wiki/>`_
+-  `Community Forums <http://ellislab.com/forums/>`_
+-  `Community Wiki <https://github.com/EllisLab/CodeIgniter/wiki/>`_
 -  `Community IRC <http://ellislab.com/codeigniter/irc>`_
 
 ***************
diff --git a/system/core/Lang.php b/system/core/Lang.php
index 3236709..290b38b 100644
--- a/system/core/Lang.php
+++ b/system/core/Lang.php
@@ -166,7 +166,7 @@
 	 * @param	bool	$log_errors	Whether to log an error message if the line is not found
 	 * @return	string	Translation
 	 */
-	public function line($line = '', $log_errors = TRUE)
+	public function line($line, $log_errors = TRUE)
 	{
 		$value = ($line === '' OR ! isset($this->language[$line])) ? FALSE : $this->language[$line];
 
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 70c1e41..334a5c4 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -472,16 +472,16 @@
 
 	/**
 	 * Clear Cached Variables
-	 * 
+	 *
 	 * Clears the cached variables.
-	 * 
+	 *
 	 * @return  void
 	 */
 	public function clear_vars()
 	{
 		$this->_ci_cached_vars = array();
 	}
-	
+
 	// --------------------------------------------------------------------
 
 	/**
diff --git a/system/core/URI.php b/system/core/URI.php
index bad9985..5e4c80a 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -703,12 +703,7 @@
 	{
 		global $RTR;
 
-		if (($dir = $RTR->directory) === '/')
-		{
-			$dir = '';
-		}
-
-		return $dir.implode('/', $this->rsegment_array());
+		return ltrim($RTR->directory, '/').implode('/', $this->rsegment_array());
 	}
 
 }
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 9aa6c5d..4791c3b 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -1421,7 +1421,7 @@
 	 */
 	protected function _has_operator($str)
 	{
-		return (bool) preg_match('/(<|>|!|=|\sIS NULL|\sIS NOT NULL|\sBETWEEN|\sLIKE|\sIN\s*\(|\s)/i', trim($str));
+		return (bool) preg_match('/(<|>|!|=|\sIS NULL|\sIS NOT NULL|\sEXISTS|\sBETWEEN|\sLIKE|\sIN\s*\(|\s)/i', trim($str));
 	}
 
 	// --------------------------------------------------------------------
@@ -1447,6 +1447,8 @@
 				'\s*>\s*',			// >
 				'\s+IS NULL',			// IS NULL
 				'\s+IS NOT NULL',		// IS NOT NULL
+				'\s+EXISTS\s*\([^\)]+\)',	// EXISTS(sql)
+				'\s+NOT EXISTS\s*\([^\)]+\)',	// NOT EXISTS(sql)
 				'\s+BETWEEN\s+\S+\s+AND\s+\S+',	// BETWEEN value AND value
 				'\s+IN\s*\([^\)]+\)',		// IN(list)
 				'\s+NOT IN\s*\([^\)]+\)',	// NOT IN (list)
@@ -1483,7 +1485,7 @@
 		}
 
 		return (func_num_args() > 1)
-			? call_user_func_array($function, array_splice(func_get_args(), 1))
+			? call_user_func_array($function, array_slice(func_get_args(), 1))
 			: call_user_func($function);
 	}
 
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index 92806d3..1cebb18 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -984,7 +984,6 @@
 	 */
 	protected function _process_indexes($table)
 	{
-		$table = $this->db->escape_identifiers($table);
 		$sqls = array();
 
 		for ($i = 0, $c = count($this->keys); $i < $c; $i++)
@@ -1008,7 +1007,7 @@
 
 			is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
 
-			$sqls[] = 'CREATE INDEX '.$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+			$sqls[] = 'CREATE INDEX '.$this->db->escape_identifiers($table.'_'.implode('_', $this->keys[$i]))
 				.' ON '.$this->db->escape_identifiers($table)
 				.' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).');';
 		}
diff --git a/system/language/english/ftp_lang.php b/system/language/english/ftp_lang.php
index ae4086f..042ab55 100644
--- a/system/language/english/ftp_lang.php
+++ b/system/language/english/ftp_lang.php
@@ -26,18 +26,18 @@
  */
 defined('BASEPATH') OR exit('No direct script access allowed');
 
-$lang['ftp_no_connection']			= 'Unable to locate a valid connection ID. Please make sure you are connected before peforming any file routines.';
+$lang['ftp_no_connection']		= 'Unable to locate a valid connection ID. Please make sure you are connected before peforming any file routines.';
 $lang['ftp_unable_to_connect']		= 'Unable to connect to your FTP server using the supplied hostname.';
 $lang['ftp_unable_to_login']		= 'Unable to login to your FTP server. Please check your username and password.';
-$lang['ftp_unable_to_makdir']		= 'Unable to create the directory you have specified.';
+$lang['ftp_unable_to_mkdir']		= 'Unable to create the directory you have specified.';
 $lang['ftp_unable_to_changedir']	= 'Unable to change directories.';
-$lang['ftp_unable_to_chmod']		= 'Unable to set file permissions. Please check your path. Note: This feature is only available in PHP 5 or higher.';
+$lang['ftp_unable_to_chmod']		= 'Unable to set file permissions. Please check your path.';
 $lang['ftp_unable_to_upload']		= 'Unable to upload the specified file. Please check your path.';
 $lang['ftp_unable_to_download']		= 'Unable to download the specified file. Please check your path.';
-$lang['ftp_no_source_file']			= 'Unable to locate the source file. Please check your path.';
+$lang['ftp_no_source_file']		= 'Unable to locate the source file. Please check your path.';
 $lang['ftp_unable_to_rename']		= 'Unable to rename the file.';
 $lang['ftp_unable_to_delete']		= 'Unable to delete the file.';
-$lang['ftp_unable_to_move']			= 'Unable to move the file. Please make sure the destination directory exists.';
+$lang['ftp_unable_to_move']		= 'Unable to move the file. Please make sure the destination directory exists.';
 
 /* End of file ftp_lang.php */
 /* Location: ./system/language/english/ftp_lang.php */
\ No newline at end of file
diff --git a/system/libraries/Ftp.php b/system/libraries/Ftp.php
index 2489f49..4be2d0a 100644
--- a/system/libraries/Ftp.php
+++ b/system/libraries/Ftp.php
@@ -214,10 +214,10 @@
 	 * Internally, this parameter is only used by the "mirror" function below.
 	 *
 	 * @param	string	$path
-	 * @param	bool	$supress_debug
+	 * @param	bool	$suppress_debug
 	 * @return	bool
 	 */
-	public function changedir($path = '', $supress_debug = FALSE)
+	public function changedir($path, $suppress_debug = FALSE)
 	{
 		if ($path === '' OR ! $this->_is_conn())
 		{
@@ -228,7 +228,7 @@
 
 		if ($result === FALSE)
 		{
-			if ($this->debug === TRUE && $supress_debug === FALSE)
+			if ($this->debug === TRUE && $suppress_debug === FALSE)
 			{
 				$this->_error('ftp_unable_to_changedir');
 			}
@@ -247,7 +247,7 @@
 	 * @param	int	$permissions
 	 * @return	bool
 	 */
-	public function mkdir($path = '', $permissions = NULL)
+	public function mkdir($path, $permissions = NULL)
 	{
 		if ($path === '' OR ! $this->_is_conn())
 		{
@@ -260,7 +260,7 @@
 		{
 			if ($this->debug === TRUE)
 			{
-				$this->_error('ftp_unable_to_makdir');
+				$this->_error('ftp_unable_to_mkdir');
 			}
 			return FALSE;
 		}
diff --git a/system/libraries/Session/drivers/Session_cookie.php b/system/libraries/Session/drivers/Session_cookie.php
index cd80744..dc75d8e 100644
--- a/system/libraries/Session/drivers/Session_cookie.php
+++ b/system/libraries/Session/drivers/Session_cookie.php
@@ -397,7 +397,7 @@
 		}
 
 		// Unserialize the session array
-		$session = $this->_unserialize($session);
+		$session = @unserialize($session);
 
 		// Is the session data we unserialized an array with the correct format?
 		if ( ! is_array($session) OR ! isset($session['session_id'], $session['ip_address'], $session['user_agent'], $session['last_activity']))
@@ -472,7 +472,7 @@
 			$row = $query->row();
 			if ( ! empty($row->user_data))
 			{
-				$custom_data = $this->_unserialize($row->user_data);
+				$custom_data = unserialize(trim($row->user_data));
 
 				if (is_array($custom_data))
 				{
@@ -608,7 +608,7 @@
 			if ( ! empty($userdata))
 			{
 				// Serialize the custom data array so we can store it
-				$set['user_data'] = $this->_serialize($userdata);
+				$set['user_data'] = serialize($userdata);
 			}
 
 			// Reset query builder values.
@@ -696,7 +696,7 @@
 				: $this->userdata;
 
 		// Serialize the userdata for the cookie
-		$cookie_data = $this->_serialize($cookie_data);
+		$cookie_data = serialize($cookie_data);
 
 		if ($this->sess_encrypt_cookie === TRUE)
 		{
@@ -737,93 +737,6 @@
 	// ------------------------------------------------------------------------
 
 	/**
-	 * Serialize an array
-	 *
-	 * 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	mixed	Data to serialize
-	 * @return	string	Serialized data
-	 */
-	protected function _serialize($data)
-	{
-		if (is_array($data))
-		{
-			array_walk_recursive($data, array(&$this, '_escape_slashes'));
-		}
-		elseif (is_string($data))
-		{
-			$data = str_replace('\\', '{{slash}}', $data);
-		}
-
-		return serialize($data);
-	}
-
-	// ------------------------------------------------------------------------
-
-	/**
-	 * Escape slashes
-	 *
-	 * This function converts any slashes found into a temporary marker
-	 *
-	 * @param	string	Value
-	 * @param	string	Key
-	 * @return	void
-	 */
-	protected function _escape_slashes(&$val, $key)
-	{
-		if (is_string($val))
-		{
-			$val = str_replace('\\', '{{slash}}', $val);
-		}
-	}
-
-	// ------------------------------------------------------------------------
-
-	/**
-	 * Unserialize
-	 *
-	 * This function unserializes a data string, then converts any
-	 * temporary slash markers back to actual slashes
-	 *
-	 * @param	mixed	Data to unserialize
-	 * @return	mixed	Unserialized data
-	 */
-	protected function _unserialize($data)
-	{
-		$data = @unserialize(trim($data));
-
-		if (is_array($data))
-		{
-			array_walk_recursive($data, array(&$this, '_unescape_slashes'));
-			return $data;
-		}
-
-		return is_string($data) ? str_replace('{{slash}}', '\\', $data) : $data;
-	}
-
-	// ------------------------------------------------------------------------
-
-	/**
-	 * Unescape slashes
-	 *
-	 * This function converts any slash markers back into actual slashes
-	 *
-	 * @param	string	Value
-	 * @param	string	Key
-	 * @return	void
-	 */
-	protected function _unescape_slashes(&$val, $key)
-	{
-		if (is_string($val))
-		{
-	 		$val = str_replace('{{slash}}', '\\', $val);
-		}
-	}
-
-	// ------------------------------------------------------------------------
-
-	/**
 	 * Garbage collection
 	 *
 	 * This deletes expired session rows from database
diff --git a/user_guide_src/source/_themes/eldocs/static/asset/css/common.css b/user_guide_src/source/_themes/eldocs/static/asset/css/common.css
index 648e330..5cbb37f 100644
--- a/user_guide_src/source/_themes/eldocs/static/asset/css/common.css
+++ b/user_guide_src/source/_themes/eldocs/static/asset/css/common.css
@@ -133,7 +133,7 @@
 a:hover,
 a:active{ color: #742CAC; }
 
-a.headerlink{ visibility: hidden; }
+a.headerlink{ visibility: hidden; margin-left: 0.4em; }
 
 	:hover > a.headerlink { visibility: visible; }
 
@@ -261,12 +261,12 @@
 	#header form{ float: right; overflow: hidden; }
 	
 	#header input{ float: left; }
-	
+
 	#header input[type="text"]{
 		background-color: #FFFFFF;
 		border: 1px solid;
 		border-color: #033861 #13598F #13598F #033861;
-		font-size: inherit;
+		font: inherit;
 		margin-right: 5px;
 		padding: 5px;
 		width: 175px;
@@ -279,8 +279,9 @@
 		border: 1px solid #033861;
 		color: #094776;
 		cursor: pointer;
+		font: inherit;
 		font-weight: bold;
-		padding: 5px 10px 4px;
+		padding: 5px 10px;
 		text-transform: uppercase;
 	}
 	
@@ -349,6 +350,4 @@
 	h3,h4,h5,h6{ font-size: 14px; }
 }
 
-@media screen and (-webkit-min-device-pixel-ratio:0){
-	#header input[type="submit"]{ padding-bottom: 7px; }
-}
+#header input[type="submit"], x:-moz-any-link{ padding: 4px 10px; }
\ No newline at end of file
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index b7fa9bb..54583e6 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -165,6 +165,7 @@
       - Added an optional parameter that allows to disable escaping (useful for custom fields) for methods ``join()``, ``order_by()``, ``where_in()``, ``or_where_in()``, ``where_not_in()``, ``or_where_not_in()``, ``insert()``, ``insert_batch()``.
       - Added support for ``join()`` with multiple conditions.
       - Added support for *USING* in ``join()``.
+      - Added support for *EXISTS* in ``where()``.
       - Added seed values support for random ordering with ``order_by(seed, 'RANDOM')``.
       - Changed ``limit()`` to ignore NULL values instead of always casting to integer.
       - Changed ``offset()`` to ignore empty values instead of always casting to integer.
@@ -439,7 +440,7 @@
 
    -  :doc:`Language Library <libraries/language>` changes include:
 
-      -  Changed method ``load()`` to filter the language name with ``ctype_digit()``.
+      -  Changed method ``load()`` to filter the language name with ``ctype_alpha()``.
       -  Added an optional second parameter to method ``line()`` to disable error login for line keys that were not found.
       -  Language files are now loaded in a cascading style with the one in **system/** always loaded and overriden afterwards, if another one is found.
 
diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst
index 4800674..9a96db0 100644
--- a/user_guide_src/source/database/query_builder.rst
+++ b/user_guide_src/source/database/query_builder.rst
@@ -665,10 +665,12 @@
 	// Produces string: INSERT INTO mytable (title, content) VALUES ('My Title', 'My Content')
 
 The key thing to notice in the above example is that the second query did not
-utlize `$this->db->from()`_ nor did it pass a table name into the first
+utlize `$this->db->from()` nor did it pass a table name into the first
 parameter. The reason this worked is because the query has not been executed
-using `$this->db->insert()`_ which resets values or reset directly using
-`$this->db->reset_query()`_.
+using `$this->db->insert()` which resets values or reset directly using
+`$this->db->reset_query()`.
+
+.. note:: This method doesn't work for batched inserts.
 
 $this->db->insert_batch()
 =========================
@@ -886,8 +888,9 @@
 This works exactly the same way as ``$this->db->get_compiled_insert()`` except
 that it produces an UPDATE SQL string instead of an INSERT SQL string.
 
-For more information view documentation for `$this->db->get_compiled_insert()`_.
+For more information view documentation for `$this->db->get_compiled_insert()`.
 
+.. note:: This method doesn't work for batched updates.
 
 *************
 Deleting Data
diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst
index 0555314..be1f8d2 100644
--- a/user_guide_src/source/libraries/security.rst
+++ b/user_guide_src/source/libraries/security.rst
@@ -83,14 +83,14 @@
 
 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()``
+your forms. If not, then you can use ``get_csrf_token_name()``
+and ``get_csrf_hash()``
 
 ::
 
 	$csrf = array(
-		'name' => $this->security->csrf_get_token_name(),
-		'hash' => $this->security->csrf_get_hash()
+		'name' => $this->security->get_csrf_token_name(),
+		'hash' => $this->security->get_csrf_hash()
 	);
 
 	...