Merged recent Core changes and fixed conflict.
diff --git a/application/config/config.php b/application/config/config.php
index 26b31e3..1ec6543 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -10,8 +10,11 @@
 |
 |	http://example.com/
 |
+| If this is not set then CodeIgniter will guess the protocol, domain and
+| path to your installation.
+|
 */
-$config['base_url']	= "http://example.com/";
+$config['base_url']	= '';
 
 /*
 |--------------------------------------------------------------------------
@@ -23,7 +26,7 @@
 | variable so that it is blank.
 |
 */
-$config['index_page'] = "index.php";
+$config['index_page'] = 'index.php';
 
 /*
 |--------------------------------------------------------------------------
@@ -31,7 +34,7 @@
 |--------------------------------------------------------------------------
 |
 | This item determines which server global should be used to retrieve the
-| URI string.  The default setting of "AUTO" works for most servers.
+| URI string.  The default setting of 'AUTO' works for most servers.
 | If your links do not seem to work, try one of the other delicious flavors:
 |
 | 'AUTO'			Default - auto detects
@@ -41,7 +44,7 @@
 | 'ORIG_PATH_INFO'	Uses the ORIG_PATH_INFO
 |
 */
-$config['uri_protocol']	= "AUTO";
+$config['uri_protocol']	= 'AUTO';
 
 /*
 |--------------------------------------------------------------------------
@@ -54,7 +57,7 @@
 | http://codeigniter.com/user_guide/general/urls.html
 */
 
-$config['url_suffix'] = "";
+$config['url_suffix'] = '';
 
 /*
 |--------------------------------------------------------------------------
@@ -66,7 +69,7 @@
 | than english.
 |
 */
-$config['language']	= "english";
+$config['language']	= 'english';
 
 /*
 |--------------------------------------------------------------------------
@@ -77,14 +80,14 @@
 | that require a character set to be provided.
 |
 */
-$config['charset'] = "UTF-8";
+$config['charset'] = 'UTF-8';
 
 /*
 |--------------------------------------------------------------------------
 | Enable/Disable System Hooks
 |--------------------------------------------------------------------------
 |
-| If you would like to use the "hooks" feature you must enable it by
+| If you would like to use the 'hooks' feature you must enable it by
 | setting this variable to TRUE (boolean).  See the user guide for details.
 |
 */
@@ -134,12 +137,15 @@
 | By default CodeIgniter uses search-engine friendly segment based URLs:
 | example.com/who/what/where/
 |
+| By default CodeIgniter enables access to the $_GET array.  If for some
+| reason you would like to disable it, set 'allow_get_array' to FALSE.
+|
 | You can optionally enable standard query string based URLs:
 | example.com?who=me&what=something&where=here
 |
 | Options are: TRUE or FALSE (boolean)
 |
-| The other items let you set the query string "words" that will
+| The other items let you set the query string 'words' that will
 | invoke your controllers and its functions:
 | example.com/index.php?c=controller&m=function
 |
@@ -148,6 +154,7 @@
 | use segment based URLs.
 |
 */
+$config['allow_get_array']		= TRUE;
 $config['enable_query_strings'] = FALSE;
 $config['controller_trigger']	= 'c';
 $config['function_trigger']		= 'm';
@@ -181,7 +188,7 @@
 |--------------------------------------------------------------------------
 |
 | Leave this BLANK unless you would like to set something other than the default
-| system/logs/ folder.  Use a full server path with trailing slash.
+| application/logs/ folder. Use a full server path with trailing slash.
 |
 */
 $config['log_path'] = '';
@@ -217,7 +224,7 @@
 | MUST set an encryption key.  See the user guide for info.
 |
 */
-$config['encryption_key'] = "";
+$config['encryption_key'] = '';
 
 /*
 |--------------------------------------------------------------------------
@@ -281,9 +288,15 @@
 | Enables a CSRF cookie token to be set. When set to TRUE, token will be
 | checked on a submitted form. If you are accepting user data, it is strongly
 | recommended CSRF protection be enabled.
+|
+| 'csrf_token_name' = The token name
+| 'csrf_cookie_name' = The cookie name
+| 'csrf_expire' = The number in seconds the token should expire.
 */
 $config['csrf_protection'] = FALSE;
-
+$config['csrf_token_name'] = 'csrf_test_name';
+$config['csrf_cookie_name'] = 'csrf_cookie_name';
+$config['csrf_expire'] = 7200;
 
 /*
 |--------------------------------------------------------------------------
@@ -299,7 +312,7 @@
 | means you are prematurely outputting something to your browser. It could
 | even be a line of whitespace at the end of one of your scripts.  For
 | compression to work, nothing can be sent before the output buffer is called
-| by the output class.  Do not "echo" any values with compression enabled.
+| by the output class.  Do not 'echo' any values with compression enabled.
 |
 */
 $config['compress_output'] = FALSE;
@@ -309,9 +322,9 @@
 | Master Time Reference
 |--------------------------------------------------------------------------
 |
-| Options are "local" or "gmt".  This pref tells the system whether to use
-| your server's local time as the master "now" reference, or convert it to
-| GMT.  See the "date helper" page of the user guide for information
+| Options are 'local' or 'gmt'.  This pref tells the system whether to use
+| your server's local time as the master 'now' reference, or convert it to
+| GMT.  See the 'date helper' page of the user guide for information
 | regarding date handling.
 |
 */
@@ -346,4 +359,4 @@
 
 
 /* End of file config.php */
-/* Location: ./application/config/config.php */
\ No newline at end of file
+/* Location: ./application/config/config.php */
diff --git a/application/config/foreign_chars.php b/application/config/foreign_chars.php
index e106ad8..14b0d73 100644
--- a/application/config/foreign_chars.php
+++ b/application/config/foreign_chars.php
@@ -7,58 +7,58 @@
 | conversion used by the Text helper
 |
 */
-$foreign_characters = array('223'	=>	"ss", // ß
-							'224'	=>	"a",
-							'225'	=>	"a",
-							'226'	=>	"a",
-							'229'	=>	"a",
-							'227'	=>	"ae",
-							'230'	=>	"ae",
-							'228'	=>	"ae",
-							'231'	=>	"c",
-							'232'	=>	"e",  // è
-							'233'	=>	"e",  // é
-							'234'	=>	"e",  // ê
-							'235'	=>	"e",  // ë
-							'236'	=>	"i",
-							'237'	=>	"i",
-							'238'	=>	"i",
-							'239'	=>	"i",
-							'241'	=>	"n",
-							'242'	=>	"o",
-							'243'	=>	"o",
-							'244'	=>	"o",
-							'245'	=>	"o",
-							'246'	=>	"oe", // ö
-							'249'	=>	"u",
-							'250'	=>	"u",
-							'251'	=>	"u",
-							'252'	=>	"ue", // ü
-							'255'	=>	"y",
-							'257'	=>	"aa",
-							'269'	=>	"ch",
-							'275'	=>	"ee",
-							'291'	=>	"gj",
-							'299'	=>	"ii",
-							'311'	=>	"kj",
-							'316'	=>	"lj",
-							'326'	=>	"nj",
-							'353'	=>	"sh",
-							'363'	=>	"uu",
-							'382'	=>	"zh",
-							'256'	=>	"aa",
-							'268'	=>	"ch",
-							'274'	=>	"ee",
-							'290'	=>	"gj",
-							'298'	=>	"ii",
-							'310'	=>	"kj",
-							'315'	=>	"lj",
-							'325'	=>	"nj",
-							'352'	=>	"sh",
-							'362'	=>	"uu",
-							'381'	=>	"zh",
-							);
-
+$foreign_characters = array(
+	'/ä|æ|ǽ/' => 'ae',
+	'/ö|œ/' => 'oe',
+	'/ü/' => 'ue',
+	'/Ä/' => 'Ae',
+	'/Ü/' => 'Ue',
+	'/Ö/' => 'Oe',
+	'/À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ/' => 'A',
+	'/à|á|â|ã|å|ǻ|ā|ă|ą|ǎ|ª/' => 'a',
+	'/Ç|Ć|Ĉ|Ċ|Č/' => 'C',
+	'/ç|ć|ĉ|ċ|č/' => 'c',
+	'/Ð|Ď|Đ/' => 'D',
+	'/ð|ď|đ/' => 'd',
+	'/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě/' => 'E',
+	'/è|é|ê|ë|ē|ĕ|ė|ę|ě/' => 'e',
+	'/Ĝ|Ğ|Ġ|Ģ/' => 'G',
+	'/ĝ|ğ|ġ|ģ/' => 'g',
+	'/Ĥ|Ħ/' => 'H',
+	'/ĥ|ħ/' => 'h',
+	'/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ/' => 'I',
+	'/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı/' => 'i',
+	'/Ĵ/' => 'J',
+	'/ĵ/' => 'j',
+	'/Ķ/' => 'K',
+	'/ķ/' => 'k',
+	'/Ĺ|Ļ|Ľ|Ŀ|Ł/' => 'L',
+	'/ĺ|ļ|ľ|ŀ|ł/' => 'l',
+	'/Ñ|Ń|Ņ|Ň/' => 'N',
+	'/ñ|ń|ņ|ň|ʼn/' => 'n',
+	'/Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ/' => 'O',
+	'/ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º/' => 'o',
+	'/Ŕ|Ŗ|Ř/' => 'R',
+	'/ŕ|ŗ|ř/' => 'r',
+	'/Ś|Ŝ|Ş|Š/' => 'S',
+	'/ś|ŝ|ş|š|ſ/' => 's',
+	'/Ţ|Ť|Ŧ/' => 'T',
+	'/ţ|ť|ŧ/' => 't',
+	'/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ/' => 'U',
+	'/ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ/' => 'u',
+	'/Ý|Ÿ|Ŷ/' => 'Y',
+	'/ý|ÿ|ŷ/' => 'y',
+	'/Ŵ/' => 'W',
+	'/ŵ/' => 'w',
+	'/Ź|Ż|Ž/' => 'Z',
+	'/ź|ż|ž/' => 'z',
+	'/Æ|Ǽ/' => 'AE',
+	'/ß/'=> 'ss',
+	'/IJ/' => 'IJ',
+	'/ij/' => 'ij',
+	'/Œ/' => 'OE',
+	'/ƒ/' => 'f'
+);
 
 /* End of file foreign_chars.php */
 /* Location: ./application/config/foreign_chars.php */
\ No newline at end of file
diff --git a/application/config/mimes.php b/application/config/mimes.php
index 146d3f9..8065794 100644
--- a/application/config/mimes.php
+++ b/application/config/mimes.php
@@ -10,7 +10,7 @@
 
 $mimes = array(	'hqx'	=>	'application/mac-binhex40',
 				'cpt'	=>	'application/mac-compactpro',
-				'csv'	=>	array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel'),
+				'csv'	=>	array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel'),
 				'bin'	=>	'application/macbinary',
 				'dms'	=>	'application/octet-stream',
 				'lha'	=>	'application/octet-stream',
@@ -56,7 +56,7 @@
 				'midi'	=>	'audio/midi',
 				'mpga'	=>	'audio/mpeg',
 				'mp2'	=>	'audio/mpeg',
-				'mp3'	=>	array('audio/mpeg', 'audio/mpg', 'audio/mpeg3'),
+				'mp3'	=>	array('audio/mpeg', 'audio/mpg', 'audio/mpeg3', 'audio/mp3'),
 				'aif'	=>	'audio/x-aiff',
 				'aiff'	=>	'audio/x-aiff',
 				'aifc'	=>	'audio/x-aiff',
@@ -97,7 +97,8 @@
 				'xlsx'	=>	'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
 				'word'	=>	array('application/msword', 'application/octet-stream'),
 				'xl'	=>	'application/excel',
-				'eml'	=>	'message/rfc822'
+				'eml'	=>	'message/rfc822',
+				'json' => array('application/json', 'text/json')
 			);
 
 
diff --git a/application/config/routes.php b/application/config/routes.php
index 614462f..5f9a583 100644
--- a/application/config/routes.php
+++ b/application/config/routes.php
@@ -23,16 +23,23 @@
 | RESERVED ROUTES
 | -------------------------------------------------------------------------
 |
-| There is one reserved routes:
+| There area two reserved routes:
 |
 |	$route['default_controller'] = 'welcome';
 |
 | This route indicates which controller class should be loaded if the
 | URI contains no data. In the above example, the "welcome" class
 | would be loaded.
+|
+|	$route['404_override'] = 'errors/page_missing';
+|
+| This route will tell the Router what URI segments to use if those provided
+| in the URL cannot be matched to a valid route.
+|
 */
 
 $route['default_controller'] = "welcome";
+$route['404_override'] = '';
 
 
 /* End of file routes.php */
diff --git a/application/config/user_agents.php b/application/config/user_agents.php
index 985deed..e2d3c3a 100644
--- a/application/config/user_agents.php
+++ b/application/config/user_agents.php
@@ -94,6 +94,7 @@
 					'nokia'				=> "Nokia",
 					'palm'				=> "Palm",
 					'iphone'			=> "Apple iPhone",
+					'ipad'				=> "iPad",
 					'ipod'				=> "Apple iPod Touch",
 					'sony'				=> "Sony Ericsson",
 					'ericsson'			=> "Sony Ericsson",
diff --git a/application/controllers/migrate.php b/application/controllers/migrate.php
new file mode 100644
index 0000000..e5442e7
--- /dev/null
+++ b/application/controllers/migrate.php
@@ -0,0 +1,40 @@
+<?php
+class Migrate extends CI_Controller
+{
+	function __construct()
+	{
+		parent::__construct();
+		
+		$this->load->library('migration');
+
+		/** VERY IMPORTANT - only turn this on when you need it. */
+//		show_error('Access to this controller is blocked, turn me on when you need me.');
+	}
+
+	// Install up to the most up-to-date version.
+	function install()
+	{
+		if ( ! $this->migration->current())
+		{
+			show_error($this->migration->error);
+			exit;
+		}
+
+		echo "<br />Migration Successful<br />";
+	}
+
+	// This will migrate up to the configed migration version
+	function version($id = NULL)
+	{
+		// No $id supplied? Use the config version
+		$id OR $id = $this->config->item('migration_version');
+
+		if ( ! $this->migration->version($id))
+		{
+			show_error($this->migration->error);
+			exit;
+		}
+
+		echo "<br />Migration Successful<br />";
+	}
+}
diff --git a/application/migrations/001_Create_accounts.php b/application/migrations/001_Create_accounts.php
new file mode 100644
index 0000000..4b2fc93
--- /dev/null
+++ b/application/migrations/001_Create_accounts.php
@@ -0,0 +1,32 @@
+<?php defined('BASEPATH') OR exit('No direct script access allowed');

+

+class Migration_Create_accounts extends	CI_Migration {

+	

+	function up() 

+	{	

+		if ( ! $this->db->table_exists('accounts'))

+		{

+			// Setup Keys

+			$this->dbforge->add_key('id', TRUE);

+			

+			$this->dbforge->add_field(array(

+				'id' => array('type' => 'INT', 'constraint' => 5, 'unsigned' => TRUE, 'auto_increment' => TRUE),

+				'company_name' => array('type' => 'VARCHAR', 'constraint' => '200', 'null' => FALSE),

+				'first_name' => array('type' => 'VARCHAR', 'constraint' => '200', 'null' => FALSE),

+				'last_name' => array('type' => 'VARCHAR', 'constraint' => '200', 'null' => FALSE),

+				'phone' => array('type' => 'TEXT', 'null' => FALSE),

+				'email' => array('type' => 'TEXT', 'null' => FALSE),

+				'address' => array('type' => 'TEXT', 'null' => FALSE),

+				'Last_Update' => array('type' => 'DATETIME', 'null' => FALSE)

+			));

+			

+			$this->dbforge->add_field("Created_At TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP");

+			$this->dbforge->create_table('accounts', TRUE);

+		}

+	}

+

+	function down() 

+	{

+		$this->dbforge->drop_table('accounts');

+	}

+}

diff --git a/index.php b/index.php
index 5bb53d2..74e3ba3 100644
--- a/index.php
+++ b/index.php
@@ -2,15 +2,46 @@
 
 /*
  *---------------------------------------------------------------
- * PHP ERROR REPORTING LEVEL
+ * APPLICATION ENVIRONMENT
  *---------------------------------------------------------------
  *
- * By default CI runs with error reporting set to ALL.  For security
- * reasons you are encouraged to change this to 0 when your site goes live.
- * For more info visit:  http://www.php.net/error_reporting
+ * You can load different configurations depending on your
+ * current environment. Setting the environment also influences
+ * things like logging and error reporting.
+ *
+ * This can be set to anything, but default usage is:
+ *
+ *     development
+ *     testing
+ *     production
+ *
+ * NOTE: If you change these, also change the error_reporting() code below
  *
  */
-	error_reporting(E_ALL);
+	define('ENVIRONMENT', 'development');
+/*
+ *---------------------------------------------------------------
+ * ERROR REPORTING
+ *---------------------------------------------------------------
+ *
+ * Different environments will require different levels of error reporting.
+ * By default development will show errors but testing and live will hide them.
+ */
+
+	switch (ENVIRONMENT)
+	{
+		case 'development':
+			error_reporting(E_ALL);
+		break;
+	
+		case 'testing':
+		case 'production':
+			error_reporting(0);
+		break;
+
+		default:
+			exit('The application environment is not set correctly.');
+	}
 
 /*
  *---------------------------------------------------------------
@@ -22,7 +53,7 @@
  * as this file.
  *
  */
-	$system_path = "system";
+	$system_path = 'system';
 
 /*
  *---------------------------------------------------------------
@@ -38,7 +69,7 @@
  * NO TRAILING SLASH!
  *
  */
-	$application_folder = "application";
+	$application_folder = 'application';
 
 /*
  * --------------------------------------------------------------------
@@ -94,14 +125,18 @@
 // END OF USER CONFIGURABLE SETTINGS.  DO NOT EDIT BELOW THIS LINE
 // --------------------------------------------------------------------
 
-
-
-
 /*
  * ---------------------------------------------------------------
  *  Resolve the system path for increased reliability
  * ---------------------------------------------------------------
  */
+
+	// Set the current directory correctly for CLI requests
+	if (defined('STDIN'))
+	{
+		chdir(dirname(__FILE__));
+	}
+
 	if (realpath($system_path) !== FALSE)
 	{
 		$system_path = realpath($system_path).'/';
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 0d0fffb..6ac333a 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -39,7 +39,7 @@
  *  Define the CodeIgniter Branch (Core = TRUE, Reactor = FALSE)
  * ------------------------------------------------------
  */
-	define('CI_CORE', TRUE);
+	define('CI_CORE', FALSE);
 
 /*
  * ------------------------------------------------------
@@ -87,7 +87,7 @@
 	{
 		get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix']));
 	}
-	
+
 /*
  * ------------------------------------------------------
  *  Set a liberal script execution time limit
@@ -296,7 +296,28 @@
 		// methods, so we'll use this workaround for consistent behavior
 		if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI))))
 		{
-			show_404("{$class}/{$method}");
+			// Check and see if we are using a 404 override and use it.
+			if ( ! empty($RTR->routes['404_override']))
+			{
+				$x = explode('/', $RTR->routes['404_override']);
+				$class = $x[0];
+				$method = (isset($x[1]) ? $x[1] : 'index');
+				if ( ! class_exists($class))
+				{
+					if ( ! file_exists(APPPATH.'controllers/'.$class.EXT))
+					{
+						show_404("{$class}/{$method}");
+					}
+
+					include_once(APPPATH.'controllers/'.$class.EXT);
+					unset($CI);
+					$CI = new $class();
+				}
+			}
+			else
+			{
+				show_404("{$class}/{$method}");
+			}
 		}
 
 		// Call the requested method.
@@ -344,4 +365,4 @@
 
 
 /* End of file CodeIgniter.php */
-/* Location: ./system/core/CodeIgniter.php */
\ No newline at end of file
+/* Location: ./system/core/CodeIgniter.php */
diff --git a/system/core/Common.php b/system/core/Common.php
index b5adfac..cd6b933 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -208,15 +208,20 @@
 			return $_config[0];
 		}
 
+		$file_path = APPPATH.'config/'.ENVIRONMENT.'/config'.EXT;
+
 		// Fetch the config file
-		if ( ! file_exists(APPPATH.'config/config'.EXT))
+		if ( ! file_exists($file_path))
 		{
-			exit('The configuration file does not exist.');
+			$file_path = APPPATH.'config/config'.EXT;
+			
+			if ( ! file_exists($file_path))
+			{
+				exit('The configuration file does not exist.');
+			}
 		}
-		else
-		{
-			require(APPPATH.'config/config'.EXT);
-		}
+	
+		require($file_path);
 
 		// Does the $config array exist in the file?
 		if ( ! isset($config) OR ! is_array($config))
diff --git a/system/core/Config.php b/system/core/Config.php
index 7fc8044..75f945e 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -47,6 +47,24 @@
 	{
 		$this->config =& get_config();
 		log_message('debug', "Config Class Initialized");
+
+		// Set the base_url automatically if none was provided
+		if ($this->config['base_url'] == '')
+		{
+			if (isset($_SERVER['HTTP_HOST']))
+			{
+				$base_url = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http';
+				$base_url .= '://'. $_SERVER['HTTP_HOST'];
+				$base_url .= str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']);
+			}
+
+			else
+			{
+				$base_url = 'http://localhost/';
+			}
+
+			$this->set_item('base_url', $base_url);
+		}
 	}
 
 	// --------------------------------------------------------------------
@@ -56,6 +74,8 @@
 	 *
 	 * @access	public
 	 * @param	string	the config file name
+	 * @param   boolean  if configuration values should be loaded into their own section
+	 * @param   boolean  true if errors should just return false, false if an error message should be displayed
 	 * @return	boolean	if the file was loaded correctly
 	 */
 	function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
@@ -63,9 +83,9 @@
 		$file = ($file == '') ? 'config' : str_replace(EXT, '', $file);
 		$loaded = FALSE;
 
-		foreach($this->_config_paths as $path)
-		{
-			$file_path = $path.'config/'.$file.EXT;
+		foreach ($this->_config_paths as $path)
+		{			
+			$file_path = $path.'config/'.ENVIRONMENT.'/'.$file.EXT;
 
 			if (in_array($file_path, $this->is_loaded, TRUE))
 			{
@@ -73,11 +93,17 @@
 				continue;
 			}
 
-			if ( ! file_exists($path.'config/'.$file.EXT))
+			if ( ! file_exists($file_path))
 			{
-				continue;
+				log_message('debug', 'Config for '.ENVIRONMENT.' environment is not found. Trying global config.');
+				$file_path = $path.'config/'.$file.EXT;
+				
+				if ( ! file_exists($file_path))
+				{
+					continue;
+				}
 			}
-
+			
 			include($file_path);
 
 			if ( ! isset($config) OR ! is_array($config))
@@ -118,9 +144,9 @@
 			{
 				return FALSE;
 			}
-			show_error('The configuration file '.$file.EXT.' does not exist.');
+			show_error('The configuration file '.ENVIRONMENT.'/'.$file.EXT.' and '.$file.EXT.' do not exist.');
 		}
-
+		
 		return TRUE;
 	}
 
@@ -185,14 +211,7 @@
 			return FALSE;
 		}
 
-		$pref = $this->config[$item];
-
-		if ($pref != '' && substr($pref, -1) != '/')
-		{
-			$pref .= '/';
-		}
-
-		return $pref;
+		return rtrim($this->config[$item], '/').'/';
 	}
 
 	// --------------------------------------------------------------------
@@ -208,14 +227,7 @@
 	{
 		if ($uri == '')
 		{
-			if ($this->item('base_url') == '')
-			{
-				return $this->item('index_page');
-			}
-			else
-			{
-				return $this->slash_item('base_url').$this->item('index_page');
-			}
+			return $this->slash_item('base_url').$this->item('index_page');
 		}
 
 		if ($this->item('enable_query_strings') == FALSE)
@@ -225,8 +237,9 @@
 				$uri = implode('/', $uri);
 			}
 
+			$index = $this->item('index_page') == '' ? '' : $this->slash_item('index_page');
 			$suffix = ($this->item('url_suffix') == FALSE) ? '' : $this->item('url_suffix');
-			return $this->slash_item('base_url').$this->slash_item('index_page').trim($uri, '/').$suffix;
+			return $this->slash_item('base_url').$index.trim($uri, '/').$suffix;
 		}
 		else
 		{
@@ -244,14 +257,7 @@
 				$uri = $str;
 			}
 
-			if ($this->item('base_url') == '')
-			{
-				return $this->item('index_page').'?'.$uri;
-			}
-			else
-			{
-				return $this->slash_item('base_url').$this->item('index_page').'?'.$uri;
-			}
+			return $this->slash_item('base_url').$this->item('index_page').'?'.$uri;
 		}
 	}
 
