Merge pull request #1324 from toopay/db-tests

Improved DB tests
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/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/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/libraries/Form_validation.php b/system/libraries/Form_validation.php
index 5547c6a..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];
 			}
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/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index a705319..d457a3f 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.
@@ -214,8 +214,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 (#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
 =============