CVE-2016-5733: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Multiple cross-site scripting (XSS) vulnerabilities in phpMyAdmin 4.0.x before 4.0.10.16, 4.4.x before 4.4.15.7, and 4.6.x before 4.6.3 allow remote attackers to inject arbitrary web script or HTML via vectors involving (1) a crafted table name that is mishandled during privilege checking in table_row.phtml, (2) a crafted mysqld log_bin directive that is mishandled in log_selector.phtml, (3) the Transformation implementation, (4) AJAX error handling in js/ajax.js, (5) the Designer implementation, (6) the charts implementation in js/tbl_chart.js, or (7) the zoom-search implementation in rows_zoom.phtml.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2016-07-03T01:59Z
Repository: https://github.com/phpmyadmin/phpmyadmin
Language: PHP
Files changed: libraries/plugins/transformations/abs/DateFormatTransformationsPlugin.php, libraries/plugins/transformations/abs/DownloadTransformationsPlugin.php, libraries/plugins/transformations/abs/ImageLinkTransformationsPlugin.php, libraries/plugins/transformations/abs/InlineTransformationsPlugin.php, libraries/plugins/transformations/abs/LongToIPv4TransformationsPlugin.php, libraries/plugins/transformations/abs/PreApPendTransformationsPlugin.php, libraries/plugins/transformations/abs/SubstringTransformationsPlugin.php, libraries/plugins/transformations/abs/TextImageLinkTransformationsPlugin.php, libraries/plugins/transformations/abs/TextLinkTransformationsPlugin.php, libraries/transformations.lib.php, test/classes/plugin/transformations/TransformationPluginsTest.php, test/libraries/PMA_transformation_test.php
Commit date: 2016-06-17 16:18:13 +0200
Commit message: Simplify and cleanup transformation plugins

Remove PMA_transformation_global_html_replace which makes the code only
more confusing.

Also add escaping to browse transformations.

Signed-off-by: Michal Čihař <michal@cihar.com>

Diff: diff --git a/libraries/plugins/transformations/abs/DateFormatTransformationsPlugin.php b/libraries/plugins/transformations/abs/DateFormatTransformationsPlugin.php
index 238004284c7cd..7a7e0cee94b95 100644
--- a/libraries/plugins/transformations/abs/DateFormatTransformationsPlugin.php
+++ b/libraries/plugins/transformations/abs/DateFormatTransformationsPlugin.php
@@ -9,10 +9,12 @@
 namespace PMA\libraries\plugins\transformations\abs;
 
 use PMA;
 use PMA\libraries\plugins\TransformationsPlugin;
 
+require_once 'libraries/js_escape.lib.php';
+
 /**
  * Provides common methods for all of the date format transformations plugins.
  *
  * @package PhpMyAdmin
  */
@@ -143,15 +145,15 @@ public function applyTransformation($buffer, $options = array(), $meta = '')
             } elseif ($options[2] == 'utc') {
                 $text = gmdate($options[1], $timestamp);
             } else {
                 $text = 'INVALID DATE TYPE';
             }
-            $buffer = '<dfn onclick="alert(\'' . $source . '\');" title="'
-                . $source . '">' . $text . '</dfn>';
+            return '<dfn onclick="alert(\'' . PMA_jsFormat($source, false) . '\');" title="'
+                . htmlspecialchars($source) . '">' . htmlspecialchars($text) . '</dfn>';
+        } else {
+            return htmlspecialchars($buffer);
         }
