hand merged remaining unresolved files following the backout of 648b42a75739, which was a NON-trivial whitespace commit
diff --git a/.hgflow b/.hgflow
new file mode 100644
index 0000000..ad6e56e
--- /dev/null
+++ b/.hgflow
@@ -0,0 +1,8 @@
+[Basic]
+develop = develop
+feature = feature/
+version_tag = 
+publish = default
+release = release/
+hotfix = hotfix/
+
diff --git a/application/config/database.php b/application/config/database.php
index fa541a7..b4b34bf 100644
--- a/application/config/database.php
+++ b/application/config/database.php
@@ -27,7 +27,8 @@
 |	['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.
+| 				 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.
diff --git a/application/config/migration.php b/application/config/migration.php
new file mode 100644
index 0000000..509fd90
--- /dev/null
+++ b/application/config/migration.php
@@ -0,0 +1,42 @@
+<?php defined('BASEPATH') OR exit('No direct script access allowed');

+/*

+|--------------------------------------------------------------------------

+| Enable/Disable Migrations

+|--------------------------------------------------------------------------

+|

+| Migrations are disabled by default for security reasons.

+| You should enable migrations whenever you intend to do a schema migration

+| and disable it back when you're done.

+|

+*/

+$config['migration_enabled'] = TRUE;

+

+

+/*

+|--------------------------------------------------------------------------

+| Migrations version

+|--------------------------------------------------------------------------

+|

+| This is used to set migration version that the file system should be on.

+| If you run $this->migration->latest() this is the version that schema will

+| be upgraded / downgraded to.

+|

+*/

+$config['migration_version'] = 0;

+

+

+/*

+|--------------------------------------------------------------------------

+| Migrations Path

+|--------------------------------------------------------------------------

+|

+| Path to your migrations folder.

+| Typically, it will be within your application path.

+| Also, writing permission is required within the migrations path.

+|

+*/

+$config['migration_path'] = APPPATH . 'migrations/';

+

+

+/* End of file migration.php */

+/* Location: ./application/config/migration.php */
\ No newline at end of file
diff --git a/system/core/Common.php b/system/core/Common.php
index d1e8e77..db9fbeb 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -39,6 +39,8 @@
 * @param	string
 * @return	bool	TRUE if the current version is $version or higher
 */
+if ( ! function_exists('is_php'))
+{
 	function is_php($version = '5.0.0')
 	{
 		static $_is_php;
@@ -51,6 +53,7 @@
 
 		return $_is_php[$version];
 	}
+}
 
 // ------------------------------------------------------------------------
 
@@ -64,6 +67,8 @@
  * @access	private
  * @return	void
  */
+if ( ! function_exists('is_really_writable'))
+{
 	function is_really_writable($file)
 	{
 		// If we're on a Unix server with safe_mode off we call is_writable
@@ -96,6 +101,7 @@
 		fclose($fp);
 		return TRUE;
 	}
+}
 
 // ------------------------------------------------------------------------
 
@@ -112,6 +118,8 @@
 * @param	string	the class name prefix
 * @return	object
 */
+if ( ! function_exists('load_class'))
+{
 	function &load_class($class, $directory = 'libraries', $prefix = 'CI_')
 	{
 		static $_classes = array();
@@ -166,6 +174,7 @@
 		$_classes[$class] = new $name();
 		return $_classes[$class];
 	}
+}
 
 // --------------------------------------------------------------------
 
@@ -176,6 +185,8 @@
 * @access	public
 * @return	array
 */
+if ( ! function_exists('is_loaded'))
+{
 	function is_loaded($class = '')
 	{
 		static $_is_loaded = array();
@@ -187,6 +198,7 @@
 
 		return $_is_loaded;
 	}
+}
 
 // ------------------------------------------------------------------------
 
@@ -199,6 +211,8 @@
 * @access	private
 * @return	array
 */
+if ( ! function_exists('get_config'))
+{
 	function &get_config($replace = array())
 	{
 		static $_config;
@@ -242,6 +256,7 @@
 
 		return $_config[0] =& $config;
 	}
+}
 
 // ------------------------------------------------------------------------
 
@@ -251,6 +266,8 @@
 * @access	public
 * @return	mixed
 */
+if ( ! function_exists('config_item'))
+{
 	function config_item($item)
 	{
 		static $_config_item = array();
@@ -268,6 +285,7 @@
 
 		return $_config_item[$item];
 	}
+}
 
 // ------------------------------------------------------------------------
 
@@ -283,12 +301,15 @@
 * @access	public
 * @return	void
 */
+if ( ! function_exists('show_error'))
+{
 	function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
 	{
 		$_error =& load_class('Exceptions', 'core');
 		echo $_error->show_error($heading, $message, 'error_general', $status_code);
 		exit;
 	}
+}
 
 // ------------------------------------------------------------------------
 
@@ -302,12 +323,15 @@
 * @access	public
 * @return	void
 */
+if ( ! function_exists('show_404'))
+{
 	function show_404($page = '', $log_error = TRUE)
 	{
 		$_error =& load_class('Exceptions', 'core');
 		$_error->show_404($page, $log_error);
 		exit;
 	}
+}
 
 // ------------------------------------------------------------------------
 
@@ -320,6 +344,8 @@
 * @access	public
 * @return	void
 */
+if ( ! function_exists('log_message'))
+{
 	function log_message($level = 'error', $message, $php_error = FALSE)
 	{
 		static $_log;
@@ -332,6 +358,7 @@
 		$_log =& load_class('Log');
 		$_log->write_log($level, $message, $php_error);
 	}
+}
 
 // ------------------------------------------------------------------------
 
@@ -343,6 +370,8 @@
  * @param	string
  * @return	void
  */
+if ( ! function_exists('set_status_header'))
+{
 	function set_status_header($code = 200, $text = '')
 	{
 		$stati = array(
@@ -417,6 +446,7 @@
 			header("HTTP/1.1 {$code} {$text}", TRUE, $code);
 		}
 	}
+}
 
 // --------------------------------------------------------------------
 
@@ -434,6 +464,8 @@
 * @access	private
 * @return	void
 */
+if ( ! function_exists('_exception_handler'))
+{
 	function _exception_handler($severity, $message, $filepath, $line)
 	{
 		 // We don't bother with "strict" notices since they tend to fill up
@@ -463,19 +495,22 @@
 
 		$_error->log_exception($severity, $message, $filepath, $line);
 	}
+}
 
-	// --------------------------------------------------------------------
+// --------------------------------------------------------------------
 
-	/**
-	 * Remove Invisible Characters
-	 *
-	 * This prevents sandwiching null characters
-	 * between ascii characters, like Java\0script.
-	 *
-	 * @access	public
-	 * @param	string
-	 * @return	string
-	 */
+/**
+ * Remove Invisible Characters
+ *
+ * This prevents sandwiching null characters
+ * between ascii characters, like Java\0script.
+ *
+ * @access	public
+ * @param	string
+ * @return	string
+ */
+if ( ! function_exists('remove_invisible_characters'))
+{
 	function remove_invisible_characters($str, $url_encoded = TRUE)
 	{
 		$non_displayables = array();
@@ -499,7 +534,7 @@
 
 		return $str;
 	}
-
+}
 
 /* End of file Common.php */
 /* Location: ./system/core/Common.php */
\ No newline at end of file
diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php
index 9ceac0b..52bad26 100644
--- a/system/database/DB_active_rec.php
+++ b/system/database/DB_active_rec.php
@@ -60,7 +60,7 @@
 	var $ar_cache_set			= array();
 	
 	var $ar_no_escape 			= array();
-
+	var $ar_cache_no_escape     = array();
 
 	// --------------------------------------------------------------------
 
@@ -93,6 +93,7 @@
 				{
 					$this->ar_cache_select[] = $val;
 					$this->ar_cache_exists[] = 'select';
+					$this->ar_cache_no_escape[] = $escape;
 				}
 			}
 		}
