Index: /trunk/lib/App.inc.php
===================================================================
--- /trunk/lib/App.inc.php	(revision 723)
+++ /trunk/lib/App.inc.php	(revision 724)
@@ -225,4 +225,8 @@
         // WP forcefully adds slashes to all input despite the setting of magic_quotes_gpc.
         'always_dispel_magicquotes' => false,
+
+        // The /u pattern modifier should only be used on UTF-8 strings. This value will be changed to `u` if character_set = `utf-8`.
+        // Use the unicode modifier like this:  preg_replace('/[^0-9]/' . $app->getParam('preg_u'), '', $str);
+        'preg_u' => '',
     );
 
@@ -376,4 +380,5 @@
         switch (mb_strtolower($this->getParam('character_set'))) {
         case 'utf-8' :
+            $this->setParam(['preg_u' => 'u']);
             mb_language('uni');
             break;
@@ -537,7 +542,7 @@
 
         // To get a safe hostname, remove port and invalid hostname characters.
-        $safe_http_host = preg_replace('/[^a-z\d.:-]/u', '', strtok(getenv('HTTP_HOST'), ':')); // FIXME: strtok shouldn't be used if there is a chance HTTP_HOST may be empty except for the port, e.g., `:80` will return `80`
+        $safe_http_host = preg_replace('/[^a-z\d.:-]/' . $this->getParam('preg_u'), '', strtok(getenv('HTTP_HOST'), ':')); // FIXME: strtok shouldn't be used if there is a chance HTTP_HOST may be empty except for the port, e.g., `:80` will return `80`
         // If strtok() matched a ':' in the previous line, the rest of the string contains the port number (or FALSE)
-        $safe_http_port = preg_replace('/[^0-9]/u', '', strtok(''));
+        $safe_http_port = preg_replace('/[^0-9]/' . $this->getParam('preg_u'), '', strtok(''));
         if ('' != $safe_http_host && '' == $this->getParam('site_hostname')) {
             $this->setParam(array('site_hostname' => $safe_http_host));
@@ -1190,7 +1195,10 @@
             $query_args = urlEncodeArray(array_merge($this->_carry_queries, $one_time_carry_queries));
             foreach ($query_args as $key=>$val) {
+
                 // Avoid indexed-array query params because in a URL array param keys should all match.
                 // I.e, we want to use `array[]=A&array[]=B` instead of `array[0]=A&array[1]=B`.
-                $key = preg_replace('/\[\d+\]$/u', '[]', $key);
+                // This is disabled because sometimes we need to retain a numeric array key, e.g., ?metadata_id[54]=on. Can't remember where having indexed-array queries was a problem, hopefully this was only added as an aesthetic feature?
+                // $key = preg_replace('/\[\d+\]$/' . $this->getParam('preg_u'), '[]', $key);
+
                 // Check value is set and value does not already exist in the url.
                 if (!preg_match('/[?&]' . preg_quote($key) . '=/', $url)) {
@@ -1261,5 +1269,5 @@
 
         // Replace any & not followed by an html or unicode entity with its &amp; equivalent.
-        $url = preg_replace('/&(?![\w\d#]{1,10};)/u', '&amp;', $url);
+        $url = preg_replace('/&(?![\w\d#]{1,10};)/' . $this->getParam('preg_u'), '&amp;', $url);
 
         return $url;
@@ -1577,5 +1585,5 @@
         if ('' != $url && is_string($url)) {
             // Delete any boomerang request keys in the query string (along with any trailing delimiters after the deletion).
-            $url = preg_replace(array('/([&?])boomerang=[^&?]+[&?]?/u', '/[&?]$/'), array('$1', ''), $url);
+            $url = preg_replace(array('/([&?])boomerang=[^&?]+[&?]?/' . $this->getParam('preg_u'), '/[&?]$/'), array('$1', ''), $url);
 
             if (isset($_SESSION['_app'][$this->_ns]['boomerang']) && is_array($_SESSION['_app'][$this->_ns]['boomerang']) && !empty($_SESSION['_app'][$this->_ns]['boomerang'])) {
Index: /trunk/lib/CSS.inc.php
===================================================================
--- /trunk/lib/CSS.inc.php	(revision 723)
+++ /trunk/lib/CSS.inc.php	(revision 724)
@@ -182,5 +182,5 @@
                 // Strip whitespace and print file.
                 echo preg_replace(
-                    array('!/\*.*?\*/!su', '/[\n\r]+/u', '/([;:])\s+/mu', '/\s*}[ \t]*/u', '/\s*{\s*/u', '/[ \t\n\r]*,[ \t\n\r]*/u', '/^\s+/u'),
+                    array('!/\*.*?\*/!s' . $app->getParam('preg_u'), '/[\n\r]+/' . $app->getParam('preg_u'), '/([;:])\s+/m' . $app->getParam('preg_u'), '/\s*}[ \t]*/' . $app->getParam('preg_u'), '/\s*{\s*/' . $app->getParam('preg_u'), '/[ \t\n\r]*,[ \t\n\r]*/' . $app->getParam('preg_u'), '/^\s+/' . $app->getParam('preg_u')),
                     array('', "\n", '$1', '}', '{', ',', ''), file_get_contents($file, true)
                 );
Index: /trunk/lib/DB.inc.php
===================================================================
--- /trunk/lib/DB.inc.php	(revision 723)
+++ /trunk/lib/DB.inc.php	(revision 724)
@@ -180,5 +180,5 @@
         if (!$this->dbh || mysql_error($this->dbh)) {
             $mysql_error_msg = $this->dbh ? 'Codebase MySQL connect error: (' . mysql_errno($this->dbh) . ') ' . mysql_error($this->dbh) : sprintf('Codebase MySQL connect error: Could not connect to server (db_server=%s, db_name=%s, db_user=%s, db_pass=%s)', $this->getParam('db_server'), $this->getParam('db_name'), $this->getParam('db_user'), ('' == $this->getParam('db_pass') ? 'NO' : 'YES'));
-            $app->logMsg($mysql_error_msg, LOG_EMERG, __FILE__, __LINE__);
+            $app->logMsg($mysql_error_msg, LOG_ERR, __FILE__, __LINE__);
 
             // Print helpful or pretty error?
@@ -346,5 +346,5 @@
         $this->_query_count++;
 
-        $debugqry = preg_replace("/\n[\t ]+/u", "\n", $query);
+        $debugqry = preg_replace('/\n[\t ]+/' . $app->getParam('preg_u'), "\n", $query);
         if ($this->getParam('db_always_debug') || $debug) {
             if ($debug > 1) {
Index: /trunk/lib/Email.inc.php
===================================================================
--- /trunk/lib/Email.inc.php	(revision 723)
+++ /trunk/lib/Email.inc.php	(revision 724)
@@ -102,4 +102,6 @@
     public function __construct($params=null)
     {
+        $app =& App::getInstance();
+
         // The regex used in validEmail(). Set here instead of in the default _params above so we can use the concatenation . dot.
         // This matches a (valid) email address as complex as:
@@ -118,5 +120,5 @@
         . '(?:\s*>\s*|>\s+\([^,@]+\)\s*)'                               // TRUE, ensure ending >
         . '|'
-        . '(?:|\s*|\s+\([^,@]+\)\s*))$/iu'));                            // FALSE ensure there is no ending >
+        . '(?:|\s*|\s+\([^,@]+\)\s*))$/i' . $app->getParam('preg_u'))); // FALSE ensure there is no ending >
 
         if (isset($params)) {
@@ -396,5 +398,5 @@
             $envelope_sender_address = sprintf('<%s>', trim($this->_params['envelope_sender_address'], '<>'));
         } else {
-            $envelope_sender_address = preg_replace('/^.*<?([^\s@\[\]<>()]+\@[A-Za-z0-9.-]{1,}\.[A-Za-z]{2,5})>?$/iUu', '$1', $this->_params['from']);
+            $envelope_sender_address = preg_replace('/^.*<?([^\s@\[\]<>()]+\@[A-Za-z0-9.-]{1,}\.[A-Za-z]{2,5})>?$/iU' . $app->getParam('preg_u'), '$1', $this->_params['from']);
         }
         if ('' != $envelope_sender_address && $this->validEmail($envelope_sender_address)) {
Index: /trunk/lib/JS.inc.php
===================================================================
--- /trunk/lib/JS.inc.php	(revision 723)
+++ /trunk/lib/JS.inc.php	(revision 724)
@@ -182,5 +182,5 @@
                 // Strip whitespace and print file.
                 echo preg_replace(
-                    array('/(?<=^|;|{)\s*\/\/.*$/mu', '/(?<=^|;|{)\s*\/\*.*?\*\//msu', '/[\n\r]+/u', '/[ \t]+}[ \t]+/u', '/[ \t]+{[ \t]+/u', '/\s+=\s+/u', '/^[ \t]+/mu', '/[ \t]+$/mu'),
+                    array('/(?<=^|;|{)\s*\/\/.*$/m' . $app->getParam('preg_u'), '/(?<=^|;|{)\s*\/\*.*?\*\//ms' . $app->getParam('preg_u'), '/[\n\r]+/' . $app->getParam('preg_u'), '/[ \t]+}[ \t]+/' . $app->getParam('preg_u'), '/[ \t]+{[ \t]+/' . $app->getParam('preg_u'), '/\s+=\s+/' . $app->getParam('preg_u'), '/^[ \t]+/m' . $app->getParam('preg_u'), '/[ \t]+$/m' . $app->getParam('preg_u')),
                     array('', '', "\n", '}', '{', '=', '', ''), file_get_contents($file, true)
                 );
Index: /trunk/lib/PDO.inc.php
===================================================================
--- /trunk/lib/PDO.inc.php	(revision 723)
+++ /trunk/lib/PDO.inc.php	(revision 724)
@@ -379,5 +379,5 @@
         $this->_query_count++;
 
-        $debugqry = preg_replace("/\n[\t ]+/u", "\n", $query);
+        $debugqry = preg_replace('/\n[\t ]+/' . $app->getParam('preg_u'), "\n", $query);
         if ($this->getParam('db_always_debug') || $debug) {
             if ($debug > 1) {
@@ -435,5 +435,5 @@
         $this->_query_count++;
 
-        $debugqry = preg_replace("/\n[\t ]+/u", "\n", $query);
+        $debugqry = preg_replace('/\n[\t ]+/' . $app->getParam('preg_u'), "\n", $query);
         if ($this->getParam('db_always_debug')) {
             echo "<!-- ----------------- PDO prepare $this->_query_count ---------------------\n$debugqry\n-->\n";
@@ -507,5 +507,7 @@
     static function sanitizeIdentifier($idname)
     {
-        return preg_replace('/\W/u', '', $idname);
+        $app =& App::getInstance();
+
+        return preg_replace('/\W/' . $app->getParam('preg_u'), '', $idname);
     }
 
Index: /trunk/lib/Upload.inc.php
===================================================================
--- /trunk/lib/Upload.inc.php	(revision 723)
+++ /trunk/lib/Upload.inc.php	(revision 724)
@@ -516,9 +516,9 @@
 
         $file_name = preg_replace(array(
-            '/&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml|caron);/ui',
-            '/&(?:amp);/ui',
-            '/[&;]+/u',
-            '/[^a-zA-Z0-9()@._=+-]+/u',
-            '/^_+|_+$/u'
+            '/&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml|caron);/i' . $app->getParam('preg_u'),
+            '/&(?:amp);/i' . $app->getParam('preg_u'),
+            '/[&;]+/' . $app->getParam('preg_u'),
+            '/[^a-zA-Z0-9()@._=+-]+/' . $app->getParam('preg_u'),
+            '/^_+|_+$/' . $app->getParam('preg_u')
         ), array(
             '$1',
Index: /trunk/lib/Utilities.inc.php
===================================================================
--- /trunk/lib/Utilities.inc.php	(revision 723)
+++ /trunk/lib/Utilities.inc.php	(revision 724)
@@ -118,9 +118,11 @@
 function getDump($var, $serialize=false)
 {
+    $app =& App::getInstance();
+
     ob_start();
     print_r($var);
     $d = ob_get_contents();
     ob_end_clean();
-    return $serialize ? preg_replace('/\s+/mu', ' ', $d) : $d;
+    return $serialize ? preg_replace('/\s+/m' . $app->getParam('preg_u'), ' ', $d) : $d;
 }
 
@@ -140,4 +142,6 @@
 function fancyDump($var, $indent='- ', $depth=1)
 {
+    $app =& App::getInstance();
+
     $indent_str = str_repeat($indent, $depth);
     $output = '';
@@ -154,5 +158,5 @@
         $output .= sprintf("%s%s\n", $indent_str, $var);
     }
-    return preg_replace(['/^[ \t]+$/u', '/\n\n+/u', '/^(?:\S( ))?(?:\S( ))?(?:\S( ))?(?:\S( ))?(?:\S( ))?(?:\S( ))?(?:\S( ))?(?:\S( ))?(\S )/mu'], ['', "\n", '$1$1$2$2$3$3$4$4$5$5$6$6$7$7$8$8$9'], $output);
+    return preg_replace(['/^[ \t]+$/' . $app->getParam('preg_u'), '/\n\n+/' . $app->getParam('preg_u'), '/^(?:\S( ))?(?:\S( ))?(?:\S( ))?(?:\S( ))?(?:\S( ))?(?:\S( ))?(?:\S( ))?(?:\S( ))?(\S )/m' . $app->getParam('preg_u')], ['', "\n", '$1$1$2$2$3$3$4$4$5$5$6$6$7$7$8$8$9'], $output);
 }
 
@@ -330,4 +334,6 @@
 function highlightWords($text, $search, $class='sc-highlightwords')
 {
+    $app =& App::getInstance();
+
     $words = preg_split('/[^\w]/', $search, -1, PREG_SPLIT_NO_EMPTY);
 
@@ -337,5 +343,5 @@
     foreach ($words as $w) {
         if ('' != trim($w)) {
-            $search[] = '/\b(' . preg_quote($w) . ')\b/iu';
+            $search[] = '/\b(' . preg_quote($w) . ')\b/i' . $app->getParam('preg_u');
             $replace[] = '<span class="' . $class . '">$1</span>';
         }
@@ -414,5 +420,7 @@
 function encodeEmail($email, $at=' at ', $dot=' dot ')
 {
-    $search = array('/@/u', '/\./u');
+    $app =& App::getInstance();
+
+    $search = array('/@/' . $app->getParam('preg_u'), '/\./' . $app->getParam('preg_u'));
     $replace = array($at, $dot);
     return preg_replace($search, $replace, $email);
@@ -438,4 +446,6 @@
 function truncate($str, $len=50, $where='end', $delim='âŠ')
 {
+    $app =& App::getInstance();
+
     $dlen = mb_strlen($delim);
     if ($len <= $dlen || mb_strlen($str) <= $dlen) {
@@ -453,12 +463,12 @@
     switch ($where) {
     case 'start' :
-        return preg_replace(array(sprintf('/^.{%s,}(.{%s})$/su', $dlen + 1, $part1 + $part2), sprintf('/\s*%s{%s,}\s*/su', preg_quote($delim), $dlen)), array($delim . '$1', $delim), $str);
+        return preg_replace(array(sprintf('/^.{%s,}(.{%s})$/s' . $app->getParam('preg_u'), $dlen + 1, $part1 + $part2), sprintf('/\s*%s{%s,}\s*/s' . $app->getParam('preg_u'), preg_quote($delim), $dlen)), array($delim . '$1', $delim), $str);
 
     case 'middle' :
-        return preg_replace(array(sprintf('/^(.{%s}).{%s,}(.{%s})$/su', $part1, $dlen + 1, $part2), sprintf('/\s*%s{%s,}\s*/su', preg_quote($delim), $dlen)), array('$1' . $delim . '$2', $delim), $str);
+        return preg_replace(array(sprintf('/^(.{%s}).{%s,}(.{%s})$/s' . $app->getParam('preg_u'), $part1, $dlen + 1, $part2), sprintf('/\s*%s{%s,}\s*/s' . $app->getParam('preg_u'), preg_quote($delim), $dlen)), array('$1' . $delim . '$2', $delim), $str);
 
     case 'end' :
     default :
-        return preg_replace(array(sprintf('/^(.{%s}).{%s,}$/su', $part1 + $part2, $dlen + 1), sprintf('/\s*%s{%s,}\s*/su', preg_quote($delim), $dlen)), array('$1' . $delim, $delim), $str);
+        return preg_replace(array(sprintf('/^(.{%s}).{%s,}$/s' . $app->getParam('preg_u'), $part1 + $part2, $dlen + 1), sprintf('/\s*%s{%s,}\s*/s' . $app->getParam('preg_u'), preg_quote($delim), $dlen)), array('$1' . $delim, $delim), $str);
     }
 }
@@ -620,11 +630,11 @@
 
     return preg_replace([
-        '/&amp;(?=[\w\d#]{1,10};)/ui',
-        '/&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml|caron);/ui',
-        '/&(?:ndash|mdash|horbar);/ui',
-        '/&(?:nbsp);/ui',
-        '/&(?:bdquo|ldquo|ldquor|lsquo|lsquor|rdquo|rdquor|rsquo|rsquor|sbquo|lsaquo|rsaquo);/ui',
-        '/&(?:amp);/ui', // This replacement must come after matching all other entities.
-        '/[&;]+/u',
+        '/&amp;(?=[\w\d#]{1,10};)/i' . $app->getParam('preg_u'),
+        '/&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml|caron);/i' . $app->getParam('preg_u'),
+        '/&(?:ndash|mdash|horbar);/i' . $app->getParam('preg_u'),
+        '/&(?:nbsp);/i' . $app->getParam('preg_u'),
+        '/&(?:bdquo|ldquo|ldquor|lsquo|lsquor|rdquo|rdquor|rsquo|rsquor|sbquo|lsaquo|rsaquo);/i' . $app->getParam('preg_u'),
+        '/&(?:amp);/i' . $app->getParam('preg_u'), // This replacement must come after matching all other entities.
+        '/[&;]+/' . $app->getParam('preg_u'),
     ], [
         '&',
@@ -650,5 +660,7 @@
 function URLSlug($str)
 {
-    return strtolower(urlencode(preg_replace(['/[-\sââ.:;?!@#=+_\/\\\]+|(?:&nbsp;|&#160;|&ndash;|&#8211;|&mdash;|&#8212;|%c2%a0|%e2%80%93|%e2%80%9)+/u', '/-+/u', '/[^\w-]+/u', '/^-+|-+$/u'], ['-', '-', '', ''], simplifyAccents($str))));
+    $app =& App::getInstance();
+
+    return strtolower(urlencode(preg_replace(['/[-\sââ.:;?!@#=+_\/\\\]+|(?:&nbsp;|&#160;|&ndash;|&#8211;|&mdash;|&#8212;|%c2%a0|%e2%80%93|%e2%80%9)+/' . $app->getParam('preg_u'), '/-+/' . $app->getParam('preg_u'), '/[^\w-]+/' . $app->getParam('preg_u'), '/^-+|-+$/' . $app->getParam('preg_u')], ['-', '-', '', ''], simplifyAccents($str))));
 }
 
@@ -664,5 +676,5 @@
     $app =& App::getInstance();
 
-    $file_name = preg_replace(['/[^a-zA-Z0-9()@._=+-]+/u', '/^_+|_+$/u'], ['_', ''], simplifyAccents($file_name));
+    $file_name = preg_replace(['/[^a-zA-Z0-9()@._=+-]+/' . $app->getParam('preg_u'), '/^_+|_+$/' . $app->getParam('preg_u')], ['_', ''], simplifyAccents($file_name));
     return mb_substr($file_name, 0, 250);
 }
@@ -1182,5 +1194,7 @@
 function hash64($string, $length=18)
 {
-    return mb_substr(preg_replace('/[^\w]/u', '', base64_encode(hash('sha512', $string, true))), 0, $length);
+    $app =& App::getInstance();
+
+    return mb_substr(preg_replace('/[^\w]/' . $app->getParam('preg_u'), '', base64_encode(hash('sha512', $string, true))), 0, $length);
 }
 
@@ -1212,5 +1226,5 @@
     switch ($app->getParam('signing_method')) {
     case 'sha512+base64':
-        return $val . '-' . mb_substr(preg_replace('/[^\w]/u', '', base64_encode(hash('sha512', $val . $salt, true))), 0, $length);
+        return $val . '-' . mb_substr(preg_replace('/[^\w]/' . $app->getParam('preg_u'), '', base64_encode(hash('sha512', $val . $salt, true))), 0, $length);
 
     case 'md5':
@@ -1448,5 +1462,7 @@
 function stripQuery($url)
 {
-    return preg_replace('/[?#].*$/u', '', $url);
+    $app =& App::getInstance();
+
+    return preg_replace('/[?#].*$/' . $app->getParam('preg_u'), '', $url);
 }
 
@@ -1458,5 +1474,7 @@
 function absoluteMe()
 {
-    $safe_http_host = preg_replace('/[^a-z\d.:-]/u', '', getenv('HTTP_HOST'));
+    $app =& App::getInstance();
+
+    $safe_http_host = preg_replace('/[^a-z\d.:-]/' . $app->getParam('preg_u'), '', getenv('HTTP_HOST'));
     return sprintf('%s://%s%s', (getenv('HTTPS') ? 'https' : 'http'), $safe_http_host, getenv('REQUEST_URI'));
 }
Index: /trunk/lib/Validator.inc.php
===================================================================
--- /trunk/lib/Validator.inc.php	(revision 723)
+++ /trunk/lib/Validator.inc.php	(revision 724)
@@ -452,6 +452,7 @@
     {
         $app =& App::getInstance();
+
         // Get rid of any non-digits
-        $cc_num = preg_replace('/[^\d]/u', '', $val);
+        $cc_num = preg_replace('/[^\d]/' . $app->getParam('preg_u'), '', $val);
 
         // Perform card-specific checks, if applicable