-
-        return $buffer;
     }
 
     /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
 
     /**
diff --git a/libraries/plugins/transformations/abs/DownloadTransformationsPlugin.php b/libraries/plugins/transformations/abs/DownloadTransformationsPlugin.php
index ee556cdeb4018..51525749648be 100644
--- a/libraries/plugins/transformations/abs/DownloadTransformationsPlugin.php
+++ b/libraries/plugins/transformations/abs/DownloadTransformationsPlugin.php
@@ -67,11 +67,11 @@ public function applyTransformation($buffer, $options = array(), $meta = '')
 
         return sprintf(
             '<a href="transformation_wrapper.php%s&amp;ct=application'
             . '/octet-stream&amp;cn=%s" title="%s" class="disableAjax">%s</a>',
             $options['wrapper_link'],
-            urlencode($cn),
+            htmlspecialchars(urlencode($cn)),
             htmlspecialchars($cn),
             htmlspecialchars($cn)
         );
     }
 
diff --git a/libraries/plugins/transformations/abs/ImageLinkTransformationsPlugin.php b/libraries/plugins/transformations/abs/ImageLinkTransformationsPlugin.php
index 1592144fd68e5..5246fb2e5ffa0 100644
--- a/libraries/plugins/transformations/abs/ImageLinkTransformationsPlugin.php
+++ b/libraries/plugins/transformations/abs/ImageLinkTransformationsPlugin.php
@@ -47,20 +47,12 @@ public static function getInfo()
      */
     public function applyTransformation($buffer, $options = array(), $meta = '')
     {
         // must disable the page loader, see
         // https://wiki.phpmyadmin.net/pma/Page_loader#Bypassing_the_page_loader
-        $transform_options = array(
-            'string' => '<a class="disableAjax"'
-                . ' target="_new" href="transformation_wrapper.php'
-                . $options['wrapper_link'] . '" alt="[__BUFFER__]">[BLOB]</a>',
-        );
-
-        return PMA_Transformation_globalHtmlReplace(
-            $buffer,
-            $transform_options
-        );
+        return '<a class="disableAjax" target="_new" href="transformation_wrapper.php'
+            . $options['wrapper_link'] . '" alt="[' . htmlspecialchars($buffer) . ']">[BLOB]</a>';
     }
 
     /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
 
     /**
diff --git a/libraries/plugins/transformations/abs/InlineTransformationsPlugin.php b/libraries/plugins/transformations/abs/InlineTransformationsPlugin.php
index 814c8dae474f0..9d2a12f59fb64 100644
--- a/libraries/plugins/transformations/abs/InlineTransformationsPlugin.php
+++ b/libraries/plugins/transformations/abs/InlineTransformationsPlugin.php
@@ -47,34 +47,26 @@ public static function getInfo()
      * @return string
      */
     public function applyTransformation($buffer, $options = array(), $meta = '')
     {
         if (PMA_IS_GD2) {
-            $transform_options = array(
-                'string' => '<a href="transformation_wrapper.php'
-                    . $options['wrapper_link']
-                    . '" target="_blank"><img src="transformation_wrapper.php'
-                    . $options['wrapper_link'] . '&amp;resize=jpeg&amp;newWidth='
-                    . (isset($options[0]) ? $options[0] : '100') . '&amp;newHeight='
-                    . (isset($options[1]) ? $options[1] : 100)
-                    . '" alt="[__BUFFER__]" border="0" /></a>',
-            );
+            return '<a href="transformation_wrapper.php'
+                . $options['wrapper_link']
+                . '" target="_blank"><img src="transformation_wrapper.php'
+                . $options['wrapper_link'] . '&amp;resize=jpeg&amp;newWidth='
+                . (isset($options[0]) ? $options[0] : '100') . '&amp;newHeight='
+                . (isset($options[1]) ? $options[1] : 100)
+                . '" alt="[' . htmlspecialchars($buffer) . ']" border="0" /></a>';
         } else {
-            $transform_options = array(
-                'string' => '<img src="transformation_wrapper.php'
-                    . $options['wrapper_link']
-                    . '" alt="[__BUFFER__]" width="320" height="240" />',
-            );
+            return '<img src="transformation_wrapper.php'
+                . $options['wrapper_link']
+                . '" alt="[' . htmlspecialchars($buffer) . ']" width="320" height="240" />';
         }
-
-        return PMA_Transformation_globalHtmlReplace(
-            $buffer,
-            $transform_options
-        );
     }
 
 
