Merge master (2.1.0) and fixed conflicts.
diff --git a/application/config/migration.php b/application/config/migration.php
index f568574..4fb027b 100644
--- a/application/config/migration.php
+++ b/application/config/migration.php
@@ -90,5 +90,4 @@
 $config['migration_path'] = APPPATH . 'migrations/';
 
 
-/* End of file migration.php */
-/* Location: ./application/config/migration.php */
\ No newline at end of file
+/* End of file migration.php */
\ No newline at end of file
diff --git a/system/core/Input.php b/system/core/Input.php
index 946d929..3cbbe78 100755
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -740,7 +740,6 @@
 	}
 
 }
-// END Input class
 
 /* End of file Input.php */
 /* Location: ./system/core/Input.php */
diff --git a/system/core/Security.php b/system/core/Security.php
index ee4f0a0..ce3f7d3 100755
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -95,7 +95,8 @@
 					'-moz-binding'		=> '[removed]',
 					'<!--'				=> '&lt;!--',
 					'-->'				=> '--&gt;',
-					'<![CDATA['			=> '&lt;![CDATA['
+					'<![CDATA['			=> '&lt;![CDATA[',
+					'<comment>'			=> '&lt;comment&gt;'
 	);
 
 	/**
@@ -498,15 +499,7 @@
 	{
 		if ($this->_xss_hash == '')
 		{
-			if (phpversion() >= 4.2)
-			{
-				mt_srand();
-			}
-			else
-			{
-				mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff);
-			}
-
+			mt_srand();
 			$this->_xss_hash = md5(time() + mt_rand(0, 1999999999));
 		}
 
@@ -520,6 +513,12 @@
 	 *
 	 * This function is a replacement for html_entity_decode()
 	 *
+	 * The reason we are not using html_entity_decode() by itself is because
+	 * while it is not technically correct to leave out the semicolon
+	 * at the end of an entity most browsers will still interpret the entity
+	 * correctly.  html_entity_decode() does not convert entities without
+	 * semicolons, so we are left with our own little solution here. Bummer.
+	 *
 	 * @param	string
 	 * @param	string
 	 * @return	string
@@ -536,11 +535,6 @@
 			$charset = config_item('charset');
 		}
 
-		// The reason we are not using html_entity_decode() by itself is because
-		// while it is not technically correct to leave out the semicolon
-		// at the end of an entity most browsers will still interpret the entity
-		// correctly.  html_entity_decode() does not convert entities without
-		// semicolons, so we are left with our own little solution here. Bummer.
 		$str = html_entity_decode($str, ENT_COMPAT, $charset);
 		$str = preg_replace('~&#x(0*[0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str);
 		return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str);
@@ -637,25 +631,45 @@
 	protected function _remove_evil_attributes($str, $is_image)
 	{
 		// All javascript event handlers (e.g. onload, onclick, onmouseover), style, and xmlns
-		$evil_attributes = array('on\w*', 'style', 'xmlns');
+		$evil_attributes = array('on\w*', 'style', 'xmlns', 'formaction');
 
 		if ($is_image === TRUE)
 		{
 			/*
-			 * Adobe Photoshop puts XML metadata into JFIF images,
+			 * Adobe Photoshop puts XML metadata into JFIF images, 
 			 * including namespacing, so we have to allow this for images.
 			 */
 			unset($evil_attributes[array_search('xmlns', $evil_attributes)]);
 		}
-
+		
 		do {
-			$str = preg_replace(
-				"#<(/?[^><]+?)([^A-Za-z\-])(".implode('|', $evil_attributes).")(\s*=\s*)([\"][^>]*?[\"]|[\'][^>]*?[\']|[^>]*?)([\s><])([><]*)#i",
-				"<$1$6",
-				$str, -1, $count
-			);
-		} while ($count);
+			$count = 0;
+			$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);
+			
+			foreach ($matches as $attr)
+			{
+				$attribs[] = preg_quote($attr[0], '/');
+			}
+			
+			// find occurrences of illegal attribute strings with quotes (042 and 047 are octal quotes)
+			preg_match_all("/(".implode('|', $evil_attributes).")\s*=\s*(\042|\047)([^\\2]*?)(\\2)/is",  $str, $matches, PREG_SET_ORDER);
 
+			foreach ($matches as $attr)
+			{
+				$attribs[] = preg_quote($attr[0], '/');
+			}
+
+			// 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);
+			}
+			
+		} while ($count);
+		
 		return $str;
 	}
 
@@ -877,4 +891,4 @@
 }
 
 /* End of file Security.php */
