Index: include/functions.inc.php
===================================================================
--- include/functions.inc.php	(revision 2981)
+++ include/functions.inc.php	(working copy)
@@ -666,25 +666,19 @@
     $patterns[] = "@\\[pid=(\\d+)&amp;tid=(\\d+)](.*?)\\[/pid]@si";
     $replacements[] = '<a <!-- nobr -->href="viewthread.php?tid=$2&amp;goto=search&amp;pid=$1"><strong><!-- /nobr -->$3</strong> &nbsp;<img src="'.$imgdir.'/lastpost.gif" border="0" alt="" style="vertical-align: middle;" /></a>';
 
-    if ($allowimgcode != 'no' && $allowimgcode != 'off') {
-        if (false == stripos($message, 'javascript:')) {
-            $base_pattern = get_img_regexp();
-            $patterns[] = '/\[img\]' . $base_pattern . '\[\/img\]/i';
-            $replacements[] = '<img <!-- nobr -->src="\1://\2\3"<!-- /nobr --> border="0" alt="" />';
-            $patterns[] = '/\[img=([0-9]*?){1}x([0-9]*?)\]' . $base_pattern . '\[\/img\]/i';
-            $replacements[] = '<img width="\1" height="\2" <!-- nobr -->src="\3://\4\5"<!-- /nobr --> alt="" border="0" />';
-        }
-    }
-
-    $patterns[] = "#\\[email\\]([^\"'<>]+?)\\[/email\\]#i";
-    $replacements[] = '<a href="mailto:\1">\1</a>';
-    $patterns[] = "#\\[email=([^\"'<>\\[\\]]+)\\](.+?)\\[/email\\]#i";
-    $replacements[] = '<a href="mailto:\1">\2</a>';
-
     $message = preg_replace($patterns, $replacements, $message);
 
     $message = preg_replace_callback($regex['size'], 'bbcodeSizeTags', $message);
 
+    if ($allowimgcode != 'no' && $allowimgcode != 'off') {
+        $base_pattern = get_img_regexp();
+
+        $patterns = array();
+        $patterns[] = '/\[img\]' . $base_pattern . '\[\/img\]/i';
+        $patterns[] = '/\[img=([0-9]*?){1}x([0-9]*?)\]' . $base_pattern . '\[\/img\]/i';
+        $message = preg_replace_callback( $patterns, 'bbcode_imgs', $message );
+    }
+
     if ($allowurlcode) {
         /*
           This block positioned last so that bare URLs may appear adjacent to BBCodes without matching on square braces.
@@ -709,6 +703,11 @@
         $message = preg_replace_callback("#\[url=([^\"'<>\[\]]+)\](.*?)\[/url\]#i", 'bbcodeLongURLs', $message);
     }
 
+    $patterns = array();
+    $patterns[] = "#\\[email\\]([^\"'<>]+?)\\[/email\\]#i";
+    $patterns[] = "#\\[email=([^\"'<>\\[\\]]+)\\](.+?)\\[/email\\]#i";
+    $message = preg_replace_callback( $patterns, 'bbcode_emails', $message );
+
     return TRUE;
 }
 
@@ -843,7 +842,7 @@
     $colon = strpos($url[1], ':');
     if (FALSE !== $colon) {
         $scheme = substr($url[1], 0, $colon);
-	if (in_array($scheme, $scheme_whitelist)) {
+        if (in_array($scheme, $scheme_whitelist)) {
             $href = $url[1];
         } else {
             return $url[0];
@@ -858,18 +857,22 @@
     } else {
         $text = substr($url[1], 0, $url_max_display_len).'...';
     }
+
+    $href = bbcode_out( $href );
+
     return '<a <!-- nobr -->href="'.$href.'" onclick="window.open(this.href); return false;"><!-- /nobr -->'.$text.'</a>';
 }
 
 /**
- * Replaces createAbsFSizeFromRel() to eliminate the /e in size bbcode regex.
+ * Adds relative font size values to the theme's font size.
  *
- * @since 1.9.11 Alpha Three
+ * @since 1.9.11
  */
 function bbcodeSizeTags($matches) {
     global $fontsize;
     static $cachedFs;
 
+    // Cache the theme font size in an array.
     if (!is_array($cachedFs) || count($cachedFs) != 2) {
         preg_match('#([0-9]+)([a-z]+)?#i', $fontsize, $res);
         $cachedFs[0] = $res[1];
@@ -880,9 +883,10 @@
         }
     }
 
-    $o = ($matches[1]+$cachedFs[0]).$cachedFs[1];
+    $relative = (int) $matches[1];
+    $o = ( $relative + $cachedFs[0] ) . $cachedFs[1];
 
-    $html = "<span style=\"font-size: $o;\">";
+    $html = "<span style='font-size: $o;'>";
 
     return $html;
 }
