Merge upstream branch
diff --git a/.travis.yml b/.travis.yml
index 29111bc..84029b9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,12 +4,20 @@
   - 5.3
   - 5.4
 
+env:
+  - DB=mysql
+  - DB=pgsql
+  - DB=sqlite
+
 before_script:
   - pyrus channel-discover pear.php-tools.net
   - pyrus install http://pear.php-tools.net/get/vfsStream-0.11.2.tgz
   - phpenv rehash
+  - sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS ci_test;' -U postgres; fi"
+  - sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database ci_test;' -U postgres; fi"
+  - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS ci_test;'; fi"
 
-script: phpunit --configuration tests/phpunit.xml 
+script: phpunit --configuration tests/travis/$DB.phpunit.xml
 
 branches:
   only:
diff --git a/application/config/database.php b/application/config/database.php
index 744de03..8c06dd2 100644
--- a/application/config/database.php
+++ b/application/config/database.php
@@ -75,23 +75,25 @@
 $active_group = 'default';
 $active_record = TRUE;
 
-$db['default']['dsn']      = '';
-$db['default']['hostname'] = 'localhost';
-$db['default']['username'] = '';
-$db['default']['password'] = '';
-$db['default']['database'] = '';
-$db['default']['dbdriver'] = 'mysql';
-$db['default']['dbprefix'] = '';
-$db['default']['pconnect'] = FALSE;
-$db['default']['db_debug'] = TRUE;
-$db['default']['cache_on'] = FALSE;
-$db['default']['cachedir'] = '';
-$db['default']['char_set'] = 'utf8';
-$db['default']['dbcollat'] = 'utf8_general_ci';
-$db['default']['swap_pre'] = '';
-$db['default']['autoinit'] = TRUE;
-$db['default']['stricton'] = FALSE;
-$db['default']['failover'] = array();
+$db['default'] = array(
+	'dsn'	=> '',
+	'hostname' => 'localhost',
+	'username' => '',
+	'password' => '',
+	'database' => '',
+	'dbdriver' => 'mysqli',
+	'dbprefix' => '',
+	'pconnect' => FALSE,
+	'db_debug' => TRUE,
+	'cache_on' => FALSE,
+	'cachedir' => '',
+	'char_set' => 'utf8',
+	'dbcollat' => 'utf8_general_ci',
+	'swap_pre' => '',
+	'autoinit' => TRUE,
+	'stricton' => FALSE,
+	'failover' => array()
+);
 
 /* End of file database.php */
 /* Location: ./application/config/database.php */