+
     /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
 
     /**
      * Gets the transformation name of the specific plugin
      *
diff --git a/libraries/plugins/transformations/abs/LongToIPv4TransformationsPlugin.php b/libraries/plugins/transformations/abs/LongToIPv4TransformationsPlugin.php
index 8ca5817a37cef..234a4925b3824 100644
--- a/libraries/plugins/transformations/abs/LongToIPv4TransformationsPlugin.php
+++ b/libraries/plugins/transformations/abs/LongToIPv4TransformationsPlugin.php
@@ -40,11 +40,11 @@ public static function getInfo()
      * @return string
      */
     public function applyTransformation($buffer, $options = array(), $meta = '')
     {
         if ($buffer < 0 || $buffer > 4294967295) {
-            return $buffer;
+            return htmlspecialchars($buffer);
         }
 
         return long2ip($buffer);
     }
 
diff --git a/libraries/plugins/transformations/abs/PreApPendTransformationsPlugin.php b/libraries/plugins/transformations/abs/PreApPendTransformationsPlugin.php
index 9d85a3d72d09d..7247ce13b9ba8 100644
--- a/libraries/plugins/transformations/abs/PreApPendTransformationsPlugin.php
+++ b/libraries/plugins/transformations/abs/PreApPendTransformationsPlugin.php
@@ -44,14 +44,12 @@ public static function getInfo()
     public function applyTransformation($buffer, $options = array(), $meta = '')
     {
         $options = $this->getOptions($options, array('', ''));
 
         //just prepend and/or append the options to the original text
-        $newtext = htmlspecialchars($options[0]) . $buffer
+        return htmlspecialchars($options[0]) . htmlspecialchars($buffer)
             . htmlspecialchars($options[1]);
-
-        return $newtext;
     }
 
     /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
 
     /**
diff --git a/libraries/plugins/transformations/abs/SubstringTransformationsPlugin.php b/libraries/plugins/transformations/abs/SubstringTransformationsPlugin.php
index fcf48b00e0cf5..57979d1cf2f14 100644
--- a/libraries/plugins/transformations/abs/SubstringTransformationsPlugin.php
+++ b/libraries/plugins/transformations/abs/SubstringTransformationsPlugin.php
@@ -69,11 +69,11 @@ public function applyTransformation($buffer, $options = array(), $meta = '')
             if (($length + $options[0]) != $baselength) {
                 $newtext .= $options[2];
             }
         }
 
-        return $newtext;
+        return htmlspecialchars($newtext);
     }
 
 
     /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
 
diff --git a/libraries/plugins/transformations/abs/TextImageLinkTransformationsPlugin.php b/libraries/plugins/transformations/abs/TextImageLinkTransformationsPlugin.php
index 76009d32b81c9..ef534f296b291 100644
--- a/libraries/plugins/transformations/abs/TextImageLinkTransformationsPlugin.php
+++ b/libraries/plugins/transformations/abs/TextImageLinkTransformationsPlugin.php
@@ -12,13 +12,10 @@
 
 if (!defined('PHPMYADMIN')) {
     exit;
 }
 
-/* For PMA_Transformation_globalHtmlReplace */
-require_once 'libraries/transformations.lib.php';
-
 /**
  * Provides common methods for all of the image link transformations plugins.
  *
  * @package PhpMyAdmin
  */