@@ -2505,5 +2509,66 @@
 
     return altMail( $to, $subject, $message, $headers, $params );
 }
+
+/**
+ * Handles the [email] BBCode.
+ *
+ * @since 1.9.12.03, ported to 1.9.11.16
+ * @param array $matches Expects $matches[0] to be the raw BBCode, $matches[1] to be the URL only, and optionally $matches[2] to be the display text.
+ * @return string The HTML replacement for $matches[0].
+ */
+function bbcode_emails( $matches ) {
+    if ( isset( $matches[2] ) ) {
+        $text = $matches[2];
+    } else {
+        $text = $matches[1];
+    }
+
+    $address = bbcode_out( $matches[1] );
+
+    return "<a href='mailto:$address'>$text</a>";
+}
+
+/**
+ * Handles the [img] BBCode.
+ *
+ * @since 1.9.12.03, ported to 1.9.11.16
+ * @param array $matches Expects different elements depending on the pattern.
+ * @return string The HTML replacement for $matches[0].
+ */
+function bbcode_imgs( $matches ) {
+    if ( count( $matches ) < 5 ) {
+        $width = 0;
+        $height = 0;
+        $scheme = $matches[1];
+        $path = $matches[2];
+        if ( isset( $matches[3] ) ) {
+            $query = $matches[3];
+        } else {
+            $query = '';
+        }
+    } else {
+        $width = (int) $matches[1];
+        $height = (int) $matches[2];
+        $scheme = $matches[3];
+        $path = $matches[4];
+        if ( isset( $matches[5] ) ) {
+            $query = $matches[5];
+        } else {
+            $query = '';
+        }
+    }
+
+    if ( $width < 1 || $height < 1 ) {
+        $size = '';
+    } else {
+        $size = "width='$width' height='$height'";
+    }
+
+    $address = bbcode_out( "$scheme://$path$query" );
+
+    return "<img $size <!-- nobr -->src='$address'<!-- /nobr --> alt='' border='0' />";
+}
+
 return;
 ?>
Index: include/validate.inc.php
===================================================================
--- include/validate.inc.php	(revision 2981)
+++ include/validate.inc.php	(working copy)
@@ -471,4 +471,17 @@
 function isValidFilename($filename) {
     return preg_match("#^[\\w\\^\\-\\#\\] `~!@$&()_+=[{};',.]+$#", trim($filename));
 }
+
+/**
+ * Output filter for BBCodes
+ *
+ * @since 1.9.12.03, ported to 1.9.11.16
+ */
+function bbcode_out( $message ) {
+    $retval = $message;
+    $retval = htmlspecialchars_decode( $retval, ENT_QUOTES ); // Double encoding avoidance compatible with PHP 4.
+    $retval = htmlspecialchars( $retval, ENT_QUOTES );
+    $retval = str_replace( array( '[', ']' ), array( '&#91;', '&#93;' ), $retval );
+    return $retval;
+}
 ?>
