Merge upstream branch
diff --git a/DCO.txt b/DCO.txt
new file mode 100644
index 0000000..a404c0d
--- /dev/null
+++ b/DCO.txt
@@ -0,0 +1,25 @@
+Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+(1)	The contribution was created in whole or in part by me and I
+	have the right to submit it under the open source license
+	indicated in the file; or
+
+(2)	The contribution is based upon previous work that, to the best
+	of my knowledge, is covered under an appropriate open source
+	license and I have the right under that license to submit that
+	work with modifications, whether created in whole or in part
+	by me, under the same open source license (unless I am
+	permitted to submit under a different license), as indicated
+	in the file; or
+
+(3)	The contribution was provided directly to me by some other
+	person who certified (1), (2) or (3) and I have not modified
+	it.
+
+(4)	I understand and agree that this project and the contribution
+	are public and that a record of the contribution (including all
+	personal information I submit with it, including my sign-off) is
+	maintained indefinitely and may be redistributed consistent with
+	this project or the open source license(s) involved.
diff --git a/application/config/config.php b/application/config/config.php
index 726e3a7..28fc406 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -300,9 +300,9 @@
 | 'cookie_httponly' = Cookie will only be accessible via HTTP(S) (no javascript)
 |
 */
-$config['cookie_prefix']	= "";
-$config['cookie_domain']	= "";
-$config['cookie_path']		= "/";
+$config['cookie_prefix']	= '';
+$config['cookie_domain']	= '';
+$config['cookie_path']		= '/';
 $config['cookie_secure']	= FALSE;
 $config['cookie_httponly'] 	= FALSE;
 
diff --git a/application/config/database.php b/application/config/database.php
index cb6ebad..bb0d87b 100644
--- a/application/config/database.php
+++ b/application/config/database.php
@@ -42,8 +42,9 @@
 |	['username'] The username used to connect to the database
 |	['password'] The password used to connect to the database
 |	['database'] The name of the database you want to connect to
-|	['dbdriver'] The database type. e.g.: mysql.  Currently supported:
-|				 cubrid, interbase, mssql, mysql, mysqli, oci8,
+|	['dbdriver'] The database driver. e.g.: mysqli.
+			Currently supported:
+|				 cubrid, ibase, mssql, mysql, mysqli, oci8,
 |				 odbc, pdo, postgre, sqlite, sqlite3, sqlsrv
 |	['dbprefix'] You can add an optional prefix, which will be added
 |				 to the table name when using the  Query Builder class
diff --git a/readme.rst b/readme.rst
index 7b718fe..b211ad7 100644
--- a/readme.rst
+++ b/readme.rst
@@ -115,6 +115,34 @@
 cannot merge the request. Using the Git-Flow branching model you can create
 new branches for both of these features and send two requests.
 
+Signing
+=======
+You must sign your work, certifying that you either wrote the work or
+otherwise have the right to pass it on to an open source project. git makes
+this trivial as you merely have to use `--signoff` on your commits to your
+CodeIgniter fork.
+
+::
+
+	git commit --signoff
+
+or simply::
+
+	git commit -s
+
+This will sign your commits with the information setup in your git config, e.g.
+
+	Signed-off-by: John Q Public <john.public@example.com>
+
+If you are using Tower there is a "Sign-Off" checkbox in the commit window. You 
+could even alias git commit to use the -s flag so you don’t have to think about 
+it.
+
+By signing your work in this manner, you certify to a "Developer's Certificate 
+or Origin". The current version of this certificate is in the `DCO.txt` file
+in the root of this repository.
+
+
 ************
 How-to Guide
 ************
diff --git a/system/core/Config.php b/system/core/Config.php
index 4b4e5a7..2f6a9e0 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -43,7 +43,7 @@
 	 *
 	 * @var array
 	 */
-	public $config =	array();
+	public $config = array();
 
 	/**
 	 * List of all loaded config files
@@ -102,13 +102,13 @@
 	{
 		$file = ($file === '') ? 'config' : str_replace('.php', '', $file);
 		$found = $loaded = FALSE;
+		
+		$check_locations = defined('ENVIRONMENT')
+			? array(ENVIRONMENT.'/'.$file, $file)
+			: array($file);
 
 		foreach ($this->_config_paths as $path)
 		{
-			$check_locations = defined('ENVIRONMENT')
-				? array(ENVIRONMENT.'/'.$file, $file)
-				: array($file);
-
 			foreach ($check_locations as $location)
 			{
 				$file_path = $path.'config/'.$location.'.php';
@@ -172,7 +172,7 @@
 			{
 				return FALSE;
 			}
-			show_error('The configuration file '.$file.'.php'.' does not exist.');
+			show_error('The configuration file '.$file.'.php does not exist.');
 		}
 
 		return TRUE;
@@ -271,7 +271,7 @@
 	 */
 	public function base_url($uri = '')
 	{
-		return $this->slash_item('base_url').ltrim($this->_uri_string($uri),'/');
+		return $this->slash_item('base_url').ltrim($this->_uri_string($uri), '/');
 	}
 
 	// -------------------------------------------------------------
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 94739c7..d51ee0b 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -820,7 +820,7 @@
 		/*
 		 * Extract and cache variables
 		 *
-		 * You can either set variables using the dedicated $this->load_vars()
+		 * You can either set variables using the dedicated $this->load->vars()
 		 * function or via the second parameter of this function. We'll merge
 		 * the two types and cache them so that views that are embedded within
 		 * other views can have access to these variables.
diff --git a/system/core/Security.php b/system/core/Security.php
index 227217e..b22d2cf 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -395,20 +395,20 @@
 
 			if (preg_match('/<a/i', $str))
 			{
-				$str = preg_replace_callback('#<a\s+([^>]*?)(>|$)#si', array($this, '_js_link_removal'), $str);
+				$str = preg_replace_callback('#<a\s+([^>]*?)(?:>|$)#si', array($this, '_js_link_removal'), $str);
 			}
 
 			if (preg_match('/<img/i', $str))
 			{
-				$str = preg_replace_callback('#<img\s+([^>]*?)(\s?/?>|$)#si', array($this, '_js_img_removal'), $str);
+				$str = preg_replace_callback('#<img\s+([^>]*?)(?:\s?/?>|$)#si', array($this, '_js_img_removal'), $str);
 			}
 
-			if (preg_match('/(script|xss)/i', $str))
+			if (preg_match('/script|xss/i', $str))
 			{
-				$str = preg_replace('#<(/*)(script|xss)(.*?)\>#si', '[removed]', $str);
+				$str = preg_replace('#</*(?:script|xss).*?>#si', '[removed]', $str);
 			}
 		}
-		while($original !== $str);
+		while ($original !== $str);
 
 		unset($original);
 
@@ -683,7 +683,7 @@
 	protected function _js_link_removal($match)
 	{
 		return str_replace($match[1],
-					preg_replace('#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
+					preg_replace('#href=.*?(?:alert\(|alert&\#40;|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
 							'',
 							$this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
 					),
@@ -706,7 +706,7 @@
 	protected function _js_img_removal($match)
 	{
 		return str_replace($match[1],
-					preg_replace('#src=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
+					preg_replace('#src=.*?(?:alert\(|alert&\#40;|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
 							'',
 							$this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
 					),
diff --git a/system/database/DB.php b/system/database/DB.php
index 13a447d..d751325 100644
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -29,8 +29,8 @@
  * Initialize the database
  *
  * @category	Database
- * @author		EllisLab Dev Team
- * @link		http://codeigniter.com/user_guide/database/
+ * @author	EllisLab Dev Team
+ * @link	http://codeigniter.com/user_guide/database/
  * @param 	string
  * @param 	bool	Determines if query builder should be used or not
  */
@@ -47,6 +47,21 @@
 		}
 
 		include($file_path);