@@ -47,25 +44,16 @@ public static function getInfo()
      *
      * @return string
      */
     public function applyTransformation($buffer, $options = array(), $meta = '')
     {
-        $transform_options = array(
-            'string' => '<a href="' . (isset($options[0]) ? $options[0] : '')
-                . $buffer . '" target="_blank"><img src="'
-                . (isset($options[0]) ? $options[0] : '') . $buffer
-                . '" border="0" width="' . (isset($options[1]) ? $options[1] : 100)
-                . '" height="' . (isset($options[2]) ? $options[2] : 50) . '" />'
-                . $buffer . '</a>',
-        );
-
-        $buffer = PMA_Transformation_globalHtmlReplace(
-            $buffer,
-            $transform_options
-        );
-
-        return $buffer;
+        return '<a href="' . htmlspecialchars(isset($options[0]) ? $options[0] : '')
+            . htmlspecialchars($buffer) . '" target="_blank"><img src="'
+            . htmlspecialchars(isset($options[0]) ? $options[0] : '') . htmlspecialchars($buffer)
+            . '" border="0" width="' . (isset($options[1]) ? $options[1] : 100)
+            . '" height="' . (isset($options[2]) ? $options[2] : 50) . '" />'
+            . htmlspecialchars($buffer) . '</a>';
     }
 
 
     /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
 
diff --git a/libraries/plugins/transformations/abs/TextLinkTransformationsPlugin.php b/libraries/plugins/transformations/abs/TextLinkTransformationsPlugin.php
index ec2da90ec2777..000b9d056bed9 100644
--- a/libraries/plugins/transformations/abs/TextLinkTransformationsPlugin.php
+++ b/libraries/plugins/transformations/abs/TextLinkTransformationsPlugin.php
@@ -12,13 +12,10 @@
 
 if (!defined('PHPMYADMIN')) {
     exit;
 }
 
-/* For PMA_Transformation_globalHtmlReplace */
-require_once 'libraries/transformations.lib.php';
-
 /**
  * Provides common methods for all of the link transformations plugins.
  *
  * @package PhpMyAdmin
  */
@@ -47,29 +44,23 @@ public static function getInfo()
      *
      * @return string
      */
     public function applyTransformation($buffer, $options = array(), $meta = '')
     {
-
         $append_part = (isset($options[2]) && $options[2]) ? '' : $buffer;
 
-        $transform_options = array(
-            'string' => '<a href="'
-                . (isset($options[0]) ? $options[0] : '') . $append_part
-                . '" title="'
-                . htmlspecialchars(isset($options[1]) ? $options[1] : '')
-                . '" target="_new">'
-                . htmlspecialchars(isset($options[1]) ? $options[1] : $buffer)
-                . '</a>',
-        );
-
-        return PMA_Transformation_globalHtmlReplace(
-            $buffer,
-            $transform_options
-        );
+        return '<a href="'
+            . htmlspecialchars(isset($options[0]) ? $options[0] : '')
+            . htmlspecialchars($append_part)
+            . '" title="'
+            . htmlspecialchars(isset($options[1]) ? $options[1] : '')
+            . '" target="_new">'
+            . htmlspecialchars(isset($options[1]) ? $options[1] : $buffer)
+            . '</a>';
     }
 
+
     /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
 
     /**
      * Gets the transformation name of the specific plugin
      *
diff --git a/libraries/transformations.lib.php b/libraries/transformations.lib.php
index 5e1562e20e1d7..2526024bcef81 100644
--- a/libraries/transformations.lib.php
+++ b/libraries/transformations.lib.php
@@ -398,48 +398,10 @@ function PMA_setMIME($db, $table, $key, $mimetype, $transformation,
 
 /**
  * GLOBAL Plugin functions
  */
 
