Merge pull request #1359 from sourcejedi/backtrace-filter-fix

fix backtrace filtering
diff --git a/application/config/user_agents.php b/application/config/user_agents.php
index 60f256e..7611461 100644
--- a/application/config/user_agents.php
+++ b/application/config/user_agents.php
@@ -36,7 +36,7 @@
 |
 */
 
-$platforms = array (
+$platforms = array(
 	'windows nt 6.1'	=> 'Windows 7',
 	'windows nt 6.0'	=> 'Windows Vista',
 	'windows nt 5.2'	=> 'Windows 2003',
@@ -51,6 +51,11 @@
 	'windows 95'		=> 'Windows 95',
 	'win95'				=> 'Windows 95',
 	'windows'			=> 'Unknown Windows OS',
+	'android'			=> 'Android',
+	'blackberry'		=> 'BlackBerry',
+	'iphone'			=> 'iOS',
+	'ipad'				=> 'iOS',
+	'ipod'				=> 'iOS',
 	'os x'				=> 'Mac OS X',
 	'ppc mac'			=> 'Power PC Mac',
 	'freebsd'			=> 'FreeBSD',
@@ -117,84 +122,83 @@
 //	'motorola'			=> 'Motorola'
 
 	// Phones and Manufacturers
-	'motorola'		=> "Motorola",
-	'nokia'			=> "Nokia",
-	'palm'			=> "Palm",
-	'iphone'		=> "Apple iPhone",
-	'ipad'			=> "iPad",
-	'ipod'			=> "Apple iPod Touch",
-	'sony'			=> "Sony Ericsson",
-	'ericsson'		=> "Sony Ericsson",
-	'blackberry'	=> "BlackBerry",
-	'cocoon'		=> "O2 Cocoon",
-	'blazer'		=> "Treo",
-	'lg'			=> "LG",
-	'amoi'			=> "Amoi",
-	'xda'			=> "XDA",
-	'mda'			=> "MDA",
-	'vario'			=> "Vario",
-	'htc'			=> "HTC",
-	'samsung'		=> "Samsung",
-	'sharp'			=> "Sharp",
-	'sie-'			=> "Siemens",
-	'alcatel'		=> "Alcatel",
-	'benq'			=> "BenQ",
-	'ipaq'			=> "HP iPaq",
-	'mot-'			=> "Motorola",
-	'playstation portable'	=> "PlayStation Portable",
-	'hiptop'		=> "Danger Hiptop",
-	'nec-'			=> "NEC",
-	'panasonic'		=> "Panasonic",
-	'philips'		=> "Philips",
-	'sagem'			=> "Sagem",
-	'sanyo'			=> "Sanyo",
-	'spv'			=> "SPV",
-	'zte'			=> "ZTE",
-	'sendo'			=> "Sendo",
-	'dsi'			=> "Nintendo DSi",
-	'ds'			=> "Nintendo DS",
-	'wii'			=> "Nintendo Wii",
-	'3ds'			=> "Nintendo 3DS",
-	'open web'		=> "Open Web",
-	'openweb'		=> "OpenWeb",
+	'motorola'		=> 'Motorola',
+	'nokia'			=> 'Nokia',
+	'palm'			=> 'Palm',
+	'iphone'		=> 'Apple iPhone',
+	'ipad'			=> 'iPad',
+	'ipod'			=> 'Apple iPod Touch',
+	'sony'			=> 'Sony Ericsson',
+	'ericsson'		=> 'Sony Ericsson',
+	'blackberry'	=> 'BlackBerry',
+	'cocoon'		=> 'O2 Cocoon',
+	'blazer'		=> 'Treo',
+	'lg'			=> 'LG',
+	'amoi'			=> 'Amoi',
+	'xda'			=> 'XDA',
+	'mda'			=> 'MDA',
+	'vario'			=> 'Vario',
+	'htc'			=> 'HTC',
+	'samsung'		=> 'Samsung',
+	'sharp'			=> 'Sharp',
+	'sie-'			=> 'Siemens',
+	'alcatel'		=> 'Alcatel',
+	'benq'			=> 'BenQ',
+	'ipaq'			=> 'HP iPaq',
+	'mot-'			=> 'Motorola',
+	'playstation portable'	=> 'PlayStation Portable',
+	'hiptop'		=> 'Danger Hiptop',
+	'nec-'			=> 'NEC',
+	'panasonic'		=> 'Panasonic',
+	'philips'		=> 'Philips',
+	'sagem'			=> 'Sagem',
+	'sanyo'			=> 'Sanyo',
+	'spv'			=> 'SPV',
+	'zte'			=> 'ZTE',
+	'sendo'			=> 'Sendo',
+	'dsi'			=> 'Nintendo DSi',
+	'ds'			=> 'Nintendo DS',
+	'wii'			=> 'Nintendo Wii',
+	'3ds'			=> 'Nintendo 3DS',
+	'open web'		=> 'Open Web',
+	'openweb'		=> 'OpenWeb',
 
 	// Operating Systems
-	'android'		=> "Android",
-	'symbian'		=> "Symbian",
-	'SymbianOS'		=> "SymbianOS",
-	'elaine'		=> "Palm",
-	'palm'			=> "Palm",
-	'series60'		=> "Symbian S60",
-	'windows ce'	=> "Windows CE",
+	'android'		=> 'Android',
+	'symbian'		=> 'Symbian',
+	'SymbianOS'		=> 'SymbianOS',
+	'elaine'		=> 'Palm',
+	'series60'		=> 'Symbian S60',
+	'windows ce'	=> 'Windows CE',
 
 	// Browsers
-	'obigo'			=> "Obigo",
-	'netfront'		=> "Netfront Browser",
-	'openwave'		=> "Openwave Browser",
-	'mobilexplorer'	=> "Mobile Explorer",
-	'operamini'		=> "Opera Mini",
-	'opera mini'	=> "Opera Mini",
-	'opera mobi'	=> "Opera Mobile",
+	'obigo'			=> 'Obigo',
+	'netfront'		=> 'Netfront Browser',
+	'openwave'		=> 'Openwave Browser',
+	'mobilexplorer'	=> 'Mobile Explorer',
+	'operamini'		=> 'Opera Mini',
+	'opera mini'	=> 'Opera Mini',
+	'opera mobi'	=> 'Opera Mobile',
 
 	// Other
-	'digital paths'	=> "Digital Paths",
-	'avantgo'		=> "AvantGo",
-	'xiino'			=> "Xiino",
-	'novarra'		=> "Novarra Transcoder",
-	'vodafone'		=> "Vodafone",
-	'docomo'		=> "NTT DoCoMo",
-	'o2'			=> "O2",
+	'digital paths'	=> 'Digital Paths',
+	'avantgo'		=> 'AvantGo',
+	'xiino'			=> 'Xiino',
+	'novarra'		=> 'Novarra Transcoder',
+	'vodafone'		=> 'Vodafone',
+	'docomo'		=> 'NTT DoCoMo',
+	'o2'			=> 'O2',
 
 	// Fallback
-	'mobile'		=> "Generic Mobile",
-	'wireless'		=> "Generic Mobile",
-	'j2me'			=> "Generic Mobile",
-	'midp'			=> "Generic Mobile",
-	'cldc'			=> "Generic Mobile",
-	'up.link'		=> "Generic Mobile",
-	'up.browser'	=> "Generic Mobile",
-	'smartphone'	=> "Generic Mobile",
-	'cellphone'		=> "Generic Mobile"
+	'mobile'		=> 'Generic Mobile',
+	'wireless'		=> 'Generic Mobile',
+	'j2me'			=> 'Generic Mobile',
+	'midp'			=> 'Generic Mobile',
+	'cldc'			=> 'Generic Mobile',
+	'up.link'		=> 'Generic Mobile',
+	'up.browser'	=> 'Generic Mobile',
+	'smartphone'	=> 'Generic Mobile',
+	'cellphone'		=> 'Generic Mobile'
 );
 
 // There are hundreds of bots but these are the most common.
diff --git a/application/errors/error_404.php b/application/errors/error_404.php
index 7460329..c19bedf 100644
--- a/application/errors/error_404.php
+++ b/application/errors/error_404.php
@@ -72,7 +72,7 @@
 #container {
 	margin: 10px;
 	border: 1px solid #D0D0D0;
-	-webkit-box-shadow: 0 0 8px #D0D0D0;
+	box-shadow: 0 0 8px #D0D0D0;
 }
 
 p {
diff --git a/application/errors/error_db.php b/application/errors/error_db.php
index eb3a752..3b244e0 100644
--- a/application/errors/error_db.php
+++ b/application/errors/error_db.php
@@ -72,7 +72,7 @@
 #container {
 	margin: 10px;
 	border: 1px solid #D0D0D0;
-	-webkit-box-shadow: 0 0 8px #D0D0D0;
+	box-shadow: 0 0 8px #D0D0D0;
 }
 
 p {
diff --git a/application/errors/error_general.php b/application/errors/error_general.php
index 59896e1..c88afe1 100644
--- a/application/errors/error_general.php
+++ b/application/errors/error_general.php
@@ -72,7 +72,7 @@
 #container {
 	margin: 10px;
 	border: 1px solid #D0D0D0;
-	-webkit-box-shadow: 0 0 8px #D0D0D0;
+	box-shadow: 0 0 8px #D0D0D0;
 }
 
 p {
diff --git a/phpdoc.dist.xml b/phpdoc.dist.xml
new file mode 100644
index 0000000..6dc58c2
--- /dev/null
+++ b/phpdoc.dist.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<phpdoc>
+	<title>CodeIgniter v3.0.0 API</title>
+    <parser>
+        <target>./api/</target>
+    </parser>
+    <transformer>
+        <target>./api/</target>
+    </transformer>
+    <files>
+        <directory>./system</directory>
+    </files>
+
+    <logging>
+        <level>warn</level>
+        <paths>
+            <default>./api/log/{DATE}.log</default>
+            <errors>./api/{DATE}.errors.log</errors>
+        </paths>
+    </logging>
+</phpdoc>
\ No newline at end of file
diff --git a/system/core/Input.php b/system/core/Input.php
index 7594a2e..fc2a550 100755
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -226,7 +226,6 @@
 	 */
 	public function cookie($index = '', $xss_clean = FALSE)
 	{
-		$index = config_item('cookie_prefix').$index;
 		return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
 	}
 
diff --git a/system/core/Router.php b/system/core/Router.php
index fe9909b..9314052 100755
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -242,12 +242,9 @@
 			$segments[1] = 'index';
 		}
 
