CI_Security::_decode_entity() to replace dangerous HTML5 entities

Related to issue #2771
diff --git a/system/core/Security.php b/system/core/Security.php
index eb26958..d6356f8 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -62,6 +62,17 @@
 	);
 
 	/**
+	 * HTML5 entities
+	 *
+	 * @var	array
+	 */
+	public $html5_entities = array(
+		':'	=> ':',
+		'('	=> '(',
+		')'	=> ')'
+	);
+
+	/**
 	 * XSS Hash
 	 *
 	 * Random Hash for protecting URLs.
@@ -810,7 +821,14 @@
 	 */
 	protected function _decode_entity($match)
 	{
-		return $this->entity_decode($match[0], strtoupper(config_item('charset')));
+		// entity_decode() won't convert dangerous HTML5 entities
+		// (it could, but ENT_HTML5 is only available since PHP 5.4),
+		// so we'll do that here
+		return str_ireplace(
+			array_keys($this->html5_entities),
+			array_values($this->html5_entities),
+			$this->entity_decode($match[0], strtoupper(config_item('charset')))
+		);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index ae29007..5130501 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -685,7 +685,8 @@
 -  Fixed a bug where :doc:`User Agent Library <libraries/user_agent>` methods ``accept_charset()`` and ``accept_lang()`` didn't properly parse HTTP headers that contain spaces.
 -  Fixed a bug where *default_controller* was called instad of triggering a 404 error if the current route is in a controller directory.
 -  Fixed a bug (#2737) - :doc:`XML-RPC Library <libraries/xmlrpc>` used objects as array keys, which triggered E_NOTICE messages.
--  Fixed a bug (#2729) - ``CI_Securty::_validate_entities()`` used overly-intrusive ``preg_replace()`` patterns that produced false-positives.
+-  Fixed a bug (#2729) - ``CI_Security::_validate_entities()`` used overly-intrusive ``preg_replace()`` patterns that produced false-positives.
+-  Fixed a bug (#2771) - ``CI_Security::xss_clean()`` didn't take into account HTML5 entities.
 
 Version 2.1.4
 =============