-
-/**
- * Replaces "[__BUFFER__]" occurrences found in $options['string'] with the text
- * in $buffer, after performing a regular expression search and replace on
- * $buffer using $options['regex'] and $options['regex_replace'].
- *
- * @param string $buffer  text that will be replaced in $options['string'],
- *                        after being formatted
- * @param array  $options the options required to format $buffer
- *     = array (
- *         'string'        => 'string', // text containing "[__BUFFER__]"
- *         'regex'         => 'mixed',  // the pattern to search for
- *         'regex_replace' => 'mixed',  // string or array of strings to replace
- *                                      // with
- *     );
- *
- * @return string containing the text with all the replacements
- */
-function PMA_Transformation_globalHtmlReplace($buffer, $options = array())
-{
-    if (! isset($options['string'])) {
-        $options['string'] = '';
-    }
-
-    if (isset($options['regex']) && isset($options['regex_replace'])) {
-        $buffer = preg_replace(
-            '@' . str_replace('@', '\@', $options['regex']) . '@si',
-            $options['regex_replace'],
-            $buffer
-        );
-    }
-
-    // Replace occurrences of [__BUFFER__] with actual text
-    $return = str_replace("[__BUFFER__]", $buffer, $options['string']);
-    return $return;
-}
-
-
 /**
  * Delete related transformation details
  * after deleting database. table or column
  *
  * @param string $db     Database name
diff --git a/test/classes/plugin/transformations/TransformationPluginsTest.php b/test/classes/plugin/transformations/TransformationPluginsTest.php
index e09bba8e296fb..872adb352c2b0 100644
--- a/test/classes/plugin/transformations/TransformationPluginsTest.php
+++ b/test/classes/plugin/transformations/TransformationPluginsTest.php
@@ -778,21 +778,21 @@ public function transformationDataProvider()
                     array("./image/", "200", "wrapper_link"=>"PMA_wrapper_link")
                 ),
                 '<a href="transformation_wrapper.phpPMA_wrapper_link" '
                 . 'target="_blank"><img src="transformation_wrapper.php'
                 . 'PMA_wrapper_link&amp;resize=jpeg&amp;newWidth=./image/&amp;'
-                . 'newHeight=200" alt="PMA_JPEG_Inline" border="0" /></a>'
+                . 'newHeight=200" alt="[PMA_JPEG_Inline]" border="0" /></a>'
             ),
             array(
                 new Image_JPEG_Link(),
                 array(
                     'PMA_IMAGE_LINK',
                     array("./image/", "200", "wrapper_link"=>"PMA_wrapper_link")
                 ),
                 '<a class="disableAjax" target="_new"'
                 . ' href="transformation_wrapper.phpPMA_wrapper_link"'
-                . ' alt="PMA_IMAGE_LINK">[BLOB]</a>'
+                . ' alt="[PMA_IMAGE_LINK]">[BLOB]</a>'
             ),
             array(
                 new Image_PNG_Inline(),
                 array(
                     'PMA_PNG_Inline',
@@ -800,11 +800,11 @@ public function transformationDataProvider()
                 ),
                 '<a href="transformation_wrapper.phpPMA_wrapper_link"'
                 . ' target="_blank"><img src="transformation_wrapper.php'
                 . 'PMA_wrapper_link&amp;'
                 . 'resize=jpeg&amp;newWidth=./image/&amp;newHeight=200" '
-                . 'alt="PMA_PNG_Inline" border="0" /></a>'
+                . 'alt="[PMA_PNG_Inline]" border="0" /></a>'
             ),
             array(
                 new Text_Plain_Dateformat(),
                 array(
                     12345,
diff --git a/test/libraries/PMA_transformation_test.php b/test/libraries/PMA_transformation_test.php
index 1319d19a2c969..f573c5e476a64 100644
--- a/test/libraries/PMA_transformation_test.php
+++ b/test/libraries/PMA_transformation_test.php
@@ -206,38 +206,10 @@ public function testGetMime()
             ),
             PMA_getMIME('pma_test', 'table1')
         );
     }
 
-    /**
-     * Test for PMA_Transformation_globalHtmlReplace
-     *
-     * @return void
-     */
-    public function testTransformationGlobalHtmlReplace()
-    {
-        // Case 1
-        $actual = PMA_Transformation_globalHtmlReplace('', array());
-        $this->assertEquals(
-            '',
-            $actual
-        );
-
-        // Case 2
-        $buffer = 'foobar';
-        $options = array(
-            'regex' => 'foo',
-            'regex_replace' => 'bar',
-            'string' => 'x[__BUFFER__]x'
-        );
-        $actual = PMA_Transformation_globalHtmlReplace($buffer, $options);
-        $this->assertEquals(
-            'xbarbarx',
-            $actual
-        );
-    }
-
     /**
      * Test for PMA_clearTransformations
      *
      * @return void
      */

