Move mbstring/iconv configuration and MB_ENABLED, ICONV_ENABLED out of CI_Utf8::__construct()

Also, use mb_substitute_character() instead of ini_set()
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 044b647..70d6ca5 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -124,6 +124,11 @@
  * ------------------------------------------------------
  *  Instantiate the config class
  * ------------------------------------------------------
+ *
+ * Note: It is important that Config is loaded first as
+ * most other classes depend on it either directly or by
+ * depending on another class that uses it.
+ *
  */
 	$CFG =& load_class('Config', 'core');
 
@@ -138,14 +143,49 @@
 
 /*
  * ------------------------------------------------------
- *  Instantiate the UTF-8 class
+ * Important charset-related stuff
  * ------------------------------------------------------
  *
- * Note: Order here is rather important as the UTF-8
- * class needs to be used very early on, but it cannot
- * properly determine if UTF-8 can be supported until
- * after the Config class is instantiated.
+ * Configure mbstring and/or iconv if they are enabled
+ * and set MB_ENABLED and ICONV_ENABLED constants, so
+ * that we don't repeatedly do extension_loaded() or
+ * function_exists() calls.
  *
+ * Note: UTF-8 class depends on this. It used to be done
+ * in it's constructor, but it's _not_ class-specific.
+ *
+ */
+	$charset = strtoupper(config_item('charset'));
+
+	if (extension_loaded('mbstring'))
+	{
+		define('MB_ENABLED', TRUE);
+		mb_internal_encoding($charset);
+		// This is required for mb_convert_encoding() to strip invalid characters.
+		// That's utilized by CI_Utf8, but it's also done for consistency with iconv.
+		mb_substitute_character('none');
+	}
+	else
+	{
+		define('MB_ENABLED', FALSE);
+	}
+
+	// There's an ICONV_IMPL constant, but the PHP manual says that using
+	// iconv's predefined constants is "strongly discouraged".
+	if (extension_loaded('iconv'))
+	{
+		define('ICONV_ENABLED', TRUE);
+		iconv_set_encoding('internal_encoding', $charset);
+	}
+	else
+	{
+		define('ICONV_ENABLED', FALSE);
+	}
+
+/*
+ * ------------------------------------------------------
+ *  Instantiate the UTF-8 class
+ * ------------------------------------------------------
  */
 	$UNI =& load_class('Utf8', 'core');
 
diff --git a/system/core/Utf8.php b/system/core/Utf8.php
index b58c611..6ca1a02 100644
--- a/system/core/Utf8.php
+++ b/system/core/Utf8.php
@@ -48,42 +48,10 @@
 	 */
 	public function __construct()
 	{
-		log_message('debug', 'Utf8 Class Initialized');
-
-		$charset = strtoupper(config_item('charset'));
-
-		// set internal encoding for multibyte string functions if necessary
-		// and set a flag so we don't have to repeatedly use extension_loaded()
-		// or function_exists()
-		if (extension_loaded('mbstring'))
-		{
-			define('MB_ENABLED', TRUE);
-			mb_internal_encoding($charset);
-			// This is required for mb_convert_encoding() to strip invalid characters
-			ini_set('mbstring.substitute_character', 'none');
-		}
-		else
-		{
-			define('MB_ENABLED', FALSE);
-		}
-
-		// Do the same for iconv, which actually has more easy to remember
-		// predefined constants (such as ICONV_IMPL), but the iconv PHP
-		// manual page says that using them is "strongly discouraged".
-		if (extension_loaded('iconv'))
-		{
-			define('ICONV_ENABLED', TRUE);
-			iconv_set_encoding('internal_encoding', $charset);
-		}
-		else
-		{
-			define('ICONV_ENABLED', FALSE);
-		}
-
 		if (
 			defined('PREG_BAD_UTF8_ERROR')				// PCRE must support UTF-8
 			&& (ICONV_ENABLED === TRUE OR MB_ENABLED === TRUE)	// iconv or mbstring must be installed
-			&& $charset === 'UTF-8'					// Application charset must be UTF-8
+			&& strnatcasecmp(config_item('charset'), 'UTF-8') === 0	// Application charset must be UTF-8
 			)
 		{
 			define('UTF8_ENABLED', TRUE);
@@ -94,6 +62,8 @@
 			define('UTF8_ENABLED', FALSE);
 			log_message('debug', 'UTF-8 Support Disabled');
 		}
+
+		log_message('debug', 'Utf8 Class Initialized');
 	}
 
 	// --------------------------------------------------------------------
diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php
index c98d885..7f10ea1 100644
--- a/tests/Bootstrap.php
+++ b/tests/Bootstrap.php
@@ -40,6 +40,29 @@
 // Prep our test environment
 include_once $dir.'/mocks/core/common.php';
 include_once SYSTEM_PATH.'core/Common.php';
+
+
+if (extension_loaded('mbstring'))
+{
+	defined('MB_ENABLED') OR define('MB_ENABLED', TRUE);
+	mb_internal_encoding('UTF-8');
+	mb_substitute_character('none');
+}
+else
+{
+	defined('MB_ENABLED') OR define('MB_ENABLED', FALSE);
+}
+
+if (extension_loaded('iconv'))
+{
+	defined('ICONV_ENABLED') OR define('ICONV_ENABLED', TRUE);
+	iconv_set_encoding('internal_encoding', 'UTF-8');
+}
+else
+{
+	defined('ICONV_ENABLED') OR define('ICONV_ENABLED', FALSE);
+}
+
 include_once $dir.'/mocks/autoloader.php';
 spl_autoload_register('autoload');
 
diff --git a/tests/mocks/core/utf8.php b/tests/mocks/core/utf8.php
index 9dda43a..30b78ad 100644
--- a/tests/mocks/core/utf8.php
+++ b/tests/mocks/core/utf8.php
@@ -3,35 +3,14 @@
 class Mock_Core_Utf8 extends CI_Utf8 {
 
 	/**
-	 * We need to define several constants as
-	 * the same process within CI_Utf8 class constructor.
+	 * We need to define UTF8_ENABLED the same way that
+	 * CI_Utf8 constructor does.
 	 *
 	 * @covers CI_Utf8::__construct()
 	 */
 	public function __construct()
 	{
 		defined('UTF8_ENABLED') OR define('UTF8_ENABLED', TRUE);
-
-		if (extension_loaded('mbstring'))
-		{
-			defined('MB_ENABLED') OR define('MB_ENABLED', TRUE);
-			mb_internal_encoding('UTF-8');
-			ini_set('mbstring.substitute_character', 'none');
-		}
-		else
-		{
-			defined('MB_ENABLED') OR define('MB_ENABLED', FALSE);
-		}
-
-		if (extension_loaded('iconv'))
-		{
-			defined('ICONV_ENABLED') OR define('ICONV_ENABLED', TRUE);
-			iconv_set_encoding('internal_encoding', 'UTF-8');
-		}
-		else
-		{
-			defined('ICONV_ENABLED') OR define('ICONV_ENABLED', FALSE);
-		}
 	}
 
 	public function is_ascii_test($str)