@@ -1933,16 +1934,17 @@
 	{
 		$this->_reset_run(
 							array(
-									'ar_cache_select'	=> array(),
-									'ar_cache_from'		=> array(),
-									'ar_cache_join'		=> array(),
-									'ar_cache_where'	=> array(),
-									'ar_cache_like'		=> array(),
-									'ar_cache_groupby'	=> array(),
-									'ar_cache_having'	=> array(),
-									'ar_cache_orderby'	=> array(),
-									'ar_cache_set'		=> array(),
-									'ar_cache_exists'	=> array()
+									'ar_cache_select'		=> array(),
+									'ar_cache_from'			=> array(),
+									'ar_cache_join'			=> array(),
+									'ar_cache_where'		=> array(),
+									'ar_cache_like'			=> array(),
+									'ar_cache_groupby'		=> array(),
+									'ar_cache_having'		=> array(),
+									'ar_cache_orderby'		=> array(),
+									'ar_cache_set'			=> array(),
+									'ar_cache_exists'		=> array(),
+									'ar_cache_no_escape'	=> array()
 								)
 							);
 	}
@@ -1984,6 +1986,8 @@
 		{
 			$this->_track_aliases($this->ar_from);
 		}
+
+		$this->ar_no_escape = $this->ar_cache_no_escape;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/DB_result.php b/system/database/DB_result.php
index 76e1d6a..0c4e781 100644
--- a/system/database/DB_result.php
+++ b/system/database/DB_result.php
@@ -28,14 +28,14 @@
  */
 class CI_DB_result {
 
-	var $conn_id		      = NULL;
-	var $result_id		      = NULL;
-	var $result_array	      = array();
-	var $result_object	      = array();
-    var $custom_result_object = array();
-	var $current_row	      = 0;
-	var $num_rows		      = 0;
-	var $row_data		      = NULL;
+	var $conn_id				= NULL;
+	var $result_id				= NULL;
+	var $result_array			= array();
+	var $result_object			= array();
+	var $custom_result_object	= array();
+	var $current_row			= 0;
+	var $num_rows				= 0;
+	var $row_data				= NULL;
 
 
 	/**
@@ -47,47 +47,52 @@
 	 */
 	function result($type = 'object')
 	{
-        if ($type == 'array') return $this->result_array();
-        else if ($type == 'object') return $this->result_object();
-        else return $this->custom_result_object($type);
+		if ($type == 'array') return $this->result_array();
+		else if ($type == 'object') return $this->result_object();
+		else return $this->custom_result_object($type);
 	}
 
 	// --------------------------------------------------------------------
 
-    /**
-     * Custom query result.
-     *
-     * @param  class_name  A string that represents the type of object you want back
-     * @return array of objects
-     */
-    function custom_result_object($class_name)
-    {
-        if (array_key_exists($class_name, $this->custom_result_object))
-        {
-            return $this->custom_result_object[$class_name];
-        }
-        
-        if ($this->result_id === FALSE OR $this->num_rows() == 0)
-        {
-            return array();
-        }
+	/**
+	 * Custom query result.
+	 *
+	 * @param class_name A string that represents the type of object you want back
+	 * @return array of objects
+	 */
+	function custom_result_object($class_name)
+	{
+		if (array_key_exists($class_name, $this->custom_result_object))
+		{
+			return $this->custom_result_object[$class_name];
+		}
 
-        // add the data to the object
-        $this->_data_seek(0);
-        $result_object = array();
+		if ($this->result_id === FALSE OR $this->num_rows() == 0)
+		{
+			return array();
+		}
+
+		// add the data to the object
+		$this->_data_seek(0);
+		$result_object = array();
+
 		while ($row = $this->_fetch_object())
-        {
-            $object = new $class_name();
-            foreach ($row as $key => $value)
-            {
-                $object->$key = $value;
-            }
+		{
+			$object = new $class_name();
+			
+			foreach ($row as $key => $value)
+			{
+				$object->$key = $value;
+			}
+			
 			$result_object[] = $object;
 		}
 
-        // return the array
-        return $this->custom_result_object[$class_name] = $result_object;
-    }
+		// return the array
+		return $this->custom_result_object[$class_name] = $result_object;
+	}
+
+	// --------------------------------------------------------------------
 
 	/**
 	 * Query result.  "object" version.
@@ -180,9 +185,9 @@
 			$n = 0;
 		}
 
-        if ($type == 'object') return $this->row_object($n);
-        else if ($type == 'array') return $this->row_array($n);
-        else return $this->custom_row_object($n, $type);
+		if ($type == 'object') return $this->row_object($n);
+		else if ($type == 'array') return $this->row_array($n);
+		else return $this->custom_row_object($n, $type);
 	}
 
 	// --------------------------------------------------------------------
@@ -219,7 +224,7 @@
 
 	// --------------------------------------------------------------------
 
-    /**
+	/**
 	 * Returns a single result row - custom object version
 	 *
 	 * @access	public
@@ -242,7 +247,7 @@
 		return $result[$this->current_row];
 	}
 
-    /**
+	/**
 	 * Returns a single result row - object version
 	 *
 	 * @access	public
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index b7d547c..28c75a5 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -54,6 +54,9 @@
 	var $_count_string = 'SELECT COUNT(*) AS ';
 	var $_random_keyword = ' RAND()'; // database specific random keyword
 
+	// whether SET NAMES must be used to set the character set
+	var $use_set_names;
+	
 	/**
 	 * Non-persistent database connection
 	 *
@@ -132,15 +135,13 @@
 	 */
 	function db_set_charset($charset, $collation)
 	{
-		static $use_set_names;
-		
-		if ( ! isset($use_set_names))
+		if ( ! isset($this->use_set_names))
 		{
 			// mysql_set_charset() requires PHP >= 5.2.3 and MySQL >= 5.0.7, use SET NAMES as fallback
-			$use_set_names = (version_compare(PHP_VERSION, '5.2.3', '>=') && version_compare(mysql_get_server_info(), '5.0.7', '>=')) ? FALSE : TRUE;
+			$this->use_set_names = (version_compare(PHP_VERSION, '5.2.3', '>=') && version_compare(mysql_get_server_info(), '5.0.7', '>=')) ? FALSE : TRUE;
 		}
 
-		if ($use_set_names)
+		if ($this->use_set_names === TRUE)
 		{
 			return @mysql_query("SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'", $this->conn_id);
 		}
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index b8586c2..b1796c9 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -54,6 +54,9 @@
 	 */
 	var $delete_hack = TRUE;
 
+	// whether SET NAMES must be used to set the character set
+	var $use_set_names;
+	
 	// --------------------------------------------------------------------
 
 	/**
@@ -132,15 +135,13 @@
 	 */
 	function _db_set_charset($charset, $collation)
 	{
-		static $use_set_names;
-		
-		if ( ! isset($use_set_names))
+		if ( ! isset($this->use_set_names))
 		{
 			// mysqli_set_charset() requires MySQL >= 5.0.7, use SET NAMES as fallback
-			$use_set_names = (version_compare(mysqli_get_server_info($this->conn_id), '5.0.7', '>=')) ? FALSE : TRUE;
+			$this->use_set_names = (version_compare(mysqli_get_server_info($this->conn_id), '5.0.7', '>=')) ? FALSE : TRUE;
 		}
 
-		if ($use_set_names)
+		if ($this->use_set_names === TRUE)
 		{
 			return @mysqli_query($this->conn_id, "SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'");
 		}
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 47ff362..1403968 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -554,6 +554,24 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Insert_batch statement
+	 *
+	 * Generates a platform-specific insert string from the supplied data
+	 *
+	 * @access  public
+	 * @param   string  the table name
+	 * @param   array   the insert keys
+	 * @param   array   the insert values
+	 * @return  string
+	 */
+	function _insert_batch($table, $keys, $values)
+	{
+		return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Update statement
 	 *
 	 * Generates a platform-specific update string from the supplied data
diff --git a/system/language/english/form_validation_lang.php b/system/language/english/form_validation_lang.php
index 3f24090..3418f29 100644
--- a/system/language/english/form_validation_lang.php
+++ b/system/language/english/form_validation_lang.php
@@ -17,6 +17,7 @@
 $lang['integer']			= "The %s field must contain an integer.";
 $lang['regex_match']		= "The %s field is not in the correct format.";
 $lang['matches']			= "The %s field does not match the %s field.";
+$lang['is_unique'] 			= "The %s field must contain a unique value.";
 $lang['is_natural']			= "The %s field must contain only positive numbers.";
 $lang['is_natural_no_zero']	= "The %s field must contain a number greater than zero.";
 $lang['decimal']			= "The %s field must contain a decimal number.";
diff --git a/system/language/english/migration_lang.php b/system/language/english/migration_lang.php
new file mode 100644
index 0000000..4763ca2
--- /dev/null
+++ b/system/language/english/migration_lang.php
@@ -0,0 +1,13 @@
+<?php
+
+$lang['migration_none_found']			= "No migrations were found.";
+$lang['migration_not_found']			= "This migration could not be found.";
+$lang['migration_multiple_version']		= "This are multiple migrations with the same version number: %d.";
+$lang['migration_class_doesnt_exist']	= "The migration class \"%s\" could not be found.";
+$lang['migration_missing_up_method']	= "The migration class \"%s\" is missing an 'up' method.";
+$lang['migration_missing_down_method']	= "The migration class \"%s\" is missing an 'up' method.";
+$lang['migration_invalid_filename']		= "Migration \"%s\" has an invalid filename.";
+
+
+/* End of file migration_lang.php */
+/* Location: ./system/language/english/migration_lang.php */
\ No newline at end of file
diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php
index d1925c0..c32f2c1 100644
--- a/system/libraries/Driver.php
+++ b/system/libraries/Driver.php
@@ -43,11 +43,11 @@
 
 		// The class will be prefixed with the parent lib
 		$child_class = $this->lib_name.'_'.$child;
-
+	
 		// Remove the CI_ prefix and lowercase
-		$lib_name = ucfirst(strtolower(preg_replace('/^CI_/', '', $this->lib_name)));
-		$driver_name = strtolower(preg_replace('/^CI_/', '', $child_class));
-
+		$lib_name = ucfirst(strtolower(str_replace('CI_', '', $this->lib_name)));
+		$driver_name = strtolower(str_replace('CI_', '', $child_class));
+		
 		if (in_array($driver_name, array_map('strtolower', $this->valid_drivers)))
 		{
 			// check and see if the driver is in a separate file
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index 6f79a55..d370d75 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -26,16 +26,15 @@
  */
 class CI_Form_validation {
 
-	var $CI;
-	var $_field_data			= array();
-	var $_config_rules			= array();
-	var $_error_array			= array();
-	var $_error_messages		= array();
-	var $_error_prefix			= '<p>';
-	var $_error_suffix			= '</p>';
-	var $error_string			= '';
-	var $_safe_form_data		= FALSE;
-
+	protected $CI;
+	protected $_field_data			= array();
+	protected $_config_rules		= array();
+	protected $_error_array			= array();
+	protected $_error_messages		= array();
+	protected $_error_prefix		= '<p>';
+	protected $_error_suffix		= '</p>';
+	protected $error_string			= '';
+	protected $_safe_form_data		= FALSE;
 
 	/**
 	 * Constructor
@@ -72,7 +71,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function set_rules($field, $label = '', $rules = '')
+	public function set_rules($field, $label = '', $rules = '')
 	{
 		// No reason to set rules if we have no POST data
 		if (count($_POST) == 0)
@@ -163,7 +162,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function set_message($lang, $val = '')
+	public function set_message($lang, $val = '')
 	{
 		if ( ! is_array($lang))
 		{
@@ -187,7 +186,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
+	public function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
 	{
 		$this->_error_prefix = $prefix;
 		$this->_error_suffix = $suffix;
@@ -206,7 +205,7 @@
 	 * @param	string	the field name
 	 * @return	void
 	 */
-	function error($field = '', $prefix = '', $suffix = '')
+	public function error($field = '', $prefix = '', $suffix = '')
 	{
 		if ( ! isset($this->_field_data[$field]['error']) OR $this->_field_data[$field]['error'] == '')
 		{
@@ -238,7 +237,7 @@
 	 * @param	string
 	 * @return	str
 	 */
-	function error_string($prefix = '', $suffix = '')
+	public function error_string($prefix = '', $suffix = '')
 	{
 		// No errrors, validation passes!
 		if (count($this->_error_array) === 0)
@@ -279,7 +278,7 @@
 	 * @access	public
 	 * @return	bool
 	 */
-	function run($group = '')
+	public function run($group = '')
 	{
 		// Do we even have any data to process?  Mm?
 		if (count($_POST) == 0)
@@ -374,7 +373,7 @@
 	 * @param	integer
 	 * @return	mixed
 	 */
-	function _reduce_array($array, $keys, $i = 0)
+	protected function _reduce_array($array, $keys, $i = 0)
 	{
 		if (is_array($array))
 		{
@@ -406,7 +405,7 @@
 	 * @access	private
 	 * @return	null
 	 */
-	function _reset_post_array()
+	protected function _reset_post_array()
 	{
 		foreach ($this->_field_data as $field => $row)
 		{
@@ -468,7 +467,7 @@
 	 * @param	integer
 	 * @return	mixed
 	 */
-	function _execute($row, $rules, $postdata = NULL, $cycles = 0)
+	protected function _execute($row, $rules, $postdata = NULL, $cycles = 0)
 	{
 		// If the $_POST data is an array we will run a recursive call
 		if (is_array($postdata))
@@ -695,7 +694,7 @@
 	 * @param	string	the field name
 	 * @return	string
 	 */
-	function _translate_fieldname($fieldname)
+	protected function _translate_fieldname($fieldname)
 	{
 		// Do we need to translate the field name?
 		// We look for the prefix lang: to determine this
@@ -727,7 +726,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function set_value($field = '', $default = '')
+	public function set_value($field = '', $default = '')
 	{
 		if ( ! isset($this->_field_data[$field]))
 		{
@@ -757,7 +756,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function set_select($field = '', $value = '', $default = FALSE)
+	public function set_select($field = '', $value = '', $default = FALSE)
 	{
 		if ( ! isset($this->_field_data[$field]) OR ! isset($this->_field_data[$field]['postdata']))
 		{
@@ -801,7 +800,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function set_radio($field = '', $value = '', $default = FALSE)
+	public function set_radio($field = '', $value = '', $default = FALSE)
 	{
 		if ( ! isset($this->_field_data[$field]) OR ! isset($this->_field_data[$field]['postdata']))
 		{
@@ -845,7 +844,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function set_checkbox($field = '', $value = '', $default = FALSE)
+	public function set_checkbox($field = '', $value = '', $default = FALSE)
 	{
 		if ( ! isset($this->_field_data[$field]) OR ! isset($this->_field_data[$field]['postdata']))
 		{
@@ -885,7 +884,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function required($str)
+	public function required($str)
 	{
 		if ( ! is_array($str))
 		{
@@ -907,7 +906,7 @@
 	 * @param	regex
 	 * @return	bool
 	 */
-	function regex_match($str, $regex)
+	public function regex_match($str, $regex)
 	{
 		if ( ! preg_match($regex, $str))
 		{
@@ -927,7 +926,7 @@
 	 * @param	field
 	 * @return	bool
 	 */
-	function matches($str, $field)
+	public function matches($str, $field)
 	{
 		if ( ! isset($_POST[$field]))
 		{
@@ -938,6 +937,24 @@
 
 		return ($str !== $field) ? FALSE : TRUE;
 	}
+	
+	// --------------------------------------------------------------------
+
+	/**
+	 * Match one field to another
+	 *
+	 * @access	public
+	 * @param	string
+	 * @param	field
+	 * @return	bool
+	 */
+	public function is_unique($str, $field)
+	{
+		list($table, $field)=explode('.', $field);
+		$query = $this->CI->db->limit(1)->get_where($table, array($field => $str));
+		
+		return $query->num_rows() === 0;
+    }
 
 	// --------------------------------------------------------------------
 
@@ -949,7 +966,7 @@
 	 * @param	value
 	 * @return	bool
 	 */
-	function min_length($str, $val)
+	public function min_length($str, $val)
 	{
 		if (preg_match("/[^0-9]/", $val))
 		{
@@ -974,7 +991,7 @@
 	 * @param	value
 	 * @return	bool
 	 */
-	function max_length($str, $val)
+	public function max_length($str, $val)
 	{
 		if (preg_match("/[^0-9]/", $val))
 		{
@@ -999,7 +1016,7 @@
 	 * @param	value
 	 * @return	bool
 	 */
-	function exact_length($str, $val)
+	public function exact_length($str, $val)
 	{
 		if (preg_match("/[^0-9]/", $val))
 		{
@@ -1023,7 +1040,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function valid_email($str)
+	public function valid_email($str)
 	{
 		return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $str)) ? FALSE : TRUE;
 	}
@@ -1037,7 +1054,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function valid_emails($str)
+	public function valid_emails($str)
 	{
 		if (strpos($str, ',') === FALSE)
 		{
@@ -1064,7 +1081,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function valid_ip($ip)
+	public function valid_ip($ip)
 	{
 		return $this->CI->input->valid_ip($ip);
 	}
@@ -1078,7 +1095,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function alpha($str)
+	public function alpha($str)
 	{
 		return ( ! preg_match("/^([a-z])+$/i", $str)) ? FALSE : TRUE;
 	}
@@ -1092,7 +1109,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function alpha_numeric($str)
+	public function alpha_numeric($str)
 	{
 		return ( ! preg_match("/^([a-z0-9])+$/i", $str)) ? FALSE : TRUE;
 	}
@@ -1106,7 +1123,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function alpha_dash($str)
+	public function alpha_dash($str)
 	{
 		return ( ! preg_match("/^([-a-z0-9_-])+$/i", $str)) ? FALSE : TRUE;
 	}
@@ -1120,7 +1137,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function numeric($str)
+	public function numeric($str)
 	{
 		return (bool)preg_match( '/^[\-+]?[0-9]*\.?[0-9]+$/', $str);
 
@@ -1135,7 +1152,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function is_numeric($str)
+	public function is_numeric($str)
 	{
 		return ( ! is_numeric($str)) ? FALSE : TRUE;
 	}
@@ -1149,7 +1166,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function integer($str)
+	public function integer($str)
 	{
 		return (bool) preg_match('/^[\-+]?[0-9]+$/', $str);
 	}
@@ -1163,7 +1180,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function decimal($str)
+	public function decimal($str)
 	{
 		return (bool) preg_match('/^[\-+]?[0-9]+\.[0-9]+$/', $str);
 	}
@@ -1177,7 +1194,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function greater_than($str, $min)
+	public function greater_than($str, $min)
 	{
 		if ( ! is_numeric($str))
 		{
@@ -1195,7 +1212,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function less_than($str, $max)
+	public function less_than($str, $max)
 	{
 		if ( ! is_numeric($str))
 		{
@@ -1213,7 +1230,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function is_natural($str)
+	public function is_natural($str)
 	{
 		return (bool) preg_match( '/^[0-9]+$/', $str);
 	}
@@ -1227,7 +1244,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function is_natural_no_zero($str)
+	public function is_natural_no_zero($str)
 	{
 		if ( ! preg_match( '/^[0-9]+$/', $str))
 		{
@@ -1254,7 +1271,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function valid_base64($str)
+	public function valid_base64($str)
 	{
 		return (bool) ! preg_match('/[^a-zA-Z0-9\/\+=]/', $str);
 	}
@@ -1271,7 +1288,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function prep_for_form($data = '')
+	public function prep_for_form($data = '')
 	{
 		if (is_array($data))
 		{
@@ -1300,7 +1317,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function prep_url($str = '')
+	public function prep_url($str = '')
 	{
 		if ($str == 'http://' OR $str == '')
 		{
@@ -1324,7 +1341,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function strip_image_tags($str)
+	public function strip_image_tags($str)
 	{
 		return $this->CI->input->strip_image_tags($str);
 	}
@@ -1338,7 +1355,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function xss_clean($str)
+	public function xss_clean($str)
 	{
 		return $this->CI->security->xss_clean($str);
 	}
@@ -1352,7 +1369,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function encode_php_tags($str)
+	public function encode_php_tags($str)
 	{
 		return str_replace(array('<?php', '<?PHP', '<?', '?>'),  array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);
 	}
@@ -1361,4 +1378,4 @@
 // END Form Validation Class
 
 /* End of file Form_validation.php */
-/* Location: ./system/libraries/Form_validation.php */
+/* Location: ./system/libraries/Form_validation.php */
\ No newline at end of file
diff --git a/system/libraries/Migration.php b/system/libraries/Migration.php
new file mode 100644
index 0000000..3943ec1
--- /dev/null
+++ b/system/libraries/Migration.php
@@ -0,0 +1,338 @@
+<?php defined('BASEPATH') OR exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package		CodeIgniter
+ * @author		EllisLab Dev Team
+ * @copyright	Copyright (c) 2006 - 2011, EllisLab, Inc.
+ * @license		http://codeigniter.com/user_guide/license.html
+ * @link		http://codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Migration Class
+ *
+ * All migrations should implement this, forces up() and down() and gives
+ * access to the CI super-global.
+ *
+ * @package		CodeIgniter
+ * @subpackage	Libraries
+ * @category	Libraries
+ * @author		Reactor Engineers
+ * @link
+ */
+class CI_Migration {
+
+	protected $_migration_enabled = FALSE;
+	protected $_migration_path = NULL;
+	protected $_migration_version = 0;
+
+	protected $_error_string = '';
+
+	public function __construct($config = array())
+	{
+		# Only run this constructor on main library load
+		if (get_parent_class($this) !== FALSE)
+		{
+			return;
+		}
+
+		foreach ($config as $key => $val)
+		{
+			$this->{'_' . $key} = $val;
+		}
+
+		log_message('debug', 'Migrations class initialized');
+
+		// Are they trying to use migrations while it is disabled?
+		if ($this->_migration_enabled !== TRUE)
+		{
+			show_error('Migrations has been loaded but is disabled or set up incorrectly.');
+		}
+
+		// If not set, set it
+		$this->_migration_path == '' OR $this->_migration_path = APPPATH . 'migrations/';
+
+		// Add trailing slash if not set
+		$this->_migration_path = rtrim($this->_migration_path, '/').'/';
+
+		// Load migration language
+		$this->lang->load('migration');
+
+		// They'll probably be using dbforge
+		$this->load->dbforge();
+
+		// If the migrations table is missing, make it
+		if ( ! $this->db->table_exists('migrations'))
+		{
+			$this->dbforge->add_field(array(
+				'version' => array('type' => 'INT', 'constraint' => 3),
+			));
+
+			$this->dbforge->create_table('migrations', TRUE);
+
+			$this->db->insert('migrations', array('version' => 0));
+		}
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Migrate to a schema version
+	 *
+	 * Calls each migration step required to get to the schema version of
+	 * choice
+	 *
+	 * @access	public
+	 * @param $version integer	Target schema version
+	 * @return	mixed	TRUE if already latest, FALSE if failed, int if upgraded
+	 */
+	public function version($target_version)
+	{
+		$start = $current_version = $this->_get_version();
+		$stop = $target_version;
+
+		if ($target_version > $current_version)
+		{
+			// Moving Up
+			++$start;
+			++$stop;
+			$step = 1;
+		}
+
+		else
+		{
+			// Moving Down
+			$step = -1;
+		}
+		
+		$method = $step === 1 ? 'up' : 'down';
+		$migrations = array();
+
+		// We now prepare to actually DO the migrations
+		// But first let's make sure that everything is the way it should be
+		for ($i = $start; $i != $stop; $i += $step)
+		{
+			$f = glob(sprintf($this->_migration_path . '%03d_*.php', $i));
+
+			// Only one migration per step is permitted
+			if (count($f) > 1)
+			{
+				$this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $i);
+				return FALSE;
+			}
+
+			// Migration step not found
+			if (count($f) == 0)
+			{
+				// If trying to migrate up to a version greater than the last
+				// existing one, migrate to the last one.
+				if ($step == 1)
+				{
+					break;
+				}
+
+				// If trying to migrate down but we're missing a step,
+				// something must definitely be wrong.
+				$this->_error_string = sprintf($this->lang->line('migration_not_found'), $i);
+				return FALSE;
+			}
+
+			$file = basename($f[0]);
+			$name = basename($f[0], '.php');
+
+			// Filename validations
+			if (preg_match('/^\d{3}_(\w+)$/', $name, $match))
+			{
+				$match[1] = strtolower($match[1]);
+
+				// Cannot repeat a migration at different steps
+				if (in_array($match[1], $migrations))
+				{
+					$this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $match[1]);
+					return FALSE;
+				}
+
+				include $f[0];
+				$class = 'Migration_' . ucfirst($match[1]);
+
+				if ( ! class_exists($class))
+				{
+					$this->_error_string = sprintf($this->lang->line('migration_class_doesnt_exist'), $class);
+					return FALSE;
+				}
+
+				if ( ! is_callable(array($class, $method)))
+				{
+					$this->_error_string = sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class);
+					return FALSE;
+				}
+
+				$migrations[] = $match[1];
+			}
+			else
+			{
+				$this->_error_string = sprintf($this->lang->line('migration_invalid_filename'), $file);
+				return FALSE;
+			}
+		}
+
+		log_message('debug', 'Current migration: ' . $current_version);
+
+		$version = $i + ($step == 1 ? -1 : 0);
+
+		// If there is nothing to do so quit
+		if ($migrations === array())
+		{
+			return TRUE;
+		}
+
+		log_message('debug', 'Migrating from ' . $method . ' to version ' . $version);
+
+		// Loop through the migrations
+		foreach ($migrations AS $migration)
+		{
+			// Run the migration class
+			$class = 'Migration_' . ucfirst(strtolower($migration));
+			call_user_func(array(new $class, $method));
+
+			$current_version += $step;
+			$this->_update_version($current_version);
+		}
+
+		log_message('debug', 'Finished migrating to '.$current_version);
+
+		return $current_version;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set's the schema to the latest migration
+	 *
+	 * @access	public
+	 * @return	mixed	true if already latest, false if failed, int if upgraded
+	 */
+	public function latest()
+	{
+		if ( ! $migrations = $this->find_migrations())
+		{
+			$this->_error_string = $this->line->lang('migration_none_found');
+			return false;
+		}
+
+		$last_migration = basename(end($migrations));
+		
+		// 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));
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set's the schema to the migration version set in config
+	 *
+	 * @access	public
+	 * @return	mixed	true if already current, false if failed, int if upgraded
+	 */
+	public function current()
+	{
+		return $this->version($this->_migration_version);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Error string
+	 *
+	 * @access	public
+	 * @return	string	Error message returned as a string
+	 */
+	public function error_string()
+	{
+		return $this->_error_string;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set's the schema to the latest migration
+	 *
+	 * @access	protected
+	 * @return	mixed	true if already latest, false if failed, int if upgraded
+	 */
+	protected function find_migrations()
+	{
+		// Load all *_*.php files in the migrations path
+		$files = glob($this->_migration_path . '*_*.php');
+		$file_count = count($files);
+		
+		for ($i = 0; $i < $file_count; $i++)
+		{
+			// Mark wrongly formatted files as false for later filtering
+			$name = basename($files[$i], '.php');
+			if ( ! preg_match('/^\d{3}_(\w+)$/', $name))
+			{
+				$files[$i] = FALSE;
+			}
+		}
+		
+		sort($files);
+
+		return $files;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Retrieves current schema version
+	 *
+	 * @access	protected
+	 * @return	integer	Current Migration
+	 */
+	protected function _get_version()
+	{
+		$row = $this->db->get('migrations')->row();
+		return $row ? $row->version : 0;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Stores the current schema version
+	 *
+	 * @access	protected
+	 * @param $migrations integer	Migration reached
+	 * @return	void					Outputs a report of the migration
+	 */
+	protected function _update_version($migrations)
+	{
+		return $this->db->update('migrations', array(
+			'version' => $migrations
+		));
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Enable the use of CI super-global
+	 *
+	 * @access	public
+	 * @param $var
+	 * @return	mixed
+	 */
+	public function __get($var)
+	{
+		return get_instance()->$var;
+	}
+}
+
+/* End of file Migration.php */
+/* Location: ./system/libraries/Migration.php */
\ No newline at end of file
diff --git a/user_guide/changelog.html b/user_guide/changelog.html
index 76f9e5d..a841785 100644
--- a/user_guide/changelog.html
+++ b/user_guide/changelog.html
@@ -67,12 +67,14 @@
 		<ul>
 			<li>An improvement was made to the MySQL and MySQLi drivers to prevent exposing a potential vector for SQL injection on sites using multi-byte character sets in the database client connection.  <p>An incompatibility in PHP versions &lt; 5.2.3 and MySQL &lt; 5.0.7 with <em>mysql_set_charset()</em> creates a situation where using multi-byte  character sets on these environments may potentially expose a SQL injection attack vector.  Latin-1, UTF-8, and other "low ASCII" character sets are unaffected on all environments.</p>  <p class="critical">If you are running or considering running a multi-byte character set for your database connection, please pay close attention to the server environment you are deploying on to ensure you are not vulnerable.</p></li>
 		</ul>
+	</li>
 	<li>General Changes
 		<ul>
 			<li>Fixed a bug where there was a misspelling within a code comment in the index.php file.</li>
 			<li>Added Session Class userdata to the output profiler.  Additionally, added a show/hide toggle on HTTP Headers, Session Data and Config Variables.</li>
 			<li>Removed internal usage of the <samp>EXT</samp> constant.</li>
-			<li>Visual updates to the welcome_message view file and default error templates.  Thanks to <a href="https://bitbucket.org/danijelb">danijelb</a> for the pull request.</li>
+			<li>Visual updates to the welcome_message view file and default error templates. Thanks to <a href="https://bitbucket.org/danijelb">danijelb</a> for the pull request.</li>
+			<li>Added <samp>insert_batch()</samp> function to the PostgreSQL database driver. Thanks to epallerols for the patch.</li>
 		</ul>
 	</li>
 	<li>Helpers
@@ -83,6 +85,7 @@
 	<li>Libraries
 		<ul>
 			<li>Altered Session to use a longer match against the user_agent string. See upgrade notes if using database sessions.</li>
+			<li class="reactor">Added <kbd>is_unique</kbd> to the <a href="libraries/form_validation.html">Form Validation library</a>.</li>
 		</ul>
 	</li>
 </ul>
diff --git a/user_guide/database/configuration.html b/user_guide/database/configuration.html
index 51d11c9..4ea2e6b 100644
--- a/user_guide/database/configuration.html
+++ b/user_guide/database/configuration.html
@@ -132,8 +132,8 @@
 <li><strong>cache_on</strong> - TRUE/FALSE (boolean) - Whether database query caching is enabled, see also <a href="caching.html">Database Caching Class</a>.</li>
 <li><strong>cachedir</strong> - The absolute server path to your database query cache directory.</li>
 <li><strong>char_set</strong> - The character set used in communicating with the database.</li>
-<li><strong>dbcollat</strong> - The character collation used in communicating with the database. <p class="important"><strong>Note:</strong> For MySQL and MySQLi databases, this setting is only used as a backup if your server is running PHP &lt; 5.2.3 or MySQL &lt; 5.0.7.  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.</p></li>
-<li><strong>swap_pre</strong> - A default table prefix that should be swapped with <var>dbprefix</var>.  This is useful for distributed applications where you might run manually written queries, and need the prefix to still be customizable by the end user.</li>
+<li><strong>dbcollat</strong> - The character collation used in communicating with the database. <p class="important"><strong>Note:</strong> For MySQL and MySQLi databases, this setting is only used as a backup if your server is running PHP &lt; 5.2.3 or MySQL &lt; 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.</p></li>
+<li><strong>swap_pre</strong> - A default table prefix that should be swapped with <var>dbprefix</var>. This is useful for distributed applications where you might run manually written queries, and need the prefix to still be customizable by the end user.</li>
 <li><strong>autoinit</strong> - Whether or not to automatically connect to the database when the library loads. If set to false, the connection will take place prior to executing the first query.</li>
 <li><strong>stricton</strong> - TRUE/FALSE (boolean) - Whether to force "Strict Mode" connections, good for ensuring strict SQL while developing an application.</li>
 <li><strong>port</strong> - The database port number.  To use this value you have to add a line to the database config array.<code>$db['default']['port'] =  5432;</code>
diff --git a/user_guide/database/index.html b/user_guide/database/index.html
index fa3548c..9c67e3b 100644
--- a/user_guide/database/index.html
+++ b/user_guide/database/index.html
@@ -86,7 +86,7 @@
 
 <div id="footer">
 <p>
-Previous Topic:&nbsp;&nbsp;<a href="../libraries/config.html">Config Class</a>
+Previous Topic:&nbsp;&nbsp;<a href="../libraries/caching.html">Caching Class</a>
 &nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="#top">Top of Page</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="../index.html">User Guide Home</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
diff --git a/user_guide/database/utilities.html b/user_guide/database/utilities.html
index c488180..582ea2c 100644
--- a/user_guide/database/utilities.html
+++ b/user_guide/database/utilities.html
@@ -306,7 +306,7 @@
 &nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="#top">Top of Page</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="../index.html">User Guide Home</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
-Next Topic:&nbsp;&nbsp;<a href="../libraries/email.html"> Email Class</a></p>
+Next Topic:&nbsp;&nbsp;<a href="../libraries/javascript.html">Javascript Class</a></p>
 <p><a href="http://codeigniter.com">CodeIgniter</a> &nbsp;&middot;&nbsp; Copyright &#169; 2006 - 2011 &nbsp;&middot;&nbsp; <a href="http://ellislab.com/">EllisLab, Inc.</a></p>
 </div>
 
diff --git a/user_guide/general/security.html b/user_guide/general/security.html
index ab92a94..0609afc 100644
--- a/user_guide/general/security.html
+++ b/user_guide/general/security.html
@@ -76,15 +76,9 @@
 <li>Dash: -</li>
 </ul>
 
-<h2>GET, POST, and COOKIE Data</h2>
-
-<p>GET data is simply disallowed by CodeIgniter since the system utilizes URI segments rather than traditional URL query strings (unless
-you have the query string option enabled in your config file).  The global GET
-array is <strong>unset</strong> by the Input class during system initialization.</p>
-
 <h2>Register_globals</h2>
 
-<p>During system initialization all global variables are unset, except those found in the $_POST and $_COOKIE arrays. The unsetting
+<p>During system initialization all global variables are unset, except those found in the $_GET, $_POST, and $_COOKIE arrays. The unsetting
 routine is effectively the same as register_globals = off.</p>
 
 <a name="error_reporting"></a>
diff --git a/user_guide/helpers/array_helper.html b/user_guide/helpers/array_helper.html
index a196214..51c7ab5 100644
--- a/user_guide/helpers/array_helper.html
+++ b/user_guide/helpers/array_helper.html
@@ -159,10 +159,10 @@
 
 <div id="footer">
 <p>
-Previous Topic:&nbsp;&nbsp; <a href="../libraries/zip.html">Zip Encoding Class</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
+Previous Topic:&nbsp;&nbsp; <a href="../libraries/javascript.html">Javascript Class</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="#top">Top of Page</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="../index.html">User Guide Home</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
-Next Topic:&nbsp;&nbsp;<a href="compatibility_helper.html">Compatibility Helper</a></p>
+Next Topic:&nbsp;&nbsp;<a href="captcha_helper.html">CAPTCHA Helper</a></p>
 <p><a href="http://codeigniter.com">CodeIgniter</a> &nbsp;&middot;&nbsp; Copyright &#169; 2006 - 2011 &nbsp;&middot;&nbsp; <a href="http://ellislab.com/">EllisLab, Inc.</a></p>
 </div>
 
diff --git a/user_guide/helpers/captcha_helper.html b/user_guide/helpers/captcha_helper.html
index 2fd5a55..95ed672 100644
--- a/user_guide/helpers/captcha_helper.html
+++ b/user_guide/helpers/captcha_helper.html
@@ -183,11 +183,11 @@
 
 <div id="footer">
 <p>
-Previous Topic:&nbsp;&nbsp;<a href="url_helper.html">URL Helper</a>
+Previous Topic:&nbsp;&nbsp;<a href="array_helper.html">Array Helper</a>
 &nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="#top">Top of Page</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
-<a href="../index.html">User Guide Home</a>
-</p>
+<a href="../index.html">User Guide Home</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
+Next Topic:&nbsp;&nbsp;<a href="cookie_helper.html">Cookie Helper</a></p>
 <p><a href="http://codeigniter.com">CodeIgniter</a> &nbsp;&middot;&nbsp; Copyright &#169; 2006 - 2011 &nbsp;&middot;&nbsp; <a href="http://ellislab.com/">EllisLab, Inc.</a></p>
 </div>
 
diff --git a/user_guide/helpers/cookie_helper.html b/user_guide/helpers/cookie_helper.html
index 34faadb..4538631 100644
--- a/user_guide/helpers/cookie_helper.html
+++ b/user_guide/helpers/cookie_helper.html
@@ -95,7 +95,7 @@
 
 <div id="footer">
 <p>
-Previous Topic:&nbsp;&nbsp;<a href="compatibility_helper.html">Compatibility Helper</a>
+Previous Topic:&nbsp;&nbsp;<a href="captcha_helper.html">CAPTCHA Helper</a>
 &nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="#top">Top of Page</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="../index.html">User Guide Home</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
diff --git a/user_guide/images/appflowchart.gif b/user_guide/images/appflowchart.gif
index 422332c..4328e48 100644
--- a/user_guide/images/appflowchart.gif
+++ b/user_guide/images/appflowchart.gif
Binary files differ
diff --git a/user_guide/libraries/caching.html b/user_guide/libraries/caching.html
index 190232e..f94a3d1 100644
--- a/user_guide/libraries/caching.html
+++ b/user_guide/libraries/caching.html
@@ -180,11 +180,11 @@
 
 <div id="footer">
 <p>
-Previous Topic:&nbsp;&nbsp;<a href="errors.html">Error Handling</a>
+Previous Topic:&nbsp;&nbsp;<a href="zip.html">Zip Encoding Class</a>
 &nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="#top">Top of Page</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="../index.html">User Guide Home</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
-Next Topic:&nbsp;&nbsp;<a href="profiling.html">Profiling Your Application</a>
+Next Topic:&nbsp;&nbsp;<a href="../database/index.html">Database Class</a>
 </p>
 <p><a href="http://codeigniter.com">CodeIgniter</a> &nbsp;&middot;&nbsp; Copyright &#169; 2006 - 2011 &nbsp;&middot;&nbsp; <a href="http://ellislab.com/">EllisLab, Inc.</a></p>
 </div>
diff --git a/user_guide/libraries/form_validation.html b/user_guide/libraries/form_validation.html
index 8fdcd14..bba8f50 100644
--- a/user_guide/libraries/form_validation.html
+++ b/user_guide/libraries/form_validation.html
@@ -390,10 +390,10 @@
 <p>CodeIgniter lets you pipe multiple rules together.  Let's try it. Change your rules in the third parameter of rule setting function, like this:</p>
 
 <code>
-$this->form_validation->set_rules('username', 'Username', 'required|min_length[5]|max_length[12]');<br />
+$this->form_validation->set_rules('username', 'Username', 'required|min_length[5]|max_length[12]|is_unique[users.username]');<br />
 $this->form_validation->set_rules('password', 'Password', 'required|matches[passconf]');<br />
 $this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');<br />
-$this->form_validation->set_rules('email', 'Email', 'required|valid_email');<br />
+$this->form_validation->set_rules('email', 'Email', 'required|valid_email|is_unique[users.email]');<br />
 </code>
 
 <p>The above code sets the following rules:</p>
@@ -516,7 +516,7 @@
 
 class Form extends CI_Controller {
 
-	function index()
+	public function index()
 	{
 		$this->load->helper(array('form', 'url'));
 
@@ -525,7 +525,7 @@
 		$this->form_validation->set_rules('username', 'Username', 'callback_username_check');
 		$this->form_validation->set_rules('password', 'Password', 'required');
 		$this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');
-		$this->form_validation->set_rules('email', 'Email', 'required');
+		$this->form_validation->set_rules('email', 'Email', 'required|is_unique[users.email]');
 
 		if ($this->form_validation->run() == FALSE)
 		{
@@ -537,7 +537,7 @@
 		}
 	}
 
-	function username_check($str)
+	public function username_check($str)
 	{
 		if ($str == 'test')
 		{
@@ -947,6 +947,13 @@
 	</tr>
 
 	<tr>
+		<td class="td"><strong>is_unique</strong></td>
+		<td class="td">Yes</td>
+		<td class="td">Returns FALSE if the form element is not unique to the table and field name in the parameter.</td>
+		<td class="td">is_unique[table.field]</td>
+	</tr>
+
+	<tr>
 		<td class="td"><strong>min_length</strong></td>
 		<td class="td">Yes</td>
 		<td class="td">Returns FALSE if the form element is shorter then the parameter value.</td>
diff --git a/user_guide/libraries/javascript.html b/user_guide/libraries/javascript.html
index 4e26227..5b7ef43 100644
--- a/user_guide/libraries/javascript.html
+++ b/user_guide/libraries/javascript.html
@@ -2,7 +2,7 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
 
-<title>CodeIgniter User Guide : JavaScript Class</title>
+<title>JavaScript Class : CodeIgniter User Guide</title>
 
 <style type='text/css' media='all'>@import url('../userguide.css');</style>
 <link rel='stylesheet' type='text/css' media='all' href='../userguide.css' />
@@ -235,11 +235,11 @@
 
 <div id="footer">
 <p>
-Previous Topic:&nbsp;&nbsp;<a href="input.html">Input Class</a>
+Previous Topic:&nbsp;&nbsp;<a href="../database/index.html">Database Class</a>
 &nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="#top">Top of Page</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="../index.html">User Guide Home</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
-Next Topic:&nbsp;&nbsp;<a href="language.html">Language Class</a></p>
+Next Topic:&nbsp;&nbsp;<a href="../helpers/array_helper.html">Array Helper</a></p>
 <p><a href="http://codeigniter.com">CodeIgniter</a> &nbsp;&middot;&nbsp; Copyright &#169; 2006 - 2011 &nbsp;&middot;&nbsp; <a href="http://ellislab.com/">EllisLab, Inc.</a></p>
 </div>
 
diff --git a/user_guide/libraries/sessions.html b/user_guide/libraries/sessions.html
index a6f3c60..75ea0e6 100644
--- a/user_guide/libraries/sessions.html
+++ b/user_guide/libraries/sessions.html
@@ -105,8 +105,8 @@
 <ul>
 <li>The user's unique Session ID (this is a statistically random string with very strong entropy, hashed with MD5 for portability, and regenerated (by default) every five minutes)</li>
 <li>The user's IP Address</li>
-<li>The user's User Agent data (the first 50 characters of the browser data string)</li>
-<li>The "last activity"  time stamp.</li>
+<li>The user's User Agent data (the first 120 characters of the browser data string)</li>
+<li>The "last activity" time stamp.</li>
 </ul>
 
 <p>The above data is stored in a cookie as a serialized array with this prototype:</p>
diff --git a/user_guide/libraries/zip.html b/user_guide/libraries/zip.html
index 0311266..087b4ad 100644
--- a/user_guide/libraries/zip.html
+++ b/user_guide/libraries/zip.html
@@ -279,7 +279,7 @@
 &nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="#top">Top of Page</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
 <a href="../index.html">User Guide Home</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
-Next Topic:&nbsp;&nbsp;<a href="../helpers/array_helper.html">Array Helper</a>
+Next Topic:&nbsp;&nbsp;<a href="caching.html">Caching Class</a>
 </p>
 <p><a href="http://codeigniter.com">CodeIgniter</a> &nbsp;&middot;&nbsp; Copyright &#169; 2006 - 2011 &nbsp;&middot;&nbsp; <a href="http://ellislab.com/">EllisLab, Inc.</a></p>
 </div>
diff --git a/user_guide/nav/nav.js b/user_guide/nav/nav.js
index ce783fc..b44994d 100644
--- a/user_guide/nav/nav.js
+++ b/user_guide/nav/nav.js
@@ -50,6 +50,8 @@
 			'<li><a href="'+base+'general/helpers.html">Helpers</a></li>' +
 			'<li><a href="'+base+'general/libraries.html">Using CodeIgniter Libraries</a></li>' +
 			'<li><a href="'+base+'general/creating_libraries.html">Creating Your Own Libraries</a></li>' +
+			'<li><a href="'+base+'general/drivers.html">Using CodeIgniter Drivers</a></li>' +
+			'<li><a href="'+base+'general/creating_drivers.html">Creating Your Own Drivers</a></li>' +
 			'<li><a href="'+base+'general/core_classes.html">Creating Core Classes</a></li>' +
 			'<li><a href="'+base+'general/hooks.html">Hooks - Extending the Core</a></li>' +
 			'<li><a href="'+base+'general/autoloader.html">Auto-loading Resources</a></li>' +
diff --git a/user_guide/overview/appflow.html b/user_guide/overview/appflow.html
index bcbc43f..7c8d4ac 100644
--- a/user_guide/overview/appflow.html
+++ b/user_guide/overview/appflow.html
@@ -60,7 +60,7 @@
 
 <p>The following graphic illustrates how data flows throughout the system:</p>
 
-<div><img src="../images/appflowchart.gif" width="697" height="205" border="0" alt="CodeIgniter application flow" /></div>
+<div><img src="../images/appflowchart.gif" width="769" height="212" alt="CodeIgniter application flow"></div>
 
 
 <ol>
diff --git a/user_guide/toc.html b/user_guide/toc.html
index 4b4ab10..f6a5fe0 100644
--- a/user_guide/toc.html
+++ b/user_guide/toc.html
@@ -103,6 +103,8 @@
 	<li><a href="./general/helpers.html">Helpers</a></li>
 	<li><a href="./general/libraries.html">Using CodeIgniter Libraries</a></li>
 	<li><a href="./general/creating_libraries.html">Creating Your Own Libraries</a></li>
+	<li><a href="./general/drivers.html">Using CodeIgniter Drivers</a></li>
+	<li><a href="./general/creating_drivers.html">Creating Your Own Drivers</a></li>
 	<li><a href="./general/core_classes.html">Creating Core Classes</a></li>
 	<li><a href="./general/hooks.html">Hooks - Extending the Core</a></li>
 	<li><a href="./general/autoloader.html">Auto-loading Resources</a></li>