Vulnerable code:             $buffer = '<dfn onclick="alert(\'' . $source . '\');" title="'
                . $source . '">' . $text . '</dfn>';

        return $buffer;
            urlencode($cn),
        $transform_options = array(
            'string' => '<a class="disableAjax"'
                . ' target="_new" href="transformation_wrapper.php'
                . $options['wrapper_link'] . '" alt="[__BUFFER__]">[BLOB]</a>',
        );

        return PMA_Transformation_globalHtmlReplace(
            $buffer,
            $transform_options
        );
            $transform_options = array(
                'string' => '<a href="transformation_wrapper.php'
                    . $options['wrapper_link']
                    . '" target="_blank"><img src="transformation_wrapper.php'
                    . $options['wrapper_link'] . '&amp;resize=jpeg&amp;newWidth='
                    . (isset($options[0]) ? $options[0] : '100') . '&amp;newHeight='
                    . (isset($options[1]) ? $options[1] : 100)
                    . '" alt="[__BUFFER__]" border="0" /></a>',
            );
            $transform_options = array(
                'string' => '<img src="transformation_wrapper.php'
                    . $options['wrapper_link']
                    . '" alt="[__BUFFER__]" width="320" height="240" />',
            );

        return PMA_Transformation_globalHtmlReplace(
            $buffer,
            $transform_options
        );
            return $buffer;
        $newtext = htmlspecialchars($options[0]) . $buffer

        return $newtext;
        return $newtext;
/* For PMA_Transformation_globalHtmlReplace */
require_once 'libraries/transformations.lib.php';

        $transform_options = array(
            'string' => '<a href="' . (isset($options[0]) ? $options[0] : '')
                . $buffer . '" target="_blank"><img src="'
                . (isset($options[0]) ? $options[0] : '') . $buffer
                . '" border="0" width="' . (isset($options[1]) ? $options[1] : 100)
                . '" height="' . (isset($options[2]) ? $options[2] : 50) . '" />'
                . $buffer . '</a>',
        );

        $buffer = PMA_Transformation_globalHtmlReplace(
            $buffer,
            $transform_options
        );

        return $buffer;
/* For PMA_Transformation_globalHtmlReplace */
require_once 'libraries/transformations.lib.php';


        $transform_options = array(
            'string' => '<a href="'
                . (isset($options[0]) ? $options[0] : '') . $append_part
                . '" title="'
                . htmlspecialchars(isset($options[1]) ? $options[1] : '')
                . '" target="_new">'
                . htmlspecialchars(isset($options[1]) ? $options[1] : $buffer)
                . '</a>',
        );

        return PMA_Transformation_globalHtmlReplace(
            $buffer,
            $transform_options
        );

/**
 * Replaces "[__BUFFER__]" occurrences found in $options['string'] with the text
 * in $buffer, after performing a regular expression search and replace on
 * $buffer using $options['regex'] and $options['regex_replace'].
 *
 * @param string $buffer  text that will be replaced in $options['string'],
 *                        after being formatted
 * @param array  $options the options required to format $buffer
 *     = array (
 *         'string'        => 'string', // text containing "[__BUFFER__]"
 *         'regex'         => 'mixed',  // the pattern to search for
 *         'regex_replace' => 'mixed',  // string or array of strings to replace
 *                                      // with
 *     );
 *
 * @return string containing the text with all the replacements
 */