-/* Location: ./system/core/Security.php */
+/* Location: ./system/core/Security.php */
\ No newline at end of file
diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php
index 66f782d..29297b6 100644
--- a/system/database/drivers/mysql/mysql_result.php
+++ b/system/database/drivers/mysql/mysql_result.php
@@ -98,10 +98,10 @@
 		$retval = array();
 		while ($field = mysql_fetch_object($this->result_id))
 		{
-			preg_match('/([a-zA-Z]+)(\((\d+)\))?/i', $field->Type, $matches);
+			preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field->Type, $matches);
 
-			$type = $matches[1];
-			$length = isset($matches[3]) ? (int) $matches[3] : NULL;
+			$type = (array_key_exists(1, $matches)) ? $matches[1] : NULL;
+			$length = (array_key_exists(2, $matches)) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL;
 
 			$F				= new stdClass();
 			$F->name		= $field->Field;
diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php
index bfe500e..163788b 100644
--- a/system/database/drivers/mysqli/mysqli_result.php
+++ b/system/database/drivers/mysqli/mysqli_result.php
@@ -98,10 +98,10 @@
 		$retval = array();
 		while ($field = mysqli_fetch_object($this->result_id))
 		{
-			preg_match('/([a-zA-Z]+)(\((\d+)\))?/i', $field->Type, $matches);
+			preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field->Type, $matches);
 
-			$type = $matches[1];
-			$length = isset($matches[3]) ? (int) $matches[3] : NULL;
+			$type = (array_key_exists(1, $matches)) ? $matches[1] : NULL;
+			$length = (array_key_exists(2, $matches)) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL;
 
 			$F				= new stdClass();
 			$F->name		= $field->Field;
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index a66a16e..5f63a37 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -255,7 +255,11 @@
 		// Reset the transaction failure flag.
 		// If the $test_mode flag is set to TRUE transactions will be rolled back
 		// even if the queries produce a successful result.
+<<<<<<< HEAD
 		$this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
+=======
+		$this->_trans_failure = (bool) ($test_mode === TRUE);
+>>>>>>> master
 
 		return $this->conn_id->beginTransaction();
 	}
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index 6739db3..7bde4c4 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -1692,12 +1692,7 @@
 	 */
 	protected function _smtp_connect()
 	{
-		$ssl = NULL;
-
-		if ($this->smtp_crypto == 'ssl')
-		{
-			$ssl = 'ssl://';
-		}
+		$ssl = ($this->smtp_crypto == 'ssl') ? 'ssl://' : NULL;
 
 		$this->_smtp_connect = fsockopen($ssl.$this->smtp_host,
 										$this->smtp_port,
@@ -1717,6 +1712,7 @@
 		{
 			$this->_send_command('hello');
 			$this->_send_command('starttls');
+
 			$crypto = stream_socket_enable_crypto($this->_smtp_connect, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT);
 
 			if ($crypto !== TRUE)
@@ -2112,4 +2108,4 @@
 // END CI_Email class
 
 /* End of file Email.php */
-/* Location: ./system/libraries/Email.php */
+/* Location: ./system/libraries/Email.php */
\ No newline at end of file
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
index 7398c29..f470deb 100644
--- a/system/libraries/Pagination.php
+++ b/system/libraries/Pagination.php
@@ -298,11 +298,11 @@
 		if ($this->last_link !== FALSE AND ($this->cur_page + $this->num_links) < $num_pages)
 		{
 			$i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;
-			
+
 			$output .= $this->last_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$this->prefix.$i.$this->suffix.'">'.$this->last_link.'</a>'.$this->last_tag_close;
 		}
 
-		// Kill double slashes.  Note: Sometimes we can end up with a double slash
+		// Kill double slashes. Note: Sometimes we can end up with a double slash
 		// in the penultimate link so we'll kill all double slashes.
 		$output = preg_replace("#([^:])//+#", "\\1/", $output);
 
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
index 56062be..66e91c5 100644
--- a/system/libraries/Upload.php
+++ b/system/libraries/Upload.php
@@ -1033,7 +1033,7 @@
 	protected function _file_mime_type($file)
 	{
 		// Use if the Fileinfo extension, if available (only versions above 5.3 support the FILEINFO_MIME_TYPE flag)
-		if (is_php('5.3') && function_exists('finfo_file'))
+		if ( (float) substr(phpversion(), 0, 3) >= 5.3 && function_exists('finfo_file'))
 		{
 			$finfo = new finfo(FILEINFO_MIME_TYPE);
 			if ($finfo !== FALSE) // This is possible, if there is no magic MIME database file found on the system
@@ -1086,4 +1086,4 @@
 // END Upload Class
 
 /* End of file Upload.php */
-/* Location: ./system/libraries/Upload.php */
+/* Location: ./system/libraries/Upload.php */
\ No newline at end of file