+		//make packages contain database config files
+		foreach(get_instance()->load->get_package_paths() as $path)
+		{
+			if ($path !== APPPATH)
+			{
+				if (file_exists ($file_path = $path.'config/'.ENVIRONMENT.'/database.php'))
+				{
+					include ($file_path);
+				}
+				elseif ( file_exists ($file_path = $path.'config/database.php'))
+				{
+					include ($file_path);
+				}
+			}
+		}
 
 		if ( ! isset($db) OR count($db) === 0)
 		{
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 877147c..eca2e68 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -45,7 +45,7 @@
 	public $password;
 	public $hostname;
 	public $database;
-	public $dbdriver		= 'mysql';
+	public $dbdriver		= 'mysqli';
 	public $subdriver;
 	public $dbprefix		= '';
 	public $char_set		= 'utf8';
@@ -78,6 +78,19 @@
 	protected $_protect_identifiers		= TRUE;
 	protected $_reserved_identifiers	= array('*'); // Identifiers that should NOT be escaped
 
+	/**
+	 * The syntax to count rows is slightly different across different
+	 * database engines, so this string appears in each driver and is
+	 * used for the count_all() and count_all_results() functions.
+	 */
+	protected $_count_string = 'SELECT COUNT(*) AS ';
+
+	/**
+	 * Constructor
+	 *
+	 * @param	array
+	 * @return	void
+	 */
 	public function __construct($params)
 	{
 		if (is_array($params))
@@ -856,7 +869,7 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Fetch MySQL Field Names
+	 * Fetch Field Names
 	 *
 	 * @param	string	the table name
 	 * @return	array
@@ -1031,6 +1044,23 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Insert statement
+	 *
+	 * Generates a platform-specific insert string from the supplied data
+	 *
+	 * @param	string	the table name
+	 * @param	array	the insert keys
+	 * @param	array	the insert values
+	 * @return	string
+	 */
+	protected function _insert($table, $keys, $values)
+	{
+		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Generate an update string
 	 *
 	 * @param	string	the table upon which the query will be performed
@@ -1083,6 +1113,41 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Update statement
+	 *
+	 * Generates a platform-specific update string from the supplied data
+	 *
+	 * @param	string	the table name
+	 * @param	array	the update data
+	 * @param	array	the where clause
+	 * @param	array	the orderby clause
+	 * @param	array	the limit clause
+	 * @param	array	the like clause
+	 * @return	string
+	 */
+	protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
+	{
+		foreach ($values as $key => $val)
+		{
+			$valstr[] = $key.' = '.$val;
+		}
+
+		$where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
+
+		if ( ! empty($like))
+		{
+			$where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
+		}
+
+		return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
+			.$where
+			.(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '')
+			.($limit ? ' LIMIT '.$limit : '');
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Tests whether the string has an SQL operator
 	 *
 	 * @param	string
@@ -1172,7 +1237,6 @@
 		return $this->cache_on = FALSE;
 	}
 
-
 	// --------------------------------------------------------------------
 
 	/**
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index 3982885..79e67e0 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -1435,23 +1435,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Insert statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert($table, $keys, $values)
-	{
-		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Validate Insert
 	 *
 	 * This method is used by both insert() and get_compiled_insert() to
@@ -1631,41 +1614,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Update statement
-	 *
-	 * Generates a platform-specific update string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the update data
-	 * @param	array	the where clause
-	 * @param	array	the orderby clause
-	 * @param	array	the limit clause
-	 * @param	array	the like clause
-	 * @return	string
-	 */
-	protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
-	{
-		foreach ($values as $key => $val)
-		{
-			$valstr[] = $key.' = '.$val;
-		}
-
-		$where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
-
-		if ( ! empty($like))
-		{
-			$where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
-		}
-
-		return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
-			.$where
-			.(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '')
-			.($limit ? ' LIMIT '.$limit : '');
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Validate Update
 	 *
 	 * This method is used by both update() and get_compiled_update() to
diff --git a/system/database/DB_result.php b/system/database/DB_result.php
index 991f6ba..ee0b612 100644
--- a/system/database/DB_result.php
+++ b/system/database/DB_result.php
@@ -38,32 +38,74 @@
  */
 class CI_DB_result {
 
-	public $conn_id				= NULL;
-	public $result_id			= NULL;
+	public $conn_id;
+	public $result_id;
 	public $result_array			= array();
 	public $result_object			= array();
 	public $custom_result_object		= array();
 	public $current_row			= 0;
-	public $num_rows			= 0;
-	public $row_data			= NULL;
+	public $num_rows;
+	public $row_data;
 
+	/**
+	 * Constructor
+	 *
+	 * @param	object
+	 * @return	void
+	 */
 	public function __construct(&$driver_object)
 	{
 		$this->conn_id = $driver_object->conn_id;
 		$this->result_id = $driver_object->result_id;
 	}
 
+	// --------------------------------------------------------------------
+
 	/**
-	 * Query result.  Acts as a wrapper function for the following functions.
+	 * Number of rows in the result set
 	 *
-	 * @param	string	can be "object" or "array"
-	 * @return	object
+	 * @return	int
+	 */
+	public function num_rows()
+	{
+		if (is_int($this->num_rows))
+		{
+			return $this->num_rows;
+		}
+		elseif (count($this->result_array) > 0)
+		{
+			return $this->num_rows = count($this->result_array);
+		}
+		elseif (count($this->result_object) > 0)
+		{
+			return $this->num_rows = count($this->result_object);
+		}
+
+		return $this->num_rows = count($this->result_array());
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Query result. Acts as a wrapper function for the following functions.
+	 *
+	 * @param	string	'object', 'array' or a custom class name
+	 * @return	array
 	 */
 	public function result($type = 'object')
 	{
-		if ($type === 'array') return $this->result_array();
-		elseif ($type === 'object') return $this->result_object();
-		else return $this->custom_result_object($type);
+		if ($type === 'array')
+		{
+			return $this->result_array();
+		}
+		elseif ($type === 'object')
+		{
+			return $this->result_object();
+		}
+		else
+		{
+			return $this->custom_result_object($type);
+		}
 	}
 
 	// --------------------------------------------------------------------
@@ -76,19 +118,43 @@
 	 */
 	public function custom_result_object($class_name)
 	{
-		if (array_key_exists($class_name, $this->custom_result_object))
+		if (isset($this->custom_result_object[$class_name]))
 		{
 			return $this->custom_result_object[$class_name];
 		}
-
-		if ($this->result_id === FALSE OR $this->num_rows() === 0)
+		elseif ( ! $this->result_id OR $this->num_rows === 0)
 		{
 			return array();
 		}
 
-		// add the data to the object
+		// Don't fetch the result set again if we already have it
+		$_data = NULL;
+		if (($c = count($this->result_array)) > 0)
+		{
+			$_data = 'result_array';
+		}
+		elseif (($c = count($this->result_object)) > 0)
+		{
+			$_data = 'result_object';
+		}
+
+		if ($_data !== NULL)
+		{
+			for ($i = 0; $i < $c; $i++)
+			{
+				$this->custom_result_object[$class_name][$i] = new $class_name();
+
+				foreach ($this->$_data as $key => $value)
+				{
+					$this->custom_result_object[$class_name][$i]->$key = $value;
+				}
+			}
+
+			return $this->custom_result_object[$class_name];
+		}
+
 		$this->_data_seek(0);
-		$result_object = array();
+		$this->custom_result_object[$class_name] = array();
 
 		while ($row = $this->_fetch_object())
 		{
@@ -98,11 +164,10 @@
 				$object->$key = $value;
 			}
 
-			$result_object[] = $object;
+			$custom_result_object[$class_name][] = $object;
 		}
 
-		// return the array
-		return $this->custom_result_object[$class_name] = $result_object;
+		return $this->custom_result_object[$class_name];
 	}
 
 	// --------------------------------------------------------------------
@@ -119,14 +184,24 @@
 			return $this->result_object;
 		}
 
-		// In the event that query caching is on the result_id variable
-		// will return FALSE since there isn't a valid SQL resource so
-		// we'll simply return an empty array.
-		if ($this->result_id === FALSE OR $this->num_rows() === 0)
+		// In the event that query caching is on, the result_id variable
+		// will not be a valid resource so we'll simply return an empty
+		// array.
+		if ( ! $this->result_id OR $this->num_rows === 0)
 		{
 			return array();
 		}
 
+		if (($c = count($this->result_array)) > 0)
+		{
+			for ($i = 0; $i < $c; $i++)
+			{
+				$this->result_object[$i] = (object) $this->result_array[$i];
+			}
+
+			return $this->result_object;
+		}
+
 		$this->_data_seek(0);
 		while ($row = $this->_fetch_object())
 		{
@@ -139,7 +214,7 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Query result.  "array" version.
+	 * Query result. "array" version.
 	 *
 	 * @return	array
 	 */
@@ -150,14 +225,24 @@
 			return $this->result_array;
 		}
 
-		// In the event that query caching is on the result_id variable
-		// will return FALSE since there isn't a valid SQL resource so
-		// we'll simply return an empty array.
-		if ($this->result_id === FALSE OR $this->num_rows() === 0)
+		// In the event that query caching is on, the result_id variable
+		// will not be a valid resource so we'll simply return an empty
+		// array.
+		if ( ! $this->result_id OR $this->num_rows === 0)
 		{
 			return array();
 		}
 
+		if (($c = count($this->result_object)) > 0)
+		{
+			for ($i = 0; $i < $c; $i++)
+			{
+				$this->result_array[$i] = (array) $this->result_object[$i];
+			}
+
+			return $this->result_array;
+		}
+
 		$this->_data_seek(0);
 		while ($row = $this->_fetch_assoc())
 		{
@@ -239,18 +324,19 @@
 	 */
 	public function custom_row_object($n, $type)
 	{
-		$result = $this->custom_result_object($type);
-		if (count($result) === 0)
+		isset($this->custom_result_object[$type]) OR $this->custom_result_object($type);
+
+		if (count($this->custom_result_object[$type]) === 0)
 		{
 			return NULL;
 		}
 
-		if ($n !== $this->current_row && isset($result[$n]))
+		if ($n !== $this->current_row && isset($this->custom_result_object[$type][$n]))
 		{
 			$this->current_row = $n;
 		}
 
-		return $result[$this->current_row];
+		return $this->custom_result_object[$type][$this->current_row];
 	}
 
 	// --------------------------------------------------------------------
@@ -393,7 +479,6 @@
 	 * operational due to the unavailability of the database resource IDs with
 	 * cached results.
 	 */
-	public function num_rows() { return $this->num_rows; }
 	public function num_fields() { return 0; }
 	public function list_fields() { return array(); }
 	public function field_data() { return array(); }
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
index 7496ee4..a3d0287 100644
--- a/system/database/drivers/cubrid/cubrid_driver.php
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -49,12 +49,6 @@
 	protected $_like_escape_str = '';
 	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
-	 * used for the count_all() and count_all_results() functions.
-	 */
-	protected $_count_string = 'SELECT COUNT(*) AS ';
 	protected $_random_keyword = ' RAND()'; // database specific random keyword
 
 	// CUBRID-specific properties
diff --git a/system/database/drivers/cubrid/cubrid_result.php b/system/database/drivers/cubrid/cubrid_result.php
index 3eb9f7e..4c39781 100644
--- a/system/database/drivers/cubrid/cubrid_result.php
+++ b/system/database/drivers/cubrid/cubrid_result.php
@@ -33,6 +33,7 @@
  * @category	Database
  * @author		Esen Sagynov
  * @link		http://codeigniter.com/user_guide/database/
+ * @since	2.1
  */
 class CI_DB_cubrid_result extends CI_DB_result {
 
@@ -43,7 +44,9 @@
 	 */
 	public function num_rows()
 	{
-		return @cubrid_num_rows($this->result_id);
+		return is_int($this->num_rows)
+			? $this->num_rows
+			: $this->num_rows = @cubrid_num_rows($this->result_id);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/interbase/interbase_driver.php b/system/database/drivers/ibase/ibase_driver.php
similarity index 95%
rename from system/database/drivers/interbase/interbase_driver.php
rename to system/database/drivers/ibase/ibase_driver.php
index 38d3096..c902767 100644
--- a/system/database/drivers/interbase/interbase_driver.php
+++ b/system/database/drivers/ibase/ibase_driver.php
@@ -38,9 +38,9 @@
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
  */
-class CI_DB_interbase_driver extends CI_DB {
+class CI_DB_ibase_driver extends CI_DB {
 
-	public $dbdriver = 'interbase';
+	public $dbdriver = 'ibase';
 
 	// The character used to escape with
 	protected $_escape_char = '"';
@@ -49,13 +49,7 @@
 	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
-	 * used for the count_all() and count_all_results() functions.
-	 */
-	protected $_count_string	= 'SELECT COUNT(*) AS ';
-	protected $_random_keyword	= ' Random()'; // database specific random keyword
+	protected $_random_keyword = ' Random()'; // database specific random keyword
 
 	// Keeps track of the resource for the current transaction
 	protected $trans;
@@ -443,5 +437,5 @@
 
 }
 
-/* End of file interbase_driver.php */
-/* Location: ./system/database/drivers/interbase/interbase_driver.php */
\ No newline at end of file
+/* End of file ibase_driver.php */
+/* Location: ./system/database/drivers/ibase/ibase_driver.php */
\ No newline at end of file
diff --git a/system/database/drivers/interbase/interbase_forge.php b/system/database/drivers/ibase/ibase_forge.php
similarity index 96%
rename from system/database/drivers/interbase/interbase_forge.php
rename to system/database/drivers/ibase/ibase_forge.php
index d1b006e..da75eb9 100644
--- a/system/database/drivers/interbase/interbase_forge.php
+++ b/system/database/drivers/ibase/ibase_forge.php
@@ -32,7 +32,7 @@
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
  */
-class CI_DB_interbase_forge extends CI_DB_forge {
+class CI_DB_ibase_forge extends CI_DB_forge {
 
 	protected $_drop_table	= 'DROP TABLE %s';
 
@@ -190,5 +190,5 @@
 
 }
 
-/* End of file interbase_forge.php */
-/* Location: ./system/database/drivers/interbase/interbase_forge.php */
\ No newline at end of file
+/* End of file ibase_forge.php */
+/* Location: ./system/database/drivers/ibase/ibase_forge.php */
\ No newline at end of file
diff --git a/system/database/drivers/ibase/ibase_result.php b/system/database/drivers/ibase/ibase_result.php
new file mode 100644
index 0000000..fdf7409
--- /dev/null
+++ b/system/database/drivers/ibase/ibase_result.php
@@ -0,0 +1,141 @@
+<?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
+ */
+
+/**
+ * Interbase/Firebird Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category	Database
+ * @author		EllisLab Dev Team
+ * @link		http://codeigniter.com/user_guide/database/
+ * @since	3.0
+ */
+class CI_DB_ibase_result extends CI_DB_result {
+
+	/**
+	 * Number of fields in the result set
+	 *
+	 * @return	int
+	 */
+	public function num_fields()
+	{
+		return @ibase_num_fields($this->result_id);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Fetch Field Names
+	 *
+	 * Generates an array of column names
+	 *
+	 * @return	array
+	 */
+	public function list_fields()
+	{
+		$field_names = array();
+		for ($i = 0, $num_fields = $this->num_fields(); $i < $num_fields; $i++)
+		{
+			$info = ibase_field_info($this->result_id, $i);
+			$field_names[] = $info['name'];
+		}
+
+		return $field_names;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Field data
+	 *
+	 * Generates an array of objects containing field meta-data
+	 *
+	 * @return	array
+	 */
+	public function field_data()
+	{
+		$retval = array();
+		for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
+		{
+			$info = ibase_field_info($this->result_id, $i);
+
+			$retval[$i]			= new stdClass();
+			$retval[$i]->name		= $info['name'];
+			$retval[$i]->type		= $info['type'];
+			$retval[$i]->max_length		= $info['length'];
+			$retval[$i]->primary_key	= 0;
+			$retval[$i]->default		= '';
+		}
+
+		return $retval;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Free the result
+	 *
+	 * @return	void
+	 */
+	public function free_result()
+	{
+		@ibase_free_result($this->result_id);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Result - associative array
+	 *
+	 * Returns the result set as an array
+	 *
+	 * @return	array
+	 */
+	protected function _fetch_assoc()
+	{
+		return @ibase_fetch_assoc($this->result_id, IBASE_FETCH_BLOBS);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Result - object
+	 *
+	 * Returns the result set as an object
+	 *
+	 * @return	object
+	 */
+	protected function _fetch_object()
+	{
+		return @ibase_fetch_object($this->result_id, IBASE_FETCH_BLOBS);
+	}
+
+}
+
+/* End of file ibase_result.php */
+/* Location: ./system/database/drivers/ibase/ibase_result.php */
\ No newline at end of file
diff --git a/system/database/drivers/interbase/interbase_utility.php b/system/database/drivers/ibase/ibase_utility.php
similarity index 90%
rename from system/database/drivers/interbase/interbase_utility.php
rename to system/database/drivers/ibase/ibase_utility.php
index 1642118..d0e84a7 100644
--- a/system/database/drivers/interbase/interbase_utility.php
+++ b/system/database/drivers/ibase/ibase_utility.php
@@ -32,7 +32,7 @@
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
  */
-class CI_DB_interbase_utility extends CI_DB_utility {
+class CI_DB_ibase_utility extends CI_DB_utility {
 
 	protected $_list_databases	= FALSE;
 
@@ -58,5 +58,5 @@
 
 }
 
-/* End of file interbase_utility.php */
-/* Location: ./system/database/drivers/interbase/interbase_utility.php */
\ No newline at end of file
+/* End of file ibase_utility.php */
+/* Location: ./system/database/drivers/ibase/ibase_utility.php */
\ No newline at end of file
diff --git a/system/database/drivers/interbase/index.html b/system/database/drivers/ibase/index.html
similarity index 100%
rename from system/database/drivers/interbase/index.html
rename to system/database/drivers/ibase/index.html
diff --git a/system/database/drivers/interbase/interbase_result.php b/system/database/drivers/interbase/interbase_result.php
deleted file mode 100644
index 5ddb6fa..0000000
--- a/system/database/drivers/interbase/interbase_result.php
+++ /dev/null
@@ -1,260 +0,0 @@
-<?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 3.0
- * @filesource
- */
-
-/**
- * Interbase/Firebird Result Class
- *
- * This class extends the parent result class: CI_DB_result
- *
- * @category	Database
- * @author		EllisLab Dev Team
- * @link		http://codeigniter.com/user_guide/database/
- */
-class CI_DB_interbase_result extends CI_DB_result {
-
-	public $num_rows;
-
-	/**
-	 * Number of rows in the result set
-	 *
-	 * @return	int
-	 */
-	public function num_rows()
-	{
-		if (is_int($this->num_rows))
-		{
-			return $this->num_rows;
-		}
-
-		// Get the results so that you can get an accurate rowcount
-		$this->result();
-
-		return $this->num_rows;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Number of fields in the result set
-	 *
-	 * @return	int
-	 */
-	public function num_fields()
-	{
-		return @ibase_num_fields($this->result_id);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Fetch Field Names
-	 *
-	 * Generates an array of column names
-	 *
-	 * @return	array
-	 */
-	public function list_fields()
-	{
-		$field_names = array();
-		for ($i = 0, $num_fields = $this->num_fields(); $i < $num_fields; $i++)
-		{
-			$info = ibase_field_info($this->result_id, $i);
-			$field_names[] = $info['name'];
-		}
-
-		return $field_names;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Field data
-	 *
-	 * Generates an array of objects containing field meta-data
-	 *
-	 * @return	array
-	 */
-	public function field_data()
-	{
-		$retval = array();
-		for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
-		{
-			$info = ibase_field_info($this->result_id, $i);
-
-			$retval[$i]			= new stdClass();
-			$retval[$i]->name		= $info['name'];
-			$retval[$i]->type		= $info['type'];
-			$retval[$i]->max_length		= $info['length'];
-			$retval[$i]->primary_key	= 0;
-			$retval[$i]->default		= '';
-		}
-
-		return $retval;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Free the result
-	 *
-	 * @return	void
-	 */
-	public function free_result()
-	{
-		@ibase_free_result($this->result_id);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Result - associative array
-	 *
-	 * Returns the result set as an array
-	 *
-	 * @return	array
-	 */
-	protected function _fetch_assoc()
-	{
-		if (($row = @ibase_fetch_assoc($this->result_id, IBASE_FETCH_BLOBS)) !== FALSE)
-		{
-			//Increment row count
-			$this->num_rows++;
-		}
-
-		return $row;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Result - object
-	 *
-	 * Returns the result set as an object
-	 *
-	 * @return	object
-	 */
-	protected function _fetch_object()
-	{
-		if (($row = @ibase_fetch_object($this->result_id, IBASE_FETCH_BLOBS)) !== FALSE)
-		{
-			//Increment row count
-			$this->num_rows++;
-		}
-
-		return $row;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Query result.  "object" version.
-	 *
-	 * @return	object
-	 */
-	public function result_object()
-	{
-		if (count($this->result_object) === $this->num_rows)
-		{
-			return $this->result_object;
-		}
-
-		// Convert result array to object so that
-		// We don't have to get the result again
-		if (($c = count($this->result_array)) > 0)
-		{
-			for ($i = 0; $i < $c; $i++)
-			{
-				$this->result_object[$i] = (object) $this->result_array[$i];
-			}
-
-			return $this->result_object;
-		}
-
-		// In the event that query caching is on the result_id variable
-		// will return FALSE since there isn't a valid SQL resource so
-		// we'll simply return an empty array.
-		if ($this->result_id === FALSE)
-		{
-			return array();
-		}
-
-		$this->num_rows = 0;
-		while ($row = $this->_fetch_object())
-		{
-			$this->result_object[] = $row;
-		}
-
-		return $this->result_object;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Query result.  "array" version.
-	 *
-	 * @return	array
-	 */
-	public function result_array()
-	{
-		if (count($this->result_array) === $this->num_rows)
-		{
-			return $this->result_array;
-		}
-
-		// Since the object and array are really similar, just case
-		// the result object to an array  if need be
-		if (($c = count($this->result_object)) > 0)
-		{
-			for ($i = 0; $i < $c; $i++)
-			{
-				$this->result_array[$i] = (array) $this->result_object[$i];
-			}
-
-			return $this->result_array;
-		}
-
-		// In the event that query caching is on the result_id variable
-		// will return FALSE since there isn't a valid SQL resource so
-		// we'll simply return an empty array.
-		if ($this->result_id === FALSE)
-		{
-			return array();
-		}
-
-		$this->num_rows = 0;
-		while ($row = $this->_fetch_assoc())
-		{
-			$this->result_array[] = $row;
-		}
-
-		return $this->result_array;
-	}
-
-}
-
-/* End of file interbase_result.php */
-/* Location: ./system/database/drivers/interbase/interbase_result.php */
\ No newline at end of file
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 3026b36..1714704 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -49,12 +49,6 @@
 	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
-	 * used for the count_all() and count_all_results() methods.
-	 */
-	protected $_count_string = 'SELECT COUNT(*) AS ';
 	protected $_random_keyword = ' NEWID()';
 
 	// MSSQL-specific properties
diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php
index 5929306..62996aa 100644
--- a/system/database/drivers/mssql/mssql_result.php
+++ b/system/database/drivers/mssql/mssql_result.php
@@ -33,6 +33,7 @@
  * @category	Database
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
+ * @since	1.3
  */
 class CI_DB_mssql_result extends CI_DB_result {
 
@@ -43,7 +44,9 @@
 	 */
 	public function num_rows()
 	{
-		return @mssql_num_rows($this->result_id);
+		return is_int($this->num_rows)
+			? $this->num_rows
+			: $this->num_rows = @mssql_num_rows($this->result_id);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index d11f015..29db904 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -49,12 +49,6 @@
 	protected $_like_escape_str = '';
 	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
-	 * used for the count_all() and count_all_results() functions.
-	 */
-	protected $_count_string = 'SELECT COUNT(*) AS ';
 	protected $_random_keyword = ' RAND()'; // database specific random keyword
 
 	/**
diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php
index 14d6d07..b507f79 100644
--- a/system/database/drivers/mysql/mysql_result.php
+++ b/system/database/drivers/mysql/mysql_result.php
@@ -33,6 +33,7 @@
  * @category	Database
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
+ * @since	1.0
  */
 class CI_DB_mysql_result extends CI_DB_result {
 
@@ -43,7 +44,9 @@
 	 */
 	public function num_rows()
 	{
-		return @mysql_num_rows($this->result_id);
+		return is_int($this->num_rows)
+			? $this->num_rows
+			: $this->num_rows = @mysql_num_rows($this->result_id);
 	}
 
 	// --------------------------------------------------------------------
@@ -132,7 +135,7 @@
 	 */
 	protected function _data_seek($n = 0)
 	{
-		return mysql_data_seek($this->result_id, $n);
+		return @mysql_data_seek($this->result_id, $n);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index d1581bf..be61aab 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -49,12 +49,6 @@
 	protected $_like_escape_str = '';
 	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
-	 * used for the count_all() and count_all_results() functions.
-	 */
-	protected $_count_string = 'SELECT COUNT(*) AS ';
 	protected $_random_keyword = ' RAND()'; // database specific random keyword
 
 	/**
diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php
index 9b4d494..bf96ed9 100644
--- a/system/database/drivers/mysqli/mysqli_result.php
+++ b/system/database/drivers/mysqli/mysqli_result.php
@@ -33,6 +33,7 @@
  * @category	Database
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
+ * @since	1.3
  */
 class CI_DB_mysqli_result extends CI_DB_result {
 
@@ -43,7 +44,9 @@
 	 */
 	public function num_rows()
 	{
-		return $this->result_id->num_rows;
+		return is_int($this->num_rows)
+			? $this->num_rows
+			: $this->num_rows = $this->result_id->num_rows;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php
index 6fb6c81..faa295e 100644
--- a/system/database/drivers/oci8/oci8_result.php
+++ b/system/database/drivers/oci8/oci8_result.php
@@ -33,6 +33,7 @@
  * @category	Database
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
+ * @since	1.4.1
  */
 class CI_DB_oci8_result extends CI_DB_result {
 
@@ -41,14 +42,16 @@
 	public $limit_used;
 	public $commit_mode;
 
-	/* Overwriting the parent here, so we have a way to know if it's
-	 * already called or not:
+	/**
+	 * Constructor
+	 *
+	 * @param	object
+	 * @return	void
 	 */
-	public $num_rows;
-
 	public function __construct(&$driver_object)
 	{
 		parent::__construct($driver_object);
+
 		$this->stmt_id = $driver_object->stmt_id;
 		$this->curs_id = $driver_object->curs_id;
 		$this->limit_used = $driver_object->limit_used;
@@ -56,33 +59,6 @@
 		$driver_object->stmt_id = FALSE;
 	}
 
-	/**
-	 * Number of rows in the result set.
-	 *
-	 * Oracle doesn't have a graceful way to return the number of rows
-	 * so we have to use what amounts to a hack.
-	 *
-	 * @return	int
-	 */
-	public function num_rows()
-	{
-		if ( ! is_int($this->num_rows))
-		{
-			if (count($this->result_array) > 0)
-			{
-				return $this->num_rows = count($this->result_array);
-			}
-			elseif (count($this->result_object) > 0)
-			{
-				return $this->num_rows = count($this->result_object);
-			}
-
-			return $this->num_rows = count($this->result_array());
-		}
-
-		return $this->num_rows;
-	}
-
 	// --------------------------------------------------------------------
 
 	/**
@@ -202,444 +178,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Query result. Array version.
-	 *
-	 * @return	array
-	 */
-	public function result_array()
-	{
-		if (count($this->result_array) > 0)
-		{
-			return $this->result_array;
-		}
-		elseif (count($this->result_object) > 0)
-		{
-			for ($i = 0, $c = count($this->result_object); $i < $c; $i++)
-			{
-				$this->result_array[$i] = (array) $this->result_object[$i];
-			}
-
-			return $this->result_array;
-		}
-		elseif (is_array($this->row_data))
-		{
-			if (count($this->row_data) === 0)
-			{
-				return $this->result_array;
-			}
-			else
-			{
-				$row_index = count($this->row_data);
-			}
-		}
-		else
-		{
-			$row_index = 0;
-			$this->row_data = array();
-		}
-
-		$row = NULL;
-		while ($row = $this->_fetch_assoc())
-		{
-			$this->row_data[$row_index++] = $row;
-		}
-
-		return $this->result_array = $this->row_data;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Query result. "object" version.
-	 *
-	 * @return	array
-	 */
-	public function result_object()
-	{
-		if (count($this->result_object) > 0)
-		{
-			return $this->result_object;
-		}
-		elseif (count($this->result_array) > 0)
-		{
-			for ($i = 0, $c = count($this->result_array); $i < $c; $i++)
-			{
-				$this->result_object[] = (object) $this->result_array[$i];
-			}
-
-			return $this->result_object;
-		}
-		elseif (is_array($this->row_data))
-		{
-			if (count($this->row_data) === 0)
-			{
-				return $this->result_object;
-			}
-			else
-			{
-				$row_index = count($this->row_data);
-				for ($i = 0; $i < $row_index; $i++)
-				{
-					$this->result_object[$i] = (object) $this->row_data[$i];
-				}
-			}
-		}
-		else
-		{
-			$row_index = 0;
-			$this->row_data = array();
-		}
-
-		$row = NULL;
-		while ($row = $this->_fetch_object())
-		{
-			$this->row_data[$row_index] = (array) $row;
-			$this->result_object[$row_index++] = $row;
-		}
-
-		return $this->result_object;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Query result. Custom object version.
-	 *
-	 * @param	string	class name used to instantiate rows to
-	 * @return	array
-	 */
-	public function custom_result_object($class_name)
-	{
-		if (isset($this->custom_result_object[$class_name]))
-		{
-			return $this->custom_result_object[$class_name];
-		}
-
-		if ( ! class_exists($class_name) OR $this->result_id === FALSE OR $this->num_rows() === 0)
-		{
-			return array();
-		}
-
-		/* Even if we didn't have result_array or result_object
-		 * set prior to custom_result_object() being called,
-		 * num_rows() has already done so.
-		 * Pass by reference, as we don't know how
-		 * large it might be and we don't want 1000 row
-		 * sets being copied.
-		 */
-		if (count($this->result_array) > 0)
-		{
-			$data = &$this->result_array;
-		}
-		elseif (count($this->result_object) > 0)
-		{
-			$data = &$this->result_object;
-		}
-
-		$this->custom_result_object[$class_name] = array();
-		for ($i = 0, $c = count($data); $i < $c; $i++)
-		{
-			$this->custom_result_object[$class_name][$i] = new $class_name();
-			foreach ($data[$i] as $key => $value)
-			{
-				$this->custom_result_object[$class_name][$i]->$key = $value;
-			}
-		}
-
-		return $this->custom_result_object[$class_name];
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Single row result.
-	 *
-	 * Acts as a wrapper for row_object(), row_array()
-	 * and custom_row_object(). Also used by first_row(), next_row()
-	 * and previous_row().
-	 *
-	 * @param	int	row index
-	 * @param	string	('object', 'array' or a custom class name)
-	 * @return	mixed	whatever was passed to the second parameter
-	 */
-	public function row($n = 0, $type = 'object')
-	{
-		if ($type === 'object')
-		{
-			return $this->row_object($n);
-		}
-		elseif ($type === 'array')
-		{
-			return $this->row_array($n);
-		}
-
-		return $this->custom_row_object($n, $type);
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Single row result. Array version.
-	 *
-	 * @param	int	row index
-	 * @return	array
-	 */
-	public function row_array($n = 0)
-	{
-		// Make sure $n is not a string
-		if ( ! is_int($n))
-		{
-			$n = (int) $n;
-		}
-
-		/* If row_data is initialized, it means that we've already tried
-		 * (at least) to fetch some data, so ... check if we already have
-		 * this row.
-		*/
-		if (is_array($this->row_data))
-		{
-			/* If we already have row_data[$n] - return it.
-			 *
-			 * If we enter the elseif, there's a number of reasons to
-			 * return an empty array:
-			 *
-			 *	- count($this->row_data) === 0 means there are no results
-			 *	- num_rows being set, result_array and/or result_object
-			 *	  having count() > 0 means that we've already fetched all
-			 *	  data and $n is greater than our highest row index available
-			 *	- $n < $this->current_row means that if such row existed,
-			 *	  we would've already returned it, therefore $n is an
-			 *	  invalid index
-			 */
-			if (isset($this->row_data[$n])) // We already have this row
-			{
-				$this->current_row = $n;
-				return $this->row_data[$n];
-			}
-			elseif (count($this->row_data) === 0 OR is_int($this->num_rows)
-				OR count($this->result_array) > 0 OR count($this->result_object) > 0
-				OR $n < $this->current_row)
-			{
-				// No such row exists
-				return NULL;
-			}
-
-			// Get the next row index that would actually need to be fetched
-			$current_row = ($this->current_row < count($this->row_data)) ? count($this->row_data) : $this->current_row + 1;
-		}
-		else
-		{
-			$current_row = $this->current_row = 0;
-			$this->row_data = array();
-		}
-
-		/* Fetch more data, if available
-		 *
-		 * NOTE: Operator precedence is important here, if you change
-		 *	 'AND' with '&&' - it WILL BREAK the results, as
-		 *	 $row will be assigned the scalar value of both
-		 *	 expressions!
-		 */
-		while ($row = $this->_fetch_assoc() AND $current_row <= $n)
-		{
-			$this->row_data[$current_row++] = $row;
-		}
-
-		// This would mean that there's no (more) data to fetch
-		if ( ! is_array($this->row_data) OR ! isset($this->row_data[$n]))
-		{
-			// Cache what we already have
-			if (is_array($this->row_data))
-			{
-				$this->num_rows = count($this->row_data);
-				/* Usually, row_data could have less elements than result_array,
-				 * but at this point - they should be exactly the same.
-				 */
-				$this->result_array = $this->row_data;
-			}
-			else
-			{
-				$this->num_rows = 0;
-			}
-
-			return NULL;
-		}
-
-		$this->current_row = $n;
-		return $this->row_data[$n];
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Single row result. Object version.
-	 *
-	 * @param	int	row index
-	 * @return	mixed	object if row found; empty array if not
-	 */
-	public function row_object($n = 0)
-	{
-		// Make sure $n is not a string
-		if ( ! is_int($n))
-		{
-			$n = (int) $n;
-		}
-		/* Logic here is exactly the same as in row_array,
-		 * except we have to cast row_data[$n] to an object.
-		 *
-		 * If we already have result_object though - we can
-		 * directly return from it.
-		 */
-		if (isset($this->result_object[$n]))
-		{
-			$this->current_row = $n;
-			// Set this, if not already done.
-			if ( ! is_int($this->num_rows))
-			{
-				$this->num_rows = count($this->result_object);
-			}
-
-			return $this->result_object[$n];
-		}
-
-		$row = $this->row_array($n);
-		// Cast only if the row exists
-		if (count($row) > 0)
-		{
-			$this->current_row = $n;
-			return (object) $row;
-		}
-
-		return NULL;
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Single row result. Custom object version.
-	 *
-	 * @param	int	row index
-	 * @param	string	custom class name
-	 * @return	mixed	custom object if row found; empty array otherwise
-	 */
-	public function custom_row_object($n = 0, $class_name)
-	{
-		// Make sure $n is not a string
-		if ( ! is_int($n))
-		{
-			$n = (int) $n;
-		}
-
-		if (array_key_exists($class_name, $this->custom_result_object))
-		{
-			/* We already have a the whole result set with this class_name,
-			 * return the specified row if it exists, and an empty array if
-			 * it doesn't.
-			 */
-			if (isset($this->custom_result_object[$class_name][$n]))
-			{
-				$this->current_row = $n;
-				return $this->custom_result_object[$class_name][$n];
-			}
-			else
-			{
-				return NULL;
-			}
-		}
-		elseif ( ! class_exists($class_name)) // No such class exists
-		{
-			return NULL;
-		}
-
-		$row = $this->row_array($n);
-		// A non-array would mean that the row doesn't exist
-		if ( ! is_array($row))
-		{
-			return NULL;
-		}
-
-		// Convert to the desired class and return
-		$row_object = new $class_name();
-		foreach ($row as $key => $value)
-		{
-			$row_object->$key = $value;
-		}
-
-		$this->current_row = $n;
-		return $row_object;
-	}
-
-	// --------------------------------------------------------------------
-
-	/* First row result.
-	 *
-	 * @param	string	('object', 'array' or a custom class name)
-	 * @return	mixed	whatever was passed to the second parameter
-	 */
-	public function first_row($type = 'object')
-	{
-		return $this->row(0, $type);
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Last row result.
-	 *
-	 * @param	string	('object', 'array' or a custom class name)
-	 * @return	mixed	whatever was passed to the second parameter
-	 */
-	public function last_row($type = 'object')
-	{
-		$result = &$this->result($type);
-		if ( ! isset($this->num_rows))
-		{
-			$this->num_rows = count($result);
-		}
-		$this->current_row = $this->num_rows - 1;
-		return $result[$this->current_row];
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Next row result.
-	 *
-	 * @param	string	('object', 'array' or a custom class name)
-	 * @return	mixed	whatever was passed to the second parameter
-	 */
-	public function next_row($type = 'object')
-	{
-		if (is_array($this->row_data))
-		{
-			$count = count($this->row_data);
-			if ($this->current_row > $count OR ($this->current_row === 0 && $count === 0))
-			{
-				$n = $count;
-			}
-			else
-			{
-				$n = $this->current_row + 1;
-			}
-		}
-		else
-		{
-			$n = 0;
-		}
-
-		return $this->row($n, $type);
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Previous row result.
-	 *
-	 * @param	string	('object', 'array' or a custom class name)
-	 * @return	mixed	whatever was passed to the second parameter
-	 */
-	public function previous_row($type = 'object')
-	{
-		$n = ($this->current_row !== 0) ? $this->current_row - 1 : 0;
-		return $this->row($n, $type);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Data Seek
 	 *
 	 * Moves the internal pointer to the desired offset. We call
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index bd57592..8f0a474 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -49,12 +49,6 @@
 	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
-	 * used for the count_all() and count_all_results() functions.
-	 */
-	protected $_count_string = 'SELECT COUNT(*) AS ';
 	protected $_random_keyword;
 
 	public function __construct($params)
diff --git a/system/database/drivers/odbc/odbc_result.php b/system/database/drivers/odbc/odbc_result.php
index 227fe4f..1d998be 100644
--- a/system/database/drivers/odbc/odbc_result.php
+++ b/system/database/drivers/odbc/odbc_result.php
@@ -33,11 +33,10 @@
  * @category	Database
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
+ * @since	1.3
  */
 class CI_DB_odbc_result extends CI_DB_result {
 
-	public $num_rows;
-
 	/**
 	 * Number of rows in the result set
 	 *
@@ -49,16 +48,26 @@
 		{
 			return $this->num_rows;
 		}
-
-		// Work-around for ODBC subdrivers that don't support num_rows()
-		if (($this->num_rows = @odbc_num_rows($this->result_id)) === -1)
+		elseif (($this->num_rows = @odbc_num_rows($this->result_id)) !== -1)
 		{
-			$this->num_rows = count($this->result_array());
+			return $this->num_rows;
 		}
 
-		return $this->num_rows;
+		// Work-around for ODBC subdrivers that don't support num_rows()
+		if (count($this->result_array) > 0)
+		{
+			return $this->num_rows = count($this->result_array);
+		}
+		elseif (count($this->result_object) > 0)
+		{
+			return $this->num_rows = count($this->result_object);
+		}
+
+		return $this->num_rows = count($this->result_array());
 	}
 
+	// --------------------------------------------------------------------
+
 	/**
 	 * Number of fields in the result set
 	 *
@@ -146,9 +155,7 @@
 	 */
 	protected function _fetch_assoc()
 	{
-		return function_exists('odbc_fetch_array')
-			? odbc_fetch_array($this->result_id)
-			: $this->_odbc_fetch_array($this->result_id);
+		return odbc_fetch_array($this->result_id);
 	}
 
 	// --------------------------------------------------------------------
@@ -162,53 +169,29 @@
 	 */
 	protected function _fetch_object()
 	{
-		return function_exists('odbc_fetch_object')
-			? odbc_fetch_object($this->result_id)
-			: $this->_odbc_fetch_object($this->result_id);
+		return odbc_fetch_object($this->result_id);
 	}
 
-	// --------------------------------------------------------------------
+}
 
+// --------------------------------------------------------------------
+
+if ( ! function_exists('odbc_fetch_array'))
+{
 	/**
-	 * Result - object
+	 * ODBC Fetch array
 	 *
-	 * subsititutes the odbc_fetch_object function when
-	 * not available (odbc_fetch_object requires unixODBC)
+	 * Emulates the native odbc_fetch_array() function when
+	 * it is not available (odbc_fetch_array() requires unixODBC)
 	 *
-	 * @return	object
-	 */
-	protected function _odbc_fetch_object(& $odbc_result)
-	{
-		$rs = array();
-		if ( ! odbc_fetch_into($odbc_result, $rs))
-		{
-			return FALSE;
-		}
-
-		$rs_obj = new stdClass();
-		foreach ($rs as $k => $v)
-		{
-			$field_name = odbc_field_name($odbc_result, $k+1);
-			$rs_obj->$field_name = $v;
-		}
-
-		return $rs_obj;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Result - array
-	 *
-	 * subsititutes the odbc_fetch_array function when
-	 * not available (odbc_fetch_array requires unixODBC)
-	 *
+	 * @param	resource
+	 * @param	int
 	 * @return	array
 	 */
-	protected function _odbc_fetch_array(& $odbc_result)
+	function odbc_fetch_array(& $result, $rownumber = 1)
 	{
 		$rs = array();
-		if ( ! odbc_fetch_into($odbc_result, $rs))
+		if ( ! odbc_fetch_into($result, $rs, $rownumber))
 		{
 			return FALSE;
 		}
@@ -216,83 +199,45 @@
 		$rs_assoc = array();
 		foreach ($rs as $k => $v)
 		{
-			$field_name = odbc_field_name($odbc_result, $k+1);
+			$field_name = odbc_field_name($result, $k+1);
 			$rs_assoc[$field_name] = $v;
 		}
 
 		return $rs_assoc;
 	}
+}
 
-	// --------------------------------------------------------------------
+// --------------------------------------------------------------------
 
+if ( ! function_exists('odbc_fetch_object'))
+{
 	/**
-	 * Query result. Array version.
+	 * ODBC Fetch object
 	 *
-	 * @return	array
-	 */
-	public function result_array()
-	{
-		if (count($this->result_array) > 0)
-		{
-			return $this->result_array;
-		}
-		elseif (($c = count($this->result_object)) > 0)
-		{
-			for ($i = 0; $i < $c; $i++)
-			{
-				$this->result_array[$i] = (array) $this->result_object[$i];
-			}
-		}
-		elseif ($this->result_id === FALSE)
-		{
-			return array();
-		}
-		else
-		{
-			while ($row = $this->_fetch_assoc())
-			{
-				$this->result_array[] = $row;
-			}
-		}
-
-		return $this->result_array;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Query result. Object version.
+	 * Emulates the native odbc_fetch_object() function when
+	 * it is not available.
 	 *
-	 * @return	array
+	 * @param	resource
+	 * @param	int
+	 * @return	object
 	 */
-	public function result_object()
+	function odbc_fetch_object(& $result, $rownumber = 1)
 	{
-		if (count($this->result_object) > 0)
+		$rs = array();
+		if ( ! odbc_fetch_into($result, $rs, $rownumber))
 		{
-			return $this->result_object;
-		}
-		elseif (($c = count($this->result_array)) > 0)
-		{
-			for ($i = 0; $i < $c; $i++)
-			{
-				$this->result_object[$i] = (object) $this->result_array[$i];
-			}
-		}
-		elseif ($this->result_id === FALSE)
-		{
-			return array();
-		}
-		else
-		{
-			while ($row = $this->_fetch_object())
-			{
-				$this->result_object[] = $row;
-			}
+			return FALSE;
 		}
 
-		return $this->result_object;
+		$rs_object = new stdClass();
+		foreach ($rs as $k => $v)
+		{
+			$field_name = odbc_field_name($result, $k+1);
+			$rs_object->$field_name = $v;
+		}
+
+		return $rs_object;
 	}
-
 }
 
 /* End of file odbc_result.php */
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index a54c1b9..dcae1a5 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -49,12 +49,6 @@
 	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
-	 * used for the count_all() and count_all_results() functions.
-	 */
-	protected $_count_string = 'SELECT COUNT(*) AS ';
 	protected $_random_keyword;
 
 	public $trans_enabled = FALSE;
diff --git a/system/database/drivers/pdo/pdo_result.php b/system/database/drivers/pdo/pdo_result.php
index 0b8937c..b45e741 100644
--- a/system/database/drivers/pdo/pdo_result.php
+++ b/system/database/drivers/pdo/pdo_result.php
@@ -21,7 +21,7 @@
  * @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 2.1.0
+ * @since		Version 1.0
  * @filesource
  */
 
@@ -33,72 +33,35 @@
  * @category	Database
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
+ * @since	2.1
  */
 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
 	 *
 	 * @return	int
 	 */
 	public function num_rows()
 	{
-		if (empty($this->result_id) OR ! is_object($this->result_id))
+		if (is_int($this->num_rows))
 		{
-			// invalid result handler
-			return 0;
+			return $this->num_rows;
 		}
-		elseif (($num_rows = $this->result_id->rowCount()) && $num_rows > 0)
+		elseif (count($this->result_array) > 0)
 		{
-			// If rowCount return something, we're done.
-			return $num_rows;
+			return $this->num_rows = count($this->result_array);
+		}
+		elseif (count($this->result_object) > 0)
+		{
+			return $this->num_rows = count($this->result_object);
+		}
+		elseif (($num_rows = $this->result_id->rowCount()) > 0)
+		{
+			return $this->num_rows = $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
-	 *
-	 * @return	mixed
-	 */
-	public 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');
-
-		// Initial value
-		$this->result_assoc = array() and $this->result_object = array();
-
-		// Fetch the result
-		while ($row = $this->_fetch_assoc())
-		{
-			$this->result_assoc[] = $row;
-			$this->result_object[] = (object) $row;
-		}
-
-		// Save this as buffer and marked the fetch flag
-		$this->result_array = $this->result_assoc;
-		$this->is_fetched = TRUE;
-
-		return $this->result_assoc;
+		return $this->num_rows = count($this->result_array());
 	}
 
 	// --------------------------------------------------------------------
@@ -124,12 +87,14 @@
 	 */
 	public function list_fields()
 	{
-		if ($this->db->db_debug)
+		$field_names = array();
+		for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
 		{
-			return $this->db->display_error('db_unsuported_feature');
+			$field_names[$i] = @$this->result_id->getColumnMeta();
+			$field_names[$i] = $field_names[$i]['name'];
 		}
 
-		return FALSE;
+		return $field_names;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index e73122b..20b7867 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -48,12 +48,6 @@
 	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
-	 * used for the count_all() and count_all_results() functions.
-	 */
-	protected $_count_string = 'SELECT COUNT(*) AS ';
 	protected $_random_keyword = ' RANDOM()'; // database specific random keyword
 
 	/**
diff --git a/system/database/drivers/postgre/postgre_result.php b/system/database/drivers/postgre/postgre_result.php
index f913bc9..515acd2 100644
--- a/system/database/drivers/postgre/postgre_result.php
+++ b/system/database/drivers/postgre/postgre_result.php
@@ -33,6 +33,7 @@
  * @category	Database
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
+ * @since	1.3
  */
 class CI_DB_postgre_result extends CI_DB_result {
 
@@ -43,7 +44,9 @@
 	 */
 	public function num_rows()
 	{
-		return @pg_num_rows($this->result_id);
+		return is_int($this->num_rows)
+			? $this->num_rows
+			: $this->num_rows = @pg_num_rows($this->result_id);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index 87be7a5..19824db 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -49,12 +49,6 @@
 	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
-	 * used for the count_all() and count_all_results() functions.
-	 */
-	protected $_count_string = 'SELECT COUNT(*) AS ';
 	protected $_random_keyword = ' Random()'; // database specific random keyword
 
 	/**
diff --git a/system/database/drivers/sqlite/sqlite_result.php b/system/database/drivers/sqlite/sqlite_result.php
index 741dc9d..307dec5 100644
--- a/system/database/drivers/sqlite/sqlite_result.php
+++ b/system/database/drivers/sqlite/sqlite_result.php
@@ -33,6 +33,7 @@
  * @category	Database
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
+ * @since	1.3
  */
 class CI_DB_sqlite_result extends CI_DB_result {
 
@@ -43,7 +44,9 @@
 	 */
 	public function num_rows()
 	{
-		return @sqlite_num_rows($this->result_id);
+		return is_int($this->num_rows)
+			? $this->num_rows
+			: $this->num_rows = @sqlite_num_rows($this->result_id);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php
index 1c6533f..cc35d31 100644
--- a/system/database/drivers/sqlite3/sqlite3_driver.php
+++ b/system/database/drivers/sqlite3/sqlite3_driver.php
@@ -50,12 +50,6 @@
 	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
-	 * used for the count_all() and count_all_results() functions.
-	 */
-	protected $_count_string = 'SELECT COUNT(*) AS ';
 	protected $_random_keyword = ' RANDOM()';
 
 	/**
diff --git a/system/database/drivers/sqlite3/sqlite3_result.php b/system/database/drivers/sqlite3/sqlite3_result.php
index 946b365..4d59bb0 100644
--- a/system/database/drivers/sqlite3/sqlite3_result.php
+++ b/system/database/drivers/sqlite3/sqlite3_result.php
@@ -33,33 +33,14 @@
  * @category	Database
  * @author	Andrey Andreev
  * @link	http://codeigniter.com/user_guide/database/
+ * @since	3.0
  */
 class CI_DB_sqlite3_result extends CI_DB_result {
 
-	// Overwriting the parent here, so we have a way to know if it's already set
-	public $num_rows;
-
 	// num_fields() might be called multiple times, so we'll use this one to cache it's result
 	protected $_num_fields;
 
 	/**
-	 * Number of rows in the result set
-	 *
-	 * @return	int
-	 */
-	public function num_rows()
-	{
-		/* The SQLite3 driver doesn't have a graceful way to do this,
-		 * so we'll have to do it on our own.
-		 */
-		return is_int($this->num_rows)
-			? $this->num_rows
-			: $this->num_rows = count($this->result_array());
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Number of fields in the result set
 	 *
 	 * @return	int
@@ -165,436 +146,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Query result. "array" version.
-	 *
-	 * return	array
-	 */
-	public function result_array()
-	{
-		if (count($this->result_array) > 0)
-		{
-			return $this->result_array;
-		}
-		elseif (is_array($this->row_data))
-		{
-			if (count($this->row_data) === 0)
-			{
-				return $this->result_array;
-			}
-			else
-			{
-				$row_index = count($this->row_data);
-			}
-		}
-		else
-		{
-			$row_index = 0;
-			$this->row_data = array();
-		}
-
-		$row = NULL;
-		while ($row = $this->_fetch_assoc())
-		{
-			$this->row_data[$row_index++] = $row;
-		}
-
-		return $this->result_array = $this->row_data;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Query result. "object" version.
-	 *
-	 * @return	array
-	 */
-	public function result_object()
-	{
-		if (count($this->result_object) > 0)
-		{
-			return $this->result_object;
-		}
-		elseif (count($this->result_array) > 0)
-		{
-			for ($i = 0, $c = count($this->result_array); $i < $c; $i++)
-			{
-				$this->result_object[] = (object) $this->result_array[$i];
-			}
-
-			return $this->result_object;
-		}
-		elseif (is_array($this->row_data))
-		{
-			if (count($this->row_data) === 0)
-			{
-				return $this->result_object;
-			}
-			else
-			{
-				$row_index = count($this->row_data);
-				for ($i = 0; $i < $row_index; $i++)
-				{
-					$this->result_object[$i] = (object) $this->row_data[$i];
-				}
-			}
-		}
-		else
-		{
-			$row_index = 0;
-			$this->row_data = array();
-		}
-
-		$row = NULL;
-		while ($row = $this->_fetch_assoc())
-		{
-			$this->row_data[$row_index] = $row;
-			$this->result_object[$row_index++] = (object) $row;
-		}
-
-		$this->result_array = $this->row_data;
-
-		/* As described for the num_rows() method - there's no easy
-		 * way to get the number of rows selected. Our work-around
-		 * solution (as in here as well) first checks if result_array
-		 * exists and returns its count. It doesn't however check for
-		 * custom_object_result, so - do it here.
-		 */
-		if ( ! is_int($this->num_rows))
-		{
-			$this->num_rows = count($this->result_object);
-		}
-
-		return $this->result_object;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Query result. Custom object version.
-	 *
-	 * @param	string	class name used to instantiate rows to
-	 * @return	array
-	 */
-	public function custom_result_object($class_name)
-	{
-		if (array_key_exists($class_name, $this->custom_result_object))
-		{
-			return $this->custom_result_object[$class_name];
-		}
-
-		if ( ! class_exists($class_name) OR ! is_object($this->result_id) OR $this->num_rows() === 0)
-		{
-			return array();
-		}
-
-		/* Even if result_array hasn't been set prior to custom_result_object being called,
-		 * num_rows() has done it.
-		*/
-		$data = &$this->result_array;
-
-		$result_object = array();
-		for ($i = 0, $c = count($data); $i < $c; $i++)
-		{
-			$result_object[$i] = new $class_name();
-			foreach ($data[$i] as $key => $value)
-			{
-				$result_object[$i]->$key = $value;
-			}
-		}
-
-		/* As described for the num_rows() method - there's no easy
-		 * way to get the number of rows selected. Our work-around
-		 * solution (as in here as well) first checks if result_array
-		 * exists and returns its count. It doesn't however check for
-		 * custom_object_result, so - do it here.
-		 */
-		if ( ! is_int($this->num_rows))
-		{
-			$this->num_rows = count($result_object);
-		}
-
-		// Cache and return the array
-		return $this->custom_result_object[$class_name] = $result_object;
-        }
-
-	// --------------------------------------------------------------------
-
-	/* Single row result.
-	 *
-	 * Acts as a wrapper for row_object(), row_array()
-	 * and custom_row_object(). Also used by first_row(), next_row()
-	 * and previous_row().
-	 *
-	 * @param	int	row index
-	 * @param	string	('object', 'array' or a custom class name)
-	 * @return	mixed	whatever was passed to the second parameter
-	 */
-	public function row($n = 0, $type = 'object')
-	{
-		if ($type === 'object')
-		{
-			return $this->row_object($n);
-		}
-		elseif ($type === 'array')
-		{
-			return $this->row_array($n);
-		}
-
-		return $this->custom_row_object($n, $type);
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Single row result. Array version.
-	 *
-	 * @param	int	row index
-	 * @return	array
-	 */
-	public function row_array($n = 0)
-	{
-		// Make sure $n is not a string
-		if ( ! is_int($n))
-		{
-			$n = (int) $n;
-		}
-
-		/* If row_data is initialized, it means that we've already tried
-		 * (at least) to fetch some data, so ... check if we already have
-		 * this row.
-		*/
-		if (is_array($this->row_data))
-		{
-			/* If we already have row_data[$n] - return it.
-			 *
-			 * If we enter the elseif, there's a number of reasons to
-			 * return an empty array:
-			 *
-			 *	- count($this->row_data) === 0 means there are no results
-			 *	- num_rows being set or result_array having count() > 0 means
-			 *	  that we've already fetched all data and $n is greater than
-			 *	  our highest row index available
-			 *	- $n < $this->current_row means that if such row existed,
-			 *	  we would've already returned it, therefore $n is an
-			 *	  invalid index
-			 */
-			if (isset($this->row_data[$n])) // We already have this row
-			{
-				$this->current_row = $n;
-				return $this->row_data[$n];
-			}
-			elseif (count($this->row_data) === 0 OR is_int($this->num_rows)
-				OR count($this->result_array) > 0 OR $n < $this->current_row)
-			{
-				// No such row exists
-				return NULL;
-			}
-
-			// Get the next row index that would actually need to be fetched
-			$current_row = ($this->current_row < count($this->row_data)) ? count($this->row_data) : $this->current_row + 1;
-		}
-		else
-		{
-			$current_row = $this->current_row = 0;
-			$this->row_data = array();
-		}
-
-		/* Fetch more data, if available
-		 *
-		 * NOTE: Operator precedence is important here, if you change
-		 *	 'AND' with '&&' - it WILL BREAK the results, as
-		 *	 $row will be assigned the scalar value of both
-		 *	 expressions!
-		 */
-		while ($row = $this->_fetch_assoc() AND $current_row <= $n)
-		{
-			$this->row_data[$current_row++] = $row;
-		}
-
-		// This would mean that there's no (more) data to fetch
-		if ( ! is_array($this->row_data) OR ! isset($this->row_data[$n]))
-		{
-			// Cache what we already have
-			if (is_array($this->row_data))
-			{
-				$this->num_rows = count($this->row_data);
-				/* Usually, row_data could have less elements than result_array,
-				 * but at this point - they should be exactly the same.
-				 */
-				$this->result_array = $this->row_data;
-			}
-			else
-			{
-				$this->num_rows = 0;
-			}
-
-			return NULL;
-		}
-
-		$this->current_row = $n;
-		return $this->row_data[$n];
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Single row result. Object version.
-	 *
-	 * @param	int	row index
-	 * @return	mixed	object if row found; empty array if not
-	 */
-	public function row_object($n = 0)
-	{
-		// Make sure $n is not a string
-		if ( ! is_int($n))
-		{
-			$n = (int) $n;
-		}
-
-		/* Logic here is exactly the same as in row_array,
-		 * except we have to cast row_data[$n] to an object.
-		 *
-		 * If we already have result_object though - we can
-		 * directly return from it.
-		 */
-		if (isset($this->result_object[$n]))
-		{
-			$this->current_row = $n;
-			return $this->result_object[$n];
-		}
-
-		$row = $this->row_array($n);
-		// Cast only if the row exists
-		if (count($row) > 0)
-		{
-			$this->current_row = $n;
-			return (object) $row;
-		}
-
-		return NULL;
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Single row result. Custom object version.
-	 *
-	 * @param	int	row index
-	 * @param	string	custom class name
-	 * @return	mixed	custom object if row found; empty array otherwise
-	 */
-	public function custom_row_object($n = 0, $class_name)
-	{
-		// Make sure $n is not a string
-		if ( ! is_int($n))
-		{
-			$n = (int) $n;
-		}
-
-		if (array_key_exists($class_name, $this->custom_result_object))
-		{
-			/* We already have a the whole result set with this class_name,
-			 * return the specified row if it exists, and an empty array if
-			 * it doesn't.
-			 */
-			if (isset($this->custom_result_object[$class_name][$n]))
-			{
-				$this->current_row = $n;
-				return $this->custom_result_object[$class_name][$n];
-			}
-			else
-			{
-				return NULL;
-			}
-		}
-		elseif ( ! class_exists($class_name)) // No such class exists
-		{
-			return NULL;
-		}
-
-		$row = $this->row_array($n);
-		// A non-array would mean that the row doesn't exist
-		if ( ! is_array($row))
-		{
-			return NULL;
-		}
-
-		// Convert to the desired class and return
-		$row_object = new $class_name();
-		foreach ($row as $key => $value)
-		{
-			$row_object->$key = $value;
-		}
-
-		$this->current_row = $n;
-		return $row_object;
-	}
-
-	// --------------------------------------------------------------------
-
-	/* First row result.
-	 *
-	 * @param	string	('object', 'array' or a custom class name)
-	 * @return	mixed	whatever was passed to the second parameter
-	 */
-	public function first_row($type = 'object')
-	{
-		return $this->row(0, $type);
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Last row result.
-	 *
-	 * @param	string	('object', 'array' or a custom class name)
-	 * @return	mixed	whatever was passed to the second parameter
-	 */
-	public function last_row($type = 'object')
-	{
-		$result = &$this->result($type);
-		if ( ! isset($this->num_rows))
-		{
-			$this->num_rows = count($result);
-		}
-		$this->current_row = $this->num_rows - 1;
-		return $result[$this->current_row];
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Next row result.
-	 *
-	 * @param	string	('object', 'array' or a custom class name)
-	 * @return	mixed	whatever was passed to the second parameter
-	 */
-	public function next_row($type = 'object')
-	{
-		if (is_array($this->row_data))
-		{
-			$count = count($this->row_data);
-			$n = ($this->current_row > $count OR ($this->current_row === 0 && $count === 0)) ? $count : $this->current_row + 1;
-		}
-		else
-		{
-			$n = 0;
-		}
-
-		return $this->row($n, $type);
-	}
-
-	// --------------------------------------------------------------------
-
-	/* Previous row result.
-	 *
-	 * @param	string	('object', 'array' or a custom class name)
-	 * @return	mixed	whatever was passed to the second parameter
-	 */
-	public function previous_row($type = 'object')
-	{
-		$n = ($this->current_row !== 0) ? $this->current_row - 1 : 0;
-		return $this->row($n, $type);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Data Seek
 	 *
 	 * Moves the internal pointer to the desired offset. We call
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index 12482de..8bd18bd 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -49,12 +49,6 @@
 	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
-	 * used for the count_all() and count_all_results() functions.
-	 */
-	protected $_count_string = 'SELECT COUNT(*) AS ';
 	protected $_random_keyword = ' NEWID()';
 
 	// SQLSRV-specific properties
@@ -143,7 +137,7 @@
 	 */
 	protected function _execute($sql)
 	{
-		return (is_write_type($sql) && stripos($sql, 'INSERT') === FALSE)
+		return ($this->is_write_type($sql) && stripos($sql, 'INSERT') === FALSE)
 			? sqlsrv_query($this->conn_id, $sql)
 			: sqlsrv_query($this->conn_id, $sql, NULL, array('Scrollable' => SQLSRV_CURSOR_STATIC));
 	}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php
index f9d5a0d..d469ff4 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_result.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_result.php
@@ -21,7 +21,7 @@
  * @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 2.0.3
+ * @since		Version 1.0
  * @filesource
  */
 
@@ -33,6 +33,7 @@
  * @category	Database
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/database/
+ * @since	2.0.3
  */
 class CI_DB_sqlsrv_result extends CI_DB_result {
 
@@ -43,7 +44,9 @@
 	 */
 	public function num_rows()
 	{
-		return @sqlsrv_num_rows($this->result_id);
+		return is_int($this->num_rows)
+			? $this->num_rows
+			: $this->num_rows = @sqlsrv_num_rows($this->result_id);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/helpers/array_helper.php b/system/helpers/array_helper.php
index 216f12e..ed2fe3c 100644
--- a/system/helpers/array_helper.php
+++ b/system/helpers/array_helper.php
@@ -43,7 +43,7 @@
 	 * Element
 	 *
 	 * Lets you determine whether an array index is set and whether it has a value.
-	 * If the element is empty it returns FALSE (or whatever you specify as the default value.)
+	 * If the element is empty it returns NULL (or whatever you specify as the default value.)
 	 *
 	 * @param	string
 	 * @param	array
@@ -52,7 +52,7 @@
 	 */
 	function element($item, $array, $default = NULL)
 	{
-		return empty($array[$item]) ? $default : $array[$item];
+		return array_key_exists($item, $array) ? $array[$item] : $default;
 	}
 }
 
@@ -95,7 +95,7 @@
 
 		foreach ($items as $item)
 		{
-			$return[$item] = isset($array[$item]) ? $array[$item] : $default;
+			$return[$item] = array_key_exists($item, $array) ? $array[$item] : $default;
 		}
 
 		return $return;
diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php
index fc790c5..a45b3d7 100644
--- a/system/helpers/date_helper.php
+++ b/system/helpers/date_helper.php
@@ -117,26 +117,37 @@
 	 *
 	 * Returns a date formatted according to the submitted standard.
 	 *
+	 * As of PHP 5.2, the DateTime extension provides constants that
+	 * serve for the exact same purpose and are used with date().
+	 * Due to that, this function is DEPRECATED and should be removed
+	 * in CodeIgniter 3.1+.
+	 *
+	 * Here are two examples of how you should replace it:
+	 *
+	 *	date(DATE_RFC822, now()); // default
+	 *	date(DATE_W3C, $time); // a different format and time
+	 *
+	 * Reference: http://www.php.net/manual/en/class.datetime.php#datetime.constants.types
+	 *
+	 * @deprecated
 	 * @param	string	the chosen format
 	 * @param	int	Unix timestamp
 	 * @return	string
 	 */
-	function standard_date($fmt = 'DATE_RFC822', $time = '')
+	function standard_date($fmt = 'DATE_RFC822', $time = NULL)
 	{
-		$formats = array(
-				'DATE_ATOM'		=>	'%Y-%m-%dT%H:%i:%s%O',
-				'DATE_COOKIE'	=>	'%l, %d-%M-%y %H:%i:%s UTC',
-				'DATE_ISO8601'	=>	'%Y-%m-%dT%H:%i:%s%O',
-				'DATE_RFC822'	=>	'%D, %d %M %y %H:%i:%s %O',
-				'DATE_RFC850'	=>	'%l, %d-%M-%y %H:%i:%s UTC',
-				'DATE_RFC1036'	=>	'%D, %d %M %y %H:%i:%s %O',
-				'DATE_RFC1123'	=>	'%D, %d %M %Y %H:%i:%s %O',
-				'DATE_RFC2822'	=>	'%D, %d %M %Y %H:%i:%s %O',
-				'DATE_RSS'		=>	'%D, %d %M %Y %H:%i:%s %O',
-				'DATE_W3C'		=>	'%Y-%m-%dT%H:%i:%s%O'
-				);
+		if (empty($time))
+		{
+			$time = now();
+		}
 
-		return isset($formats[$fmt]) ? mdate($formats[$fmt], $time) : FALSE;
+		// Procedural style pre-defined constants from the DateTime extension
+		if (strpos($fmt, 'DATE_') !== 0 OR defined($fmt) === FALSE)
+		{
+			return FALSE;
+		}
+
+		return date(constant($fmt), $time);
 	}
 }
 
diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php
index 4735dfd..899b995 100644
--- a/system/libraries/Image_lib.php
+++ b/system/libraries/Image_lib.php
@@ -855,7 +855,14 @@
 		}
 		else // Resize
 		{
-			$cmd .= ' -resize '.$this->width.'x'.$this->height.' "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
+			if($this->maintain_ratio === TRUE)
+			{
+				$cmd .= ' -resize '.$this->width.'x'.$this->height.' "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
+			}
+			else
+			{
+				$cmd .= ' -resize '.$this->width.'x'.$this->height.'\! "'.$this->full_src_path.'" "'.$this->full_dst_path.'" 2>&1';
+			}
 		}
 
 		$retval = 1;
diff --git a/system/libraries/Migration.php b/system/libraries/Migration.php
index 3a1e7a0..c786703 100644
--- a/system/libraries/Migration.php
+++ b/system/libraries/Migration.php
@@ -292,7 +292,7 @@
 
 		// Calculate the last migration step from existing migration
 		// filenames and procceed to the standard version migration
-		return $this->version((int) substr($last_migration, 0, 3));
+		return $this->version((int) $last_migration);
 	}
 
 	// --------------------------------------------------------------------
@@ -322,9 +322,9 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Set's the schema to the latest migration
+	 * Retrieves list of available migration scripts
 	 *
-	 * @return	mixed	true if already latest, false if failed, int if upgraded
+	 * @return	array	list of migration file paths sorted by version
 	 */
 	protected function find_migrations()
 	{
diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php
index eac4ac1..cbb91c4 100644
--- a/system/libraries/Xmlrpc.php
+++ b/system/libraries/Xmlrpc.php
@@ -174,7 +174,7 @@
 	 * @param	int	port
 	 * @return	void
 	 */
-	public function server($url, $port = 80)
+	public function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)
 	{
 		if (strpos($url, 'http') !== 0)
 		{
@@ -190,7 +190,7 @@
 			$path .= '?'.$parts['query'];
 		}
 
-		$this->client = new XML_RPC_Client($path, $parts['host'], $port);
+		$this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);
 	}
 
 	// --------------------------------------------------------------------
@@ -385,6 +385,8 @@
 	public $path			= '';
 	public $server			= '';
 	public $port			= 80;
+	public $proxy			= FALSE;
+	public $proxy_port		= 8080;
 	public $errno			= '';
 	public $errstring		= '';
 	public $timeout		= 5;
@@ -398,13 +400,15 @@
 	 * @param	int
 	 * @return	void
 	 */
-	public function __construct($path, $server, $port = 80)
+	public function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)
 	{
 		parent::__construct();
 
 		$this->port = $port;
 		$this->server = $server;
 		$this->path = $path;
+		$this->proxy = $proxy;
+		$this->proxy_port = $proxy_port;
 	}
 
 	// --------------------------------------------------------------------
@@ -436,7 +440,18 @@
 	 */
 	public function sendPayload($msg)
 	{
-		$fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstring, $this->timeout);
+		if ($this->proxy === FALSE)
+		{
+			$server = $this->server;
+			$port = $this->port;
+		}
+		else
+		{
+			$server = $this->proxy;
+			$port = $this->proxy_port;
+		}
+
+		$fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);
 
 		if ( ! is_resource($fp))
 		{
diff --git a/tests/codeigniter/helpers/date_helper_test.php b/tests/codeigniter/helpers/date_helper_test.php
index 4e01b1a..1b79b94 100644
--- a/tests/codeigniter/helpers/date_helper_test.php
+++ b/tests/codeigniter/helpers/date_helper_test.php
@@ -69,7 +69,7 @@
 	public function test_standard_date_rfc822()
 	{
 		$this->assertEquals(
-			date('D, d M y H:i:s O', $this->time),
+			date(DATE_RFC822, $this->time),
 			standard_date('DATE_RFC822', $this->time)
 		);
 	}
@@ -79,7 +79,7 @@
 	public function test_standard_date_atom()
 	{
 		$this->assertEquals(
-			date("Y-m-d\TH:i:sO", $this->time),
+			date(DATE_ATOM, $this->time),
 			standard_date('DATE_ATOM', $this->time)
 		);
 	}
@@ -89,7 +89,7 @@
 	public function test_standard_date_cookie()
 	{
 		$this->assertEquals(
-			date("l, d-M-y H:i:s \U\T\C", $this->time),
+			date(DATE_COOKIE, $this->time),
 			standard_date('DATE_COOKIE', $this->time)
 		);
 	}
@@ -99,7 +99,7 @@
 	public function test_standard_date_iso8601()
 	{
 		$this->assertEquals(
-			date("Y-m-d\TH:i:sO", $this->time),
+			date(DATE_ISO8601, $this->time),
 			standard_date('DATE_ISO8601', $this->time)
 		);
 	}
@@ -109,7 +109,7 @@
 	public function test_standard_date_rfc850()
 	{
 		$this->assertEquals(
-			date("l, d-M-y H:i:s \U\T\C", $this->time),
+			date(DATE_RFC850, $this->time),
 			standard_date('DATE_RFC850', $this->time)
 		);
 	}
@@ -119,7 +119,7 @@
 	public function test_standard_date_rfc1036()
 	{
 		$this->assertEquals(
-			date('D, d M y H:i:s O', $this->time),
+			date(DATE_RFC1036, $this->time),
 			standard_date('DATE_RFC1036', $this->time)
 		);
 	}
@@ -129,7 +129,7 @@
 	public function test_standard_date_rfc1123()
 	{
 		$this->assertEquals(
-			date('D, d M Y H:i:s O', $this->time),
+			date(DATE_RFC1123, $this->time),
 			standard_date('DATE_RFC1123', $this->time)
 		);
 	}
@@ -139,7 +139,7 @@
 	public function test_standard_date_rfc2822()
 	{
 		$this->assertEquals(
-			date('D, d M Y H:i:s O', $this->time),
+			date(DATE_RFC2822, $this->time),
 			standard_date('DATE_RFC2822', $this->time)
 		);
 	}
@@ -149,7 +149,7 @@
 	public function test_standard_date_rss()
 	{
 		$this->assertEquals(
-			date('D, d M Y H:i:s O', $this->time),
+			date(DATE_RSS, $this->time),
 			standard_date('DATE_RSS', $this->time)
 		);
 	}
@@ -159,7 +159,7 @@
 	public function test_standard_date_w3c()
 	{
 		$this->assertEquals(
-			date("Y-m-d\TH:i:sO", $this->time),
+			date(DATE_W3C, $this->time),
 			standard_date('DATE_W3C', $this->time)
 		);
 	}
diff --git a/user_guide_src/source/DCO.rst b/user_guide_src/source/DCO.rst
new file mode 100644
index 0000000..c8f9b49
--- /dev/null
+++ b/user_guide_src/source/DCO.rst
@@ -0,0 +1,27 @@
+#####################################
+Developer's Certificate of Origin 1.1
+#####################################
+
+By making a contribution to this project, I certify that:
+
+(1)	The contribution was created in whole or in part by me and I
+	have the right to submit it under the open source license
+	indicated in the file; or
+
+(2)	The contribution is based upon previous work that, to the best
+	of my knowledge, is covered under an appropriate open source
+	license and I have the right under that license to submit that
+	work with modifications, whether created in whole or in part
+	by me, under the same open source license (unless I am
+	permitted to submit under a different license), as indicated
+	in the file; or
+
+(3)	The contribution was provided directly to me by some other
+	person who certified (1), (2) or (3) and I have not modified
+	it.
+
+(4)	I understand and agree that this project and the contribution
+	are public and that a record of the contribution (including all
+	personal information I submit with it, including my sign-off) is
+	maintained indefinitely and may be redistributed consistent with
+	this project or the open source license(s) involved.
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 9edb1c4..8117bc6 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -52,7 +52,11 @@
 
 -  Helpers
 
-   -  :doc:`Date Helper <helpers/date_helper>` function now() now works with all timezone strings supported by PHP.
+   -  :doc:`Date Helper <helpers/date_helper>` changes include:
+	 - ``now()`` now works with all timezone strings supported by PHP.
+	 - Added an optional third parameter to ``timespan()`` that constrains the number of time units displayed.
+	 - Added an optional parameter to ``timezone_menu()`` that allows more attributes to be added to the generated select tag.
+	 - Deprecated ``standard_date()``, which now just uses the native ``date()`` with `DateTime constants <http://bg2.php.net/manual/en/class.datetime.php#datetime.constants.types>`_.
    -  ``create_captcha()`` accepts additional colors parameter, allowing for color customization.
    -  :doc:`URL Helper <helpers/url_helper>` changes include:
 	 - ``url_title()`` will now trim extra dashes from beginning and end.
@@ -63,7 +67,6 @@
    -  Changed ``humanize()`` to include a second param for the separator.
    -  Refactored ``plural()`` and ``singular()`` to avoid double pluralization and support more words.
    -  Added an optional third parameter to ``force_download()`` that enables/disables sending the actual file MIME type in the Content-Type header (disabled by default).
-   -  Added an optional third parameter to ``timespan()`` that constrains the number of time units displayed.
    -  Added a work-around in ``force_download()`` for a bug Android <= 2.1, where the filename extension needs to be in uppercase.
    -  ``form_dropdown()`` will now also take an array for unity with other form helpers.
    -  ``do_hash()`` now uses PHP's native ``hash()`` function (supporting more algorithms) and is deprecated.
@@ -72,7 +75,6 @@
 	 - ``set_realpath()`` can now also handle file paths as opposed to just directories.
 	 - Added an optional paramater to ``delete_files()`` to enable it to skip deleting files such as .htaccess and index.html.
 	 - ``read_file()`` is now a deprecated alias of ``file_get_contents()``.
-   -  Added an optional parameter to :doc:`Date Helper <helpers/date_helper>` function ``timezone_menu()`` that allows more attributes to be added to the generated select tag.
    -  :doc:`Security Helper <helpers/security_helper>` function ``strip_image_tags()`` is now an alias for the same method in the :doc:`Security Library <libraries/security>`.
 
 -  Database
@@ -93,7 +95,7 @@
 	 - Added support for backup() in :doc:`Database Utilities <database/utilities>`.
    -  Added 'dsn' configuration setting for drivers that support DSN strings (PDO, PostgreSQL, Oracle, ODBC, CUBRID).
    -  Improved PDO database support.
-   -  Added Interbase/Firebird database support via the "interbase" driver.
+   -  Added Interbase/Firebird database support via the 'ibase' driver.
    -  Added an optional database name parameter to db_select().
    -  Replaced the _error_message() and _error_number() methods with error(), that returns an array containing the last database error code and message.
    -  Improved version() implementation so that drivers that have a native function to get the version number don't have to be defined in the core DB_driver class.
@@ -126,7 +128,6 @@
 	 - Added support for drop_table() in :doc:`Database Forge <database/forge>`.
 	 - Added support for list_databases() in :doc:`Database Utilities <database/utilities>`.
 	 - Generally improved for speed and cleaned up all of its components.
-	 - *Row* result methods now really only fetch only the needed number of rows, instead of depending entirely on result().
 	 - num_rows() is now only called explicitly by the developer and no longer re-executes statements.
    -  Improved support of the SQLite driver, including:
 	 - Added support for replace() in :doc:`Query Builder <database/query_builder>`.
@@ -134,9 +135,12 @@
    -  Added ODBC support for create_database(), drop_database() and drop_table() in :doc:`Database Forge <database/forge>`.
    -  Added PDO support for create_database(), drop_database and drop_table() in :doc:`Database Forge <database/forge>`.
    -  Added unbuffered_row() method for getting a row without prefetching whole result (consume less memory).
+   -  Added PDO support for ``list_fields()`` in :doc:`Database Results <database/results>`.
+   -  Added capability for packages to hold database.php config files 
    -  Added subdrivers support (currently only used by PDO).
 
 -  Libraries
+
    -  CI_Session now respects php.ini's session.gc_probability and session.gc_divisor
    -  Added max_filename_increment config setting for Upload library.
    -  CI_Loader::_ci_autoloader() is now a protected method.
@@ -151,6 +155,7 @@
 	 -  Added support for 3-length hex color values for wm_font_color and wm_shadow_color properties, as well as validation for them.
 	 -  Class properties wm_font_color, wm_shadow_color and wm_use_drop_shadow are now protected, to avoid breaking the text_watermark() method if they are set manually after initialization.
 	 -  If property maintain_ratio is set to TRUE, image_reproportion() now doesn't need both width and height to be specified.
+	 -  Property maintain_ratio is now taken into account when resizing images using ImageMagick library
    -  Removed SHA1 function in the :doc:`Encryption Library <libraries/encryption>`.
    -  Added $config['csrf_regeneration'] to the CSRF protection in the :doc:`Security library <libraries/security>`, which makes token regeneration optional.
    -  Added $config['csrf_exclude_uris'] to the CSRF protection in the :doc:`Security library <libraries/security>`, which allows you list URIs which will not have the CSRF validation functions run.
@@ -176,6 +181,7 @@
 	 -  Added support for setting custom attributes.
 	 -  Deprecated usage of the "anchor_class" setting (use the new "attributes" setting instead).
 	 -  Added $config['reuse_query_string'] to allow automatic repopulation of query string arguments, combined with normal URI segments.
+   -  Added the ability to use a proxy with the :doc:`XML-RPC Library <libraries/xmlrpc>`.
 
 -  Core
 
@@ -301,11 +307,20 @@
 -  Fixed a bug (#79) - :doc:`Form Validation Library <libraries/form_validation>` didn't properly validate array fields that use associative keys or have custom indexes.
 -  Fixed a bug (#427) - :doc:`Form Validation Library <libraries/form_validation>` method ``strip_image_tags()`` was an alias to a non-existent method.
 -  Fixed a bug (#1545) - :doc:`Query Builder <database/query_builder>` method ``limit()`` wasn't executed properly under Oracle.
+-  Fixed a bug (#1551) - :doc:`Date Helper <helpers/date_helper>` function ``standard_date()`` didn't properly format *W3C* and *ATOM* standard dates.
+
+Version 2.1.2
+=============
+
+Release Date: June 29, 2012
+
+-  General Changes
+   -  Improved security in ``xss_clean()``.
 
 Version 2.1.1
 =============
 
-Release Date: June 13, 2012
+Release Date: June 12, 2012
 
 -  General Changes
    -  Fixed support for docx, xlsx files in mimes.php.
@@ -316,20 +331,20 @@
    -  Added support for the IP format parameter to the :doc:`Form Validation Library <libraries/form_validation>`.
 
 -  Helpers
-   -  url_title() performance and output improved. You can now use any string as the word delimiter, but 'dash' and 'underscore' are still supported.
+   -  ``url_title()`` performance and output improved. You can now use any string as the word delimiter, but 'dash' and 'underscore' are still supported.
 
 Bug fixes for 2.1.1
 -------------------
 
--  Fixed a bug (#697) - A wrong array key was used in the Upload library to check for mime-types.
--  Fixed a bug - form_open() compared $action against site_url() instead of base_url().
--  Fixed a bug - CI_Upload::_file_mime_type() could've failed if mime_content_type() is used for the detection and returns FALSE.
+-  Fixed a bug (#697) - A wrong array key was used in the :doc:`File Uploading Library <libraries/file_uploading>` to check for mime-types.
+-  Fixed a bug - ``form_open()`` compared $action against ``site_url()`` instead of ``base_url()``.
+-  Fixed a bug - ``CI_Upload::_file_mime_type()`` could've failed if ``mime_content_type()`` is used for the detection and returns FALSE.
 -  Fixed a bug (#538) - Windows paths were ignored when using the :doc:`Image Manipulation Library <libraries/image_lib>` to create a new file.
 -  Fixed a bug - When database caching was enabled, $this->db->query() checked the cache before binding variables which resulted in cached queries never being found.
 -  Fixed a bug - CSRF cookie value was allowed to be any (non-empty) string before being written to the output, making code injection a risk.
 -  Fixed a bug (#726) - PDO put a 'dbname' argument in it's connection string regardless of the database platform in use, which made it impossible to use SQLite.
--  Fixed a bug - CI_DB_pdo_driver::num_rows() was not returning properly value with SELECT queries, cause it was relying on PDOStatement::rowCount().
--  Fixed a bug (#1059) - CI_Image_lib::clear() was not correctly clearing all necessary object properties, namely width and height.
+-  Fixed a bug - ``CI_DB_pdo_driver::num_rows()`` was not returning properly value with SELECT queries, cause it was relying on ``PDOStatement::rowCount()``.
+-  Fixed a bug (#1059) - ``CI_Image_lib::clear()`` was not correctly clearing all necessary object properties, namely width and height.
 
 Version 2.1.0
 =============
diff --git a/user_guide_src/source/contributing/index.rst b/user_guide_src/source/contributing/index.rst
new file mode 100644
index 0000000..2ede0e6
--- /dev/null
+++ b/user_guide_src/source/contributing/index.rst
@@ -0,0 +1,105 @@
+###########################
+Contributing to CodeIgniter
+###########################
+
+CodeIgniter is a community driven project and accepts contributions of code
+and documentation from the community. These contributions are made in the form
+of Issues or `Pull Requests <http://help.github.com/send-pull-requests/>`_ on
+the `EllisLab CodeIgniter repository
+<https://github.com/EllisLab/CodeIgniter>`_ on GitHub.
+
+Issues are a quick way to point out a bug. If you find a bug or documentation
+error in CodeIgniter then please check a few things first:
+
+- There is not already an open Issue
+- The issue has already been fixed (check the develop branch, or look for
+  closed Issues)
+- Is it something really obvious that you fix it yourself?
+
+Reporting issues is helpful but an even better approach is to send a Pull
+Request, which is done by "Forking" the main repository and committing to your
+own copy. This will require you to use the version control system called Git.
+
+**********
+Guidelines
+**********
+
+Before we look into how, here are the guidelines. If your Pull Requests fail
+to pass these guidelines it will be declined and you will need to re-submit
+when you’ve made the changes. This might sound a bit tough, but it is required
+for us to maintain quality of the code-base.
+
+PHP Style
+=========
+
+All code must meet the `Style Guide
+<http://codeigniter.com/user_guide/general/styleguide.html>`_, which is
+essentially the `Allman indent style
+<http://en.wikipedia.org/wiki/Indent_style#Allman_style>`_, underscores and
+readable operators. This makes certain that all code is the same format as the
+existing code and means it will be as readable as possible.
+
+Documentation
+=============
+
+If you change anything that requires a change to documentation then you will
+need to add it. New classes, methods, parameters, changing default values, etc
+are all things that will require a change to documentation. The change-log
+must also be updated for every change. Also PHPDoc blocks must be maintained.
+
+Compatibility
+=============
+
+CodeIgniter is compatible with PHP 5.2.4 so all code supplied must stick to
+this requirement. If PHP 5.3 or 5.4 functions or features are used then there
+must be a fallback for PHP 5.2.4.
+
+Branching
+=========
+
+CodeIgniter uses the `Git-Flow
+<http://nvie.com/posts/a-successful-git-branching-model/>`_ branching model
+which requires all pull requests to be sent to the "develop" branch. This is
+where the next planned version will be developed. The "master" branch will
+always contain the latest stable version and is kept clean so a "hotfix" (e.g:
+an emergency security patch) can be applied to master to create a new version,
+without worrying about other features holding it up. For this reason all
+commits need to be made to "develop" and any sent to "master" will be closed
+automatically. If you have multiple changes to submit, please place all
+changes into their own branch on your fork.
+
+One thing at a time: A pull request should only contain one change. That does
+not mean only one commit, but one change - however many commits it took. The
+reason for this is that if you change X and Y but send a pull request for both
+at the same time, we might really want X but disagree with Y, meaning we
+cannot merge the request. Using the Git-Flow branching model you can create
+new branches for both of these features and send two requests.
+
+Signing
+=======
+You must sign your work, certifying that you either wrote the work or
+otherwise have the right to pass it on to an open source project. git makes
+this trivial as you merely have to use `--signoff` on your commits to your
+CodeIgniter fork.
+
+.. code-block:: bash
+
+	git commit --signoff
+
+or simply
+
+.. code-block:: bash
+
+	git commit -s
+
+This will sign your commits with the information setup in your git config, e.g.
+
+	Signed-off-by: John Q Public <john.public@example.com>
+
+If you are using Tower there is a "Sign-Off" checkbox in the commit window. You 
+could even alias git commit to use the -s flag so you don’t have to think about 
+it.
+
+By signing your work in this manner, you certify to a "Developer's Certificate 
+or Origin". The current version of this certificate is in the :doc:`/DCO` file
+in the root of this documentation.
diff --git a/user_guide_src/source/database/configuration.rst b/user_guide_src/source/database/configuration.rst
index 7a19c84..c17de60 100644
--- a/user_guide_src/source/database/configuration.rst
+++ b/user_guide_src/source/database/configuration.rst
@@ -12,26 +12,44 @@
 The config settings are stored in a multi-dimensional array with this
 prototype::
 
-	$db['default']['hostname'] = "localhost";
-	$db['default']['username'] = "root";
-	$db['default']['password'] = "";
-	$db['default']['database'] = "database_name";
-	$db['default']['dbdriver'] = "mysql";
-	$db['default']['dbprefix'] = "";
-	$db['default']['pconnect'] = TRUE;
-	$db['default']['db_debug'] = FALSE;
-	$db['default']['cache_on'] = FALSE;
-	$db['default']['cachedir'] =  "";
-	$db['default']['char_set'] = "utf8";
-	$db['default']['dbcollat'] = "utf8_general_ci";
-	$db['default']['swap_pre'] = "";
-	$db['default']['autoinit'] = TRUE;
-	$db['default']['stricton'] = FALSE;
+	$db['default'] = array(
+		'dsn'	=> '',
+		'hostname' => 'localhost',
+		'username' => 'root',
+		'password' => '',
+		'database' => 'database_name',
+		'dbdriver' => 'mysqli',
+		'dbprefix' => '',
+		'pconnect' => TRUE,
+		'db_debug' => TRUE,
+		'cache_on' => FALSE,
+		'cachedir' => '',
+		'char_set' => 'utf8',
+		'dbcollat' => 'utf8_general_ci',
+		'swap_pre' => '',
+		'autoinit' => TRUE,
+		'stricton' => FALSE,
+		'failover' => array()
+	);
 
-If you use PDO as your dbdriver, you can specify the full DSN string describe a connection to the database like this::
+Some database drivers (such as PDO, PostgreSQL, Oracle, ODBC) might
+require a full DSN string to be provided. If that is the case, you
+should use the 'dsn' configuration setting, as if you're using the
+driver's underlying native PHP extension, like this::
 
+	// PDO
 	$db['default']['dsn'] = 'pgsql:host=localhost;port=5432;dbname=database_name';
 
+	// Oracle
+	$db['default']['dsn'] = '//localhost/XE';
+
+.. note:: If you do not specify a DSN string for a driver that requires it, CodeIgniter
+	will try to build it with the rest of the provided settings.
+
+.. note:: If you provide a DSN string and it is missing some valid settings (e.g. the
+	database character set), which are present in the rest of the configuration
+	fields, CodeIgniter will append them.
+
 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::
 
@@ -41,7 +59,7 @@
 				'username' => '',
 				'password' => '',
 				'database' => '',
-				'dbdriver' => 'mysql',
+				'dbdriver' => 'mysqli',
 				'dbprefix' => '',
 				'pconnect' => TRUE,
 				'db_debug' => TRUE,
@@ -58,7 +76,7 @@
 				'username' => '',
 				'password' => '',
 				'database' => '',
-				'dbdriver' => 'mysql',
+				'dbdriver' => 'mysqli',
 				'dbprefix' => '',
 				'pconnect' => TRUE,
 				'db_debug' => TRUE,
@@ -81,30 +99,34 @@
 connection group for each, then switch between groups as needed. For
 example, to set up a "test" environment you would do this::
 
-	$db['test']['hostname'] = "localhost";
-	$db['test']['username'] = "root";
-	$db['test']['password'] = "";
-	$db['test']['database'] = "database_name";
-	$db['test']['dbdriver'] = "mysql";
-	$db['test']['dbprefix'] = "";
-	$db['test']['pconnect'] = TRUE;
-	$db['test']['db_debug'] = FALSE;
-	$db['test']['cache_on'] = FALSE;
-	$db['test']['cachedir'] =  "";
-	$db['test']['char_set'] = "utf8";
-	$db['test']['dbcollat'] = "utf8_general_ci";
-	$db['test']['swap_pre'] = "";
-	$db['test']['autoinit'] = TRUE;
-	$db['test']['stricton'] = FALSE;
+	$db['test'] = array(
+		'dsn'	=> '',
+		'hostname' => 'localhost',
+		'username' => 'root',
+		'password' => '',
+		'database' => 'database_name',
+		'dbdriver' => 'mysqli',
+		'dbprefix' => '',
+		'pconnect' => TRUE,
+		'db_debug' => TRUE,
+		'cache_on' => FALSE,
+		'cachedir' => '',
+		'char_set' => 'utf8',
+		'dbcollat' => 'utf8_general_ci',
+		'swap_pre' => '',
+		'autoinit' => TRUE,
+		'stricton' => FALSE,
+		'failover' => array()
+	);
 
 Then, to globally tell the system to use that group you would set this
 variable located in the config file::
 
-	$active_group = "test";
+	$active_group = 'test';
 
-Note: The name "test" is arbitrary. It can be anything you want. By
-default we've used the word "default" for the primary connection, but it
-too can be renamed to something more relevant to your project.
+.. note:: The name 'test' is arbitrary. It can be anything you want. By
+	default we've used the word "default" for the primary connection,
+	but it too can be renamed to something more relevant to your project.
 
 Query Builder
 -------------
@@ -119,8 +141,8 @@
 
 	$query_builder = TRUE;
 
-.. note:: that some CodeIgniter classes such as Sessions require Active
-	Records be enabled to access certain functionality.
+.. note:: that some CodeIgniter classes such as Sessions require Query
+	Builder to be enabled to access certain functionality.
 
 Explanation of Values:
 ----------------------
@@ -128,11 +150,12 @@
 ======================  ==================================================================================================
  Name Config             Description
 ======================  ==================================================================================================
-**hostname** 		The hostname of your database server. Often this is "localhost".
+**dsn**			The DSN connect string (an all-in-one configuration sequence).
+**hostname** 		The hostname of your database server. Often this is 'localhost'.
 **username**		The username used to connect to the database.
 **password**		The password used to connect to the database.
 **database**		The name of the database you want to connect to.
-**dbdriver**		The database type. ie: mysql, postgre, odbc, etc. Must be specified in lower case.
+**dbdriver**		The database type. ie: mysqli, postgre, odbc, etc. Must be specified in lower case.
 **dbprefix**		An optional table prefix which will added to the table name when running :doc:
 			`Query Builder <query_builder>` queries. This permits multiple CodeIgniter installations
 			to share one database.
@@ -144,14 +167,7 @@
 **char_set**		The character set used in communicating with the database.
 **dbcollat**		The character collation used in communicating with the database
 
-			.. note:: For MySQL and MySQLi databases, this setting is only used
-				as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7
-				(and in table creation queries made with DB Forge). There is an
-				incompatibility in PHP with mysql_real_escape_string() which can
-				make your site vulnerable to SQL injection if you are using a
-				multi-byte character set and are running versions lower than these.
-				Sites using Latin-1 or UTF-8 database character set and collation are
-				unaffected.
+			.. note:: Only used in the 'mysql' and 'mysqli' drivers.
 
 **swap_pre**		A default table prefix that should be swapped with dbprefix. This is useful for distributed
 			applications where you might run manually written queries, and need the prefix to still be
@@ -163,11 +179,11 @@
 **port**		The database port number. To use this value you have to add a line to the database config array.
 			::
 			
-				$db['default']['port'] =  5432;
+				$db['default']['port'] = 5432;
 ======================  ==================================================================================================
 
 .. note:: Depending on what database platform you are using (MySQL, PostgreSQL,
 	etc.) not all values will be needed. For example, when using SQLite you
 	will not need to supply a username or password, and the database name
 	will be the path to your database file. The information above assumes
-	you are using MySQL.
+	you are using MySQL.
\ No newline at end of file
diff --git a/user_guide_src/source/database/connecting.rst b/user_guide_src/source/database/connecting.rst
index 5822ca6..9b81170 100644
--- a/user_guide_src/source/database/connecting.rst
+++ b/user_guide_src/source/database/connecting.rst
@@ -57,25 +57,28 @@
 To connect manually to a desired database you can pass an array of
 values::
 
-	$config['hostname'] = "localhost"; 
-	$config['username'] = "myusername"; 
-	$config['password'] = "mypassword"; 
-	$config['database'] = "mydatabase"; 
-	$config['dbdriver'] = "mysql"; 
-	$config['dbprefix'] = ""; 
-	$config['pconnect'] = FALSE; 
-	$config['db_debug'] = TRUE; 
-	$config['cache_on'] = FALSE; 
-	$config['cachedir'] = ""; 
-	$config['char_set'] = "utf8"; 
-	$config['dbcollat'] = "utf8_general_ci";  
+	$config['hostname'] = 'localhost';
+	$config['username'] = 'myusername';
+	$config['password'] = 'mypassword';
+	$config['database'] = 'mydatabase';
+	$config['dbdriver'] = 'mysqli';
+	$config['dbprefix'] = '';
+	$config['pconnect'] = FALSE;
+	$config['db_debug'] = TRUE;
+	$config['cache_on'] = FALSE;
+	$config['cachedir'] = '';
+	$config['char_set'] = 'utf8';
+	$config['dbcollat'] = 'utf8_general_ci';
 	$this->load->database($config);
 
 For information on each of these values please see the :doc:`configuration
 page <configuration>`.
 
-.. note:: For the PDO driver, $config['hostname'] should look like
-	this: 'mysql:host=localhost'
+.. note:: For the PDO driver, you should use the $config['dsn'] setting
+	instead of 'hostname' and 'database':
+
+	|
+	| $config['dsn'] = 'mysql:host=localhost;dbname=mydatabase';
 
 Or you can submit your database values as a Data Source Name. DSNs must
 have this prototype::
@@ -149,5 +152,4 @@
 
 ::
 
-	$this->db->close();
-
+	$this->db->close();
\ No newline at end of file
diff --git a/user_guide_src/source/general/models.rst b/user_guide_src/source/general/models.rst
index 2e1e025..4e52a96 100644
--- a/user_guide_src/source/general/models.rst
+++ b/user_guide_src/source/general/models.rst
@@ -72,10 +72,11 @@
 
 	class Model_name extends CI_Model {
 
-	    function __construct()
-	    {
-	        parent::__construct();
-	    }
+		public function __construct()
+		{
+			parent::__construct();
+		}
+
 	}
 
 Where **Model_name** is the name of your class. Class names **must** have
@@ -87,10 +88,11 @@
 
 	class User_model extends CI_Model {
 
-	    function __construct()
-	    {
-	        parent::__construct();
-	    }
+		public function __construct()
+		{
+			parent::__construct();
+		}
+
 	}
 
 Your file will be this::
@@ -102,7 +104,7 @@
 
 Your models will typically be loaded and called from within your
 :doc:`controller <controllers>` functions. To load a model you will use
-the following function::
+the following method::
 
 	$this->load->model('model_name');
 
@@ -112,33 +114,34 @@
 
 	$this->load->model('blog/queries');
 
-Once loaded, you will access your model functions using an object with
-the same name as your class::
+Once loaded, you will access your model methods using an object with the
+same name as your class::
 
 	$this->load->model('model_name');
 
-	$this->model_name->function();
+	$this->model_name->method();
 
 If you would like your model assigned to a different object name you can
-specify it via the second parameter of the loading function::
+specify it via the second parameter of the loading method::
 
-	$this->load->model('model_name', 'fubar');
+	$this->load->model('model_name', 'foobar');
 
-	$this->fubar->function();
+	$this->foobar->method();
 
 Here is an example of a controller, that loads a model, then serves a
 view::
 
 	class Blog_controller extends CI_Controller {
 
-	    function blog()
-	    {
-	        $this->load->model('blog');
+		public function blog()
+		{
+			$this->load->model('blog');
 
-	        $data['query'] = $this->Blog->get_last_ten_entries();
+			$data['query'] = $this->Blog->get_last_ten_entries();
 
-	        $this->load->view('blog', $data);
-	    }
+			$this->load->view('blog', $data);
+		}
+
 	}
 	
 
@@ -170,15 +173,13 @@
 -  You can manually pass database connectivity settings via the third
    parameter::
 
-	$config['hostname'] = "localhost";
-	$config['username'] = "myusername";
-	$config['password'] = "mypassword";
-	$config['database'] = "mydatabase";
-	$config['dbdriver'] = "mysql";
-	$config['dbprefix'] = "";
+	$config['hostname'] = 'localhost';
+	$config['username'] = 'myusername';
+	$config['password'] = 'mypassword';
+	$config['database'] = 'mydatabase';
+	$config['dbdriver'] = 'mysqli';
+	$config['dbprefix'] = '';
 	$config['pconnect'] = FALSE;
 	$config['db_debug'] = TRUE;
 
-	$this->load->model('Model_name', '', $config);
-
-
+	$this->load->model('Model_name', '', $config);
\ No newline at end of file
diff --git a/user_guide_src/source/helpers/array_helper.rst b/user_guide_src/source/helpers/array_helper.rst
index 4308753..15b5e17 100644
--- a/user_guide_src/source/helpers/array_helper.rst
+++ b/user_guide_src/source/helpers/array_helper.rst
@@ -21,17 +21,17 @@
 element()
 =========
 
-.. php:method:: element($item, $array, $default = FALSE)
+.. php:method:: element($item, $array, $default = NULL)
 
 	:param string 	$item: Item to fetch from the array
 	:param array 	$array: Input array
 	:param boolean	$default: What to return if the array isn't valid
-	:returns: FALSE on failure or the array item.
+	:returns: NULL on failure or the array item.
 
 
 Lets you fetch an item from an array. The function tests whether the
 array index is set and whether it has a value. If a value exists it is
-returned. If a value does not exist it returns FALSE, or whatever you've
+returned. If a value does not exist it returns NULL, or whatever you've
 specified as the default value via the third parameter. Example
 
 ::
@@ -43,31 +43,31 @@
 	);
 
 	echo element('color', $array); // returns "red" 
-	echo element('size', $array, NULL); // returns NULL 
+	echo element('size', $array, 'foobar'); // returns "foobar" 
 
 elements()
 ==========
 
 Lets you fetch a number of items from an array. The function tests
 whether each of the array indices is set. If an index does not exist it
-is set to FALSE, or whatever you've specified as the default value via
+is set to NULL, or whatever you've specified as the default value via
 the third parameter. 
 
-.. php:method:: elements($items, $array, $default = FALSE)
+.. php:method:: elements($items, $array, $default = NULL)
 
 	:param string 	$item: Item to fetch from the array
 	:param array 	$array: Input array
 	:param boolean	$default: What to return if the array isn't valid
-	:returns: FALSE on failure or the array item.
+	:returns: NULL on failure or the array item.
 
 Example
 
 ::
 
 	$array = array(
-		'color' => 'red',  
-		'shape' => 'round',     
-		'radius' => '10',     
+		'color' => 'red',
+		'shape' => 'round',
+		'radius' => '10',
 		'diameter' => '20'
 	);
 
@@ -78,25 +78,25 @@
 ::
 
 	array(
-		'color' => 'red',     
-		'shape' => 'round',     
-		'height' => FALSE
+		'color' => 'red',
+		'shape' => 'round',
+		'height' => NULL
 	);
 
 You can set the third parameter to any default value you like
 
 ::
 
-	 $my_shape = elements(array('color', 'shape', 'height'), $array, NULL);
+	 $my_shape = elements(array('color', 'shape', 'height'), $array, 'foobar');
 
 The above will return the following array
 
 ::
 
 	array(     
-		'color' 	=> 'red',     
-		'shape' 	=> 'round',     
-		'height'	=> NULL
+		'color' 	=> 'red',
+		'shape' 	=> 'round',
+		'height'	=> 'foobar'
 	);
 
 This is useful when sending the $_POST array to one of your Models.
diff --git a/user_guide_src/source/helpers/date_helper.rst b/user_guide_src/source/helpers/date_helper.rst
index 5adfb18..e332a91 100644
--- a/user_guide_src/source/helpers/date_helper.rst
+++ b/user_guide_src/source/helpers/date_helper.rst
@@ -40,7 +40,7 @@
 mdate()
 =======
 
-This function is identical to PHPs `date() <http://www.php.net/date>`_
+This function is identical to PHP's `date() <http://www.php.net/date>`_
 function, except that it lets you use MySQL style date codes, where each
 code letter is preceded with a percent sign: %Y %m %d etc.
 
@@ -85,21 +85,28 @@
 The first parameter must contain the format, the second parameter must
 contain the date as a Unix timestamp.
 
+.. note:: This function is DEPRECATED. Use the native ``date()`` combined
+	with `DateTime's format constants <http://www.php.net/manual/en/class.datetime.php#datetime.constants.types>`_
+	instead:
+
+	|
+	| echo date(DATE_RFC822, time());
+
 Supported formats:
 
 ===============	=======================	======================================
 Constant		Description				Example
 ===============	=======================	======================================
-DATE_ATOM		Atom					2005-08-15T16:13:03+0000
-DATE_COOKIE		HTTP Cookies			Sun, 14 Aug 2005 16:13:03 UTC
-DATE_ISO8601   	ISO-8601				2005-08-14T16:13:03+00:00
-DATE_RFC822		RFC 822					Sun, 14 Aug 05 16:13:03 UTC
-DATE_RFC850		RFC 850					Sunday, 14-Aug-05 16:13:03 UTC
-DATE_RFC1036	RFC 1036				Sunday, 14-Aug-05 16:13:03 UTC
-DATE_RFC1123	RFC 1123				Sun, 14 Aug 2005 16:13:03 UTC
-DATE_RFC2822 	RFC 2822				Sun, 14 Aug 2005 16:13:03 +0000
-DATE_RSS		RSS						Sun, 14 Aug 2005 16:13:03 UTC
-DATE_W3C		W3C						2005-08-14T16:13:03+0000
+DATE_ATOM	Atom			2005-08-15T16:13:03+0000
+DATE_COOKIE	HTTP Cookies		Sun, 14 Aug 2005 16:13:03 UTC
+DATE_ISO8601   	ISO-8601		2005-08-14T16:13:03+00:00
+DATE_RFC822	RFC 822			Sun, 14 Aug 05 16:13:03 UTC
+DATE_RFC850	RFC 850			Sunday, 14-Aug-05 16:13:03 UTC
+DATE_RFC1036	RFC 1036		Sunday, 14-Aug-05 16:13:03 UTC
+DATE_RFC1123	RFC 1123		Sun, 14 Aug 2005 16:13:03 UTC
+DATE_RFC2822 	RFC 2822		Sun, 14 Aug 2005 16:13:03 +0000
+DATE_RSS	RSS			Sun, 14 Aug 2005 16:13:03 UTC
+DATE_W3C	W3C			2005-08-14T16:13:03+0000
 ===============	=======================	======================================
 
 local_to_gmt()
diff --git a/user_guide_src/source/index.rst b/user_guide_src/source/index.rst
index c89b41c..e42425b 100644
--- a/user_guide_src/source/index.rst
+++ b/user_guide_src/source/index.rst
@@ -91,6 +91,17 @@
 	
 	helpers/index
 
+***************************
+Contributing to CodeIgniter
+***************************
+
+.. toctree::
+	:glob:
+	:titlesonly:
+	
+	contributing/index
+	DCO
+
 .. toctree::
 	:glob:
 	:titlesonly:
@@ -99,6 +110,7 @@
 	*
 	overview/index
 	general/requirements
+	general/welcome
 	installation/index
 	general/index
 	libraries/index
diff --git a/user_guide_src/source/installation/downloads.rst b/user_guide_src/source/installation/downloads.rst
index a4a6b7f..45a8f80 100644
--- a/user_guide_src/source/installation/downloads.rst
+++ b/user_guide_src/source/installation/downloads.rst
@@ -2,9 +2,15 @@
 Downloading CodeIgniter
 #######################
 
--  `CodeIgniter V 2.1.0 (Current
+-  `CodeIgniter V 3.0.0 (Current
    version) <http://codeigniter.com/downloads/>`_
 -  `CodeIgniter V
+   2.1.2 <http://codeigniter.com/download_files/reactor/CodeIgniter_2.1.2.zip>`_
+-  `CodeIgniter V
+   2.1.1 <http://codeigniter.com/download_files/reactor/CodeIgniter_2.1.1.zip>`_
+-  `CodeIgniter V
+   2.1.0 <http://codeigniter.com/download_files/reactor/CodeIgniter_2.1.0.zip>`_
+-  `CodeIgniter V
    2.0.3 <http://codeigniter.com/download_files/reactor/CodeIgniter_2.0.3.zip>`_
 -  `CodeIgniter V
    2.0.2 <http://codeigniter.com/download_files/reactor/CodeIgniter_2.0.2.zip>`_
diff --git a/user_guide_src/source/installation/upgrade_210.rst b/user_guide_src/source/installation/upgrade_210.rst
index 9d7e1a2..5874bfc 100644
--- a/user_guide_src/source/installation/upgrade_210.rst
+++ b/user_guide_src/source/installation/upgrade_210.rst
@@ -8,15 +8,19 @@
 Step 1: Update your CodeIgniter files
 =====================================
 
-Replace all files and directories in your "system" folder and replace
-your index.php file. If any modifications were made to your index.php
-they will need to be made fresh in this new one.
+Replace all files and directories in your "system" folder.
+
+.. note:: If you have any custom developed files in these folders please
+	make copies of them first.
 
 Step 2: Replace config/user_agents.php
 ======================================
 
 This config file has been updated to contain more user agent types,
-please copy it to application/config/user_agents.php.
+please copy it to _application/config/user_agents.php*.
 
-.. note:: If you have any custom developed files in these folders please
-	make copies of them first.
\ No newline at end of file
+Step 3: Update your user guide
+==============================
+
+Please also replace your local copy of the user guide with the new
+version.
\ No newline at end of file
diff --git a/user_guide_src/source/installation/upgrade_211.rst b/user_guide_src/source/installation/upgrade_211.rst
new file mode 100644
index 0000000..59faca8
--- /dev/null
+++ b/user_guide_src/source/installation/upgrade_211.rst
@@ -0,0 +1,33 @@
+#############################
+Upgrading from 2.1.0 to 2.1.1
+#############################
+
+Before performing an update you should take your site offline by
+replacing the index.php file with a static one.
+
+Step 1: Update your CodeIgniter files
+=====================================
+
+Replace all files and directories in your "system" folder and replace
+your index.php file. If any modifications were made to your index.php
+they will need to be made fresh in this new one.
+
+.. note:: If you have any custom developed files in these folders please
+	make copies of them first.
+
+Step 2: Replace config/mimes.php
+================================
+
+This config file has been updated to contain more user mime-types, please copy
+it to _application/config/mimes.php*.
+
+Step 3: Update your IP address tables
+=====================================
+
+This upgrade adds support for IPv6 IP addresses. In order to store them, you need
+to enlarge your ip_address columns to 45 characters. For example, CodeIgniter's
+session table will need to change
+
+::
+
+	ALTER TABLE ci_sessions CHANGE ip_address ip_address varchar(45) default '0' NOT NULL
\ No newline at end of file
diff --git a/user_guide_src/source/installation/upgrade_212.rst b/user_guide_src/source/installation/upgrade_212.rst
new file mode 100644
index 0000000..205ad86
--- /dev/null
+++ b/user_guide_src/source/installation/upgrade_212.rst
@@ -0,0 +1,22 @@
+#############################
+Upgrading from 2.1.1 to 2.1.2
+#############################
+
+Before performing an update you should take your site offline by
+replacing the index.php file with a static one.
+
+Step 1: Update your CodeIgniter files
+=====================================
+
+Replace all files and directories in your "system" folder and replace
+your index.php file. If any modifications were made to your index.php
+they will need to be made fresh in this new one.
+
+.. note:: If you have any custom developed files in these folders please
+	make copies of them first.
+
+Step 2: Update your user guide
+==============================
+
+Please also replace your local copy of the user guide with the new
+version.
\ No newline at end of file
diff --git a/user_guide_src/source/installation/upgrade_300.rst b/user_guide_src/source/installation/upgrade_300.rst
index 1419909..f304a71 100644
--- a/user_guide_src/source/installation/upgrade_300.rst
+++ b/user_guide_src/source/installation/upgrade_300.rst
@@ -1,15 +1,14 @@
 #############################
-Upgrading from 2.1.0 to 3.0.0
+Upgrading from 2.1.2 to 3.0.0
 #############################
 
 .. note:: These upgrade notes are for a version that is yet to be released.
 
+Before performing an update you should take your site offline by replacing the index.php file with a static one.
 
-Before performing an update you should take your site offline by
-replacing the index.php file with a static one.
-
+*************************************
 Step 1: Update your CodeIgniter files
-=====================================
+*************************************
 
 Replace all files and directories in your "system" folder and replace
 your index.php file. If any modifications were made to your index.php
@@ -18,22 +17,23 @@
 .. note:: If you have any custom developed files in these folders please
 	make copies of them first.
 
-Step 2: Change References to the SHA Library
-============================================
+********************************
+Step 2: Replace config/mimes.php
+********************************
 
-The previously deprecated SHA library has been removed in CodeIgniter 3.0.
-Alter your code to use the native `sha1()` PHP function to generate a sha1 hash.
+This config file has been updated to contain more user mime-types, please copy
+it to _application/config/mimes.php*.
 
-Additionally, the `sha1()` method in the :doc:`Encryption Library <../libraries/encryption>` has been removed.
-
+**************************************************************
 Step 3: Remove $autoload['core'] from your config/autoload.php
-==============================================================
+**************************************************************
 
-Use of the `$autoload['core']` config array has been deprecated as of CodeIgniter 1.4.1 and is now removed.
-Move any entries that you might have listed there to `$autoload['libraries']` instead.
+Use of the ``$autoload['core']`` config array has been deprecated as of CodeIgniter 1.4.1 and is now removed.
+Move any entries that you might have listed there to ``$autoload['libraries']`` instead.
 
+***************************************
 Step 4: Update your config/database.php
-=======================================
+***************************************
 
 Due to 3.0.0's renaming of Active Record to Query Builder, inside your `config/database.php`, you will
 need to rename the `$active_record` variable to `$query_builder`.
@@ -42,7 +42,100 @@
     // $active_record = TRUE;
     $query_builder = TRUE;
 
+*******************************
 Step 5: Move your errors folder
-===============================
+*******************************
 
-In version 3.0.0, the errors folder has been moved from _application/errors* to _application/views/errors*.
\ No newline at end of file
+In version 3.0.0, the errors folder has been moved from _application/errors* to _application/views/errors*.
+
+****************************************************************************
+Step 6: Check the calls to Array Helper's element() and elements() functions
+****************************************************************************
+
+The default return value of these functions, when the required elements
+don't exist, has been changed from FALSE to NULL.
+
+***************************************************************
+Step 7: Remove usage of (previously) deprecated functionalities
+***************************************************************
+
+In addition to the ``$autoload['core']`` configuration setting, there's a number of other functionalities
+that have been removed in CodeIgniter 3.0.0:
+
+The SHA1 library
+================
+
+The previously deprecated SHA1 library has been removed, alter your code to use PHP's native
+``sha1()`` function to generate a SHA1 hash.
+
+Additionally, the ``sha1()`` method in the :doc:`Encryption Library <../libraries/encryption>` has been removed.
+
+The EXT constant
+================
+
+Usage of the ``EXT`` constant has been deprecated since dropping support for PHP 4. There's no
+longer a need to maintain different filename extensions and in this new CodeIgniter version,
+the ``EXT`` constant has been removed. Use just '.php' instead.
+
+Smiley helper js_insert_smiley()
+================================
+
+:doc:`Smiley Helper <../helpers/smiley_helper>` function ``js_insert_smiley()`` has been deprecated
+since CodeIgniter 1.7.2 and is now removed. You'll need to switch to ``smiley_js()`` instead.
+
+Security helper do_hash()
+=========================
+
+:doc:`Security Helper <../helpers/security_helper>` function ``do_hash()`` is now just an alias for
+PHP's native ``hash()`` function. It is deprecated and scheduled for removal in CodeIgniter 3.1+.
+
+.. note:: This function is still available, but you're strongly encouraged to remove it's usage sooner
+	rather than later.
+
+File helper read_file()
+=======================
+
+:doc:`File Helper <../helpers/file_helper>` function ``read_file()`` is now just an alias for
+PHP's native ``file_get_contents()`` function. It is deprecated and scheduled for removal in
+CodeIgniter 3.1+.
+
+.. note:: This function is still available, but you're strongly encouraged to remove it's usage sooner
+	rather than later.
+
+Date helper standard_date()
+===========================
+
+:doc:`Date Helper <../helpers/date_helper>` function ``standard_date()`` is being deprecated due
+to the availability of native PHP `constants <http://www.php.net/manual/en/class.datetime.php#datetime.constants.types>`_,
+which when combined with ``date()`` provide the same functionality. Furthermore, they have the
+exact same names as the ones supported by ``standard_date()``. Here are examples of how to replace
+it's usage:
+
+::
+
+	// Old way
+	standard_date(); // defaults to standard_date('DATE_RFC822', now());
+
+	// Replacement
+	date(DATE_RFC822, now());
+
+	// Old way
+	standard_date('DATE_ATOM', $time);
+
+	// Replacement
+	date(DATE_ATOM, $time);
+
+.. note:: This function is still available, but you're strongly encouraged to remove its' usage sooner
+	rather than later as it is scheduled for removal in CodeIgniter 3.1+.
+
+Pagination library 'anchor_class' setting
+=========================================
+
+The :doc:`Pagination Library <../libraries/pagination>` now supports adding pretty much any HTML
+attribute to your anchors via the 'attributes' configuration setting. This includes passing the
+'class' attribute and using the separate 'anchor_class' setting no longer makes sense.
+As a result of that, the 'anchor_class' setting is now deprecated and scheduled for removal in
+CodeIgniter 3.1+.
+
+.. note:: This setting is still available, but you're strongly encouraged to remove its' usage sooner
+	rather than later.
\ No newline at end of file
diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst
index 255c6a5..545f344 100644
--- a/user_guide_src/source/installation/upgrading.rst
+++ b/user_guide_src/source/installation/upgrading.rst
@@ -5,8 +5,10 @@
 Please read the upgrade notes corresponding to the version you are
 upgrading from.
 
--  :doc:`Upgrading from 2.1.1 to 3.0.0 <upgrade_300>`
+-  :doc:`Upgrading from 2.1.2 to 3.0.0 <upgrade_300>`
+-  :doc:`Upgrading from 2.1.1 to 2.1.2 <upgrade_212>`
 -  :doc:`Upgrading from 2.1.0 to 2.1.1 <upgrade_211>`
+-  :doc:`Upgrading from 2.0.3 to 2.1.0 <upgrade_210>`
 -  :doc:`Upgrading from 2.0.2 to 2.0.3 <upgrade_203>`
 -  :doc:`Upgrading from 2.0.1 to 2.0.2 <upgrade_202>`
 -  :doc:`Upgrading from 2.0 to 2.0.1 <upgrade_201>`
diff --git a/user_guide_src/source/libraries/config.rst b/user_guide_src/source/libraries/config.rst
index 6948963..08d9c29 100644
--- a/user_guide_src/source/libraries/config.rst
+++ b/user_guide_src/source/libraries/config.rst
@@ -175,7 +175,7 @@
 as to a stylesheet or image.
 
 The two functions above are normally accessed via the corresponding
-functions in the :doc:`URL Helper <helpers/url_helper>`.
+functions in the :doc:`URL Helper </helpers/url_helper>`.
 
 $this->config->system_url();
 *****************************
diff --git a/license_afl.rst b/user_guide_src/source/license_afl.rst
similarity index 100%
rename from license_afl.rst
rename to user_guide_src/source/license_afl.rst