function PMA_Transformation_globalHtmlReplace($buffer, $options = array())
{
    if (! isset($options['string'])) {
        $options['string'] = '';
    }

    if (isset($options['regex']) && isset($options['regex_replace'])) {
        $buffer = preg_replace(
            '@' . str_replace('@', '\@', $options['regex']) . '@si',
            $options['regex_replace'],
            $buffer
        );
    }

    // Replace occurrences of [__BUFFER__] with actual text
    $return = str_replace("[__BUFFER__]", $buffer, $options['string']);
    return $return;
}


                . 'newHeight=200" alt="PMA_JPEG_Inline" border="0" /></a>'
                . ' alt="PMA_IMAGE_LINK">[BLOB]</a>'
                . 'alt="PMA_PNG_Inline" border="0" /></a>'
    /**
     * Test for PMA_Transformation_globalHtmlReplace
     *
     * @return void
     */
    public function testTransformationGlobalHtmlReplace()
    {
        // Case 1
        $actual = PMA_Transformation_globalHtmlReplace('', array());
        $this->assertEquals(
            '',
            $actual
        );

        // Case 2
        $buffer = 'foobar';
        $options = array(
            'regex' => 'foo',
            'regex_replace' => 'bar',
            'string' => 'x[__BUFFER__]x'
        );
        $actual = PMA_Transformation_globalHtmlReplace($buffer, $options);
        $this->assertEquals(
            'xbarbarx',
            $actual
        );
    }

Fixed code: require_once 'libraries/js_escape.lib.php';

            return '<dfn onclick="alert(\'' . PMA_jsFormat($source, false) . '\');" title="'
                . htmlspecialchars($source) . '">' . htmlspecialchars($text) . '</dfn>';
        } else {
            return htmlspecialchars($buffer);
            htmlspecialchars(urlencode($cn)),
        return '<a class="disableAjax" target="_new" href="transformation_wrapper.php'
            . $options['wrapper_link'] . '" alt="[' . htmlspecialchars($buffer) . ']">[BLOB]</a>';
            return '<a href="transformation_wrapper.php'
                . $options['wrapper_link']
                . '" target="_blank"><img src="transformation_wrapper.php'
                . $options['wrapper_link'] . '&amp;resize=jpeg&amp;newWidth='
                . (isset($options[0]) ? $options[0] : '100') . '&amp;newHeight='
                . (isset($options[1]) ? $options[1] : 100)
                . '" alt="[' . htmlspecialchars($buffer) . ']" border="0" /></a>';
            return '<img src="transformation_wrapper.php'
                . $options['wrapper_link']
                . '" alt="[' . htmlspecialchars($buffer) . ']" width="320" height="240" />';

            return htmlspecialchars($buffer);
        return htmlspecialchars($options[0]) . htmlspecialchars($buffer)
        return htmlspecialchars($newtext);
        return '<a href="' . htmlspecialchars(isset($options[0]) ? $options[0] : '')
            . htmlspecialchars($buffer) . '" target="_blank"><img src="'
            . htmlspecialchars(isset($options[0]) ? $options[0] : '') . htmlspecialchars($buffer)
            . '" border="0" width="' . (isset($options[1]) ? $options[1] : 100)
            . '" height="' . (isset($options[2]) ? $options[2] : 50) . '" />'
            . htmlspecialchars($buffer) . '</a>';
        return '<a href="'
            . htmlspecialchars(isset($options[0]) ? $options[0] : '')
            . htmlspecialchars($append_part)
            . '" title="'
            . htmlspecialchars(isset($options[1]) ? $options[1] : '')
            . '" target="_new">'
            . htmlspecialchars(isset($options[1]) ? $options[1] : $buffer)
            . '</a>';

                . 'newHeight=200" alt="[PMA_JPEG_Inline]" border="0" /></a>'
                . ' alt="[PMA_IMAGE_LINK]">[BLOB]</a>'
                . 'alt="[PMA_PNG_Inline]" border="0" /></a>'