diff --git a/system/core/Input.php b/system/core/Input.php
index c2db94d..6262453 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -30,7 +30,7 @@
 
 	var $ip_address				= FALSE;
 	var $user_agent				= FALSE;
-	var $_allow_get_array		= FALSE;
+	var $_allow_get_array		= TRUE;
 	var $_standardize_newlines	= TRUE;
 	var $_enable_xss			= FALSE; // Set automatically based on config setting
 	var $_enable_csrf			= FALSE; // Set automatically based on config setting
@@ -49,9 +49,9 @@
 	{
 		log_message('debug', "Input Class Initialized");
 
-		$this->_allow_get_array	= (config_item('enable_query_strings') === TRUE) ? TRUE : FALSE;
-		$this->_enable_xss		= (config_item('global_xss_filtering') === TRUE) ? TRUE : FALSE;
-		$this->_enable_csrf		= (config_item('csrf_protection') === TRUE) ? TRUE : FALSE;
+		$this->_allow_get_array	= (config_item('allow_get_array') === TRUE);
+		$this->_enable_xss		= (config_item('global_xss_filtering') === TRUE);
+		$this->_enable_csrf		= (config_item('csrf_protection') === TRUE);
 
 		// Do we need to load the security class?
 		if ($this->_enable_xss == TRUE OR $this->_enable_csrf == TRUE)
@@ -109,8 +109,21 @@
 	* @param	bool
 	* @return	string
 	*/
-	function get($index = '', $xss_clean = FALSE)
+	function get($index = NULL, $xss_clean = FALSE)
 	{
+		// Check if a field has been provided
+		if ($index === NULL AND ! empty($_GET))
+		{
+			$get = array();
+
+			// loop through the full _GET array
+			foreach (array_keys($_GET) as $key)
+			{
+				$get[$key] = $this->_fetch_from_array($_GET, $key, $xss_clean);
+			}
+			return $get;
+		}
+
 		return $this->_fetch_from_array($_GET, $index, $xss_clean);
 	}
 
@@ -124,8 +137,21 @@
 	* @param	bool
 	* @return	string
 	*/
-	function post($index = '', $xss_clean = FALSE)
+	function post($index = NULL, $xss_clean = FALSE)
 	{
+		// Check if a field has been provided
+		if ($index === NULL AND ! empty($_POST))
+		{
+			$post = array();
+
+			// Loop through the full _POST array and return it
+			foreach (array_keys($_POST) as $key)
+			{
+				$post[$key] = $this->_fetch_from_array($_POST, $key, $xss_clean);
+			}
+			return $post;
+		}
+		
 		return $this->_fetch_from_array($_POST, $index, $xss_clean);
 	}
 
@@ -182,13 +208,15 @@
 	* @param	string	the cookie domain.  Usually:  .yourdomain.com
 	* @param	string	the cookie path
 	* @param	string	the cookie prefix
+	* @param	bool	true makes the cookie secure
 	* @return	void
 	*/
-	function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '')
+	function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE)
 	{
 		if (is_array($name))
 		{
-			foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'name') as $item)
+			// always leave 'name' in last place, as the loop will break otherwise, due to $$item
+			foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'name') as $item)
 			{
 				if (isset($name[$item]))
 				{
@@ -209,6 +237,10 @@
 		{
 			$path = config_item('cookie_path');
 		}
+		if ($secure == FALSE AND config_item('cookie_secure') != FALSE)
+		{
+			$secure = config_item('cookie_secure');
+		}
 
 		if ( ! is_numeric($expire))
 		{
@@ -216,19 +248,10 @@
 		}
 		else
 		{
-			if ($expire > 0)
-			{
-				$expire = time() + $expire;
-			}
-			else
-			{
-				$expire = 0;
-			}
+			$expire = ($expire > 0) ? time() + $expire : 0;
 		}
-		
-		$secure_cookie = (config_item('cookie_secure') === TRUE) ? 1 : 0;
 
-		setcookie($prefix.$name, $value, $expire, $path, $domain, $secure_cookie);
+		setcookie($prefix.$name, $value, $expire, $path, $domain, $secure);
 	}
 
 	// --------------------------------------------------------------------
@@ -422,7 +445,7 @@
 		{
 			if (is_array($_GET) AND count($_GET) > 0)
 			{
-				foreach($_GET as $key => $val)
+				foreach ($_GET as $key => $val)
 				{
 					$_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
 				}
@@ -432,7 +455,7 @@
 		// Clean $_POST Data
 		if (is_array($_POST) AND count($_POST) > 0)
 		{
-			foreach($_POST as $key => $val)
+			foreach ($_POST as $key => $val)
 			{
 				$_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
 			}
@@ -450,7 +473,7 @@
 			unset($_COOKIE['$Path']);
 			unset($_COOKIE['$Domain']);
 
-			foreach($_COOKIE as $key => $val)
+			foreach ($_COOKIE as $key => $val)
 			{
 				$_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
 			}
@@ -494,7 +517,7 @@
 		}
 
 		// We strip slashes if magic quotes is on to keep things consistent
-		if (get_magic_quotes_gpc())
+		if (function_exists('get_magic_quotes_gpc') AND get_magic_quotes_gpc())
 		{
 			$str = stripslashes($str);
 		}
@@ -516,7 +539,7 @@
 		{
 			if (strpos($str, "\r") !== FALSE)
 			{
-				$str = str_replace(array("\r\n", "\r"), "\n", $str);
+				$str = str_replace(array("\r\n", "\r"), PHP_EOL, $str);
 			}
 		}
 
@@ -627,21 +650,35 @@
 	}
 
 	// --------------------------------------------------------------------
-	
+
 	/**
 	 * Is ajax Request?
 	 *
 	 * Test to see if a request contains the HTTP_X_REQUESTED_WITH header
 	 *
-	 * @return 	boolean 	
+	 * @return 	boolean
 	 */
 	public function is_ajax_request()
 	{
 		return ($this->server('HTTP_X_REQUESTED_WITH') === 'XMLHttpRequest');
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Is cli Request?
+	 *
+	 * Test to see if a request was made from the command line
+	 *
+	 * @return 	boolean
+	 */
+	public function is_cli_request()
+	{
+		return (bool) defined('STDIN');
+	}
+
 }
 // END Input class
 
 /* End of file Input.php */
-/* Location: ./system/core/Input.php */
\ No newline at end of file
+/* Location: ./system/core/Input.php */
diff --git a/system/core/Lang.php b/system/core/Lang.php
index 6805d0e..fb17790 100644
--- a/system/core/Lang.php
+++ b/system/core/Lang.php
@@ -78,17 +78,21 @@
 		{
 			include($alt_path.'language/'.$idiom.'/'.$langfile);
 		}
-		elseif (file_exists(APPPATH.'language/'.$idiom.'/'.$langfile))
-		{
-			include(APPPATH.'language/'.$idiom.'/'.$langfile);
-		}
 		else
 		{
-			if (file_exists(BASEPATH.'language/'.$idiom.'/'.$langfile))
+			$found = FALSE;
+
+			foreach (get_instance()->load->get_package_paths(TRUE) as $package_path)
 			{
-				include(BASEPATH.'language/'.$idiom.'/'.$langfile);
+				if (file_exists($package_path.'language/'.$idiom.'/'.$langfile))
+				{
+					include($package_path.'language/'.$idiom.'/'.$langfile);
+					$found = TRUE;
+					break;
+				}
 			}
-			else
+
+			if ($found !== TRUE)
 			{
 				show_error('Unable to load the requested language file: language/'.$idiom.'/'.$langfile);
 			}
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 8b1986b..7003318 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -79,14 +79,14 @@
 	{
 		if (is_array($library))
 		{
-			foreach($library as $read)
+			foreach ($library as $read)
 			{
-				$this->library($read);	
+				$this->library($read);
 			}
-			
+
 			return;
 		}
-		
+
 		if ($library == '' OR isset($this->_base_classes[$library]))
 		{
 			return FALSE;
@@ -127,7 +127,7 @@
 	{
 		if (is_array($model))
 		{
-			foreach($model as $babe)
+			foreach ($model as $babe)
 			{
 				$this->model($babe);
 			}
@@ -527,7 +527,7 @@
 	function add_package_path($path)
 	{
 		$path = rtrim($path, '/').'/';
-		
+
 		array_unshift($this->_ci_library_paths, $path);
 		array_unshift($this->_ci_model_paths, $path);
 		array_unshift($this->_ci_helper_paths, $path);
@@ -540,6 +540,22 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Get Package Paths
+	 *
+	 * Return a list of all package paths, by default it will ignore BASEPATH.
+	 *
+	 * @access	public
+	 * @param	string
+	 * @return	void
+	 */
+	function get_package_paths($include_base = FALSE)
+	{
+		return $include_base === TRUE ? $this->_ci_library_paths : $this->_ci_model_paths;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Remove Package Path
 	 *
 	 * Remove a path from the library, model, and helper path arrays if it exists
@@ -563,7 +579,7 @@
 		else
 		{
 			$path = rtrim($path, '/').'/';
-			
+
 			foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)
 			{
 				if (($key = array_search($path, $this->{$var})) !== FALSE)
@@ -854,15 +870,39 @@
 		// Is there an associated config file for this class?  Note: these should always be lowercase
 		if ($config === NULL)
 		{
-			// We test for both uppercase and lowercase, for servers that
-			// are case-sensitive with regard to file names
-			if (file_exists(APPPATH.'config/'.strtolower($class).EXT))
+			// Fetch the config paths containing any package paths
+			$config_component = $this->_ci_get_component('config');
+
+			if (is_array($config_component->_config_paths))
 			{
-				include_once(APPPATH.'config/'.strtolower($class).EXT);
-			}
-			elseif (file_exists(APPPATH.'config/'.ucfirst(strtolower($class)).EXT))
-			{
-				include_once(APPPATH.'config/'.ucfirst(strtolower($class)).EXT);
+				// Break on the first found file, thus package files
+				// are not overridden by default paths
+				foreach ($config_component->_config_paths as $path)
+				{
+					// We test for both uppercase and lowercase, for servers that
+					// are case-sensitive with regard to file names. Check for environment
+					// first, global next
+					if (file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).EXT))
+					{
+						include_once($path .'config/'.ENVIRONMENT.'/'.strtolower($class).EXT);
+						break;
+					}
+					elseif (file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).EXT))
+					{
+						include_once($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).EXT);
+						break;
+					}
+					elseif (file_exists($path .'config/'.strtolower($class).EXT))
+					{
+						include_once($path .'config/'.strtolower($class).EXT);
+						break;
+					}
+					elseif (file_exists($path .'config/'.ucfirst(strtolower($class)).EXT))
+					{
+						include_once($path .'config/'.ucfirst(strtolower($class)).EXT);
+						break;
+					}
+				}
 			}
 		}
 
diff --git a/system/core/Output.php b/system/core/Output.php
index 7fb9f79..6644b3b 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -28,19 +28,24 @@
  */
 class CI_Output {
 
-	var $final_output;
-	var $cache_expiration	= 0;
-	var $headers			= array();
-	var $enable_profiler	= FALSE;
-	var $parse_exec_vars	= TRUE;	// whether or not to parse variables like {elapsed_time} and {memory_usage}
+	protected $final_output;
+	protected $cache_expiration	= 0;
+	protected $headers			= array();
+	protected $mime_types			= array();
+	protected $enable_profiler	= FALSE;
+	protected $parse_exec_vars	= TRUE;	// whether or not to parse variables like {elapsed_time} and {memory_usage}
 
-	var $_zlib_oc			= FALSE;
-	var $_profiler_sections = array();
+	protected $_zlib_oc			= FALSE;
+	protected $_profiler_sections = array();
 
 	function __construct()
 	{
 		$this->_zlib_oc = @ini_get('zlib.output_compression');
 
+		// Get mime types for later
+		include APPPATH.'config/mimes'.EXT;
+		$this->mime_types = $mimes;
+		
 		log_message('debug', "Output Class Initialized");
 	}
 
@@ -73,6 +78,8 @@
 	function set_output($output)
 	{
 		$this->final_output = $output;
+		
+		return $this;
 	}
 
 	// --------------------------------------------------------------------
@@ -96,6 +103,8 @@
 		{
 			$this->final_output .= $output;
 		}
+
+		return $this;
 	}
 
 	// --------------------------------------------------------------------
@@ -125,6 +134,42 @@
 		}
 
 		$this->headers[] = array($header, $replace);
+
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set Content Type Header
+	 *
+	 * @access	public
+	 * @param	string	extension of the file we're outputting
+	 * @return	void
+	 */
+	function set_content_type($mime_type)
+	{
+		if (strpos($mime_type, '/') === FALSE)
+		{
+			$extension = ltrim($mime_type, '.');
+
+			// Is this extension supported?
+			if (isset($this->mime_types[$extension]))
+			{
+				$mime_type =& $this->mime_types[$extension];
+
+				if (is_array($mime_type))
+				{
+					$mime_type = current($mime_type);
+				}
+			}
+		}
+
+		$header = 'Content-Type: '.$mime_type;
+
+		$this->headers[] = array($header, TRUE);
+		
+		return $this;
 	}
 
 	// --------------------------------------------------------------------
@@ -141,6 +186,8 @@
 	function set_status_header($code = 200, $text = '')
 	{
 		set_status_header($code, $text);
+
+		return $this;
 	}
 
 	// --------------------------------------------------------------------
@@ -155,6 +202,8 @@
 	function enable_profiler($val = TRUE)
 	{
 		$this->enable_profiler = (is_bool($val)) ? $val : TRUE;
+
+		return $this;
 	}
 
 	// --------------------------------------------------------------------
@@ -174,6 +223,8 @@
 		{
 			$this->_profiler_sections[$section] = ($enable !== FALSE) ? TRUE : FALSE;
 		}
+
+		return $this;
 	}
 
 	// --------------------------------------------------------------------
@@ -188,6 +239,8 @@
 	function cache($time)
 	{
 		$this->cache_expiration = ( ! is_numeric($time)) ? 0 : $time;
+
+		return $this;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/core/Router.php b/system/core/Router.php
index bb4eb0e..6893e6e 100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -270,19 +270,17 @@
 
 		// If we've gotten this far it means that the URI does not correlate to a valid
 		// controller class.  We will now see if there is an override
-		if (isset($this->routes['404_override']) AND $this->routes['404_override'] != '')
+		if ( ! empty($this->routes['404_override']))
 		{
-			if (strpos($this->routes['404_override'], '/') !== FALSE)
-			{
-				$x = explode('/', $this->routes['404_override']);
+			$x = explode('/', $this->routes['404_override']);
 
-				$this->set_class($x[0]);
-				$this->set_method($x[1]);
+			$this->set_class($x[0]);
+			$this->set_method(isset($x[1]) ? $x[1] : 'index');
 
-				return $x;
-			}
+			return $x;
 		}
 
+
 		// Nothing else to do at this point but show a 404
 		show_404($segments[0]);
 	}
diff --git a/system/core/URI.php b/system/core/URI.php
index a991118..c43cde0 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -61,13 +61,17 @@
 	{
 		if (strtoupper($this->config->item('uri_protocol')) == 'AUTO')
 		{
-			// If the URL has a question mark then it's simplest to just
-			// build the URI string from the zero index of the $_GET array.
-			// This avoids having to deal with $_SERVER variables, which
-			// can be unreliable in some environments
-			if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')
+			// Is the request coming from the command line?
+			if (defined('STDIN'))
 			{
-				$this->uri_string = key($_GET);
+				$this->uri_string = $this->_parse_cli_args();
+				return;
+			}
+
+			// Let's try the REQUEST_URI first, this will work in most situations
+			if ($uri = $this->_detect_uri())
+			{
+				$this->uri_string = $uri;
 				return;
 			}
 
@@ -88,12 +92,10 @@
 				return;
 			}
 
-			// No QUERY_STRING?... Maybe the ORIG_PATH_INFO variable exists?
-			$path = str_replace($_SERVER['SCRIPT_NAME'], '', (isset($_SERVER['ORIG_PATH_INFO'])) ? $_SERVER['ORIG_PATH_INFO'] : @getenv('ORIG_PATH_INFO'));
-			if (trim($path, '/') != '' && $path != "/".SELF)
+			// As a last ditch effort lets try using the $_GET array
+			if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')
 			{
-				// remove path and script information so we have good URI data
-				$this->uri_string = $path;
+				$this->uri_string = key($_GET);
 				return;
 			}
 
@@ -106,7 +108,12 @@
 
 			if ($uri == 'REQUEST_URI')
 			{
-				$this->uri_string = $this->_parse_request_uri();
+				$this->uri_string = $this->_detect_uri();
+				return;
+			}
+			elseif ($uri == 'CLI')
+			{
+				$this->uri_string = $this->_parse_cli_args();
 				return;
 			}
 
@@ -123,54 +130,76 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Parse the REQUEST_URI
+	 * Detects the URI
 	 *
-	 * Due to the way REQUEST_URI works it usually contains path info
-	 * that makes it unusable as URI data.  We'll trim off the unnecessary
-	 * data, hopefully arriving at a valid URI that we can use.
+	 * This function will detect the URI automatically and fix the query string
+	 * if necessary.
 	 *
 	 * @access	private
 	 * @return	string
 	 */
-	function _parse_request_uri()
+	private function _detect_uri()
 	{
-		if ( ! isset($_SERVER['REQUEST_URI']) OR $_SERVER['REQUEST_URI'] == '')
+		if ( ! isset($_SERVER['REQUEST_URI']))
 		{
 			return '';
 		}
 
-		$request_uri = preg_replace("|/(.*)|", "\\1", str_replace("\\", "/", $_SERVER['REQUEST_URI']));
-
-		if ($request_uri == '' OR $request_uri == SELF)
+		$uri = $_SERVER['REQUEST_URI'];
+		if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
 		{
-			return '';
+			$uri = substr($uri, strlen($_SERVER['SCRIPT_NAME']));
+		}
+		elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
+		{
+			$uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
 		}
 
-		$fc_path = FCPATH.SELF;
-		if (strpos($request_uri, '?') !== FALSE)
+		// This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct
+		// URI is found, and also fixes the QUERY_STRING server var and $_GET array.
+		if (strncmp($uri, '?/', 2) === 0)
 		{
-			$fc_path .= '?';
+			$uri = substr($uri, 2);
 		}
-
-		$parsed_uri = explode("/", $request_uri);
-
-		$i = 0;
-		foreach(explode("/", $fc_path) as $segment)
+		$parts = preg_split('#\?#i', $uri, 2);
+		$uri = $parts[0];
+		if (isset($parts[1]))
 		{
-			if (isset($parsed_uri[$i]) && $segment == $parsed_uri[$i])
-			{
-				$i++;
-			}
+			$_SERVER['QUERY_STRING'] = $parts[1];
+			parse_str($_SERVER['QUERY_STRING'], $_GET);
 		}
-
-		$parsed_uri = implode("/", array_slice($parsed_uri, $i));
-
-		if ($parsed_uri != '')
+		else
 		{
-			$parsed_uri = '/'.$parsed_uri;
+			$_SERVER['QUERY_STRING'] = '';
+			$_GET = array();
 		}
+		
+		if ($uri == '/' || empty($uri))
+		{
+			return '/';
+		}
+				
+		$uri = parse_url($uri, PHP_URL_PATH);
 
-		return $parsed_uri;
+		// Do some final cleaning of the URI and return it
+		return str_replace(array('//', '../'), '/', trim($uri, '/'));
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Parse cli arguments
+	 *
+	 * Take each command line argument and assume it is a URI segment.
+	 *
+	 * @access	private
+	 * @return	string
+	 */
+	private function _parse_cli_args()
+	{
+		$args = array_slice($_SERVER['argv'], 1);
+
+		return $args ? '/' . implode('/', $args) : '';
 	}
 
 	// --------------------------------------------------------------------
@@ -228,7 +257,7 @@
 	 */
 	function _explode_segments()
 	{
-		foreach(explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val)
+		foreach (explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val)
 		{
 			// Filter segments for security
 			$val = trim($this->_filter_uri($val));
@@ -484,7 +513,7 @@
 	{
 		$leading	= '/';
 		$trailing	= '/';
-		
+
 		if ($where == 'trailing')
 		{
 			$leading	= '';
@@ -493,7 +522,7 @@
 		{
 			$trailing	= '';
 		}
-		
+
 		return $leading.$this->$which($n).$trailing;
 	}
 
@@ -573,7 +602,7 @@
 	 */
 	function ruri_string()
 	{
-		return '/'.implode('/', $this->rsegment_array()).'/';
+		return '/'.implode('/', $this->rsegment_array());
 	}
 
 }
diff --git a/system/database/DB.php b/system/database/DB.php
index fb0516b..93ee392 100644
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -27,7 +27,21 @@
 	// Load the DB config file if a DSN string wasn't passed
 	if (is_string($params) AND strpos($params, '://') === FALSE)
 	{
-		include(APPPATH.'config/database'.EXT);
+		
+		$file_path = APPPATH.'config/'.ENVIRONMENT.'/database'.EXT;
+		
+		if ( ! file_exists($file_path))
+		{
+			log_message('debug', 'Database config for '.ENVIRONMENT.' environment is not found. Trying global config.');
+			$file_path = APPPATH.'config/database'.EXT;
+			
+			if ( ! file_exists($file_path))
+			{
+				continue;
+			}
+		}
+		
+		include($file_path);
 
 		if ( ! isset($db) OR count($db) == 0)
 		{
@@ -74,7 +88,7 @@
 		{
 			parse_str($dns['query'], $extra);
 
-			foreach($extra as $key => $val)
+			foreach ($extra as $key => $val)
 			{
 				// booleans please
 				if (strtoupper($val) == "TRUE")
diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php
index ce9d1c1..ee72dbb 100644
--- a/system/database/DB_active_rec.php
+++ b/system/database/DB_active_rec.php
@@ -954,7 +954,7 @@
 			}
 			else
 			{
-				$this->ar_set[$this->_protect_identifiers($k)] = $this->escape($v);
+				$this->ar_set[$this->_protect_identifiers($k, FALSE, TRUE)] = $this->escape($v);
 			}
 		}
 
@@ -1156,7 +1156,7 @@
 				$this->ar_set[] = array();
 				return;
 			}
-		
+
 			ksort($row); // puts $row in the same order as our keys
 
 			if ($escape === FALSE)
@@ -1167,7 +1167,7 @@
 			{
 				$clean = array();
 
-				foreach($row as $value)
+				foreach ($row as $value)
 				{
 					$clean[] = $this->escape($value);
 				}
@@ -1425,7 +1425,7 @@
 			$index_set = FALSE;
 			$clean = array();
 
-			foreach($v as $k2 => $v2)
+			foreach ($v as $k2 => $v2)
 			{
 				if ($k2 == $index)
 				{
@@ -1569,7 +1569,7 @@
 		}
 		elseif (is_array($table))
 		{
-			foreach($table as $single_table)
+			foreach ($table as $single_table)
 			{
 				$this->delete($single_table, $where, $limit, FALSE);
 			}
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 2d8f592..e7a9de4 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -767,7 +767,7 @@
 
 		if ($query->num_rows() > 0)
 		{
-			foreach($query->result_array() as $row)
+			foreach ($query->result_array() as $row)
 			{
 				if (isset($row['TABLE_NAME']))
 				{
@@ -834,7 +834,7 @@
 		$query = $this->query($sql);
 
 		$retval = array();
-		foreach($query->result_array() as $row)
+		foreach ($query->result_array() as $row)
 		{
 			if (isset($row['COLUMN_NAME']))
 			{
@@ -904,7 +904,7 @@
 		$fields = array();
 		$values = array();
 
-		foreach($data as $key => $val)
+		foreach ($data as $key => $val)
 		{
 			$fields[] = $this->_escape_identifiers($key);
 			$values[] = $this->escape($val);
@@ -932,7 +932,7 @@
 		}
 
 		$fields = array();
-		foreach($data as $key => $val)
+		foreach ($data as $key => $val)
 		{
 			$fields[$this->_protect_identifiers($key)] = $this->escape($val);
 		}
@@ -1175,7 +1175,7 @@
 
 		$trace = debug_backtrace();
 
-		foreach($trace as $call)
+		foreach ($trace as $call)
 		{
 			if (isset($call['file']) && strpos($call['file'], BASEPATH.'database') === FALSE)
 			{
@@ -1248,7 +1248,7 @@
 		{
 			$escaped_array = array();
 
-			foreach($item as $k => $v)
+			foreach ($item as $k => $v)
 			{
 				$escaped_array[$this->_protect_identifiers($k)] = $this->_protect_identifiers($v);
 			}
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index e6a64f3..a71fca7 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -99,7 +99,7 @@
 	{
 		if (is_array($key))
 		{
-			foreach($key as $one)
+			foreach ($key as $one)
 			{
 				$this->add_key($one, $primary);
 			}
@@ -333,6 +333,12 @@
 
 		foreach ($field as $k => $v)
 		{
+			// If no name provided, use the current name
+			if ( ! isset($field[$k]['name']))
+			{
+				$field[$k]['name'] = $k;
+			}
+
 			$this->add_field(array($k => $field[$k]));
 
 			if (count($this->fields) == 0)
diff --git a/system/database/DB_result.php b/system/database/DB_result.php
index fb791cf..76e1d6a 100644
--- a/system/database/DB_result.php
+++ b/system/database/DB_result.php
@@ -28,13 +28,14 @@
  */
 class CI_DB_result {
 
-	var $conn_id		= NULL;
-	var $result_id		= NULL;
-	var $result_array	= array();
-	var $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;
 
 
 	/**
@@ -46,11 +47,48 @@
 	 */
 	function result($type = 'object')
 	{
-		return ($type == 'object') ? $this->result_object() : $this->result_array();
+        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();
+        }
+
+        // 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;
+            }
+			$result_object[] = $object;
+		}
+
+        // return the array
+        return $this->custom_result_object[$class_name] = $result_object;
+    }
+
 	/**
 	 * Query result.  "object" version.
 	 *
@@ -142,7 +180,9 @@
 			$n = 0;
 		}
 
-		return ($type == 'object') ? $this->row_object($n) : $this->row_array($n);
+        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);
 	}
 
 	// --------------------------------------------------------------------
@@ -179,7 +219,30 @@
 
 	// --------------------------------------------------------------------
 
-	/**
+    /**
+	 * Returns a single result row - custom object version
+	 *
+	 * @access	public
+	 * @return	object
+	 */
+	function custom_row_object($n, $type)
+	{
+		$result = $this->custom_result_object($type);
+
+		if (count($result) == 0)
+		{
+			return $result;
+		}
+
+		if ($n != $this->current_row AND isset($result[$n]))
+		{
+			$this->current_row = $n;
+		}
+
+		return $result[$this->current_row];
+	}
+
+    /**
 	 * Returns a single result row - object version
 	 *
 	 * @access	public
@@ -339,4 +402,4 @@
 // END DB_result class
 
 /* End of file DB_result.php */
-/* Location: ./system/database/DB_result.php */
\ No newline at end of file
+/* Location: ./system/database/DB_result.php */
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 5a69132..5048c0b 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -253,7 +253,7 @@
 	{
 		if (is_array($str))
 		{
-			foreach($str as $key => $val)
+			foreach ($str as $key => $val)
 			{
 				$str[$key] = $this->escape_str($val, $like);
 			}
@@ -551,7 +551,7 @@
 	 */
 	function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
 	{
-		foreach($values as $key => $val)
+		foreach ($values as $key => $val)
 		{
 			$valstr[] = $key." = ".$val;
 		}
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index df18c91..4ff9b0a 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -286,13 +286,13 @@
 	{
 		if (is_array($str))
 		{
-			foreach($str as $key => $val)
-			{
+			foreach ($str as $key => $val)
+	   		{
 				$str[$key] = $this->escape_str($val, $like);
-			}
+	   		}
 
-			return $str;
-		}
+	   		return $str;
+	   	}
 
 		if (function_exists('mysql_real_escape_string') AND is_resource($this->conn_id))
 		{
@@ -590,9 +590,9 @@
 	 */
 	function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
 	{
-		foreach($values as $key => $val)
+		foreach ($values as $key => $val)
 		{
-			$valstr[] = $key." = ".$val;
+			$valstr[] = $key . ' = ' . $val;
 		}
 
 		$limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
@@ -627,11 +627,11 @@
 		$ids = array();
 		$where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
 
-		foreach($values as $key => $val)
+		foreach ($values as $key => $val)
 		{
 			$ids[] = $val[$index];
 
-			foreach(array_keys($val) as $field)
+			foreach (array_keys($val) as $field)
 			{
 				if ($field != $index)
 				{
@@ -643,7 +643,7 @@
 		$sql = "UPDATE ".$table." SET ";
 		$cases = '';
 
-		foreach($final as $k => $v)
+		foreach ($final as $k => $v)
 		{
 			$cases .= $k.' = CASE '."\n";
 			foreach ($v as $row)
diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php
index c02b8cb..529ec98 100644
--- a/system/database/drivers/mysql/mysql_forge.php
+++ b/system/database/drivers/mysql/mysql_forge.php
@@ -87,11 +87,26 @@
 				if (array_key_exists('TYPE', $attributes))
 				{
 					$sql .=  ' '.$attributes['TYPE'];
-				}
 
-				if (array_key_exists('CONSTRAINT', $attributes))
-				{
-					$sql .= '('.$attributes['CONSTRAINT'].')';
+					if (array_key_exists('CONSTRAINT', $attributes))
+					{
+						switch ($attributes['TYPE'])
+						{
+							case 'decimal':
+							case 'float':
+							case 'numeric':
+								$sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
+							break;
+
+							case 'enum':
+							case 'set':
+								$sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
+							break;
+
+							default:
+								$sql .= '('.$attributes['CONSTRAINT'].')';
+						}
+					}
 				}
 
 				if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index 8942100..ccdabce 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -287,7 +287,7 @@
 	{
 		if (is_array($str))
 		{
-			foreach($str as $key => $val)
+			foreach ($str as $key => $val)
 			{
 				$str[$key] = $this->escape_str($val, $like);
 			}
@@ -571,7 +571,7 @@
 	 */
 	function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
 	{
-		foreach($values as $key => $val)
+		foreach ($values as $key => $val)
 		{
 			$valstr[] = $key." = ".$val;
 		}
@@ -607,11 +607,11 @@
 		$ids = array();
 		$where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
 
-		foreach($values as $key => $val)
+		foreach ($values as $key => $val)
 		{
 			$ids[] = $val[$index];
 
-			foreach(array_keys($val) as $field)
+			foreach (array_keys($val) as $field)
 			{
 				if ($field != $index)
 				{
@@ -623,7 +623,7 @@
 		$sql = "UPDATE ".$table." SET ";
 		$cases = '';
 
-		foreach($final as $k => $v)
+		foreach ($final as $k => $v)
 		{
 			$cases .= $k.' = CASE '."\n";
 			foreach ($v as $row)
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index 64f53cc..14df104 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -253,7 +253,7 @@
 		$sql = "begin $package.$procedure(";
 
 		$have_cursor = FALSE;
-		foreach($params as $param)
+		foreach ($params as $param)
 		{
 			$sql .= $param['name'] . ",";
 
@@ -395,7 +395,7 @@
 	{
 		if (is_array($str))
 		{
-			foreach($str as $key => $val)
+			foreach ($str as $key => $val)
 			{
 				$str[$key] = $this->escape_str($val, $like);
 			}
@@ -655,7 +655,7 @@
 	 */
 	function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
 	{
-		foreach($values as $key => $val)
+		foreach ($values as $key => $val)
 		{
 			$valstr[] = $key." = ".$val;
 		}
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index c8e03c3..81e0d7c 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -264,7 +264,7 @@
 	{
 		if (is_array($str))
 		{
-			foreach($str as $key => $val)
+			foreach ($str as $key => $val)
 			{
 				$str[$key] = $this->escape_str($val, $like);
 			}
@@ -523,7 +523,7 @@
 	 */
 	function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
 	{
-		foreach($values as $key => $val)
+		foreach ($values as $key => $val)
 		{
 			$valstr[] = $key." = ".$val;
 		}
diff --git a/system/database/drivers/odbc/odbc_result.php b/system/database/drivers/odbc/odbc_result.php
index a81a2b8..5d64a46 100644
--- a/system/database/drivers/odbc/odbc_result.php
+++ b/system/database/drivers/odbc/odbc_result.php
@@ -188,7 +188,7 @@
 	 */
 	function _odbc_fetch_object(& $odbc_result) {
 		$rs = array();
-		$rs_obj = false;
+		$rs_obj = FALSE;
 		if (odbc_fetch_into($odbc_result, $rs)) {
 			foreach ($rs as $k=>$v) {
 				$field_name= odbc_field_name($odbc_result, $k+1);
@@ -210,7 +210,7 @@
 	 */
 	function _odbc_fetch_array(& $odbc_result) {
 		$rs = array();
-		$rs_assoc = false;
+		$rs_assoc = FALSE;
 		if (odbc_fetch_into($odbc_result, $rs)) {
 			$rs_assoc=array();
 			foreach ($rs as $k=>$v) {
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 0bb7974..47ff362 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -283,7 +283,7 @@
 	{
 		if (is_array($str))
 		{
-			foreach($str as $key => $val)
+			foreach ($str as $key => $val)
 			{
 				$str[$key] = $this->escape_str($val, $like);
 			}
@@ -330,21 +330,21 @@
 		$v = $this->_version();
 		$v = $v['server'];
 
-		$table	= func_num_args() > 0 ? func_get_arg(0) : null;
-		$column	= func_num_args() > 1 ? func_get_arg(1) : null;
+		$table	= func_num_args() > 0 ? func_get_arg(0) : NULL;
+		$column	= func_num_args() > 1 ? func_get_arg(1) : NULL;
 
-		if ($table == null && $v >= '8.1')
+		if ($table == NULL && $v >= '8.1')
 		{
 			$sql='SELECT LASTVAL() as ins_id';
 		}
-		elseif ($table != null && $column != null && $v >= '8.0')
+		elseif ($table != NULL && $column != NULL && $v >= '8.0')
 		{
 			$sql = sprintf("SELECT pg_get_serial_sequence('%s','%s') as seq", $table, $column);
 			$query = $this->query($sql);
 			$row = $query->row();
 			$sql = sprintf("SELECT CURRVAL('%s') as ins_id", $row->seq);
 		}
-		elseif ($table != null)
+		elseif ($table != NULL)
 		{
 			// seq_name passed in table parameter
 			$sql = sprintf("SELECT CURRVAL('%s') as ins_id", $table);
@@ -568,7 +568,7 @@
 	 */
 	function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
 	{
-		foreach($values as $key => $val)
+		foreach ($values as $key => $val)
 		{
 			$valstr[] = $key." = ".$val;
 		}
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index 5bfc1f5..eb4e585 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -280,7 +280,7 @@
 	{
 		if (is_array($str))
 		{
-			foreach($str as $key => $val)
+			foreach ($str as $key => $val)
 			{
 				$str[$key] = $this->escape_str($val, $like);
 			}
@@ -537,7 +537,7 @@
 	 */
 	function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
 	{
-		foreach($values as $key => $val)
+		foreach ($values as $key => $val)
 		{
 			$valstr[] = $key." = ".$val;
 		}
diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php
index c0e3798..19ec0c7 100644
--- a/system/helpers/captcha_helper.php
+++ b/system/helpers/captcha_helper.php
@@ -87,7 +87,7 @@
 
 		$current_dir = @opendir($img_path);
 
-		while($filename = @readdir($current_dir))
+		while ($filename = @readdir($current_dir))
 		{
 			if ($filename != "." and $filename != ".." and $filename != "index.html")
 			{
diff --git a/system/helpers/cookie_helper.php b/system/helpers/cookie_helper.php
index 7701d50..7cee028 100644
--- a/system/helpers/cookie_helper.php
+++ b/system/helpers/cookie_helper.php
@@ -44,11 +44,11 @@
  */
 if ( ! function_exists('set_cookie'))
 {
-	function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '')
+	function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE)
 	{
 		// Set the config file options
 		$CI =& get_instance();
-		$CI->input->set_cookie($name, $value, $expire, $domain, $path, $prefix);
+		$CI->input->set_cookie($name, $value, $expire, $domain, $path, $prefix, $secure);
 	}
 }
 
diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php
index 334eef8..9518e48 100644
--- a/system/helpers/file_helper.php
+++ b/system/helpers/file_helper.php
@@ -128,7 +128,7 @@
 			return FALSE;
 		}
 
-		while(FALSE !== ($filename = @readdir($current_dir)))
+		while (FALSE !== ($filename = @readdir($current_dir)))
 		{
 			if ($filename != "." and $filename != "..")
 			{
diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php
index ed9ab5f..4cd7486 100644
--- a/system/helpers/inflector_helper.php
+++ b/system/helpers/inflector_helper.php
@@ -93,7 +93,7 @@
 		}
 		elseif ($end == 'h')
 		{
-			if (substr($str, -2) == 'ch' || substr($str, -2) == 'sh')
+			if (substr($str, -2) == 'ch' OR substr($str, -2) == 'sh')
 			{
 				$str .= 'es';
 			}
diff --git a/system/helpers/language_helper.php b/system/helpers/language_helper.php
index 68c1a1f..ac0d69d 100644
--- a/system/helpers/language_helper.php
+++ b/system/helpers/language_helper.php
@@ -1,4 +1,4 @@
-<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
 /**
  * CodeIgniter
  *
diff --git a/system/helpers/number_helper.php b/system/helpers/number_helper.php
index a2caea5..6117775 100644
--- a/system/helpers/number_helper.php
+++ b/system/helpers/number_helper.php
@@ -1,4 +1,4 @@
-<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
 /**
  * CodeIgniter
  *
diff --git a/system/helpers/smiley_helper.php b/system/helpers/smiley_helper.php
index 80a8d79..463881f 100644
--- a/system/helpers/smiley_helper.php
+++ b/system/helpers/smiley_helper.php
@@ -59,7 +59,7 @@
 
 				if (is_array($alias))
 				{
-					foreach($alias as $name => $id)
+					foreach ($alias as $name => $id)
 					{
 						$m[] = '"'.$name.'" : "'.$id.'"';
 					}
@@ -101,7 +101,7 @@
 		{
 			if (is_array($alias))
 			{
-				foreach($alias as $name => $id)
+				foreach ($alias as $name => $id)
 				{
 					$r .= 'smiley_map["'.$name.'"] = "'.$id.'";'."\n";
 				}
diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php
index e1b56c9..96afd4c 100644
--- a/system/helpers/text_helper.php
+++ b/system/helpers/text_helper.php
@@ -364,30 +364,21 @@
  */
 if ( ! function_exists('convert_accented_characters'))
 {
-	function convert_accented_characters($match)
+	function convert_accented_characters($str)
 	{
 		if ( ! file_exists(APPPATH.'config/foreign_chars'.EXT))
 		{
-			return $match;
+			return $str;
 		}
 
 		include APPPATH.'config/foreign_chars'.EXT;
 
 		if ( ! isset($foreign_characters))
 		{
-			return $match;
+			return $str;
 		}
 
-		$ord = ord($match['1']);
-
-		if (isset($foreign_characters[$ord]))
-		{
-			return $foreign_characters[$ord];
-		}
-		else
-		{
-			return $match['1'];
-		}
+		return preg_replace(array_keys($foreign_characters), array_values($foreign_characters), $str);
 	}
 }
 
@@ -452,7 +443,7 @@
 			}
 
 			$temp = '';
-			while((strlen($line)) > $charlim)
+			while ((strlen($line)) > $charlim)
 			{
 				// If the over-length word is a URL we won't wrap it
 				if (preg_match("!\[url.+\]|://|wwww.!", $line))
diff --git a/system/language/english/form_validation_lang.php b/system/language/english/form_validation_lang.php
index 99ed70a..b018850 100644
--- a/system/language/english/form_validation_lang.php
+++ b/system/language/english/form_validation_lang.php
@@ -15,6 +15,7 @@
 $lang['numeric']			= "The %s field must contain only numbers.";
 $lang['is_numeric']			= "The %s field must contain only numeric characters.";
 $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_natural']			= "The %s field must contain only positive numbers.";
 $lang['is_natural_no_zero']	= "The %s field must contain a number greater than zero.";
diff --git a/system/libraries/Cache/Cache.php b/system/libraries/Cache/Cache.php
new file mode 100644
index 0000000..d3f6105
--- /dev/null
+++ b/system/libraries/Cache/Cache.php
@@ -0,0 +1,216 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		ExpressionEngine Dev Team
+ * @copyright	Copyright (c) 2006 - 2011 EllisLab, Inc.
+ * @license		http://codeigniter.com/user_guide/license.html
+ * @link		http://codeigniter.com
+ * @since		Version 2.0
+ * @filesource	
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CodeIgniter Caching Class 
+ *
+ * @package		CodeIgniter
+ * @subpackage	Libraries
+ * @category	Core
+ * @author		ExpressionEngine Dev Team
+ * @link		
+ */
+class Cache extends CI_Driver_Library {
+	
+	protected $valid_drivers 	= array(
+				'cache_apc', 'cache_file', 'cache_memcached', 'cache_dummy'
+		);
+
+	protected $_cache_path		= NULL;		// Path of cache files (if file-based cache)
+	protected $_adapter			= 'dummy';
+	protected $_backup_driver;
+	
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Constructor
+	 *
+	 * @param array
+	 */
+	public function __construct($config = array())
+	{
+		if ( ! empty($config))
+		{
+			$this->_initialize($config);
+		}
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Get 
+	 *
+	 * Look for a value in the cache.  If it exists, return the data 
+	 * if not, return FALSE
+	 *
+	 * @param 	string	
+	 * @return 	mixed		value that is stored/FALSE on failure
+	 */
+	public function get($id)
+	{	
+		return $this->{$this->_adapter}->get($id);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Cache Save
+	 *
+	 * @param 	string		Unique Key
+	 * @param 	mixed		Data to store
+	 * @param 	int			Length of time (in seconds) to cache the data
+	 *
+	 * @return 	boolean		true on success/false on failure
+	 */
+	public function save($id, $data, $ttl = 60)
+	{
+		return $this->{$this->_adapter}->save($id, $data, $ttl);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Delete from Cache
+	 *
+	 * @param 	mixed		unique identifier of the item in the cache
+	 * @return 	boolean		true on success/false on failure
+	 */
+	public function delete($id)
+	{
+		return $this->{$this->_adapter}->delete($id);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Clean the cache
+	 *
+	 * @return 	boolean		false on failure/true on success
+	 */
+	public function clean()
+	{
+		return $this->{$this->_adapter}->clean();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Cache Info
+	 *
+	 * @param 	string		user/filehits
+	 * @return 	mixed		array on success, false on failure	
+	 */
+	public function cache_info($type = 'user')
+	{
+		return $this->{$this->_adapter}->cache_info($type);
+	}
+
+	// ------------------------------------------------------------------------
+	
+	/**
+	 * Get Cache Metadata
+	 *
+	 * @param 	mixed		key to get cache metadata on
+	 * @return 	mixed		return value from child method
+	 */
+	public function get_metadata($id)
+	{
+		return $this->{$this->_adapter}->get_metadata($id);
+	}
+	
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Initialize
+	 *
+	 * Initialize class properties based on the configuration array.
+	 *
+	 * @param	array 	
+	 * @return 	void
+	 */
+	private function _initialize($config)
+	{        
+		$default_config = array(
+				'adapter',
+				'memcached'
+			);
+
+		foreach ($default_config as $key)
+		{
+			if (isset($config[$key]))
+			{
+				$param = '_'.$key;
+
+				$this->{$param} = $config[$key];
+			}
+		}
+
+		if (isset($config['backup']))
+		{
+			if (in_array('cache_'.$config['backup'], $this->valid_drivers))
+			{
+				$this->_backup_driver = $config['backup'];
+			}
+		}
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Is the requested driver supported in this environment?
+	 *
+	 * @param 	string	The driver to test.
+	 * @return 	array
+	 */
+	public function is_supported($driver)
+	{
+		static $support = array();
+
+		if ( ! isset($support[$driver]))
+		{
+			$support[$driver] = $this->{$driver}->is_supported();
+		}
+
+		return $support[$driver];
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * __get()
+	 *
+	 * @param 	child
+	 * @return 	object
+	 */
+	public function __get($child)
+	{
+		$obj = parent::__get($child);
+
+		if ( ! $this->is_supported($child))
+		{
+			$this->_adapter = $this->_backup_driver;
+		}
+
+		return $obj;
+	}
+	
+	// ------------------------------------------------------------------------
+}
+// End Class
+
+/* End of file Cache.php */
+/* Location: ./system/libraries/Cache/Cache.php */
\ No newline at end of file
diff --git a/system/libraries/Cache/drivers/Cache_apc.php b/system/libraries/Cache/drivers/Cache_apc.php
new file mode 100644
index 0000000..4b995c7
--- /dev/null
+++ b/system/libraries/Cache/drivers/Cache_apc.php
@@ -0,0 +1,151 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package		CodeIgniter
+ * @author		ExpressionEngine Dev Team
+ * @copyright	Copyright (c) 2006 - 2011 EllisLab, Inc.
+ * @license		http://codeigniter.com/user_guide/license.html
+ * @link		http://codeigniter.com
+ * @since		Version 2.0
+ * @filesource	
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CodeIgniter APC Caching Class 
+ *
+ * @package		CodeIgniter
+ * @subpackage	Libraries
+ * @category	Core
+ * @author		ExpressionEngine Dev Team
+ * @link		
+ */
+
+class Cache_apc extends CI_Driver {
+
+	/**
+	 * Get 
+	 *
+	 * Look for a value in the cache.  If it exists, return the data 
+	 * if not, return FALSE
+	 *
+	 * @param 	string	
+	 * @return 	mixed		value that is stored/FALSE on failure
+	 */
+	public function get($id)
+	{
+		$data = apc_fetch($id);
+
+		return (is_array($data)) ? $data[0] : FALSE;
+	}
+
+	// ------------------------------------------------------------------------	
+	
+	/**
+	 * Cache Save
+	 *
+	 * @param 	string		Unique Key
+	 * @param 	mixed		Data to store
+	 * @param 	int			Length of time (in seconds) to cache the data
+	 *
+	 * @return 	boolean		true on success/false on failure
+	 */
+	public function save($id, $data, $ttl = 60)
+	{
+		return apc_store($id, array($data, time(), $ttl), $ttl);
+	}
+	
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Delete from Cache
+	 *
+	 * @param 	mixed		unique identifier of the item in the cache
+	 * @param 	boolean		true on success/false on failure
+	 */
+	public function delete($id)
+	{
+		return apc_delete($id);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Clean the cache
+	 *
+	 * @return 	boolean		false on failure/true on success
+	 */
+	public function clean()
+	{
+		return apc_clear_cache('user');
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Cache Info
+	 *
+	 * @param 	string		user/filehits
+	 * @return 	mixed		array on success, false on failure	
+	 */
+	 public function cache_info($type = NULL)
+	 {
+		 return apc_cache_info($type);
+	 }
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Get Cache Metadata
+	 *
+	 * @param 	mixed		key to get cache metadata on
+	 * @return 	mixed		array on success/false on failure
+	 */
+	public function get_metadata($id)
+	{
+		$stored = apc_fetch($id);
+
+		if (count($stored) !== 3)
+		{
+			return FALSE;
+		}
+
+		list($data, $time, $ttl) = $stored;
+
+		return array(
+			'expire'	=> $time + $ttl,
+			'mtime'		=> $time,
+			'data'		=> $data
+		);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * is_supported()
+	 *
+	 * Check to see if APC is available on this system, bail if it isn't.
+	 */
+	public function is_supported()
+	{
+		if ( ! extension_loaded('apc') OR ! function_exists('apc_store'))
+		{
+			log_message('error', 'The APC PHP extension must be loaded to use APC Cache.');
+			return FALSE;
+		}
+		
+		return TRUE;
+	}
+
+	// ------------------------------------------------------------------------
+
+	
+}
+// End Class
+
+/* End of file Cache_apc.php */
+/* Location: ./system/libraries/Cache/drivers/Cache_apc.php */
\ No newline at end of file
diff --git a/system/libraries/Cache/drivers/Cache_dummy.php b/system/libraries/Cache/drivers/Cache_dummy.php
new file mode 100644
index 0000000..74f6892
--- /dev/null
+++ b/system/libraries/Cache/drivers/Cache_dummy.php
@@ -0,0 +1,129 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		ExpressionEngine Dev Team
+ * @copyright	Copyright (c) 2006 - 2011 EllisLab, Inc.
+ * @license		http://codeigniter.com/user_guide/license.html
+ * @link		http://codeigniter.com
+ * @since		Version 2.0
+ * @filesource	
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CodeIgniter Dummy Caching Class 
+ *
+ * @package		CodeIgniter
+ * @subpackage	Libraries
+ * @category	Core
+ * @author		ExpressionEngine Dev Team
+ * @link		
+ */
+
+class Cache_dummy extends CI_Driver {
+
+	/**
+	 * Get 
+	 *
+	 * Since this is the dummy class, it's always going to return FALSE.
+	 *
+	 * @param 	string	
+	 * @return 	Boolean		FALSE
+	 */
+	public function get($id)
+	{
+		return FALSE;
+	}
+
+	// ------------------------------------------------------------------------	
+	
+	/**
+	 * Cache Save
+	 *
+	 * @param 	string		Unique Key
+	 * @param 	mixed		Data to store
+	 * @param 	int			Length of time (in seconds) to cache the data
+	 *
+	 * @return 	boolean		TRUE, Simulating success
+	 */
+	public function save($id, $data, $ttl = 60)
+	{
+		return TRUE;
+	}
+	
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Delete from Cache
+	 *
+	 * @param 	mixed		unique identifier of the item in the cache
+	 * @param 	boolean		TRUE, simulating success
+	 */
+	public function delete($id)
+	{
+		return TRUE;
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Clean the cache
+	 *
+	 * @return 	boolean		TRUE, simulating success
+	 */
+	public function clean()
+	{
+		return TRUE;
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Cache Info
+	 *
+	 * @param 	string		user/filehits
+	 * @return 	boolean		FALSE
+	 */
+	 public function cache_info($type = NULL)
+	 {
+		 return FALSE;
+	 }
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Get Cache Metadata
+	 *
+	 * @param 	mixed		key to get cache metadata on
+	 * @return 	boolean		FALSE
+	 */
+	public function get_metadata($id)
+	{
+		return FALSE;
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Is this caching driver supported on the system?
+	 * Of course this one is.
+	 * 
+	 * @return TRUE;
+	 */
+	public function is_supported()
+	{
+		return TRUE;
+	}
+
+	// ------------------------------------------------------------------------
+	
+}
+// End Class
+
+/* End of file Cache_apc.php */
+/* Location: ./system/libraries/Cache/drivers/Cache_apc.php */
\ No newline at end of file
diff --git a/system/libraries/Cache/drivers/Cache_file.php b/system/libraries/Cache/drivers/Cache_file.php
new file mode 100644
index 0000000..86d1a3b
--- /dev/null
+++ b/system/libraries/Cache/drivers/Cache_file.php
@@ -0,0 +1,196 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		ExpressionEngine Dev Team
+ * @copyright	Copyright (c) 2006 - 2011 EllisLab, Inc.
+ * @license		http://codeigniter.com/user_guide/license.html
+ * @link		http://codeigniter.com
+ * @since		Version 2.0
+ * @filesource	
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CodeIgniter Memcached Caching Class 
+ *
+ * @package		CodeIgniter
+ * @subpackage	Libraries
+ * @category	Core
+ * @author		ExpressionEngine Dev Team
+ * @link		
+ */
+
+class Cache_file extends CI_Driver {
+
+	protected $_cache_path;
+
+	/**
+	 * Constructor
+	 */
+	public function __construct()
+	{
+		$CI =& get_instance();
+		$CI->load->helper('file');
+		
+		$path = $CI->config->item('cache_path');
+	
+		$this->_cache_path = ($path == '') ? APPPATH.'cache/' : $path;
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Fetch from cache
+	 *
+	 * @param 	mixed		unique key id
+	 * @return 	mixed		data on success/false on failure
+	 */
+	public function get($id)
+	{
+		if ( ! file_exists($this->_cache_path.$id))
+		{
+			return FALSE;
+		}
+		
+		$data = read_file($this->_cache_path.$id);
+		$data = unserialize($data);
+		
+		if (time() >  $data['time'] + $data['ttl'])
+		{
+			unlink($this->_cache_path.$id);
+			return FALSE;
+		}
+		
+		return $data['data'];
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Save into cache
+	 *
+	 * @param 	string		unique key
+	 * @param 	mixed		data to store
+	 * @param 	int			length of time (in seconds) the cache is valid 
+	 *						- Default is 60 seconds
+	 * @return 	boolean		true on success/false on failure
+	 */
+	public function save($id, $data, $ttl = 60)
+	{		
+		$contents = array(
+				'time'		=> time(),
+				'ttl'		=> $ttl,			
+				'data'		=> $data
+			);
+		
+		if (write_file($this->_cache_path.$id, serialize($contents)))
+		{
+			@chmod($this->_cache_path.$id, 0777);
+			return TRUE;			
+		}
+
+		return FALSE;
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Delete from Cache
+	 *
+	 * @param 	mixed		unique identifier of item in cache
+	 * @return 	boolean		true on success/false on failure
+	 */
+	public function delete($id)
+	{
+		return unlink($this->_cache_path.$id);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Clean the Cache
+	 *
+	 * @return 	boolean		false on failure/true on success
+	 */	
+	public function clean()
+	{
+		return delete_files($this->_cache_path);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Cache Info
+	 *
+	 * Not supported by file-based caching
+	 *
+	 * @param 	string	user/filehits
+	 * @return 	mixed 	FALSE
+	 */
+	public function cache_info($type = NULL)
+	{
+		return get_dir_file_info($this->_cache_path);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Get Cache Metadata
+	 *
+	 * @param 	mixed		key to get cache metadata on
+	 * @return 	mixed		FALSE on failure, array on success.
+	 */
+	public function get_metadata($id)
+	{
+		if ( ! file_exists($this->_cache_path.$id))
+		{
+			return FALSE;
+		}
+		
+		$data = read_file($this->_cache_path.$id);		
+		$data = unserialize($data);
+		
+		if (is_array($data))
+		{
+			$data = $data['data'];
+			$mtime = filemtime($this->_cache_path.$id);
+
+			if ( ! isset($data['ttl']))
+			{
+				return FALSE;
+			}
+
+			return array(
+				'expire' 	=> $mtime + $data['ttl'],
+				'mtime'		=> $mtime
+			);
+		}
+		
+		return FALSE;
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Is supported
+	 *
+	 * In the file driver, check to see that the cache directory is indeed writable
+	 * 
+	 * @return boolean
+	 */
+	public function is_supported()
+	{
+		return is_really_writable($this->_cache_path);
+	}
+
+	// ------------------------------------------------------------------------
+}
+// End Class
+
+/* End of file Cache_file.php */
+/* Location: ./system/libraries/Cache/drivers/Cache_file.php */
\ No newline at end of file
diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php
new file mode 100644
index 0000000..5f5a315
--- /dev/null
+++ b/system/libraries/Cache/drivers/Cache_memcached.php
@@ -0,0 +1,209 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		ExpressionEngine Dev Team
+ * @copyright	Copyright (c) 2006 - 2011 EllisLab, Inc.
+ * @license		http://codeigniter.com/user_guide/license.html
+ * @link		http://codeigniter.com
+ * @since		Version 2.0
+ * @filesource	
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CodeIgniter Memcached Caching Class 
+ *
+ * @package		CodeIgniter
+ * @subpackage	Libraries
+ * @category	Core
+ * @author		ExpressionEngine Dev Team
+ * @link		
+ */
+
+class Cache_memcached extends CI_Driver {
+
+	private $_memcached;	// Holds the memcached object
+
+	protected $_memcache_conf 	= array(
+					'default' => array(
+						'default_host'		=> '127.0.0.1',
+						'default_port'		=> 11211,
+						'default_weight'	=> 1
+					)
+				);
+
+	// ------------------------------------------------------------------------	
+
+	/**
+	 * Fetch from cache
+	 *
+	 * @param 	mixed		unique key id
+	 * @return 	mixed		data on success/false on failure
+	 */	
+	public function get($id)
+	{	
+		$data = $this->_memcached->get($id);
+		
+		return (is_array($data)) ? $data[0] : FALSE;
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Save
+	 *
+	 * @param 	string		unique identifier
+	 * @param 	mixed		data being cached
+	 * @param 	int			time to live
+	 * @return 	boolean 	true on success, false on failure
+	 */
+	public function save($id, $data, $ttl = 60)
+	{
+		return $this->_memcached->add($id, array($data, time(), $ttl), $ttl);
+	}
+
+	// ------------------------------------------------------------------------
+	
+	/**
+	 * Delete from Cache
+	 *
+	 * @param 	mixed		key to be deleted.
+	 * @return 	boolean 	true on success, false on failure
+	 */
+	public function delete($id)
+	{
+		return $this->_memcached->delete($id);
+	}
+
+	// ------------------------------------------------------------------------
+	
+	/**
+	 * Clean the Cache
+	 *
+	 * @return 	boolean		false on failure/true on success
+	 */
+	public function clean()
+	{
+		return $this->_memcached->flush();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Cache Info
+	 *
+	 * @param 	null		type not supported in memcached
+	 * @return 	mixed 		array on success, false on failure
+	 */
+	public function cache_info($type = NULL)
+	{
+		return $this->_memcached->getStats();
+	}
+
+	// ------------------------------------------------------------------------
+	
+	/**
+	 * Get Cache Metadata
+	 *
+	 * @param 	mixed		key to get cache metadata on
+	 * @return 	mixed		FALSE on failure, array on success.
+	 */
+	public function get_metadata($id)
+	{
+		$stored = $this->_memcached->get($id);
+
+		if (count($stored) !== 3)
+		{
+			return FALSE;
+		}
+
+		list($data, $time, $ttl) = $stored;
+
+		return array(
+			'expire'	=> $time + $ttl,
+			'mtime'		=> $time,
+			'data'		=> $data
+		);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * Setup memcached.
+	 */
+	private function _setup_memcached()
+	{
+		// Try to load memcached server info from the config file.
+		$CI =& get_instance();
+		if ($CI->config->load('memcached', TRUE, TRUE))
+		{
+			if (is_array($CI->config->config['memcached']))
+			{
+				$this->_memcache_conf = NULL;
+
+				foreach ($CI->config->config['memcached'] as $name => $conf)
+				{
+					$this->_memcache_conf[$name] = $conf;
+				}				
+			}			
+		}
+		
+		$this->_memcached = new Memcached();
+
+		foreach ($this->_memcache_conf as $name => $cache_server)
+		{
+			if ( ! array_key_exists('hostname', $cache_server))
+			{
+				$cache_server['hostname'] = $this->_default_options['default_host'];
+			}
+	
+			if ( ! array_key_exists('port', $cache_server))
+			{
+				$cache_server['port'] = $this->_default_options['default_port'];
+			}
+	
+			if ( ! array_key_exists('weight', $cache_server))
+			{
+				$cache_server['weight'] = $this->_default_options['default_weight'];
+			}
+	
+			$this->_memcached->addServer(
+					$cache_server['hostname'], $cache_server['port'], $cache_server['weight']
+			);
+		}
+	}
+
+	// ------------------------------------------------------------------------
+
+
+	/**
+	 * Is supported
+	 *
+	 * Returns FALSE if memcached is not supported on the system.
+	 * If it is, we setup the memcached object & return TRUE
+	 */
+	public function is_supported()
+	{
+		if ( ! extension_loaded('memcached'))
+		{
+			log_message('error', 'The Memcached Extension must be loaded to use Memcached Cache.');
+			
+			return FALSE;
+		}
+		
+		$this->_setup_memcached();
+		return TRUE;
+	}
+
+	// ------------------------------------------------------------------------
+
+}
+// End Class
+
+/* End of file Cache_memcached.php */
+/* Location: ./system/libraries/Cache/drivers/Cache_memcached.php */
\ No newline at end of file
diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php
index 15fc3da..02e093d 100644
--- a/system/libraries/Driver.php
+++ b/system/libraries/Driver.php
@@ -1,4 +1,4 @@
-<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
 /**
  * CodeIgniter
  *
@@ -36,7 +36,7 @@
 	// subsequents calls will go straight to the proper child.
 	function __get($child)
 	{
-		if (! isset($this->lib_name))
+		if ( ! isset($this->lib_name))
 		{
 			$this->lib_name = get_class($this);
 		}
@@ -143,7 +143,7 @@
 				}
 			}
 
-			foreach($r->getProperties() as $prop)
+			foreach ($r->getProperties() as $prop)
 			{
 				if ($prop->isPublic())
 				{
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index c6d8944..6c21f11 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -82,7 +82,7 @@
 	 *
 	 * The constructor can be passed an array of config values
 	 */
-	function __construct($config = array())
+	public function __construct($config = array())
 	{
 		if (count($config) > 0)
 		{
@@ -106,9 +106,8 @@
 	 * @param	array
 	 * @return	void
 	 */
-	function initialize($config = array())
+	public function initialize($config = array())
 	{
-		$this->clear();
 		foreach ($config as $key => $val)
 		{
 			if (isset($this->$key))
@@ -125,9 +124,12 @@
 				}
 			}
 		}
+		$this->clear();
 
 		$this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE;
 		$this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE;
+
+		return $this;
 	}
 
 	// --------------------------------------------------------------------
@@ -138,7 +140,7 @@
 	 * @access	public
 	 * @return	void
 	 */
-	function clear($clear_attachments = FALSE)
+	public function clear($clear_attachments = FALSE)
 	{
 		$this->_subject		= "";
 		$this->_body		= "";
@@ -160,7 +162,7 @@
 			$this->_attach_type = array();
 			$this->_attach_disp = array();
 		}
-		
+
 		return $this;
 	}
 
@@ -174,7 +176,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function from($from, $name = '')
+	public function from($from, $name = '')
 	{
 		if (preg_match( '/\<(.*)\>/', $from, $match))
 		{
@@ -203,7 +205,7 @@
 
 		$this->_set_header('From', $name.' <'.$from.'>');
 		$this->_set_header('Return-Path', '<'.$from.'>');
-		
+
 		return $this;
 	}
 
@@ -217,7 +219,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function reply_to($replyto, $name = '')
+	public function reply_to($replyto, $name = '')
 	{
 		if (preg_match( '/\<(.*)\>/', $replyto, $match))
 		{
@@ -254,7 +256,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function to($to)
+	public function to($to)
 	{
 		$to = $this->_str_to_array($to);
 		$to = $this->clean_email($to);
@@ -271,14 +273,15 @@
 
 		switch ($this->_get_protocol())
 		{
-			case 'smtp'		: $this->_recipients = $to;
+			case 'smtp'		:
+				$this->_recipients = $to;
 			break;
-			case 'sendmail'	: $this->_recipients = implode(", ", $to);
-			break;
-			case 'mail'		: $this->_recipients = implode(", ", $to);
+			case 'sendmail'	:
+			case 'mail'		:
+				$this->_recipients = implode(", ", $to);
 			break;
 		}
-		
+
 		return $this;
 	}
 
@@ -291,7 +294,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function cc($cc)
+	public function cc($cc)
 	{
 		$cc = $this->_str_to_array($cc);
 		$cc = $this->clean_email($cc);
@@ -307,7 +310,7 @@
 		{
 			$this->_cc_array = $cc;
 		}
-		
+
 		return $this;
 	}
 
@@ -321,7 +324,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function bcc($bcc, $limit = '')
+	public function bcc($bcc, $limit = '')
 	{
 		if ($limit != '' && is_numeric($limit))
 		{
@@ -345,7 +348,7 @@
 		{
 			$this->_set_header('Bcc', implode(", ", $bcc));
 		}
-		
+
 		return $this;
 	}
 
@@ -358,7 +361,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function subject($subject)
+	public function subject($subject)
 	{
 		$subject = $this->_prep_q_encoding($subject);
 		$this->_set_header('Subject', $subject);
@@ -374,7 +377,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function message($body)
+	public function message($body)
 	{
 		$this->_body = stripslashes(rtrim(str_replace("\r", "", $body)));
 		return $this;
@@ -389,7 +392,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function attach($filename, $disposition = 'attachment')
+	public function attach($filename, $disposition = 'attachment')
 	{
 		$this->_attach_name[] = $filename;
 		$this->_attach_type[] = $this->_mime_types(next(explode('.', basename($filename))));
@@ -407,7 +410,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function _set_header($header, $value)
+	private function _set_header($header, $value)
 	{
 		$this->_headers[$header] = $value;
 	}
@@ -421,7 +424,7 @@
 	 * @param	string
 	 * @return	array
 	 */
-	function _str_to_array($email)
+	private function _str_to_array($email)
 	{
 		if ( ! is_array($email))
 		{
@@ -447,7 +450,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function set_alt_message($str = '')
+	public function set_alt_message($str = '')
 	{
 		$this->alt_message = ($str == '') ? '' : $str;
 		return $this;
@@ -462,7 +465,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function set_mailtype($type = 'text')
+	public function set_mailtype($type = 'text')
 	{
 		$this->mailtype = ($type == 'html') ? 'html' : 'text';
 		return $this;
@@ -477,7 +480,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function set_wordwrap($wordwrap = TRUE)
+	public function set_wordwrap($wordwrap = TRUE)
 	{
 		$this->wordwrap = ($wordwrap === FALSE) ? FALSE : TRUE;
 		return $this;
@@ -492,7 +495,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function set_protocol($protocol = 'mail')
+	public function set_protocol($protocol = 'mail')
 	{
 		$this->protocol = ( ! in_array($protocol, $this->_protocols, TRUE)) ? 'mail' : strtolower($protocol);
 		return $this;
@@ -507,7 +510,7 @@
 	 * @param	integer
 	 * @return	void
 	 */
-	function set_priority($n = 3)
+	public function set_priority($n = 3)
 	{
 		if ( ! is_numeric($n))
 		{
@@ -534,7 +537,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function set_newline($newline = "\n")
+	public function set_newline($newline = "\n")
 	{
 		if ($newline != "\n" AND $newline != "\r\n" AND $newline != "\r")
 		{
@@ -543,7 +546,7 @@
 		}
 
 		$this->newline	= $newline;
-		
+
 		return $this;
 	}
 
@@ -556,7 +559,7 @@
 	 * @param	string
 	 * @return	void
 	 */
-	function set_crlf($crlf = "\n")
+	public function set_crlf($crlf = "\n")
 	{
 		if ($crlf != "\n" AND $crlf != "\r\n" AND $crlf != "\r")
 		{
@@ -565,7 +568,7 @@
 		}
 
 		$this->crlf	= $crlf;
-		
+
 		return $this;
 	}
 
@@ -577,7 +580,7 @@
 	 * @access	private
 	 * @return	void
 	 */
-	function _set_boundaries()
+	private function _set_boundaries()
 	{
 		$this->_alt_boundary = "B_ALT_".uniqid(''); // multipart/alternative
 		$this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary
@@ -591,7 +594,7 @@
 	 * @access	private
 	 * @return	string
 	 */
-	function _get_message_id()
+	private function _get_message_id()
 	{
 		$from = $this->_headers['Return-Path'];
 		$from = str_replace(">", "", $from);
@@ -609,7 +612,7 @@
 	 * @param	bool
 	 * @return	string
 	 */
-	function _get_protocol($return = TRUE)
+	private function _get_protocol($return = TRUE)
 	{
 		$this->protocol = strtolower($this->protocol);
 		$this->protocol = ( ! in_array($this->protocol, $this->_protocols, TRUE)) ? 'mail' : $this->protocol;
@@ -629,7 +632,7 @@
 	 * @param	bool
 	 * @return	string
 	 */
-	function _get_encoding($return = TRUE)
+	private function _get_encoding($return = TRUE)
 	{
 		$this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '8bit' : $this->_encoding;
 
@@ -655,7 +658,7 @@
 	 * @access	private
 	 * @return	string
 	 */
-	function _get_content_type()
+	private function _get_content_type()
 	{
 		if	($this->mailtype == 'html' &&  count($this->_attach_name) == 0)
 		{
@@ -683,7 +686,7 @@
 	 * @access	private
 	 * @return	string
 	 */
-	function _set_date()
+	private function _set_date()
 	{
 		$timezone = date("Z");
 		$operator = (strncmp($timezone, '-', 1) == 0) ? '-' : '+';
@@ -701,7 +704,7 @@
 	 * @access	private
 	 * @return	string
 	 */
-	function _get_mime_message()
+	private function _get_mime_message()
 	{
 		return "This is a multi-part message in MIME format.".$this->newline."Your email application may not support this format.";
 	}
@@ -715,7 +718,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function validate_email($email)
+	public function validate_email($email)
 	{
 		if ( ! is_array($email))
 		{
@@ -744,7 +747,7 @@
 	 * @param	string
 	 * @return	bool
 	 */
-	function valid_email($address)
+	public function valid_email($address)
 	{
 		return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $address)) ? FALSE : TRUE;
 	}
@@ -758,7 +761,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function clean_email($email)
+	public function clean_email($email)
 	{
 		if ( ! is_array($email))
 		{
@@ -794,7 +797,7 @@
 	/**
 	 * Build alternative plain text message
 	 *
-	 * This function provides the raw message for use
+	 * This public function provides the raw message for use
 	 * in plain-text headers of HTML-formatted emails.
 	 * If the user hasn't specified his own alternative message
 	 * it creates one by stripping the HTML
@@ -802,7 +805,7 @@
 	 * @access	private
 	 * @return	string
 	 */
-	function _get_alt_message()
+	private function _get_alt_message()
 	{
 		if ($this->alt_message != "")
 		{
@@ -847,7 +850,7 @@
 	 * @param	integer
 	 * @return	string
 	 */
-	function word_wrap($str, $charlim = '')
+	public function word_wrap($str, $charlim = '')
 	{
 		// Se the character limit
 		if ($charlim == '')
@@ -876,7 +879,7 @@
 			}
 		}
 
-		// Use PHP's native function to do the initial wordwrap.
+		// Use PHP's native public function to do the initial wordwrap.
 		// We set the cut flag to FALSE so that any individual words that are
 		// too long get left alone.  In the next step we'll deal with them.
 		$str = wordwrap($str, $charlim, "\n", FALSE);
@@ -894,7 +897,7 @@
 			}
 
 			$temp = '';
-			while((strlen($line)) > $charlim)
+			while ((strlen($line)) > $charlim)
 			{
 				// If the over-length word is a URL we won't wrap it
 				if (preg_match("!\[url.+\]|://|wwww.!", $line))
@@ -942,7 +945,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function _build_headers()
+	private function _build_headers()
 	{
 		$this->_set_header('X-Sender', $this->clean_email($this->_headers['From']));
 		$this->_set_header('X-Mailer', $this->useragent);
@@ -959,7 +962,7 @@
 	 * @access	private
 	 * @return	void
 	 */
-	function _write_headers()
+	private function _write_headers()
 	{
 		if ($this->protocol == 'mail')
 		{
@@ -970,7 +973,7 @@
 		reset($this->_headers);
 		$this->_header_str = "";
 
-		foreach($this->_headers as $key => $val)
+		foreach ($this->_headers as $key => $val)
 		{
 			$val = trim($val);
 
@@ -994,7 +997,7 @@
 	 * @access	private
 	 * @return	void
 	 */
-	function _build_message()
+	private function _build_message()
 	{
 		if ($this->wordwrap === TRUE  AND  $this->mailtype != 'html')
 		{
@@ -1023,7 +1026,7 @@
 				{
 					$this->_finalbody = $hdr . $this->newline . $this->newline . $this->_body;
 				}
-				
+
 				return;
 
 			break;
@@ -1048,10 +1051,10 @@
 					$body .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
 					$body .= "Content-Transfer-Encoding: quoted-printable" . $this->newline . $this->newline;
 				}
-				
+
 				$this->_finalbody = $body . $this->_prep_quoted_printable($this->_body) . $this->newline . $this->newline;
-				
-				
+
+
 				if ($this->_get_protocol() == 'mail')
 				{
 					$this->_header_str .= $hdr;
@@ -1077,8 +1080,8 @@
 				if ($this->_get_protocol() == 'mail')
 				{
 					$this->_header_str .= $hdr;
-				}				
-				
+				}
+
 				$body .= $this->_get_mime_message() . $this->newline . $this->newline;
 				$body .= "--" . $this->_atc_boundary . $this->newline;
 
@@ -1091,7 +1094,7 @@
 			case 'html-attach' :
 
 				$hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline . $this->newline;
-				
+
 				if ($this->_get_protocol() == 'mail')
 				{
 					$this->_header_str .= $hdr;
@@ -1152,7 +1155,7 @@
 		}
 
 		$body .= implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--";
-		
+
 
 		if ($this->_get_protocol() == 'mail')
 		{
@@ -1162,7 +1165,7 @@
 		{
 			$this->_finalbody = $hdr . $body;
 		}
-		
+
 		return;
 	}
 
@@ -1179,7 +1182,7 @@
 	 * @param	integer
 	 * @return	string
 	 */
-	function _prep_quoted_printable($str, $charlim = '')
+	private function _prep_quoted_printable($str, $charlim = '')
 	{
 		// Set the character limit
 		// Don't allow over 76, as that will make servers and MUAs barf
@@ -1272,7 +1275,7 @@
 	 * @param	bool	// set to TRUE for processing From: headers
 	 * @return	str
 	 */
-	function _prep_q_encoding($str, $from = FALSE)
+	private function _prep_q_encoding($str, $from = FALSE)
 	{
 		$str = str_replace(array("\r", "\n"), array('', ''), $str);
 
@@ -1339,7 +1342,7 @@
 	 * @access	public
 	 * @return	bool
 	 */
-	function send()
+	public function send()
 	{
 		if ($this->_replyto_flag == FALSE)
 		{
@@ -1382,7 +1385,7 @@
 	 * @access	public
 	 * @return	bool
 	 */
-	function batch_bcc_send()
+	public function batch_bcc_send()
 	{
 		$float = $this->bcc_batch_size -1;
 
@@ -1440,7 +1443,7 @@
 	 * @access	private
 	 * @return	void
 	 */
-	function _unwrap_specials()
+	private function _unwrap_specials()
 	{
 		$this->_finalbody = preg_replace_callback("/\{unwrap\}(.*?)\{\/unwrap\}/si", array($this, '_remove_nl_callback'), $this->_finalbody);
 	}
@@ -1453,7 +1456,7 @@
 	 * @access	private
 	 * @return	string
 	 */
-	function _remove_nl_callback($matches)
+	private function _remove_nl_callback($matches)
 	{
 		if (strpos($matches[1], "\r") !== FALSE OR strpos($matches[1], "\n") !== FALSE)
 		{
@@ -1471,7 +1474,7 @@
 	 * @access	private
 	 * @return	bool
 	 */
-	function _spool_email()
+	private function _spool_email()
 	{
 		$this->_unwrap_specials();
 
@@ -1516,7 +1519,7 @@
 	 * @access	private
 	 * @return	bool
 	 */
-	function _send_with_mail()
+	private function _send_with_mail()
 	{
 		if ($this->_safe_mode == TRUE)
 		{
@@ -1533,7 +1536,7 @@
 		{
 			// most documentation of sendmail using the "-f" flag lacks a space after it, however
 			// we've encountered servers that seem to require it to be in place.
-						
+
 			if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, "-f ".$this->clean_email($this->_headers['From'])))
 			{
 				return FALSE;
@@ -1553,7 +1556,7 @@
 	 * @access	private
 	 * @return	bool
 	 */
-	function _send_with_sendmail()
+	private function _send_with_sendmail()
 	{
 		$fp = @popen($this->mailpath . " -oi -f ".$this->clean_email($this->_headers['From'])." -t", 'w');
 
@@ -1567,7 +1570,7 @@
 		fputs($fp, $this->_finalbody);
 
 		$status = pclose($fp);
-	
+
 		if (version_compare(PHP_VERSION, '4.2.3') == -1)
 		{
 			$status = $status >> 8 & 0xFF;
@@ -1591,7 +1594,7 @@
 	 * @access	private
 	 * @return	bool
 	 */
-	function _send_with_smtp()
+	private function _send_with_smtp()
 	{
 		if ($this->smtp_host == '')
 		{
@@ -1604,14 +1607,14 @@
 
 		$this->_send_command('from', $this->clean_email($this->_headers['From']));
 
-		foreach($this->_recipients as $val)
+		foreach ($this->_recipients as $val)
 		{
 			$this->_send_command('to', $val);
 		}
 
 		if (count($this->_cc_array) > 0)
 		{
-			foreach($this->_cc_array as $val)
+			foreach ($this->_cc_array as $val)
 			{
 				if ($val != "")
 				{
@@ -1622,7 +1625,7 @@
 
 		if (count($this->_bcc_array) > 0)
 		{
-			foreach($this->_bcc_array as $val)
+			foreach ($this->_bcc_array as $val)
 			{
 				if ($val != "")
 				{
@@ -1661,7 +1664,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function _smtp_connect()
+	private function _smtp_connect()
 	{
 		$this->_smtp_connect = fsockopen($this->smtp_host,
 										$this->smtp_port,
@@ -1669,7 +1672,7 @@
 										$errstr,
 										$this->smtp_timeout);
 
-		if( ! is_resource($this->_smtp_connect))
+		if ( ! is_resource($this->_smtp_connect))
 		{
 			$this->_set_error_message('email_smtp_error', $errno." ".$errstr);
 			return FALSE;
@@ -1689,7 +1692,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function _send_command($cmd, $data = '')
+	private function _send_command($cmd, $data = '')
 	{
 		switch ($cmd)
 		{
@@ -1754,7 +1757,7 @@
 	 * @access	private
 	 * @return	bool
 	 */
-	function _smtp_authenticate()
+	private function _smtp_authenticate()
 	{
 		if ( ! $this->_smtp_auth)
 		{
@@ -1808,7 +1811,7 @@
 	 * @access	private
 	 * @return	bool
 	 */
-	function _send_data($data)
+	private function _send_data($data)
 	{
 		if ( ! fwrite($this->_smtp_connect, $data . $this->newline))
 		{
@@ -1829,7 +1832,7 @@
 	 * @access	private
 	 * @return	string
 	 */
-	function _get_smtp_data()
+	private function _get_smtp_data()
 	{
 		$data = "";
 
@@ -1854,7 +1857,7 @@
 	 * @access	private
 	 * @return	string
 	 */
-	function _get_hostname()
+	private function _get_hostname()
 	{
 		return (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain';
 	}
@@ -1867,7 +1870,7 @@
 	 * @access	private
 	 * @return	string
 	 */
-	function _get_ip()
+	private function _get_ip()
 	{
 		if ($this->_IP !== FALSE)
 		{
@@ -1909,7 +1912,7 @@
 	 * @access	public
 	 * @return	string
 	 */
-	function print_debugger()
+	public function print_debugger()
 	{
 		$msg = '';
 
@@ -1934,7 +1937,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function _set_error_message($msg, $val = '')
+	private function _set_error_message($msg, $val = '')
 	{
 		$CI =& get_instance();
 		$CI->lang->load('email');
@@ -1958,7 +1961,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function _mime_types($ext = "")
+	private function _mime_types($ext = "")
 	{
 		$mimes = array(	'hqx'	=>	'application/mac-binhex40',
 						'cpt'	=>	'application/mac-compactpro',
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index cbefca1..adfd17d 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -138,14 +138,14 @@
 
 		// Build our master array
 		$this->_field_data[$field] = array(
-											'field'				=> $field,
-											'label'				=> $label,
-											'rules'				=> $rules,
-											'is_array'			=> $is_array,
-											'keys'				=> $indexes,
-											'postdata'			=> NULL,
-											'error'				=> ''
-											);
+			'field'				=> $field,
+			'label'				=> $label,
+			'rules'				=> $rules,
+			'is_array'			=> $is_array,
+			'keys'				=> $indexes,
+			'postdata'			=> NULL,
+			'error'				=> ''
+		);
 
 		return $this;
 	}
@@ -171,7 +171,7 @@
 		}
 
 		$this->_error_messages = array_merge($this->_error_messages, $lang);
-		
+
 		return $this;
 	}
 
@@ -191,7 +191,7 @@
 	{
 		$this->_error_prefix = $prefix;
 		$this->_error_suffix = $suffix;
-		
+
 		return $this;
 	}
 
@@ -576,7 +576,7 @@
 			// Strip the parameter (if exists) from the rule
 			// Rules can contain a parameter: max_length[5]
 			$param = FALSE;
-			if (preg_match("/(.*?)\[(.*?)\]/", $rule, $match))
+			if (preg_match("/(.*?)\[(.*)\]/", $rule, $match))
 			{
 				$rule	= $match[1];
 				$param	= $match[2];
@@ -730,6 +730,13 @@
 			return $default;
 		}
 
+		// If the data is an array output them one at a time.
+		//     E.g: form_input('name[]', set_value('name[]');
+		if (is_array($this->_field_data[$field]['postdata']))
+		{
+			return array_shift($this->_field_data[$field]['postdata']);
+		}
+
 		return $this->_field_data[$field]['postdata'];
 	}
 
@@ -889,6 +896,26 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Performs a Regular Expression match test.
+	 *
+	 * @access	public
+	 * @param	string
+	 * @param	regex
+	 * @return	bool
+	 */
+	function regex_match($str, $regex)
+	{
+		if ( ! preg_match($regex, $str))
+		{
+			return FALSE;
+		}
+
+		return  TRUE;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Match one field to another
 	 *
 	 * @access	public
@@ -1013,7 +1040,7 @@
 			return $this->valid_email(trim($str));
 		}
 
-		foreach(explode(',', $str) as $email)
+		foreach (explode(',', $str) as $email)
 		{
 			if (trim($email) != '' && $this->valid_email(trim($email)) === FALSE)
 			{
@@ -1120,7 +1147,57 @@
 	 */
 	function integer($str)
 	{
-		return (bool)preg_match( '/^[\-+]?[0-9]+$/', $str);
+		return (bool) preg_match('/^[\-+]?[0-9]+$/', $str);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Decimal number
+	 *
+	 * @access	public
+	 * @param	string
+	 * @return	bool
+	 */
+	function decimal($str)
+	{
+		return (bool) preg_match('/^[\-+]?[0-9]+\.[0-9]+$/', $str);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Greather than
+	 *
+	 * @access	public
+	 * @param	string
+	 * @return	bool
+	 */
+	function greater_than($str, $min)
+	{
+		if ( ! is_numeric($str))
+		{
+			return FALSE;
+		}
+		return $str > $min;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Less than
+	 *
+	 * @access	public
+	 * @param	string
+	 * @return	bool
+	 */
+	function less_than($str, $max)
+	{
+		if ( ! is_numeric($str))
+		{
+			return FALSE;
+		}
+		return $str < $max;
 	}
 
 	// --------------------------------------------------------------------
@@ -1134,7 +1211,7 @@
 	 */
 	function is_natural($str)
 	{
-		return (bool)preg_match( '/^[0-9]+$/', $str);
+		return (bool) preg_match( '/^[0-9]+$/', $str);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php
index 41f9ad3..8902f52 100644
--- a/system/libraries/Image_lib.php
+++ b/system/libraries/Image_lib.php
@@ -749,7 +749,7 @@
 
 		@chmod($this->full_dst_path, FILE_WRITE_MODE);
 
-		return true;
+		return TRUE;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php
index 6587eae..8a1f18c 100644
--- a/system/libraries/Profiler.php
+++ b/system/libraries/Profiler.php
@@ -415,7 +415,7 @@
 
 		$output .= "\n\n<table style='width:100%'>\n";
 
-		foreach(array('HTTP_ACCEPT', 'HTTP_USER_AGENT', 'HTTP_CONNECTION', 'SERVER_PORT', 'SERVER_NAME', 'REMOTE_ADDR', 'SERVER_SOFTWARE', 'HTTP_ACCEPT_LANGUAGE', 'SCRIPT_NAME', 'REQUEST_METHOD',' HTTP_HOST', 'REMOTE_HOST', 'CONTENT_TYPE', 'SERVER_PROTOCOL', 'QUERY_STRING', 'HTTP_ACCEPT_ENCODING', 'HTTP_X_FORWARDED_FOR') as $header)
+		foreach (array('HTTP_ACCEPT', 'HTTP_USER_AGENT', 'HTTP_CONNECTION', 'SERVER_PORT', 'SERVER_NAME', 'REMOTE_ADDR', 'SERVER_SOFTWARE', 'HTTP_ACCEPT_LANGUAGE', 'SCRIPT_NAME', 'REQUEST_METHOD',' HTTP_HOST', 'REMOTE_HOST', 'CONTENT_TYPE', 'SERVER_PROTOCOL', 'QUERY_STRING', 'HTTP_ACCEPT_ENCODING', 'HTTP_X_FORWARDED_FOR') as $header)
 		{
 			$val = (isset($_SERVER[$header])) ? $_SERVER[$header] : '';
 			$output .= "<tr><td style='vertical-align: top;width:50%;padding:5px;color:#900;background-color:#ddd;'>".$header."&nbsp;&nbsp;</td><td style='width:50%;padding:5px;color:#000;background-color:#ddd;'>".$val."</td></tr>\n";
@@ -446,7 +446,7 @@
 
 		$output .= "\n\n<table style='width:100%'>\n";
 
-		foreach($this->CI->config->config as $config=>$val)
+		foreach ($this->CI->config->config as $config=>$val)
 		{
 			if (is_array($val))
 			{
diff --git a/system/libraries/Security.php b/system/libraries/Security.php
index a73b8e1..58db4e7 100644
--- a/system/libraries/Security.php
+++ b/system/libraries/Security.php
@@ -25,14 +25,15 @@
  * @link		http://codeigniter.com/user_guide/libraries/sessions.html
  */
 class CI_Security {
-	var $xss_hash			= '';
-	var $csrf_hash			= '';
-	var $csrf_expire		= 7200;  // Two hours (in seconds)
-	var $csrf_token_name	= 'ci_csrf_token';
-	var $csrf_cookie_name	= 'ci_csrf_token';
+
+	public $xss_hash			= '';
+	public $csrf_hash			= '';
+	public $csrf_expire			= 7200;  // Two hours (in seconds)
+	public $csrf_token_name		= 'ci_csrf_token';
+	public $csrf_cookie_name	= 'ci_csrf_token';
 
 	/* never allowed, string replacement */
-	var $never_allowed_str = array(
+	public $never_allowed_str = array(
 									'document.cookie'	=> '[removed]',
 									'document.write'	=> '[removed]',
 									'.parentNode'		=> '[removed]',
@@ -44,7 +45,7 @@
 									'<![CDATA['			=> '&lt;![CDATA['
 									);
 	/* never allowed, regex replacement */
-	var $never_allowed_regex = array(
+	public $never_allowed_regex = array(
 										"javascript\s*:"			=> '[removed]',
 										"expression\s*(\(|&\#40;)"	=> '[removed]', // CSS and IE
 										"vbscript\s*:"				=> '[removed]', // IE, surprise!
@@ -53,6 +54,10 @@
 
 	public function __construct()
 	{
+		$this->csrf_token_name = (config_item('csrf_token_name')) ? config_item('csrf_token_name') : 'csrf_token_name';
+		$this->csrf_cookie_name = (config_item('csrf_cookie_name')) ? config_item('csrf_cookie_name') : 'csrf_cookie_name';
+		$this->csrf_expire = (config_item('csrf_expire')) ? config_item('csrf_expire') : 7200;
+
 		// Append application specific cookie prefix to token name
 		$this->csrf_cookie_name = (config_item('cookie_prefix')) ? config_item('cookie_prefix').$this->csrf_token_name : $this->csrf_token_name;
 
@@ -70,7 +75,7 @@
 	 * @access	public
 	 * @return	null
 	 */
-	function csrf_verify()
+	public function csrf_verify()
 	{
 		// If no POST data exists we will set the CSRF cookie
 		if (count($_POST) == 0)
@@ -109,7 +114,7 @@
 	 * @access	public
 	 * @return	null
 	 */
-	function csrf_set_cookie()
+	public function csrf_set_cookie()
 	{
 		$expire = time() + $this->csrf_expire;
 		$secure_cookie = (config_item('cookie_secure') === TRUE) ? 1 : 0;
@@ -124,10 +129,10 @@
 	/**
 	 * Set Cross Site Request Forgery Protection Cookie
 	 *
-	 * @access	public
+	 * @access	private
 	 * @return	null
 	 */
-	function _csrf_set_hash()
+	private function _csrf_set_hash()
 	{
 		if ($this->csrf_hash == '')
 		{
@@ -154,7 +159,7 @@
 	 * @access	public
 	 * @return	null
 	 */
-	function csrf_show_error()
+	public function csrf_show_error()
 	{
 		show_error('The action you have requested is not allowed.');
 	}
@@ -187,7 +192,7 @@
 	 * @param	mixed	string or array
 	 * @return	string
 	 */
-	function xss_clean($str, $is_image = FALSE)
+	public function xss_clean($str, $is_image = FALSE)
 	{
 		/*
 		 * Is the string an array?
@@ -211,9 +216,9 @@
 		/*
 		 * Protect GET variables in URLs
 		 */
-		
+
 		 // 901119URL5918AMP18930PROTECT8198
-		
+
 		$str = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-]+)|i', $this->xss_hash()."\\1=\\2", $str);
 
 		/*
@@ -260,7 +265,7 @@
 		 */
 
 		$str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str);
-	
+
 		$str = preg_replace_callback("/<\w+.*?(?=>|<|$)/si", array($this, '_decode_entity'), $str);
 
 		/*
@@ -369,7 +374,7 @@
 				$str = preg_replace("#<(/*)(script|xss)(.*?)\>#si", '[removed]', $str);
 			}
 		}
-		while($original != $str);
+		while ($original != $str);
 
 		unset($original);
 
@@ -471,7 +476,7 @@
 	 * @access	public
 	 * @return	string
 	 */
-	function xss_hash()
+	public function xss_hash()
 	{
 		if ($this->xss_hash == '')
 		{
@@ -494,11 +499,11 @@
 	 * Callback function for xss_clean() to remove whitespace from
 	 * things like j a v a s c r i p t
 	 *
-	 * @access	public
+	 * @access	private
 	 * @param	type
 	 * @return	type
 	 */
-	function _compact_exploded_words($matches)
+	private function _compact_exploded_words($matches)
 	{
 		return preg_replace('/\s+/s', '', $matches[1]).$matches[2];
 	}
@@ -514,7 +519,7 @@
 	 * @param	array
 	 * @return	string
 	 */
-	function _sanitize_naughty_html($matches)
+	private function _sanitize_naughty_html($matches)
 	{
 		// encode opening brace
 		$str = '&lt;'.$matches[1].$matches[2].$matches[3];
@@ -539,7 +544,7 @@
 	 * @param	array
 	 * @return	string
 	 */
-	function _js_link_removal($match)
+	private function _js_link_removal($match)
 	{
 		$attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]));
 		return str_replace($match[1], preg_replace("#href=.*?(alert\(|alert&\#40;|javascript\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]);
@@ -557,7 +562,7 @@
 	 * @param	array
 	 * @return	string
 	 */
-	function _js_img_removal($match)
+	private function _js_img_removal($match)
 	{
 		$attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]));
 		return str_replace($match[1], preg_replace("#src=.*?(alert\(|alert&\#40;|javascript\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]);
@@ -570,11 +575,11 @@
 	 *
 	 * Used as a callback for XSS Clean
 	 *
-	 * @access	public
+	 * @access	private
 	 * @param	array
 	 * @return	string
 	 */
-	function _convert_attribute($match)
+	private function _convert_attribute($match)
 	{
 		return str_replace(array('>', '<', '\\'), array('&gt;', '&lt;', '\\\\'), $match[0]);
 	}
@@ -586,11 +591,11 @@
 	 *
 	 * Filters tag attributes for consistency and safety
 	 *
-	 * @access	public
+	 * @access	private
 	 * @param	string
 	 * @return	string
 	 */
-	function _filter_attributes($str)
+	private function _filter_attributes($str)
 	{
 		$out = '';
 
@@ -612,11 +617,11 @@
 	 *
 	 * Used as a callback for XSS Clean
 	 *
-	 * @access	public
+	 * @access	private
 	 * @param	array
 	 * @return	string
 	 */
-	function _decode_entity($match)
+	private function _decode_entity($match)
 	{
 		return $this->entity_decode($match[0], strtoupper(config_item('charset')));
 	}
@@ -642,7 +647,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function entity_decode($str, $charset='UTF-8')
+	public function entity_decode($str, $charset='UTF-8')
 	{
 		if (stristr($str, '&') === FALSE) return $str;
 
@@ -681,7 +686,7 @@
 	 * @param	string
 	 * @return	string
 	 */
-	function sanitize_filename($str, $relative_path = FALSE)
+	public function sanitize_filename($str, $relative_path = FALSE)
 	{
 		$bad = array(
 						"../",
@@ -716,7 +721,7 @@
 						"%3b",		// ;
 						"%3d"		// =
 					);
-		
+
 		if ( ! $relative_path)
 		{
 			$bad[] = './';
diff --git a/system/libraries/Session.php b/system/libraries/Session.php
index 0b94340..1822940 100644
--- a/system/libraries/Session.php
+++ b/system/libraries/Session.php
@@ -37,6 +37,7 @@
 	var $cookie_prefix				= '';
 	var $cookie_path				= '';
 	var $cookie_domain				= '';
+	var $cookie_secure				= FALSE;
 	var $sess_time_to_update		= 300;
 	var $encryption_key				= '';
 	var $flashdata_key				= 'flash';
@@ -61,7 +62,7 @@
 
 		// Set all the session preferences, which can either be set
 		// manually via the $params array above or via the config file
-		foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_expire_on_close', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key)
+		foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_expire_on_close', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'cookie_secure', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key)
 		{
 			$this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
 		}
@@ -658,8 +659,6 @@
 		}
 
 		$expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
-		
-		$secure_cookie = (config_item('cookie_secure') === TRUE) ? 1 : 0;
 
 		// Set the cookie
 		setcookie(
@@ -668,7 +667,7 @@
 					$expire,
 					$this->cookie_path,
 					$this->cookie_domain,
-					$secure_cookie
+					$this->cookie_secure
 				);
 	}
 
diff --git a/system/libraries/Sha1.php b/system/libraries/Sha1.php
index ad747a0..1a65757 100644
--- a/system/libraries/Sha1.php
+++ b/system/libraries/Sha1.php
@@ -42,7 +42,7 @@
  * @author		ExpressionEngine Dev Team
  * @link		http://codeigniter.com/user_guide/general/encryption.html
  */
-class CI_SHA {
+class CI_SHA1 {
 
 	public function __construct()
 	{
@@ -88,7 +88,7 @@
 			$oldd = $d;
 			$olde = $e;
 
-			for($j = 0; $j < 80; $j++)
+			for ($j = 0; $j < 80; $j++)
 			{
 				if ($j < 16)
 				{
diff --git a/system/libraries/Table.php b/system/libraries/Table.php
index cb2535e..def6967 100644
--- a/system/libraries/Table.php
+++ b/system/libraries/Table.php
@@ -108,7 +108,7 @@
 		}
 
 		$new = array();
-		while(count($array) > 0)
+		while (count($array) > 0)
 		{
 			$temp = array_splice($array, 0, $col_limit);
 
@@ -280,7 +280,7 @@
 			$out .= $this->template['heading_row_start'];
 			$out .= $this->newline;
 
-			foreach($this->heading as $heading)
+			foreach ($this->heading as $heading)
 			{
 				$temp = $this->template['heading_cell_start'];
 
@@ -310,7 +310,7 @@
 			$out .= $this->newline;
 
 			$i = 1;
-			foreach($this->rows as $row)
+			foreach ($this->rows as $row)
 			{
 				if ( ! is_array($row))
 				{
@@ -323,7 +323,7 @@
 				$out .= $this->template['row_'.$name.'start'];
 				$out .= $this->newline;
 
-				foreach($row as $cell)
+				foreach ($row as $cell)
 				{
 					$temp = $this->template['cell_'.$name.'start'];
 
@@ -346,7 +346,7 @@
 					{
 						if ($function !== FALSE && is_callable($function))
 						{
-							$out .= $function($cell);
+							$out .= call_user_func($function, $cell);
 						}
 						else
 						{
diff --git a/system/libraries/Trackback.php b/system/libraries/Trackback.php
index e29b35c..b0a7678 100644
--- a/system/libraries/Trackback.php
+++ b/system/libraries/Trackback.php
@@ -94,7 +94,7 @@
 				{
 					$$item = $this->convert_ascii($$item);
 				}
-				elseif($item == 'blog_name')
+				elseif ($item == 'blog_name')
 				{
 					$$item = $this->convert_ascii($$item);
 				}
@@ -261,7 +261,7 @@
 		// Was it successful?
 		$this->response = "";
 
-		while( ! feof($fp))
+		while ( ! feof($fp))
 		{
 			$this->response .= fgets($fp, 128);
 		}
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
index 97343a1..e15ea1b 100644
--- a/system/libraries/Upload.php
+++ b/system/libraries/Upload.php
@@ -213,7 +213,18 @@
 		if ($this->_file_name_override != '')
 		{
 			$this->file_name = $this->_prep_filename($this->_file_name_override);
-			$this->file_ext  = $this->get_extension($this->file_name);
+
+			// If no extension was provided in the file_name config item, use the uploaded one
+			if (strpos($this->_file_name_override, '.') === FALSE)
+			{
+				$this->file_name .= $this->file_ext;
+			}
+
+			// An extension was provided, lets have it!
+			else
+			{
+				$this->file_ext	 = $this->get_extension($this->_file_name_override);
+			}
 
 			if ( ! $this->is_allowed_filetype(TRUE))
 			{
diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php
index 863faba..3774fc2 100644
--- a/system/libraries/User_agent.php
+++ b/system/libraries/User_agent.php
@@ -82,7 +82,7 @@
 	 * @access	private
 	 * @return	bool
 	 */
-	function _load_agent_file()
+	private function _load_agent_file()
 	{
 		if ( ! @include(APPPATH.'config/user_agents'.EXT))
 		{
@@ -130,7 +130,7 @@
 	 * @access	private
 	 * @return	bool
 	 */
-	function _compile_data()
+	private function _compile_data()
 	{
 		$this->_set_platform();
 
@@ -151,7 +151,7 @@
 	 * @access	private
 	 * @return	mixed
 	 */
-	function _set_platform()
+	private function _set_platform()
 	{
 		if (is_array($this->platforms) AND count($this->platforms) > 0)
 		{
@@ -175,7 +175,7 @@
 	 * @access	private
 	 * @return	bool
 	 */
-	function _set_browser()
+	private function _set_browser()
 	{
 		if (is_array($this->browsers) AND count($this->browsers) > 0)
 		{
@@ -202,7 +202,7 @@
 	 * @access	private
 	 * @return	bool
 	 */
-	function _set_robot()
+	private function _set_robot()
 	{
 		if (is_array($this->robots) AND count($this->robots) > 0)
 		{
@@ -227,7 +227,7 @@
 	 * @access	private
 	 * @return	bool
 	 */
-	function _set_mobile()
+	private function _set_mobile()
 	{
 		if (is_array($this->mobiles) AND count($this->mobiles) > 0)
 		{
@@ -252,7 +252,7 @@
 	 * @access	private
 	 * @return	void
 	 */
-	function _set_languages()
+	private function _set_languages()
 	{
 		if ((count($this->languages) == 0) AND isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) AND $_SERVER['HTTP_ACCEPT_LANGUAGE'] != '')
 		{
@@ -275,7 +275,7 @@
 	 * @access	private
 	 * @return	void
 	 */
-	function _set_charsets()
+	private function _set_charsets()
 	{
 		if ((count($this->charsets) == 0) AND isset($_SERVER['HTTP_ACCEPT_CHARSET']) AND $_SERVER['HTTP_ACCEPT_CHARSET'] != '')
 		{
@@ -298,9 +298,21 @@
 	 * @access	public
 	 * @return	bool
 	 */
-	function is_browser()
+	public function is_browser($key = NULL)
 	{
-		return $this->is_browser;
+		if ( ! $this->is_browser)
+		{
+			return FALSE;
+		}
+
+		// No need to be specific, it's a browser
+		if ($key === NULL)
+		{
+			return TRUE;
+		}
+
+		// Check for a specific browser
+		return array_key_exists($key, $this->browsers) AND $this->browser === $this->browsers[$key];
 	}
 
 	// --------------------------------------------------------------------
@@ -311,9 +323,21 @@
 	 * @access	public
 	 * @return	bool
 	 */
-	function is_robot()
+	public function is_robot($key = NULL)
 	{
-		return $this->is_robot;
+		if ( ! $this->is_robot)
+		{
+			return FALSE;
+		}
+
+		// No need to be specific, it's a robot
+		if ($key === NULL)
+		{
+			return TRUE;
+		}
+
+		// Check for a specific robot
+		return array_key_exists($key, $this->robots) AND $this->robot === $this->robots[$key];
 	}
 
 	// --------------------------------------------------------------------
@@ -324,9 +348,21 @@
 	 * @access	public
 	 * @return	bool
 	 */
-	function is_mobile()
+	public function is_mobile($key = NULL)
 	{
-		return $this->is_mobile;
+		if ( ! $this->is_mobile)
+		{
+			return FALSE;
+		}
+
+		// No need to be specific, it's a mobile
+		if ($key === NULL)
+		{
+			return TRUE;
+		}
+
+		// Check for a specific robot
+		return array_key_exists($key, $this->mobiles) AND $this->mobile === $this->mobiles[$key];
 	}
 
 	// --------------------------------------------------------------------
@@ -337,9 +373,13 @@
 	 * @access	public
 	 * @return	bool
 	 */
-	function is_referral()
+	public function is_referral()
 	{
-		return ( ! isset($_SERVER['HTTP_REFERER']) OR $_SERVER['HTTP_REFERER'] == '') ? FALSE : TRUE;
+		if ( ! isset($_SERVER['HTTP_REFERER']) OR $_SERVER['HTTP_REFERER'] == '')
+		{
+			return FALSE;
+		}
+		return TRUE;
 	}
 
 	// --------------------------------------------------------------------
@@ -350,7 +390,7 @@
 	 * @access	public
 	 * @return	string
 	 */
-	function agent_string()
+	public function agent_string()
 	{
 		return $this->agent;
 	}
@@ -363,7 +403,7 @@
 	 * @access	public
 	 * @return	string
 	 */
-	function platform()
+	public function platform()
 	{
 		return $this->platform;
 	}
@@ -376,7 +416,7 @@
 	 * @access	public
 	 * @return	string
 	 */
-	function browser()
+	public function browser()
 	{
 		return $this->browser;
 	}
@@ -389,7 +429,7 @@
 	 * @access	public
 	 * @return	string
 	 */
-	function version()
+	public function version()
 	{
 		return $this->version;
 	}
@@ -402,7 +442,7 @@
 	 * @access	public
 	 * @return	string
 	 */
-	function robot()
+	public function robot()
 	{
 		return $this->robot;
 	}
@@ -414,7 +454,7 @@
 	 * @access	public
 	 * @return	string
 	 */
-	function mobile()
+	public function mobile()
 	{
 		return $this->mobile;
 	}
@@ -427,7 +467,7 @@
 	 * @access	public
 	 * @return	bool
 	 */
-	function referrer()
+	public function referrer()
 	{
 		return ( ! isset($_SERVER['HTTP_REFERER']) OR $_SERVER['HTTP_REFERER'] == '') ? '' : trim($_SERVER['HTTP_REFERER']);
 	}
@@ -440,7 +480,7 @@
 	 * @access	public
 	 * @return	array
 	 */
-	function languages()
+	public function languages()
 	{
 		if (count($this->languages) == 0)
 		{
@@ -458,7 +498,7 @@
 	 * @access	public
 	 * @return	array
 	 */
-	function charsets()
+	public function charsets()
 	{
 		if (count($this->charsets) == 0)
 		{
@@ -476,9 +516,9 @@
 	 * @access	public
 	 * @return	bool
 	 */
-	function accept_lang($lang = 'en')
+	public function accept_lang($lang = 'en')
 	{
-		return (in_array(strtolower($lang), $this->languages(), TRUE)) ? TRUE : FALSE;
+		return (in_array(strtolower($lang), $this->languages(), TRUE));
 	}
 
 	// --------------------------------------------------------------------
@@ -489,12 +529,11 @@
 	 * @access	public
 	 * @return	bool
 	 */
-	function accept_charset($charset = 'utf-8')
+	public function accept_charset($charset = 'utf-8')
 	{
-		return (in_array(strtolower($charset), $this->charsets(), TRUE)) ? TRUE : FALSE;
+		return (in_array(strtolower($charset), $this->charsets(), TRUE));
 	}
 
-
 }
 
 
diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php
index 9cf307c..a24bca9 100644
--- a/system/libraries/Xmlrpc.php
+++ b/system/libraries/Xmlrpc.php
@@ -207,7 +207,7 @@
 
 		$this->data = array();
 
-		foreach($incoming as $key => $value)
+		foreach ($incoming as $key => $value)
 		{
 			$this->data[$key] = $this->values_parsing($value);
 		}
@@ -232,7 +232,7 @@
 	{
 		if (is_array($value) && array_key_exists(0, $value))
 		{
-			if ( ! isset($value['1']) OR (! isset($this->xmlrpcTypes[$value['1']])))
+			if ( ! isset($value['1']) OR ( ! isset($this->xmlrpcTypes[$value['1']])))
 			{
 				if (is_array($value[0]))
 				{
@@ -243,7 +243,7 @@
 					$temp = new XML_RPC_Values($value['0'], 'string');
 				}
 			}
-			elseif(is_array($value['0']) && ($value['1'] == 'struct' OR $value['1'] == 'array'))
+			elseif (is_array($value['0']) && ($value['1'] == 'struct' OR $value['1'] == 'array'))
 			{
 				while (list($k) = each($value['0']))
 				{
@@ -281,7 +281,7 @@
 			$this->error = $this->result->errstr;
 			return FALSE;
 		}
-		elseif( ! is_object($this->result->val))
+		elseif ( ! is_object($this->result->val))
 		{
 			$this->error = $this->result->errstr;
 			return FALSE;
@@ -358,7 +358,7 @@
 	var $errno			= '';
 	var $errstring		= '';
 	var $timeout		= 5;
-	var $no_multicall	= false;
+	var $no_multicall	= FALSE;
 
 	public function __construct($path, $server, $port=80)
 	{
@@ -392,7 +392,7 @@
 			return $r;
 		}
 
-		if(empty($msg->payload))
+		if (empty($msg->payload))
 		{
 			// $msg = XML_RPC_Messages
 			$msg->createPayload();
@@ -553,11 +553,11 @@
 	{
 		$kind = $xmlrpc_val->kindOf();
 
-		if($kind == 'scalar')
+		if ($kind == 'scalar')
 		{
 			return $xmlrpc_val->scalarval();
 		}
-		elseif($kind == 'array')
+		elseif ($kind == 'array')
 		{
 			reset($xmlrpc_val->me);
 			list($a,$b) = each($xmlrpc_val->me);
@@ -565,18 +565,18 @@
 
 			$arr = array();
 
-			for($i = 0; $i < $size; $i++)
+			for ($i = 0; $i < $size; $i++)
 			{
 				$arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
 			}
 			return $arr;
 		}
-		elseif($kind == 'struct')
+		elseif ($kind == 'struct')
 		{
 			reset($xmlrpc_val->me['struct']);
 			$arr = array();
 
-			while(list($key,$value) = each($xmlrpc_val->me['struct']))
+			while (list($key,$value) = each($xmlrpc_val->me['struct']))
 			{
 				$arr[$key] = $this->xmlrpc_decoder($value);
 			}
@@ -595,10 +595,8 @@
 		$t = 0;
 		if (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))
 		{
-			if ($utc == 1)
-				$t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
-			else
-				$t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
+			$fnc = ($utc == 1) ? 'gmmktime' : 'mktime';
+			$t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
 		}
 		return $t;
 	}
@@ -628,7 +626,7 @@
 		$this->method_name = $method;
 		if (is_array($pars) && count($pars) > 0)
 		{
-			for($i=0; $i<count($pars); $i++)
+			for ($i=0; $i<count($pars); $i++)
 			{
 				// $pars[$i] = XML_RPC_Values
 				$this->params[] = $pars[$i];
@@ -646,7 +644,7 @@
 		$this->payload .= '<methodName>' . $this->method_name . "</methodName>\r\n";
 		$this->payload .= "<params>\r\n";
 
-		for($i=0; $i<count($this->params); $i++)
+		for ($i=0; $i<count($this->params); $i++)
 		{
 			// $p = XML_RPC_Values
 			$p = $this->params[$i];
@@ -664,7 +662,7 @@
 	{
 		$data = '';
 
-		while($datum = fread($fp, 4096))
+		while ($datum = fread($fp, 4096))
 		{
 			$data .= $datum;
 		}
@@ -684,7 +682,7 @@
 		//  Check for data
 		//-------------------------------------
 
-		if($data == "")
+		if ($data == "")
 		{
 			error_log($this->xmlrpcstr['no_data']);
 			$r = new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
@@ -896,7 +894,7 @@
 				$this->xh[$the_parser]['isf'] = 1;
 			break;
 			case 'PARAM':
-				$this->xh[$the_parser]['value'] = null;
+				$this->xh[$the_parser]['value'] = NULL;
 			break;
 			case 'VALUE':
 				$this->xh[$the_parser]['vt'] = 'value';
@@ -925,7 +923,7 @@
 				$this->xh[$the_parser]['valuestack'][0]['name'] = '';
 
 				// Set NULL value to check to see if value passed for this param/member
-				$this->xh[$the_parser]['value'] = null;
+				$this->xh[$the_parser]['value'] = NULL;
 			break;
 			case 'DATA':
 			case 'METHODCALL':
@@ -1108,7 +1106,7 @@
 				$this->xh[$the_parser]['lv'] = 2; // Found a value
 			}
 
-			if( ! @isset($this->xh[$the_parser]['ac']))
+			if ( ! @isset($this->xh[$the_parser]['ac']))
 			{
 				$this->xh[$the_parser]['ac'] = '';
 			}
@@ -1174,11 +1172,11 @@
 	{
 		$kind = $param->kindOf();
 
-		if($kind == 'scalar')
+		if ($kind == 'scalar')
 		{
 			return $param->scalarval();
 		}
-		elseif($kind == 'array')
+		elseif ($kind == 'array')
 		{
 			reset($param->me);
 			list($a,$b) = each($param->me);
@@ -1192,13 +1190,13 @@
 
 			return $arr;
 		}
-		elseif($kind == 'struct')
+		elseif ($kind == 'struct')
 		{
 			reset($param->me['struct']);
 
 			$arr = array();
 
-			while(list($key,$value) = each($param->me['struct']))
+			while (list($key,$value) = each($param->me['struct']))
 			{
 				$arr[$key] = $this->decode_message($value);
 			}
@@ -1343,7 +1341,7 @@
 				// struct
 				$rs .= "<struct>\n";
 				reset($val);
-				while(list($key2, $val2) = each($val))
+				while (list($key2, $val2) = each($val))
 				{
 					$rs .= "<member>\n<name>{$key2}</name>\n";
 					$rs .= $this->serializeval($val2);
diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php
index 6bedfe3..9cd3321 100644
--- a/system/libraries/Xmlrpcs.php
+++ b/system/libraries/Xmlrpcs.php
@@ -59,10 +59,15 @@
 		log_message('debug', "XML-RPC Server Class Initialized");
 	}
 
-	//-------------------------------------
-	//  Initialize Prefs and Serve
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Initialize Prefs and Serve
+	 *
+	 * @access	public
+	 * @param	mixed
+	 * @return	void
+	 */
 	function initialize($config=array())
 	{
 		if (isset($config['functions']) && is_array($config['functions']))
@@ -86,11 +91,15 @@
 		}
 	}
 
-	//-------------------------------------
-	//  Setting of System Methods
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
-	function set_system_methods ()
+	/**
+	 * Setting of System Methods
+	 *
+	 * @access	public
+	 * @return	void
+	 */
+	function set_system_methods()
 	{
 		$this->methods = array(
 					'system.listMethods'	 => array(
@@ -112,11 +121,14 @@
 					);
 	}
 
+	// --------------------------------------------------------------------
 
-	//-------------------------------------
-	//  Main Server Function
-	//-------------------------------------
-
+	/**
+	 * Main Server Function
+	 *
+	 * @access	public
+	 * @return	void
+	 */
 	function serve()
 	{
 		$r = $this->parseRequest();
@@ -129,11 +141,19 @@
 		exit($payload);
 	}
 
-	//-------------------------------------
-	//  Add Method to Class
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
-	function add_to_map($methodname,$function,$sig,$doc)
+	/**
+	 * Add Method to Class
+	 *
+	 * @access	public
+	 * @param	string	method name
+	 * @param	string	function
+	 * @param	string	signature
+	 * @param	string	docstring
+	 * @return	void
+	 */
+	function add_to_map($methodname, $function, $sig, $doc)
 	{
 		$this->methods[$methodname] = array(
 			'function'  => $function,
@@ -142,11 +162,15 @@
 		);
 	}
 
+	// --------------------------------------------------------------------
 
-	//-------------------------------------
-	//  Parse Server Request
-	//-------------------------------------
-
+	/**
+	 * Parse Server Request
+	 *
+	 * @access	public
+	 * @param	string	data
+	 * @return	object	xmlrpc response
+	 */
 	function parseRequest($data='')
 	{
 		global $HTTP_RAW_POST_DATA;
@@ -196,7 +220,7 @@
 				xml_get_current_line_number($parser)));
 			xml_parser_free($parser);
 		}
-		elseif($parser_object->xh[$parser]['isf'])
+		elseif ($parser_object->xh[$parser]['isf'])
 		{
 			return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
 		}
@@ -207,7 +231,7 @@
 			$m = new XML_RPC_Message($parser_object->xh[$parser]['method']);
 			$plist='';
 
-			for($i=0; $i < count($parser_object->xh[$parser]['params']); $i++)
+			for ($i=0; $i < count($parser_object->xh[$parser]['params']); $i++)
 			{
 				if ($this->debug === TRUE)
 				{
@@ -239,10 +263,15 @@
 		return $r;
 	}
 
-	//-------------------------------------
-	//  Executes the Method
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Executes the Method
+	 *
+	 * @access	protected
+	 * @param	object
+	 * @return	mixed
+	 */
 	function _execute($m)
 	{
 		$methName = $m->method_name;
@@ -297,13 +326,13 @@
 		if (isset($this->methods[$methName]['signature']))
 		{
 			$sig = $this->methods[$methName]['signature'];
-			for($i=0; $i<count($sig); $i++)
+			for ($i=0; $i<count($sig); $i++)
 			{
 				$current_sig = $sig[$i];
 
 				if (count($current_sig) == count($m->params)+1)
 				{
-					for($n=0; $n < count($m->params); $n++)
+					for ($n=0; $n < count($m->params); $n++)
 					{
 						$p = $m->params[$n];
 						$pt = ($p->kindOf() == 'scalar') ? $p->scalarval() : $p->kindOf();
@@ -352,23 +381,27 @@
 			return call_user_func($this->methods[$methName]['function'], $m);
 		}
 	}
+	
+	// --------------------------------------------------------------------
 
-
-	//-------------------------------------
-	//  Server Function:  List Methods
-	//-------------------------------------
-
+	/**
+	 * Server Function:  List Methods
+	 *
+	 * @access	public
+	 * @param	mixed
+	 * @return	object
+	 */
 	function listMethods($m)
 	{
 		$v = new XML_RPC_Values();
 		$output = array();
 
-		foreach($this->methods as $key => $value)
+		foreach ($this->methods as $key => $value)
 		{
 			$output[] = new XML_RPC_Values($key, 'string');
 		}
 
-		foreach($this->system_methods as $key => $value)
+		foreach ($this->system_methods as $key => $value)
 		{
 			$output[]= new XML_RPC_Values($key, 'string');
 		}
@@ -376,11 +409,16 @@
 		$v->addArray($output);
 		return new XML_RPC_Response($v);
 	}
+	
+	// --------------------------------------------------------------------
 
-	//-------------------------------------
-	//  Server Function:  Return Signature for Method
-	//-------------------------------------
-
+	/**
+	 * Server Function:  Return Signature for Method
+	 *
+	 * @access	public
+	 * @param	mixed
+	 * @return	object
+	 */
 	function methodSignature($m)
 	{
 		$parameters = $m->output_parameters();
@@ -393,11 +431,11 @@
 				$sigs = array();
 				$signature = $this->methods[$method_name]['signature'];
 
-				for($i=0; $i < count($signature); $i++)
+				for ($i=0; $i < count($signature); $i++)
 				{
 					$cursig = array();
 					$inSig = $signature[$i];
-					for($j=0; $j<count($inSig); $j++)
+					for ($j=0; $j<count($inSig); $j++)
 					{
 						$cursig[]= new XML_RPC_Values($inSig[$j], 'string');
 					}
@@ -417,10 +455,15 @@
 		return $r;
 	}
 
-	//-------------------------------------
-	//  Server Function:  Doc String for Method
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Server Function:  Doc String for Method
+	 *
+	 * @access	public
+	 * @param	mixed
+	 * @return	object
+	 */
 	function methodHelp($m)
 	{
 		$parameters = $m->output_parameters();
@@ -437,11 +480,16 @@
 			return new XML_RPC_Response(0, $this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']);
 		}
 	}
+	
+	// --------------------------------------------------------------------
 
-	//-------------------------------------
-	//  Server Function:  Multi-call
-	//-------------------------------------
-
+	/**
+	 * Server Function:  Multi-call
+	 *
+	 * @access	public
+	 * @param	mixed
+	 * @return	object
+	 */
 	function multicall($m)
 	{
 		// Disabled
@@ -459,7 +507,7 @@
 			$m = new XML_RPC_Message($value[0]);
 			$plist='';
 
-			for($i=0; $i < count($value[1]); $i++)
+			for ($i=0; $i < count($value[1]); $i++)
 			{
 				$m->addParam(new XML_RPC_Values($value[1][$i], 'string'));
 			}
@@ -477,11 +525,15 @@
 		return new XML_RPC_Response(new XML_RPC_Values($result, 'array'));
 	}
 
+	// --------------------------------------------------------------------
 
-	//-------------------------------------
-	//  Multi-call Function:  Error Handling
-	//-------------------------------------
-
+	/**
+	 *  Multi-call Function:  Error Handling
+	 *
+	 * @access	public
+	 * @param	mixed
+	 * @return	object
+	 */
 	function multicall_error($err)
 	{
 		$str  = is_string($err) ? $this->xmlrpcstr["multicall_${err}"] : $err->faultString();
@@ -493,29 +545,45 @@
 		return new XML_RPC_Values($struct, 'struct');
 	}
 
+	// --------------------------------------------------------------------
 
-	//-------------------------------------
-	//  Multi-call Function:  Processes method
-	//-------------------------------------
-
+	/**
+	 *  Multi-call Function:  Processes method
+	 *
+	 * @access	public
+	 * @param	mixed
+	 * @return	object
+	 */
 	function do_multicall($call)
 	{
 		if ($call->kindOf() != 'struct')
+		{
 			return $this->multicall_error('notstruct');
+		}
 		elseif ( ! $methName = $call->me['struct']['methodName'])
+		{
 			return $this->multicall_error('nomethod');
+		}
 
 		list($scalar_type,$scalar_value)=each($methName->me);
 		$scalar_type = $scalar_type == $this->xmlrpcI4 ? $this->xmlrpcInt : $scalar_type;
 
 		if ($methName->kindOf() != 'scalar' OR $scalar_type != 'string')
+		{
 			return $this->multicall_error('notstring');
+		}
 		elseif ($scalar_value == 'system.multicall')
+		{
 			return $this->multicall_error('recursion');
+		}
 		elseif ( ! $params = $call->me['struct']['params'])
+		{
 			return $this->multicall_error('noparams');
+		}
 		elseif ($params->kindOf() != 'array')
+		{
 			return $this->multicall_error('notarray');
+		}
 
 		list($a,$b)=each($params->me);
 		$numParams = count($b);
diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php
index 80633c7..666327d 100644
--- a/system/libraries/Zip.php
+++ b/system/libraries/Zip.php
@@ -289,7 +289,7 @@
 
 		while (FALSE !== ($file = readdir($fp)))
 		{
-			if(substr($file, 0, 1) == '.')
+			if (substr($file, 0, 1) == '.')
 			{
 				continue;
 			}
diff --git a/user_guide/changelog.html b/user_guide/changelog.html
index b113b0c..159f1a6 100644
--- a/user_guide/changelog.html
+++ b/user_guide/changelog.html
@@ -57,10 +57,12 @@
 
 <h1>Change Log</h1>
 
-<h2>Version 2.0.1</h2>
-<p>Release Date: not yet released</p>
+<p>The <img src="images/reactor-bullet.png" width="16" height="16" alt="Reactor Marker" /> indicates items that were contributed to CodeIgniter via CodeIgniter Reactor.</p>
 
-<h3>Bug Fixes for 2.0.1</h3>
+<h2>Version 2.0.1</h2>
+<p>Release Date: n/a<br />
+Hg Tag: n/a</p>
+
 <ul>
 	<li>General changes
 		<ul>
@@ -70,11 +72,23 @@
 	</li>
 	<li>Libraries
 		<ul>
-			<li>Fixed a bug where the table class would not clear table data after calling generate().</li>
+			<li class="reactor">Added <kbd>decimal</kbd>, <kbd>less_than</kbd> and <kbd>greater_than</kbd> rules to the <a href="libraries/form_validation.html">Form validation Class</a>.</li>
+			<li class="reactor"><a href="libraries/input.html">Input Class</a> methods <kbd>post()</kbd> and <kbd>get()</kbd> will now return a full array if the first argument is not provided.</li>
+			<li class="reactor">Secure cookies can now be made with the <kbd>set_cookie()</kbd> helper and <a href="libraries/input.html">Input Class</a> method.</li>
+			<li class="reactor">Added <kbd>set_content_type()</kbd> to <a href="libraries/output.html">Output Class</a> to set the output <kbd>Content-Type</kbd> HTTP header based on a MIME Type or a config/mimes.php array key.</li>
+			<li class="reactor"><a href="libraries/output.html">Output Class</a> will now support method chaining.</li>
 		</ul>
 	</li>
 </ul>
 
+<h3>Bug fixes for 2.0.1</h3>
+<ul>
+	<li class="reactor">CLI requests can now be run from any folder, not just when CD'ed next to index.php.</li>
+	<li class="reactor">Fixed issue #41: Added audio/mp3 mime type to mp3.</li>
+	<li class="reactor">Fixed a bug (Core #329) where the file caching driver referenced the incorrect cache directory.</li>
+	<li class="reactor">Fixed a bug (Reactor #69) where the SHA1 library was named incorrectly.</li>
+</ul>
+
 <h2>Version 2.0.0</h2>
 <p>Release Date: January 28, 2011<br />
 Hg Tag: v2.0.0</p>
@@ -86,18 +100,25 @@
 			<li>Scaffolding, having been deprecated for a number of versions, has been removed.</li>
 			<li>Plugins have been removed, in favor of Helpers.  The CAPTCHA plugin has been converted to a Helper and <a href="./helpers/captcha_helper.html">documented</a>.  The JavaScript calendar plugin was removed due to the ready availability of great JavaScript calendars, particularly with jQuery.</li>
 			<li>Added new special Library type: <a href="./general/drivers.html">Drivers</a>.</li>
+			<li class="reactor">Added full query-string support.  See the config file for details.</li>
 			<li>Moved the application folder outside of the system folder.</li>
 			<li>Moved system/cache and system/logs directories to the application directory.</li>
 			<li>Added routing overrides to the main index.php file, enabling the normal routing to be overridden on a per "index" file basis.</li>
 			<li>Added the ability to set config values (or override config values) directly from data set in the main index.php file.  This allows a single application to be used with multiple front controllers, each having its own config values.</li>
 			<li>Added <kbd>$config['directory_trigger']</kbd> to the config file so that a controller sub-directory can be specified when running _GET strings instead of URI segments.</li>
 			<li>Added ability to set "Package" paths - specific paths where the Loader and Config classes should try to look first for a requested file.  This allows distribution of sub-applications with their own libraries, models, config files, etc. in a single "package" directory.  See the <a href="libraries/loader.html">Loader class</a> documentation for more details.</li>
-			<li>In-development code is now hosted at <a href="http://bitbucket.org/ellislab/codeigniter/">BitBucket</a>.</li>
+			<li>In-development code is now hosted at <a href="http://bitbucket.org/ellislab/codeigniter-reactor/">BitBucket</a>.</li>
 			<li>Removed the deprecated Validation Class.</li>
 			<li>Added CI_ Prefix to all core classes.</li>
+			<li class="reactor">Package paths can now be set in application/config/autoload.php.</li>
+			<li class="reactor"><a href="libraries/file_uploading.html">Upload library</a> file_name can now be set without an extension, the extension will be taken from the uploaded file instead of the given name.</li>
+			<li class="reactor">In <a href="database/forge.html">Database Forge</a> the name can be omitted from $this->dbforge->modify_column()'s 2nd param if you aren't changing the name.</li>
+			<li class="reactor"><kbd>$config['base_url']</kbd> is now empty by default and will guess what it should be.</li>
+			<li class="reactor">Enabled full Command Line Interface compatibility with <kbd>config['uri_protocol'] = 'CLI';</kbd>.</li>
 		</ul>
 	<li>Libraries
 		<ul>
+			<li class="reactor">Added a <a href="libraries/caching.html">Cache driver</a> with APC, memcached, and file-based support.</li>
 			<li>Added <var>$prefix</var>, <var>$suffix</var> and <var>$first_url</var> properties to <a href="./libraries/pagination.html">Pagination library</a>.</li>
 			<li>Added the ability to suppress first, previous, next, last, and page links by setting their values to FALSE in the <a href="./libraries/pagination.html">Pagination library</a>.</li>
 			<li>Added <a href="./libraries/security.html">Security library</a>, which now contains the <dfn>xss_clean</dfn> function, <dfn>filename_security</dfn> function and other security related functions.</li>
@@ -128,6 +149,8 @@
 			<li>Altered Form_Validation library to allow for method chaining on <kbd>set_rules()</kbd>, <kbd>set_message()</kbd> and <kbd>set_error_delimiters()</kbd> functions.</li>
 			<li>Altered Email Library to allow for method chaining.</li>
 			<li>Added <kbd>request_headers()</kbd>, <kbd>get_request_header()</kbd> and <kbd>is_ajax_request()</kbd> to the input class.</li>
+			<li class="reactor">Altered <a href="libraries/user_agent.html">User agent library</a> so that <kbd>is_browser()</kbd>, <kbd>is_mobile()</kbd> and <kbd>is_robot()</kbd> can optionally check for a specific browser or mobile device.</li>
+			<li class="reactor">Altered <a href="libraries/input.html">Input library</a> so that <kbd>post()</kbd> and <kbd>get()</kbd> will return all POST and GET items (respectively) if there are no parameters passed in.</li>
 		</ul>
 	</li>
 	<li>Database
@@ -189,6 +212,7 @@
 
 <h3>Bug fixes for 2.0.0</h3>
 <ul>
+	<li class="reactor">Fixed a bug where you could not change the User-Agent when sending email.</li>
 	<li>Fixed a bug where the Output class would send incorrect cached output for controllers implementing their own <dfn>_output()</dfn> method.</li>
 	<li>Fixed a bug where a failed query would not have a saved query execution time causing errors in the Profiler</li>
 	<li>Fixed a bug that was writing log entries when multiple identical helpers and plugins were loaded.</li>
@@ -770,7 +794,7 @@
 		</ul>
 	</li>
 
-	
+
 	<li>Documentation Changes
 		<ul>
 			<li>Added <a href="./doc_style/index.html">Writing Documentation</a> section for the community to use in writing their own documentation.</li>
diff --git a/user_guide/database/active_record.html b/user_guide/database/active_record.html
index 60e9202..f2f33e2 100644
--- a/user_guide/database/active_record.html
+++ b/user_guide/database/active_record.html
@@ -489,10 +489,10 @@
 
 <code>
 $data = array(<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'title' => 'My title' ,<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'name' => 'My Name' ,<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'date' => 'My date'<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br />
+&nbsp;&nbsp;&nbsp;'title' => 'My title' ,<br />
+&nbsp;&nbsp;&nbsp;'name' => 'My Name' ,<br />
+&nbsp;&nbsp;&nbsp;'date' => 'My date'<br />
+);<br />
 <br />
 $this->db->insert('mytable', $data);
 <br /><br />
@@ -521,6 +521,31 @@
 
 <p class="important"><strong>Note:</strong> All values are escaped automatically producing safer queries.</p>
 
+<h2>$this->db->insert_batch();</h2>
+<p>Generates an insert string based on the data you supply, and runs the query. You can either pass an
+<strong>array</strong> or an <strong>object</strong> to the function.  Here is an example using an array:</p>
+
+<code>
+$data = array(<br/>
+&nbsp;&nbsp;&nbsp;array(<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'title' => 'My title' ,<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'name' => 'My Name' ,<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'date' => 'My date'<br />
+&nbsp;&nbsp;&nbsp;),<br />
+&nbsp;&nbsp;&nbsp;array(<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'title' => 'Another title' ,<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'name' => 'Another Name' ,<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'date' => 'Another date'<br />
+&nbsp;&nbsp;&nbsp;)<br/>
+);<br />
+<br />
+$this->db->insert_batch('mytable', $data);
+<br /><br />
+// Produces: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date'),  ('Another title', 'Another name', 'Another date')</code>
+
+<p>The first parameter will contain the table name, the second is an associative array of values.</p>
+
+<p class="important"><strong>Note:</strong> All values are escaped automatically producing safer queries.</p>
 
 
 
@@ -736,7 +761,7 @@
 <br />
 //Generates:  SELECT `field2` FROM (`tablename`)</code></p>
 
-<p class="important"> <strong>Note:</strong> The following statements can be cached: select, from, join, where, like, groupby, having, orderby, set</p>
+<p class="important"> <strong>Note:</strong> The following statements can be cached: select, from, join, where, like, group_by, having, order_by, set</p>
 <p>&nbsp;</p>
 </div>
 <!-- END CONTENT -->
diff --git a/user_guide/database/configuration.html b/user_guide/database/configuration.html
index 8e6fe1f..d71cd34 100644
--- a/user_guide/database/configuration.html
+++ b/user_guide/database/configuration.html
@@ -61,9 +61,7 @@
 <h1>Database Configuration</h1>
 
 <p>CodeIgniter has a config file that lets you store your database connection values (username, password, database name, etc.).
-The config file is located at:</p>
-
-<p><kbd>application/config/database.php</kbd></p>
+The config file is located at <samp>application/config/database.php</samp>. You can also set database connection values for specific <a href="../libraries/config.html">environments</a> by placing <strong>database.php</strong> it the respective environment config folder.</p>
 
 <p>The config settings are stored in a multi-dimensional array with this prototype:</p>
 
@@ -136,7 +134,7 @@
 <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.</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 initialize the database.</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>
 </ul>
diff --git a/user_guide/database/forge.html b/user_guide/database/forge.html
index 8b59848..d18db58 100644
--- a/user_guide/database/forge.html
+++ b/user_guide/database/forge.html
@@ -205,7 +205,7 @@
 <p>Used to remove a column from a table. </p>
 <p><code>$this-&gt;dbforge-&gt;drop_column('table_name', 'column_to_drop');</code></p>
 <h2>$this-&gt;dbforge-&gt;modify_column()</h2>
-<p>The usage of this function is identical to add_column(), except it alters an existing column rather than adding a new one. In order to use it you must add a &quot;name&quot; key into the field defining array.</p>
+<p>The usage of this function is identical to add_column(), except it alters an existing column rather than adding a new one. In order to change the name you can add a &quot;name&quot; key into the field defining array.</p>
 <p><code>$fields = array(<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'old_name' =&gt; array(<br />
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'name' =&gt; 'new_name',<br />
diff --git a/user_guide/database/results.html b/user_guide/database/results.html
index 75cb190..e9a5cb4 100644
--- a/user_guide/database/results.html
+++ b/user_guide/database/results.html
@@ -98,6 +98,18 @@
 	}
 	</code>
 
+	<p>You can also pass a string to result() which represents a class to instantiate for each result object (note: this class must be loaded)</p>
+
+	<code>
+	$query = $this->db->query("SELECT * FROM users;");<br />
+	<br />
+	foreach ($query->result('User') as $user)<br />
+	{<br />
+	&nbsp;&nbsp;&nbsp;echo $row->name; // call attributes<br />
+	&nbsp;&nbsp;&nbsp;echo $row->reverse_name(); // or methods defined on the 'User' class<br />
+	}
+	</code>
+
 	<h2>result_array()</h2>
 
 	<p>This function returns the query result as a pure array, or an empty array when no result is produced.  Typically you'll use this in a foreach loop, like this:</p>
@@ -133,6 +145,15 @@
 
 	<code>$row = $query->row(<dfn>5</dfn>);</code>
 
+	<p>You can also add a second String parameter, which is the name of a class to instantiate the row with:</p>
+
+	<code>
+	$query = $this->db->query("SELECT * FROM users LIMIT 1;");<br />
+	<br />
+	$query->row(0, 'User')<br />
+	echo $row->name; // call attributes<br />
+	echo $row->reverse_name(); // or methods defined on the 'User' class<br />
+	</code>
 
 	<h2>row_array()</h2>
 
@@ -235,4 +256,4 @@
 </div>
 
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/user_guide/database/utilities.html b/user_guide/database/utilities.html
index d4296fe..4a8b673 100644
--- a/user_guide/database/utilities.html
+++ b/user_guide/database/utilities.html
@@ -96,19 +96,19 @@
 <code>
 $dbs = $this->dbutil->list_databases();<br />
 <br />
-foreach($dbs as $db)<br />
+foreach ($dbs as $db)<br />
 {<br />
 &nbsp;&nbsp;&nbsp; echo $db;<br />
 }</code>
 
 
-<h2><a name="exists"></a>$this->db->database_exists();</h2>
+<h2><a name="exists"></a>$this->dbutil->database_exists();</h2>
 
 <p>Sometimes it's helpful to know whether a particular database exists.
 Returns a boolean TRUE/FALSE.  Usage example:</p>
 
 <code>
-if ($this->db->database_exists('database_name'))<br />
+if ($this->dbutil->database_exists('database_name'))<br />
 {<br />
 &nbsp;&nbsp; // some code...<br />
 }
diff --git a/user_guide/general/alternative_php.html b/user_guide/general/alternative_php.html
index 652cdad..c843f2f 100644
--- a/user_guide/general/alternative_php.html
+++ b/user_guide/general/alternative_php.html
@@ -94,7 +94,7 @@
 <code>
 &lt;ul><br />
 <br />
-<var>&lt;?php foreach($todo as $item): ?></var><br />
+<var>&lt;?php foreach ($todo as $item): ?></var><br />
 <br />
 &lt;li><var>&lt;?=$item?></var>&lt;/li><br />
 <br />
diff --git a/user_guide/general/caching.html b/user_guide/general/caching.html
index 440896b..9f49b95 100644
--- a/user_guide/general/caching.html
+++ b/user_guide/general/caching.html
@@ -68,7 +68,7 @@
 <h2>How Does Caching Work?</h2>
 
 <p>Caching can be enabled on a per-page basis, and you can set the length of time that a page should remain cached before being refreshed.
-When a page is loaded for the first time, the cache file will be written to your <dfn>system/cache</dfn> folder.  On subsequent page loads the cache file will be retrieved
+When a page is loaded for the first time, the cache file will be written to your <dfn>application/cache</dfn> folder.  On subsequent page loads the cache file will be retrieved
 and sent to the requesting user's browser.  If it has expired, it will be deleted and refreshed before being sent to the browser.</p>
 
 <p>Note: The Benchmark tag is not cached so you can still view your page load speed when caching is enabled.</p>
@@ -86,7 +86,7 @@
 
 <p class="important"><strong>Warning:</strong> Because of the way CodeIgniter stores content for output, caching will only work if you are generating display for your controller with a <a href="./views.html">view</a>.</p>
 <p class="important"><strong>Note:</strong> Before the cache files can be written you must set the file permissions on your
-<dfn>system/cache</dfn> folder such that it is writable.</p>
+<dfn>application/cache</dfn> folder such that it is writable.</p>
 
 <h2>Deleting Caches</h2>
 
diff --git a/user_guide/general/views.html b/user_guide/general/views.html
index fd5bde6..746f7b8 100644
--- a/user_guide/general/views.html
+++ b/user_guide/general/views.html
@@ -233,7 +233,7 @@
 &lt;h3>My Todo List&lt;/h3>
 
 &lt;ul>
-&lt;?php foreach($todo_list as $item):?>
+&lt;?php foreach ($todo_list as $item):?>
 
 &lt;li>&lt;?php echo $item;?>&lt;/li>
 
diff --git a/user_guide/images/reactor-bullet.png b/user_guide/images/reactor-bullet.png
new file mode 100755
index 0000000..89c8129
--- /dev/null
+++ b/user_guide/images/reactor-bullet.png
Binary files differ
diff --git a/user_guide/installation/downloads.html b/user_guide/installation/downloads.html
index d580fde..ad65330 100644
--- a/user_guide/installation/downloads.html
+++ b/user_guide/installation/downloads.html
@@ -58,7 +58,9 @@
 <h1>Downloading CodeIgniter</h1>
 
 <ul>
-<li><a href="http://codeigniter.com/download.php">CodeIgniter V 1.7.2 (Current version)</a></li>
+<li><a href="http://codeigniter.com/downloads/">CodeIgniter V 2.0.0 (Current version)</a></li>
+<li><a href="http://codeigniter.com/download_files/CodeIgniter_1.7.3.zip">CodeIgniter V 1.7.3</a></li>
+<li><a href="http://codeigniter.com/download_files/CodeIgniter_1.7.2.zip">CodeIgniter V 1.7.2</a></li>
 <li><a href="http://codeigniter.com/download_files/CodeIgniter_1.7.1.zip">CodeIgniter V 1.7.1</a></li>
 <li><a href="http://codeigniter.com/download_files/CodeIgniter_1.7.0.zip">CodeIgniter V 1.7.0</a></li>
 <li><a href="http://codeigniter.com/download_files/CodeIgniter_1.6.3.zip">CodeIgniter V 1.6.3</a></li>
@@ -85,7 +87,7 @@
 <h1 id="hg">Mercurial Server</h1>
 <p><a href="http://mercurial.selenic.com">Mercurial</a> is a distributed version control system.</p>
 
-							<p>Public Hg access is available at <a href="http://bitbucket.org/ellislab/codeigniter/">BitBucket</a>.
+							<p>Public Hg access is available at <a href="http://bitbucket.org/ellislab/codeigniter-reactor/">BitBucket</a>.
 								Please note that while every effort is made to keep this code base functional, we cannot guarantee the functionality of code taken
 								from the tip.</p>
 
diff --git a/user_guide/libraries/caching.html b/user_guide/libraries/caching.html
new file mode 100644
index 0000000..3d33544
--- /dev/null
+++ b/user_guide/libraries/caching.html
@@ -0,0 +1,193 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>Caching Driver : 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' />
+
+<script type="text/javascript" src="../nav/nav.js"></script>
+<script type="text/javascript" src="../nav/prototype.lite.js"></script>
+<script type="text/javascript" src="../nav/moo.fx.js"></script>
+<script type="text/javascript" src="../nav/user_guide_menu.js"></script>
+
+<meta http-equiv='expires' content='-1' />
+<meta http-equiv= 'pragma' content='no-cache' />
+<meta name='robots' content='all' />
+<meta name='author' content='ExpressionEngine Dev Team' />
+<meta name='description' content='CodeIgniter User Guide' />
+
+</head>
+<body>
+
+<!-- START NAVIGATION -->
+<div id="nav"><div id="nav_inner"><script type="text/javascript">create_menu('../');</script></div></div>
+<div id="nav2"><a name="top"></a><a href="javascript:void(0);" onclick="myHeight.toggle();"><img src="../images/nav_toggle_darker.jpg" width="154" height="43" border="0" title="Toggle Table of Contents" alt="Toggle Table of Contents" /></a></div>
+<div id="masthead">
+<table cellpadding="0" cellspacing="0" border="0" style="width:100%">
+<tr>
+<td><h1>CodeIgniter User Guide Version 2.0.0</h1></td>
+<td id="breadcrumb_right"><a href="../toc.html">Table of Contents Page</a></td>
+</tr>
+</table>
+</div>
+<!-- END NAVIGATION -->
+
+
+<!-- START BREADCRUMB -->
+<table cellpadding="0" cellspacing="0" border="0" style="width:100%">
+<tr>
+<td id="breadcrumb">
+<a href="http://codeigniter.com/">CodeIgniter Home</a> &nbsp;&#8250;&nbsp;
+<a href="../index.html">User Guide Home</a> &nbsp;&#8250;&nbsp;
+<a href="../general/drivers.html">Drivers</a> &nbsp;&#8250;&nbsp;
+Caching Driver
+</td>
+<td id="searchbox"><form method="get" action="http://www.google.com/search"><input type="hidden" name="as_sitesearch" id="as_sitesearch" value="codeigniter.com/user_guide/" />Search User Guide&nbsp; <input type="text" class="input" style="width:200px;" name="q" id="q" size="31" maxlength="255" value="" />&nbsp;<input type="submit" class="submit" name="sa" value="Go" /></form></td>
+</tr>
+</table>
+<!-- END BREADCRUMB -->
+
+<br clear="all" />
+
+
+<!-- START CONTENT -->
+<div id="content">
+
+<h1>Caching Driver</h1>
+
+<p>CodeIgniter features wrappers around some of the most popular forms of fast and dynamic caching.  All but file-based caching require specific server requirements, and a Fatal Exception will be thrown if server requirements are not met.</p>
+
+<h2>Table of Contents</h2>
+<ul>
+	<li><a href="#example_usage" title="Example Usage">Example Usage</a></li>
+	<li><a href="#function_reference" title="Function Reference">Function Reference</a></li>
+</ul>
+
+<h3>Available Drivers</h3>
+<ul>
+	<li><a href="#apc" title="APC Cache">Alternative PHP Cache (APC) Caching</a></li>
+	<li><a href="#file" title="File Caching">File-based Caching</a></li>
+	<li><a href="#memcached" title="Memcached">Memcached Caching</a></li>
+	<li><a href="#dummy" title="Dummy Caching">Dummy Cache</a></li>
+</ul>
+
+<h2 id="example_usage">Example Usage</h2>
+
+<p>The following example will load the cache driver, specify <a href="#apc" title="APC">APC</a> as the driver to use, and fall back to file-based caching if APC is not available in the hosting environment.</p>
+
+<code>
+$this->load->driver('cache', array('adapter' => 'apc', 'backup' => 'file'));<br />
+<br />
+if ( ! $foo = $this->cache->get('foo'))<br />
+{<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo 'Saving to the cache!&lt;br />';<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$foo = 'foobarbaz!';<br />
+<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Save into the cache for 5 minutes<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this->cache->save('foo', $foo, 300);<br />
+}<br />
+<br />
+echo $foo;
+</code>
+
+<h1 id="function_reference">Function Reference</h1>
+
+<h2>is_supported(<var>driver</var>['string'])</h2>
+
+<p>This function is automatically called when accessing drivers via <samp>$this->cache->get()</samp>.  However, if the individual drivers are used, make sure to call this function to ensure the driver is supported in the hosting environment.</p>
+
+<code>
+if ($this->cache->apc->is_supported())<br />
+{<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($data = $this->cache->apc->get('my_cache'))<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// do things.<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
+}
+</code>
+
+<h2>get(<var>id</var>['string'])</h2>
+
+<p>This function will attempt to fetch an item from the cache store.  If the item does not exist, the function will return <samp>FALSE</samp>.</p>
+<code>$foo = $this->cache->get('my_cached_item');</code>
+
+<h2>save(<var>id</var>['string'], <var>data</var>['mixed'], <var>ttl</var>['int'])</h2>
+
+<p>This function will save an item to the cache store.  If saving fails, the function will return <samp>FALSE</samp>.</p>
+<p>The optional third parameter (Time To Live) defaults to 60 seconds.</p>
+<code>$this->cache->save('cache_item_id', 'data_to_cache');</code>
+
+<h2>delete(<var>id</var>['string'])</h2>
+
+<p>This function will delete a specific item from the cache store.  If item deletion fails, the function will return <samp>FALSE</samp>.</p>
+<code>$this->cache->delete('cache_item_id');</code>
+
+<h2>clean()</h2>
+
+<p>This function will 'clean' the entire cache.  If the deletion of the cache files fails, the function will return <samp>FALSE</samp>.</p>
+
+<code>$this->cache->clean();</code>
+
+<h2>cache_info()</h2>
+
+<p>This function will return information on the entire cache.</p>
+
+<code>var_dump($this->cache->cache_info());</code>
+
+<h2>get_metadata(<var>id</var>['string'])</h2>
+
+<p>This function will return detailed information on a specific item in the cache.</p>
+
+<code>var_dump($this->cache->get_metadata('my_cached_item'));</code>
+
+<h1>Drivers</h1>
+
+<h2 id="apc">Alternative PHP Cache (APC) Caching</h2>
+
+<p>All of the functions listed above can be accessed without passing a specific adapter to the driver loader as follows:</p>
+<code>$this->load->driver('cache');<br />
+	$this->cache->apc->save('foo', 'bar', 10);</code>
+<p>For more information on APC, please see <a href="http://php.net/apc">http://php.net/apc</a></p>
+
+<h2 id="file">File-based Caching</h2>
+
+<p>Unlike caching from the Output Class, the driver file-based caching allows for pieces of view files to be cached.  Use this with care, and make sure to benchmark your application, as a point can come where disk I/O will negate positive gains by caching.</p>
+
+<p>All of the functions listed above can be accessed without passing a specific adapter to the driver loader as follows:</p>
+<code>$this->load->driver('cache');<br />
+	$this->cache->file->save('foo', 'bar', 10);</code>
+
+<h2 id="memcached">Memcached Caching</h2>
+
+<p>Multiple Memcached servers can be specified in the memcached.php configuration file, located in the <samp>application/config/</samp> directory.
+
+<p>All of the functions listed above can be accessed without passing a specific adapter to the driver loader as follows:</p>
+<code>$this->load->driver('cache');<br />
+	$this->cache->memcached->save('foo', 'bar', 10);</code>
+
+<p>For more information on Memcached, please see <a href="http://php.net/memcached">http://php.net/memcached</a></p>
+
+<h2 id="dummy">Dummy Cache</h2>
+
+<p>This is a caching backend that will always 'miss.'  It stores no data, but lets you keep your caching code in place in environments that don't support your chosen cache.</p>
+
+</div>
+<!-- END CONTENT -->
+
+
+<div id="footer">
+<p>
+Previous Topic:&nbsp;&nbsp;<a href="errors.html">Error Handling</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>
+</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>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/user_guide/libraries/cart.html b/user_guide/libraries/cart.html
index bc0721b..fe87a23 100644
--- a/user_guide/libraries/cart.html
+++ b/user_guide/libraries/cart.html
@@ -178,7 +178,7 @@
 
 &lt;?php $i = 1; ?>
 
-&lt;?php foreach($this->cart->contents() as $items): ?>
+&lt;?php foreach ($this->cart->contents() as $items): ?>
 
 	&lt;?php echo form_hidden($i.'[rowid]', $items['rowid']); ?>
 
diff --git a/user_guide/libraries/config.html b/user_guide/libraries/config.html
index 6b48b25..98b6052 100644
--- a/user_guide/libraries/config.html
+++ b/user_guide/libraries/config.html
@@ -150,6 +150,23 @@
 
 <p>Where <var>item_name</var> is the $config array index you want to change, and <var>item_value</var> is its value.</p>
 
+<h2>Environments</h2>
+
+<p>You can set the environment of you application and load config items depending on the current environment. It also disables PHP from displaying errors in environments other than development. To set your environment, open <strong>index.php</strong>, located at the root and change the <var>ENVIRONMENT</var> constant. By default, there is support for a development, test and production environment.</p>
+	
+<code>
+define('<var>ENVIRONMENT</var>', '<var>development</var>');	
+</code>
+
+<p>To make a config file environment-aware, copy the file from <samp>application/config/</samp> to <samp>application/config/development/</samp>, depending on the environment the config file belongs to. You can place the following configuration files in environment folders:</p>
+	
+<ul>
+<li>Default config files</li>
+<li>Database config files</li>
+<li>Custom config files</li>
+</ul>
+
+<p><strong>Note:</strong> CodeIgniter always tries to load the config file for the current environment first. If the file does not exist, the global config file (i.e. <samp>application/config/</samp>) is loaded. This means you are not obligated to place <strong>all</strong> your config files (but rather the files that change per environment) in an environment folder.</p>
 
 <h2>Helper Functions</h2>
 
diff --git a/user_guide/libraries/file_uploading.html b/user_guide/libraries/file_uploading.html
index c5eab46..5c31628 100644
--- a/user_guide/libraries/file_uploading.html
+++ b/user_guide/libraries/file_uploading.html
@@ -125,7 +125,7 @@
 &lt;h3>Your file was successfully uploaded!&lt;/h3>
 
 &lt;ul>
-&lt;?php foreach($upload_data as $item => $value):?>
+&lt;?php foreach ($upload_data as $item => $value):?>
 &lt;li>&lt;?php echo $item;?>: &lt;?php echo $value;?>&lt;/li>
 &lt;?php endforeach; ?>
 &lt;/ul>
diff --git a/user_guide/libraries/form_validation.html b/user_guide/libraries/form_validation.html
index 935dca6..d612005 100644
--- a/user_guide/libraries/form_validation.html
+++ b/user_guide/libraries/form_validation.html
@@ -924,118 +924,146 @@
 <p>The following is a list of all the native rules that are available to use:</p>
 
 
-
 <table cellpadding="0" cellspacing="1" border="0" style="width:100%" class="tableborder">
-<tr>
-<th>Rule</th>
-<th>Parameter</th>
-<th>Description</th>
-<th>Example</th>
-</tr><tr>
+	<tr>
+		<th>Rule</th>
+		<th>Parameter</th>
+		<th>Description</th>
+		<th>Example</th>
+	</tr>
 
-<td class="td"><strong>required</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if the form element is empty.</td>
-<td class="td">&nbsp;</td>
-</tr><tr>
+	<tr>
+		<td class="td"><strong>required</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if the form element is empty.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
 
-<td class="td"><strong>matches</strong></td>
-<td class="td">Yes</td>
-<td class="td">Returns FALSE if the form element does not match the one in the parameter.</td>
-<td class="td">matches[form_item]</td>
-</tr><tr>
+	<tr>
+		<td class="td"><strong>matches</strong></td>
+		<td class="td">Yes</td>
+		<td class="td">Returns FALSE if the form element does not match the one in the parameter.</td>
+		<td class="td">matches[form_item]</td>
+	</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>
-<td class="td">min_length[6]</td>
-</tr><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>
+		<td class="td">min_length[6]</td>
+	</tr>
 
-<td class="td"><strong>max_length</strong></td>
-<td class="td">Yes</td>
-<td class="td">Returns FALSE if the form element is longer then the parameter value.</td>
-<td class="td">max_length[12]</td>
-</tr><tr>
+	<tr>
+		<td class="td"><strong>max_length</strong></td>
+		<td class="td">Yes</td>
+		<td class="td">Returns FALSE if the form element is longer then the parameter value.</td>
+		<td class="td">max_length[12]</td>
+	</tr>
 
-<td class="td"><strong>exact_length</strong></td>
-<td class="td">Yes</td>
-<td class="td">Returns FALSE if the form element is not exactly the parameter value.</td>
-<td class="td">exact_length[8]</td>
-</tr><tr>
+	<tr>
+		<td class="td"><strong>exact_length</strong></td>
+		<td class="td">Yes</td>
+		<td class="td">Returns FALSE if the form element is not exactly the parameter value.</td>
+		<td class="td">exact_length[8]</td>
+	</tr>
 
-<td class="td"><strong>alpha</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if the form element contains anything other than alphabetical characters.</td>
-<td class="td">&nbsp;</td>
-</tr><tr>
+	<tr>
+		<td class="td"><strong>greater_than</strong></td>
+		<td class="td">Yes</td>
+		<td class="td">Returns FALSE if the form element is less than the parameter value or not numeric.</td>
+		<td class="td">greater_than[8]</td>
+	</tr>
 
-<td class="td"><strong>alpha_numeric</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if the form element contains anything other than alpha-numeric characters.</td>
-<td class="td">&nbsp;</td>
-</tr><tr>
+	<tr>
+		<td class="td"><strong>less_than</strong></td>
+		<td class="td">Yes</td>
+		<td class="td">Returns FALSE if the form element is greater than the parameter value or not numeric.</td>
+		<td class="td">less_than[8]</td>
+	</tr>
 
-<td class="td"><strong>alpha_dash</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if the form element contains anything other than alpha-numeric characters, underscores or dashes.</td>
-<td class="td">&nbsp;</td>
-</tr>
+	<tr>
+		<td class="td"><strong>alpha</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if the form element contains anything other than alphabetical characters.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
 
-<tr>
-<td class="td"><strong>numeric</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if the form element contains anything other than numeric characters.</td>
-<td class="td">&nbsp;</td>
-</tr>
+	<tr>
+		<td class="td"><strong>alpha_numeric</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if the form element contains anything other than alpha-numeric characters.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
 
-<tr>
-<td class="td"><strong>integer</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if the form element contains anything other than an integer.</td>
-<td class="td">&nbsp;</td>
-</tr>
+	<tr>
+		<td class="td"><strong>alpha_dash</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if the form element contains anything other than alpha-numeric characters, underscores or dashes.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
 
-<tr>
-<td class="td"><strong>is_natural</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if the form element contains anything other than a natural number: 0, 1, 2, 3, etc.</td>
-<td class="td">&nbsp;</td>
-</tr>
+	<tr>
+		<td class="td"><strong>numeric</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if the form element contains anything other than numeric characters.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
 
-<tr>
-<td class="td"><strong>is_natural_no_zero</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if the form element contains anything other than a natural number, but not zero: 1, 2, 3, etc.</td>
-<td class="td">&nbsp;</td>
-</tr>
+	<tr>
+		<td class="td"><strong>integer</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if the form element contains anything other than an integer.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
 
-<tr>
-<td class="td"><strong>valid_email</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if the form element does not contain a valid email address.</td>
-<td class="td">&nbsp;</td>
-</tr>
+	<tr>
+		<td class="td"><strong>decimal</strong></td>
+		<td class="td">Yes</td>
+		<td class="td">Returns FALSE if the form element is not exactly the parameter value.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
 
-<tr>
-<td class="td"><strong>valid_emails</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if any value provided in a comma separated list is not a valid email.</td>
-<td class="td">&nbsp;</td>
-</tr>
+	<tr>
+		<td class="td"><strong>is_natural</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if the form element contains anything other than a natural number: 0, 1, 2, 3, etc.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
 
-<tr>
-<td class="td"><strong>valid_ip</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if the supplied IP is not valid.</td>
-<td class="td">&nbsp;</td>
-</tr>
+	<tr>
+		<td class="td"><strong>is_natural_no_zero</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if the form element contains anything other than a natural number, but not zero: 1, 2, 3, etc.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
 
-<tr>
-<td class="td"><strong>valid_base64</strong></td>
-<td class="td">No</td>
-<td class="td">Returns FALSE if the supplied string contains anything other than valid Base64 characters.</td>
-<td class="td">&nbsp;</td>
-</tr>
+	<tr>
+		<td class="td"><strong>valid_email</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if the form element does not contain a valid email address.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
+
+	<tr>
+		<td class="td"><strong>valid_emails</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if any value provided in a comma separated list is not a valid email.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
+
+	<tr>
+		<td class="td"><strong>valid_ip</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if the supplied IP is not valid.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
+
+	<tr>
+		<td class="td"><strong>valid_base64</strong></td>
+		<td class="td">No</td>
+		<td class="td">Returns FALSE if the supplied string contains anything other than valid Base64 characters.</td>
+		<td class="td">&nbsp;</td>
+	</tr>
 
 
 </table>
@@ -1058,36 +1086,36 @@
 
 
 <table cellpadding="0" cellspacing="1" border="0" style="width:100%" class="tableborder">
-<tr>
-<th>Name</th>
-<th>Parameter</th>
-<th>Description</th>
-</tr><tr>
+	<tr>
+		<th>Name</th>
+		<th>Parameter</th>
+		<th>Description</th>
+	</tr><tr>
 
-<td class="td"><strong>xss_clean</strong></td>
-<td class="td">No</td>
-<td class="td">Runs the data through the XSS filtering function, described in the <a href="input.html">Input Class</a> page.</td>
-</tr><tr>
+		<td class="td"><strong>xss_clean</strong></td>
+		<td class="td">No</td>
+		<td class="td">Runs the data through the XSS filtering function, described in the <a href="input.html">Input Class</a> page.</td>
+	</tr><tr>
 
-<td class="td"><strong>prep_for_form</strong></td>
-<td class="td">No</td>
-<td class="td">Converts special characters so that HTML data can be shown in a form field without breaking it.</td>
-</tr><tr>
+		<td class="td"><strong>prep_for_form</strong></td>
+		<td class="td">No</td>
+		<td class="td">Converts special characters so that HTML data can be shown in a form field without breaking it.</td>
+	</tr><tr>
 
-<td class="td"><strong>prep_url</strong></td>
-<td class="td">No</td>
-<td class="td">Adds "http://" to URLs if missing.</td>
-</tr><tr>
+		<td class="td"><strong>prep_url</strong></td>
+		<td class="td">No</td>
+		<td class="td">Adds "http://" to URLs if missing.</td>
+	</tr><tr>
 
-<td class="td"><strong>strip_image_tags</strong></td>
-<td class="td">No</td>
-<td class="td">Strips the HTML from image tags leaving the raw URL.</td>
-</tr><tr>
+		<td class="td"><strong>strip_image_tags</strong></td>
+		<td class="td">No</td>
+		<td class="td">Strips the HTML from image tags leaving the raw URL.</td>
+	</tr><tr>
 
-<td class="td"><strong>encode_php_tags</strong></td>
-<td class="td">No</td>
-<td class="td">Converts PHP tags to entities.</td>
-</tr>
+		<td class="td"><strong>encode_php_tags</strong></td>
+		<td class="td">No</td>
+		<td class="td">Converts PHP tags to entities.</td>
+	</tr>
 
 </table>
 
diff --git a/user_guide/libraries/input.html b/user_guide/libraries/input.html
index 552c49a..2bc9b3b 100644
--- a/user_guide/libraries/input.html
+++ b/user_guide/libraries/input.html
@@ -132,12 +132,32 @@
 
 <code>$this->input->post('some_data', TRUE);</code>
 
+<p>To return an array of all POST items call without any parameters.</p>
+<p>To return all POST items and pass them through the XSS filter leave the first parameter blank while setting the second parameter to boolean;</p>
+<p>The function returns FALSE (boolean) if there are no items in the POST.</p>
+
+<code>
+	$this->input->post(); // returns all POST items with XSS filter
+	<br />
+	$this->input->post(NULL, FALSE); // returns all POST items without XSS
+</code>
+
 <h2>$this->input->get()</h2>
 
 <p>This function is identical to the post function, only it fetches get data:</p>
 
 <code>$this->input->get('some_data', TRUE);</code>
 
+<p>To return an array of all GET items call without any parameters.</p>
+<p>To return all GET items and pass them through the XSS filter leave the first parameter blank while setting the second parameter to boolean;</p>
+<p>The function returns FALSE (boolean) if there are no items in the GET.</p>
+
+<code>
+	$this->input->get(); // returns all GET items with XSS filter
+	<br />
+	$this->input->get(NULL, FALSE); // returns all GET items without XSS filtering
+</code>
+
 <h2>$this->input->get_post()</h2>
 
 <p>This function will search through both the post and get streams for data, looking first in post, and then in get:</p>
@@ -167,13 +187,14 @@
 <p>Using this method, an associative array is passed to the first parameter:</p>
 
 <code>$cookie = array(<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'name'&nbsp;&nbsp;&nbsp;=> 'The Cookie Name',<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'value'&nbsp;&nbsp;=> 'The Value',<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'expire' => '86500',<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'domain' => '.some-domain.com',<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'path'&nbsp;&nbsp;&nbsp;=> '/',<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'prefix' => 'myprefix_',<br />
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br />
+&nbsp;&nbsp;&nbsp;&nbsp;'name'&nbsp;&nbsp;&nbsp;=> 'The Cookie Name',<br />
+&nbsp;&nbsp;&nbsp;&nbsp;'value'&nbsp;&nbsp;=> 'The Value',<br />
+&nbsp;&nbsp;&nbsp;&nbsp;'expire' => '86500',<br />
+&nbsp;&nbsp;&nbsp;&nbsp;'domain' => '.some-domain.com',<br />
+&nbsp;&nbsp;&nbsp;&nbsp;'path'&nbsp;&nbsp;&nbsp;=> '/',<br />
+&nbsp;&nbsp;&nbsp;&nbsp;'prefix' => 'myprefix_',<br />
+&nbsp;&nbsp;&nbsp;&nbsp;'secure' => TRUE<br />
+);<br />
 <br />
 $this->input->set_cookie($cookie);
 </code>
@@ -188,12 +209,13 @@
 <p>For site-wide cookies regardless of how your site is requested, add your URL to the <strong>domain</strong> starting with a period, like this:  .your-domain.com</p>
 <p>The path is usually not needed since the function sets a root path.</p>
 <p>The prefix is only needed if you need to avoid name collisions with other identically named cookies for your server.</p>
+<p>The secure boolean is only needed if you want to make it a secure cookie by setting it to TRUE.</p>
 
 <h4>Discrete Parameters</h4>
 
 <p>If you prefer, you can set the cookie by passing data using individual parameters:</p>
 
-<code>$this->input->set_cookie($name, $value, $expire, $domain, $path, $prefix);</code>
+<code>$this->input->set_cookie($name, $value, $expire, $domain, $path, $prefix, $secure);</code>
 
 <h2>$this->input->get_cookie()</h2>
 
@@ -231,7 +253,7 @@
 <h2>$this->input->user_agent()</h2>
 <p>Returns the user agent (web browser) being used by the current user. Returns FALSE if it's not available.</p>
 <code>echo $this->input->user_agent();</code>
-
+<p>See the <a href="user_agent.html">User Agent Class</a> for methods which extract information from the user agent string.</p>
 
 <h2>$this->input->request_headers()</h2>
 <p>Useful if running in a non-Apache environment where <a href="http://php.net/apache_request_headers">apache_request_headers()</a> will not be supported.  Returns an array of headers.</p>
diff --git a/user_guide/libraries/javascript.html b/user_guide/libraries/javascript.html
index 55ad189..4cd751f 100644
--- a/user_guide/libraries/javascript.html
+++ b/user_guide/libraries/javascript.html
@@ -42,7 +42,8 @@
 <td id="breadcrumb">
 <a href="http://codeigniter.com/">CodeIgniter Home</a> &nbsp;&#8250;&nbsp;
 <a href="../index.html">User Guide Home</a> &nbsp;&#8250;&nbsp;
-Input Class
+<a href="../general/drivers.html">Drivers</a> &nbsp;&#8250;&nbsp;
+JavaScript Driver
 </td>
 <td id="searchbox"><form method="get" action="http://www.google.com/search"><input type="hidden" name="as_sitesearch" id="as_sitesearch" value="codeigniter.com/user_guide/" />Search User Guide&nbsp; <input type="text" class="input" style="width:200px;" name="q" id="q" size="31" maxlength="255" value="" />&nbsp;<input type="submit" class="submit" name="sa" value="Go" /></form></td>
 </tr>
@@ -82,7 +83,7 @@
 <h3>Set the path to the librarys with config items</h3>
 <p>There are some configuration items in Javascript library. These can either be set in application/config.php, within its own config/javascript.php file, or within any controller usings the set_item() function. </p>
 <p>An image to be used as an &quot;ajax loader&quot;, or progress indicator. Without one, the simple text message of &quot;loading&quot; will appear when Ajax calls need to be made.</p>
-<p><code>$config['javascript_location'] = 'http://localhost/codeigniter/themes/js/jquery/');<br />
+<p><code>$config['javascript_location'] = 'http://localhost/codeigniter/themes/js/jquery/';<br />
 		$config['javascript_ajax_img'] = 'images/ajax-loader.gif';</code></p>
 <p>If you keep your files in the same directories they were downloaded from, then you need not set this configuration items.</p>
 
@@ -243,4 +244,4 @@
 </div>
 
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/user_guide/libraries/output.html b/user_guide/libraries/output.html
index ab8f1d6..25ec521 100644
--- a/user_guide/libraries/output.html
+++ b/user_guide/libraries/output.html
@@ -78,6 +78,21 @@
 For example, if you build a page in one of your controller functions, don't set the output until the end.</p>
 
 
+<h2>$this->output->set_content_type();</h2>
+
+<p>Permits you to set the mime-type of your page so you can serve JSON data, JPEG's, XML, etc easily.</p>
+
+<code>$this->output<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;->set_content_type('application/json')<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;->set_output(json_encode(array('foo' => 'bar')));<br/>
+<br/>
+$this->output<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;->set_content_type('jpeg') // You could also use ".jpeg" which will have the full stop removed before looking in config/mimes.php<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;->set_output(file_get_contents('files/something.jpg'));</code>
+
+<p><strong>Important:</strong> Make sure any non-mime string you pass to this method exists in config/mimes.php or it will have no effect.</p>
+
+
 <h2>$this->output->get_output();</h2>
 
 <p>Permits you to manually retrieve any output that has been sent for storage in the output class.  Usage example:</p>
diff --git a/user_guide/libraries/security.html b/user_guide/libraries/security.html
index 5cd2747..943f72a 100644
--- a/user_guide/libraries/security.html
+++ b/user_guide/libraries/security.html
@@ -104,11 +104,18 @@
 
 <p>If it is acceptable for the user input to include relative paths, e.g. <kbd>file/in/some/approved/folder.txt</kbd>, you can set the second optional parameter,
 	<samp>$relative_path</samp> to TRUE.</p>
-	
+
 <code>$filename = $this->security->sanitize_filename($this->input->post('filename'), TRUE);</code>
 
 <!-- @todo write docs for CSRF methods -->
 
+<h2>Cross-site request forgery (CSRF)</h2>
+
+<p>You can enable csrf protection by opening your <kbd>application/config/config.php</kbd> file and setting this:</p>
+<code>$config['csrf_protection'] = TRUE;</code>
+
+<p>If you use the <a href="../helpers/form_helper.html">form helper</a> the <var>form_open()</var> function will automatically insert a hidden csrf field in your forms.</p>
+
 </div>
 <!-- END CONTENT -->
 
diff --git a/user_guide/libraries/user_agent.html b/user_guide/libraries/user_agent.html
index a9ef937..8989fb2 100644
--- a/user_guide/libraries/user_agent.html
+++ b/user_guide/libraries/user_agent.html
@@ -111,9 +111,34 @@
 <h2>$this->agent->is_browser()</h2>
 <p>Returns TRUE/FALSE (boolean) if the user agent is a known web browser.</p>
 
+<code> if ($this->agent->is_browser('Safari'))<br />
+{<br />
+&nbsp;&nbsp;&nbsp;&nbsp;echo 'You are using Safari.';<br />
+}<br />
+else if ($this->agent->is_browser())<br />
+{<br />
+&nbsp;&nbsp;&nbsp;&nbsp;echo 'You are using a browser.';<br />
+}</code>
+
+<p class="important"><strong>Note:</strong>&nbsp; The string "Safari" in this example is an array key in the list of browser definitions.
+You can find this list in <dfn>application/config/user_agents.php</dfn> if you want to add new browsers or change the stings.</p>
+
 <h2>$this->agent->is_mobile()</h2>
 <p>Returns TRUE/FALSE (boolean) if the user agent is a known mobile device.</p>
 
+<code> if ($this->agent->is_mobile('iphone'))<br />
+{<br />
+&nbsp;&nbsp;&nbsp;&nbsp;$this->load->view('iphone/home');<br />
+}<br />
+else if ($this->agent->is_mobile())<br />
+{<br />
+&nbsp;&nbsp;&nbsp;&nbsp;$this->load->view('mobile/home');<br />
+}<br/>
+else<br />
+{<br />
+&nbsp;&nbsp;&nbsp;&nbsp;$this->load->view('web/home');<br />
+}</code>
+
 <h2>$this->agent->is_robot()</h2>
 <p>Returns TRUE/FALSE (boolean) if the user agent is a known robot.</p>
 
diff --git a/user_guide/toc.html b/user_guide/toc.html
index 5eb9c2a..9f51b1e 100644
--- a/user_guide/toc.html
+++ b/user_guide/toc.html
@@ -118,6 +118,13 @@
 	<li><a href="./doc_style/index.html">Writing Documentation</a></li>
 </ul>
 
+<h3>Additional Resources</h3>
+
+<ul>
+<li><a href="http://codeigniter.com/forums/">Community Forums</a></li>
+<li><a href="http://codeigniter.com/wiki/">Community Wiki</a></li>
+</ul>
+
 </td>
 <td valign="top" width="25%">
 
@@ -127,7 +134,6 @@
 <li><a href="./libraries/calendar.html">Calendar Class</a></li>
 <li><a href="./libraries/cart.html">Cart Class</a></li>
 <li><a href="./libraries/config.html">Config Class</a></li>
-<li><a href="./database/index.html">Database Class</a></li>
 <li><a href="./libraries/email.html">Email Class</a></li>
 <li><a href="./libraries/encryption.html">Encryption Class</a></li>
 <li><a href="./libraries/file_uploading.html">File Uploading Class</a></li>
@@ -157,6 +163,13 @@
 </td>
 <td valign="top" width="25%">
 
+<h3>Driver Reference</h3>
+<ul>
+<li><a href="./libraries/caching.html">Caching Class</a></li>
+<li><a href="./database/index.html">Database Class</a></li>
+<li><a href="./libraries/javascript.html">Javascript Class</a></li>
+</ul>
+
 <h3>Helper Reference</h3>
 <ul>
 <li><a href="./helpers/array_helper.html">Array Helper</a></li>
@@ -182,12 +195,7 @@
 <li><a href="./helpers/xml_helper.html">XML Helper</a></li>
 </ul>
 
-<h3>Additional Resources</h3>
 
-<ul>
-<li><a href="http://codeigniter.com/forums/">Community Forums</a></li>
-<li><a href="http://codeigniter.com/wiki/">Community Wiki</a></li>
-</ul>
 
 
 </td>
diff --git a/user_guide/userguide.css b/user_guide/userguide.css
index 57c2b05..f93ff0d 100644
--- a/user_guide/userguide.css
+++ b/user_guide/userguide.css
@@ -259,6 +259,9 @@
  margin: 10px 0 12px 0;
 }
 
+li.reactor {
+ list-style-image: url(images/reactor-bullet.png);
+}
 #content li {
  margin-bottom: 9px;
 }