Commit 16a44263 authored by catch's avatar catch
Browse files

Issue #3259255 by gordon, smustgrave, cilefen, quietone, catch, larowlan:...

Issue #3259255 by gordon, smustgrave, cilefen, quietone, catch, larowlan: Html::escapeCdataElement() not adding CDATA correctly
parent 36ef945b
Loading
Loading
Loading
Loading
+7 −8
Original line number Diff line number Diff line
@@ -350,17 +350,16 @@ public static function serialize(\DOMDocument $document) {
  public static function escapeCdataElement(\DOMNode $node, $comment_start = '//', $comment_end = '') {
    foreach ($node->childNodes as $child_node) {
      if ($child_node instanceof \DOMCdataSection) {
        $embed_prefix = "\n<!--{$comment_start}--><![CDATA[{$comment_start} ><!--{$comment_end}\n";
        $embed_suffix = "\n{$comment_start}--><!]]>{$comment_end}\n";
        $data = $child_node->data;
        if (!str_contains($child_node->data, 'CDATA')) {
          $embed_prefix = "\n{$comment_start}<![CDATA[{$comment_end}\n";
          $embed_suffix = "\n{$comment_start}]]>{$comment_end}\n";

        // Prevent invalid cdata escaping as this would throw a DOM error.
        // This is the same behavior as found in libxml2.
        // Related W3C standard: http://www.w3.org/TR/REC-xml/#dt-cdsection
        // Fix explanation: http://wikipedia.org/wiki/CDATA#Nesting
        $data = str_replace(']]>', ']]]]><![CDATA[>', $child_node->data);
          $data = $embed_prefix . $data . $embed_suffix;
        }

        $fragment = $node->ownerDocument->createDocumentFragment();
        $fragment->appendXML($embed_prefix . $data . $embed_suffix);
        $fragment->appendXML($data);
        $node->appendChild($fragment);
        $node->removeChild($child_node);
      }
+46 −33
Original line number Diff line number Diff line
@@ -1015,23 +1015,23 @@ public function testHtmlCorrectorFilter() {

    $f = Html::normalize('<script>alert("test")</script>');
    $this->assertEquals('<script>
<!--//--><![CDATA[// ><!--
//<![CDATA[
alert("test")
//--><!]]>
//]]>
</script>', $f, 'HTML corrector -- CDATA added to script element');

    $f = Html::normalize('<p><script>alert("test")</script></p>');
    $this->assertEquals('<p><script>
<!--//--><![CDATA[// ><!--
//<![CDATA[
alert("test")
//--><!]]>
//]]>
</script></p>', $f, 'HTML corrector -- CDATA added to a nested script element');

    $f = Html::normalize('<p><style> /* Styling */ body {color:red}</style></p>');
    $this->assertEquals('<p><style>
<!--/*--><![CDATA[/* ><!--*/
/*<![CDATA[*/
 /* Styling */ body {color:red}
/*--><!]]>*/
/*]]>*/
</style></p>', $f, 'HTML corrector -- CDATA added to a style element.');

    $filtered_data = Html::normalize('<p><style>
@@ -1041,50 +1041,38 @@ public function testHtmlCorrectorFilter() {
/*]]>*/
</style></p>');
    $this->assertEquals('<p><style>
<!--/*--><![CDATA[/* ><!--*/

/*<![CDATA[*/
/* Styling */
body {color:red}
/*]]]]><![CDATA[>*/

/*--><!]]>*/
/*]]>*/
</style></p>', $filtered_data,
      new FormattableMarkup('HTML corrector -- Existing cdata section @pattern_name properly escaped', ['@pattern_name' => '/*<![CDATA[*/'])
    );

    $filtered_data = Html::normalize('<p><style>
  <!--/*--><![CDATA[/* ><!--*/
/*<![CDATA[*/
  /* Styling */
  body {color:red}
  /*--><!]]>*/
/*]]>*/
</style></p>');
    $this->assertEquals('<p><style>
<!--/*--><![CDATA[/* ><!--*/

  <!--/*--><![CDATA[/* ><!--*/
/*<![CDATA[*/
  /* Styling */
  body {color:red}
  /*--><!]]]]><![CDATA[>*/

/*--><!]]>*/
/*]]>*/
</style></p>', $filtered_data,
      new FormattableMarkup('HTML corrector -- Existing cdata section @pattern_name properly escaped', ['@pattern_name' => '<!--/*--><![CDATA[/* ><!--*/'])
    );

    $filtered_data = Html::normalize('<p><script>
<!--//--><![CDATA[// ><!--
//<![CDATA[
  alert("test");
//--><!]]>
//]]>
</script></p>');
    $this->assertEquals('<p><script>
<!--//--><![CDATA[// ><!--

<!--//--><![CDATA[// ><!--
//<![CDATA[
  alert("test");
//--><!]]]]><![CDATA[>

//--><!]]>
//]]>
</script></p>', $filtered_data,
      new FormattableMarkup('HTML corrector -- Existing cdata section @pattern_name properly escaped', ['@pattern_name' => '<!--//--><![CDATA[// ><!--'])
    );
@@ -1095,17 +1083,42 @@ public function testHtmlCorrectorFilter() {
//]]>
</script></p>');
    $this->assertEquals('<p><script>
<!--//--><![CDATA[// ><!--

// <![CDATA[
  alert("test");
// ]]]]><![CDATA[>

//--><!]]>
//]]>
</script></p>', $filtered_data,
      new FormattableMarkup('HTML corrector -- Existing cdata section @pattern_name properly escaped', ['@pattern_name' => '// <![CDATA['])
    );

    $filtered_data = Html::normalize('<p><script>
// <![CDATA[![CDATA[![CDATA[
  alert("test");
//]]]]]]>
</script></p>');
    $this->assertEquals('<p><script>
// <![CDATA[![CDATA[![CDATA[
  alert("test");
//]]]]]]>
</script></p>', $filtered_data,
      new FormattableMarkup('HTML corrector -- Existing cdata section @pattern_name properly escaped', ['@pattern_name' => '// <![CDATA[![CDATA[![CDATA['])
    );

    // Test calling Html::normalize() twice.
    $filtered_data = Html::normalize('<p><script>
// <![CDATA[![CDATA[![CDATA[
  alert("test");
//]]]]]]>
</script></p>');
    $filtered_data = Html::normalize($filtered_data);

    $this->assertEquals('<p><script>
// <![CDATA[![CDATA[![CDATA[
  alert("test");
//]]]]]]>
</script></p>', $filtered_data,
      new FormattableMarkup('HTML corrector -- Existing cdata section @pattern_name properly escaped', ['@pattern_name' => '// <![CDATA[![CDATA[![CDATA['])
    );

  }

  /**