\ No newline at end of file
diff --git a/system/core/Output.php b/system/core/Output.php
index 9bf818e..01fd1d8 100755
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -224,6 +224,26 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Get Current Content Type Header
+	 *
+	 * @return	string	'text/html', if not already set
+	 */
+	public function get_content_type()
+	{
+		for ($i = 0, $c = count($this->headers); $i < $c; $i++)
+		{
+			if (preg_match('/^Content-Type:\s(.+)$/', $this->headers[$i][0], $matches))
+			{
+				return $matches[1];
+			}
+		}
+
+		return 'text/html';
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Set HTTP Status Header
 	 * moved to Common procedural functions in 1.7.2
 	 *
diff --git a/system/database/DB.php b/system/database/DB.php
index 96e4955..0d81e40 100755
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -92,16 +92,12 @@
 		if (isset($dsn['query']))
 		{
 			parse_str($dsn['query'], $extra);
+
 			foreach ($extra as $key => $val)
 			{
-				// booleans please
-				if (strtoupper($val) === 'TRUE')
+				if (is_string($val) && in_array(strtoupper($val), array('TRUE', 'FALSE', 'NULL')))
 				{
-					$val = TRUE;
-				}
-				elseif (strtoupper($val) === 'FALSE')
-				{
-					$val = FALSE;
+					$val = var_export($val);
 				}
 
 				$params[$key] = $val;
@@ -138,7 +134,12 @@
 		class CI_DB extends CI_DB_driver { }
 	}
 
-	require_once(BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php');
+	// Load the DB driver
+	$driver_file = BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php';
+
+	if ( ! file_exists($driver_file)) show_error('Invalid DB driver');
+
+	require_once($driver_file);
 
 	// Instantiate the DB adapter
 	$driver = 'CI_DB_'.$params['dbdriver'].'_driver';
diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php
index b324226..a19f9be 100644
--- a/system/database/DB_active_rec.php
+++ b/system/database/DB_active_rec.php
@@ -1219,6 +1219,23 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Insert_batch statement
+	 *
+	 * Generates a platform-specific insert string from the supplied data.
+	 *
+	 * @param	string	the table name
+	 * @param	array	the insert keys
+	 * @param	array	the insert values
+	 * @return	string
+	 */
+	protected function _insert_batch($table, $keys, $values)
+	{
+		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * The "set_insert_batch" function.  Allows key/value pairs to be set for batch inserts
 	 *
 	 * @param	mixed
@@ -1341,6 +1358,23 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Insert statement
+	 *
+	 * Generates a platform-specific insert string from the supplied data
+	 *
+	 * @param	string	the table name
+	 * @param	array	the insert keys
+	 * @param	array	the insert values
+	 * @return	string
+	 */
+	protected function _insert($table, $keys, $values)
+	{
+		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Validate Insert
 	 *
 	 * This method is used by both insert() and get_compiled_insert() to
@@ -1413,6 +1447,23 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Replace statement
+	 *
+	 * Generates a platform-specific replace string from the supplied data
+	 *
+	 * @param	string	the table name
+	 * @param	array	the insert keys
+	 * @param	array	the insert values
+	 * @return	string
+	 */
+	protected function _replace($table, $keys, $values)
+	{
+		return 'REPLACE INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Get UPDATE query string
 	 *
 	 * Compiles an update query and returns the sql
@@ -1486,6 +1537,33 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Update statement
+	 *
+	 * Generates a platform-specific update string from the supplied data
+	 *
+	 * @param	string	the table name
+	 * @param	array	the update data
+	 * @param	array	the where clause
+	 * @param	array	the orderby clause
+	 * @param	array	the limit clause
+	 * @return	string
+	 */
+	protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
+	{
+		foreach ($values as $key => $val)
+		{
+			$valstr[] = $key.' = '.$val;
+		}
+
+		return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
+			.(($where != '' && count($where) > 0) ? ' WHERE '.implode(' ', $where) : '')
+			.(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '')
+			.($limit ? ' LIMIT '.$limit : '');
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Validate Update
 	 *
 	 * This method is used by both update() and get_compiled_update() to
@@ -1684,6 +1762,24 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Truncate statement
+	 *
+	 * Generates a platform-specific truncate string from the supplied data
+	 *
+	 * If the database does not support the truncate() command,
+	 * then this method maps to 'DELETE FROM table'
+	 *
+	 * @param	string	the table name
+	 * @return	string
+	 */
+	protected function _truncate($table)
+	{
+		return 'TRUNCATE '.$table;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Get DELETE query string
 	 *
 	 * Compiles a delete query string and returns the sql
diff --git a/system/database/DB_cache.php b/system/database/DB_cache.php
index 58e6968..ff94285 100644
--- a/system/database/DB_cache.php
+++ b/system/database/DB_cache.php
@@ -177,7 +177,7 @@
 	 */
 	public function delete_all()
 	{
-		delete_files($this->db->cachedir, TRUE);
+		delete_files($this->db->cachedir, TRUE, 0, TRUE);
 	}
 
 }
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 45f17e8..8b030af 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -407,8 +407,6 @@
 		$driver		= $this->load_rdriver();
 		$RES		= new $driver($this);
 
-		$RES->num_rows	= $RES->num_rows();
-
 		// Is query caching enabled? If so, we'll serialize the
 		// result object and save it to a cache file.
 		if ($this->cache_on == TRUE && $this->_cache_init())
@@ -903,6 +901,43 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Escape the SQL Identifiers
+	 *
+	 * This function escapes column and table names
+	 *
+	 * @param	string
+	 * @return	string
+	 */
+	public function escape_identifiers($item)
+	{
+		if ($this->_escape_char == '')
+		{
+			return $item;
+		}
+
+		foreach ($this->_reserved_identifiers as $id)
+		{
+			if (strpos($item, '.'.$id) !== FALSE)
+			{
+				$item = str_replace('.', $this->_escape_char.'.', $item);
+
+				// remove duplicates if the user already included the escape
+				return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item);
+			}
+		}
+
+		if (strpos($item, '.') !== FALSE)
+		{
+			$item = str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
+		}
+
+		// remove duplicates if the user already included the escape
+		return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item.$this->_escape_char);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Generate an insert string
 	 *
 	 * @param	string	the table upon which the query will be performed
@@ -915,7 +950,7 @@
 
 		foreach ($data as $key => $val)
 		{
-			$fields[] = $this->_escape_identifiers($key);
+			$fields[] = $this->escape_identifiers($key);
 			$values[] = $this->escape($val);
 		}
 
@@ -1256,7 +1291,7 @@
 					{
 						if ( ! in_array($val, $this->_reserved_identifiers))
 						{
-							$parts[$key] = $this->_escape_identifiers($val);
+							$parts[$key] = $this->escape_identifiers($val);
 						}
 					}
 
@@ -1313,7 +1348,7 @@
 
 			if ($protect_identifiers === TRUE)
 			{
-				$item = $this->_escape_identifiers($item);
+				$item = $this->escape_identifiers($item);
 			}
 
 			return $item.$alias;
@@ -1336,7 +1371,7 @@
 
 		if ($protect_identifiers === TRUE && ! in_array($item, $this->_reserved_identifiers))
 		{
-			$item = $this->_escape_identifiers($item);
+			$item = $this->escape_identifiers($item);
 		}
 
 		return $item.$alias;
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
index 0f9c427..74d1a85 100644
--- a/system/database/drivers/cubrid/cubrid_driver.php
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -435,45 +435,6 @@
 		return array('code' => cubrid_errno($this->conn_id), 'message' => cubrid_error($this->conn_id));
 	}
 
-	/**
-	 * Escape the SQL Identifiers
-	 *
-	 * This function escapes column and table names
-	 *
-	 * @param	string
-	 * @return	string
-	 */
-	public function _escape_identifiers($item)
-	{
-		if ($this->_escape_char == '')
-		{
-			return $item;
-		}
-
-		foreach ($this->_reserved_identifiers as $id)
-		{
-			if (strpos($item, '.'.$id) !== FALSE)
-			{
-				$str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
-				// remove duplicates if the user already included the escape
-				return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-			}
-		}
-
-		if (strpos($item, '.') !== FALSE)
-		{
-			$str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
-		}
-		else
-		{
-			$str = $this->_escape_char.$item.$this->_escape_char;
-		}
-
-		// remove duplicates if the user already included the escape
-		return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-	}
-
 	// --------------------------------------------------------------------
 
 	/**
@@ -498,94 +459,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Insert statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert($table, $keys, $values)
-	{
-		return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
-	}
-
-	// --------------------------------------------------------------------
-
-
-	/**
-	 * Replace statement
-	 *
-	 * Generates a platform-specific replace string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _replace($table, $keys, $values)
-	{
-		return "REPLACE INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Insert_batch statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert_batch($table, $keys, $values)
-	{
-		return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES ".implode(', ', $values);
-	}
-
-	// --------------------------------------------------------------------
-
-
-	/**
-	 * Update statement
-	 *
-	 * Generates a platform-specific update string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the update data
-	 * @param	array	the where clause
-	 * @param	array	the orderby clause
-	 * @param	array	the limit clause
-	 * @return	string
-	 */
-	protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
-	{
-		foreach ($values as $key => $val)
-		{
-			$valstr[] = sprintf('"%s" = %s', $key, $val);
-		}
-
-		$limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
-		$orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
-		$sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
-		$sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
-		$sql .= $orderby.$limit;
-
-		return $sql;
-	}
-
-	// --------------------------------------------------------------------
-
-
-	/**
 	 * Update_Batch statement
 	 *
 	 * Generates a platform-specific batch update string from the supplied data
@@ -637,23 +510,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Truncate statement
-	 *
-	 * Generates a platform-specific truncate string from the supplied data
-	 * If the database does not support the truncate() command
-	 * This function maps to "DELETE FROM table"
-	 *
-	 * @param	string	the table name
-	 * @return	string
-	 */
-	protected function _truncate($table)
-	{
-		return "TRUNCATE ".$table;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Delete statement
 	 *
 	 * Generates a platform-specific delete string from the supplied data
diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php
index bbda484..f83dc97 100644
--- a/system/database/drivers/cubrid/cubrid_forge.php
+++ b/system/database/drivers/cubrid/cubrid_forge.php
@@ -184,9 +184,7 @@
 			// As of version 8.4.0 CUBRID does not support this SQL syntax.
 		}
 
-		$sql .= $this->db->_escape_identifiers($table)." (";
-
-		$sql .= $this->_process_fields($fields);
+		$sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields);
 
 		// If there is a PK defined
 		if (count($primary_keys) > 0)
@@ -230,7 +228,7 @@
 	 */
 	public function _drop_table($table)
 	{
-		return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table);
+		return 'DROP TABLE IF EXISTS '.$this->db->escape_identifiers($table);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/interbase/interbase_driver.php b/system/database/drivers/interbase/interbase_driver.php
index 6d33462..88638a2 100644
--- a/system/database/drivers/interbase/interbase_driver.php
+++ b/system/database/drivers/interbase/interbase_driver.php
@@ -343,38 +343,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Escape the SQL Identifiers
-	 *
-	 * This public function escapes column and table names
-	 *
-	 * @param	string
-	 * @return	string
-	 */
-	protected function _escape_identifiers($item)
-	{
-		foreach ($this->_reserved_identifiers as $id)
-		{
-			if (strpos($item, '.'.$id) !== FALSE)
-			{
-				$item = str_replace('.', $this->_escape_char.'.', $item);
-
-				// remove duplicates if the user already included the escape
-				return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item);
-			}
-		}
-
-		if (strpos($item, '.') !== FALSE)
-		{
-			$item = str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
-		}
-
-		// remove duplicates if the user already included the escape
-		return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item.$this->_escape_char);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * From Tables
 	 *
 	 * This public function implicitly groups FROM tables so there is no confusion
@@ -397,23 +365,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Insert statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert($table, $keys, $values)
-	{
-		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Update statement
 	 *
 	 * Generates a platform-specific update string from the supplied data
@@ -446,15 +397,16 @@
 	 * Truncate statement
 	 *
 	 * Generates a platform-specific truncate string from the supplied data
-	 * If the database does not support the truncate() command
-	 * This public function maps to "DELETE FROM table"
+	 *
+	 * If the database does not support the truncate() command,
+	 * then this method maps to 'DELETE FROM table'
 	 *
 	 * @param	string	the table name
 	 * @return	string
 	 */
 	protected function _truncate($table)
 	{
-		return $this->_delete($table);
+		return 'DELETE FROM '.$table;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 81af6cd..ae3b843 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -404,47 +404,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Escape the SQL Identifiers
-	 *
-	 * This function escapes column and table names
-	 *
-	 * @param	string
-	 * @return	string
-	 */
-	public function _escape_identifiers($item)
-	{
-		if ($this->_escape_char == '')
-		{
-			return $item;
-		}
-
-		foreach ($this->_reserved_identifiers as $id)
-		{
-			if (strpos($item, '.'.$id) !== FALSE)
-			{
-				$str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
-				// remove duplicates if the user already included the escape
-				return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-			}
-		}
-
-		if (strpos($item, '.') !== FALSE)
-		{
-			$str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
-		}
-		else
-		{
-			$str = $this->_escape_char.$item.$this->_escape_char;
-		}
-
-		// remove duplicates if the user already included the escape
-		return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * From Tables
 	 *
 	 * This function implicitly groups FROM tables so there is no confusion
@@ -466,70 +425,19 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Insert statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert($table, $keys, $values)
-	{
-		return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Update statement
-	 *
-	 * Generates a platform-specific update string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the update data
-	 * @param	array	the where clause
-	 * @param	array	the orderby clause
-	 * @param	array	the limit clause
-	 * @return	string
-	 */
-	protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
-	{
-		foreach ($values as $key => $val)
-		{
-			$valstr[] = $key." = ".$val;
-		}
-
-		$limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
-		$orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
-		$sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
-		$sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
-		$sql .= $orderby.$limit;
-
-		return $sql;
-	}
-
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Truncate statement
 	 *
 	 * Generates a platform-specific truncate string from the supplied data
-	 * If the database does not support the truncate() command
-	 * This function maps to "DELETE FROM table"
+	 *
+	 * If the database does not support the truncate() command,
+	 * then this method maps to 'DELETE FROM table'
 	 *
 	 * @param	string	the table name
 	 * @return	string
 	 */
 	protected function _truncate($table)
 	{
-		return "TRUNCATE ".$table;
+		return 'TRUNCATE TABLE '.$table;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php
index 2e3e314..d787b37 100644
--- a/system/database/drivers/mssql/mssql_forge.php
+++ b/system/database/drivers/mssql/mssql_forge.php
@@ -68,7 +68,7 @@
 	 */
 	public function _drop_table($table)
 	{
-		return "DROP TABLE ".$this->db->_escape_identifiers($table);
+		return 'DROP TABLE '.$this->db->escape_identifiers($table);
 	}
 
 	// --------------------------------------------------------------------
@@ -92,7 +92,7 @@
 			$sql .= 'IF NOT EXISTS ';
 		}
 
-		$sql .= $this->db->_escape_identifiers($table)." (";
+		$sql .= $this->db->escape_identifiers($table).' (';
 		$current_field_count = 0;
 
 		foreach ($fields as $field => $attributes)
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index bef4111..28020d3 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -439,43 +439,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Escape the SQL Identifiers
-	 *
-	 * This function escapes column and table names
-	 *
-	 * @param	string
-	 * @return	string
-	 */
-	public function _escape_identifiers($item)
-	{
-		if ($this->_escape_char == '')
-		{
-			return $item;
-		}
-
-		foreach ($this->_reserved_identifiers as $id)
-		{
-			if (strpos($item, '.'.$id) !== FALSE)
-			{
-				$item = str_replace('.', $this->_escape_char.'.', $item);
-
-				// remove duplicates if the user already included the escape
-				return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item);
-			}
-		}
-
-		if (strpos($item, '.') !== FALSE)
-		{
-			$item = str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
-		}
-
-		// remove duplicates if the user already included the escape
-		return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item.$this->_escape_char);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * From Tables
 	 *
 	 * This function implicitly groups FROM tables so there is no confusion
@@ -497,59 +460,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Insert statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert($table, $keys, $values)
-	{
-		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
-	}
-
-	// --------------------------------------------------------------------
-
-
-	/**
-	 * Replace statement
-	 *
-	 * Generates a platform-specific replace string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _replace($table, $keys, $values)
-	{
-		return 'REPLACE INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Insert_batch statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert_batch($table, $keys, $values)
-	{
-		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values);
-	}
-
-	// --------------------------------------------------------------------
-
-
-	/**
 	 * Update statement
 	 *
 	 * Generates a platform-specific update string from the supplied data
@@ -624,23 +534,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Truncate statement
-	 *
-	 * Generates a platform-specific truncate string from the supplied data
-	 * If the database does not support the truncate() command
-	 * This function maps to "DELETE FROM table"
-	 *
-	 * @param	string	the table name
-	 * @return	string
-	 */
-	protected function _truncate($table)
-	{
-		return 'TRUNCATE '.$table;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Delete statement
 	 *
 	 * Generates a platform-specific delete string from the supplied data
diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php
index 11172b4..9e19de1 100644
--- a/system/database/drivers/mysql/mysql_forge.php
+++ b/system/database/drivers/mysql/mysql_forge.php
@@ -42,7 +42,7 @@
 	 */
 	public function _create_database($name)
 	{
-		return 'CREATE DATABASE '.$name;
+		return 'CREATE DATABASE '.$name.' CHARACTER SET '.$this->db->char_set.' COLLATE '.$this->db->dbcollat;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index 47b0449..50e2136 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -439,43 +439,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Escape the SQL Identifiers
-	 *
-	 * This function escapes column and table names
-	 *
-	 * @param	string
-	 * @return	string
-	 */
-	public function _escape_identifiers($item)
-	{
-		if ($this->_escape_char == '')
-		{
-			return $item;
-		}
-
-		foreach ($this->_reserved_identifiers as $id)
-		{
-			if (strpos($item, '.'.$id) !== FALSE)
-			{
-				$item = str_replace('.', $this->_escape_char.'.', $item);
-
-				// remove duplicates if the user already included the escape
-				return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item);
-			}
-		}
-
-		if (strpos($item, '.') !== FALSE)
-		{
-			$item = str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
-		}
-
-		// remove duplicates if the user already included the escape
-		return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item.$this->_escape_char);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * From Tables
 	 *
 	 * This function implicitly groups FROM tables so there is no confusion
@@ -497,85 +460,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Insert statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert($table, $keys, $values)
-	{
-		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Insert_batch statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert_batch($table, $keys, $values)
-	{
-		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values);
-	}
-
-	// --------------------------------------------------------------------
-
-
-	/**
-	 * Replace statement
-	 *
-	 * Generates a platform-specific replace string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _replace($table, $keys, $values)
-	{
-		return 'REPLACE INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Update statement
-	 *
-	 * Generates a platform-specific update string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the update data
-	 * @param	array	the where clause
-	 * @param	array	the orderby clause
-	 * @param	array	the limit clause
-	 * @return	string
-	 */
-	protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
-	{
-		foreach ($values as $key => $val)
-		{
-			$valstr[] = $key.' = '.$val;
-		}
-
-		return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
-			.(($where != '' && count($where) > 0) ? ' WHERE '.implode(' ', $where) : '')
-			.(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '')
-			.( ! $limit ? '' : ' LIMIT '.$limit);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Update_Batch statement
 	 *
 	 * Generates a platform-specific batch update string from the supplied data
@@ -619,23 +503,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Truncate statement
-	 *
-	 * Generates a platform-specific truncate string from the supplied data
-	 * If the database does not support the truncate() command
-	 * This function maps to "DELETE FROM table"
-	 *
-	 * @param	string	the table name
-	 * @return	string
-	 */
-	protected function _truncate($table)
-	{
-		return 'TRUNCATE '.$table;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Delete statement
 	 *
 	 * Generates a platform-specific delete string from the supplied data
diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php
index 8cf0ae1..4b6939e 100644
--- a/system/database/drivers/mysqli/mysqli_forge.php
+++ b/system/database/drivers/mysqli/mysqli_forge.php
@@ -42,7 +42,7 @@
 	 */
 	public function _create_database($name)
 	{
-		return 'CREATE DATABASE '.$name;
+		return 'CREATE DATABASE '.$name.' CHARACTER SET '.$this->db->char_set.' COLLATE '.$this->db->dbcollat;
 	}
 
 	// --------------------------------------------------------------------
@@ -148,7 +148,7 @@
 			$sql .= 'IF NOT EXISTS ';
 		}
 
-		$sql .= $this->db->_escape_identifiers($table).' ('.$this->_process_fields($fields);
+		$sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields);
 
 		if (count($primary_keys) > 0)
 		{
@@ -187,7 +187,7 @@
 	 */
 	public function _drop_table($table)
 	{
-		return 'DROP TABLE IF EXISTS '.$this->db->_escape_identifiers($table);
+		return 'DROP TABLE IF EXISTS '.$this->db->escape_identifiers($table);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysqli/mysqli_utility.php b/system/database/drivers/mysqli/mysqli_utility.php
index 4d7002e..cb3f86b 100644
--- a/system/database/drivers/mysqli/mysqli_utility.php
+++ b/system/database/drivers/mysqli/mysqli_utility.php
@@ -56,7 +56,7 @@
 	 */
 	public function _optimize_table($table)
 	{
-		return 'OPTIMIZE TABLE '.$this->db->_escape_identifiers($table);
+		return 'OPTIMIZE TABLE '.$this->db->escape_identifiers($table);
 	}
 
 	// --------------------------------------------------------------------
@@ -71,7 +71,7 @@
 	 */
 	public function _repair_table($table)
 	{
-		return 'REPAIR TABLE '.$this->db->_escape_identifiers($table);
+		return 'REPAIR TABLE '.$this->db->escape_identifiers($table);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index 45b0198..6e225ee 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -46,7 +46,6 @@
  * permit access to oracle databases
  *
  * @author	  Kelly McArdle
- *
  */
 class CI_DB_oci8_driver extends CI_DB {
 
@@ -68,7 +67,7 @@
 	protected $_random_keyword = ' ASC'; // not currently supported
 
 	// Set "auto commit" by default
-	protected $_commit = OCI_COMMIT_ON_SUCCESS;
+	public $commit_mode = OCI_COMMIT_ON_SUCCESS;
 
 	// need to track statement id and cursor id
 	public $stmt_id;
@@ -207,12 +206,13 @@
 	 */
 	protected function _execute($sql)
 	{
-		// oracle must parse the query before it is run. All of the actions with
-		// the query are based on the statement id returned by ociparse
+		/* Oracle must parse the query before it is run. All of the actions with
+		 * the query are based on the statement id returned by oci_parse().
+		 */
 		$this->stmt_id = FALSE;
 		$this->_set_stmt_id($sql);
 		oci_set_prefetch($this->stmt_id, 1000);
-		return @oci_execute($this->stmt_id, $this->_commit);
+		return @oci_execute($this->stmt_id, $this->commit_mode);
 	}
 
 	/**
@@ -238,8 +238,7 @@
 	 */
 	public function get_cursor()
 	{
-		$this->curs_id = oci_new_cursor($this->conn_id);
-		return $this->curs_id;
+		return $this->curs_id = oci_new_cursor($this->conn_id);
 	}
 
 	// --------------------------------------------------------------------
@@ -247,19 +246,19 @@
 	/**
 	 * Stored Procedure.  Executes a stored procedure
 	 *
-	 * @param	string	package stored procedure is in
-	 * @param	string	stored procedure to execute
+	 * @param	string	package name in which the stored procedure is in
+	 * @param	string	stored procedure name to execute
 	 * @param	array	parameters
-	 * @return	object
+	 * @return	mixed
 	 *
 	 * params array keys
 	 *
 	 * KEY	  OPTIONAL	NOTES
-	 * name		no		the name of the parameter should be in :<param_name> format
-	 * value	no		the value of the parameter.  If this is an OUT or IN OUT parameter,
-	 *					this should be a reference to a variable
-	 * type		yes		the type of the parameter
-	 * length	yes		the max size of the parameter
+	 * name		no	the name of the parameter should be in :<param_name> format
+	 * value	no	the value of the parameter.  If this is an OUT or IN OUT parameter,
+	 *				this should be a reference to a variable
+	 * type		yes	the type of the parameter
+	 * length	yes	the max size of the parameter
 	 */
 	public function stored_procedure($package, $procedure, $params)
 	{
@@ -274,24 +273,24 @@
 		}
 
 		// build the query string
-		$sql = "begin $package.$procedure(";
+		$sql = 'BEGIN '.$package.'.'.$procedure.'(';
 
 		$have_cursor = FALSE;
 		foreach ($params as $param)
 		{
-			$sql .= $param['name'] . ",";
+			$sql .= $param['name'].',';
 
-			if (array_key_exists('type', $param) && ($param['type'] === OCI_B_CURSOR))
+			if (isset($param['type']) && $param['type'] === OCI_B_CURSOR)
 			{
 				$have_cursor = TRUE;
 			}
 		}
-		$sql = trim($sql, ",") . "); end;";
+		$sql = trim($sql, ',') . '); END;';
 
 		$this->stmt_id = FALSE;
 		$this->_set_stmt_id($sql);
 		$this->_bind_params($params);
-		$this->query($sql, FALSE, $have_cursor);
+		return $this->query($sql, FALSE, $have_cursor);
 	}
 
 	// --------------------------------------------------------------------
@@ -347,7 +346,7 @@
 		// even if the queries produce a successful result.
 		$this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
 
-		$this->_commit = OCI_DEFAULT;
+		$this->commit_mode = (is_php('5.3.2')) ? OCI_NO_AUTO_COMMIT : OCI_DEFAULT;
 		return TRUE;
 	}
 
@@ -371,9 +370,8 @@
 			return TRUE;
 		}
 
-		$ret = oci_commit($this->conn_id);
-		$this->_commit = OCI_COMMIT_ON_SUCCESS;
-		return $ret;
+		$this->commit_mode = OCI_COMMIT_ON_SUCCESS;
+		return oci_commit($this->conn_id);
 	}
 
 	// --------------------------------------------------------------------
@@ -385,20 +383,14 @@
 	 */
 	public function trans_rollback()
 	{
-		if ( ! $this->trans_enabled)
-		{
-			return TRUE;
-		}
-
 		// When transactions are nested we only begin/commit/rollback the outermost ones
-		if ($this->_trans_depth > 0)
+		if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
 		{
 			return TRUE;
 		}
 
-		$ret = oci_rollback($this->conn_id);
-		$this->_commit = OCI_COMMIT_ON_SUCCESS;
-		return $ret;
+		$this->commit_mode = OCI_COMMIT_ON_SUCCESS;
+		return oci_rollback($this->conn_id);
 	}
 
 	// --------------------------------------------------------------------
@@ -469,7 +461,7 @@
 	 * the specified database
 	 *
 	 * @param	string
-	 * @return	string
+	 * @return	int
 	 */
 	public function count_all($table = '')
 	{
@@ -501,11 +493,11 @@
 	 */
 	protected function _list_tables($prefix_limit = FALSE)
 	{
-		$sql = "SELECT TABLE_NAME FROM ALL_TABLES";
+		$sql = 'SELECT TABLE_NAME FROM ALL_TABLES';
 
-		if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+		if ($prefix_limit !== FALSE && $this->dbprefix != '')
 		{
-			$sql .= " WHERE TABLE_NAME LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
+			return $sql." WHERE TABLE_NAME LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
 		}
 
 		return $sql;
@@ -523,7 +515,7 @@
 	 */
 	protected function _list_columns($table = '')
 	{
-		return "SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = '$table'";
+		return 'SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = \''.$table.'\'';
 	}
 
 	// --------------------------------------------------------------------
@@ -538,7 +530,7 @@
 	 */
 	protected function _field_data($table)
 	{
-		return "SELECT * FROM ".$table." where rownum = 1";
+		return 'SELECT * FROM '.$table.' WHERE rownum = 1';
 	}
 
 	// --------------------------------------------------------------------
@@ -575,47 +567,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Escape the SQL Identifiers
-	 *
-	 * This function escapes column and table names
-	 *
-	 * @param	string
-	 * @return	string
-	 */
-	public function _escape_identifiers($item)
-	{
-		if ($this->_escape_char == '')
-		{
-			return $item;
-		}
-
-		foreach ($this->_reserved_identifiers as $id)
-		{
-			if (strpos($item, '.'.$id) !== FALSE)
-			{
-				$str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
-				// remove duplicates if the user already included the escape
-				return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-			}
-		}
-
-		if (strpos($item, '.') !== FALSE)
-		{
-			$str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
-		}
-		else
-		{
-			$str = $this->_escape_char.$item.$this->_escape_char;
-		}
-
-		// remove duplicates if the user already included the escape
-		return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * From Tables
 	 *
 	 * This function implicitly groups FROM tables so there is no confusion
@@ -626,29 +577,7 @@
 	 */
 	protected function _from_tables($tables)
 	{
-		if ( ! is_array($tables))
-		{
-			$tables = array($tables);
-		}
-
-		return implode(', ', $tables);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Insert statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert($table, $keys, $values)
-	{
-		return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+		return is_array($tables) ? implode(', ', $tables) : $tables;
 	}
 
 	// --------------------------------------------------------------------
@@ -670,46 +599,10 @@
 
 		for ($i = 0, $c = count($values); $i < $c; $i++)
 		{
-			$sql .= '	INTO ' . $table . ' (' . $keys . ') VALUES ' . $values[$i] . "\n";
+			$sql .= '	INTO '.$table.' ('.$keys.') VALUES '.$values[$i]."\n";
 		}
 
-		$sql .= 'SELECT * FROM dual';
-
-		return $sql;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Update statement
-	 *
-	 * Generates a platform-specific update string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the update data
-	 * @param	array	the where clause
-	 * @param	array	the orderby clause
-	 * @param	array	the limit clause
-	 * @return	string
-	 */
-	protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
-	{
-		foreach ($values as $key => $val)
-		{
-			$valstr[] = $key." = ".$val;
-		}
-
-		$limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
-		$orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
-		$sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
-		$sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
-		$sql .= $orderby.$limit;
-
-		return $sql;
+		return $sql.'SELECT * FROM dual';
 	}
 
 	// --------------------------------------------------------------------
@@ -718,15 +611,16 @@
 	 * Truncate statement
 	 *
 	 * Generates a platform-specific truncate string from the supplied data
-	 * If the database does not support the truncate() command
-	 * This function maps to "DELETE FROM table"
+	 *
+	 * If the database does not support the truncate() command,
+	 * then this method maps to 'DELETE FROM table'
 	 *
 	 * @param	string	the table name
 	 * @return	string
 	 */
 	protected function _truncate($table)
 	{
-		return "TRUNCATE TABLE ".$table;
+		return 'TRUNCATE TABLE '.$table;
 	}
 
 	// --------------------------------------------------------------------
@@ -744,22 +638,18 @@
 	protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
 	{
 		$conditions = '';
-
 		if (count($where) > 0 OR count($like) > 0)
 		{
-			$conditions = "\nWHERE ";
-			$conditions .= implode("\n", $this->ar_where);
+			$conditions = "\nWHERE ".implode("\n", $this->ar_where);
 
 			if (count($where) > 0 && count($like) > 0)
 			{
-				$conditions .= " AND ";
+				$conditions .= ' AND ';
 			}
 			$conditions .= implode("\n", $like);
 		}
 
-		$limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
-		return "DELETE FROM ".$table.$conditions.$limit;
+		return 'DELETE FROM '.$table.$conditions.( ! $limit ? '' : ' LIMIT '.$limit);
 	}
 
 	// --------------------------------------------------------------------
@@ -776,18 +666,9 @@
 	 */
 	protected function _limit($sql, $limit, $offset)
 	{
-		$limit = $offset + $limit;
-		$newsql = "SELECT * FROM (select inner_query.*, rownum rnum FROM ($sql) inner_query WHERE rownum < $limit)";
-
-		if ($offset != 0)
-		{
-			$newsql .= " WHERE rnum >= $offset";
-		}
-
-		// remember that we used limits
 		$this->limit_used = TRUE;
-
-		return $newsql;
+		return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit).')'
+			.($offset != 0 ? ' WHERE rnum >= '.$offset : '');
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php
index 8285a29..033e618 100644
--- a/system/database/drivers/oci8/oci8_forge.php
+++ b/system/database/drivers/oci8/oci8_forge.php
@@ -42,6 +42,7 @@
 	 */
 	public function _create_database($name)
 	{
+		// Not supported - schemas in Oracle are actual usernames
 		return FALSE;
 	}
 
@@ -55,6 +56,7 @@
 	 */
 	public function _drop_database($name)
 	{
+		// Not supported - schemas in Oracle are actual usernames
 		return FALSE;
 	}
 
@@ -68,7 +70,7 @@
 	 * @param	mixed	primary key(s)
 	 * @param	mixed	key(s)
 	 * @param	bool	should 'IF NOT EXISTS' be added to the SQL
-	 * @return	bool
+	 * @return	string
 	 */
 	public function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
 	{
@@ -79,7 +81,7 @@
 			$sql .= 'IF NOT EXISTS ';
 		}
 
-		$sql .= $this->db->_escape_identifiers($table).' (';
+		$sql .= $this->db->escape_identifiers($table).' (';
 		$current_field_count = 0;
 
 		foreach ($fields as $field => $attributes)
@@ -128,7 +130,7 @@
 					$key = array($this->db->protect_identifiers($key));
 				}
 
-				$sql .= ",\n\tUNIQUE COLUMNS (".implode(', ', $key).")";
+				$sql .= ",\n\tUNIQUE COLUMNS (".implode(', ', $key).')';
 			}
 		}
 
@@ -140,11 +142,11 @@
 	/**
 	 * Drop Table
 	 *
-	 * @return	bool
+	 * @return	string
 	 */
 	public function _drop_table($table)
 	{
-		return FALSE;
+		return 'DROP TABLE '.$this->db->protect_identifiers($table);
 	}
 
 	// --------------------------------------------------------------------
@@ -169,33 +171,15 @@
 		$sql = 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '.$this->db->protect_identifiers($column_name);
 
 		// DROP has everything it needs now.
-		if ($alter_type == 'DROP')
+		if ($alter_type === 'DROP')
 		{
 			return $sql;
 		}
 
-		$sql .= " $column_definition";
-
-		if ($default_value != '')
-		{
-			$sql .= " DEFAULT \"$default_value\"";
-		}
-
-		if ($null === NULL)
-		{
-			$sql .= ' NULL';
-		}
-		else
-		{
-			$sql .= ' NOT NULL';
-		}
-
-		if ($after_field != '')
-		{
-			return $sql.' AFTER '.$this->db->protect_identifiers($after_field);
-		}
-
-		return $sql;
+		return $sql.' '.$column_definition
+			.($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '')
+			.($null === NULL ? ' NULL' : ' NOT NULL')
+			.($after_field != '' ? ' AFTER '.$this->db->protect_identifiers($after_field) : '');
 
 	}
 
diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php
index c3f7757..aad24cf 100644
--- a/system/database/drivers/oci8/oci8_result.php
+++ b/system/database/drivers/oci8/oci8_result.php
@@ -39,6 +39,12 @@
 	public $stmt_id;
 	public $curs_id;
 	public $limit_used;
+	public $commit_mode;
+
+	/* Overwriting the parent here, so we have a way to know if it's
+	 * already called or not:
+	 */
+	public $num_rows;
 
 	public function __construct(&$driver_object)
 	{
@@ -46,28 +52,32 @@
 		$this->stmt_id = $driver_object->stmt_id;
 		$this->curs_id = $driver_object->curs_id;
 		$this->limit_used = $driver_object->limit_used;
+		$this->commit_mode =& $driver_object->commit_mode;
 		$driver_object->stmt_id = FALSE;
 	}
 
 	/**
 	 * Number of rows in the result set.
 	 *
-	 * Oracle doesn't have a graceful way to retun the number of rows
+	 * Oracle doesn't have a graceful way to return the number of rows
 	 * so we have to use what amounts to a hack.
 	 *
 	 * @return	int
 	 */
 	public function num_rows()
 	{
-		if ($this->num_rows === 0 && count($this->result_array()) > 0)
+		if ( ! is_int($this->num_rows))
 		{
-			$this->num_rows = count($this->result_array());
-			@oci_execute($this->stmt_id, OCI_DEFAULT);
-
-			if ($this->curs_id)
+			if (count($this->result_array) > 0)
 			{
-				@oci_execute($this->curs_id, OCI_DEFAULT);
+				return $this->num_rows = count($this->result_array);
 			}
+			elseif (count($this->result_object) > 0)
+			{
+				return $this->num_rows = count($this->result_object);
+			}
+
+			return $this->num_rows = count($this->result_array());
 		}
 
 		return $this->num_rows;
@@ -85,12 +95,7 @@
 		$count = @oci_num_fields($this->stmt_id);
 
 		// if we used a limit we subtract it
-		if ($this->limit_used)
-		{
-			$count = $count - 1;
-		}
-
-		return $count;
+		return ($this->limit_used) ? $count - 1 : $count;
 	}
 
 	// --------------------------------------------------------------------
@@ -126,10 +131,10 @@
 		$retval = array();
 		for ($c = 1, $fieldCount = $this->num_fields(); $c <= $fieldCount; $c++)
 		{
-			$F			= new stdClass();
-			$F->name		= oci_field_name($this->stmt_id, $c);
-			$F->type		= oci_field_type($this->stmt_id, $c);
-			$F->max_length		= oci_field_size($this->stmt_id, $c);
+			$F		= new stdClass();
+			$F->name	= oci_field_name($this->stmt_id, $c);
+			$F->type	= oci_field_type($this->stmt_id, $c);
+			$F->max_length	= oci_field_size($this->stmt_id, $c);
 
 			$retval[] = $F;
 		}
@@ -151,6 +156,17 @@
 			oci_free_statement($this->result_id);
 			$this->result_id = FALSE;
 		}
+
+		if (is_resource($this->stmt_id))
+		{
+			oci_free_statement($this->stmt_id);
+		}
+
+		if (is_resource($this->curs_id))
+		{
+			oci_cancel($this->curs_id);
+			$this->curs_id = NULL;
+		}
 	}
 
 	// --------------------------------------------------------------------
@@ -180,13 +196,13 @@
 	protected function _fetch_object()
 	{
 		$id = ($this->curs_id) ? $this->curs_id : $this->stmt_id;
-		return @oci_fetch_object($id);
+		return oci_fetch_object($id);
 	}
 
 	// --------------------------------------------------------------------
 
 	/**
-	 * Query result.  "array" version.
+	 * Query result. Array version.
 	 *
 	 * @return	array
 	 */
@@ -196,14 +212,433 @@
 		{
 			return $this->result_array;
 		}
+		elseif (count($this->result_object) > 0)
+		{
+			for ($i = 0, $c = count($this->result_object); $i < $c; $i++)
+			{
+				$this->result_array[$i] = (array) $this->result_object[$i];
+			}
+
+			return $this->result_array;
+		}
+		elseif (is_array($this->row_data))
+		{
+			if (count($this->row_data) === 0)
+			{
+				return $this->result_array;
+			}
+			else
+			{
+				$row_index = count($this->row_data);
+			}
+		}
+		else
+		{
+			$row_index = 0;
+			$this->row_data = array();
+		}
 
 		$row = NULL;
 		while ($row = $this->_fetch_assoc())
 		{
-			$this->result_array[] = $row;
+			$this->row_data[$row_index++] = $row;
 		}
 
-		return $this->result_array;
+		// Un-comment the following line, in case it becomes needed
+		// $this->_data_seek();
+		return $this->result_array = $this->row_data;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Query result. "object" version.
+	 *
+	 * @return	array
+	 */
+	public function result_object()
+	{
+		if (count($this->result_object) > 0)
+		{
+			return $this->result_object;
+		}
+		elseif (count($this->result_array) > 0)
+		{
+			for ($i = 0, $c = count($this->result_array); $i < $c; $i++)
+			{
+				$this->result_object[] = (object) $this->result_array[$i];
+			}
+
+			return $this->result_object;
+		}
+		elseif (is_array($this->row_data))
+		{
+			if (count($this->row_data) === 0)
+			{
+				return $this->result_object;
+			}
+			else
+			{
+				$row_index = count($this->row_data);
+				for ($i = 0; $i < $row_index; $i++)
+				{
+					$this->result_object[$i] = (object) $this->row_data[$i];
+				}
+			}
+		}
+		else
+		{
+			$row_index = 0;
+			$this->row_data = array();
+		}
+
+		$row = NULL;
+		while ($row = $this->_fetch_object())
+		{
+			$this->row_data[$row_index] = (array) $row;
+			$this->result_object[$row_index++] = $row;
+		}
+
+		// Un-comment the following line, in case it becomes needed
+		// $this->_data_seek();
+		return $this->result_object;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Query result. Custom object version.
+	 *
+	 * @param	string	class name used to instantiate rows to
+	 * @return	array
+	 */
+	public function custom_result_object($class_name)
+	{
+		if (isset($this->custom_result_object[$class_name]))
+		{
+			return $this->custom_result_object[$class_name];
+		}
+
+		if ( ! class_exists($class_name) OR $this->result_id === FALSE OR $this->num_rows() === 0)
+		{
+			return array();
+		}
+
+		/* Even if we didn't have result_array or result_object
+		 * set prior to custom_result_object() being called,
+		 * num_rows() has already done so.
+		 * Pass by reference, as we don't know how
+		 * large it might be and we don't want 1000 row
+		 * sets being copied.
+		 */
+		if (count($this->result_array) > 0)
+		{
+			$data = &$this->result_array;
+		}
+		elseif (count($this->result_object) > 0)
+		{
+			$data = &$this->result_object;
+		}
+
+		$this->custom_result_object[$class_name] = array();
+		for ($i = 0, $c = count($data); $i < $c; $i++)
+		{
+			$this->custom_result_object[$class_name][$i] = new $class_name();
+			foreach ($data[$i] as $key => $value)
+			{
+				$this->custom_result_object[$class_name][$i]->$key = $value;
+			}
+		}
+
+		return $this->custom_result_object[$class_name];
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Single row result.
+	 *
+	 * Acts as a wrapper for row_object(), row_array()
+	 * and custom_row_object(). Also used by first_row(), next_row()
+	 * and previous_row().
+	 *
+	 * @param	int	row index
+	 * @param	string	('object', 'array' or a custom class name)
+	 * @return	mixed	whatever was passed to the second parameter
+	 */
+	public function row($n = 0, $type = 'object')
+	{
+		if ($type === 'object')
+		{
+			return $this->row_object($n);
+		}
+		elseif ($type === 'array')
+		{
+			return $this->row_array($n);
+		}
+
+		return $this->custom_row_object($n, $type);
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Single row result. Array version.
+	 *
+	 * @param	int	row index
+	 * @return	array
+	 */
+	public function row_array($n = 0)
+	{
+		// Make sure $n is not a string
+		if ( ! is_int($n))
+		{
+			$n = (int) $n;
+		}
+
+		/* If row_data is initialized, it means that we've already tried
+		 * (at least) to fetch some data, so ... check if we already have
+		 * this row.
+		*/
+		if (is_array($this->row_data))
+		{
+			/* If we already have row_data[$n] - return it.
+			 *
+			 * If we enter the elseif, there's a number of reasons to
+			 * return an empty array:
+			 *
+			 *	- count($this->row_data) === 0 means there are no results
+			 *	- num_rows being set, result_array and/or result_object
+			 *	  having count() > 0 means that we've already fetched all
+			 *	  data and $n is greater than our highest row index available
+			 *	- $n < $this->current_row means that if such row existed,
+			 *	  we would've already returned it, therefore $n is an
+			 *	  invalid index
+			 */
+			if (isset($this->row_data[$n])) // We already have this row
+			{
+				$this->current_row = $n;
+				return $this->row_data[$n];
+			}
+			elseif (count($this->row_data) === 0 OR is_int($this->num_rows)
+				OR count($this->result_array) > 0 OR count($this->result_object) > 0
+				OR $n < $this->current_row)
+			{
+				// No such row exists
+				return array();
+			}
+
+			// Get the next row index that would actually need to be fetched
+			$current_row = ($this->current_row < count($this->row_data)) ? count($this->row_data) : $this->current_row + 1;
+		}
+		else
+		{
+			$current_row = $this->current_row = 0;
+			$this->row_data = array();
+		}
+
+		/* Fetch more data, if available
+		 *
+		 * NOTE: Operator precedence is important here, if you change
+		 *	 'AND' with '&&' - it WILL BREAK the results, as
+		 *	 $row will be assigned the scalar value of both
+		 *	 expressions!
+		 */
+		while ($row = $this->_fetch_assoc() AND $current_row <= $n)
+		{
+			$this->row_data[$current_row++] = $row;
+		}
+
+		// This would mean that there's no (more) data to fetch
+		if ( ! is_array($this->row_data) OR ! isset($this->row_data[$n]))
+		{
+			// Cache what we already have
+			if (is_array($this->row_data))
+			{
+				$this->num_rows = count($this->row_data);
+				/* Usually, row_data could have less elements than result_array,
+				 * but at this point - they should be exactly the same.
+				 */
+				$this->result_array = $this->row_data;
+			}
+			else
+			{
+				$this->num_rows = 0;
+			}
+
+			return array();
+		}
+
+		$this->current_row = $n;
+		return $this->row_data[$n];
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Single row result. Object version.
+	 *
+	 * @param	int	row index
+	 * @return	mixed	object if row found; empty array if not
+	 */
+	public function row_object($n = 0)
+	{
+		// Make sure $n is not a string
+		if ( ! is_int($n))
+		{
+			$n = (int) $n;
+		}
+		/* Logic here is exactly the same as in row_array,
+		 * except we have to cast row_data[$n] to an object.
+		 *
+		 * If we already have result_object though - we can
+		 * directly return from it.
+		 */
+		if (isset($this->result_object[$n]))
+		{
+			$this->current_row = $n;
+			// Set this, if not already done.
+			if ( ! is_int($this->num_rows))
+			{
+				$this->num_rows = count($this->result_object);
+			}
+
+			return $this->result_object[$n];
+		}
+
+		$row = $this->row_array($n);
+		// Cast only if the row exists
+		if (count($row) > 0)
+		{
+			$this->current_row = $n;
+			return (object) $row;
+		}
+
+		return array();
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Single row result. Custom object version.
+	 *
+	 * @param	int	row index
+	 * @param	string	custom class name
+	 * @return	mixed	custom object if row found; empty array otherwise
+	 */
+	public function custom_row_object($n = 0, $class_name)
+	{
+		// Make sure $n is not a string
+		if ( ! is_int($n))
+		{
+			$n = (int) $n;
+		}
+
+		if (array_key_exists($class_name, $this->custom_result_object))
+		{
+			/* We already have a the whole result set with this class_name,
+			 * return the specified row if it exists, and an empty array if
+			 * it doesn't.
+			 */
+			if (isset($this->custom_result_object[$class_name][$n]))
+			{
+				$this->current_row = $n;
+				return $this->custom_result_object[$class_name][$n];
+			}
+			else
+			{
+				return array();
+			}
+		}
+		elseif ( ! class_exists($class_name)) // No such class exists
+		{
+			return array();
+		}
+
+		$row = $this->row_array($n);
+		// An array would mean that the row doesn't exist
+		if (is_array($row))
+		{
+			return $row;
+		}
+
+		// Convert to the desired class and return
+		$row_object = new $class_name();
+		foreach ($row as $key => $value)
+		{
+			$row_object->$key = $value;
+		}
+
+		$this->current_row = $n;
+		return $row_object;
+	}
+
+	// --------------------------------------------------------------------
+
+	/* First row result.
+	 *
+	 * @param	string	('object', 'array' or a custom class name)
+	 * @return	mixed	whatever was passed to the second parameter
+	 */
+	public function first_row($type = 'object')
+	{
+		return $this->row(0, $type);
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Last row result.
+	 *
+	 * @param	string	('object', 'array' or a custom class name)
+	 * @return	mixed	whatever was passed to the second parameter
+	 */
+	public function last_row($type = 'object')
+	{
+		$result = &$this->result($type);
+		if ( ! isset($this->num_rows))
+		{
+			$this->num_rows = count($result);
+		}
+		$this->current_row = $this->num_rows - 1;
+		return $result[$this->current_row];
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Next row result.
+	 *
+	 * @param	string	('object', 'array' or a custom class name)
+	 * @return	mixed	whatever was passed to the second parameter
+	 */
+	public function next_row($type = 'object')
+	{
+		if (is_array($this->row_data))
+		{
+			$count = count($this->row_data);
+			if ($this->current_row > $count OR ($this->current_row === 0 && $count === 0))
+			{
+				$n = $count;
+			}
+			else
+			{
+				$n = $this->current_row + 1;
+			}
+		}
+		else
+		{
+			$n = 0;
+		}
+
+		return $this->row($n, $type);
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Previous row result.
+	 *
+	 * @param	string	('object', 'array' or a custom class name)
+	 * @return	mixed	whatever was passed to the second parameter
+	 */
+	public function previous_row($type = 'object')
+	{
+		$n = ($this->current_row !== 0) ? $this->current_row - 1 : 0;
+		return $this->row($n, $type);
 	}
 
 	// --------------------------------------------------------------------
@@ -213,13 +648,54 @@
 	 *
 	 * Moves the internal pointer to the desired offset. We call
 	 * this internally before fetching results to make sure the
-	 * result set starts at zero
+	 * result set starts at zero.
 	 *
-	 * @return	array
+	 * Oracle's PHP extension doesn't have an easy way of doing this
+	 * and the only workaround is to (re)execute the statement or cursor
+	 * in order to go to the first (zero) index of the result set.
+	 * Then, we would need to "dummy" fetch ($n - 1) rows to get to the
+	 * right one.
+	 *
+	 * This is as ridiculous as it sounds and it's the reason why every
+	 * other method that is fetching data tries to use an already "cached"
+	 * result set. Keeping this just in case it becomes needed at
+	 * some point in the future, but it will only work for resetting the
+	 * pointer to zero.
+	 *
+	 * @return	bool
 	 */
-	protected function _data_seek($n = 0)
+	protected function _data_seek()
 	{
-		return FALSE; // Not needed
+		/* The PHP manual says that if OCI_NO_AUTO_COMMIT mode
+		 * is used, and oci_rollback() and/or oci_commit() are
+		 * not subsequently called - this will cause an unnecessary
+		 * rollback to be triggered at the end of the script execution.
+		 *
+		 * Therefore we'll try to avoid using that mode flag
+		 * if we're not currently in the middle of a transaction.
+		 */
+		if ($this->commit_mode !== OCI_COMMIT_ON_SUCCESS)
+		{
+			$result = @oci_execute($this->stmt_id, $this->commit_mode);
+		}
+		else
+		{
+			$result = @oci_execute($this->stmt_id);
+		}
+
+		if ($result && $this->curs_id)
+		{
+			if ($this->commit_mode !== OCI_COMMIT_ON_SUCCESS)
+			{
+				return @oci_execute($this->curs_id, $this->commit_mode);
+			}
+			else
+			{
+				return @oci_execute($this->curs_id);
+			}
+		}
+
+		return $result;
 	}
 
 }
diff --git a/system/database/drivers/oci8/oci8_utility.php b/system/database/drivers/oci8/oci8_utility.php
index e303fb6..efb4bca 100644
--- a/system/database/drivers/oci8/oci8_utility.php
+++ b/system/database/drivers/oci8/oci8_utility.php
@@ -37,11 +37,14 @@
 	/**
 	 * List databases
 	 *
-	 * @return	bool
+	 * Generates a platform-specific query so that we get a list of schemas
+	 * Those are actually usernames in Oracle.
+	 *
+	 * @return	string
 	 */
 	public function _list_databases()
 	{
-		return FALSE;
+		return 'SELECT username FROM dba_users';
 	}
 
 	// --------------------------------------------------------------------
@@ -56,7 +59,7 @@
 	 */
 	public function _optimize_table($table)
 	{
-		return FALSE; // Is this supported in Oracle?
+		return FALSE; // Not supported in Oracle
 	}
 
 	// --------------------------------------------------------------------
@@ -71,7 +74,7 @@
 	 */
 	public function _repair_table($table)
 	{
-		return FALSE; // Is this supported in Oracle?
+		return FALSE; // Not supported in Oracle
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index ed901bd..d1a5f77 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -343,47 +343,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Escape the SQL Identifiers
-	 *
-	 * This function escapes column and table names
-	 *
-	 * @param	string
-	 * @return	string
-	 */
-	public function _escape_identifiers($item)
-	{
-		if ($this->_escape_char == '')
-		{
-			return $item;
-		}
-
-		foreach ($this->_reserved_identifiers as $id)
-		{
-			if (strpos($item, '.'.$id) !== FALSE)
-			{
-				$str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
-				// remove duplicates if the user already included the escape
-				return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-			}
-		}
-
-		if (strpos($item, '.') !== FALSE)
-		{
-			$str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
-		}
-		else
-		{
-			$str = $this->_escape_char.$item.$this->_escape_char;
-		}
-
-		// remove duplicates if the user already included the escape
-		return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * From Tables
 	 *
 	 * This function implicitly groups FROM tables so there is no confusion
@@ -405,70 +364,19 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Insert statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert($table, $keys, $values)
-	{
-		return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Update statement
-	 *
-	 * Generates a platform-specific update string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the update data
-	 * @param	array	the where clause
-	 * @param	array	the orderby clause
-	 * @param	array	the limit clause
-	 * @return	string
-	 */
-	protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
-	{
-		foreach ($values as $key => $val)
-		{
-			$valstr[] = $key." = ".$val;
-		}
-
-		$limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
-		$orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
-		$sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
-		$sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
-		$sql .= $orderby.$limit;
-
-		return $sql;
-	}
-
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Truncate statement
 	 *
 	 * Generates a platform-specific truncate string from the supplied data
-	 * If the database does not support the truncate() command
-	 * This function maps to "DELETE FROM table"
+	 *
+	 * If the database does not support the truncate() command,
+	 * then this method maps to 'DELETE FROM table'
 	 *
 	 * @param	string	the table name
 	 * @return	string
 	 */
 	protected function _truncate($table)
 	{
-		return $this->_delete($table);
+		return 'DELETE FROM '.$table;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/odbc/odbc_forge.php b/system/database/drivers/odbc/odbc_forge.php
index 486a8dd..afdd6de 100644
--- a/system/database/drivers/odbc/odbc_forge.php
+++ b/system/database/drivers/odbc/odbc_forge.php
@@ -91,7 +91,7 @@
 			$sql .= 'IF NOT EXISTS ';
 		}
 
-		$sql .= $this->db->_escape_identifiers($table)." (";
+		$sql .= $this->db->escape_identifiers($table).' (';
 		$current_field_count = 0;
 
 		foreach ($fields as $field => $attributes)
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index a9bed36..919bb9c 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -46,8 +46,8 @@
 	protected $_escape_char = '';
 
 	// clause and character used for LIKE escape sequences
-	protected $_like_escape_str;
-	protected $_like_escape_chr;
+	protected $_like_escape_str = " ESCAPE '%s' ";
+	protected $_like_escape_chr = '!';
 
 	/**
 	 * The syntax to count rows is slightly different across different
@@ -81,18 +81,17 @@
 		// this one depends on the driver being used
 		if ($this->pdodriver == 'mysql')
 		{
+			$this->_escape_char = '`';
 			$this->_like_escape_str = '';
 			$this->_like_escape_chr = '';
 		}
 		elseif ($this->pdodriver == 'odbc')
 		{
 			$this->_like_escape_str = " {escape '%s'} ";
-			$this->_like_escape_chr = '!';
 		}
-		else
+		elseif ( ! in_array($this->pdodriver, array('sqlsrv', 'mssql', 'dblib', 'sybase')))
 		{
-			$this->_like_escape_str = " ESCAPE '%s' ";
-			$this->_like_escape_chr = '!';
+			$this->_escape_char = '"';
 		}
 
 		$this->trans_enabled = FALSE;
@@ -268,8 +267,6 @@
 	 */
 	protected function _execute($sql)
 	{
-		$sql = $this->_prep_query($sql);
-
 		$result_id = $this->conn_id->query($sql);
 
 		if (is_object($result_id))
@@ -287,32 +284,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Prep the query
-	 *
-	 * If needed, each database adapter can prep the query string
-	 *
-	 * @param	string	an SQL query
-	 * @return	string
-	 */
-	protected function _prep_query($sql)
-	{
-		if ($this->pdodriver === 'pgsql')
-		{
-			// Change the backtick(s) for Postgre
-			$sql = str_replace('`', '"', $sql);
-		}
-		elseif ($this->pdodriver === 'sqlite')
-		{
-			// Change the backtick(s) for SQLite
-			$sql = str_replace('`', '', $sql);
-		}
-
-		return $sql;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Begin Transaction
 	 *
 	 * @return	bool
@@ -516,7 +487,7 @@
 		}
 		else
 		{
-			$sql = "SHOW TABLES FROM `".$this->database."`";
+			$sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
 		}
 
 		if ($prefix_limit !== FALSE AND $this->dbprefix != '')
@@ -539,7 +510,7 @@
 	 */
 	protected function _list_columns($table = '')
 	{
-		return 'SHOW COLUMNS FROM '.$this->_from_tables($table);
+		return 'SHOW COLUMNS FROM '.$this->escape_identifiers($table);
 	}
 
 	// --------------------------------------------------------------------
@@ -557,20 +528,20 @@
 		if ($this->pdodriver == 'mysql' or $this->pdodriver == 'pgsql')
 		{
 			// Analog function for mysql and postgre
-			return 'SELECT * FROM '.$this->_from_tables($table).' LIMIT 1';
+			return 'SELECT * FROM '.$this->escape_identifiers($table).' LIMIT 1';
 		}
 		elseif ($this->pdodriver == 'oci')
 		{
 			// Analog function for oci
-			return 'SELECT * FROM '.$this->_from_tables($table).' WHERE ROWNUM <= 1';
+			return 'SELECT * FROM '.$this->escape_identifiers($table).' WHERE ROWNUM <= 1';
 		}
 		elseif ($this->pdodriver == 'sqlite')
 		{
 			// Analog function for sqlite
-			return 'PRAGMA table_info('.$this->_from_tables($table).')';
+			return 'PRAGMA table_info('.$this->escape_identifiers($table).')';
 		}
 
-		return 'SELECT TOP 1 FROM '.$this->_from_tables($table);
+		return 'SELECT TOP 1 FROM '.$this->escape_identifiers($table);
 	}
 
 	// --------------------------------------------------------------------
@@ -605,48 +576,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Escape the SQL Identifiers
-	 *
-	 * This function escapes column and table names
-	 *
-	 * @param	string
-	 * @return	string
-	 */
-	public function _escape_identifiers($item)
-	{
-		if ($this->_escape_char == '')
-		{
-			return $item;
-		}
-
-		foreach ($this->_reserved_identifiers as $id)
-		{
-			if (strpos($item, '.'.$id) !== FALSE)
-			{
-				$str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
-				// remove duplicates if the user already included the escape
-				return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-			}
-		}
-
-		if (strpos($item, '.') !== FALSE)
-		{
-			$str  = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
-			$str .= $this->_escape_char;
-		}
-		else
-		{
-			$str = $this->_escape_char.$item.$this->_escape_char;
-		}
-
-		// remove duplicates if the user already included the escape
-		return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * From Tables
 	 *
 	 * This function implicitly groups FROM tables so there is no confusion
@@ -662,72 +591,7 @@
 			$tables = array($tables);
 		}
 
-		return (count($tables) == 1) ? '`'.$tables[0].'`' : '('.implode(', ', $tables).')';
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Insert statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert($table, $keys, $values)
-	{
-		return 'INSERT INTO '.$this->_from_tables($table).' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Insert_batch statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert_batch($table, $keys, $values)
-	{
-		return 'INSERT INTO '.$this->_from_tables($table).' ('.implode(', ', $keys).') VALUES '.implode(', ', $values);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Update statement
-	 *
-	 * Generates a platform-specific update string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the update data
-	 * @param	array	the where clause
-	 * @param	array	the orderby clause
-	 * @param	array	the limit clause
-	 * @return	string
-	 */
-	protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
-	{
-		foreach ($values as $key => $val)
-		{
-			$valstr[] = $key." = ".$val;
-		}
-
-		$limit   = ( ! $limit) ? '' : ' LIMIT '.$limit;
-		$orderby = (count($orderby) >= 1) ? ' ORDER BY '.implode(', ', $orderby) : '';
-
-		$sql  = 'UPDATE '.$this->_from_tables($table).' SET '.implode(', ', $valstr);
-		$sql .= ($where != '' && count($where) >= 1) ? ' WHERE '.implode(' ', $where) : '';
-		$sql .= $orderby.$limit;
-
-		return $sql;
+		return (count($tables) === 1) ? $tables[0] : '('.implode(', ', $tables).')';
 	}
 
 	// --------------------------------------------------------------------
@@ -760,7 +624,7 @@
 			}
 		}
 
-		$sql   = 'UPDATE '.$this->_from_tables($table).' SET ';
+		$sql   = 'UPDATE '.$table.' SET ';
 		$cases = '';
 
 		foreach ($final as $k => $v)
@@ -787,15 +651,16 @@
 	 * Truncate statement
 	 *
 	 * Generates a platform-specific truncate string from the supplied data
-	 * If the database does not support the truncate() command
-	 * This function maps to "DELETE FROM table"
+	 *
+	 * If the database does not support the truncate() command,
+	 * then this method maps to 'DELETE FROM table'
 	 *
 	 * @param	string	the table name
 	 * @return	string
 	 */
 	protected function _truncate($table)
 	{
-		return $this->_delete($table);
+		return 'DELETE FROM '.$table;
 	}
 
 	// --------------------------------------------------------------------
@@ -829,7 +694,7 @@
 
 		$limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
 
-		return 'DELETE FROM '.$this->_from_tables($table).$conditions.$limit;
+		return 'DELETE FROM '.$table.$conditions.$limit;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/pdo/pdo_forge.php b/system/database/drivers/pdo/pdo_forge.php
index 6bff354..9635e4c 100644
--- a/system/database/drivers/pdo/pdo_forge.php
+++ b/system/database/drivers/pdo/pdo_forge.php
@@ -91,10 +91,10 @@
 			$sql .= 'IF NOT EXISTS ';
 		}
 
-		$sql .= '`'.$this->db->_escape_identifiers($table).'` (';
+		$sql .= $this->db->escape_identifiers($table).' (';
 		$current_field_count = 0;
 
-		foreach ($fields as $field=>$attributes)
+		foreach ($fields as $field => $attributes)
 		{
 			// Numeric field names aren't allowed in databases, so if the key is
 			// numeric, we know it was assigned by PHP and the developer manually
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index a033d74..1e96452 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -80,16 +80,16 @@
 			$this->port = '';
 		}
 
-		$this->hostname === '' OR $this->dsn = 'host='.$this->hostname;
+		$this->hostname === '' OR $this->dsn = 'host='.$this->hostname.' ';
 
 		if ( ! empty($this->port) && ctype_digit($this->port))
 		{
-			$this->dsn .= 'host='.$this->port.' ';
+			$this->dsn .= 'port='.$this->port.' ';
 		}
 
 		if ($this->username !== '')
 		{
-			$this->dsn .= 'username='.$this->username.' ';
+			$this->dsn .= 'user='.$this->username.' ';
 
 			/* An empty password is valid!
 			 *
@@ -457,47 +457,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Escape the SQL Identifiers
-	 *
-	 * This function escapes column and table names
-	 *
-	 * @param	string
-	 * @return	string
-	 */
-	public function _escape_identifiers($item)
-	{
-		if ($this->_escape_char == '')
-		{
-			return $item;
-		}
-
-		foreach ($this->_reserved_identifiers as $id)
-		{
-			if (strpos($item, '.'.$id) !== FALSE)
-			{
-				$str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
-				// remove duplicates if the user already included the escape
-				return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-			}
-		}
-
-		if (strpos($item, '.') !== FALSE)
-		{
-			$str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
-		}
-		else
-		{
-			$str = $this->_escape_char.$item.$this->_escape_char;
-		}
-
-		// remove duplicates if the user already included the escape
-		return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * From Tables
 	 *
 	 * This function implicitly groups FROM tables so there is no confusion
@@ -519,40 +478,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Insert statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert($table, $keys, $values)
-	{
-		return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Insert_batch statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param   string  the table name
-	 * @param   array   the insert keys
-	 * @param   array   the insert values
-	 * @return  string
-	 */
-	protected function _insert_batch($table, $keys, $values)
-	{
-		return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Update statement
 	 *
 	 * Generates a platform-specific update string from the supplied data
@@ -581,23 +506,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Truncate statement
-	 *
-	 * Generates a platform-specific truncate string from the supplied data
-	 * If the database does not support the truncate() command
-	 * This function maps to "DELETE FROM table"
-	 *
-	 * @param	string	the table name
-	 * @return	string
-	 */
-	protected function _truncate($table)
-	{
-		return "TRUNCATE ".$table;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Delete statement
 	 *
 	 * Generates a platform-specific delete string from the supplied data
diff --git a/system/database/drivers/postgre/postgre_forge.php b/system/database/drivers/postgre/postgre_forge.php
index a724498..f7d5928 100644
--- a/system/database/drivers/postgre/postgre_forge.php
+++ b/system/database/drivers/postgre/postgre_forge.php
@@ -193,8 +193,7 @@
 			}
 		}
 
-		$sql .= $this->db->_escape_identifiers($table)." (";
-		$sql .= $this->_process_fields($fields, $primary_keys);
+		$sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields, $primary_keys);
 
 		if (count($primary_keys) > 0)
 		{
@@ -237,11 +236,12 @@
 	/**
 	 * Drop Table
 	 *
+	 * @param	string	table name
 	 * @return	string
 	 */
 	public function _drop_table($table)
 	{
-		return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table)." CASCADE";
+		return 'DROP TABLE IF EXISTS '.$this->db->escape_identifiers($table).' CASCADE';
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index 65f60b0..7936b61 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -354,43 +354,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Escape the SQL Identifiers
-	 *
-	 * This function escapes column and table names
-	 *
-	 * @param	string
-	 * @return	string
-	 */
-	public function _escape_identifiers($item)
-	{
-		if ($this->_escape_char == '')
-		{
-			return $item;
-		}
-
-		foreach ($this->_reserved_identifiers as $id)
-		{
-			if (strpos($item, '.'.$id) !== FALSE)
-			{
-				$item = str_replace('.', $this->_escape_char.'.', $item);
-
-				// remove duplicates if the user already included the escape
-				return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item);
-			}
-		}
-
-		if (strpos($item, '.') !== FALSE)
-		{
-			$item = str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item);
-		}
-
-		// remove duplicates if the user already included the escape
-		return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $this->_escape_char.$item.$this->_escape_char);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * From Tables
 	 *
 	 * This function implicitly groups FROM tables so there is no confusion
@@ -412,63 +375,36 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Insert statement
+	 * Replace statement
 	 *
-	 * Generates a platform-specific insert string from the supplied data
+	 * Generates a platform-specific replace string from the supplied data
 	 *
 	 * @param	string	the table name
 	 * @param	array	the insert keys
 	 * @param	array	the insert values
 	 * @return	string
 	 */
-	protected function _insert($table, $keys, $values)
+	protected function _replace($table, $keys, $values)
 	{
-		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
+		return 'INSERT OR '.parent::_replace($table, $keys, $values);
 	}
 
 	// --------------------------------------------------------------------
 
 	/**
-	 * Update statement
-	 *
-	 * Generates a platform-specific update string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the update data
-	 * @param	array	the where clause
-	 * @param	array	the orderby clause
-	 * @param	array	the limit clause
-	 * @return	string
-	 */
-	protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
-	{
-		foreach ($values as $key => $val)
-		{
-			$valstr[] = $key.' = '.$val;
-		}
-
-		return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
-			.(($where != '' && count($where) > 0) ? ' WHERE '.implode(' ', $where) : '')
-			.(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '')
-			.( ! $limit ? '' : ' LIMIT '.$limit);
-	}
-
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Truncate statement
 	 *
 	 * Generates a platform-specific truncate string from the supplied data
-	 * If the database does not support the truncate() command
-	 * This function maps to "DELETE FROM table"
+	 *
+	 * If the database does not support the truncate() command,
+	 * then this function maps to 'DELETE FROM table'
 	 *
 	 * @param	string	the table name
 	 * @return	string
 	 */
 	protected function _truncate($table)
 	{
-		return $this->_delete($table);
+		return 'DELETE FROM '.$table;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php
index 4c91cc3..70bb6a7 100644
--- a/system/database/drivers/sqlite/sqlite_forge.php
+++ b/system/database/drivers/sqlite/sqlite_forge.php
@@ -87,7 +87,7 @@
 			$sql .= 'IF NOT EXISTS ';
 		}
 
-		$sql .= $this->db->_escape_identifiers($table).'(';
+		$sql .= $this->db->escape_identifiers($table).' (';
 		$current_field_count = 0;
 
 		foreach ($fields as $field => $attributes)
diff --git a/system/database/drivers/sqlite3/index.html b/system/database/drivers/sqlite3/index.html
new file mode 100644
index 0000000..c942a79
--- /dev/null
+++ b/system/database/drivers/sqlite3/index.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+	<title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php
new file mode 100644
index 0000000..12354e1
--- /dev/null
+++ b/system/database/drivers/sqlite3/sqlite3_driver.php
@@ -0,0 +1,459 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst.  It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package		CodeIgniter
+ * @author		EllisLab Dev Team
+ * @copyright	Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license		http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link		http://codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+
+/**
+ * SQLite3 Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the active record
+ * class is being used or not.
+ *
+ * @package		CodeIgniter
+ * @subpackage	Drivers
+ * @category	Database
+ * @author		Andrey Andreev
+ * @link		http://codeigniter.com/user_guide/database/
+ * @since		Version 3.0
+ */
+class CI_DB_sqlite3_driver extends CI_DB {
+
+	public $dbdriver = 'sqlite3';
+
+	// The character used for escaping
+	protected $_escape_char = '"';
+
+	// clause and character used for LIKE escape sequences
+	protected $_like_escape_str = ' ESCAPE \'%s\' ';
+	protected $_like_escape_chr = '!';
+
+	/**
+	 * The syntax to count rows is slightly different across different
+	 * database engines, so this string appears in each driver and is
+	 * used for the count_all() and count_all_results() functions.
+	 */
+	protected $_count_string = 'SELECT COUNT(*) AS ';
+	protected $_random_keyword = ' RANDOM()';
+
+	/**
+	 * Non-persistent database connection
+	 *
+	 * @return	object	type SQLite3
+	 */
+	public function db_connect()
+	{
+		try
+		{
+			return ( ! $this->password)
+				? new SQLite3($this->database)
+				: new SQLite3($this->database, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE, $this->password);
+		}
+		catch (Exception $e)
+		{
+			return FALSE;
+		}
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Persistent database connection
+	 *
+	 * @return  object	type SQLite3
+	 */
+	public function db_pconnect()
+	{
+		log_message('debug', 'SQLite3 doesn\'t support persistent connections');
+		return $this->db_pconnect();
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Database version number
+	 *
+	 * @return	string
+	 */
+	public function version()
+	{
+		if (isset($this->data_cache['version']))
+		{
+			return $this->data_cache['version'];
+		}
+
+		$version = $this->conn_id->version();
+		return $this->data_cache['version'] = $version['versionString'];
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Execute the query
+	 *
+	 * @param	string	an SQL query
+	 * @return	mixed	SQLite3Result object or bool
+	 */
+	protected function _execute($sql)
+	{
+		// TODO: Implement use of SQLite3::querySingle(), if needed
+
+		return $this->is_write_type($sql)
+			? $this->conn_id->exec($sql)
+			: $this->conn_id->query($sql);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Begin Transaction
+	 *
+	 * @return	bool
+	 */
+	public function trans_begin($test_mode = FALSE)
+	{
+		// When transactions are nested we only begin/commit/rollback the outermost ones
+		if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+		{
+			return TRUE;
+		}
+
+		// Reset the transaction failure flag.
+		// If the $test_mode flag is set to TRUE transactions will be rolled back
+		// even if the queries produce a successful result.
+		$this->_trans_failure = ($test_mode === TRUE);
+
+		return $this->conn_id->exec('BEGIN TRANSACTION');
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Commit Transaction
+	 *
+	 * @return	bool
+	 */
+	public function trans_commit()
+	{
+		// When transactions are nested we only begin/commit/rollback the outermost ones
+		if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+		{
+			return TRUE;
+		}
+
+		return $this->conn_id->exec('END TRANSACTION');
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Rollback Transaction
+	 *
+	 * @return	bool
+	 */
+	public function trans_rollback()
+	{
+		// When transactions are nested we only begin/commit/rollback the outermost ones
+		if ( ! $this->trans_enabled OR $this->_trans_depth > 0)
+		{
+			return TRUE;
+		}
+
+		return $this->conn_id->exec('ROLLBACK');
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Escape String
+	 *
+	 * @param	string
+	 * @param	bool	whether or not the string will be used in a LIKE condition
+	 * @return	string
+	 */
+	public function escape_str($str, $like = FALSE)
+	{
+		if (is_array($str))
+		{
+			foreach ($str as $key => $val)
+			{
+				$str[$key] = $this->escape_str($val, $like);
+			}
+
+			return $str;
+		}
+
+		$str = $this->conn_id->escapeString(remove_invisible_characters($str));
+
+		// escape LIKE condition wildcards
+		if ($like === TRUE)
+		{
+			return str_replace(array($this->_like_escape_chr, '%', '_'),
+						array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'),
+						$str);
+		}
+
+		return $str;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Affected Rows
+	 *
+	 * @return	int
+	 */
+	public function affected_rows()
+	{
+		return $this->conn_id->changes();
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Insert ID
+	 *
+	 * @return	int
+	 */
+	public function insert_id()
+	{
+		return $this->conn_id->lastInsertRowID();
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * "Count All" query
+	 *
+	 * Generates a platform-specific query string that counts all records in
+	 * the specified database
+	 *
+	 * @param	string
+	 * @return	int
+	 */
+	public function count_all($table = '')
+	{
+		if ($table == '')
+		{
+			return 0;
+		}
+
+		$result = $this->conn_id->querySingle($this->_count_string.$this->protect_identifiers('numrows')
+							.' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
+
+		return empty($result) ? 0 : (int) $result;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Show table query
+	 *
+	 * Generates a platform-specific query string so that the table names can be fetched
+	 *
+	 * @param	bool
+	 * @return	string
+	 */
+	protected function _list_tables($prefix_limit = FALSE)
+	{
+		return 'SELECT "NAME" FROM "SQLITE_MASTER" WHERE "TYPE" = \'table\''
+			.(($prefix_limit !== FALSE && $this->dbprefix != '')
+				? ' AND "NAME" LIKE \''.$this->escape_like_str($this->dbprefix).'%\' '.sprintf($this->_like_escape_str, $this->_like_escape_chr)
+				: '');
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Show column query
+	 *
+	 * Generates a platform-specific query string so that the column names can be fetched
+	 *
+	 * @param	string	the table name
+	 * @return	string
+	 */
+	protected function _list_columns($table = '')
+	{
+		// Not supported
+		return FALSE;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Field data query
+	 *
+	 * Generates a platform-specific query so that the column data can be retrieved
+	 *
+	 * @param	string	the table name
+	 * @return	string
+	 */
+	protected function _field_data($table)
+	{
+		return 'SELECT * FROM '.$table.' LIMIT 0,1';
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * The error message string
+	 *
+	 * @return	string
+	 */
+	protected function _error_message()
+	{
+		return $this->conn_id->lastErrorMsg();
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * The error message number
+	 *
+	 * @return	int
+	 */
+	protected function _error_number()
+	{
+		return $this->conn_id->lastErrorCode();
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * From Tables
+	 *
+	 * This function implicitly groups FROM tables so there is no confusion
+	 * about operator precedence in harmony with SQL standards
+	 *
+	 * @param	string
+	 * @return	string
+	 */
+	protected function _from_tables($tables)
+	{
+		if ( ! is_array($tables))
+		{
+			$tables = array($tables);
+		}
+
+		return '('.implode(', ', $tables).')';
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Replace statement
+	 *
+	 * Generates a platform-specific replace string from the supplied data
+	 *
+	 * @param	string	the table name
+	 * @param	array	the insert keys
+	 * @param	array	the insert values
+	 * @return	string
+	 */
+	protected function _replace($table, $keys, $values)
+	{
+		return 'INSERT OR '.parent::_replace($table, $keys, $values);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Truncate statement
+	 *
+	 * Generates a platform-specific truncate string from the supplied data
+	 *
+	 * If the database does not support the truncate() command, then,
+	 * then this method maps to 'DELETE FROM table'
+	 *
+	 * @param	string	the table name
+	 * @return	string
+	 */
+	protected function _truncate($table)
+	{
+		return 'DELETE FROM '.$table;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Delete statement
+	 *
+	 * Generates a platform-specific delete string from the supplied data
+	 *
+	 * @param	string	the table name
+	 * @param	array	the where clause
+	 * @param	string	the limit clause
+	 * @return	string
+	 */
+	protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+	{
+		$conditions = '';
+		if (count($where) > 0 OR count($like) > 0)
+		{
+			$conditions .= "\nWHERE ".implode("\n", $this->ar_where);
+
+			if (count($where) > 0 && count($like) > 0)
+			{
+				$conditions .= ' AND ';
+			}
+			$conditions .= implode("\n", $like);
+		}
+
+		return 'DELETE FROM '.$table.$conditions.( ! $limit ? '' : ' LIMIT '.$limit);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Limit string
+	 *
+	 * Generates a platform-specific LIMIT clause
+	 *
+	 * @param	string	the sql query string
+	 * @param	int	the number of rows to limit the query to
+	 * @param	int	the offset value
+	 * @return	string
+	 */
+	protected function _limit($sql, $limit, $offset)
+	{
+		return $sql.' LIMIT '.($offset ? $offset.',' : '').$limit;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Close DB Connection
+	 *
+	 * @return	void
+	 */
+	protected function _close()
+	{
+		$this->conn_id->close();
+	}
+
+}
+
+/* End of file sqlite3_driver.php */
+/* Location: ./system/database/drivers/sqlite3/sqlite3_driver.php */
\ No newline at end of file
diff --git a/system/database/drivers/sqlite3/sqlite3_forge.php b/system/database/drivers/sqlite3/sqlite3_forge.php
new file mode 100644
index 0000000..3a2060c
--- /dev/null
+++ b/system/database/drivers/sqlite3/sqlite3_forge.php
@@ -0,0 +1,223 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst.  It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package	CodeIgniter
+ * @author	EllisLab Dev Team
+ * @copyright	Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license	http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link	http://codeigniter.com
+ * @since	Version 1.0
+ * @filesource
+ */
+
+/**
+ * SQLite3 Forge Class
+ *
+ * @category	Database
+ * @author	Andrey Andreev
+ * @link	http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_sqlite3_forge extends CI_DB_forge {
+
+	/**
+	 * Create database
+	 *
+	 * @param	string	the database name
+	 * @return	bool
+	 */
+	public function _create_database()
+	{
+		// In SQLite, a database is created when you connect to the database.
+		// We'll return TRUE so that an error isn't generated
+		return TRUE;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Drop database
+	 *
+	 * @param	string	the database name
+	 * @return	bool
+	 */
+	public function _drop_database($name)
+	{
+		// In SQLite, a database is dropped when we delete a file
+		if (@file_exists($this->db->database))
+		{
+			// We need to close the pseudo-connection first
+			$this->db->close();
+			if ( ! @unlink($this->db->database))
+			{
+				return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;
+			}
+
+			return TRUE;
+		}
+
+		return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Create Table
+	 *
+	 * @param	string	the table name
+	 * @param	array	the fields
+	 * @param	mixed	primary key(s)
+	 * @param	mixed	key(s)
+	 * @param	bool	should 'IF NOT EXISTS' be added to the SQL
+	 * @return	bool
+	 */
+	public function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+	{
+		$sql = 'CREATE TABLE ';
+
+		// IF NOT EXISTS added to SQLite in 3.3.0
+		if ($if_not_exists === TRUE && version_compare($this->db->version(), '3.3.0', '>=') === TRUE)
+		{
+			$sql .= 'IF NOT EXISTS ';
+		}
+
+		$sql .= $this->db->escape_identifiers($table).' (';
+		$current_field_count = 0;
+
+		foreach ($fields as $field => $attributes)
+		{
+			// Numeric field names aren't allowed in databases, so if the key is
+			// numeric, we know it was assigned by PHP and the developer manually
+			// entered the field information, so we'll simply add it to the list
+			if (is_numeric($field))
+			{
+				$sql .= "\n\t".$attributes;
+			}
+			else
+			{
+				$attributes = array_change_key_case($attributes, CASE_UPPER);
+
+				$sql .= "\n\t".$this->db->protect_identifiers($field)
+					.' '.$attributes['TYPE']
+					.( ! empty($attributes['CONSTRAINT']) ? '('.$attributes['CONSTRAINT'].')' : '')
+					.(( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE) ? ' UNSIGNED' : '')
+					.(isset($attributes['DEFAULT']) ? ' DEFAULT \''.$attributes['DEFAULT'].'\'' : '')
+					.(( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE) ? ' NULL' : ' NOT NULL')
+					.(( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) ? ' AUTO_INCREMENT' : '');
+			}
+
+			// don't add a comma on the end of the last field
+			if (++$current_field_count < count($fields))
+			{
+				$sql .= ',';
+			}
+		}
+
+		if (count($primary_keys) > 0)
+		{
+			$primary_keys = $this->db->protect_identifiers($primary_keys);
+			$sql .= ",\n\tPRIMARY KEY (".implode(', ', $primary_keys).')';
+		}
+
+		if (is_array($keys) && count($keys) > 0)
+		{
+			foreach ($keys as $key)
+			{
+				if (is_array($key))
+				{
+					$key = $this->db->protect_identifiers($key);
+				}
+				else
+				{
+					$key = array($this->db->protect_identifiers($key));
+				}
+
+				$sql .= ",\n\tUNIQUE (".implode(', ', $key).')';
+			}
+		}
+
+		return $sql."\n)";
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Drop Table
+	 *
+	 * @param	string	the table name
+	 * @return	string
+	 */
+	public function _drop_table($table)
+	{
+		return 'DROP TABLE '.$table.' IF EXISTS';
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Alter table query
+	 *
+	 * Generates a platform-specific query so that a table can be altered
+	 * Called by add_column(), drop_column(), and column_alter(),
+	 *
+	 * @param	string	the ALTER type (ADD, DROP, CHANGE)
+	 * @param	string	the column name
+	 * @param	string	the table name
+	 * @param	string	the column definition
+	 * @param	string	the default value
+	 * @param	bool	should 'NOT NULL' be added
+	 * @param	string	the field after which we should add the new field
+	 * @return	string
+	 */
+	public function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+	{
+		/* SQLite only supports adding new columns and it does
+		 * NOT support the AFTER statement. Each new column will
+		 * be added as the last one in the table.
+		 */
+		if ($alter_type !== 'ADD COLUMN')
+		{
+			// Not supported
+			return FALSE;
+		}
+
+		return 'ALTER TABLE '.$this->db->protect_identifiers($table).' '.$alter_type.' '.$this->db->protect_identifiers($column_name)
+			.' '.$column_definition
+			.($default_value != '' ? ' DEFAULT '.$default_value : '')
+			// If NOT NULL is specified, the field must have a DEFAULT value other than NULL
+			.(($null !== NULL && $default_value !== 'NULL') ? ' NOT NULL' : ' NULL');
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Rename a table
+	 *
+	 * Generates a platform-specific query so that a table can be renamed
+	 *
+	 * @param	string	the old table name
+	 * @param	string	the new table name
+	 * @return	string
+	 */
+	public function _rename_table($table_name, $new_table_name)
+	{
+		return 'ALTER TABLE '.$this->db->protect_identifiers($table_name).' RENAME TO '.$this->db->protect_identifiers($new_table_name);
+	}
+}
+
+/* End of file sqlite3_forge.php */
+/* Location: ./system/database/drivers/sqlite3/sqlite3_forge.php */
\ No newline at end of file
diff --git a/system/database/drivers/sqlite3/sqlite3_result.php b/system/database/drivers/sqlite3/sqlite3_result.php
new file mode 100644
index 0000000..ddf59db
--- /dev/null
+++ b/system/database/drivers/sqlite3/sqlite3_result.php
@@ -0,0 +1,619 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst.  It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package	CodeIgniter
+ * @author	EllisLab Dev Team
+ * @copyright	Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license	http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link	http://codeigniter.com
+ * @since	Version 1.0
+ * @filesource
+ */
+
+/**
+ * SQLite Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category	Database
+ * @author	Andrey Andreev
+ * @link	http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_sqlite3_result extends CI_DB_result {
+
+	// Overwriting the parent here, so we have a way to know if it's already set
+	public $num_rows;
+
+	// num_fields() might be called multiple times, so we'll use this one to cache it's result
+	protected $_num_fields;
+
+	/**
+	 * Number of rows in the result set
+	 *
+	 * @return	int
+	 */
+	public function num_rows()
+	{
+		/* The SQLite3 driver doesn't have a graceful way to do this,
+		 * so we'll have to do it on our own.
+		 */
+		return is_int($this->num_rows)
+			? $this->num_rows
+			: $this->num_rows = count($this->result_array());
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Number of fields in the result set
+	 *
+	 * @return	int
+	 */
+	public function num_fields()
+	{
+		return ( ! is_int($this->_num_fields))
+			? $this->_num_fields = $this->result_id->numColumns()
+			: $this->_num_fields;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Fetch Field Names
+	 *
+	 * Generates an array of column names
+	 *
+	 * @return	array
+	 */
+	public function list_fields()
+	{
+		$field_names = array();
+		for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
+		{
+			$field_names[] = $this->result_id->columnName($i);
+		}
+
+		return $field_names;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Field data
+	 *
+	 * Generates an array of objects containing field meta-data
+	 *
+	 * @return	array
+	 */
+	public function field_data()
+	{
+		$retval = array();
+		for ($i = 0, $c = $this->num_fields(); $i < $this->num_fields(); $i++)
+		{
+			$retval[$i]			= new stdClass();
+			$retval[$i]->name		= $this->result_id->columnName($i);
+			$retval[$i]->type		= 'varchar';
+			$retval[$i]->max_length		= 0;
+			$retval[$i]->primary_key	= 0;
+			$retval[$i]->default		= '';
+		}
+
+		return $retval;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Free the result
+	 *
+	 * @return	void
+	 */
+	public function free_result()
+	{
+		if (is_object($this->result_id))
+		{
+			$this->result_id->finalize();
+			$this->result_id = NULL;
+		}
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Result - associative array
+	 *
+	 * Returns the result set as an array
+	 *
+	 * @return	array
+	 */
+	protected function _fetch_assoc()
+	{
+		return $this->result_id->fetchArray(SQLITE3_ASSOC);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Result - object
+	 *
+	 * Returns the result set as an object
+	 *
+	 * @return	object
+	 */
+	protected function _fetch_object()
+	{
+		// No native support for fetching as an object
+		$row = $this->_fetch_assoc();
+		return ($row !== FALSE) ? (object) $row : FALSE;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Query result. "array" version.
+	 *
+	 * return	array
+	 */
+	public function result_array()
+	{
+		if (count($this->result_array) > 0)
+		{
+			return $this->result_array;
+		}
+		elseif (is_array($this->row_data))
+		{
+			if (count($this->row_data) === 0)
+			{
+				return $this->result_array;
+			}
+			else
+			{
+				$row_index = count($this->row_data);
+			}
+		}
+		else
+		{
+			$row_index = 0;
+			$this->row_data = array();
+		}
+
+		$row = NULL;
+		while ($row = $this->_fetch_assoc())
+		{
+			$this->row_data[$row_index++] = $row;
+		}
+
+		// Un-comment the following line, in case it becomes needed
+		// $this->_data_seek();
+		return $this->result_array = $this->row_data;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Query result. "object" version.
+	 *
+	 * @return	array
+	 */
+	public function result_object()
+	{
+		if (count($this->result_object) > 0)
+		{
+			return $this->result_object;
+		}
+		elseif (count($this->result_array) > 0)
+		{
+			for ($i = 0, $c = count($this->result_array); $i < $c; $i++)
+			{
+				$this->result_object[] = (object) $this->result_array[$i];
+			}
+
+			return $this->result_object;
+		}
+		elseif (is_array($this->row_data))
+		{
+			if (count($this->row_data) === 0)
+			{
+				return $this->result_object;
+			}
+			else
+			{
+				$row_index = count($this->row_data);
+				for ($i = 0; $i < $row_index; $i++)
+				{
+					$this->result_object[$i] = (object) $this->row_data[$i];
+				}
+			}
+		}
+		else
+		{
+			$row_index = 0;
+			$this->row_data = array();
+		}
+
+		$row = NULL;
+		while ($row = $this->_fetch_assoc())
+		{
+			$this->row_data[$row_index] = $row;
+			$this->result_object[$row_index++] = (object) $row;
+		}
+
+		$this->result_array = $this->row_data;
+
+		/* As described for the num_rows() method - there's no easy
+		 * way to get the number of rows selected. Our work-around
+		 * solution (as in here as well) first checks if result_array
+		 * exists and returns its count. It doesn't however check for
+		 * custom_object_result, so - do it here.
+		 */
+		if ( ! is_int($this->num_rows))
+		{
+			$this->num_rows = count($this->result_object);
+		}
+
+		// Un-comment the following line, in case it becomes needed
+		// $this->_data_seek();
+		return $this->result_object;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Query result. Custom object version.
+	 *
+	 * @param	string	class name used to instantiate rows to
+	 * @return	array
+	 */
+	public function custom_result_object($class_name)
+	{
+		if (array_key_exists($class_name, $this->custom_result_object))
+		{
+			return $this->custom_result_object[$class_name];
+		}
+
+		if ( ! class_exists($class_name) OR ! is_object($this->result_id) OR $this->num_rows() === 0)
+		{
+			return array();
+		}
+
+		/* Even if result_array hasn't been set prior to custom_result_object being called,
+		 * num_rows() has done it.
+		*/
+		$data = &$this->result_array;
+
+		$result_object = array();
+		for ($i = 0, $c = count($data); $i < $c; $i++)
+		{
+			$result_object[$i] = new $class_name();
+			foreach ($data[$i] as $key => $value)
+			{
+				$result_object[$i]->$key = $value;
+			}
+		}
+
+		/* As described for the num_rows() method - there's no easy
+		 * way to get the number of rows selected. Our work-around
+		 * solution (as in here as well) first checks if result_array
+		 * exists and returns its count. It doesn't however check for
+		 * custom_object_result, so - do it here.
+		 */
+		if ( ! is_int($this->num_rows))
+		{
+			$this->num_rows = count($result_object);
+		}
+
+		// Cache and return the array
+		return $this->custom_result_object[$class_name] = $result_object;
+        }
+
+	// --------------------------------------------------------------------
+
+	/* Single row result.
+	 *
+	 * Acts as a wrapper for row_object(), row_array()
+	 * and custom_row_object(). Also used by first_row(), next_row()
+	 * and previous_row().
+	 *
+	 * @param	int	row index
+	 * @param	string	('object', 'array' or a custom class name)
+	 * @return	mixed	whatever was passed to the second parameter
+	 */
+	public function row($n = 0, $type = 'object')
+	{
+		if ($type === 'object')
+		{
+			return $this->row_object($n);
+		}
+		elseif ($type === 'array')
+		{
+			return $this->row_array($n);
+		}
+
+		return $this->custom_row_object($n, $type);
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Single row result. Array version.
+	 *
+	 * @param	int	row index
+	 * @return	array
+	 */
+	public function row_array($n = 0)
+	{
+		// Make sure $n is not a string
+		if ( ! is_int($n))
+		{
+			$n = (int) $n;
+		}
+
+		/* If row_data is initialized, it means that we've already tried
+		 * (at least) to fetch some data, so ... check if we already have
+		 * this row.
+		*/
+		if (is_array($this->row_data))
+		{
+			/* If we already have row_data[$n] - return it.
+			 *
+			 * If we enter the elseif, there's a number of reasons to
+			 * return an empty array:
+			 *
+			 *	- count($this->row_data) === 0 means there are no results
+			 *	- num_rows being set or result_array having count() > 0 means
+			 *	  that we've already fetched all data and $n is greater than
+			 *	  our highest row index available
+			 *	- $n < $this->current_row means that if such row existed,
+			 *	  we would've already returned it, therefore $n is an
+			 *	  invalid index
+			 */
+			if (isset($this->row_data[$n])) // We already have this row
+			{
+				$this->current_row = $n;
+				return $this->row_data[$n];
+			}
+			elseif (count($this->row_data) === 0 OR is_int($this->num_rows)
+				OR count($this->result_array) > 0 OR $n < $this->current_row)
+			{
+				// No such row exists
+				return array();
+			}
+
+			// Get the next row index that would actually need to be fetched
+			$current_row = ($this->current_row < count($this->row_data)) ? count($this->row_data) : $this->current_row + 1;
+		}
+		else
+		{
+			$current_row = $this->current_row = 0;
+			$this->row_data = array();
+		}
+
+		/* Fetch more data, if available
+		 *
+		 * NOTE: Operator precedence is important here, if you change
+		 *	 'AND' with '&&' - it WILL BREAK the results, as
+		 *	 $row will be assigned the scalar value of both
+		 *	 expressions!
+		 */
+		while ($row = $this->_fetch_assoc() AND $current_row <= $n)
+		{
+			$this->row_data[$current_row++] = $row;
+		}
+
+		// This would mean that there's no (more) data to fetch
+		if ( ! is_array($this->row_data) OR ! isset($this->row_data[$n]))
+		{
+			// Cache what we already have
+			if (is_array($this->row_data))
+			{
+				$this->num_rows = count($this->row_data);
+				/* Usually, row_data could have less elements than result_array,
+				 * but at this point - they should be exactly the same.
+				 */
+				$this->result_array = $this->row_data;
+			}
+			else
+			{
+				$this->num_rows = 0;
+			}
+
+			return array();
+		}
+
+		$this->current_row = $n;
+		return $this->row_data[$n];
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Single row result. Object version.
+	 *
+	 * @param	int	row index
+	 * @return	mixed	object if row found; empty array if not
+	 */
+	public function row_object($n = 0)
+	{
+		// Make sure $n is not a string
+		if ( ! is_int($n))
+		{
+			$n = (int) $n;
+		}
+
+		/* Logic here is exactly the same as in row_array,
+		 * except we have to cast row_data[$n] to an object.
+		 *
+		 * If we already have result_object though - we can
+		 * directly return from it.
+		 */
+		if (isset($this->result_object[$n]))
+		{
+			$this->current_row = $n;
+			return $this->result_object[$n];
+		}
+
+		$row = $this->row_array($n);
+		// Cast only if the row exists
+		if (count($row) > 0)
+		{
+			$this->current_row = $n;
+			return (object) $row;
+		}
+
+		return array();
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Single row result. Custom object version.
+	 *
+	 * @param	int	row index
+	 * @param	string	custom class name
+	 * @return	mixed	custom object if row found; empty array otherwise
+	 */
+	public function custom_row_object($n = 0, $class_name)
+	{
+		// Make sure $n is not a string
+		if ( ! is_int($n))
+		{
+			$n = (int) $n;
+		}
+
+		if (array_key_exists($class_name, $this->custom_result_object))
+		{
+			/* We already have a the whole result set with this class_name,
+			 * return the specified row if it exists, and an empty array if
+			 * it doesn't.
+			 */
+			if (isset($this->custom_result_object[$class_name][$n]))
+			{
+				$this->current_row = $n;
+				return $this->custom_result_object[$class_name][$n];
+			}
+			else
+			{
+				return array();
+			}
+		}
+		elseif ( ! class_exists($class_name)) // No such class exists
+		{
+			return array();
+		}
+
+		$row = $this->row_array($n);
+		// An array would mean that the row doesn't exist
+		if (is_array($row))
+		{
+			return $row;
+		}
+
+		// Convert to the desired class and return
+		$row_object = new $class_name();
+		foreach ($row as $key => $value)
+		{
+			$row_object->$key = $value;
+		}
+
+		$this->current_row = $n;
+		return $row_object;
+	}
+
+	// --------------------------------------------------------------------
+
+	/* First row result.
+	 *
+	 * @param	string	('object', 'array' or a custom class name)
+	 * @return	mixed	whatever was passed to the second parameter
+	 */
+	public function first_row($type = 'object')
+	{
+		return $this->row(0, $type);
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Last row result.
+	 *
+	 * @param	string	('object', 'array' or a custom class name)
+	 * @return	mixed	whatever was passed to the second parameter
+	 */
+	public function last_row($type = 'object')
+	{
+		$result = &$this->result($type);
+		if ( ! isset($this->num_rows))
+		{
+			$this->num_rows = count($result);
+		}
+		$this->current_row = $this->num_rows - 1;
+		return $result[$this->current_row];
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Next row result.
+	 *
+	 * @param	string	('object', 'array' or a custom class name)
+	 * @return	mixed	whatever was passed to the second parameter
+	 */
+	public function next_row($type = 'object')
+	{
+		if (is_array($this->row_data))
+		{
+			$count = count($this->row_data);
+			$n = ($this->current_row > $count OR ($this->current_row === 0 && $count === 0)) ? $count : $this->current_row + 1;
+		}
+		else
+		{
+			$n = 0;
+		}
+
+		return $this->row($n, $type);
+	}
+
+	// --------------------------------------------------------------------
+
+	/* Previous row result.
+	 *
+	 * @param	string	('object', 'array' or a custom class name)
+	 * @return	mixed	whatever was passed to the second parameter
+	 */
+	public function previous_row($type = 'object')
+	{
+		$n = ($this->current_row !== 0) ? $this->current_row - 1 : 0;
+		return $this->row($n, $type);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Data Seek
+	 *
+	 * Moves the internal pointer to the desired offset. We call
+	 * this internally before fetching results to make sure the
+	 * result set starts at zero
+	 *
+	 * @return	array
+	 */
+	protected function _data_seek($n = 0)
+	{
+		// Only resetting to the start of the result set is supported
+		return $this->result_id->reset();
+	}
+
+}
+
+/* End of file sqlite3_result.php */
+/* Location: ./system/database/drivers/sqlite3/sqlite3_result.php */
\ No newline at end of file
diff --git a/system/database/drivers/sqlite3/sqlite3_utility.php b/system/database/drivers/sqlite3/sqlite3_utility.php
new file mode 100644
index 0000000..a4dc875
--- /dev/null
+++ b/system/database/drivers/sqlite3/sqlite3_utility.php
@@ -0,0 +1,103 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst.  It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package	CodeIgniter
+ * @author	EllisLab Dev Team
+ * @copyright	Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license	http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link	http://codeigniter.com
+ * @since	Version 1.0
+ * @filesource
+ */
+
+/**
+ * SQLite3 Utility Class
+ *
+ * @category	Database
+ * @author	Andrey Andreev
+ * @link	http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_sqlite3_utility extends CI_DB_utility {
+
+	/**
+	 * List databases
+	 *
+	 * @return	bool
+	 */
+	public function _list_databases()
+	{
+		// Not supported
+		return FALSE;
+
+		// Do we use this?
+		if ($this->db_debug)
+		{
+			return $this->db->display_error('db_unsuported_feature');
+		}
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Optimize table query
+	 *
+	 * Is optimization even supported in SQLite?
+	 *
+	 * @param	string	the table name
+	 * @return	bool
+	 */
+	public function _optimize_table($table)
+	{
+		// Not supported
+		return FALSE;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Repair table query
+	 *
+	 * Are table repairs even supported in SQLite?
+	 *
+	 * @param	string	the table name
+	 * @return	object
+	 */
+	public function _repair_table($table)
+	{
+		// Not supported
+		return FALSE;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * SQLite Export
+	 *
+	 * @param	array	Preferences
+	 * @return	mixed
+	 */
+	public function _backup($params = array())
+	{
+		// Not supported
+		return $this->db->display_error('db_unsuported_feature');
+	}
+
+}
+
+/* End of file sqlite3_utility.php */
+/* Location: ./system/database/drivers/sqlite3/sqlite3_utility.php */
\ No newline at end of file
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index bb4f009..f4eab8f 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -393,21 +393,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Escape the SQL Identifiers
-	 *
-	 * This function escapes column and table names
-	 *
-	 * @param	string
-	 * @return	string
-	 */
-	public function _escape_identifiers($item)
-	{
-		return $item;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * From Tables
 	 *
 	 * This function implicitly groups FROM tables so there is no confusion
@@ -429,23 +414,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Insert statement
-	 *
-	 * Generates a platform-specific insert string from the supplied data
-	 *
-	 * @param	string	the table name
-	 * @param	array	the insert keys
-	 * @param	array	the insert values
-	 * @return	string
-	 */
-	protected function _insert($table, $keys, $values)
-	{
-		return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Update statement
 	 *
 	 * Generates a platform-specific update string from the supplied data
@@ -473,15 +441,16 @@
 	 * Truncate statement
 	 *
 	 * Generates a platform-specific truncate string from the supplied data
-	 * If the database does not support the truncate() command
-	 * This function maps to "DELETE FROM table"
+	 *
+	 * If the database does not support the truncate() command,
+	 * then this method maps to 'DELETE FROM table'
 	 *
 	 * @param	string	the table name
 	 * @return	string
 	 */
 	protected function _truncate($table)
 	{
-		return "TRUNCATE ".$table;
+		return 'TRUNCATE TABLE '.$table;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php
index 0dc7b52..377dcf1 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_forge.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php
@@ -63,11 +63,12 @@
 	/**
 	 * Drop Table
 	 *
-	 * @return	bool
+	 * @param	string	table name
+	 * @return	string
 	 */
 	public function _drop_table($table)
 	{
-		return "DROP TABLE ".$this->db->_escape_identifiers($table);
+		return 'DROP TABLE '.$this->db->escape_identifiers($table);
 	}
 
 	// --------------------------------------------------------------------
@@ -91,7 +92,7 @@
 			$sql .= 'IF NOT EXISTS ';
 		}
 
-		$sql .= $this->db->_escape_identifiers($table)." (";
+		$sql .= $this->db->escape_identifiers($table).' (';
 		$current_field_count = 0;
 
 		foreach ($fields as $field => $attributes)
diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php
index 6e8a4de..3a373ef 100644
--- a/system/helpers/file_helper.php
+++ b/system/helpers/file_helper.php
@@ -121,11 +121,13 @@
  *
  * @param	string	path to file
  * @param	bool	whether to delete any directories found in the path
+ * @param	int
+ * @param	bool	whether to skip deleting .htaccess and index page files
  * @return	bool
  */
 if ( ! function_exists('delete_files'))
 {
-	function delete_files($path, $del_dir = FALSE, $level = 0)
+	function delete_files($path, $del_dir = FALSE, $level = 0, $htdocs = FALSE)
 	{
 		// Trim the trailing slash
 		$path = rtrim($path, DIRECTORY_SEPARATOR);
@@ -141,9 +143,9 @@
 			{
 				if (is_dir($path.DIRECTORY_SEPARATOR.$filename) && $filename[0] !== '.')
 				{
-					delete_files($path.DIRECTORY_SEPARATOR.$filename, $del_dir, $level + 1);
+					delete_files($path.DIRECTORY_SEPARATOR.$filename, $del_dir, $level + 1, $htdocs);
 				}
-				else
+				elseif ($htdocs === TRUE && ! preg_match('/^(\.htaccess|index\.(html|htm|php))$/', $filename))
 				{
 					@unlink($path.DIRECTORY_SEPARATOR.$filename);
 				}
diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php
index 1028c8f..4cd5f3d 100644
--- a/system/libraries/Cache/drivers/Cache_memcached.php
+++ b/system/libraries/Cache/drivers/Cache_memcached.php
@@ -189,17 +189,17 @@
 		{
 			if ( ! array_key_exists('hostname', $cache_server))
 			{
-				$cache_server['hostname'] = $this->_default_options['default_host'];
+				$cache_server['hostname'] = $this->_memcache_conf['default']['default_host'];
 			}
 
 			if ( ! array_key_exists('port', $cache_server))
 			{
-				$cache_server['port'] = $this->_default_options['default_port'];
+				$cache_server['port'] = $this->_memcache_conf['default']['default_port'];
 			}
 
 			if ( ! array_key_exists('weight', $cache_server))
 			{
-				$cache_server['weight'] = $this->_default_options['default_weight'];
+				$cache_server['weight'] = $this->_memcache_conf['default']['default_weight'];
 			}
 
 			if (get_class($this->_memcached) == 'Memcache')
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index 8f383c9..48c3bf3 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -407,11 +407,11 @@
 	 * @param	string
 	 * @return	object
 	 */
-	public function attach($filename, $disposition = '', $newname = NULL)
+	public function attach($filename, $disposition = '', $newname = NULL, $mime = '')
 	{
 		$this->_attach_name[] = array($filename, $newname);
-		$this->_attach_type[] = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION));
 		$this->_attach_disp[] = empty($disposition) ? 'attachment' : $disposition; // Can also be 'inline'  Not sure if it matters
+		$this->_attach_type[] = $mime;
 		return $this;
 	}
 
@@ -1049,29 +1049,39 @@
 			$filename = $this->_attach_name[$i][0];
 			$basename = (is_null($this->_attach_name[$i][1])) ? basename($filename) : $this->_attach_name[$i][1];
 			$ctype = $this->_attach_type[$i];
+			$file_content = '';
 
-			if ( ! file_exists($filename))
+			if ($this->_attach_type[$i] == '')
 			{
-				$this->_set_error_message('lang:email_attachment_missing', $filename);
-				return FALSE;
-			}
+				if ( ! file_exists($filename))
+				{
+					$this->_set_error_message('lang:email_attachment_missing', $filename);
+					return FALSE;
+				}
 
+				$file = filesize($filename) +1;
+
+				if ( ! $fp = fopen($filename, FOPEN_READ))
+				{
+					$this->_set_error_message('lang:email_attachment_unreadable', $filename);
+					return FALSE;
+				}
+
+				$ctype = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION));
+				$file_content = fread($fp, $file);
+				fclose($fp);
+			}
+			else
+			{
+				$file_content =& $this->_attach_content[$i];
+			}
 			$attachment[$z++] = "--".$this->_atc_boundary.$this->newline
 				. "Content-type: ".$ctype."; "
 				. "name=\"".$basename."\"".$this->newline
 				. "Content-Disposition: ".$this->_attach_disp[$i].";".$this->newline
 				. "Content-Transfer-Encoding: base64".$this->newline;
 
-			$file = filesize($filename) +1;
-
-			if ( ! $fp = fopen($filename, FOPEN_READ))
-			{
-				$this->_set_error_message('lang:email_attachment_unreadable', $filename);
-				return FALSE;
-			}
-
-			$attachment[$z++] = chunk_split(base64_encode(fread($fp, $file)));
-			fclose($fp);
+			$attachment[$z++] = chunk_split(base64_encode($file_content));
 		}
 
 		$body .= implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--";
diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php
index b29eb47..54b5bf7 100644
--- a/system/libraries/Encrypt.php
+++ b/system/libraries/Encrypt.php
@@ -38,15 +38,15 @@
  */
 class CI_Encrypt {
 
-	public $encryption_key	= '';
-	protected $_hash_type	= 'sha1';
-	protected $_mcrypt_exists = FALSE;
+	public $encryption_key		= '';
+	protected $_hash_type		= 'sha1';
+	protected $_mcrypt_exists	= FALSE;
 	protected $_mcrypt_cipher;
 	protected $_mcrypt_mode;
 
 	public function __construct()
 	{
-		$this->_mcrypt_exists = ( ! function_exists('mcrypt_encrypt')) ? FALSE : TRUE;
+		$this->_mcrypt_exists = function_exists('mcrypt_encrypt');
 		log_message('debug', 'Encrypt Class Initialized');
 	}
 
@@ -349,8 +349,8 @@
 	 *
 	 * Function description
 	 *
-	 * @param	type
-	 * @return	type
+	 * @param	string
+	 * @return	string
 	 */
 	protected function _remove_cipher_noise($data, $key)
 	{
@@ -382,8 +382,8 @@
 	/**
 	 * Set the Mcrypt Cipher
 	 *
-	 * @param	constant
-	 * @return	string
+	 * @param	int
+	 * @return	object
 	 */
 	public function set_cipher($cipher)
 	{
@@ -396,8 +396,8 @@
 	/**
 	 * Set the Mcrypt Mode
 	 *
-	 * @param	constant
-	 * @return	string
+	 * @param	int
+	 * @return	object
 	 */
 	public function set_mode($mode)
 	{
@@ -410,7 +410,7 @@
 	/**
 	 * Get Mcrypt cipher Value
 	 *
-	 * @return	string
+	 * @return	int
 	 */
 	protected function _get_cipher()
 	{
@@ -427,7 +427,7 @@
 	/**
 	 * Get Mcrypt Mode Value
 	 *
-	 * @return	string
+	 * @return	int
 	 */
 	protected function _get_mode()
 	{
@@ -464,7 +464,8 @@
 	{
 		return ($this->_hash_type === 'sha1') ? sha1($str) : md5($str);
 	}
+
 }
 
 /* End of file Encrypt.php */
-/* Location: ./system/libraries/Encrypt.php */
+/* Location: ./system/libraries/Encrypt.php */
\ No newline at end of file
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index 3e0c72e..22bc7dd 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -25,8 +25,6 @@
  * @filesource
  */
 
-// ------------------------------------------------------------------------
-
 /**
  * Form Validation Class
  *
@@ -39,15 +37,15 @@
 class CI_Form_validation {
 
 	protected $CI;
-	protected $_field_data			= array();
-	protected $_config_rules		= array();
-	protected $_error_array			= array();
-	protected $_error_messages		= array();
-	protected $_error_prefix		= '<p>';
-	protected $_error_suffix		= '</p>';
-	protected $error_string			= '';
-	protected $_safe_form_data		= FALSE;
-	protected $validation_data		= array();
+	protected $_field_data		= array();
+	protected $_config_rules	= array();
+	protected $_error_array		= array();
+	protected $_error_messages	= array();
+	protected $_error_prefix	= '<p>';
+	protected $_error_suffix	= '</p>';
+	protected $error_string		= '';
+	protected $_safe_form_data	= FALSE;
+	protected $validation_data	= array();
 
 	public function __construct($rules = array())
 	{
@@ -64,7 +62,7 @@
 			$this->_error_suffix = $rules['error_suffix'];
 			unset($rules['error_suffix']);
 		}
-		
+
 		// Validation rules can be stored in a config file.
 		$this->_config_rules = $rules;
 
@@ -90,7 +88,7 @@
 	 *
 	 * @param	mixed
 	 * @param	string
-	 * @return	void
+	 * @return	object
 	 */
 	public function set_rules($field, $label = '', $rules = '')
 	{
@@ -108,17 +106,18 @@
 			foreach ($field as $row)
 			{
 				// Houston, we have a problem...
-				if ( ! isset($row['field']) OR ! isset($row['rules']))
+				if ( ! isset($row['field'], $row['rules']))
 				{
 					continue;
 				}
 
 				// If the field label wasn't passed we use the field name
-				$label = ( ! isset($row['label'])) ? $row['field'] : $row['label'];
+				$label = isset($row['label']) ? $row['label'] : $row['field'];
 
 				// Here we go!
 				$this->set_rules($row['field'], $label, $row['rules']);
 			}
+
 			return $this;
 		}
 
@@ -198,12 +197,12 @@
 	/**
 	 * Set Error Message
 	 *
-	 * Lets users set their own error messages on the fly.  Note:  The key
-	 * name has to match the function name that it corresponds to.
+	 * Lets users set their own error messages on the fly. Note:
+	 * The key name has to match the function name that it corresponds to.
 	 *
+	 * @param	array
 	 * @param	string
-	 * @param	string
-	 * @return	string
+	 * @return	object
 	 */
 	public function set_message($lang, $val = '')
 	{
@@ -213,7 +212,6 @@
 		}
 
 		$this->_error_messages = array_merge($this->_error_messages, $lang);
-
 		return $this;
 	}
 
@@ -226,13 +224,12 @@
 	 *
 	 * @param	string
 	 * @param	string
-	 * @return	void
+	 * @return	object
 	 */
 	public function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
 	{
 		$this->_error_prefix = $prefix;
 		$this->_error_suffix = $suffix;
-
 		return $this;
 	}
 
@@ -244,11 +241,11 @@
 	 * Gets the error message associated with a particular field
 	 *
 	 * @param	string	the field name
-	 * @return	void
+	 * @return	string
 	 */
 	public function error($field = '', $prefix = '', $suffix = '')
 	{
-		if ( ! isset($this->_field_data[$field]['error']) OR $this->_field_data[$field]['error'] == '')
+		if (empty($this->_field_data[$field]['error']))
 		{
 			return '';
 		}
@@ -289,7 +286,7 @@
 	 *
 	 * @param	string
 	 * @param	string
-	 * @return	str
+	 * @return	string
 	 */
 	public function error_string($prefix = '', $suffix = '')
 	{
@@ -334,7 +331,7 @@
 	public function run($group = '')
 	{
 		// Do we even have any data to process?  Mm?
-		$validation_array = ( ! empty($this->validation_data)) ? $this->validation_data : $_POST;
+		$validation_array = empty($this->validation_data) ? $_POST : $this->validation_data;
 		if (count($validation_array) === 0)
 		{
 			return FALSE;
@@ -353,7 +350,7 @@
 			// Is there a validation rule for the particular URI being accessed?
 			$uri = ($group == '') ? trim($this->CI->uri->ruri_string(), '/') : $group;
 
-			if ($uri != '' AND isset($this->_config_rules[$uri]))
+			if ($uri != '' && isset($this->_config_rules[$uri]))
 			{
 				$this->set_rules($this->_config_rules[$uri]);
 			}
@@ -362,10 +359,10 @@
 				$this->set_rules($this->_config_rules);
 			}
 
-			// We're we able to set the rules correctly?
+			// Were we able to set the rules correctly?
 			if (count($this->_field_data) === 0)
 			{
-				log_message('debug', "Unable to find validation rules");
+				log_message('debug', 'Unable to find validation rules');
 				return FALSE;
 			}
 		}
@@ -379,17 +376,13 @@
 		{
 			// Fetch the data from the corresponding $_POST or validation array and cache it in the _field_data array.
 			// Depending on whether the field name is an array or a string will determine where we get it from.
-
 			if ($row['is_array'] === TRUE)
 			{
 				$this->_field_data[$field]['postdata'] = $this->_reduce_array($validation_array, $row['keys']);
 			}
-			else
+			elseif ( ! empty($validation_array[$field]))
 			{
-				if (isset($validation_array[$field]) AND $validation_array[$field] != "")
-				{
-					$this->_field_data[$field]['postdata'] = $validation_array[$field];
-				}
+				$this->_field_data[$field]['postdata'] = $validation_array[$field];
 			}
 
 			$this->_execute($row, explode('|', $row['rules']), $this->_field_data[$field]['postdata']);
@@ -397,7 +390,6 @@
 
 		// Did we end up with any errors?
 		$total_errors = count($this->_error_array);
-
 		if ($total_errors > 0)
 		{
 			$this->_safe_form_data = TRUE;
@@ -416,7 +408,7 @@
 	 *
 	 * @param	array
 	 * @param	array
-	 * @param	integer
+	 * @param	int
 	 * @return	mixed
 	 */
 	protected function _reduce_array($array, $keys, $i = 0)
@@ -434,7 +426,7 @@
 	/**
 	 * Re-populate the _POST array with our finalized and processed data
 	 *
-	 * @return	null
+	 * @return	void
 	 */
 	protected function _reset_post_array()
 	{
@@ -494,7 +486,7 @@
 	 * @param	array
 	 * @param	array
 	 * @param	mixed
-	 * @param	integer
+	 * @param	int
 	 * @return	mixed
 	 */
 	protected function _execute($row, $rules, $postdata = NULL, $cycles = 0)
@@ -511,17 +503,15 @@
 			return;
 		}
 
-		// --------------------------------------------------------------------
-
 		// If the field is blank, but NOT required, no further tests are necessary
 		$callback = FALSE;
-		if ( ! in_array('required', $rules) AND is_null($postdata))
+		if ( ! in_array('required', $rules) && is_null($postdata))
 		{
 			// Before we bail out, does the rule contain a callback?
-			if (preg_match("/(callback_\w+(\[.*?\])?)/", implode(' ', $rules), $match))
+			if (preg_match('/(callback_\w+(\[.*?\])?)/', implode(' ', $rules), $match))
 			{
 				$callback = TRUE;
-				$rules = (array('1' => $match[1]));
+				$rules = array(1 => $match[1]);
 			}
 			else
 			{
@@ -529,15 +519,13 @@
 			}
 		}
 
-		// --------------------------------------------------------------------
-
 		// Isset Test. Typically this rule will only apply to checkboxes.
-		if (is_null($postdata) AND $callback === FALSE)
+		if (is_null($postdata) && $callback === FALSE)
 		{
 			if (in_array('isset', $rules, TRUE) OR in_array('required', $rules))
 			{
 				// Set the message type
-				$type = (in_array('required', $rules)) ? 'required' : 'isset';
+				$type = in_array('required', $rules) ? 'required' : 'isset';
 
 				if ( ! isset($this->_error_messages[$type]))
 				{
@@ -569,13 +557,13 @@
 		// --------------------------------------------------------------------
 
 		// Cycle through each rule and run it
-		foreach ($rules As $rule)
+		foreach ($rules as $rule)
 		{
 			$_in_array = FALSE;
 
 			// We set the $postdata variable with the current data in our master array so that
 			// each cycle of the loop is dealing with the processed data from the last cycle
-			if ($row['is_array'] == TRUE AND is_array($this->_field_data[$row['field']]['postdata']))
+			if ($row['is_array'] == TRUE && is_array($this->_field_data[$row['field']]['postdata']))
 			{
 				// We shouldn't need this safety, but just in case there isn't an array index
 				// associated with this cycle we'll bail out
@@ -592,11 +580,9 @@
 				$postdata = $this->_field_data[$row['field']]['postdata'];
 			}
 
-			// --------------------------------------------------------------------
-
 			// Is the rule a callback?
 			$callback = FALSE;
-			if (substr($rule, 0, 9) == 'callback_')
+			if (strpos($rule, 'callback_') === 0)
 			{
 				$rule = substr($rule, 9);
 				$callback = TRUE;
@@ -605,7 +591,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];
@@ -616,68 +602,69 @@
 			{
 				if ( ! method_exists($this->CI, $rule))
 				{
-					continue;
+					log_message('debug', 'Unable to find callback validation rule: '.$rule);
+					$result = FALSE;
 				}
-
-				// Run the function and grab the result
-				$result = $this->CI->$rule($postdata, $param);
+				else
+				{
+					// Run the function and grab the result
+					$result = $this->CI->$rule($postdata, $param);
+				}
 
 				// Re-assign the result to the master data array
 				if ($_in_array === TRUE)
 				{
-					$this->_field_data[$row['field']]['postdata'][$cycles] = (is_bool($result)) ? $postdata : $result;
+					$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
 				}
 				else
 				{
-					$this->_field_data[$row['field']]['postdata'] = (is_bool($result)) ? $postdata : $result;
+					$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
 				}
 
 				// If the field isn't required and we just processed a callback we'll move on...
-				if ( ! in_array('required', $rules, TRUE) AND $result !== FALSE)
+				if ( ! in_array('required', $rules, TRUE) && $result !== FALSE)
 				{
 					continue;
 				}
 			}
+			elseif ( ! method_exists($this, $rule))
+			{
+				// If our own wrapper function doesn't exist we see if a native PHP function does.
+				// Users can use any native PHP function call that has one param.
+				if (function_exists($rule))
+				{
+					$result = ($param !== FALSE) ? $rule($postdata, $param) : $rule($postdata);
+
+					if ($_in_array === TRUE)
+					{
+						$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
+					}
+					else
+					{
+						$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
+					}
+				}
+				else
+				{
+					log_message('debug', 'Unable to find validation rule: '.$rule);
+					$result = FALSE;
+				}
+			}
 			else
 			{
-				if ( ! method_exists($this, $rule))
-				{
-					// If our own wrapper function doesn't exist we see if a native PHP function does.
-					// Users can use any native PHP function call that has one param.
-					if (function_exists($rule))
-					{
-						$result = $rule($postdata);
-
-						if ($_in_array === TRUE)
-						{
-							$this->_field_data[$row['field']]['postdata'][$cycles] = (is_bool($result)) ? $postdata : $result;
-						}
-						else
-						{
-							$this->_field_data[$row['field']]['postdata'] = (is_bool($result)) ? $postdata : $result;
-						}
-					}
-					else
-					{
-						log_message('debug', "Unable to find validation rule: ".$rule);
-					}
-
-					continue;
-				}
-
 				$result = $this->$rule($postdata, $param);
 
 				if ($_in_array === TRUE)
 				{
-					$this->_field_data[$row['field']]['postdata'][$cycles] = (is_bool($result)) ? $postdata : $result;
+					$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
 				}
 				else
 				{
-					$this->_field_data[$row['field']]['postdata'] = (is_bool($result)) ? $postdata : $result;
+					$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
 				}
 			}
 
-			// Did the rule test negatively?  If so, grab the error.
+			// Did the rule test negatively? If so, grab the error.
 			if ($result === FALSE)
 			{
 				if ( ! isset($this->_error_messages[$rule]))
@@ -693,7 +680,7 @@
 				}
 
 				// Is the parameter we are inserting into the error message the name
-				// of another field?  If so we need to grab its "field label"
+				// of another field? If so we need to grab its "field label"
 				if (isset($this->_field_data[$param], $this->_field_data[$param]['label']))
 				{
 					$param = $this->_translate_fieldname($this->_field_data[$param]['label']);
@@ -727,7 +714,7 @@
 	{
 		// Do we need to translate the field name?
 		// We look for the prefix lang: to determine this
-		if (substr($fieldname, 0, 5) === 'lang:')
+		if (strpos($fieldname, 'lang:') === 0)
 		{
 			// Grab the variable
 			$line = substr($fieldname, 5);
@@ -791,7 +778,6 @@
 		}
 
 		$field = $this->_field_data[$field]['postdata'];
-
 		if (is_array($field))
 		{
 			if ( ! in_array($value, $field))
@@ -827,7 +813,6 @@
 		}
 
 		$field = $this->_field_data[$field]['postdata'];
-
 		if (is_array($field))
 		{
 			if ( ! in_array($value, $field))
@@ -835,12 +820,9 @@
 				return '';
 			}
 		}
-		else
+		elseif (($field == '' OR $value == '') OR ($field != $value))
 		{
-			if (($field == '' OR $value == '') OR ($field != $value))
-			{
-				return '';
-			}
+			return '';
 		}
 
 		return ' checked="checked"';
@@ -874,7 +856,7 @@
 	 */
 	public function required($str)
 	{
-		return ( ! is_array($str)) ? (trim($str) !== '') : ( ! empty($str));
+		return is_array($str) ? (bool) count($str) : (trim($str) !== '');
 	}
 
 	// --------------------------------------------------------------------
@@ -883,7 +865,7 @@
 	 * Performs a Regular Expression match test.
 	 *
 	 * @param	string
-	 * @param	regex
+	 * @param	string	regex
 	 * @return	bool
 	 */
 	public function regex_match($str, $regex)
@@ -897,12 +879,12 @@
 	 * Match one field to another
 	 *
 	 * @param	string
-	 * @param	field
+	 * @param	string	field
 	 * @return	bool
 	 */
 	public function matches($str, $field)
 	{
-		$validation_array = ( ! empty($this->validation_data)) ? $this->validation_data : $_POST;
+		$validation_array = empty($this->validation_data) ? $_POST : $this->validation_data;
 		if ( ! isset($validation_array[$field]))
 		{
 			return FALSE;
@@ -920,7 +902,7 @@
 	 * in the specified database field.
 	 *
 	 * @param	string
-	 * @param	field
+	 * @param	string	field
 	 * @return	bool
 	 */
 	public function is_unique($str, $field)
@@ -940,7 +922,7 @@
 	 * Minimum Length
 	 *
 	 * @param	string
-	 * @param	value
+	 * @param	int
 	 * @return	bool
 	 */
 	public function min_length($str, $val)
@@ -950,12 +932,9 @@
 			return FALSE;
 		}
 
-		if (MB_ENABLED === TRUE)
-		{
-			return ! (mb_strlen($str) < $val);
-		}
-
-		return ! (strlen($str) < $val);
+		return (MB_ENABLED === TRUE)
+			? ($val <= mb_strlen($str))
+			: ($val <= strlen(str));
 	}
 
 	// --------------------------------------------------------------------
@@ -964,7 +943,7 @@
 	 * Max Length
 	 *
 	 * @param	string
-	 * @param	value
+	 * @param	int
 	 * @return	bool
 	 */
 	public function max_length($str, $val)
@@ -974,12 +953,9 @@
 			return FALSE;
 		}
 
-		if (MB_ENABLED === TRUE)
-		{
-			return ! (mb_strlen($str) > $val);
-		}
-
-		return ! (strlen($str) > $val);
+		return (MB_ENABLED === TRUE)
+			? ($val >= mb_strlen($str))
+			: ($val >= strlen($str));
 	}
 
 	// --------------------------------------------------------------------
@@ -988,7 +964,7 @@
 	 * Exact Length
 	 *
 	 * @param	string
-	 * @param	value
+	 * @param	int
 	 * @return	bool
 	 */
 	public function exact_length($str, $val)
@@ -998,12 +974,9 @@
 			return FALSE;
 		}
 
-		if (MB_ENABLED === TRUE)
-		{
-			return (mb_strlen($str) == $val);
-		}
-
-		return (strlen($str) == $val);
+		return (MB_ENABLED === TRUE)
+			? (mb_strlen($str) == $val)
+			: (strlen($str) == $val);
 	}
 
 	// --------------------------------------------------------------------
@@ -1114,19 +1087,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Is Numeric
-	 *
-	 * @param	string
-	 * @return	bool
-	 */
-	public function is_numeric($str)
-	{
-		return is_numeric($str);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Integer
 	 *
 	 * @param	string
@@ -1160,11 +1120,7 @@
 	 */
 	public function greater_than($str, $min)
 	{
-		if ( ! is_numeric($str))
-		{
-			return FALSE;
-		}
-		return $str > $min;
+		return is_numeric($str) ? ($str > $min) : FALSE;
 	}
 
 	// --------------------------------------------------------------------
@@ -1177,11 +1133,7 @@
 	 */
 	public function greater_than_equal_to($str, $min)
 	{
-		if ( ! is_numeric($str))
-		{
-			return FALSE;
-		}
-		return $str >= $min;
+		return is_numeric($str) ? ($str >= $min) : FALSE;
 	}
 
 	// --------------------------------------------------------------------
@@ -1194,11 +1146,7 @@
 	 */
 	public function less_than($str, $max)
 	{
-		if ( ! is_numeric($str))
-		{
-			return FALSE;
-		}
-		return $str < $max;
+		return is_numeric($str) ? ($str < $max) : FALSE;
 	}
 
 	// --------------------------------------------------------------------
@@ -1211,11 +1159,7 @@
 	 */
 	public function less_than_equal_to($str, $max)
 	{
-		if ( ! is_numeric($str))
-		{
-			return FALSE;
-		}
-		return $str <= $max;
+		return is_numeric($str) ? ($str <= $max) : FALSE;
 	}
 
 	// --------------------------------------------------------------------
@@ -1301,14 +1245,14 @@
 	 */
 	public function prep_url($str = '')
 	{
-		if ($str == 'http://' OR $str == '')
+		if ($str === 'http://' OR $str == '')
 		{
 			return '';
 		}
 
-		if (substr($str, 0, 7) !== 'http://' && substr($str, 0, 8) !== 'https://')
+		if (strpos($str, 'http://') !== 0 && strpos($str, 'https://') !== 0)
 		{
-			$str = 'http://'.$str;
+			return 'http://'.$str;
 		}
 
 		return $str;
@@ -1375,4 +1319,4 @@
 }
 
 /* End of file Form_validation.php */
-/* Location: ./system/libraries/Form_validation.php */
+/* Location: ./system/libraries/Form_validation.php */
\ No newline at end of file
diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php
index 86b77bf..1ab8b23 100644
--- a/system/libraries/Image_lib.php
+++ b/system/libraries/Image_lib.php
@@ -251,7 +251,7 @@
 		}
 		else
 		{
-			if (strpos($this->new_image, '/') === FALSE AND strpos($this->new_image, '\\') === FALSE)
+			if (strpos($this->new_image, '/') === FALSE && strpos($this->new_image, '\\') === FALSE)
 			{
 				$full_dest_path = str_replace('\\', '/', realpath($this->new_image));
 			}
@@ -1462,4 +1462,4 @@
 }
 
 /* End of file Image_lib.php */
-/* Location: ./system/libraries/Image_lib.php */
+/* Location: ./system/libraries/Image_lib.php */
\ No newline at end of file
diff --git a/system/libraries/Javascript.php b/system/libraries/Javascript.php
index 9ba9300..629a3ad 100644
--- a/system/libraries/Javascript.php
+++ b/system/libraries/Javascript.php
@@ -25,8 +25,6 @@
  * @filesource
  */
 
-// ------------------------------------------------------------------------
-
 /**
  * Javascript Class
  *
@@ -46,7 +44,7 @@
 
 		foreach ($defaults as $key => $val)
 		{
-			if (isset($params[$key]) && $params[$key] !== "")
+			if (isset($params[$key]) && $params[$key] !== '')
 			{
 				$defaults[$key] = $params[$key];
 			}
@@ -61,7 +59,7 @@
 		// make js to refer to current library
 		$this->js =& $this->CI->$js_library_driver;
 
-		log_message('debug', "Javascript Class Initialized and loaded.  Driver used: $js_library_driver");
+		log_message('debug', 'Javascript Class Initialized and loaded. Driver used: '.$js_library_driver);
 	}
 
 	// --------------------------------------------------------------------
@@ -107,7 +105,7 @@
 	 *
 	 * @param	string	The element to attach the event to
 	 * @param	string	The code to execute
-	 * @param	boolean	whether or not to return false
+	 * @param	bool	whether or not to return false
 	 * @return	string
 	 */
 	public function click($element = 'this', $js = '', $ret_false = TRUE)
@@ -375,7 +373,6 @@
 	// Effects
 	// --------------------------------------------------------------------
 
-
 	/**
 	 * Add Class
 	 *
@@ -618,12 +615,9 @@
 		{
 			$this->_javascript_location = $external_file;
 		}
-		else
+		elseif ($this->CI->config->item('javascript_location') != '')
 		{
-			if ($this->CI->config->item('javascript_location') != '')
-			{
-				$this->_javascript_location = $this->CI->config->item('javascript_location');
-			}
+			$this->_javascript_location = $this->CI->config->item('javascript_location');
 		}
 
 		if ($relative === TRUE OR strncmp($external_file, 'http://', 7) === 0 OR strncmp($external_file, 'https://', 8) === 0)
@@ -650,13 +644,13 @@
 	 * Outputs a <script> tag
 	 *
 	 * @param	string	The element to attach the event to
-	 * @param	boolean	If a CDATA section should be added
+	 * @param	bool	If a CDATA section should be added
 	 * @return	string
 	 */
 	public function inline($script, $cdata = TRUE)
 	{
 		return $this->_open_script()
-			. ($cdata ? "\n// <![CDATA[\n{$script}\n// ]]>\n" : "\n{$script}\n")
+			. ($cdata ? "\n// <![CDATA[\n".$script."\n// ]]>\n" : "\n".$script."\n")
 			. $this->_close_script();
 	}
 
@@ -673,7 +667,7 @@
 	protected function _open_script($src = '')
 	{
 		return '<script type="text/javascript" charset="'.strtolower($this->CI->config->item('charset')).'"'
-			. ($src == '' ? '>' : ' src="'.$src.'">');
+			.($src == '' ? '>' : ' src="'.$src.'">');
 	}
 
 	// --------------------------------------------------------------------
@@ -688,15 +682,12 @@
 	 */
 	protected function _close_script($extra = "\n")
 	{
-		return "</script>$extra";
+		return '</script>'.$extra;
 	}
 
-
-	// --------------------------------------------------------------------
 	// --------------------------------------------------------------------
 	// AJAX-Y STUFF - still a testbed
 	// --------------------------------------------------------------------
-	// --------------------------------------------------------------------
 
 	/**
 	 * Update
@@ -751,9 +742,9 @@
 		$json = array();
 		$_is_assoc = TRUE;
 
-		if ( ! is_array($json_result) AND empty($json_result))
+		if ( ! is_array($json_result) && empty($json_result))
 		{
-			show_error("Generate JSON Failed - Illegal key, value pair.");
+			show_error('Generate JSON Failed - Illegal key, value pair.');
 		}
 		elseif ($match_array_type)
 		{
@@ -774,7 +765,7 @@
 
 		$json = implode(',', $json);
 
-		return $_is_assoc ? "{".$json."}" : "[".$json."]";
+		return $_is_assoc ? '{'.$json.'}' : '['.$json.']';
 
 	}
 
@@ -785,8 +776,8 @@
 	 *
 	 * Checks for an associative array
 	 *
-	 * @param	type
-	 * @return	type
+	 * @param	array
+	 * @return	bool
 	 */
 	protected function _is_associative_array($arr)
 	{
@@ -808,8 +799,8 @@
 	 *
 	 * Ensures a standard json value and escapes values
 	 *
-	 * @param	type
-	 * @return	type
+	 * @param	mixed
+	 * @return	string
 	 */
 	protected function _prep_args($result, $is_key = FALSE)
 	{
@@ -831,9 +822,7 @@
 		}
 	}
 
-	// --------------------------------------------------------------------
 }
-// END Javascript Class
 
 /* End of file Javascript.php */
-/* Location: ./system/libraries/Javascript.php */
+/* Location: ./system/libraries/Javascript.php */
\ No newline at end of file
diff --git a/system/libraries/Log.php b/system/libraries/Log.php
index 955277a..66f9ebf 100644
--- a/system/libraries/Log.php
+++ b/system/libraries/Log.php
@@ -25,8 +25,6 @@
  * @filesource
  */
 
-// ------------------------------------------------------------------------
-
 /**
  * Logging Class
  *
@@ -43,12 +41,9 @@
 	protected $_threshold_max	= 0;
 	protected $_threshold_array	= array();
 	protected $_date_fmt		= 'Y-m-d H:i:s';
-	protected $_enabled			= TRUE;
-	protected $_levels			= array('ERROR' => 1, 'DEBUG' => 2,  'INFO' => 3, 'ALL' => 4);
+	protected $_enabled		= TRUE;
+	protected $_levels		= array('ERROR' => 1, 'DEBUG' => 2,  'INFO' => 3, 'ALL' => 4);
 
-	/**
-	 * Constructor
-	 */
 	public function __construct()
 	{
 		$config =& get_config();
@@ -98,7 +93,7 @@
 		$level = strtoupper($level);
 
 		if (( ! isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold))
-			AND ! isset($this->_threshold_array[$this->_levels[$level]]))
+			&& ! isset($this->_threshold_array[$this->_levels[$level]]))
 		{
 			return FALSE;
 		}
@@ -125,15 +120,15 @@
 		flock($fp, LOCK_UN);
 		fclose($fp);
 
-		if (isset($newfile) AND $newfile === TRUE)
+		if (isset($newfile) && $newfile === TRUE)
 		{
 			@chmod($filepath, FILE_WRITE_MODE);
 		}
+
 		return TRUE;
 	}
 
 }
-// END Log Class
 
 /* End of file Log.php */
-/* Location: ./system/libraries/Log.php */
+/* Location: ./system/libraries/Log.php */
\ No newline at end of file
diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php
index d84e5d3..6320ab5 100644
--- a/system/libraries/Profiler.php
+++ b/system/libraries/Profiler.php
@@ -25,8 +25,6 @@
  * @filesource
  */
 
-// ------------------------------------------------------------------------
-
 /**
  * CodeIgniter Profiler Class
  *
@@ -45,24 +43,22 @@
 class CI_Profiler {
 
 	protected $_available_sections = array(
-										'benchmarks',
-										'get',
-										'memory_usage',
-										'post',
-										'uri_string',
-										'controller_info',
-										'queries',
-										'http_headers',
-										'session_data',
-										'config'
-										);
+						'benchmarks',
+						'get',
+						'memory_usage',
+						'post',
+						'uri_string',
+						'controller_info',
+						'queries',
+						'http_headers',
+						'session_data',
+						'config'
+					);
 
 	protected $_query_toggle_count = 25;
 
 	protected $CI;
 
-	// --------------------------------------------------------------------
-
 	public function __construct($config = array())
 	{
 		$this->CI =& get_instance();
@@ -102,7 +98,7 @@
 		{
 			if (in_array($method, $this->_available_sections))
 			{
-				$this->_compile_{$method} = ($enable !== FALSE) ? TRUE : FALSE;
+				$this->_compile_{$method} = ($enable !== FALSE);
 			}
 		}
 	}
@@ -127,7 +123,7 @@
 			// We match the "end" marker so that the list ends
 			// up in the order that it was defined
 			if (preg_match('/(.+?)_end/i', $key, $match)
-				AND isset($this->CI->benchmark->marker[$match[1].'_end'], $this->CI->benchmark->marker[$match[1].'_start']))
+				&& isset($this->CI->benchmark->marker[$match[1].'_end'], $this->CI->benchmark->marker[$match[1].'_start']))
 			{
 				$profile[$match[1]] = $this->CI->benchmark->elapsed_time($match[1].'_start', $key);
 			}
@@ -135,18 +131,20 @@
 
 		// Build a table containing the profile data.
 		// Note: At some point we should turn this into a template that can
-		// be modified.  We also might want to make this data available to be logged
+		// be modified. We also might want to make this data available to be logged
 
 		$output = "\n\n"
-			. '<fieldset id="ci_profiler_benchmarks" style="border:1px solid #900;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">'
-			. "\n"
-			. '<legend style="color:#900;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_benchmarks').'&nbsp;&nbsp;</legend>'
-			. "\n\n\n<table style='width:100%'>\n";
+			.'<fieldset id="ci_profiler_benchmarks" style="border:1px solid #900;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
+			."\n"
+			.'<legend style="color:#900;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_benchmarks')."&nbsp;&nbsp;</legend>"
+			."\n\n\n<table style=\"width:100%;\">\n";
 
 		foreach ($profile as $key => $val)
 		{
 			$key = ucwords(str_replace(array('_', '-'), ' ', $key));
-			$output .= "<tr><td style='padding:5px;width:50%;color:#000;font-weight:bold;background-color:#ddd;'>".$key."&nbsp;&nbsp;</td><td style='padding:5px;width:50%;color:#900;font-weight:normal;background-color:#ddd;'>".$val."</td></tr>\n";
+			$output .= '<tr><td style="padding:5px;width:50%;color:#000;font-weight:bold;background-color:#ddd;">'
+					.$key.'&nbsp;&nbsp;</td><td style="padding:5px;width:50%;color:#900;font-weight:normal;background-color:#ddd;">'
+					.$val."</td></tr>\n";
 		}
 
 		return $output."</table>\n</fieldset>";
@@ -166,7 +164,7 @@
 		// Let's determine which databases are currently connected to
 		foreach (get_object_vars($this->CI) as $CI_object)
 		{
-			if (is_object($CI_object) && is_subclass_of(get_class($CI_object), 'CI_DB') )
+			if (is_object($CI_object) && is_subclass_of(get_class($CI_object), 'CI_DB'))
 			{
 				$dbs[] = $CI_object;
 			}
@@ -175,13 +173,13 @@
 		if (count($dbs) === 0)
 		{
 			return "\n\n"
-				. '<fieldset id="ci_profiler_queries" style="border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
-				. "\n"
-				. '<legend style="color:#0000FF;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries').'&nbsp;&nbsp;</legend>'
-				. "\n\n\n<table style='border:none; width:100%;'>\n"
-				. '<tr><td style="width:100%;color:#0000FF;font-weight:normal;background-color:#eee;padding:5px;">'
-				. $this->CI->lang->line('profiler_no_db')
-				. "</td></tr>\n</table>\n</fieldset>";
+				.'<fieldset id="ci_profiler_queries" style="border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
+				."\n"
+				.'<legend style="color:#0000FF;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries').'&nbsp;&nbsp;</legend>'
+				."\n\n\n<table style=\"border:none; width:100%;\">\n"
+				.'<tr><td style="width:100%;color:#0000FF;font-weight:normal;background-color:#eee;padding:5px;">'
+				.$this->CI->lang->line('profiler_no_db')
+				."</td></tr>\n</table>\n</fieldset>";
 		}
 
 		// Load the text helper so we can highlight the SQL
@@ -191,7 +189,6 @@
 		$highlight = array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'AND', 'LEFT&nbsp;JOIN', 'ORDER&nbsp;BY', 'GROUP&nbsp;BY', 'LIMIT', 'INSERT', 'INTO', 'VALUES', 'UPDATE', 'OR&nbsp;', 'HAVING', 'OFFSET', 'NOT&nbsp;IN', 'IN', 'LIKE', 'NOT&nbsp;LIKE', 'COUNT', 'MAX', 'MIN', 'ON', 'AS', 'AVG', 'SUM', '(', ')');
 
 		$output  = "\n\n";
-
 		$count = 0;
 
 		foreach ($dbs as $db)
@@ -205,21 +202,23 @@
 				$show_hide_js = '(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_queries_db_'.$count.'\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show').'</span>)';
 			}
 
-			$output .= '<fieldset style="border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">'
-				. "\n"
-				. '<legend style="color:#0000FF;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_database').':&nbsp; '.$db->database.'&nbsp;&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries').': '.count($db->queries).'&nbsp;&nbsp;'.$show_hide_js.'</legend>'
-				. "\n\n\n<table style='width:100%;{$hide_queries}' id='ci_profiler_queries_db_{$count}'>\n";
+			$output .= '<fieldset style="border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
+				."\n"
+				.'<legend style="color:#0000FF;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_database')
+				.':&nbsp; '.$db->database.'&nbsp;&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries')
+				.': '.count($db->queries).'&nbsp;&nbsp;'.$show_hide_js."</legend>\n\n\n"
+				.'<table style="width:100%;'.$hide_queries.'" id="ci_profiler_queries_db_'.$count."\">\n";
 
 			if (count($db->queries) === 0)
 			{
-				$output .= "<tr><td style='width:100%;color:#0000FF;font-weight:normal;background-color:#eee;padding:5px;'>".$this->CI->lang->line('profiler_no_queries')."</td></tr>\n";
+				$output .= '<tr><td style="width:100%;color:#0000FF;font-weight:normal;background-color:#eee;padding:5px;">'
+						.$this->CI->lang->line('profiler_no_queries')."</td></tr>\n";
 			}
 			else
 			{
 				foreach ($db->queries as $key => $val)
 				{
 					$time = number_format($db->query_times[$key], 4);
-
 					$val = highlight_code($val, ENT_QUOTES);
 
 					foreach ($highlight as $bold)
@@ -227,18 +226,18 @@
 						$val = str_replace($bold, '<strong>'.$bold.'</strong>', $val);
 					}
 
-					$output .= "<tr><td style='padding:5px; vertical-align: top;width:1%;color:#900;font-weight:normal;background-color:#ddd;'>".$time."&nbsp;&nbsp;</td><td style='padding:5px; color:#000;font-weight:normal;background-color:#ddd;'>".$val."</td></tr>\n";
+					$output .= '<tr><td style="padding:5px;vertical-align:top;width:1%;color:#900;font-weight:normal;background-color:#ddd;">'
+							.$time.'&nbsp;&nbsp;</td><td style="padding:5px;color:#000;font-weight:normal;background-color:#ddd;">'
+							.$val."</td></tr>\n";
 				}
 			}
 
 			$output .= "</table>\n</fieldset>";
-
 		}
 
 		return $output;
 	}
 
-
 	// --------------------------------------------------------------------
 
 	/**
@@ -248,19 +247,18 @@
 	 */
 	protected function _compile_get()
 	{
-		$output  = "\n\n"
-			. '<fieldset id="ci_profiler_get" style="border:1px solid #cd6e00;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">'
-			. "\n"
-			. '<legend style="color:#cd6e00;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_get_data').'&nbsp;&nbsp;</legend>'
-			. "\n";
+		$output = "\n\n"
+			.'<fieldset id="ci_profiler_get" style="border:1px solid #cd6e00;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
+			."\n"
+			.'<legend style="color:#cd6e00;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_get_data')."&nbsp;&nbsp;</legend>\n";
 
 		if (count($_GET) === 0)
 		{
-			$output .= "<div style='color:#cd6e00;font-weight:normal;padding:4px 0 4px 0'>".$this->CI->lang->line('profiler_no_get')."</div>";
+			$output .= '<div style="color:#cd6e00;font-weight:normal;padding:4px 0 4px 0;">'.$this->CI->lang->line('profiler_no_get').'</div>';
 		}
 		else
 		{
-			$output .= "\n\n<table style='width:100%; border:none'>\n";
+			$output .= "\n\n<table style=\"width:100%;border:none;\">\n";
 
 			foreach ($_GET as $key => $val)
 			{
@@ -269,9 +267,10 @@
 					$key = "'".$key."'";
 				}
 
-				$output .= "<tr><td style='width:50%;color:#000;background-color:#ddd;padding:5px'>&#36;_GET[".$key."]&nbsp;&nbsp; </td><td style='width:50%;padding:5px;color:#cd6e00;font-weight:normal;background-color:#ddd;'>"
-					. ((is_array($val) OR is_object($val)) ? "<pre>" . htmlspecialchars(stripslashes(print_r($val, true))) . "</pre>" : htmlspecialchars(stripslashes($val)))
-					. "</td></tr>\n";
+				$output .= '<tr><td style="width:50%;color:#000;background-color:#ddd;padding:5px;">&#36;_GET['
+					.$key.']&nbsp;&nbsp; </td><td style="width:50%;padding:5px;color:#cd6e00;font-weight:normal;background-color:#ddd;">'
+					.((is_array($val) OR is_object($val)) ? '<pre>'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'</pre>' : htmlspecialchars(stripslashes($val)))
+					."</td></tr>\n";
 			}
 
 			$output .= "</table>\n";
@@ -290,18 +289,17 @@
 	protected function _compile_post()
 	{
 		$output = "\n\n"
-			. '<fieldset id="ci_profiler_post" style="border:1px solid #009900;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">'
-			. "\n"
-			. '<legend style="color:#009900;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_post_data').'&nbsp;&nbsp;</legend>'
-			. "\n";
+			.'<fieldset id="ci_profiler_post" style="border:1px solid #009900;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
+			."\n"
+			.'<legend style="color:#009900;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_post_data')."&nbsp;&nbsp;</legend>\n";
 
 		if (count($_POST) == 0)
 		{
-			$output .= "<div style='color:#009900;font-weight:normal;padding:4px 0 4px 0'>".$this->CI->lang->line('profiler_no_post')."</div>";
+			$output .= '<div style="color:#009900;font-weight:normal;padding:4px 0 4px 0;">'.$this->CI->lang->line('profiler_no_post').'</div>';
 		}
 		else
 		{
-			$output .= "\n\n<table style='width:100%'>\n";
+			$output .= "\n\n<table style=\"width:100%;\">\n";
 
 			foreach ($_POST as $key => $val)
 			{
@@ -310,15 +308,18 @@
 					$key = "'".$key."'";
 				}
 
-				$output .= "<tr><td style='width:50%;padding:5px;color:#000;background-color:#ddd;'>&#36;_POST[".$key."]&nbsp;&nbsp; </td><td style='width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;'>";
+				$output .= '<tr><td style="width:50%;padding:5px;color:#000;background-color:#ddd;">&#36;_POST['
+					.$key.']&nbsp;&nbsp; </td><td style="width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;">';
+
 				if (is_array($val) OR is_object($val))
 				{
-					$output .= "<pre>" . htmlspecialchars(stripslashes(print_r($val, TRUE))) . "</pre>";
+					$output .= '<pre>'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'</pre>';
 				}
 				else
 				{
 					$output .= htmlspecialchars(stripslashes($val));
 				}
+
 				$output .= "</td></tr>\n";
 			}
 
@@ -338,12 +339,12 @@
 	protected function _compile_uri_string()
 	{
 		return "\n\n"
-			. '<fieldset id="ci_profiler_uri_string" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">'
-			. "\n"
-			. '<legend style="color:#000;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_uri_string').'&nbsp;&nbsp;</legend>'
-			. "\n<div style='color:#000;font-weight:normal;padding:4px 0 4px 0'>"
-			. ($this->CI->uri->uri_string == '' ? $this->CI->lang->line('profiler_no_uri') : $this->CI->uri->uri_string)
-			. '</div></fieldset>';
+			.'<fieldset id="ci_profiler_uri_string" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
+			."\n"
+			.'<legend style="color:#000;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_uri_string')."&nbsp;&nbsp;</legend>\n"
+			.'<div style="color:#000;font-weight:normal;padding:4px 0 4px 0;">'
+			.($this->CI->uri->uri_string == '' ? $this->CI->lang->line('profiler_no_uri') : $this->CI->uri->uri_string)
+			.'</div></fieldset>';
 	}
 
 	// --------------------------------------------------------------------
@@ -356,11 +357,11 @@
 	protected function _compile_controller_info()
 	{
 		return "\n\n"
-			. '<fieldset id="ci_profiler_controller_info" style="border:1px solid #995300;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">'
-			. "\n"
-			. '<legend style="color:#995300;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_controller_info').'&nbsp;&nbsp;</legend>'
-			. "\n<div style='color:#995300;font-weight:normal;padding:4px 0 4px 0'>".$this->CI->router->fetch_class().'/'.$this->CI->router->fetch_method()
-			. '</div></fieldset>';
+			.'<fieldset id="ci_profiler_controller_info" style="border:1px solid #995300;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
+			."\n"
+			.'<legend style="color:#995300;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_controller_info')."&nbsp;&nbsp;</legend>\n"
+			.'<div style="color:#995300;font-weight:normal;padding:4px 0 4px 0;">'.$this->CI->router->fetch_class().'/'.$this->CI->router->fetch_method()
+			.'</div></fieldset>';
 	}
 
 	// --------------------------------------------------------------------
@@ -375,12 +376,12 @@
 	protected function _compile_memory_usage()
 	{
 		return "\n\n"
-			. '<fieldset id="ci_profiler_memory_usage" style="border:1px solid #5a0099;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">'
-			. "\n"
-			. '<legend style="color:#5a0099;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_memory_usage').'&nbsp;&nbsp;</legend>'
-			. "\n<div style='color:#5a0099;font-weight:normal;padding:4px 0 4px 0'>"
-			. ((function_exists('memory_get_usage') && ($usage = memory_get_usage()) != '') ? number_format($usage).' bytes' : $this->CI->lang->line('profiler_no_memory'))
-			. '</div></fieldset>';
+			.'<fieldset id="ci_profiler_memory_usage" style="border:1px solid #5a0099;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
+			."\n"
+			.'<legend style="color:#5a0099;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_memory_usage')."&nbsp;&nbsp;</legend>\n"
+			.'<div style="color:#5a0099;font-weight:normal;padding:4px 0 4px 0;">'
+			.((function_exists('memory_get_usage') && ($usage = memory_get_usage()) != '') ? number_format($usage).' bytes' : $this->CI->lang->line('profiler_no_memory'))
+			.'</div></fieldset>';
 	}
 
 	// --------------------------------------------------------------------
@@ -395,15 +396,17 @@
 	protected function _compile_http_headers()
 	{
 		$output = "\n\n"
-			. '<fieldset id="ci_profiler_http_headers" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">'
-			. "\n"
-			. '<legend style="color:#000;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_headers').'&nbsp;&nbsp;(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_httpheaders_table\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show').'</span>)</legend>'
-			. "\n\n\n<table style='width:100%;display:none' id='ci_profiler_httpheaders_table'>\n";
+			.'<fieldset id="ci_profiler_http_headers" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
+			."\n"
+			.'<legend style="color:#000;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_headers')
+			.'&nbsp;&nbsp;(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_httpheaders_table\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show')."</span>)</legend>\n\n\n"
+			.'<table style="width:100%;display:none;" id="ci_profiler_httpheaders_table">'."\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)
 		{
-			$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";
+			$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";
 		}
 
 		return $output."</table>\n</fieldset>";
@@ -421,10 +424,10 @@
 	protected function _compile_config()
 	{
 		$output = "\n\n"
-			. '<fieldset id="ci_profiler_config" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">'
-			. "\n"
-			. '<legend style="color:#000;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_config').'&nbsp;&nbsp;(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_config_table\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show').'</span>)</legend>'
-			. "\n\n\n<table style='width:100%; display:none' id='ci_profiler_config_table'>\n";
+			.'<fieldset id="ci_profiler_config" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
+			."\n"
+			.'<legend style="color:#000;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_config').'&nbsp;&nbsp;(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_config_table\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show')."</span>)</legend>\n\n\n"
+			.'<table style="width:100%;display:none;" id="ci_profiler_config_table">'."\n";
 
 		foreach ($this->CI->config->config as $config => $val)
 		{
@@ -433,7 +436,8 @@
 				$val = print_r($val, TRUE);
 			}
 
-			$output .= "<tr><td style='padding:5px; vertical-align: top;color:#900;background-color:#ddd;'>".$config."&nbsp;&nbsp;</td><td style='padding:5px; color:#000;background-color:#ddd;'>".htmlspecialchars($val)."</td></tr>\n";
+			$output .= '<tr><td style="padding:5px;vertical-align:top;color:#900;background-color:#ddd;">'
+				.$config.'&nbsp;&nbsp;</td><td style="padding:5px;color:#000;background-color:#ddd;">'.htmlspecialchars($val)."</td></tr>\n";
 		}
 
 		return $output."</table>\n</fieldset>";
@@ -453,9 +457,9 @@
 			return;
 		}
 
-		$output = '<fieldset id="ci_profiler_csession" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">'
-			. '<legend style="color:#000;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_session_data').'&nbsp;&nbsp;(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_session_data\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show').'</span>)</legend>'
-			. "<table style='width:100%;display:none' id='ci_profiler_session_data'>";
+		$output = '<fieldset id="ci_profiler_csession" style="border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;">'
+			.'<legend style="color:#000;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_session_data').'&nbsp;&nbsp;(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_session_data\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_show').'\'?\''.$this->CI->lang->line('profiler_section_hide').'\':\''.$this->CI->lang->line('profiler_section_show').'\';">'.$this->CI->lang->line('profiler_section_show').'</span>)</legend>'
+			.'<table style="width:100%;display:none;" id="ci_profiler_session_data">';
 
 		foreach ($this->CI->session->all_userdata() as $key => $val)
 		{
@@ -464,7 +468,8 @@
 				$val = print_r($val, TRUE);
 			}
 
-			$output .= "<tr><td style='padding:5px; vertical-align: top;color:#900;background-color:#ddd;'>".$key."&nbsp;&nbsp;</td><td style='padding:5px; color:#000;background-color:#ddd;'>".htmlspecialchars($val)."</td></tr>\n";
+			$output .= '<tr><td style="padding:5px;vertical-align:top;color:#900;background-color:#ddd;">'
+				.$key.'&nbsp;&nbsp;</td><td style="padding:5px;color:#000;background-color:#ddd;">'.htmlspecialchars($val)."</td></tr>\n";
 		}
 
 		return $output."</table>\n</fieldset>";
@@ -479,14 +484,14 @@
 	 */
 	public function run()
 	{
-		$output = "<div id='codeigniter_profiler' style='clear:both;background-color:#fff;padding:10px;'>";
+		$output = '<div id="codeigniter_profiler" style="clear:both;background-color:#fff;padding:10px;">';
 		$fields_displayed = 0;
 
 		foreach ($this->_available_sections as $section)
 		{
 			if ($this->_compile_{$section} !== FALSE)
 			{
-				$func = "_compile_{$section}";
+				$func = '_compile_'.$section;
 				$output .= $this->{$func}();
 				$fields_displayed++;
 			}
@@ -494,7 +499,8 @@
 
 		if ($fields_displayed === 0)
 		{
-			$output .= '<p style="border:1px solid #5a0099;padding:10px;margin:20px 0;background-color:#eee">'.$this->CI->lang->line('profiler_no_profiles').'</p>';
+			$output .= '<p style="border:1px solid #5a0099;padding:10px;margin:20px 0;background-color:#eee;">'
+				.$this->CI->lang->line('profiler_no_profiles').'</p>';
 		}
 
 		return $output.'</div>';
@@ -502,4 +508,4 @@
 }
 
 /* End of file Profiler.php */
-/* Location: ./system/libraries/Profiler.php */
+/* Location: ./system/libraries/Profiler.php */
\ No newline at end of file
diff --git a/system/libraries/Session.php b/system/libraries/Session.php
index 3a80c16..3515764 100644
--- a/system/libraries/Session.php
+++ b/system/libraries/Session.php
@@ -469,21 +469,21 @@
 	{
 		return $this->userdata;
 	}
-	
+
 	// --------------------------------------------------------------------------
-	
+
 	/**
 	 * Fetch all flashdata
-	 * 
+	 *
 	 * @return	array
 	 */
 	public function all_flashdata()
 	{
 		$out = array();
-		
+
 		// loop through all userdata
 		foreach ($this->all_userdata() as $key => $val)
-		{	
+		{
 			// if it contains flashdata, add it
 			if (strpos($key, 'flash:old:') !== FALSE)
 			{
@@ -816,4 +816,4 @@
 }
 
 /* End of file Session.php */
-/* Location: ./system/libraries/Session.php */
+/* Location: ./system/libraries/Session.php */
\ No newline at end of file
diff --git a/system/libraries/Table.php b/system/libraries/Table.php
index 11a4858..3777d29 100644
--- a/system/libraries/Table.php
+++ b/system/libraries/Table.php
@@ -38,14 +38,14 @@
  */
 class CI_Table {
 
-	public $rows			= array();
-	public $heading			= array();
-	public $auto_heading		= TRUE;
-	public $caption			= NULL;
-	public $template		= NULL;
-	public $newline			= "\n";
-	public $empty_cells		= '';
-	public $function		= FALSE;
+	public $rows		= array();
+	public $heading		= array();
+	public $auto_heading	= TRUE;
+	public $caption		= NULL;
+	public $template	= NULL;
+	public $newline		= "\n";
+	public $empty_cells	= '';
+	public $function	= FALSE;
 
 	/**
 	 * Set the template from the table config file if it exists
@@ -55,13 +55,13 @@
 	 */
 	public function __construct($config = array())
 	{
-		log_message('debug', 'Table Class Initialized');
-
 		// initialize config
 		foreach ($config as $key => $val)
 		{
 			$this->template[$key] = $val;
 		}
+
+		log_message('debug', 'Table Class Initialized');
 	}
 
 	// --------------------------------------------------------------------
@@ -70,7 +70,7 @@
 	 * Set the template
 	 *
 	 * @param	array
-	 * @return	void
+	 * @return	bool
 	 */
 	public function set_template($template)
 	{
@@ -80,6 +80,7 @@
 		}
 
 		$this->template = $template;
+		return TRUE;
 	}
 
 	// --------------------------------------------------------------------
@@ -101,9 +102,9 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Set columns.  Takes a one-dimensional array as input and creates
+	 * Set columns. Takes a one-dimensional array as input and creates
 	 * a multi-dimensional array with a depth equal to the number of
-	 * columns.  This allows a single array with many elements to  be
+	 * columns. This allows a single array with many elements to be
 	 * displayed in a table that has a fixed column count.
 	 *
 	 * @param	array
@@ -184,29 +185,22 @@
 	 *
 	 * Ensures a standard associative array format for all cell data
 	 *
-	 * @param	type
-	 * @return	type
+	 * @param	array
+	 * @return	array
 	 */
 	protected function _prep_args($args)
 	{
 		// If there is no $args[0], skip this and treat as an associative array
 		// This can happen if there is only a single key, for example this is passed to table->generate
 		// array(array('foo'=>'bar'))
-		if (isset($args[0]) AND (count($args) === 1 && is_array($args[0])))
+		if (isset($args[0]) && count($args) === 1 && is_array($args[0]))
 		{
 			// args sent as indexed array
 			if ( ! isset($args[0]['data']))
 			{
 				foreach ($args[0] as $key => $val)
 				{
-					if (is_array($val) && isset($val['data']))
-					{
-						$args[$key] = $val;
-					}
-					else
-					{
-						$args[$key] = array('data' => $val);
-					}
+					$args[$key] = (is_array($val) && isset($val['data'])) ? $val : array('data' => $val);
 				}
 			}
 		}
@@ -257,13 +251,13 @@
 			}
 			elseif (is_array($table_data))
 			{
-				$set_heading = (count($this->heading) === 0 AND $this->auto_heading == FALSE) ? FALSE : TRUE;
+				$set_heading = (count($this->heading) !== 0 OR $this->auto_heading != FALSE);
 				$this->_set_from_array($table_data, $set_heading);
 			}
 		}
 
-		// Is there anything to display?  No?  Smite them!
-		if (count($this->heading) === 0 AND count($this->rows) === 0)
+		// Is there anything to display? No? Smite them!
+		if (count($this->heading) === 0 && count($this->rows) === 0)
 		{
 			return 'Undefined table data';
 		}
@@ -297,7 +291,7 @@
 				{
 					if ($key != 'data')
 					{
-						$temp = str_replace('<th', "<th $key='$val'", $temp);
+						$temp = str_replace('<th', '<th '.$key.'="'.$val.'"', $temp);
 					}
 				}
 
@@ -321,7 +315,7 @@
 				}
 
 				// We use modulus to alternate the row colors
-				$name = (fmod($i++, 2)) ? '' : 'alt_';
+				$name = fmod($i++, 2) ? '' : 'alt_';
 
 				$out .= $this->template['row_'.$name.'start'].$this->newline;
 
@@ -333,27 +327,24 @@
 					{
 						if ($key !== 'data')
 						{
-							$temp = str_replace('<td', "<td $key='$val'", $temp);
+							$temp = str_replace('<td', '<td '.$key.'="'.$val.'"', $temp);
 						}
 					}
 
 					$cell = isset($cell['data']) ? $cell['data'] : '';
 					$out .= $temp;
 
-					if ($cell === "" OR $cell === NULL)
+					if ($cell === '' OR $cell === NULL)
 					{
 						$out .= $this->empty_cells;
 					}
+					elseif ($function !== FALSE && is_callable($function))
+					{
+						$out .= call_user_func($function, $cell);
+					}
 					else
 					{
-						if ($function !== FALSE && is_callable($function))
-						{
-							$out .= call_user_func($function, $cell);
-						}
-						else
-						{
-							$out .= $cell;
-						}
+						$out .= $cell;
 					}
 
 					$out .= $this->template['cell_'.$name.'end'];
@@ -382,9 +373,9 @@
 	 */
 	public function clear()
 	{
-		$this->rows				= array();
-		$this->heading			= array();
-		$this->auto_heading		= TRUE;
+		$this->rows		= array();
+		$this->heading		= array();
+		$this->auto_heading	= TRUE;
 	}
 
 	// --------------------------------------------------------------------
@@ -399,7 +390,7 @@
 	{
 		if ( ! is_object($query))
 		{
-			return FALSE;
+			return;
 		}
 
 		// First generate the headings from the table column names
@@ -407,14 +398,13 @@
 		{
 			if ( ! is_callable(array($query, 'list_fields')))
 			{
-				return FALSE;
+				return;
 			}
 
 			$this->heading = $this->_prep_args($query->list_fields());
 		}
 
 		// Next blast through the result array and build out the rows
-
 		if ($query->num_rows() > 0)
 		{
 			foreach ($query->result_array() as $row)
@@ -443,7 +433,7 @@
 		foreach ($data as $row)
 		{
 			// If a heading hasn't already been set we'll use the first row of the array as the heading
-			if ($i++ === 0 AND count($data) > 1 AND count($this->heading) === 0 AND $set_heading == TRUE)
+			if ($i++ === 0 && count($data) > 1 && count($this->heading) === 0 && $set_heading == TRUE)
 			{
 				$this->heading = $this->_prep_args($row);
 			}
@@ -488,36 +478,35 @@
 	 */
 	protected function _default_template()
 	{
-		return  array (
-						'table_open'			=> '<table border="0" cellpadding="4" cellspacing="0">',
+		return  array(
+				'table_open'		=> '<table border="0" cellpadding="4" cellspacing="0">',
 
-						'thead_open'			=> '<thead>',
-						'thead_close'			=> '</thead>',
+				'thead_open'		=> '<thead>',
+				'thead_close'		=> '</thead>',
 
-						'heading_row_start'		=> '<tr>',
-						'heading_row_end'		=> '</tr>',
-						'heading_cell_start'	=> '<th>',
-						'heading_cell_end'		=> '</th>',
+				'heading_row_start'	=> '<tr>',
+				'heading_row_end'	=> '</tr>',
+				'heading_cell_start'	=> '<th>',
+				'heading_cell_end'	=> '</th>',
 
-						'tbody_open'			=> '<tbody>',
-						'tbody_close'			=> '</tbody>',
+				'tbody_open'		=> '<tbody>',
+				'tbody_close'		=> '</tbody>',
 
-						'row_start'				=> '<tr>',
-						'row_end'				=> '</tr>',
-						'cell_start'			=> '<td>',
-						'cell_end'				=> '</td>',
+				'row_start'		=> '<tr>',
+				'row_end'		=> '</tr>',
+				'cell_start'		=> '<td>',
+				'cell_end'		=> '</td>',
 
-						'row_alt_start'		=> '<tr>',
-						'row_alt_end'			=> '</tr>',
-						'cell_alt_start'		=> '<td>',
-						'cell_alt_end'			=> '</td>',
+				'row_alt_start'		=> '<tr>',
+				'row_alt_end'		=> '</tr>',
+				'cell_alt_start'	=> '<td>',
+				'cell_alt_end'		=> '</td>',
 
-						'table_close'			=> '</table>'
-					);
+				'table_close'		=> '</table>'
+			);
 	}
 
-
 }
 
 /* End of file Table.php */
-/* Location: ./system/libraries/Table.php */
+/* Location: ./system/libraries/Table.php */
\ No newline at end of file
diff --git a/system/libraries/Trackback.php b/system/libraries/Trackback.php
index be1de6f..6761f63 100644
--- a/system/libraries/Trackback.php
+++ b/system/libraries/Trackback.php
@@ -25,8 +25,6 @@
  * @filesource
  */
 
-// ------------------------------------------------------------------------
-
 /**
  * Trackback Class
  *
@@ -49,7 +47,7 @@
 
 	public function __construct()
 	{
-		log_message('debug', "Trackback Class Initialized");
+		log_message('debug', 'Trackback Class Initialized');
 	}
 
 	// --------------------------------------------------------------------
@@ -97,9 +95,10 @@
 		}
 
 		// Build the Trackback data string
-		$charset = ( ! isset($tb_data['charset'])) ? $this->charset : $tb_data['charset'];
+		$charset = isset($tb_data['charset']) ? $tb_data['charset'] : $this->charset;
 
-		$data = "url=".rawurlencode($url)."&title=".rawurlencode($title)."&blog_name=".rawurlencode($blog_name)."&excerpt=".rawurlencode($excerpt)."&charset=".rawurlencode($charset);
+		$data = 'url='.rawurlencode($url).'&title='.rawurlencode($title).'&blog_name='.rawurlencode($blog_name)
+			.'&excerpt='.rawurlencode($excerpt).'&charset='.rawurlencode($charset);
 
 		// Send Trackback(s)
 		$return = TRUE;
@@ -139,7 +138,7 @@
 				return FALSE;
 			}
 
-			$this->data['charset'] = ( ! isset($_POST['charset'])) ? 'auto' : strtoupper(trim($_POST['charset']));
+			$this->data['charset'] = isset($_POST['charset']) ? strtoupper(trim($_POST['charset'])) : 'auto';
 
 			if ($val != 'url' && MB_ENABLED === TRUE)
 			{
@@ -164,7 +163,7 @@
 	/**
 	 * Send Trackback Error Message
 	 *
-	 * Allows custom errors to be set.  By default it
+	 * Allows custom errors to be set. By default it
 	 * sends the "incomplete information" error, as that's
 	 * the most common one.
 	 *
@@ -173,7 +172,7 @@
 	 */
 	public function send_error($message = 'Incomplete Information')
 	{
-		echo "<?xml version=\"1.0\" encoding=\"utf-8\"?".">\n<response>\n<error>1</error>\n<message>".$message."</message>\n</response>";
+		echo '<?xml version="1.0" encoding="utf-8"?'.">\n<response>\n<error>1</error>\n<message>".$message."</message>\n</response>";
 		exit;
 	}
 
@@ -189,7 +188,7 @@
 	 */
 	public function send_success()
 	{
-		echo "<?xml version=\"1.0\" encoding=\"utf-8\"?".">\n<response>\n<error>0</error>\n</response>";
+		echo '<?xml version="1.0" encoding="utf-8"?'.">\n<response>\n<error>0</error>\n</response>";
 		exit;
 	}
 
@@ -203,7 +202,7 @@
 	 */
 	public function data($item)
 	{
-		return ( ! isset($this->data[$item])) ? '' : $this->data[$item];
+		return isset($this->data[$item]) ? $this->data[$item] : '';
 	}
 
 	// --------------------------------------------------------------------
@@ -212,7 +211,7 @@
 	 * Process Trackback
 	 *
 	 * Opens a socket connection and passes the data to
-	 * the server.  Returns TRUE on success, FALSE on failure
+	 * the server. Returns TRUE on success, FALSE on failure
 	 *
 	 * @param	string
 	 * @param	string
@@ -230,37 +229,36 @@
 		}
 
 		// Build the path
-		$ppath = ( ! isset($target['path'])) ? $url : $target['path'];
+		$ppath = isset($target['path']) ? $target['path'] : $url;
 
-		$path = (isset($target['query']) && $target['query'] != "") ? $ppath.'?'.$target['query'] : $ppath;
+		$path = empty($target['query']) ? $ppath : $ppath.'?'.$target['query'];
 
 		// Add the Trackback ID to the data string
 		if ($id = $this->get_id($url))
 		{
-			$data = "tb_id=".$id."&".$data;
+			$data = 'tb_id='.$id.'&'.$data;
 		}
 
 		// Transfer the data
-		fputs ($fp, "POST " . $path . " HTTP/1.0\r\n" );
-		fputs ($fp, "Host: " . $target['host'] . "\r\n" );
-		fputs ($fp, "Content-type: application/x-www-form-urlencoded\r\n" );
-		fputs ($fp, "Content-length: " . strlen($data) . "\r\n" );
-		fputs ($fp, "Connection: close\r\n\r\n" );
-		fputs ($fp, $data);
+		fputs($fp, 'POST '.$path." HTTP/1.0\r\n");
+		fputs($fp, 'Host: '.$target['host']."\r\n");
+		fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
+		fputs($fp, 'Content-length: '.strlen($data)."\r\n");
+		fputs($fp, "Connection: close\r\n\r\n");
+		fputs($fp, $data);
 
 		// Was it successful?
-		$this->response = "";
 
+		$this->response = '';
 		while ( ! feof($fp))
 		{
 			$this->response .= fgets($fp, 128);
 		}
 		@fclose($fp);
 
-
 		if (stripos($this->response, '<error>0</error>') === FALSE)
 		{
-			$message = (preg_match('/<message>(.*?)<\/message>/is', $this->response, $match)) ? trim($match[1]) : 'An unknown error was encountered';
+			$message = preg_match('/<message>(.*?)<\/message>/is', $this->response, $match) ? trim($match[1]) : 'An unknown error was encountered';
 			$this->set_error($message);
 			return FALSE;
 		}
@@ -282,11 +280,8 @@
 	 */
 	public function extract_urls($urls)
 	{
-		// Remove the pesky white space and replace with a comma.
-		$urls = preg_replace("/\s*(\S+)\s*/", "\\1,", $urls);
-
-		// If they use commas get rid of the doubles.
-		$urls = str_replace(",,", ",", $urls);
+		// Remove the pesky white space and replace with a comma, then replace doubles.
+		$urls = str_replace(',,', ',', preg_replace('/\s*(\S+)\s*/', '\\1,', $urls));
 
 		// Remove any comma that might be at the end
 		if (substr($urls, -1) === ',')
@@ -294,11 +289,8 @@
 			$urls = substr($urls, 0, -1);
 		}
 
-		// Break into an array via commas
-		$urls = preg_split('/[,]/', $urls);
-
-		// Removes duplicates
-		$urls = array_unique($urls);
+		// Break into an array via commas and remove duplicates
+		$urls = array_unique(preg_split('/[,]/', $urls));
 
 		array_walk($urls, array($this, 'validate_url'));
 
@@ -313,9 +305,9 @@
 	 * Simply adds "http://" if missing
 	 *
 	 * @param	string
-	 * @return	string
+	 * @return	void
 	 */
-	public function validate_url($url)
+	public function validate_url(&$url)
 	{
 		$url = trim($url);
 
@@ -335,7 +327,7 @@
 	 */
 	public function get_id($url)
 	{
-		$tb_id = "";
+		$tb_id = '';
 
 		if (strpos($url, '?') !== FALSE)
 		{
@@ -359,18 +351,11 @@
 
 			if ( ! is_numeric($tb_id))
 			{
-				$tb_id  = $tb_array[count($tb_array)-2];
+				$tb_id = $tb_array[count($tb_array)-2];
 			}
 		}
 
-		if ( ! preg_match ("/^([0-9]+)$/", $tb_id))
-		{
-			return FALSE;
-		}
-		else
-		{
-			return $tb_id;
-		}
+		return preg_match('/^[0-9]+$/', $tb_id) ? $tb_id : FALSE;
 	}
 
 	// --------------------------------------------------------------------
@@ -385,15 +370,13 @@
 	{
 		$temp = '__TEMP_AMPERSANDS__';
 
-		$str = preg_replace(array('/&#(\d+);/', '/&(\w+);/'), "$temp\\1;", $str);
+		$str = preg_replace(array('/&#(\d+);/', '/&(\w+);/'), $temp.'\\1;', $str);
 
-		$str = str_replace(array("&","<",">","\"", "'", "-"),
-							array("&amp;", "&lt;", "&gt;", "&quot;", "&#39;", "&#45;"),
-							$str);
+		$str = str_replace(array('&', '<', '>', '"', "'", '-'),
+					array('&amp;', '&lt;', '&gt;', '&quot;', '&#39;', '&#45;'),
+					$str);
 
-		$str = preg_replace(array("/$temp(\d+);/", "/$temp(\w+);/"), array('&#\\1;', '&\\1;'), $str);
-
-		return $str;
+		return preg_replace(array('/'.$temp.'(\d+);/', '/'.$temp.'(\w+);/'), array('&#\\1;', '&\\1;'), $str);
 	}
 
 	// --------------------------------------------------------------------
@@ -404,7 +387,7 @@
 	 * Limits the string based on the character count. Will preserve complete words.
 	 *
 	 * @param	string
-	 * @param	integer
+	 * @param	int
 	 * @param	string
 	 * @return	string
 	 */
@@ -415,7 +398,7 @@
 			return $str;
 		}
 
-		$str = preg_replace("/\s+/", ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $str));
+		$str = preg_replace('/\s+/', ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $str));
 
 		if (strlen($str) <= $n)
 		{
@@ -469,7 +452,9 @@
 
 				if (count($temp) === $count)
 				{
-					$number = ($count == 3) ? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64) : (($temp[0] % 32) * 64) + ($temp[1] % 64);
+					$number = ($count === 3)
+						? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64)
+						: (($temp[0] % 32) * 64) + ($temp[1] % 64);
 
 					$out .= '&#'.$number.';';
 					$count = 1;
@@ -506,11 +491,10 @@
 	 */
 	public function display_errors($open = '<p>', $close = '</p>')
 	{
-		return (count($this->error_msg) > 0) ? $open . implode($close . $open, $this->error_msg) . $close : '';
+		return (count($this->error_msg) > 0) ? $open.implode($close.$open, $this->error_msg).$close : '';
 	}
 
 }
-// END Trackback Class
 
 /* End of file Trackback.php */
-/* Location: ./system/libraries/Trackback.php */
+/* Location: ./system/libraries/Trackback.php */
\ No newline at end of file
diff --git a/system/libraries/Unit_test.php b/system/libraries/Unit_test.php
index 2eb8df3..0f6e2df 100644
--- a/system/libraries/Unit_test.php
+++ b/system/libraries/Unit_test.php
@@ -25,8 +25,6 @@
  * @filesource
  */
 
-// ------------------------------------------------------------------------
-
 /**
  * Unit Testing Class
  *
@@ -60,7 +58,7 @@
 							'notes'
 						);
 
-		log_message('debug', "Unit Testing Class Initialized");
+		log_message('debug', 'Unit Testing Class Initialized');
 	}
 
 	// --------------------------------------------------------------------
@@ -75,7 +73,7 @@
 	 */
 	public function set_test_items($items = array())
 	{
-		if ( ! empty($items) AND is_array($items))
+		if ( ! empty($items) && is_array($items))
 		{
 			$this->_test_items_visible = $items;
 		}
@@ -102,8 +100,8 @@
 
 		if (in_array($expected, array('is_object', 'is_string', 'is_bool', 'is_true', 'is_false', 'is_int', 'is_numeric', 'is_float', 'is_double', 'is_array', 'is_null'), TRUE))
 		{
-			$expected = str_replace('is_float', 'is_double', $expected);
-			$result = ($expected($test)) ? TRUE : FALSE;
+			$expected = str_replace('is_double', 'is_float', $expected);
+			$result = $expected($test);
 			$extype = str_replace(array('true', 'false'), 'bool', str_replace('is_', '', $expected));
 		}
 		else
@@ -186,7 +184,7 @@
 	 * Causes the evaluation to use === rather than ==
 	 *
 	 * @param	bool
-	 * @return	null
+	 * @return	void
 	 */
 	public function use_strict($state = TRUE)
 	{
@@ -201,7 +199,7 @@
 	 * Enables/disables unit testing
 	 *
 	 * @param	bool
-	 * @return	null
+	 * @return	void
 	 */
 	public function active($state = TRUE)
 	{
@@ -311,10 +309,10 @@
 	 */
 	protected function _default_template()
 	{
-		$this->_template = "\n".'<table style="width:100%; font-size:small; margin:10px 0; border-collapse:collapse; border:1px solid #CCC;">{rows}'."\n".'</table>';
+		$this->_template = "\n".'<table style="width:100%; font-size:small; margin:10px 0; border-collapse:collapse; border:1px solid #CCC;">{rows}'."\n</table>";
 
 		$this->_template_rows = "\n\t<tr>\n\t\t".'<th style="text-align: left; border-bottom:1px solid #CCC;">{item}</th>'
-					. "\n\t\t".'<td style="border-bottom:1px solid #CCC;">{result}</td>'."\n\t</tr>";
+					."\n\t\t".'<td style="border-bottom:1px solid #CCC;">{result}</td>'."\n\t</tr>";
 	}
 
 	// --------------------------------------------------------------------
@@ -333,7 +331,7 @@
 			return;
 		}
 
-		if (is_null($this->_template) OR ! preg_match("/\{rows\}(.*?)\{\/rows\}/si", $this->_template, $match))
+		if (is_null($this->_template) OR ! preg_match('/\{rows\}(.*?)\{\/rows\}/si', $this->_template, $match))
 		{
 			$this->_default_template();
 			return;
@@ -344,7 +342,6 @@
 	}
 
 }
-// END Unit_test Class
 
 /**
  * Helper functions to test boolean true/false
@@ -353,13 +350,12 @@
  */
 function is_true($test)
 {
-	return (is_bool($test) AND $test === TRUE) ? TRUE : FALSE;
+	return (is_bool($test) && $test === TRUE);
 }
 function is_false($test)
 {
-	return (is_bool($test) AND $test === FALSE) ? TRUE : FALSE;
+	return (is_bool($test) && $test === FALSE);
 }
 
-
 /* End of file Unit_test.php */
-/* Location: ./system/libraries/Unit_test.php */
+/* Location: ./system/libraries/Unit_test.php */
\ No newline at end of file
diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php
index 9109edd..b8e0d37 100644
--- a/system/libraries/User_agent.php
+++ b/system/libraries/User_agent.php
@@ -25,8 +25,6 @@
  * @filesource
  */
 
-// ------------------------------------------------------------------------
-
 /**
  * User Agent Class
  *
@@ -74,15 +72,12 @@
 			$this->agent = trim($_SERVER['HTTP_USER_AGENT']);
 		}
 
-		if ( ! is_null($this->agent))
+		if ( ! is_null($this->agent) && $this->_load_agent_file())
 		{
-			if ($this->_load_agent_file())
-			{
-				$this->_compile_data();
-			}
+			$this->_compile_data();
 		}
 
-		log_message('debug', "User Agent Class Initialized");
+		log_message('debug', 'User Agent Class Initialized');
 	}
 
 	// --------------------------------------------------------------------
@@ -94,7 +89,7 @@
 	 */
 	protected function _load_agent_file()
 	{
-		if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php'))
+		if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php'))
 		{
 			include(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php');
 		}
@@ -165,22 +160,24 @@
 	/**
 	 * Set the Platform
 	 *
-	 * @return	mixed
+	 * @return	bool
 	 */
 	protected function _set_platform()
 	{
-		if (is_array($this->platforms) AND count($this->platforms) > 0)
+		if (is_array($this->platforms) && count($this->platforms) > 0)
 		{
 			foreach ($this->platforms as $key => $val)
 			{
-				if (preg_match("|".preg_quote($key)."|i", $this->agent))
+				if (preg_match('|'.preg_quote($key).'|i', $this->agent))
 				{
 					$this->platform = $val;
 					return TRUE;
 				}
 			}
 		}
+
 		$this->platform = 'Unknown Platform';
+		return FALSE;
 	}
 
 	// --------------------------------------------------------------------
@@ -192,11 +189,11 @@
 	 */
 	protected function _set_browser()
 	{
-		if (is_array($this->browsers) AND count($this->browsers) > 0)
+		if (is_array($this->browsers) && count($this->browsers) > 0)
 		{
 			foreach ($this->browsers as $key => $val)
 			{
-				if (preg_match("|".preg_quote($key).".*?([0-9\.]+)|i", $this->agent, $match))
+				if (preg_match('|'.preg_quote($key).'.*?([0-9\.]+)|i', $this->agent, $match))
 				{
 					$this->is_browser = TRUE;
 					$this->version = $match[1];
@@ -206,6 +203,7 @@
 				}
 			}
 		}
+
 		return FALSE;
 	}
 
@@ -218,11 +216,11 @@
 	 */
 	protected function _set_robot()
 	{
-		if (is_array($this->robots) AND count($this->robots) > 0)
+		if (is_array($this->robots) && count($this->robots) > 0)
 		{
 			foreach ($this->robots as $key => $val)
 			{
-				if (preg_match("|".preg_quote($key)."|i", $this->agent))
+				if (preg_match('|'.preg_quote($key).'|i', $this->agent))
 				{
 					$this->is_robot = TRUE;
 					$this->robot = $val;
@@ -230,6 +228,7 @@
 				}
 			}
 		}
+
 		return FALSE;
 	}
 
@@ -242,7 +241,7 @@
 	 */
 	protected function _set_mobile()
 	{
-		if (is_array($this->mobiles) AND count($this->mobiles) > 0)
+		if (is_array($this->mobiles) && count($this->mobiles) > 0)
 		{
 			foreach ($this->mobiles as $key => $val)
 			{
@@ -254,6 +253,7 @@
 				}
 			}
 		}
+
 		return FALSE;
 	}
 
@@ -266,7 +266,7 @@
 	 */
 	protected function _set_languages()
 	{
-		if ((count($this->languages) === 0) AND isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) AND $_SERVER['HTTP_ACCEPT_LANGUAGE'] != '')
+		if ((count($this->languages) === 0) && ! empty($_SERVER['HTTP_ACCEPT_LANGUAGE']))
 		{
 			$this->languages = explode(',', preg_replace('/(;q=[0-9\.]+)/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_LANGUAGE']))));
 		}
@@ -286,7 +286,7 @@
 	 */
 	protected function _set_charsets()
 	{
-		if ((count($this->charsets) === 0) AND isset($_SERVER['HTTP_ACCEPT_CHARSET']) AND $_SERVER['HTTP_ACCEPT_CHARSET'] != '')
+		if ((count($this->charsets) === 0) && ! empty($_SERVER['HTTP_ACCEPT_CHARSET']))
 		{
 			$this->charsets = explode(',', preg_replace('/(;q=.+)/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_CHARSET']))));
 		}
@@ -318,7 +318,7 @@
 		}
 
 		// Check for a specific browser
-		return array_key_exists($key, $this->browsers) AND $this->browser === $this->browsers[$key];
+		return (isset($this->browsers[$key]) && $this->browser === $this->browsers[$key]);
 	}
 
 	// --------------------------------------------------------------------
@@ -342,7 +342,7 @@
 		}
 
 		// Check for a specific robot
-		return array_key_exists($key, $this->robots) AND $this->robot === $this->robots[$key];
+		return (isset($this->robots[$key]) && $this->robot === $this->robots[$key]);
 	}
 
 	// --------------------------------------------------------------------
@@ -366,7 +366,7 @@
 		}
 
 		// Check for a specific robot
-		return array_key_exists($key, $this->mobiles) AND $this->mobile === $this->mobiles[$key];
+		return (isset($this->mobiles[$key]) && $this->mobile === $this->mobiles[$key]);
 	}
 
 	// --------------------------------------------------------------------
@@ -378,7 +378,7 @@
 	 */
 	public function is_referral()
 	{
-		return ( ! isset($_SERVER['HTTP_REFERER']) OR $_SERVER['HTTP_REFERER'] == '') ? FALSE : TRUE;
+		return ! empty($_SERVER['HTTP_REFERER']);
 	}
 
 	// --------------------------------------------------------------------
@@ -461,7 +461,7 @@
 	 */
 	public function referrer()
 	{
-		return ( ! isset($_SERVER['HTTP_REFERER']) OR $_SERVER['HTTP_REFERER'] == '') ? '' : trim($_SERVER['HTTP_REFERER']);
+		return empty($_SERVER['HTTP_REFERER']) ? '' : trim($_SERVER['HTTP_REFERER']);
 	}
 
 	// --------------------------------------------------------------------
@@ -507,7 +507,7 @@
 	 */
 	public function accept_lang($lang = 'en')
 	{
-		return (in_array(strtolower($lang), $this->languages(), TRUE));
+		return in_array(strtolower($lang), $this->languages(), TRUE);
 	}
 
 	// --------------------------------------------------------------------
@@ -519,10 +519,10 @@
 	 */
 	public function accept_charset($charset = 'utf-8')
 	{
-		return (in_array(strtolower($charset), $this->charsets(), TRUE));
+		return in_array(strtolower($charset), $this->charsets(), TRUE);
 	}
 
 }
 
 /* End of file User_agent.php */
-/* Location: ./system/libraries/User_agent.php */
+/* Location: ./system/libraries/User_agent.php */
\ No newline at end of file
diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php
index b6e6c81..fea560c 100644
--- a/system/libraries/Xmlrpc.php
+++ b/system/libraries/Xmlrpc.php
@@ -25,14 +25,6 @@
  * @filesource
  */
 
-if ( ! function_exists('xml_parser_create'))
-{
-	show_error('Your PHP installation does not support XML');
-}
-
-
-// ------------------------------------------------------------------------
-
 /**
  * XML-RPC request handler class
  *
@@ -42,6 +34,14 @@
  * @author		EllisLab Dev Team
  * @link		http://codeigniter.com/user_guide/libraries/xmlrpc.html
  */
+
+if ( ! function_exists('xml_parser_create'))
+{
+	show_error('Your PHP installation does not support XML');
+}
+
+// ------------------------------------------------------------------------
+
 class CI_Xmlrpc {
 
 	public $debug		= FALSE;	// Debugging on or off
@@ -77,13 +77,17 @@
 
 	public $xss_clean		= TRUE;
 
-	//-------------------------------------
-	//  VALUES THAT MULTIPLE CLASSES NEED
-	//-------------------------------------
 
+	/**
+	 * Constructor
+	 *
+	 * Initializes property default values
+	 *
+	 * @param	array
+	 * @return	void
+	 */
 	public function __construct($config = array())
 	{
-		$this->xmlrpcName	= $this->xmlrpcName;
 		$this->xmlrpc_backslash = chr(92).chr(92);
 
 		// Types for info sent back and forth
@@ -139,10 +143,14 @@
 		log_message('debug', 'XML-RPC Class Initialized');
 	}
 
-	//-------------------------------------
-	//  Initialize Prefs
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Initialize
+	 *
+	 * @param	array
+	 * @return	void
+	 */
 	public function initialize($config = array())
 	{
 		if (count($config) > 0)
@@ -156,17 +164,21 @@
 			}
 		}
 	}
-	// END
 
-	//-------------------------------------
-	//  Take URL and parse it
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Parse server URL
+	 *
+	 * @param	string	url
+	 * @param	int	port
+	 * @return	void
+	 */
 	public function server($url, $port = 80)
 	{
 		if (strpos($url, 'http') !== 0)
 		{
-			$url = "http://".$url;
+			$url = 'http://'.$url;
 		}
 
 		$parts = parse_url($url);
@@ -180,12 +192,15 @@
 
 		$this->client = new XML_RPC_Client($path, $parts['host'], $port);
 	}
-	// END
 
-	//-------------------------------------
-	//  Set Timeout
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Set Timeout
+	 *
+	 * @param	int	seconds
+	 * @return	void
+	 */
 	public function timeout($seconds = 5)
 	{
 		if ( ! is_null($this->client) && is_int($seconds))
@@ -193,27 +208,34 @@
 			$this->client->timeout = $seconds;
 		}
 	}
-	// END
 
-	//-------------------------------------
-	//  Set Methods
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Set Methods
+	 *
+	 * @param	string	method name
+	 * @return	void
+	 */
 	public function method($function)
 	{
 		$this->method = $function;
 	}
-	// END
 
-	//-------------------------------------
-	//  Take Array of Data and Create Objects
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Take Array of Data and Create Objects
+	 *
+	 * @param	array
+	 * @return	void
+	 */
 	public function request($incoming)
 	{
 		if ( ! is_array($incoming))
 		{
 			// Send Error
+			return;
 		}
 
 		$this->data = array();
@@ -223,23 +245,29 @@
 			$this->data[$key] = $this->values_parsing($value);
 		}
 	}
-	// END
 
+	// --------------------------------------------------------------------
 
-	//-------------------------------------
-	//  Set Debug
-	//-------------------------------------
-
+	/**
+	 * Set Debug
+	 *
+	 * @param	bool
+	 * @return	void
+	 */
 	public function set_debug($flag = TRUE)
 	{
 		$this->debug = ($flag == TRUE);
 	}
 
-	//-------------------------------------
-	//  Values Parsing
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
-	public function values_parsing($value, $return = FALSE)
+	/**
+	 * Values Parsing
+	 *
+	 * @param	mixed
+	 * @return	object
+	 */
+	public function values_parsing($value)
 	{
 		if (is_array($value) && array_key_exists(0, $value))
 		{
@@ -267,16 +295,17 @@
 
 		return $temp;
 	}
-	// END
 
+	// --------------------------------------------------------------------
 
-	//-------------------------------------
-	//  Sends XML-RPC Request
-	//-------------------------------------
-
+	/**
+	 * Sends XML-RPC Request
+	 *
+	 * @return	bool
+	 */
 	public function send_request()
 	{
-		$this->message = new XML_RPC_Message($this->method,$this->data);
+		$this->message = new XML_RPC_Message($this->method, $this->data);
 		$this->message->debug = $this->debug;
 
 		if ( ! $this->result = $this->client->send($this->message) OR ! is_object($this->result->val))
@@ -288,54 +317,62 @@
 		$this->response = $this->result->decode();
 		return TRUE;
 	}
-	// END
 
-	//-------------------------------------
-	//  Returns Error
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Returns Error
+	 *
+	 * @return	string
+	 */
 	public function display_error()
 	{
 		return $this->error;
 	}
-	// END
 
-	//-------------------------------------
-	//  Returns Remote Server Response
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Returns Remote Server Response
+	 *
+	 * @return	string
+	 */
 	public function display_response()
 	{
 		return $this->response;
 	}
-	// END
 
-	//-------------------------------------
-	//  Sends an Error Message for Server Request
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Sends an Error Message for Server Request
+	 *
+	 * @param	int
+	 * @param	string
+	 * @return	object
+	 */
 	public function send_error_message($number, $message)
 	{
 		return new XML_RPC_Response(0, $number, $message);
 	}
-	// END
 
+	// --------------------------------------------------------------------
 
-	//-------------------------------------
-	//  Send Response for Server Request
-	//-------------------------------------
-
+	/**
+	 * Send Response for Server Request
+	 *
+	 * @param	array
+	 * @return	object
+	 */
 	public function send_response($response)
 	{
 		// $response should be array of values, which will be parsed
 		// based on their data and type into a valid group of XML-RPC values
 		return new XML_RPC_Response($this->values_parsing($response));
 	}
-	// END
 
 } // END XML_RPC Class
 
-
 /**
  * XML-RPC Client class
  *
@@ -353,6 +390,14 @@
 	public $timeout		= 5;
 	public $no_multicall	= FALSE;
 
+	/**
+	 * Constructor
+	 *
+	 * @param	string
+	 * @param	object
+	 * @param	int
+	 * @return	void
+	 */
 	public function __construct($path, $server, $port = 80)
 	{
 		parent::__construct();
@@ -362,18 +407,33 @@
 		$this->path = $path;
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Send message
+	 *
+	 * @param	mixed
+	 * @return	object
+	 */
 	public function send($msg)
 	{
 		if (is_array($msg))
 		{
 			// Multi-call disabled
-			$r = new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'],$this->xmlrpcstr['multicall_recursion']);
-			return $r;
+			return new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']);
 		}
 
 		return $this->sendPayload($msg);
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Send payload
+	 *
+	 * @param	object
+	 * @return	object
+	 */
 	public function sendPayload($msg)
 	{
 		$fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstr, $this->timeout);
@@ -381,8 +441,7 @@
 		if ( ! is_resource($fp))
 		{
 			error_log($this->xmlrpcstr['http_error']);
-			$r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
-			return $r;
+			return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
 		}
 
 		if (empty($msg->payload))
@@ -399,20 +458,18 @@
 			.'Content-Length: '.strlen($msg->payload).$r.$r
 			.$msg->payload;
 
-
 		if ( ! fputs($fp, $op, strlen($op)))
 		{
 			error_log($this->xmlrpcstr['http_error']);
-			$r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
-			return $r;
+			return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
 		}
+
 		$resp = $msg->parseResponse($fp);
 		fclose($fp);
 		return $resp;
 	}
 
-}
-// end class XML_RPC_Client
+} // END XML_RPC_Client Class
 
 /**
  * XML-RPC Response class
@@ -423,26 +480,29 @@
  */
 class XML_RPC_Response
 {
-	public $val = 0;
-	public $errno = 0;
-	public $errstr = '';
-	public $headers = array();
-	public $xss_clean = TRUE;
+	public $val		= 0;
+	public $errno		= 0;
+	public $errstr		= '';
+	public $headers		= array();
+	public $xss_clean	= TRUE;
 
+	/**
+	 * Constructor
+	 *
+	 * @param	mixed
+	 * @param	int
+	 * @param	string
+	 * @return	void
+	 */
 	public function __construct($val, $code = 0, $fstr = '')
 	{
 		if ($code != 0)
 		{
 			// error
 			$this->errno = $code;
-			if ( ! is_php('5.4'))
-			{
-				$this->errstr = htmlspecialchars($fstr, ENT_NOQUOTES, 'UTF-8');
-			}
-			else
-			{
-				$this->errstr = htmlspecialchars($fstr, ENT_XML1 | ENT_NOQUOTES, 'UTF-8');
-			}
+			$this->errstr = htmlspecialchars($fstr,
+							(is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),
+							'UTF-8');
 		}
 		elseif ( ! is_object($val))
 		{
@@ -456,43 +516,79 @@
 		}
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Fault code
+	 *
+	 * @return	int
+	 */
 	public function faultCode()
 	{
 		return $this->errno;
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Fault string
+	 *
+	 * @return	string
+	 */
 	public function faultString()
 	{
 		return $this->errstr;
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Value
+	 *
+	 * @return	mixed
+	 */
 	public function value()
 	{
 		return $this->val;
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Prepare response
+	 *
+	 * @return	string	xml
+	 */
 	public function prepare_response()
 	{
 		return "<methodResponse>\n"
-			. ($this->errno
-			? '<fault>
+			.($this->errno
+				? '<fault>
 	<value>
 		<struct>
 			<member>
 				<name>faultCode</name>
-				<value><int>' . $this->errno . '</int></value>
+				<value><int>'.$this->errno.'</int></value>
 			</member>
 			<member>
 				<name>faultString</name>
-				<value><string>' . $this->errstr . '</string></value>
+				<value><string>'.$this->errstr.'</string></value>
 			</member>
 		</struct>
 	</value>
 </fault>'
-			: "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")
-			. "\n</methodResponse>";
+				: "<params>\n<param>\n".$this->val->serialize_class()."</param>\n</params>")
+			."\n</methodResponse>";
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Decode
+	 *
+	 * @param	mixed
+	 * @return	array
+	 */
 	public function decode($array = FALSE)
 	{
 		$CI =& get_instance();
@@ -511,29 +607,31 @@
 				}
 			}
 
-			$result = $array;
+			return $array;
+		}
+
+		$result = $this->xmlrpc_decoder($this->val);
+
+		if (is_array($result))
+		{
+			$result = $this->decode($result);
 		}
 		else
 		{
-			$result = $this->xmlrpc_decoder($this->val);
-
-			if (is_array($result))
-			{
-				$result = $this->decode($result);
-			}
-			else
-			{
-				$result = ($this->xss_clean) ? $CI->security->xss_clean($result) : $result;
-			}
+			$result = ($this->xss_clean) ? $CI->security->xss_clean($result) : $result;
 		}
 
 		return $result;
 	}
 
-	//-------------------------------------
-	//  XML-RPC Object to PHP Types
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * XML-RPC Object to PHP Types
+	 *
+	 * @param	object
+	 * @return	array
+	 */
 	public function xmlrpc_decoder($xmlrpc_val)
 	{
 		$kind = $xmlrpc_val->kindOf();
@@ -567,24 +665,28 @@
 		}
 	}
 
-	//-------------------------------------
-	//  ISO-8601 time to server or UTC time
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
-	public function iso8601_decode($time, $utc = 0)
+	/**
+	 * ISO-8601 time to server or UTC time
+	 *
+	 * @param	string
+	 * @param	bool
+	 * @return	int	unix timestamp
+	 */
+	public function iso8601_decode($time, $utc = FALSE)
 	{
-		// return a timet in the localtime, or UTC
+		// return a time in the localtime, or UTC
 		$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))
 		{
-			$fnc = ($utc == 1) ? 'gmmktime' : 'mktime';
+			$fnc = ($utc == TRUE) ? 'gmmktime' : 'mktime';
 			$t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
 		}
 		return $t;
 	}
 
-}
-// End Response Class
+} // END XML_RPC_Response Class
 
 /**
  * XML-RPC Message class
@@ -597,10 +699,17 @@
 {
 	public $payload;
 	public $method_name;
-	public $params			= array();
-	public $xh				= array();
+	public $params		= array();
+	public $xh		= array();
 
-	public function __construct($method, $pars = 0)
+	/**
+	 * Constructor
+	 *
+	 * @param	string	method name
+	 * @param	array
+	 * @return	void
+	 */
+	public function __construct($method, $pars = FALSE)
 	{
 		parent::__construct();
 
@@ -615,15 +724,18 @@
 		}
 	}
 
-	//-------------------------------------
-	//  Create Payload to Send
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Create Payload to Send
+	 *
+	 * @return	void
+	 */
 	public function createPayload()
 	{
-		$this->payload = "<?xml version=\"1.0\"?".">\r\n<methodCall>\r\n"
-				. '<methodName>'.$this->method_name."</methodName>\r\n"
-				. "<params>\r\n";
+		$this->payload = '<?xml version="1.0"?'.">\r\n<methodCall>\r\n"
+				.'<methodName>'.$this->method_name."</methodName>\r\n"
+				."<params>\r\n";
 
 		for ($i = 0, $c = count($this->params); $i < $c; $i++)
 		{
@@ -635,10 +747,14 @@
 		$this->payload .= "</params>\r\n</methodCall>\r\n";
 	}
 
-	//-------------------------------------
-	//  Parse External XML-RPC Server's Response
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Parse External XML-RPC Server's Response
+	 *
+	 * @param	resource
+	 * @return	object
+	 */
 	public function parseResponse($fp)
 	{
 		$data = '';
@@ -648,36 +764,24 @@
 			$data .= $datum;
 		}
 
-		//-------------------------------------
-		//  DISPLAY HTTP CONTENT for DEBUGGING
-		//-------------------------------------
-
+		// Display HTTP content for debugging
 		if ($this->debug === TRUE)
 		{
 			echo "<pre>---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n</pre>";
 		}
 
-		//-------------------------------------
-		//  Check for data
-		//-------------------------------------
-
+		// Check for data
 		if ($data === '')
 		{
 			error_log($this->xmlrpcstr['no_data']);
-			$r = new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
-			return $r;
+			return new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
 		}
 
-
-		//-------------------------------------
-		//  Check for HTTP 200 Response
-		//-------------------------------------
-
+		// Check for HTTP 200 Response
 		if (strncmp($data, 'HTTP', 4) === 0 && ! preg_match('/^HTTP\/[0-9\.]+ 200 /', $data))
 		{
-			$errstr= substr($data, 0, strpos($data, "\n")-1);
-			$r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' (' . $errstr . ')');
-			return $r;
+			$errstr = substr($data, 0, strpos($data, "\n")-1);
+			return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');
 		}
 
 		//-------------------------------------
@@ -687,24 +791,21 @@
 		$parser = xml_parser_create($this->xmlrpc_defencoding);
 
 		$this->xh[$parser] = array(
-						'isf' =>	0,
-						'ac' =>		'',
-						'headers' =>	array(),
-						'stack' =>	array(),
-						'valuestack' =>	array(),
-						'isf_reason' =>	0
+						'isf'		=> 0,
+						'ac'		=> '',
+						'headers'	=> array(),
+						'stack'		=> array(),
+						'valuestack'	=> array(),
+						'isf_reason'	=> 0
 					);
 
 		xml_set_object($parser, $this);
-		xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
+		xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
 		xml_set_element_handler($parser, 'open_tag', 'closing_tag');
 		xml_set_character_data_handler($parser, 'character_data');
 		//xml_set_default_handler($parser, 'default_handler');
 
-		//-------------------------------------
-		//  GET HEADERS
-		//-------------------------------------
-
+		// Get headers
 		$lines = explode("\r\n", $data);
 		while (($line = array_shift($lines)))
 		{
@@ -716,16 +817,12 @@
 		}
 		$data = implode("\r\n", $lines);
 
-
-		//-------------------------------------
-		//  PARSE XML DATA
-		//-------------------------------------
-
+		// Parse XML data
 		if ( ! xml_parse($parser, $data, count($data)))
 		{
 			$errstr = sprintf('XML error: %s at line %d',
-					xml_error_string(xml_get_error_code($parser)),
-					xml_get_current_line_number($parser));
+						xml_error_string(xml_get_error_code($parser)),
+						xml_get_current_line_number($parser));
 			//error_log($errstr);
 			$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
 			xml_parser_free($parser);
@@ -733,10 +830,7 @@
 		}
 		xml_parser_free($parser);
 
-		// ---------------------------------------
-		//  Got Ourselves Some Badness, It Seems
-		// ---------------------------------------
-
+		// Got ourselves some badness, it seems
 		if ($this->xh[$parser]['isf'] > 1)
 		{
 			if ($this->debug === TRUE)
@@ -744,19 +838,14 @@
 				echo "---Invalid Return---\n".$this->xh[$parser]['isf_reason']."---Invalid Return---\n\n";
 			}
 
-			$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
-			return $r;
+			return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
 		}
 		elseif ( ! is_object($this->xh[$parser]['value']))
 		{
-			$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
-			return $r;
+			return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
 		}
 
-		//-------------------------------------
-		//  DISPLAY XML CONTENT for DEBUGGING
-		//-------------------------------------
-
+		// Display XML content for debugging
 		if ($this->debug === TRUE)
 		{
 			echo '<pre>';
@@ -776,10 +865,7 @@
 			echo "\n---END PARSED---</pre>";
 		}
 
-		//-------------------------------------
-		//  SEND RESPONSE
-		//-------------------------------------
-
+		// Send response
 		$v = $this->xh[$parser]['value'];
 		if ($this->xh[$parser]['isf'])
 		{
@@ -804,6 +890,8 @@
 		return $r;
 	}
 
+	// --------------------------------------------------------------------
+
 	// ------------------------------------
 	//  Begin Return Message Parsing section
 	// ------------------------------------
@@ -818,17 +906,21 @@
 	//	 stack - array with parent tree of the xml element,
 	//			 used to validate the nesting of elements
 
-	//-------------------------------------
-	//  Start Element Handler
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
-	public function open_tag($the_parser, $name, $attrs)
+	/**
+	 * Start Element Handler
+	 *
+	 * @param	string
+	 * @param	string
+	 * @return	void
+	 */
+	public function open_tag($the_parser, $name)
 	{
 		// If invalid nesting, then return
 		if ($this->xh[$the_parser]['isf'] > 1) return;
 
 		// Evaluate and check for correct nesting of XML elements
-
 		if (count($this->xh[$the_parser]['stack']) == 0)
 		{
 			if ($name != 'METHODRESPONSE' && $name != 'METHODCALL')
@@ -838,42 +930,37 @@
 				return;
 			}
 		}
-		else
+		// not top level element: see if parent is OK
+		elseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
 		{
-			// not top level element: see if parent is OK
-			if ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))
-			{
-				$this->xh[$the_parser]['isf'] = 2;
-				$this->xh[$the_parser]['isf_reason'] = 'XML-RPC element $name cannot be child of '.$this->xh[$the_parser]['stack'][0];
-				return;
-			}
+			$this->xh[$the_parser]['isf'] = 2;
+			$this->xh[$the_parser]['isf_reason'] = 'XML-RPC element $name cannot be child of '.$this->xh[$the_parser]['stack'][0];
+			return;
 		}
 
-		switch($name)
+		switch ($name)
 		{
 			case 'STRUCT':
 			case 'ARRAY':
 				// Creates array for child elements
-
 				$cur_val = array('value' => array(), 'type' => $name);
-
 				array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
-			break;
+				break;
 			case 'METHODNAME':
 			case 'NAME':
 				$this->xh[$the_parser]['ac'] = '';
-			break;
+				break;
 			case 'FAULT':
 				$this->xh[$the_parser]['isf'] = 1;
-			break;
+				break;
 			case 'PARAM':
 				$this->xh[$the_parser]['value'] = NULL;
-			break;
+				break;
 			case 'VALUE':
 				$this->xh[$the_parser]['vt'] = 'value';
 				$this->xh[$the_parser]['ac'] = '';
 				$this->xh[$the_parser]['lv'] = 1;
-			break;
+				break;
 			case 'I4':
 			case 'INT':
 			case 'STRING':
@@ -885,65 +972,70 @@
 				{
 					//two data elements inside a value: an error occurred!
 					$this->xh[$the_parser]['isf'] = 2;
-					$this->xh[$the_parser]['isf_reason'] = "'Twas a $name element following a ".$this->xh[$the_parser]['vt']." element inside a single value";
+					$this->xh[$the_parser]['isf_reason'] = "'Twas a ".$name.' element following a '
+										.$this->xh[$the_parser]['vt'].' element inside a single value';
 					return;
 				}
 
 				$this->xh[$the_parser]['ac'] = '';
-			break;
+				break;
 			case 'MEMBER':
 				// Set name of <member> to nothing to prevent errors later if no <name> is found
 				$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;
-			break;
+				break;
 			case 'DATA':
 			case 'METHODCALL':
 			case 'METHODRESPONSE':
 			case 'PARAMS':
 				// valid elements that add little to processing
-			break;
+				break;
 			default:
 				/// An Invalid Element is Found, so we have trouble
 				$this->xh[$the_parser]['isf'] = 2;
-				$this->xh[$the_parser]['isf_reason'] = "Invalid XML-RPC element found: $name";
-			break;
+				$this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;
+				break;
 		}
 
 		// Add current element name to stack, to allow validation of nesting
 		array_unshift($this->xh[$the_parser]['stack'], $name);
 
-		if ($name != 'VALUE') $this->xh[$the_parser]['lv'] = 0;
+		$name == 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;
 	}
-	// END
 
-	//-------------------------------------
-	//  End Element Handler
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * End Element Handler
+	 *
+	 * @param	string
+	 * @param	string
+	 * @return	void
+	 */
 	public function closing_tag($the_parser, $name)
 	{
 		if ($this->xh[$the_parser]['isf'] > 1) return;
 
 		// Remove current element from stack and set variable
 		// NOTE: If the XML validates, then we do not have to worry about
-		// the opening and closing of elements.  Nesting is checked on the opening
+		// the opening and closing of elements. Nesting is checked on the opening
 		// tag so we be safe there as well.
 
 		$curr_elem = array_shift($this->xh[$the_parser]['stack']);
 
-		switch($name)
+		switch ($name)
 		{
 			case 'STRUCT':
 			case 'ARRAY':
 				$cur_val = array_shift($this->xh[$the_parser]['valuestack']);
-				$this->xh[$the_parser]['value'] = ( ! isset($cur_val['values'])) ? array() : $cur_val['values'];
+				$this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();
 				$this->xh[$the_parser]['vt']	= strtolower($name);
-			break;
+				break;
 			case 'NAME':
 				$this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
-			break;
+				break;
 			case 'BOOLEAN':
 			case 'I4':
 			case 'INT':
@@ -957,56 +1049,39 @@
 				{
 					$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
 				}
-				elseif ($name=='DATETIME.ISO8601')
+				elseif ($name == 'DATETIME.ISO8601')
 				{
 					$this->xh[$the_parser]['vt']	= $this->xmlrpcDateTime;
 					$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
 				}
-				elseif ($name=='BASE64')
+				elseif ($name == 'BASE64')
 				{
 					$this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
 				}
-				elseif ($name=='BOOLEAN')
+				elseif ($name == 'BOOLEAN')
 				{
 					// Translated BOOLEAN values to TRUE AND FALSE
-					if ($this->xh[$the_parser]['ac'] == '1')
-					{
-						$this->xh[$the_parser]['value'] = TRUE;
-					}
-					else
-					{
-						$this->xh[$the_parser]['value'] = FALSE;
-					}
+					$this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];
 				}
 				elseif ($name=='DOUBLE')
 				{
 					// we have a DOUBLE
 					// we must check that only 0123456789-.<space> are characters here
-					if ( ! preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac']))
-					{
-						$this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND';
-					}
-					else
-					{
-						$this->xh[$the_parser]['value'] = (float) $this->xh[$the_parser]['ac'];
-					}
+					$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\t \.]+$/', $this->xh[$the_parser]['ac'])
+										? (float) $this->xh[$the_parser]['ac']
+										: 'ERROR_NON_NUMERIC_FOUND';
 				}
 				else
 				{
 					// we have an I4/INT
 					// we must check that only 0123456789-<space> are characters here
-					if ( ! preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac']))
-					{
-						$this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND';
-					}
-					else
-					{
-						$this->xh[$the_parser]['value'] = (int)$this->xh[$the_parser]['ac'];
-					}
+					$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
+										? (int) $this->xh[$the_parset]['ac']
+										: 'ERROR_NON_NUMERIC_FOUND';
 				}
 				$this->xh[$the_parser]['ac'] = '';
 				$this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
-			break;
+				break;
 			case 'VALUE':
 				// This if() detects if no scalar was inside <VALUE></VALUE>
 				if ($this->xh[$the_parser]['vt']=='value')
@@ -1028,44 +1103,49 @@
 					// Struct
 					$this->xh[$the_parser]['value'] = $temp;
 				}
-			break;
+				break;
 			case 'MEMBER':
-				$this->xh[$the_parser]['ac']='';
+				$this->xh[$the_parser]['ac'] = '';
 
 				// If value add to array in the stack for the last element built
 				if ($this->xh[$the_parser]['value'])
 				{
 					$this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
 				}
-			break;
+				break;
 			case 'DATA':
-				$this->xh[$the_parser]['ac']='';
-			break;
+				$this->xh[$the_parser]['ac'] = '';
+				break;
 			case 'PARAM':
 				if ($this->xh[$the_parser]['value'])
 				{
 					$this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
 				}
-			break;
+				break;
 			case 'METHODNAME':
 				$this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);
-			break;
+				break;
 			case 'PARAMS':
 			case 'FAULT':
 			case 'METHODCALL':
 			case 'METHORESPONSE':
 				// We're all good kids with nuthin' to do
-			break;
+				break;
 			default:
-				// End of an Invalid Element.  Taken care of during the opening tag though
-			break;
+				// End of an Invalid Element. Taken care of during the opening tag though
+				break;
 		}
 	}
 
-	//-------------------------------------
-	//  Parses Character Data
-	//-------------------------------------
+	// --------------------------------------------------------------------
 
+	/**
+	 * Parse character data
+	 *
+	 * @param	string
+	 * @param	string
+	 * @return	void
+	 */
 	public function character_data($the_parser, $data)
 	{
 		if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
@@ -1078,7 +1158,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'] = '';
 			}
@@ -1087,12 +1167,27 @@
 		}
 	}
 
+	// --------------------------------------------------------------------
 
+	/**
+	 * Add parameter
+	 *
+	 * @param	mixed
+	 * @return	void
+	 */
 	public function addParam($par)
 	{
 		$this->params[] = $par;
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Output parameters
+	 *
+	 * @param	array
+	 * @return	array
+	 */
 	public function output_parameters($array = FALSE)
 	{
 		$CI =& get_instance();
@@ -1113,30 +1208,36 @@
 				}
 			}
 
-			$parameters = $array;
+			return $array;
 		}
-		else
+
+		$parameters = array();
+
+		for ($i = 0, $c = count($this->params); $i < $c; $i++)
 		{
-			$parameters = array();
+			$a_param = $this->decode_message($this->params[$i]);
 
-			for ($i = 0, $c = count($this->params); $i < $c; $i++)
+			if (is_array($a_param))
 			{
-				$a_param = $this->decode_message($this->params[$i]);
-
-				if (is_array($a_param))
-				{
-					$parameters[] = $this->output_parameters($a_param);
-				}
-				else
-				{
-					$parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
-				}
+				$parameters[] = $this->output_parameters($a_param);
+			}
+			else
+			{
+				$parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;
 			}
 		}
 
 		return $parameters;
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Decode message
+	 *
+	 * @param	object
+	 * @return	mixed
+	 */
 	public function decode_message($param)
 	{
 		$kind = $param->kindOf();
@@ -1151,7 +1252,7 @@
 			$b = current($param->me);
 			$arr = array();
 
-			for($i = 0, $c = count($b); $i < $c; $i++)
+			for ($i = 0, $c = count($b); $i < $c; $i++)
 			{
 				$arr[] = $this->decode_message($param->me['array'][$i]);
 			}
@@ -1172,8 +1273,7 @@
 		}
 	}
 
-}
-// End XML_RPC_Messages class
+} // END XML_RPC_Message Class
 
 /**
  * XML-RPC Values class
@@ -1187,6 +1287,13 @@
 	public $me	= array();
 	public $mytype	= 0;
 
+	/**
+	 * Constructor
+	 *
+	 * @param	mixed
+	 * @param	string
+	 * @return	void
+	 */
 	public function __construct($val = -1, $type = '')
 	{
 		parent::__construct();
@@ -1210,11 +1317,20 @@
 		}
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Add scalar value
+	 *
+	 * @param	scalar
+	 * @param	string
+	 * @return	int
+	 */
 	public function addScalar($val, $type = 'string')
 	{
 		$typeof = $this->xmlrpcTypes[$type];
 
-		if ($this->mytype==1)
+		if ($this->mytype == 1)
 		{
 			echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
 			return 0;
@@ -1228,7 +1344,7 @@
 
 		if ($type == $this->xmlrpcBoolean)
 		{
-			$val = (strcasecmp($val,'true') === 0 OR $val == 1 OR ($val == TRUE && strcasecmp($val, 'false'))) ? 1 : 0;
+			$val = (int) (strcasecmp($val,'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));
 		}
 
 		if ($this->mytype == 2)
@@ -1244,9 +1360,18 @@
 			$this->me[$type] = $val;
 			$this->mytype = $typeof;
 		}
+
 		return 1;
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Add array value
+	 *
+	 * @param	array
+	 * @return	int
+	 */
 	public function addArray($vals)
 	{
 		if ($this->mytype != 0)
@@ -1260,6 +1385,14 @@
 		return 1;
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Add struct value
+	 *
+	 * @param	object
+	 * @return	int
+	 */
 	public function addStruct($vals)
 	{
 		if ($this->mytype != 0)
@@ -1272,29 +1405,37 @@
 		return 1;
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Get value type
+	 *
+	 * @return	string
+	 */
 	public function kindOf()
 	{
-		switch($this->mytype)
+		switch ($this->mytype)
 		{
-			case 3:
-				return 'struct';
-				break;
-			case 2:
-				return 'array';
-				break;
-			case 1:
-				return 'scalar';
-				break;
-			default:
-				return 'undef';
+			case 3: return 'struct';
+			case 2: return 'array';
+			case 1: return 'scalar';
+			default: return 'undef';
 		}
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Serialize data
+	 *
+	 * @param	string
+	 * @param	mixed
+	 */
 	public function serializedata($typ, $val)
 	{
 		$rs = '';
 
-		switch($this->xmlrpcTypes[$typ])
+		switch ($this->xmlrpcTypes[$typ])
 		{
 			case 3:
 				// struct
@@ -1305,11 +1446,11 @@
 					$rs .= "<member>\n<name>{$key2}</name>\n".$this->serializeval($val2)."</member>\n";
 				}
 				$rs .= '</struct>';
-			break;
+				break;
 			case 2:
 				// array
 				$rs .= "<array>\n<data>\n";
-				for($i = 0, $c = count($val); $i < $c; $i++)
+				for ($i = 0, $c = count($val); $i < $c; $i++)
 				{
 					$rs .= $this->serializeval($val[$i]);
 				}
@@ -1320,29 +1461,45 @@
 				switch ($typ)
 				{
 					case $this->xmlrpcBase64:
-						$rs .= "<{$typ}>" . base64_encode((string)$val) . "</{$typ}>\n";
-					break;
+						$rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.">\n";
+						break;
 					case $this->xmlrpcBoolean:
-						$rs .= "<{$typ}>" . ((bool)$val ? '1' : '0') . "</{$typ}>\n";
-					break;
+						$rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.">\n";
+						break;
 					case $this->xmlrpcString:
-						$rs .= "<{$typ}>" . htmlspecialchars((string)$val). "</{$typ}>\n";
-					break;
+						$rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.">\n";
+						break;
 					default:
-						$rs .= "<{$typ}>{$val}</{$typ}>\n";
-					break;
+						$rs .= '<'.$typ.'>'.$val.'</'.$typ.">\n";
+						break;
 				}
 			default:
-			break;
+				break;
 		}
+
 		return $rs;
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Serialize class
+	 *
+	 * @return	string
+	 */
 	public function serialize_class()
 	{
 		return $this->serializeval($this);
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Serialize value
+	 *
+	 * @param	object
+	 * @return	string
+	 */
 	public function serializeval($o)
 	{
 		$ar = $o->me;
@@ -1352,26 +1509,35 @@
 		return "<value>\n".$this->serializedata($typ, $val)."</value>\n";
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Scalar value
+	 *
+	 * @return	mixed
+	 */
 	public function scalarval()
 	{
 		reset($this->me);
 		return current($this->me);
 	}
 
+	// --------------------------------------------------------------------
 
-	//-------------------------------------
-	// Encode time in ISO-8601 form.
-	//-------------------------------------
-
-	// Useful for sending time in XML-RPC
-
-	public function iso8601_encode($time, $utc = 0)
+	/**
+	 * Encode time in ISO-8601 form.
+	 * Useful for sending time in XML-RPC
+	 *
+	 * @param	int	unix timestamp
+	 * @param	bool
+	 * @return	string
+	*/
+	public function iso8601_encode($time, $utc = FALSE)
 	{
 		return ($utc) ? strftime('%Y%m%dT%H:%i:%s', $time) : gmstrftime('%Y%m%dT%H:%i:%s', $time);
 	}
 
-}
-// END XML_RPC_Values Class
+} // END XML_RPC_Values Class
 
 /* End of file Xmlrpc.php */
 /* Location: ./system/libraries/Xmlrpc.php */
\ No newline at end of file
diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php
index e91e2a2..8043854 100644
--- a/system/libraries/Zip.php
+++ b/system/libraries/Zip.php
@@ -279,7 +279,7 @@
 	 */
 	public function read_dir($path, $preserve_filepath = TRUE, $root_path = NULL)
 	{
-		$path = rtrim($path, '/\\').'/';
+		$path = rtrim($path, '/\\').DIRECTORY_SEPARATOR;
 		if ( ! $fp = @opendir($path))
 		{
 			return FALSE;
@@ -288,7 +288,7 @@
 		// Set the original directory root for child dir's to use as relative
 		if ($root_path === NULL)
 		{
-			$root_path = dirname($path).'/';
+			$root_path = dirname($path).DIRECTORY_SEPARATOR;
 		}
 
 		while (FALSE !== ($file = readdir($fp)))
@@ -300,11 +300,11 @@
 
 			if (@is_dir($path.$file))
 			{
-				$this->read_dir($path.$file.'/', $preserve_filepath, $root_path);
+				$this->read_dir($path.$file.DIRECTORY_SEPARATOR, $preserve_filepath, $root_path);
 			}
 			elseif (FALSE !== ($data = file_get_contents($path.$file)))
 			{
-				$name = str_replace('\\', '/', $path);
+				$name = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $path);
 				if ($preserve_filepath === FALSE)
 				{
 					$name = str_replace($root_path, '', $name);
diff --git a/tests/codeigniter/database/DB_test.php b/tests/codeigniter/database/DB_test.php
new file mode 100644
index 0000000..9b93e22
--- /dev/null
+++ b/tests/codeigniter/database/DB_test.php
@@ -0,0 +1,49 @@
+<?php
+
+class DB_test extends CI_TestCase {
+
+	// ------------------------------------------------------------------------
+
+	public function test_db_invalid()
+	{
+		$connection = new Mock_Database_DB(array(
+			'undefined' => array(
+				'dsn' => '',
+				'hostname' => 'undefined',
+				'username' => 'undefined',
+				'password' => 'undefined',
+				'database' => 'undefined',
+				'dbdriver' => 'undefined',
+			),
+		));
+
+		$this->setExpectedException('InvalidArgumentException', 'CI Error: Invalid DB driver');
+
+		Mock_Database_DB::DB($connection->set_dsn('undefined'), TRUE);
+	}
+
+	// ------------------------------------------------------------------------
+
+	public function test_db_valid()
+	{
+		$config = Mock_Database_DB::config(DB_DRIVER);
+		$connection = new Mock_Database_DB($config);
+		$db = Mock_Database_DB::DB($connection->set_dsn(DB_DRIVER), TRUE);
+
+		$this->assertTrue($db instanceof CI_DB);
+		$this->assertTrue($db instanceof CI_DB_Driver);
+	}
+
+	// ------------------------------------------------------------------------
+
+	public function test_db_failover()
+	{
+		$config = Mock_Database_DB::config(DB_DRIVER);
+		$connection = new Mock_Database_DB($config);
+		$db = Mock_Database_DB::DB($connection->set_dsn(DB_DRIVER.'_failover'), TRUE);
+
+		$this->assertTrue($db instanceof CI_DB);
+		$this->assertTrue($db instanceof CI_DB_Driver);
+	}
+	
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/.gitkeep b/tests/codeigniter/database/query_builder/.gitkeep
similarity index 100%
rename from tests/codeigniter/database/.gitkeep
rename to tests/codeigniter/database/query_builder/.gitkeep
diff --git a/tests/codeigniter/helpers/form_helper_test.php b/tests/codeigniter/helpers/form_helper_test.php
new file mode 100644
index 0000000..80bace9
--- /dev/null
+++ b/tests/codeigniter/helpers/form_helper_test.php
@@ -0,0 +1,252 @@
+<?php
+
+require BASEPATH . 'core/Common.php';
+require BASEPATH . 'helpers/form_helper.php';
+
+class Form_helper_test extends CI_TestCase 
+{
+	public function test_form_hidden()
+	{				
+		$expected = <<<EOH
+
+<input type="hidden" name="username" value="johndoe" />
+
+EOH;
+	
+		$this->assertEquals($expected, form_hidden('username', 'johndoe'));
+	}
+	
+	public function test_form_input()
+	{
+		$expected = <<<EOH
+<input type="text" name="username" value="johndoe" id="username" maxlength="100" size="50" style="width:50%"  />
+
+EOH;
+	
+		$data = array(
+			'name'        => 'username',
+			'id'          => 'username',
+			'value'       => 'johndoe',
+			'maxlength'   => '100',
+			'size'        => '50',
+			'style'       => 'width:50%',
+		);
+
+		$this->assertEquals($expected, form_input($data));
+	}
+	
+	public function test_form_password()
+	{				
+		$expected = <<<EOH
+<input type="password" name="password" value=""  />
+
+EOH;
+	
+		$this->assertEquals($expected, form_password('password'));
+	}
+	
+	public function test_form_upload()
+	{				
+		$expected = <<<EOH
+<input type="file" name="attachment" value=""  />
+
+EOH;
+	
+		$this->assertEquals($expected, form_upload('attachment'));
+	}
+	
+	public function test_form_textarea()
+	{				
+		$expected = <<<EOH
+<textarea name="notes" cols="40" rows="10" >Notes</textarea>
+
+EOH;
+	
+		$this->assertEquals($expected, form_textarea('notes', 'Notes'));
+	}
+	
+	public function test_form_dropdown()
+	{
+		$expected = <<<EOH
+<select name="shirts">
+<option value="small">Small Shirt</option>
+<option value="med">Medium Shirt</option>
+<option value="large" selected="selected">Large Shirt</option>
+<option value="xlarge">Extra Large Shirt</option>
+</select>
+
+EOH;
+		
+		$options = array(
+			'small'  => 'Small Shirt',
+			'med'    => 'Medium Shirt',
+			'large'   => 'Large Shirt',
+			'xlarge' => 'Extra Large Shirt',
+		);
+		
+		$this->assertEquals($expected, form_dropdown('shirts', $options, 'large'));
+		
+		$expected = <<<EOH
+<select name="shirts" multiple="multiple">
+<option value="small" selected="selected">Small Shirt</option>
+<option value="med">Medium Shirt</option>
+<option value="large" selected="selected">Large Shirt</option>
+<option value="xlarge">Extra Large Shirt</option>
+</select>
+
+EOH;
+		
+		$shirts_on_sale = array('small', 'large');
+		
+		$this->assertEquals($expected, form_dropdown('shirts', $options, $shirts_on_sale));
+		
+		$options = array(
+			'Swedish Cars' => array(
+				'volvo'  => 'Volvo',
+				'saab'    => 'Saab'
+			),
+			'German Cars' => array(
+				'mercedes'  => 'Mercedes',
+				'audi'    => 'Audi'
+			)
+		);
+		
+		$expected = <<<EOH
+<select name="cars" multiple="multiple">
+<optgroup label="Swedish Cars">
+<option value="volvo" selected="selected">Volvo</option>
+<option value="saab">Saab</option>
+</optgroup>
+<optgroup label="German Cars">
+<option value="mercedes">Mercedes</option>
+<option value="audi" selected="selected">Audi</option>
+</optgroup>
+</select>
+
+EOH;
+		
+		$cars_on_sale = array('volvo', 'audi');
+		
+		$this->assertEquals($expected, form_dropdown('cars', $options, $cars_on_sale));
+		
+	}
+	
+	public function test_form_multiselect()
+	{
+		$expected = <<<EOH
+<select name="shirts[]"  multiple="multiple">
+<option value="small">Small Shirt</option>
+<option value="med" selected="selected">Medium Shirt</option>
+<option value="large" selected="selected">Large Shirt</option>
+<option value="xlarge">Extra Large Shirt</option>
+</select>
+
+EOH;
+		
+		$options = array(
+                  'small'  => 'Small Shirt',
+                  'med'    => 'Medium Shirt',
+                  'large'   => 'Large Shirt',
+                  'xlarge' => 'Extra Large Shirt',
+                );
+		
+		$this->assertEquals($expected, form_multiselect('shirts[]', $options, array('med', 'large')));
+	}
+	
+	public function test_form_fieldset()
+	{
+		$expected = <<<EOH
+<fieldset>
+<legend>Address Information</legend>
+
+EOH;
+		
+		$this->assertEquals($expected, form_fieldset('Address Information'));
+	}
+
+	public function test_form_fieldset_close()
+	{
+		$expected = <<<EOH
+</fieldset></div></div>
+EOH;
+		
+		$this->assertEquals($expected, form_fieldset_close('</div></div>'));
+	}
+	
+	public function test_form_checkbox()
+	{
+		$expected = <<<EOH
+<input type="checkbox" name="newsletter" value="accept" checked="checked"  />
+
+EOH;
+
+		$this->assertEquals($expected, form_checkbox('newsletter', 'accept', TRUE));
+	}
+	
+	public function test_form_radio()
+	{
+		$expected = <<<EOH
+<input type="radio" name="newsletter" value="accept" checked="checked"  />
+
+EOH;
+
+		$this->assertEquals($expected, form_radio('newsletter', 'accept', TRUE));
+	}
+	
+	public function test_form_submit()
+	{
+		$expected = <<<EOH
+<input type="submit" name="mysubmit" value="Submit Post!"  />
+
+EOH;
+
+		$this->assertEquals($expected, form_submit('mysubmit', 'Submit Post!'));
+	}
+	
+	public function test_form_label()
+	{
+		$expected = <<<EOH
+<label for="username">What is your Name</label>
+EOH;
+
+		$this->assertEquals($expected, form_label('What is your Name', 'username'));
+	}
+	
+	public function test_form_reset()
+	{
+		$expected = <<<EOH
+<input type="reset" name="myreset" value="Reset"  />
+
+EOH;
+
+		$this->assertEquals($expected, form_reset('myreset', 'Reset'));
+	}
+	
+	public function test_form_button()
+	{
+		$expected = <<<EOH
+<button name="name" type="button" >content</button>
+
+EOH;
+
+		$this->assertEquals($expected, form_button('name','content'));
+	}
+	
+	public function test_form_close()
+	{
+		$expected = <<<EOH
+</form></div></div>
+EOH;
+
+		$this->assertEquals($expected, form_close('</div></div>'));
+	}
+	
+	public function test_form_prep()
+	{
+		$expected = "Here is a string containing &quot;quoted&quot; text.";
+		
+		$this->assertEquals($expected, form_prep('Here is a string containing "quoted" text.'));
+	}
+}
+
+/* End of file form_helper_test.php */
\ No newline at end of file
diff --git a/tests/mocks/autoloader.php b/tests/mocks/autoloader.php
deleted file mode 100644
index dd59292..0000000
--- a/tests/mocks/autoloader.php
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-
-// This autoloader provide convinient way to working with mock object
-// make the test looks natural. This autoloader support cascade file loading as well
-// within mocks directory.
-//
-// Prototype :
-//
-// include_once('Mock_Core_Loader') 					// Will load ./mocks/core/loader.php
-// $mock_table = new Mock_Libraries_Table(); 			// Will load ./mocks/libraries/table.php
-// $mock_database_driver = new Mock_Database_Driver();	// Will load ./mocks/database/driver.php 
-// and so on...
-function autoload($class) 
-{
-	$dir = realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR;
-
-	$ci_core = array(
-		'Benchmark', 'Config', 'Controller',
-		'Exceptions', 'Hooks', 'Input',
-		'Lang', 'Loader', 'Model',
-		'Output', 'Router', 'Security',
-		'URI', 'Utf8',
-	);
-
-	$ci_libraries = array(
-		'Calendar', 'Cart', 'Driver',
-		'Email', 'Encrypt', 'Form_validation',
-		'Ftp', 'Image_lib', 'Javascript',
-		'Log', 'Migration', 'Pagination',
-		'Parser', 'Profiler', 'Session',
-		'Table', 'Trackback', 'Typography',
-		'Unit_test', 'Upload', 'User_agent',
-		'Xmlrpc', 'Zip',
-	);
-
-	if (strpos($class, 'Mock_') === 0)
-	{
-		$class = str_replace(array('Mock_', '_'), array('', DIRECTORY_SEPARATOR), $class);
-		$class = strtolower($class);
-	}
-	elseif (strpos($class, 'CI_') === 0)
-	{
-		$fragments = explode('_', $class, 2);
-		$subclass = next($fragments);
-
-		if (in_array($subclass, $ci_core))
-		{
-			$dir = BASEPATH.'core'.DIRECTORY_SEPARATOR;
-			$class = $subclass;
-		}
-		elseif (in_array($subclass, $ci_libraries))
-		{
-			$dir = BASEPATH.'libraries'.DIRECTORY_SEPARATOR;
-			$class = $subclass;
-		}
-		else
-		{
-			$class = strtolower($class);
-		}
-	}
-
-	$file = $dir.$class.'.php';
-
-	if ( ! file_exists($file))
-	{
-		$trace = debug_backtrace();
-
-		// If the autoload call came from `class_exists` or `file_exists`, 
-		// we skipped and return FALSE
-		if ($trace[2]['function'] == 'class_exists' OR $trace[2]['function'] == 'file_exists')
-		{
-			return FALSE;
-		}
-
-	    throw new InvalidArgumentException("Unable to load $class.");
-	}
-
-	include_once($file);
-}
\ No newline at end of file
diff --git a/tests/mocks/ci_testcase.php b/tests/mocks/ci_testcase.php
deleted file mode 100644
index f327e6b..0000000
--- a/tests/mocks/ci_testcase.php
+++ /dev/null
@@ -1,196 +0,0 @@
-<?php
-
-class CI_TestCase extends PHPUnit_Framework_TestCase {
-	
-	protected $ci_config;
-	protected $ci_instance;
-	protected static $ci_test_instance;
-		
-	private $global_map = array(
-		'benchmark'	=> 'bm',
-		'config'	=> 'cfg',
-		'hooks'		=> 'ext',
-		'utf8'		=> 'uni',
-		'router'	=> 'rtr',
-		'output'	=> 'out',
-		'security'	=> 'sec',
-		'input'		=> 'in',
-		'lang'		=> 'lang',
-		'loader'	=> 'load',
-		'model'		=> 'model'
-	);
-	
-	// --------------------------------------------------------------------
-	
-	public function __construct()
-	{
-		parent::__construct();
-		
-		$this->ci_config = array();
-	}
-	
-	// --------------------------------------------------------------------
-	
-	public function setUp()
-	{
-		if (method_exists($this, 'set_up'))
-		{
-			$this->set_up();
-		}
-	}
-	
-	// --------------------------------------------------------------------
-	
-	public function tearDown() 
-	{
-		if (method_exists($this, 'tear_down'))
-		{
-			$this->tear_down();
-		}
-	}
-
-	// --------------------------------------------------------------------
-	
-	public static function instance()
-	{
-		return self::$ci_test_instance;
-	}
-	
-	// --------------------------------------------------------------------
-	
-	function ci_set_config($key, $val = '')
-	{
-		if (is_array($key))
-		{
-			$this->ci_config = $key;
-		}
-		else
-		{
-			$this->ci_config[$key] = $val;
-		}
-	}
-
-	// --------------------------------------------------------------------
-	
-	function ci_get_config()
-	{
-		return $this->ci_config;
-	}
-	
-	// --------------------------------------------------------------------
-	
-	function ci_instance($obj = FALSE)
-	{
-		if ( ! is_object($obj))
-		{
-			return $this->ci_instance;
-		}
-		
-		$this->ci_instance = $obj;
-	}
-	
-	// --------------------------------------------------------------------
-	
-	function ci_instance_var($name, $obj = FALSE)
-	{
-		if ( ! is_object($obj))
-		{
-			return $this->ci_instance->$name;
-		}
-		
-		$this->ci_instance->$name =& $obj;
-	}
-	
-	// --------------------------------------------------------------------
-
-	/**
-	 * Grab a core class
-	 *
-	 * Loads the correct core class without extensions
-	 * and returns a reference to the class name in the
-	 * globals array with the correct key. This way the
-	 * test can modify the variable it assigns to and
-	 * still maintain the global.
-	 */
-	function &ci_core_class($name)
-	{
-		$name = strtolower($name);
-		
-		if (isset($this->global_map[$name]))
-		{
-			$class_name = ucfirst($name);
-			$global_name = $this->global_map[$name];
-		}
-		elseif (in_array($name, $this->global_map))
-		{
-			$class_name = ucfirst(array_search($name, $this->global_map));
-			$global_name = $name;
-		}
-		else
-		{
-			throw new Exception('Not a valid core class.');
-		}
-		
-		if ( ! class_exists('CI_'.$class_name))
-		{
-			require_once BASEPATH.'core/'.$class_name.'.php';
-		}
-		
-		$GLOBALS[strtoupper($global_name)] = 'CI_'.$class_name;
-		return $GLOBALS[strtoupper($global_name)];
-	}
-	
-	// --------------------------------------------------------------------
-	
-	// convenience function for global mocks
-	function ci_set_core_class($name, $obj)
-	{
-		$orig =& $this->ci_core_class($name);
-		$orig = $obj;
-	}
-	
-	// --------------------------------------------------------------------
-	// Internals
-	// --------------------------------------------------------------------
-	
-	/**
-	 * Overwrite runBare
-	 *
-	 * PHPUnit instantiates the test classes before
-	 * running them individually. So right before a test
-	 * runs we set our instance. Normally this step would
-	 * happen in setUp, but someone is bound to forget to
-	 * call the parent method and debugging this is no fun.
-	 */
-	public function runBare()
-	{
-		self::$ci_test_instance = $this;
-		parent::runBare();
-	}
-
-	// --------------------------------------------------------------------
-	
-	function helper($name)
-	{
-		require_once(BASEPATH.'helpers/'.$name.'_helper.php');
-	}
-
-	// --------------------------------------------------------------------
-	
-	/**
-	 * This overload is useful to create a stub, that need to have a specific method.
-	 */
-	function __call($method, $args)
-	{
-		if ($this->{$method} instanceof Closure) 
-		{
-			return call_user_func_array($this->{$method},$args);
-		} 
-		else 
-		{
-			return parent::__call($method, $args);
-		}
-	}
-}
-
-// EOF
\ No newline at end of file
diff --git a/tests/mocks/core/common.php b/tests/mocks/core/common.php
deleted file mode 100644
index fc94d7f..0000000
--- a/tests/mocks/core/common.php
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-
-// Set up the global CI functions in their most minimal core representation
-
-function &get_instance() 
-{
-	$test = CI_TestCase::instance();
-	$instance = $test->ci_instance();
-	return $instance;
-}
-
-// --------------------------------------------------------------------
-
-function &get_config() {
-	$test = CI_TestCase::instance();
-	$config = $test->ci_get_config();
-		
-	return $config;
-}
-
-function config_item($item)
-{
-	$config =& get_config();
-	
-	if ( ! isset($config[$item]))
-	{
-		return FALSE;
-	}
-	
-	return $config[$item];
-}
-
-// --------------------------------------------------------------------
-
-function load_class($class, $directory = 'libraries', $prefix = 'CI_')
-{
-	if ($directory != 'core' OR $prefix != 'CI_')
-	{
-		throw new Exception('Not Implemented: Non-core load_class()');
-	}
-	
-	$test = CI_TestCase::instance();
-	
-	$obj =& $test->ci_core_class($class);
-	
-	if (is_string($obj))
-	{
-		throw new Exception('Bad Isolation: Use ci_set_core_class to set '.$class.'');
-	}
-	
-	return $obj;
-}
-
-// This is sort of meh. Should probably be mocked up with
-// controllable output, so that we can test some of our
-// security code. The function itself will be tested in the
-// bootstrap testsuite.
-// --------------------------------------------------------------------
-
-function remove_invisible_characters($str, $url_encoded = TRUE)
-{
-	$non_displayables = array();
-	
-	// every control character except newline (dec 10)
-	// carriage return (dec 13), and horizontal tab (dec 09)
-	
-	if ($url_encoded)
-	{
-		$non_displayables[] = '/%0[0-8bcef]/';	// url encoded 00-08, 11, 12, 14, 15
-		$non_displayables[] = '/%1[0-9a-f]/';	// url encoded 16-31
-	}
-	
-	$non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S';	// 00-08, 11, 12, 14-31, 127
-
-	do
-	{
-		$str = preg_replace($non_displayables, '', $str, -1, $count);
-	}
-	while ($count);
-
-	return $str;
-}
-
-
-// Clean up error messages
-// --------------------------------------------------------------------
-
-function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
-{
-	throw new RuntimeException('CI Error: '.$message);
-}
-
-function show_404($page = '', $log_error = TRUE)
-{
-	throw new RuntimeException('CI Error: 404');
-}
-
-function _exception_handler($severity, $message, $filepath, $line)
-{
-	throw new RuntimeException('CI Exception: '.$message.' | '.$filepath.' | '.$line);
-}
-
-
-// We assume a few things about our environment ...
-// --------------------------------------------------------------------
-
-function is_php($version = '5.0.0')
-{
-	return ! (version_compare(PHP_VERSION, $version) < 0);
-}
-
-function is_really_writable($file)
-{
-	return is_writable($file);
-}
-
-function is_loaded()
-{
-	throw new Exception('Bad Isolation: mock up environment');
-}
-
-function log_message($level = 'error', $message, $php_error = FALSE)
-{
-	return TRUE;
-}
-
-function set_status_header($code = 200, $text = '')
-{
-	return TRUE;
-}
-
-// EOF
\ No newline at end of file
diff --git a/tests/mocks/core/loader.php b/tests/mocks/core/loader.php
deleted file mode 100644
index d4b29bb..0000000
--- a/tests/mocks/core/loader.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-class Mock_Core_Loader extends CI_Loader {
-	
-	/**
-	 * Since we use paths to load up models, views, etc, we need the ability to
-	 * mock up the file system so when core tests are run, we aren't mucking
-	 * in the application directory.  this will give finer grained control over
-	 * these tests.  So yeah, while this looks odd, I need to overwrite protected
-	 * class vars in the loader.  So here we go...
-	 *
-	 * @covers CI_Loader::__construct()
-	 */
-	public function __construct()
-	{
-		vfsStreamWrapper::register();
-		vfsStreamWrapper::setRoot(new vfsStreamDirectory('application'));
-		
-		$this->models_dir 	= vfsStream::newDirectory('models')->at(vfsStreamWrapper::getRoot());
-		$this->libs_dir 	= vfsStream::newDirectory('libraries')->at(vfsStreamWrapper::getRoot());
-		$this->helpers_dir 	= vfsStream::newDirectory('helpers')->at(vfsStreamWrapper::getRoot());
-		$this->views_dir 	= vfsStream::newDirectory('views')->at(vfsStreamWrapper::getRoot());
-		
-		$this->_ci_ob_level  		= ob_get_level();
-		$this->_ci_library_paths	= array(vfsStream::url('application').'/', BASEPATH);
-		$this->_ci_helper_paths 	= array(vfsStream::url('application').'/', BASEPATH);
-		$this->_ci_model_paths 		= array(vfsStream::url('application').'/');
-		$this->_ci_view_paths 		= array(vfsStream::url('application').'/views/' => TRUE);
-	}
-}
\ No newline at end of file
diff --git a/tests/mocks/core/uri.php b/tests/mocks/core/uri.php
deleted file mode 100644
index b694609..0000000
--- a/tests/mocks/core/uri.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-class Mock_Core_URI extends CI_URI {
-	
-	public function __construct()
-	{
-		$test = CI_TestCase::instance();
-		$cls =& $test->ci_core_class('cfg');
-		
-		// set predictable config values
-		$test->ci_set_config(array(
-			'index_page'		=> 'index.php',
-			'base_url'			=> 'http://example.com/',
-			'subclass_prefix'	=> 'MY_'
-		));
-
-		$this->config = new $cls;	
-
-	}
-	
-	protected function _is_cli_request()
-	{
-		return FALSE;
-	}
-}
\ No newline at end of file
diff --git a/tests/mocks/database/ci_test.sqlite b/tests/mocks/database/ci_test.sqlite
new file mode 100755
index 0000000..37ce4f8
--- /dev/null
+++ b/tests/mocks/database/ci_test.sqlite
Binary files differ
diff --git a/tests/mocks/database/config/mysql.php b/tests/mocks/database/config/mysql.php
new file mode 100644
index 0000000..ace0a31
--- /dev/null
+++ b/tests/mocks/database/config/mysql.php
@@ -0,0 +1,34 @@
+<?php
+
+return array(
+	
+	// Typical Database configuration
+	'mysql' => array(
+		'dsn' => '',
+		'hostname' => 'localhost',
+		'username' => 'travis',
+		'password' => '',
+		'database' => 'ci_test',
+		'dbdriver' => 'mysql',
+	),
+
+	// Database configuration with failover
+	'mysql_failover' => array(
+		'dsn' => '',
+		'hostname' => 'localhost',
+		'username' => 'not_travis',
+		'password' => 'wrong password',
+		'database' => 'not_ci_test',
+		'dbdriver' => 'mysql',
+		'failover' => array(
+			array(
+				'dsn' => '',
+				'hostname' => 'localhost',
+				'username' => 'travis',
+				'password' => '',
+				'database' => 'ci_test',
+				'dbdriver' => 'mysql',
+			),
+		),
+	),
+);
\ No newline at end of file
diff --git a/tests/mocks/database/config/pgsql.php b/tests/mocks/database/config/pgsql.php
new file mode 100644
index 0000000..c06af8c
--- /dev/null
+++ b/tests/mocks/database/config/pgsql.php
@@ -0,0 +1,34 @@
+<?php
+
+return array(
+	
+	// Typical Database configuration
+	'pgsql' => array(
+		'dsn' => '',
+		'hostname' => 'localhost',
+		'username' => 'postgres',
+		'password' => '',
+		'database' => 'ci_test',
+		'dbdriver' => 'postgre',
+	),
+
+	// Database configuration with failover
+	'pgsql_failover' => array(
+		'dsn' => '',
+		'hostname' => 'localhost',
+		'username' => 'not_travis',
+		'password' => 'wrong password',
+		'database' => 'not_ci_test',
+		'dbdriver' => 'postgre',
+		'failover' => array(
+			array(
+				'dsn' => '',
+				'hostname' => 'localhost',
+				'username' => 'postgres',
+				'password' => '',
+				'database' => 'ci_test',
+				'dbdriver' => 'postgre',
+			),
+		),
+	),
+);
\ No newline at end of file
diff --git a/tests/mocks/database/config/sqlite.php b/tests/mocks/database/config/sqlite.php
new file mode 100644
index 0000000..8665e20
--- /dev/null
+++ b/tests/mocks/database/config/sqlite.php
@@ -0,0 +1,35 @@
+<?php
+$dbdriver = is_php('5.4') ? 'sqlite3' : 'sqlite';
+
+return array(
+
+	// Typical Database configuration
+	'sqlite' => array(
+		'dsn' => '',
+		'hostname' => 'localhost',
+		'username' => 'sqlite',
+		'password' => 'sqlite',
+		'database' => realpath(__DIR__.'/..').'/ci_test.sqlite',
+		'dbdriver' => $dbdriver,
+	),
+
+	// Database configuration with failover
+	'sqlite_failover' => array(
+		'dsn' => '',
+		'hostname' => 'localhost',
+		'username' => 'sqlite',
+		'password' => 'sqlite',
+		'database' => '../not_exists.sqlite',
+		'dbdriver' => $dbdriver,
+		'failover' => array(
+			array(
+				'dsn' => '',
+				'hostname' => 'localhost',
+				'username' => 'sqlite',
+				'password' => 'sqlite',
+				'database' => realpath(__DIR__.'/..').'/ci_testf.sqlite',
+				'dbdriver' => $dbdriver,
+			),
+		),
+	),
+);
\ No newline at end of file
diff --git a/tests/mocks/database/db.php b/tests/mocks/database/db.php
new file mode 100644
index 0000000..43a0d39
--- /dev/null
+++ b/tests/mocks/database/db.php
@@ -0,0 +1,101 @@
+<?php
+
+class Mock_Database_DB {
+
+	/**
+	 * @var array DB configuration
+	 */
+	private $config = array();
+	
+	/**
+	 * Prepare database configuration skeleton
+	 *
+	 * @param  array 	DB configuration to set
+	 * @return void
+	 */
+	public function __construct($config = array())
+	{
+		$this->config = $config;
+	}
+
+	/**
+	 * Build DSN connection string for DB driver instantiate process
+	 *
+	 * @param 	string 	Group name 		
+	 * @return 	string 	DSN Connection string
+	 */
+	public function set_dsn($group = 'default')
+	{
+		if ( ! isset($this->config[$group]))
+		{
+			throw new InvalidArgumentException('Group '.$group.' not exists');
+		}
+
+		$params = array(
+			'dbprefix' => '',
+			'pconnect' => FALSE,
+			'db_debug' => FALSE,
+			'cache_on' => FALSE,
+			'cachedir' => '',
+			'char_set' => 'utf8',
+			'dbcollat' => 'utf8_general_ci',
+			'swap_pre' => '',
+			'autoinit' => TRUE,
+			'stricton' => FALSE,
+		);
+
+		$config = array_merge($this->config[$group], $params);
+
+		if ( ! empty($config['dsn']))
+		{
+			$dsn = $config['dsn'];
+		}
+		else
+		{
+			$dsn = $config['dbdriver'].'://'.$config['username'].':'.$config['password']
+			       .'@'.$config['hostname'].'/'.$config['database'];
+
+		}
+
+		$other_params = array_slice($config, 6);
+
+		return $dsn.'?'.http_build_query($other_params);
+	}
+
+	/**
+	 * Return a database config array
+	 *
+	 * @see 	./config
+	 * @param 	string 		Driver based configuration
+	 * @return 	array 		
+	 */
+	public static function config($driver)
+	{
+		$dir = realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR;
+
+		return include($dir.'config'.DIRECTORY_SEPARATOR.$driver.'.php');
+	}
+
+	/**
+	 * Main DB method wrapper
+	 *
+	 * @param 	string 		Group or DSN string
+	 * @param 	bool 		
+	 * @return 	object 		
+	 */
+	public static function DB($group, $query_builder = FALSE)
+	{
+		include_once(BASEPATH.'database/DB.php');
+
+		try 
+		{
+			$db = DB($group, $query_builder);
+		}
+		catch (Exception $e)
+		{
+			throw new InvalidArgumentException($e->getMessage());
+		}
+
+		return $db;
+	}
+}
\ No newline at end of file
diff --git a/tests/mocks/database/.gitkeep b/tests/mocks/database/schema/.gitkeep
similarity index 100%
rename from tests/mocks/database/.gitkeep
rename to tests/mocks/database/schema/.gitkeep
diff --git a/tests/mocks/libraries/parser.php b/tests/mocks/libraries/parser.php
deleted file mode 100644
index 81dcfb3..0000000
--- a/tests/mocks/libraries/parser.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
-
-class Mock_Libraries_Parser extends CI_Parser {}
\ No newline at end of file
diff --git a/tests/mocks/libraries/table.php b/tests/mocks/libraries/table.php
deleted file mode 100644
index 1a6ff8d..0000000
--- a/tests/mocks/libraries/table.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-class Mock_Libraries_Table extends CI_Table {
-	
-	// Overide inaccesible private or protected method
-	public function __call($method, $params)
-	{
-		if (is_callable(array($this, '_'.$method)))
-		{
-			return call_user_func_array(array($this, '_'.$method), $params);
-		}
-
-		throw new BadMethodCallException('Method '.$method.' was not found');
-	}
-}
\ No newline at end of file
diff --git a/tests/mocks/libraries/typography.php b/tests/mocks/libraries/typography.php
deleted file mode 100644
index 0f76c57..0000000
--- a/tests/mocks/libraries/typography.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
-
-class Mock_Libraries_Typography extends CI_Typography {}
\ No newline at end of file
diff --git a/tests/mocks/libraries/useragent.php b/tests/mocks/libraries/useragent.php
deleted file mode 100644
index c957cde..0000000
--- a/tests/mocks/libraries/useragent.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
-
-class Mock_Libraries_UserAgent extends CI_User_agent {}
\ No newline at end of file
diff --git a/tests/phpunit.xml b/tests/phpunit.xml
deleted file mode 100644
index dfeecd1..0000000
--- a/tests/phpunit.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<phpunit 
-	bootstrap="Bootstrap.php"
-	colors="true"
-	convertNoticesToExceptions="true"
-	convertWarningsToExceptions="true"
-	stopOnError="false"
-	stopOnFailure="false"
-	stopOnIncomplete="false"
-	stopOnSkipped="false">
-	<testsuites>
-		<testsuite name="CodeIgniter Core Test Suite">
-			<file>./codeigniter/Setup_test.php</file>
-			<directory suffix="test.php">codeigniter/core</directory>
-			<directory suffix="test.php">codeigniter/helpers</directory>
-			<directory suffix="test.php">codeigniter/libraries</directory>
-			<!-- We'll worry about these later ...
-			<directory suffix="test.php">codeigniter/libraries</directory>
-			<directory suffix="test.php">codeigniter/helpers</directory>
-			-->
-		</testsuite>
-	</testsuites>
-	<filters>
-		<blacklist>
-			<directory suffix=".php">PEAR_INSTALL_DIR</directory>
-			<directory suffix=".php">PHP_LIBDIR</directory>
-			<directory suffix=".php">PROJECT_BASE.'tests'</directory>
-			<directory suffix=".php">'../system/core/CodeIgniter.php'</directory>
-		</blacklist>
-		<whitelist>
-			<!--
-			<directory suffix=".php">'../system/core'</directory>
-			-->
-		</whitelist>
-	</filters>
-</phpunit>
\ No newline at end of file
diff --git a/tests/travis/mysql.phpunit.xml b/tests/travis/mysql.phpunit.xml
new file mode 100644
index 0000000..44d6d6e
--- /dev/null
+++ b/tests/travis/mysql.phpunit.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit 
+	bootstrap="../Bootstrap.php"
+	colors="true"
+	convertNoticesToExceptions="true"
+	convertWarningsToExceptions="true"
+	stopOnError="false"
+	stopOnFailure="false"
+	stopOnIncomplete="false"
+	stopOnSkipped="false">
+	<php>
+        <const name="DB_DRIVER" value="mysql"/>
+    </php>
+	<testsuites>
+		<testsuite name="CodeIgniter Core Test Suite">
+			<file>../codeigniter/Setup_test.php</file>
+			<directory suffix="test.php">../codeigniter/core</directory>
+			<directory suffix="test.php">../codeigniter/helpers</directory>
+			<directory suffix="test.php">../codeigniter/libraries</directory>
+			<directory suffix="test.php">../codeigniter/database</directory>
+		</testsuite>
+	</testsuites>
+	<filters>
+		<blacklist>
+			<directory suffix=".php">PEAR_INSTALL_DIR</directory>
+			<directory suffix=".php">PHP_LIBDIR</directory>
+			<directory suffix=".php">PROJECT_BASE.'tests'</directory>
+			<directory suffix=".php">'../../system/core/CodeIgniter.php'</directory>
+		</blacklist>
+		<whitelist>
+			<!--
+			<directory suffix=".php">'../system/core'</directory>
+			-->
+		</whitelist>
+	</filters>
+</phpunit>
\ No newline at end of file
diff --git a/tests/travis/pgsql.phpunit.xml b/tests/travis/pgsql.phpunit.xml
new file mode 100644
index 0000000..9f52b40
--- /dev/null
+++ b/tests/travis/pgsql.phpunit.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit 
+	bootstrap="../Bootstrap.php"
+	colors="true"
+	convertNoticesToExceptions="true"
+	convertWarningsToExceptions="true"
+	stopOnError="false"
+	stopOnFailure="false"
+	stopOnIncomplete="false"
+	stopOnSkipped="false">
+	<php>
+        <const name="DB_DRIVER" value="pgsql"/>
+    </php>
+	<testsuites>
+		<testsuite name="CodeIgniter Core Test Suite">
+			<file>../codeigniter/Setup_test.php</file>
+			<directory suffix="test.php">../codeigniter/core</directory>
+			<directory suffix="test.php">../codeigniter/helpers</directory>
+			<directory suffix="test.php">../codeigniter/libraries</directory>
+			<directory suffix="test.php">../codeigniter/database</directory>
+		</testsuite>
+	</testsuites>
+	<filters>
+		<blacklist>
+			<directory suffix=".php">PEAR_INSTALL_DIR</directory>
+			<directory suffix=".php">PHP_LIBDIR</directory>
+			<directory suffix=".php">PROJECT_BASE.'tests'</directory>
+			<directory suffix=".php">'../../system/core/CodeIgniter.php'</directory>
+		</blacklist>
+		<whitelist>
+			<!--
+			<directory suffix=".php">'../system/core'</directory>
+			-->
+		</whitelist>
+	</filters>
+</phpunit>
\ No newline at end of file
diff --git a/tests/travis/sqlite.phpunit.xml b/tests/travis/sqlite.phpunit.xml
new file mode 100644
index 0000000..74ebb48
--- /dev/null
+++ b/tests/travis/sqlite.phpunit.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit 
+	bootstrap="../Bootstrap.php"
+	colors="true"
+	convertNoticesToExceptions="true"
+	convertWarningsToExceptions="true"
+	stopOnError="false"
+	stopOnFailure="false"
+	stopOnIncomplete="false"
+	stopOnSkipped="false">
+	<php>
+        <const name="DB_DRIVER" value="sqlite"/>
+    </php>
+	<testsuites>
+		<testsuite name="CodeIgniter Core Test Suite">
+			<file>../codeigniter/Setup_test.php</file>
+			<directory suffix="test.php">../codeigniter/core</directory>
+			<directory suffix="test.php">../codeigniter/helpers</directory>
+			<directory suffix="test.php">../codeigniter/libraries</directory>
+			<directory suffix="test.php">../codeigniter/database</directory>
+		</testsuite>
+	</testsuites>
+	<filters>
+		<blacklist>
+			<directory suffix=".php">PEAR_INSTALL_DIR</directory>
+			<directory suffix=".php">PHP_LIBDIR</directory>
+			<directory suffix=".php">PROJECT_BASE.'tests'</directory>
+			<directory suffix=".php">'../../system/core/CodeIgniter.php'</directory>
+		</blacklist>
+		<whitelist>
+			<!--
+			<directory suffix=".php">'../system/core'</directory>
+			-->
+		</whitelist>
+	</filters>
+</phpunit>
\ No newline at end of file
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 22235ee..3ad930e 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -50,6 +50,7 @@
    -  form_dropdown() will now also take an array for unity with other form helpers.
    -  set_realpath() can now also handle file paths as opposed to just directories.
    -  do_hash() now uses PHP's native hash() function, supporting more algorithms.
+   -  Added an optional paramater to ``delete_files()`` to enable it to skip deleting files such as .htaccess and index.html.
 
 -  Database
 
@@ -74,25 +75,35 @@
 	 -  Added _optimize_table() support for the :doc:`Database Utility Class <database/utilities>` (rebuilds table indexes).
    -  Added a constructor to the DB_result class and moved all driver-specific properties and logic out of the base DB_driver class to allow better abstraction.
    -  Removed limit() and order_by() support for UPDATE and DELETE queries in PostgreSQL driver. Postgres does not support those features.
-   -  Removed protect_identifiers() and renamed _protect_identifiers() to it instead - it was just an alias.
+   -  Removed protect_identifiers() and renamed internal method _protect_identifiers() to it instead - it was just an alias.
    -  MySQL and MySQLi drivers now require at least MySQL version 5.1.
    -  db_set_charset() now only requires one parameter (collation was only needed due to legacy support for MySQL versions prior to 5.1).
    -  Added DSN string support for CUBRID.
    -  Added persistent connections support for CUBRID.
-   -  Added DSN string support (Easy Connect and TNS) for Oracle.
    -  Added random ordering support for MSSQL.
    -  Added random ordering support for SQLSRV.
+   -  Added support for SQLite3 database driver.
+   -  Improved support of the Oracle (OCI8) driver, including:
+	 -  Added DSN string support (Easy Connect and TNS).
+	 -  Added support for dropping tables to :doc:`Database Forge <database/forge>`.
+	 -  Added support for listing database schemas to :doc:`Database Utilities <database/utilities>`.
+	 -  Generally improved for speed and cleaned up all of its components.
+	 -  *Row* result methods now really only fetch only the needed number of rows, instead of depending entirely on result().
+	 -  num_rows() is now only called explicitly by the developer and no longer re-executes statements.
+   -  Added replace() support for SQLite.
+   -  Renamed internal method _escape_identifiers() to escape_identifiers().
 
 -  Libraries
 
    -  Added max_filename_increment config setting for Upload library.
    -  CI_Loader::_ci_autoloader() is now a protected method.
-   -  Added custom filename to Email::attach() as $this->email->attach($filename, $disposition, $newname)
+   -  Added custom filename to Email::attach() as $this->email->attach($filename, $disposition, $newname).
+   -  Added possibility to send attachment as buffer string in Email::attach() as $this->email->attach($buffer, $disposition, $newname, $mime).
    -  Cart library changes include:
 	 -  It now auto-increments quantity's instead of just resetting it, this is the default behaviour of large e-commerce sites.
 	 -  Product Name strictness can be disabled via the Cart Library by switching "$product_name_safe"
 	 -  Added function remove() to remove a cart item, updating with quantity of 0 seemed like a hack but has remained to retain compatability
-   -  Image manipulation library changes include:
+   -  :doc:`Image Manipulation library <libraries/image_lib>` changes include:
 	 -  The initialize() method now only sets existing class properties.
 	 -  Added support for 3-length hex color values for wm_font_color and wm_shadow_color properties, as well as validation for them.
 	 -  Class properties wm_font_color, wm_shadow_color and wm_use_drop_shadow are now protected, to avoid breaking the text_watermark() method
@@ -101,14 +112,18 @@
    -  Minor speed optimizations and method & property visibility declarations in the Calendar Library.
    -  Removed SHA1 function in the :doc:`Encryption Library <libraries/encryption>`.
    -  Added $config['csrf_regeneration'] to the CSRF protection in the :doc:`Security library <libraries/security>`, which makes token regeneration optional.
+   -  :doc:`Form Validation library <libraries/form_validation>` changes include:
+	 -  Added method error_array() to return all error messages as an array.
+	 -  Added method set_data() to set an alternative data array to be validated instead of the default $_POST.
+	 -  Added method reset_validation(), which resets internal validation variables in case of multiple validation routines.
+	 -  Added support for setting error delimiters in the config file via $config['error_prefix'] and $config['error_suffix'].
+	 -  _execute() now considers input data to be invalid if a specified rule is not found.
+	 -  Removed method is_numeric() as it exists as a native PHP function and _execute() will find and use that (the 'is_numeric' rule itself is deprecated since 1.6.1).
+	 -  Native PHP functions used as rules can now accept an additional parameter, other than the data itself.
+   -  Changed the :doc:`Session Library <libraries/sessions>` to select only one row when using database sessions.
    -  Added all_flashdata() method to session class. Returns an associative array of only flashdata.
    -  Allowed for setting table class defaults in a config file.
-   -  Form Validation library now allows setting of error delimiters in the config file via $config['error_prefix'] and $config['error_suffix'].
-   -  Added function error_array() to return all error messages as an array in the Form_validation class.
-   -  Added function set_data() to Form_validation library, which can be used in place of the default $_POST array.
-   -  Added function reset_validation() to form validation library, which resets internal validation variables in case of multiple validation routines.
-   -  Changed the Session library to select only one row when using database sessions.
-   -  Added a Wincache driver to the `Caching Library <libraries/caching>`.
+   -  Added a Wincache driver to the :doc:`Caching Library <libraries/caching>`.
    -  Added dsn (delivery status notification) option to the :doc:`Email Library <libraries/email>`.
 
 -  Core
@@ -121,7 +136,8 @@
    -  Added method() to CI_Input to retrieve $_SERVER['REQUEST_METHOD'].
    -  Modified valid_ip() to use PHP's filter_var() in the :doc:`Input Library <libraries/input>`.
    -  Added support for HTTP-Only cookies with new config option ``cookie_httponly`` (default FALSE).
-   -  Renamed method _call_hook() to call_hook() in the :doc:`Hooks Library <general/hooks.html>`.
+   -  Renamed method _call_hook() to call_hook() in the :doc:`Hooks Library <general/hooks>`.
+   -  Added get_content_type() method to the :doc:`Output Library <libraries/output>`.
 
 Bug fixes for 3.0
 ------------------
@@ -175,11 +191,19 @@
 -  Fixed a bug (#940) - csrf_verify() used to set the CSRF cookie while processing a POST request with no actual POST data, which resulted in validating a request that should be considered invalid.
 -  Fixed a bug in PostgreSQL's escape_str() where it didn't properly escape LIKE wild characters.
 -  Fixed a bug in the library loader where some PHP versions wouldn't execute the class constructor.
+-  Fixed a bug (#88) - An unexisting property was used for configuration of the Memcache cache driver.
+-  Fixed a bug (#14) - create_database() method in the :doc:`Database Forge Library <database/forge>` didn't utilize the configured database character set.
+-  Fixed a bug (#1238) - delete_all() in the `Database Caching Library <database/caching>` used to delete .htaccess and index.html files, which is a potential security risk.
+-  Fixed a bug in :doc:`Trackback Library <libraries/trackback>` method validate_url() where it didn't actually do anything, due to input not being passed by reference.
+-  Fixed a bug (#11, #183, #863) - CI_Form_validation::_execute() silently continued to the next rule, if a rule method/function is not found.
+-  Fixed a bug (#1242) - read_dir() in the :doc:`Zip Library <libraries/zip>` wasn't compatible with Windows.
+-  Fixed a bug (#306) - ODBC driver didn't have an _insert_batch() method, which resulted in fatal error being triggered when insert_batch() is used with it.
+-  Fixed a bug in MSSQL and SQLSrv's _truncate() where the TABLE keyword was missing.
 
 Version 2.1.1
 =============
 
-Release Date: Not Released
+Release Date: November 14, 2011
 
 -  General Changes
    -  Fixed support for docx, xlsx files in mimes.php.
diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py
index 593ceaf..e972a38 100644
--- a/user_guide_src/source/conf.py
+++ b/user_guide_src/source/conf.py
@@ -121,7 +121,7 @@
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+#html_static_path = ['_static']
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
diff --git a/user_guide_src/source/database/configuration.rst b/user_guide_src/source/database/configuration.rst
index 040e7e3..3f3bae3 100644
--- a/user_guide_src/source/database/configuration.rst
+++ b/user_guide_src/source/database/configuration.rst
@@ -132,7 +132,7 @@
 **username**		The username used to connect to the database.
 **password**		The password used to connect to the database.
 **database**		The name of the database you want to connect to.
-**dbdriver**		The database type. ie: mysql, postgres, odbc, etc. Must be specified in lower case.
+**dbdriver**		The database type. ie: mysql, postgre, odbc, etc. Must be specified in lower case.
 **dbprefix**		An optional table prefix which will added to the table name when running :doc:
 			`Active Record <active_record>` queries. This permits multiple CodeIgniter installations
 			to share one database.
@@ -166,8 +166,8 @@
 				$db['default']['port'] =  5432;
 ======================  ==================================================================================================
 
-.. note:: Depending on what database platform you are using (MySQL,
-	Postgres, etc.) not all values will be needed. For example, when using
-	SQLite you will not need to supply a username or password, and the
-	database name will be the path to your database file. The information
-	above assumes you are using MySQL.
+.. note:: Depending on what database platform you are using (MySQL, PostgreSQL,
+	etc.) not all values will be needed. For example, when using SQLite you
+	will not need to supply a username or password, and the database name
+	will be the path to your database file. The information above assumes
+	you are using MySQL.
diff --git a/user_guide_src/source/general/requirements.rst b/user_guide_src/source/general/requirements.rst
index 05e8796..d97b7b4 100644
--- a/user_guide_src/source/general/requirements.rst
+++ b/user_guide_src/source/general/requirements.rst
@@ -5,4 +5,4 @@
 -  `PHP <http://www.php.net/>`_ version 5.2.4 or newer.
 -  A Database is required for most web application programming. Current
    supported databases are MySQL (5.1+), MySQLi, MS SQL, SQLSRV, Oracle,
-   PostgreSQL, SQLite, CUBRID, Interbase, ODBC and PDO.
+   PostgreSQL, SQLite, SQLite3, CUBRID, Interbase, ODBC and PDO.
diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst
index d7e40f5..daf0009 100644
--- a/user_guide_src/source/libraries/email.rst
+++ b/user_guide_src/source/libraries/email.rst
@@ -229,11 +229,20 @@
 	$this->email->attach('/path/to/photo2.jpg');
 	$this->email->attach('/path/to/photo3.jpg');
 
-If you'd like to change the disposition or add a custom file name, you can use the second and third paramaters. To use the default disposition (attachment), leave the second parameter blank. Here's an example::
-  
-	$this->email->attach('/path/to/photo1.jpg', 'inline');
-	$this->email->attach('/path/to/photo1.jpg', '', 'birthday.jpg');
-	
+To use the default disposition (attachment), leave the second parameter blank,
+otherwise use a custom disposition::
+
+	$this->email->attach('image.jpg', 'inline');
+
+If you'd like to use a custom file name, you can use the third paramater::
+
+	$this->email->attach('filename.pdf', 'attachment', 'report.pdf');
+
+If you need to use a buffer string instead of a real - physical - file you can
+use the first parameter as buffer, the third parameter as file name and the fourth
+parameter as mime-type::
+
+	$this->email->attach($buffer, 'attachment', 'report.pdf', 'application/pdf');
 
 $this->email->print_debugger()
 -------------------------------
diff --git a/user_guide_src/source/libraries/form_validation.rst b/user_guide_src/source/libraries/form_validation.rst
index 3e8855f..028b61c 100644
--- a/user_guide_src/source/libraries/form_validation.rst
+++ b/user_guide_src/source/libraries/form_validation.rst
@@ -321,7 +321,7 @@
 function, which removes malicious data.
 
 **Any native PHP function that accepts one parameter can be used as a
-rule, like htmlspecialchars, trim, MD5, etc.**
+rule, like htmlspecialchars, trim, md5, etc.**
 
 .. note:: You will generally want to use the prepping functions
 	**after** the validation rules so if there is an error, the original
@@ -608,7 +608,7 @@
 
 For more info please see the :ref:`function-reference` section below.
 
--.. _saving-groups:
+.. _saving-groups:
 
 ************************************************
 Saving Sets of Validation Rules to a Config File
@@ -892,8 +892,9 @@
 
 		$this->form_validation->required($string);
 
-.. note:: You can also use any native PHP functions that permit one
-	parameter.
+.. note:: You can also use any native PHP functions that permit up
+	to two parameters, where at least one is required (to pass
+	the field data).
 
 ******************
 Prepping Reference
@@ -976,7 +977,7 @@
 		$_POST array.
 
 $this->form_validation->reset_validation();
-========================================
+===========================================
 
  .. php:method:: reset_validation ()
 
diff --git a/user_guide_src/source/libraries/output.rst b/user_guide_src/source/libraries/output.rst
index 2cf7c08..baceaae 100644
--- a/user_guide_src/source/libraries/output.rst
+++ b/user_guide_src/source/libraries/output.rst
@@ -49,6 +49,15 @@
 .. important:: Make sure any non-mime string you pass to this method
 	exists in config/mimes.php or it will have no effect.
 
+$this->output->get_content_type();
+==========================================
+
+Returns the Content-Type HTTP header that's currently in use.
+
+	$mime = $this->output->get_content_type();
+
+.. note:: If not set, the default return value is 'text/html'.
+
 $this->output->get_output();
 =============================