-		// This is being routed to a file in a sub directory
-		$this->directory and array_unshift($segments, trim($this->directory, '/'));
-
 		// Update our "routed" segment array to contain the segments.
 		// Note: If there is no custom routing, this array will be
-		// identical to $this->uri->segments		
+		// identical to $this->uri->segments
 		$this->uri->rsegments = $segments;
 	}
 
diff --git a/system/core/Security.php b/system/core/Security.php
index 974e2e4..c82b69f 100755
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -95,13 +95,14 @@
 	 *
 	 * @var array
 	 */
-	protected $_never_allowed_regex =	array(
+	protected $_never_allowed_regex = array(
 		'javascript\s*:',
 		'expression\s*(\(|&\#40;)', // CSS and IE
 		'vbscript\s*:', // IE, surprise!
-		'Redirect\s+302'
+		'Redirect\s+302',
+		"([\"'])?data\s*:[^\\1]*?base64[^\\1]*?,[^\\1]*?\\1?"
 	);
-
+	
 	/**
 	 * Initialize security class
 	 */
@@ -365,10 +366,11 @@
 		 * These words are compacted back to their correct state.
 		 */
 		$words = array(
-			'javascript', 'expression', 'vbscript', 'script',
+			'javascript', 'expression', 'vbscript', 'script', 'base64',
 			'applet', 'alert', 'document', 'write', 'cookie', 'window'
 		);
 
+
 		foreach ($words as $word)
 		{
 			$word = implode('\s*', str_split($word)).'\s*';
@@ -605,10 +607,11 @@
 			$attribs = array();
 
 			// find occurrences of illegal attribute strings without quotes
-			preg_match_all('/('.implode('|', $evil_attributes).')\s*=\s*([^\s]*)/is', $str, $matches, PREG_SET_ORDER);
+			preg_match_all('/('.implode('|', $evil_attributes).')\s*=\s*([^\s>]*)/is', $str, $matches, PREG_SET_ORDER);
 
 			foreach ($matches as $attr)
 			{
+
 				$attribs[] = preg_quote($attr[0], '/');
 			}
 
@@ -623,7 +626,7 @@
 			// replace illegal attribute strings that are inside an html tag
 			if (count($attribs) > 0)
 			{
-				$str = preg_replace('/<(\/?[^><]+?)([^A-Za-z\-])('.implode('|', $attribs).')([\s><])([><]*)/i', '<$1$2$4$5', $str, -1, $count);
+				$str = preg_replace("/<(\/?[^><]+?)([^A-Za-z<>\-])(.*?)(".implode('|', $attribs).")(.*?)([\s><])([><]*)/i", '<$1 $3$5$6$7', $str, -1, $count);
 			}
 
 		} while ($count);
@@ -664,7 +667,7 @@
 	protected function _js_link_removal($match)
 	{
 		return str_replace($match[1],
-					preg_replace('#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
+					preg_replace('#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
 							'',
 							$this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
 					),
@@ -804,7 +807,7 @@
 
 		foreach ($this->_never_allowed_regex as $regex)
 		{
-			$str = preg_replace('#'.$regex.'#i', '[removed]', $str);
+			$str = preg_replace('#'.$regex.'#is', '[removed]', $str);
 		}
 
 		return $str;
@@ -841,4 +844,4 @@
 }
 
 /* End of file Security.php */
-/* Location: ./system/core/Security.php */
\ No newline at end of file
+/* Location: ./system/core/Security.php */
diff --git a/system/core/URI.php b/system/core/URI.php
index 705575a..cf82c58 100755
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -645,10 +645,10 @@
 	 */
 	public function ruri_string()
 	{
-		return implode('/', $this->rsegment_array());
+		return '/'.implode('/', $this->rsegment_array());
 	}
 
 }
 
 /* End of file URI.php */
-/* Location: ./system/core/URI.php */
\ No newline at end of file
+/* Location: ./system/core/URI.php */
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index 393a1cd..d0af66d 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -281,7 +281,7 @@
 					$v = trim($v);
 					$this->_track_aliases($v);
 
-					$v = $this->qb_from[] = $this->protect_identifiers($v, TRUE, NULL, FALSE);
+					$this->qb_from[] = $v = $this->protect_identifiers($v, TRUE, NULL, FALSE);
 
 					if ($this->qb_caching === TRUE)
 					{
diff --git a/system/database/drivers/interbase/interbase_utility.php b/system/database/drivers/interbase/interbase_utility.php
index 1b92af9..1642118 100644
--- a/system/database/drivers/interbase/interbase_utility.php
+++ b/system/database/drivers/interbase/interbase_utility.php
@@ -42,7 +42,7 @@
 	 * @param	string	$filename
 	 * @return	mixed
 	 */
-	protected function backup($filename)
+	protected function _backup($filename)
 	{
 		if ($service = ibase_service_attach($this->db->hostname, $this->db->username, $this->db->password))
 		{
diff --git a/system/database/drivers/pdo/pdo_result.php b/system/database/drivers/pdo/pdo_result.php
index 19aee1d..0b8937c 100644
--- a/system/database/drivers/pdo/pdo_result.php
+++ b/system/database/drivers/pdo/pdo_result.php
@@ -84,19 +84,14 @@
 		// Define the output
 		$output = array('assoc', 'object');
 
+		// Initial value
+		$this->result_assoc = array() and $this->result_object = array();
+
 		// Fetch the result
-		foreach ($output as $type)
+		while ($row = $this->_fetch_assoc())
 		{
-			// Define the method and handler
-			$res_method  = '_fetch_'.$type;
-			$res_handler = 'result_'.$type;
-
-			$this->$res_handler = array();
-
-			while ($row = $this->$res_method())
-			{
-				$this->{$res_handler}[] = $row;
-			}
+			$this->result_assoc[] = $row;
+			$this->result_object[] = (object) $row;
 		}
 
 		// Save this as buffer and marked the fetch flag
@@ -249,7 +244,7 @@
 	 */
 	protected function _fetch_object()
 	{
-		return $this->result_id->fetchObject();
+		return $this->result_id->fetch(PDO::FETCH_OBJ);
 	}
 
 }
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 84bf768..17bd37b 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -311,6 +311,27 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * "Smart" Escape String
+	 *
+	 * Escapes data based on type
+	 * Sets boolean and null types
+	 *
+	 * @param	string
+	 * @return	mixed
+	 */
+	public function escape($str)
+	{
+		if (is_bool($str))
+		{
+			return ($str) ? 'TRUE' : 'FALSE';
+		}
+
+		return parent::escape($str);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Affected Rows
 	 *
 	 * @return	int
@@ -558,6 +579,78 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Where
+	 *
+	 * Called by where() or or_where()
+	 *
+	 * @param	mixed
+	 * @param	mixed
+	 * @param	string
+	 * @return	object
+	 *
+	 */
+	protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
+	{
+		$type = $this->_group_get_type($type);
+
+		if ( ! is_array($key))
+		{
+			$key = array($key => $value);
+		}
+
+		// If the escape value was not set will will base it on the global setting
+		if ( ! is_bool($escape))
+		{
+			$escape = $this->_protect_identifiers;
+		}
+
+		foreach ($key as $k => $v)
+		{
+			$prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type;
+
+			if (is_null($v) && ! $this->_has_operator($k))
+			{
+				// value appears not to have been set, assign the test to IS NULL
+				$k .= ' IS NULL';
+			}
+
+			if ( ! is_null($v))
+			{
+				if ($escape === TRUE)
+				{
+					$k = $this->protect_identifiers($k, FALSE, $escape);
+					$v = ' '.$this->escape($v);
+				}
+				elseif (is_bool($v))
+				{
+					$v = ($v ? ' TRUE' : ' FALSE');
+				}
+
+				if ( ! $this->_has_operator($k))
+				{
+					$k .= ' = ';
+				}
+			}
+			else
+			{
+				$k = $this->protect_identifiers($k, FALSE, $escape);
+			}
+
+			$this->qb_where[] = $prefix.$k.$v;
+			if ($this->qb_caching === TRUE)
+			{
+				$this->qb_cache_where[] = $prefix.$k.$v;
+				$this->qb_cache_exists[] = 'where';
+			}
+
+		}
+
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Close DB Connection
 	 *
 	 * @param	resource
@@ -571,4 +664,4 @@
 }
 
 /* End of file postgre_driver.php */
-/* Location: ./system/database/drivers/postgre/postgre_driver.php */
+/* Location: ./system/database/drivers/postgre/postgre_driver.php */
\ No newline at end of file
diff --git a/system/helpers/smiley_helper.php b/system/helpers/smiley_helper.php
index 8dba74e..638100e 100644
--- a/system/helpers/smiley_helper.php
+++ b/system/helpers/smiley_helper.php
@@ -40,7 +40,7 @@
 /**
  * Smiley Javascript
  *
- * Returns the javascript required for the smiley insertion.  Optionally takes
+ * Returns the javascript required for the smiley insertion. Optionally takes
  * an array of aliases to loosely couple the smiley array to the view.
  *
  * @param	mixed	alias name or array of alias->field_id pairs
@@ -52,7 +52,6 @@
 	function smiley_js($alias = '', $field_id = '', $inline = TRUE)
 	{
 		static $do_setup = TRUE;
-
 		$r = '';
 
 		if ($alias != '' && ! is_array($alias))
@@ -62,69 +61,58 @@
 
 		if ($do_setup === TRUE)
 		{
-				$do_setup = FALSE;
+			$do_setup = FALSE;
+			$m = array();
 
-				$m = array();
-
-				if (is_array($alias))
-				{
-					foreach ($alias as $name => $id)
-					{
-						$m[] = '"'.$name.'" : "'.$id.'"';
-					}
-				}
-
-				$m = '{'.implode(',', $m).'}';
-
-				$r .= <<<EOF
-				var smiley_map = {$m};
-
-				function insert_smiley(smiley, field_id) {
-					var el = document.getElementById(field_id), newStart;
-
-					if ( ! el && smiley_map[field_id]) {
-						el = document.getElementById(smiley_map[field_id]);
-
-						if ( ! el)
-							return false;
-					}
-
-					el.focus();
-					smiley = " " + smiley;
-
-					if ('selectionStart' in el) {
-						newStart = el.selectionStart + smiley.length;
-
-						el.value = el.value.substr(0, el.selectionStart) +
-										smiley +
-										el.value.substr(el.selectionEnd, el.value.length);
-						el.setSelectionRange(newStart, newStart);
-					}
-					else if (document.selection) {
-						document.selection.createRange().text = smiley;
-					}
-				}
-EOF;
-		}
-		else
-		{
 			if (is_array($alias))
 			{
 				foreach ($alias as $name => $id)
 				{
-					$r .= 'smiley_map["'.$name.'"] = "'.$id.'";'."\n";
+					$m[] = '"'.$name.'" : "'.$id.'"';
 				}
 			}
+
+			$m = '{'.implode(',', $m).'}';
+
+			$r .= <<<EOF
+			var smiley_map = {$m};
+
+			function insert_smiley(smiley, field_id) {
+				var el = document.getElementById(field_id), newStart;
+
+				if ( ! el && smiley_map[field_id]) {
+					el = document.getElementById(smiley_map[field_id]);
+
+					if ( ! el)
+						return false;
+				}
+
+				el.focus();
+				smiley = " " + smiley;
+
+				if ('selectionStart' in el) {
+					newStart = el.selectionStart + smiley.length;
+
+					el.value = el.value.substr(0, el.selectionStart) +
+									smiley +
+									el.value.substr(el.selectionEnd, el.value.length);
+					el.setSelectionRange(newStart, newStart);
+				}
+				else if (document.selection) {
+					document.selection.createRange().text = smiley;
+				}
+			}
+EOF;
+		}
+		elseif (is_array($alias))
+		{
+			foreach ($alias as $name => $id)
+			{
+				$r .= 'smiley_map["'.$name.'"] = "'.$id."\";\n";
+			}
 		}
 
-		if ($inline)
-		{
-			return '<script type="text/javascript" charset="utf-8">/*<![CDATA[ */'.$r.'// ]]></script>';
-		}
-		else
-		{
-			return $r;
-		}
+		return ($inline) ? '<script type="text/javascript" charset="utf-8">/*<![CDATA[ */'.$r.'// ]]></script>' : $r;
 	}
 }
 
@@ -144,18 +132,13 @@
 	function get_clickable_smileys($image_url, $alias = '', $smileys = NULL)
 	{
 		// For backward compatibility with js_insert_smiley
-
 		if (is_array($alias))
 		{
 			$smileys = $alias;
 		}
-
-		if ( ! is_array($smileys))
+		elseif (FALSE === ($smileys = _get_smiley_array()))
 		{
-			if (FALSE === ($smileys = _get_smiley_array()))
-			{
-				return $smileys;
-			}
+			return $smileys;
 		}
 
 		// Add a trailing slash to the file path if needed
@@ -165,7 +148,7 @@
 		foreach ($smileys as $key => $val)
 		{
 			// Keep duplicates from being used, which can happen if the
-			// mapping array contains multiple identical replacements.  For example:
+			// mapping array contains multiple identical replacements. For example:
 			// :-) and :) might be replaced with the same image so both smileys
 			// will be in the array.
 			if (isset($used[$smileys[$key][0]]))
@@ -173,8 +156,7 @@
 				continue;
 			}
 
-			$link[] = "<a href=\"javascript:void(0);\" onclick=\"insert_smiley('".$key."', '".$alias."')\"><img src=\"".$image_url.$smileys[$key][0]."\" width=\"".$smileys[$key][1]."\" height=\"".$smileys[$key][2]."\" alt=\"".$smileys[$key][3]."\" style=\"border:0;\" /></a>";
-
+			$link[] = '<a href="javascript:void(0);" onclick="insert_smiley(\''.$key.'\', \''.$alias.'\')"><img src="'.$image_url.$smileys[$key][0].'" alt="'.$smileys[$key][3].'" style="width: '.$smileys[$key][1].'; height: '.$smileys[$key][2].'; border: 0;" /></a>';
 			$used[$smileys[$key][0]] = TRUE;
 		}
 
@@ -197,25 +179,17 @@
 {
 	function parse_smileys($str = '', $image_url = '', $smileys = NULL)
 	{
-		if ($image_url == '')
+		if ($image_url == '' OR ( ! is_array($smileys) && FALSE === ($smileys = _get_smiley_array())))
 		{
 			return $str;
 		}
 
-		if ( ! is_array($smileys))
-		{
-			if (FALSE === ($smileys = _get_smiley_array()))
-			{
-				return $str;
-			}
-		}
-
 		// Add a trailing slash to the file path if needed
-		$image_url = preg_replace("/(.+?)\/*$/", "\\1/",  $image_url);
+		$image_url = rtrim($image_url, '/').'/';
 
 		foreach ($smileys as $key => $val)
 		{
-			$str = str_replace($key, "<img src=\"".$image_url.$smileys[$key][0]."\" width=\"".$smileys[$key][1]."\" height=\"".$smileys[$key][2]."\" alt=\"".$smileys[$key][3]."\" style=\"border:0;\" />", $str);
+			$str = str_replace($key, '<img src="'.$image_url.$smileys[$key][0].'" alt="'.$smileys[$key][3].'" style="width: '.$smileys[$key][1].'; height: '.$smileys[$key][2].'; border: 0;" />', $str);
 		}
 
 		return $str;
@@ -244,12 +218,7 @@
 			include(APPPATH.'config/smileys.php');
 		}
 
-		if (isset($smileys) && is_array($smileys))
-		{
-			return $smileys;
-		}
-
-		return FALSE;
+		return (isset($smileys) && is_array($smileys)) ? $smileys : FALSE;
 	}
 }
 
diff --git a/system/helpers/string_helper.php b/system/helpers/string_helper.php
index aed35c1..a6a6b48 100644
--- a/system/helpers/string_helper.php
+++ b/system/helpers/string_helper.php
@@ -73,16 +73,14 @@
 {
 	function strip_slashes($str)
 	{
-		if (is_array($str))
+		if ( ! is_array($str))
 		{
-			foreach ($str as $key => $val)
-			{
-				$str[$key] = strip_slashes($val);
-			}
+			return stripslashes($str);
 		}
-		else
+
+		foreach ($str as $key => $val)
 		{
-			$str = stripslashes($str);
+			$str[$key] = strip_slashes($val);
 		}
 
 		return $str;
@@ -173,13 +171,7 @@
 	function reduce_multiples($str, $character = ',', $trim = FALSE)
 	{
 		$str = preg_replace('#'.preg_quote($character, '#').'{2,}#', $character, $str);
-
-		if ($trim === TRUE)
-		{
-			return trim($str, $character);
-		}
-
-		return $str;
+		return ($trim === TRUE) ? trim($str, $character) : $str;
 	}
 }
 
@@ -198,44 +190,36 @@
 {
 	function random_string($type = 'alnum', $len = 8)
 	{
-		switch($type)
+		switch ($type)
 		{
-			case 'basic'	: return mt_rand();
-				break;
-			case 'alnum'	:
-			case 'numeric'	:
-			case 'nozero'	:
-			case 'alpha'	:
-
-					switch ($type)
-					{
-						case 'alpha'	:	$pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
-							break;
-						case 'alnum'	:	$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
-							break;
-						case 'numeric'	:	$pool = '0123456789';
-							break;
-						case 'nozero'	:	$pool = '123456789';
-							break;
-					}
-
-					$str = substr(str_shuffle(str_repeat($pool, ceil($len/strlen($pool)))),0,$len);
-
-					return $str;
-				break;
-			case 'unique'	:
-			case 'md5'		:
-
-						return md5(uniqid(mt_rand()));
-				break;
-			case 'encrypt'	:
-			case 'sha1'	:
-
-						$CI =& get_instance();
-						$CI->load->helper('security');
-
-						return do_hash(uniqid(mt_rand(), TRUE), 'sha1');
-				break;
+			case 'basic':
+				return mt_rand();
+			case 'alnum':
+			case 'numeric':
+			case 'nozero':
+			case 'alpha':
+				switch ($type)
+				{
+					case 'alpha':
+						$pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+						break;
+					case 'alnum':
+						$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+						break;
+					case 'numeric':
+						$pool = '0123456789';
+						break;
+					case 'nozero':
+						$pool = '123456789';
+						break;
+				}
+				return substr(str_shuffle(str_repeat($pool, ceil($len / strlen($pool)))), 0, $len);
+			case 'unique':
+			case 'md5':
+				return md5(uniqid(mt_rand()));
+			case 'encrypt':
+			case 'sha1':
+				return sha1(uniqid(mt_rand(), TRUE));
 		}
 	}
 }
@@ -255,7 +239,6 @@
 	function increment_string($str, $separator = '_', $first = 1)
 	{
 		preg_match('/(.+)'.$separator.'([0-9]+)$/', $str, $match);
-
 		return isset($match[2]) ? $match[1].$separator.($match[2] + 1) : $str.$separator.$first;
 	}
 }
@@ -267,7 +250,7 @@
  *
  * Allows strings to be alternated. See docs...
  *
- * @param	string (as many parameters as needed)
+ * @param	string	(as many parameters as needed)
  * @return	string
  */
 if ( ! function_exists('alternator'))
diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php
index cc501c3..c1c0eb9 100644
--- a/system/helpers/text_helper.php
+++ b/system/helpers/text_helper.php
@@ -58,7 +58,7 @@
 
 		preg_match('/^\s*+(?:\S++\s*+){1,'.(int) $limit.'}/', $str, $matches);
 
-		if (strlen($str) == strlen($matches[0]))
+		if (strlen($str) === strlen($matches[0]))
 		{
 			$end_char = '';
 		}
@@ -72,7 +72,7 @@
 /**
  * Character Limiter
  *
- * Limits the string based on the character count.  Preserves complete words
+ * Limits the string based on the character count. Preserves complete words
  * so the character count may not be exactly as specified.
  *
  * @param	string
@@ -89,14 +89,14 @@
 			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)
 		{
 			return $str;
 		}
 
-		$out = "";
+		$out = '';
 		foreach (explode(' ', trim($str)) as $val)
 		{
 			$out .= $val.' ';
@@ -104,7 +104,7 @@
 			if (strlen($out) >= $n)
 			{
 				$out = trim($out);
-				return (strlen($out) == strlen($str)) ? $out : $out.$end_char;
+				return (strlen($out) === strlen($str)) ? $out : $out.$end_char;
 			}
 		}
 	}
@@ -138,7 +138,7 @@
 					If the $temp array has a value but we have moved on, then it seems only
 					fair that we output that entity and restart $temp before continuing. -Paul
 				*/
-				if (count($temp) == 1)
+				if (count($temp) === 1)
 				{
 					$out  .= '&#'.array_shift($temp).';';
 					$count = 1;
@@ -148,16 +148,18 @@
 			}
 			else
 			{
-				if (count($temp) == 0)
+				if (count($temp) === 0)
 				{
 					$count = ($ordinal < 224) ? 2 : 3;
 				}
 
 				$temp[] = $ordinal;
 
-				if (count($temp) == $count)
+				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;
@@ -187,10 +189,9 @@
 	{
 		if (preg_match_all('/\&#(\d+)\;/', $str, $matches))
 		{
-			for ($i = 0, $s = count($matches['0']); $i < $s; $i++)
+			for ($i = 0, $s = count($matches[0]); $i < $s; $i++)
 			{
-				$digits = $matches['1'][$i];
-
+				$digits = $matches[1][$i];
 				$out = '';
 
 				if ($digits < 128)
@@ -200,25 +201,24 @@
 				}
 				elseif ($digits < 2048)
 				{
-					$out .= chr(192 + (($digits - ($digits % 64)) / 64));
-					$out .= chr(128 + ($digits % 64));
+					$out .= chr(192 + (($digits - ($digits % 64)) / 64)).chr(128 + ($digits % 64));
 				}
 				else
 				{
-					$out .= chr(224 + (($digits - ($digits % 4096)) / 4096));
-					$out .= chr(128 + ((($digits % 4096) - ($digits % 64)) / 64));
-					$out .= chr(128 + ($digits % 64));
+					$out .= chr(224 + (($digits - ($digits % 4096)) / 4096))
+						.chr(128 + ((($digits % 4096) - ($digits % 64)) / 64))
+						.chr(128 + ($digits % 64));
 				}
 
-				$str = str_replace($matches['0'][$i], $out, $str);
+				$str = str_replace($matches[0][$i], $out, $str);
 			}
 		}
 
 		if ($all)
 		{
-			$str = str_replace(array("&amp;", "&lt;", "&gt;", "&quot;", "&apos;", "&#45;"),
-								array("&","<",">","\"", "'", "-"),
-								$str);
+			return str_replace(array('&amp;', '&lt;', '&gt;', '&quot;', '&apos;', '&#45;'),
+						array('&', '<', '>', '"', "'", '-'),
+						$str);
 		}
 
 		return $str;
@@ -286,27 +286,33 @@
 {
 	function highlight_code($str)
 	{
-		// The highlight string function encodes and highlights
-		// brackets so we need them to start raw
-		$str = str_replace(array('&lt;', '&gt;'), array('<', '>'), $str);
-
-		// Replace any existing PHP tags to temporary markers so they don't accidentally
-		// break the string out of PHP, and thus, thwart the highlighting.
-		$str = str_replace(array('<?', '?>', '<%', '%>', '\\', '</script>'),
-					array('phptagopen', 'phptagclose', 'asptagopen', 'asptagclose', 'backslashtmp', 'scriptclose'),
+		/* The highlight string function encodes and highlights
+		 * brackets so we need them to start raw.
+		 *
+		 * Also replace any existing PHP tags to temporary markers
+		 * so they don't accidentally break the string out of PHP,
+		 * and thus, thwart the highlighting.
+		 */
+		$str = str_replace(array('&lt;', '&gt;', '<?', '?>', '<%', '%>', '\\', '</script>'),
+					array('<', '>', 'phptagopen', 'phptagclose', 'asptagopen', 'asptagclose', 'backslashtmp', 'scriptclose'),
 					$str);
 
 		// The highlight_string function requires that the text be surrounded
 		// by PHP tags, which we will remove later
-		$str = '<?php '.$str.' ?>'; // <?
-
-		// All the magic happens here, baby!
-		$str = highlight_string($str, TRUE);
+		$str = highlight_string('<?php '.$str.' ?>', TRUE);
 
 		// Remove our artificially added PHP, and the syntax highlighting that came with it
-		$str = preg_replace('/<span style="color: #([A-Z0-9]+)">&lt;\?php(&nbsp;| )/i', '<span style="color: #$1">', $str);
-		$str = preg_replace('/(<span style="color: #[A-Z0-9]+">.*?)\?&gt;<\/span>\n<\/span>\n<\/code>/is', "$1</span>\n</span>\n</code>", $str);
-		$str = preg_replace('/<span style="color: #[A-Z0-9]+"\><\/span>/i', '', $str);
+		$str = preg_replace(array(
+						'/<span style="color: #([A-Z0-9]+)">&lt;\?php(&nbsp;| )/i',
+						'/(<span style="color: #[A-Z0-9]+">.*?)\?&gt;<\/span>\n<\/span>\n<\/code>/is',
+						'/<span style="color: #[A-Z0-9]+"\><\/span>/i'
+					),
+					array(
+						'<span style="color: #$1">',
+						"$1</span>\n</span>\n</code>",
+						''
+					),
+					$str);
 
 		// Replace our markers back to PHP tags.
 		return str_replace(array('phptagopen', 'phptagclose', 'asptagopen', 'asptagclose', 'backslashtmp', 'scriptclose'),
@@ -339,7 +345,7 @@
 
 		if ($phrase != '')
 		{
-			return preg_replace('/('.preg_quote($phrase, '/').')/i', $tag_open."\\1".$tag_close, $str);
+			return preg_replace('/('.preg_quote($phrase, '/').')/i', $tag_open.'\\1'.$tag_close, $str);
 		}
 
 		return $str;
@@ -358,18 +364,23 @@
 {
 	function convert_accented_characters($str)
 	{
-		if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php'))
-		{
-			include(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php');
-		}
-		elseif (is_file(APPPATH.'config/foreign_chars.php'))
-		{
-			include(APPPATH.'config/foreign_chars.php');
-		}
+		global $foreign_characters;
 
-		if ( ! isset($foreign_characters))
+		if ( ! isset($foreign_characters) OR ! is_array($foreign_characters))
 		{
-			return $str;
+			if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php'))
+			{
+				include(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php');
+			}
+			elseif (is_file(APPPATH.'config/foreign_chars.php'))
+			{
+				include(APPPATH.'config/foreign_chars.php');
+			}
+
+			if ( ! isset($foreign_characters) OR ! is_array($foreign_characters))
+			{
+				return $str;
+			}
 		}
 
 		return preg_replace(array_keys($foreign_characters), array_values($foreign_characters), $str);
@@ -381,7 +392,7 @@
 /**
  * Word Wrap
  *
- * Wraps text at the specified character.  Maintains the integrity of words.
+ * Wraps text at the specified character. Maintains the integrity of words.
  * Anything placed between {unwrap}{/unwrap} will not be word wrapped, nor
  * will URLs.
  *
@@ -391,14 +402,16 @@
  */
 if ( ! function_exists('word_wrap'))
 {
-	function word_wrap($str, $charlim = '76')
+	function word_wrap($str, $charlim = 76)
 	{
-		// Se the character limit
+		// Set the character limit
 		if ( ! is_numeric($charlim))
+		{
 			$charlim = 76;
+		}
 
 		// Reduce multiple spaces
-		$str = preg_replace("| +|", " ", $str);
+		$str = preg_replace('| +|', ' ', $str);
 
 		// Standardize newlines
 		if (strpos($str, "\r") !== FALSE)
@@ -409,22 +422,22 @@
 		// If the current word is surrounded by {unwrap} tags we'll
 		// strip the entire chunk and replace it with a marker.
 		$unwrap = array();
-		if (preg_match_all("|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches))
+		if (preg_match_all('|(\{unwrap\}.+?\{/unwrap\})|s', $str, $matches))
 		{
-			for ($i = 0; $i < count($matches['0']); $i++)
+			for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
 			{
-				$unwrap[] = $matches['1'][$i];
-				$str = str_replace($matches['1'][$i], "{{unwrapped".$i."}}", $str);
+				$unwrap[] = $matches[1][$i];
+				$str = str_replace($matches[1][$i], '{{unwrapped'.$i.'}}', $str);
 			}
 		}
 
 		// Use PHP's native function to do the initial wordwrap.
 		// We set the cut flag to FALSE so that any individual words that are
-		// too long get left alone.  In the next step we'll deal with them.
+		// too long get left alone. In the next step we'll deal with them.
 		$str = wordwrap($str, $charlim, "\n", FALSE);
 
 		// Split the string into individual lines of text and cycle through them
-		$output = "";
+		$output = '';
 		foreach (explode("\n", $str) as $line)
 		{
 			// Is the line within the allowed character count?
@@ -439,28 +452,26 @@
 			while ((strlen($line)) > $charlim)
 			{
 				// If the over-length word is a URL we won't wrap it
-				if (preg_match("!\[url.+\]|://|wwww.!", $line))
+				if (preg_match('!\[url.+\]|://|wwww.!', $line))
 				{
 					break;
 				}
 
 				// Trim the word down
-				$temp .= substr($line, 0, $charlim-1);
-				$line = substr($line, $charlim-1);
+				$temp .= substr($line, 0, $charlim - 1);
+				$line = substr($line, $charlim - 1);
 			}
 
 			// If $temp contains data it means we had to split up an over-length
 			// word into smaller chunks so we'll add it back to our current line
 			if ($temp != '')
 			{
-				$output .= $temp."\n".$line;
+				$output .= $temp."\n".$line."\n";
 			}
 			else
 			{
-				$output .= $line;
+				$output .= $line."\n";
 			}
-
-			$output .= "\n";
 		}
 
 		// Put our markers back
@@ -468,14 +479,12 @@
 		{
 			foreach ($unwrap as $key => $val)
 			{
-				$output = str_replace("{{unwrapped".$key."}}", $val, $output);
+				$output = str_replace('{{unwrapped'.$key.'}}', $val, $output);
 			}
 		}
 
-		// Remove the unwrap tags
-		$output = str_replace(array('{unwrap}', '{/unwrap}'), '', $output);
-
-		return $output;
+		// Remove the unwrap tags and return
+		return str_replace(array('{unwrap}', '{/unwrap}'), '', $output);
 	}
 }
 
@@ -506,7 +515,6 @@
 		}
 
 		$beg = substr($str, 0, floor($max_length * $position));
-
 		$position = ($position > 1) ? 1 : $position;
 
 		if ($position === 1)
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index a52cad5..c396580 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -448,7 +448,7 @@
 			{
 				$this->_field_data[$field]['postdata'] = $this->_reduce_array($validation_array, $row['keys']);
 			}
-			elseif ( ! empty($validation_array[$field]))
+			elseif (isset($validation_array[$field]) && $validation_array[$field] !== '')
 			{
 				$this->_field_data[$field]['postdata'] = $validation_array[$field];
 			}
@@ -1005,7 +1005,7 @@
 
 		return (MB_ENABLED === TRUE)
 			? ($val <= mb_strlen($str))
-			: ($val <= strlen(str));
+			: ($val <= strlen($str));
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/libraries/Javascript.php b/system/libraries/Javascript.php
index 629a3ad..dd2df69 100644
--- a/system/libraries/Javascript.php
+++ b/system/libraries/Javascript.php
@@ -723,7 +723,7 @@
 		{
 			if (is_object($result))
 			{
-				$json_result = $result->result_array();
+				$json_result = is_callable(array($result, 'result_array')) ? $result->result_array() : (array) $result;
 			}
 			elseif (is_array($result))
 			{
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
index 0fe73d6..3d29118 100644
--- a/system/libraries/Pagination.php
+++ b/system/libraries/Pagination.php
@@ -94,17 +94,16 @@
 		{
 			foreach ($params as $key => $val)
 			{
-				if (isset($this->$key))
+				if ($key === 'anchor_class')
+				{
+					$this->anchor_class = ($val != '') ? 'class="'.$val.'" ' : '';
+				}
+				elseif (isset($this->$key))
 				{
 					$this->$key = $val;
 				}
 			}
 		}
-
-		if ($this->anchor_class != '')
-		{
-			$this->anchor_class = 'class="'.$this->anchor_class.'" ';
-		}
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/libraries/Session.php b/system/libraries/Session.php
index 3fa446d..3195f0a 100644
--- a/system/libraries/Session.php
+++ b/system/libraries/Session.php
@@ -36,146 +36,146 @@
  */
 class CI_Session {
 
-	/** 
+	/**
 	 * Whether to encrypt the session cookie
 	 *
 	 * @var bool
 	 */
 	public $sess_encrypt_cookie		= FALSE;
-	
+
 	/**
 	 * Whether to use to the database for session storage
 	 *
 	 * @var bool
 	 */
 	public $sess_use_database		= FALSE;
-	
+
 	/**
 	 * Name of the database table in which to store sessions
 	 *
 	 * @var string
 	 */
 	public $sess_table_name			= '';
-	
+
 	/**
 	 * Length of time (in seconds) for sessions to expire
 	 *
 	 * @var int
 	 */
 	public $sess_expiration			= 7200;
-	
+
 	/**
 	 * Whether to kill session on close of browser window
 	 *
 	 * @var bool
 	 */
 	public $sess_expire_on_close		= FALSE;
-	
+
 	/**
 	 * Whether to match session on ip address
 	 *
 	 * @var bool
 	 */
 	public $sess_match_ip			= FALSE;
-	
+
 	/**
 	 * Whether to match session on user-agent
 	 *
 	 * @var bool
 	 */
 	public $sess_match_useragent		= TRUE;
-	
+
 	/**
 	 * Name of session cookie
 	 *
 	 * @var string
 	 */
 	public $sess_cookie_name		= 'ci_session';
-	
+
 	/**
 	 * Session cookie prefix
 	 *
 	 * @var string
 	 */
 	public $cookie_prefix			= '';
-	
+
 	/**
 	 * Session cookie path
 	 *
 	 * @var string
 	 */
 	public $cookie_path			= '';
-	
+
 	/**
 	 * Session cookie domain
 	 *
 	 * @var string
 	 */
 	public $cookie_domain			= '';
-	
+
 	/**
 	 * Whether to set the cookie only on HTTPS connections
 	 *
 	 * @var bool
 	 */
 	public $cookie_secure			= FALSE;
-	
+
 	/**
 	 * Whether cookie should be allowed only to be sent by the server
 	 *
 	 * @var bool
 	 */
 	public $cookie_httponly 		= FALSE;
-	
+
 	/**
 	 * Interval at which to update session
 	 *
 	 * @var int
 	 */
 	public $sess_time_to_update		= 300;
-	
+
 	/**
 	 * Key with which to encrypt the session cookie
 	 *
 	 * @var string
 	 */
 	public $encryption_key			= '';
-	
+
 	/**
 	 * String to indicate flash data cookies
 	 *
 	 * @var string
 	 */
 	public $flashdata_key			= 'flash';
-	
+
 	/**
 	 * Function to use to get the current time
 	 *
 	 * @var string
 	 */
 	public $time_reference			= 'time';
-	
+
 	/**
 	 * Probablity level of garbage collection of old sessions
 	 *
 	 * @var int
 	 */
 	public $gc_probability			= 5;
-	
+
 	/**
 	 * Session data
 	 *
 	 * @var array
 	 */
 	public $userdata			= array();
-	
+
 	/**
 	 * Reference to CodeIgniter instance
 	 *
 	 * @var object
 	 */
 	public $CI;
-	
+
 	/**
 	 * Current time
 	 *
@@ -570,6 +570,9 @@
 				$this->cookie_domain,
 				0
 			);
+
+		// Kill session data
+		$this->userdata = array();
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
index 8ad6705..24d4bd4 100644
--- a/system/libraries/Upload.php
+++ b/system/libraries/Upload.php
@@ -725,7 +725,7 @@
 	public function get_extension($filename)
 	{
 		$x = explode('.', $filename);
-		return '.'.end($x);
+		return (count($x) !== 1) ? '.'.end($x) : '';
 	}
 
 	// --------------------------------------------------------------------
@@ -850,6 +850,10 @@
 			{
 				return TRUE; // its an image, no "triggers" detected in the first 256 bytes, we're good
 			}
+			else
+			{
+				return FALSE;
+			}
 		}
 
 		if (($data = @file_get_contents($file)) === FALSE)
@@ -1099,4 +1103,4 @@
 }
 
 /* End of file Upload.php */
-/* Location: ./system/libraries/Upload.php */
\ No newline at end of file
+/* Location: ./system/libraries/Upload.php */
diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php
index 0ac605f..ff596f0 100644
--- a/system/libraries/User_agent.php
+++ b/system/libraries/User_agent.php
@@ -51,14 +51,14 @@
 	 * @var bool
 	 */
 	public $is_browser = FALSE;
-	
+
 	/**
 	 * Flag for if the user-agent is a robot
 	 *
 	 * @var bool
 	 */
 	public $is_robot = FALSE;
-	
+
 	/**
 	 * Flag for if the user-agent is a mobile browser
 	 *
@@ -72,7 +72,7 @@
 	 * @var array
 	 */
 	public $languages = array();
-	
+
 	/**
 	 * Character sets accepted by the current user agent
 	 *
@@ -86,21 +86,21 @@
 	 * @var array
 	 */
 	public $platforms = array();
-	
+
 	/**
 	 * List of browsers to compare against current user agent
 	 *
 	 * @var array
 	 */
 	public $browsers = array();
-	
+
 	/**
 	 * List of mobile browsers to compare against current user agent
 	 *
 	 * @var array
 	 */
 	public $mobiles = array();
-	
+
 	/**
 	 * List of robots to compare against current user agent
 	 *
@@ -114,28 +114,28 @@
 	 * @var string
 	 */
 	public $platform = '';
-	
+
 	/**
 	 * Current user-agent browser
 	 *
 	 * @var string
 	 */
 	public $browser = '';
-	
+
 	/**
 	 * Current user-agent version
 	 *
 	 * @var string
 	 */
 	public $version = '';
-	
+
 	/**
 	 * Current user-agent mobile name
 	 *
 	 * @var string
 	 */
 	public $mobile = '';
-	
+
 	/**
 	 * Current user-agent robot name
 	 *
@@ -330,7 +330,7 @@
 		{
 			foreach ($this->mobiles as $key => $val)
 			{
-				if (FALSE !== (strpos(strtolower($this->agent), $key)))
+				if (FALSE !== (stripos($this->agent, $key)))
 				{
 					$this->is_mobile = TRUE;
 					$this->mobile = $val;
@@ -604,7 +604,7 @@
 	/**
 	 * Test for a particular character set
 	 *
-	 * @param	string $charset
+	 * @param	string	$charset
 	 * @return	bool
 	 */
 	public function accept_charset($charset = 'utf-8')
diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php
index 7009dea..0d25338 100644
--- a/system/libraries/Xmlrpc.php
+++ b/system/libraries/Xmlrpc.php
@@ -436,7 +436,7 @@
 	 */
 	public function sendPayload($msg)
 	{
-		$fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstr, $this->timeout);
+		$fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstring, $this->timeout);
 
 		if ( ! is_resource($fp))
 		{
@@ -458,7 +458,7 @@
 			.'Content-Length: '.strlen($msg->payload).$r.$r
 			.$msg->payload;
 
-		if ( ! fputs($fp, $op, strlen($op)))
+		if ( ! fwrite($fp, $op, strlen($op)))
 		{
 			error_log($this->xmlrpcstr['http_error']);
 			return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
@@ -1076,7 +1076,7 @@
 					// we have an I4/INT
 					// we must check that only 0123456789-<space> are characters here
 					$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\t ]+$/', $this->xh[$the_parser]['ac'])
-										? (int) $this->xh[$the_parset]['ac']
+										? (int) $this->xh[$the_parser]['ac']
 										: 'ERROR_NON_NUMERIC_FOUND';
 				}
 				$this->xh[$the_parser]['ac'] = '';
diff --git a/tests/README.md b/tests/README.md
index 6d83c34..b46f344 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -2,12 +2,6 @@
 
 Status : [![Build Status](https://secure.travis-ci.org/EllisLab/CodeIgniter.png?branch=feature/unit-tests)](http://travis-ci.org/EllisLab/CodeIgniter)
 
-*Do not merge to default until these issues have been addressed*
-
-- Clean up naming conventions
-- Figure out config stuff
-- Figure out database testing
-
 ### Introduction:
 
 This is the preliminary CodeIgniter testing documentation. It
diff --git a/tests/codeigniter/Setup_test.php b/tests/codeigniter/Setup_test.php
index 550245f..b48e32b 100644
--- a/tests/codeigniter/Setup_test.php
+++ b/tests/codeigniter/Setup_test.php
@@ -2,12 +2,12 @@
 
 class Setup_test extends PHPUnit_Framework_TestCase {
 	
-	function test_nonsense()
+	function test_bootstrap_constants()
 	{
-		$this->markTestIncomplete('not implemented');
-		// ensure that our bootstrapped test environment
-		// is a good representation of an isolated CI install
-		//die('here');
+		$this->assertTrue(defined('PROJECT_BASE'));
+		$this->assertTrue(defined('BASEPATH'));
+		$this->assertTrue(defined('APPPATH'));
+		$this->assertTrue(defined('VIEWPATH'));
 	}
 	
 }
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/count_test.php b/tests/codeigniter/database/query_builder/count_test.php
new file mode 100644
index 0000000..5e69169
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/count_test.php
@@ -0,0 +1,44 @@
+<?php
+
+class Count_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_count_all()
+	{
+		$job_count = $this->db->count_all('job');
+		
+		// Check the result
+		$this->assertEquals(4, $job_count);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_count_all_results()
+	{
+		$job_count = $this->db->like('name', 'ian')
+		                      ->count_all_results('job');
+		
+		// Check the result
+		$this->assertEquals(2, $job_count);
+	}
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/delete_test.php b/tests/codeigniter/database/query_builder/delete_test.php
new file mode 100644
index 0000000..84ea761
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/delete_test.php
@@ -0,0 +1,72 @@
+<?php
+
+class Delete_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_delete()
+	{
+		// Check initial record
+		$job1 = $this->db->where('id', 1)
+							->get('job')
+							->row();
+
+		$this->assertEquals('Developer', $job1->name);
+
+		// Do the delete
+		$this->db->delete('job', array('id' => 1));
+
+		// Check the record
+		$job1 = $this->db->where('id', 1)
+							->get('job');
+
+		$this->assertEmpty($job1->result_array());
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_delete_several_tables()
+	{
+		// Check initial record
+		$user4 = $this->db->where('id', 4)
+							->get('user')
+							->row();
+
+		$job4 = $this->db->where('id', 4)
+							->get('job')
+							->row();
+
+		$this->assertEquals('Musician', $job4->name);
+		$this->assertEquals('Chris Martin', $user4->name);
+
+		// Do the delete
+		$this->db->delete(array('job', 'user'), array('id' => 4));
+
+		// Check the record
+		$job4 = $this->db->where('id', 4)->get('job');
+		$user4 = $this->db->where('id', 4)->get('user');
+
+		$this->assertEmpty($job4->result_array());
+		$this->assertEmpty($user4->result_array());
+	}
+
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/distinct_test.php b/tests/codeigniter/database/query_builder/distinct_test.php
new file mode 100644
index 0000000..925eadb
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/distinct_test.php
@@ -0,0 +1,34 @@
+<?php
+
+class Distinct_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_distinct()
+	{
+		$users = $this->db->select('country')
+							  ->distinct()
+		                      ->get('user')
+		                      ->result_array();
+		
+		// Check the result
+		$this->assertEquals(3, count($users));
+	}
+
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/empty_test.php b/tests/codeigniter/database/query_builder/empty_test.php
new file mode 100644
index 0000000..d1f5628
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/empty_test.php
@@ -0,0 +1,39 @@
+<?php
+
+class Empty_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_empty_table()
+	{
+		// Check initial record
+		$jobs = $this->db->get('job')->result_array();
+
+		$this->assertEquals(4, count($jobs));
+
+		// Do the empty
+		$this->db->empty_table('job');
+
+		// Check the record
+		$jobs = $this->db->get('job');
+
+		$this->assertEmpty($jobs->result_array());
+	}
+
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/from_test.php b/tests/codeigniter/database/query_builder/from_test.php
new file mode 100644
index 0000000..95ae4df
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/from_test.php
@@ -0,0 +1,51 @@
+<?php
+
+class From_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_from_simple()
+	{
+		$jobs = $this->db->from('job')
+		                      ->get()
+		                      ->result_array();
+		
+		// Check items
+		$this->assertEquals(4, count($jobs));
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_from_with_where()
+	{
+		$job1 = $this->db->from('job')
+							->where('id', 1)
+		                    ->get()
+		                    ->row();
+		
+		// Check the result
+		$this->assertEquals('1', $job1->id);
+		$this->assertEquals('Developer', $job1->name);
+		$this->assertEquals('Awesome job, but sometimes makes you bored', $job1->description);
+	}
+	
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/group_test.php b/tests/codeigniter/database/query_builder/group_test.php
new file mode 100644
index 0000000..7d8abc3
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/group_test.php
@@ -0,0 +1,53 @@
+<?php
+
+class Group_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_group_by()
+	{
+		$jobs = $this->db->select('name')
+							  ->from('job')
+							  ->group_by('name')
+		                      ->get()
+		                      ->result_array();
+		
+		// Check the result
+		$this->assertEquals(4, count($jobs));
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_having_by()
+	{
+		$jobs = $this->db->select('name')
+							  ->from('job')
+							  ->group_by('name')
+							  ->having('SUM(id) > 2')
+		                      ->get()
+		                      ->result_array();
+		
+		// Check the result
+		$this->assertEquals(2, count($jobs));
+	}
+	
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/insert_test.php b/tests/codeigniter/database/query_builder/insert_test.php
index 53ce23c..8ba60e2 100644
--- a/tests/codeigniter/database/query_builder/insert_test.php
+++ b/tests/codeigniter/database/query_builder/insert_test.php
@@ -30,11 +30,10 @@
 		// Do normal insert
 		$this->assertTrue($this->db->insert('job', $job_data));
 
-		$jobs = $this->db->get('job')->result_array();
-		$job1 = $jobs[0];
+		$job1 = $this->db->get('job')->row();
 
 		// Check the result
-		$this->assertEquals('Grocery Sales', $job1['name']);
+		$this->assertEquals('Grocery Sales', $job1->name);
 
 	}
 
diff --git a/tests/codeigniter/database/query_builder/join_test.php b/tests/codeigniter/database/query_builder/join_test.php
new file mode 100644
index 0000000..e05329d
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/join_test.php
@@ -0,0 +1,38 @@
+<?php
+
+class Join_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_join_simple()
+	{
+		$job_user = $this->db->select('job.id as job_id, job.name as job_name, user.id as user_id, user.name as user_name')
+							->from('job')
+							->join('user', 'user.id = job.id')
+							->get()
+							->result_array();
+
+		// Check the result
+		$this->assertEquals('1', $job_user[0]['job_id']);
+		$this->assertEquals('1', $job_user[0]['user_id']);
+		$this->assertEquals('Derek Jones', $job_user[0]['user_name']);
+		$this->assertEquals('Developer', $job_user[0]['job_name']);
+	}
+	
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/like_test.php b/tests/codeigniter/database/query_builder/like_test.php
new file mode 100644
index 0000000..df98c71
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/like_test.php
@@ -0,0 +1,90 @@
+<?php
+
+class Like_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_like()
+	{
+		$job1 = $this->db->like('name', 'veloper')
+							->get('job')
+							->row();
+
+		// Check the result
+		$this->assertEquals('1', $job1->id);
+		$this->assertEquals('Developer', $job1->name);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_or_like()
+	{
+		$jobs = $this->db->like('name', 'ian')
+							->or_like('name', 'veloper')
+							->get('job')
+							->result_array();
+
+		// Check the result
+		$this->assertEquals(3, count($jobs));
+		$this->assertEquals('Developer', $jobs[0]['name']);
+		$this->assertEquals('Politician', $jobs[1]['name']);
+		$this->assertEquals('Musician', $jobs[2]['name']);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_not_like()
+	{
+		$jobs = $this->db->not_like('name', 'veloper')
+							->get('job')
+							->result_array();
+
+		// Check the result
+		$this->assertEquals(3, count($jobs));
+		$this->assertEquals('Politician', $jobs[0]['name']);
+		$this->assertEquals('Accountant', $jobs[1]['name']);
+		$this->assertEquals('Musician', $jobs[2]['name']);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_or_not_like()
+	{
+		$jobs = $this->db->like('name', 'an')
+							->or_not_like('name', 'veloper')
+							->get('job')
+							->result_array();
+
+		// Check the result
+		$this->assertEquals(3, count($jobs));
+		$this->assertEquals('Politician', $jobs[0]['name']);
+		$this->assertEquals('Accountant', $jobs[1]['name']);
+		$this->assertEquals('Musician', $jobs[2]['name']);
+	}
+	
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/limit_test.php b/tests/codeigniter/database/query_builder/limit_test.php
new file mode 100644
index 0000000..704f3b6
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/limit_test.php
@@ -0,0 +1,49 @@
+<?php
+
+class Limit_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_limit()
+	{
+		$jobs = $this->db->limit(2)
+		                      ->get('job')
+		                      ->result_array();
+		
+		// Check the result
+		$this->assertEquals(2, count($jobs));
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_limit_and_offset()
+	{
+		$jobs = $this->db->limit(2, 2)
+		                      ->get('job')
+		                      ->result_array();
+		
+		// Check the result
+		$this->assertEquals(2, count($jobs));
+		$this->assertEquals('Accountant', $jobs[0]['name']);
+		$this->assertEquals('Musician', $jobs[1]['name']);
+	}
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/order_test.php b/tests/codeigniter/database/query_builder/order_test.php
new file mode 100644
index 0000000..01aa1c2
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/order_test.php
@@ -0,0 +1,55 @@
+<?php
+
+class Order_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_order_ascending()
+	{
+		$jobs = $this->db->order_by('name', 'asc')
+		                      ->get('job')
+		                      ->result_array();
+		
+		// Check the result
+		$this->assertEquals(4, count($jobs));
+		$this->assertEquals('Accountant', $jobs[0]['name']);
+		$this->assertEquals('Developer', $jobs[1]['name']);
+		$this->assertEquals('Musician', $jobs[2]['name']);
+		$this->assertEquals('Politician', $jobs[3]['name']);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_order_descending()
+	{
+		$jobs = $this->db->order_by('name', 'desc')
+		                      ->get('job')
+		                      ->result_array();
+		
+		// Check the result
+		$this->assertEquals(4, count($jobs));
+		$this->assertEquals('Politician', $jobs[0]['name']);
+		$this->assertEquals('Musician', $jobs[1]['name']);
+		$this->assertEquals('Developer', $jobs[2]['name']);
+		$this->assertEquals('Accountant', $jobs[3]['name']);
+	}
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/select_test.php b/tests/codeigniter/database/query_builder/select_test.php
index dbf432a..0d299ed 100644
--- a/tests/codeigniter/database/query_builder/select_test.php
+++ b/tests/codeigniter/database/query_builder/select_test.php
@@ -41,10 +41,10 @@
 	{
 		$job_min = $this->db->select_min('id')
 		                    ->get('job')
-		                    ->result_array();
+		                    ->row();
 		
 		// Minimum id was 1
-		$this->assertEquals('1', $job_min[0]['id']);
+		$this->assertEquals('1', $job_min->id);
 	}
 
 	// ------------------------------------------------------------------------
@@ -56,10 +56,10 @@
 	{
 		$job_max = $this->db->select_max('id')
 		                    ->get('job')
-		                    ->result_array();
+		                    ->row();
 		
 		// Maximum id was 4
-		$this->assertEquals('4', $job_max[0]['id']);
+		$this->assertEquals('4', $job_max->id);
 	}
 
 	// ------------------------------------------------------------------------
@@ -71,10 +71,10 @@
 	{
 		$job_avg = $this->db->select_avg('id')
 		                    ->get('job')
-		                    ->result_array();
+		                    ->row();
 		
 		// Average should be 2.5
-		$this->assertEquals('2.5', $job_avg[0]['id']);
+		$this->assertEquals('2.5', $job_avg->id);
 	}
 
 	// ------------------------------------------------------------------------
@@ -86,10 +86,10 @@
 	{
 		$job_sum = $this->db->select_sum('id')
 		                    ->get('job')
-		                    ->result_array();
+		                    ->row();
 		
 		// Sum of ids should be 10
-		$this->assertEquals('10', $job_sum[0]['id']);
+		$this->assertEquals('10', $job_sum->id);
 	}
 	
 }
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/truncate_test.php b/tests/codeigniter/database/query_builder/truncate_test.php
new file mode 100644
index 0000000..2a9c8a9
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/truncate_test.php
@@ -0,0 +1,61 @@
+<?php
+
+class Truncate_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_truncate()
+	{
+		// Check initial record
+		$jobs = $this->db->get('job')->result_array();
+
+		$this->assertEquals(4, count($jobs));
+
+		// Do the empty
+		$this->db->truncate('job');
+
+		// Check the record
+		$jobs = $this->db->get('job');
+
+		$this->assertEmpty($jobs->result_array());
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_truncate_with_from()
+	{
+		// Check initial record
+		$users = $this->db->get('user')->result_array();
+
+		$this->assertEquals(4, count($users));
+
+		// Do the empty
+		$this->db->from('user')
+					->truncate();
+
+		// Check the record
+		$users = $this->db->get('user');
+
+		$this->assertEmpty($users->result_array());
+	}
+
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/update_test.php b/tests/codeigniter/database/query_builder/update_test.php
new file mode 100644
index 0000000..f5bbffd
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/update_test.php
@@ -0,0 +1,71 @@
+<?php
+
+class Update_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_update()
+	{
+		// Check initial record
+		$job1 = $this->db->where('id', 1)
+							->get('job')
+							->row();
+
+		$this->assertEquals('Developer', $job1->name);
+
+		// Do the update
+		$job_data = array('name' => 'Programmer');
+
+		$this->db->where('id', 1)
+						->update('job', $job_data);
+
+		// Check updated record
+		$job1 = $this->db->where('id', 1)
+							->get('job')
+							->row();
+
+		$this->assertEquals('Programmer', $job1->name);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_update_with_set()
+	{
+		// Check initial record
+		$job1 = $this->db->where('id', 4)
+							->get('job')
+							->row();
+
+		$this->assertEquals('Musician', $job1->name);
+
+		// Do the update
+		$this->db->set('name', 'Vocalist');
+		$this->db->update('job', NULL, 'id = 4');
+
+		// Check updated record
+		$job1 = $this->db->where('id', 4)
+							->get('job')
+							->row();
+
+		$this->assertEquals('Vocalist', $job1->name);
+	}
+}
\ No newline at end of file
diff --git a/tests/codeigniter/database/query_builder/where_test.php b/tests/codeigniter/database/query_builder/where_test.php
new file mode 100644
index 0000000..607eaa0
--- /dev/null
+++ b/tests/codeigniter/database/query_builder/where_test.php
@@ -0,0 +1,144 @@
+<?php
+
+class Where_test extends CI_TestCase {
+
+	/**
+	 * @var object Database/Query Builder holder
+	 */
+	protected $db;
+
+	public function set_up()
+	{
+		$this->db = Mock_Database_Schema_Skeleton::init(DB_DRIVER);
+
+		Mock_Database_Schema_Skeleton::create_tables();
+		Mock_Database_Schema_Skeleton::create_data();
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_where_simple_key_value()
+	{
+		$job1 = $this->db->where('id', 1)
+							->get('job')
+							->row();
+
+		// Check the result
+		$this->assertEquals('1', $job1->id);
+		$this->assertEquals('Developer', $job1->name);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_where_custom_key_value()
+	{
+		$jobs = $this->db->where('id !=', 1)
+							->get('job')
+							->result_array();
+
+		// Check the result
+		$this->assertEquals(3, count($jobs));
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_where_associative_array()
+	{
+		$where = array('id >' => 2, 'name !=' => 'Accountant');
+		$jobs = $this->db->where($where)
+							->get('job')
+							->result_array();
+
+		// Check the result
+		$this->assertEquals(1, count($jobs));
+
+		// Should be Musician
+		$job = current($jobs);
+
+		$this->assertEquals('Musician', $job['name']);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_where_custom_string()
+	{
+		$where = "id > 2 AND name != 'Accountant'";
+		$jobs = $this->db->where($where)
+							->get('job')
+							->result_array();
+
+		// Check the result
+		$this->assertEquals(1, count($jobs));
+
+		// Should be Musician
+		$job = current($jobs);
+
+		$this->assertEquals('Musician', $job['name']);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_where_or()
+	{
+		$jobs = $this->db->where('name !=', 'Accountant')
+							->or_where('id >', 3)
+							->get('job')
+							->result_array();
+
+		// Check the result
+		$this->assertEquals(3, count($jobs));
+		$this->assertEquals('Developer', $jobs[0]['name']);
+		$this->assertEquals('Politician', $jobs[1]['name']);
+		$this->assertEquals('Musician', $jobs[2]['name']);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_where_in()
+	{
+		$jobs = $this->db->where_in('name', array('Politician', 'Accountant'))
+							->get('job')
+							->result_array();
+
+		// Check the result
+		$this->assertEquals(2, count($jobs));
+		$this->assertEquals('Politician', $jobs[0]['name']);
+		$this->assertEquals('Accountant', $jobs[1]['name']);
+	}
+
+	// ------------------------------------------------------------------------
+
+	/**
+	 * @see ./mocks/schema/skeleton.php
+	 */
+	public function test_where_not_in()
+	{
+		$jobs = $this->db->where_not_in('name', array('Politician', 'Accountant'))
+							->get('job')
+							->result_array();
+
+		// Check the result
+		$this->assertEquals(2, count($jobs));
+		$this->assertEquals('Developer', $jobs[0]['name']);
+		$this->assertEquals('Musician', $jobs[1]['name']);
+	}
+	
+}
\ No newline at end of file
diff --git a/tests/mocks/database/ci_test.sqlite b/tests/mocks/database/ci_test.sqlite
index 86d868a..23a3de2 100755
--- a/tests/mocks/database/ci_test.sqlite
+++ b/tests/mocks/database/ci_test.sqlite
Binary files differ
diff --git a/tests/mocks/database/schema/skeleton.php b/tests/mocks/database/schema/skeleton.php
index a3d5bac..671336c 100644
--- a/tests/mocks/database/schema/skeleton.php
+++ b/tests/mocks/database/schema/skeleton.php
@@ -50,6 +50,28 @@
 	 */
 	public static function create_tables()
 	{
+		// User Table
+		static::$forge->add_field(array(
+			'id' => array(
+				'type' => 'INTEGER',
+				'constraint' => 3,
+			),
+			'name' => array(
+				'type' => 'VARCHAR',
+				'constraint' => 40,
+			),
+			'email' => array(
+				'type' => 'VARCHAR',
+				'constraint' => 100,
+			),
+			'country' => array(
+				'type' => 'VARCHAR',
+				'constraint' => 40,
+			),
+		));
+		static::$forge->add_key('id', TRUE);
+		static::$forge->create_table('user', (strpos(static::$driver, 'pgsql') === FALSE));
+
 		// Job Table
 		static::$forge->add_field(array(
 			'id' => array(
@@ -77,6 +99,12 @@
 	{
 		// Job Data
 		$data = array(
+			'user' => array(
+				array('id' => 1, 'name' => 'Derek Jones', 'email' => 'derek@world.com', 'country' => 'US'),
+				array('id' => 2, 'name' => 'Ahmadinejad', 'email' => 'ahmadinejad@world.com', 'country' => 'Iran'),
+				array('id' => 3, 'name' => 'Richard A Causey', 'email' => 'richard@world.com', 'country' => 'US'),
+				array('id' => 4, 'name' => 'Chris Martin', 'email' => 'chris@world.com', 'country' => 'UK'),
+			),
 			'job' => array(
 				array('id' => 1, 'name' => 'Developer', 'description' => 'Awesome job, but sometimes makes you bored'), 
 				array('id' => 2, 'name' => 'Politician', 'description' => 'This is not really a job'),
diff --git a/tests/travis/mysql.phpunit.xml b/tests/travis/mysql.phpunit.xml
index e9556f7..c5fcf13 100644
--- a/tests/travis/mysql.phpunit.xml
+++ b/tests/travis/mysql.phpunit.xml
@@ -14,11 +14,7 @@
     </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>
+			<directory suffix="test.php">../codeigniter</directory>
 		</testsuite>
 	</testsuites>
 	<filters>
diff --git a/tests/travis/pdo/mysql.phpunit.xml b/tests/travis/pdo/mysql.phpunit.xml
index 69eece2..f6fcc1c 100644
--- a/tests/travis/pdo/mysql.phpunit.xml
+++ b/tests/travis/pdo/mysql.phpunit.xml
@@ -14,10 +14,6 @@
     </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>
diff --git a/tests/travis/pdo/pgsql.phpunit.xml b/tests/travis/pdo/pgsql.phpunit.xml
index e68c3e0..6a23227 100644
--- a/tests/travis/pdo/pgsql.phpunit.xml
+++ b/tests/travis/pdo/pgsql.phpunit.xml
@@ -14,11 +14,7 @@
     </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>
+			<directory suffix="test.php">../../codeigniter</directory>
 		</testsuite>
 	</testsuites>
 	<filters>
diff --git a/tests/travis/pdo/sqlite.phpunit.xml b/tests/travis/pdo/sqlite.phpunit.xml
index 1871f62..b85b730 100644
--- a/tests/travis/pdo/sqlite.phpunit.xml
+++ b/tests/travis/pdo/sqlite.phpunit.xml
@@ -14,11 +14,7 @@
     </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>
+			<directory suffix="test.php">../../codeigniter</directory>
 		</testsuite>
 	</testsuites>
 	<filters>
diff --git a/tests/travis/pgsql.phpunit.xml b/tests/travis/pgsql.phpunit.xml
index ad8aede..78b6046 100644
--- a/tests/travis/pgsql.phpunit.xml
+++ b/tests/travis/pgsql.phpunit.xml
@@ -14,11 +14,7 @@
     </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>
+			<directory suffix="test.php">../codeigniter</directory>
 		</testsuite>
 	</testsuites>
 	<filters>
diff --git a/tests/travis/sqlite.phpunit.xml b/tests/travis/sqlite.phpunit.xml
index 628370e..46e3d50 100644
--- a/tests/travis/sqlite.phpunit.xml
+++ b/tests/travis/sqlite.phpunit.xml
@@ -14,11 +14,7 @@
     </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>
+			<directory suffix="test.php">../codeigniter</directory>
 		</testsuite>
 	</testsuites>
 	<filters>
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index bdb418f..d33a6a6 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -22,7 +22,7 @@
    -  PHP 5.1.6 is no longer supported. CodeIgniter now requires PHP 5.2.4.
    -  Added an optional backtrace to php-error template.
    -  Added Android to the list of user agents.
-   -  Added Windows 7 to the list of user platforms.
+   -  Added Windows 7, Android, Blackberry and iOS to the list of user platforms.
    -  Ability to log certain error types, not all under a threshold.
    -  Added support for pem, p10, p12, p7a, p7c, p7m, p7r, p7s, crt, crl, der, kdb, rsa, cer, sst, csr Certs to mimes.php.
    -  Added support for pgp and gpg to mimes.php.
@@ -55,7 +55,7 @@
 
 -  Database
 
-   -  Renamed the Active Record class to Query Builder to remove confusion with 
+   -  Renamed the Active Record class to Query Builder to remove confusion with
       the Active Record design pattern
    -  Added new :doc:`Query Builder <database/query_builder>` methods that return
    -  Added the ability to insert objects with insert_batch() in :doc:`Query Builder <database/query_builder>`.
@@ -77,6 +77,7 @@
 	 -  pg_version() is now used to get the database version number, when possible.
 	 -  Added db_set_charset() support.
 	 -  Added _optimize_table() support for the :doc:`Database Utility Class <database/utilities>` (rebuilds table indexes).
+	 -  Added boolean data type support in escape().
    -  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 internal method _protect_identifiers() to it instead - it was just an alias.
@@ -214,6 +215,9 @@
 -  Fixed a bug in SQLSRV's delete() method where like() and limit() conditions were ignored.
 -  Fixed a bug (#1265) - Database connections were always closed, regardless of the 'pconnect' option value.
 -  Fixed a bug (#128) - :doc:`Language Library <libraries/language>` did not correctly keep track of loaded language files.
+-  Fixed a bug (#1242) - Added Windows path compatibility to function read_dir of ZIP library
+-  Fixed a bug (#1314) - sess_destroy() did not destroy userdata.
+-  Fixed a bug (#1349) - get_extension() in the `File Uploading Library <libraries/file_uploading>` returned the original filename when it didn't have an actual extension.
 
 Version 2.1.1
 =============