diff --git a/CHANGELOG b/CHANGELOG index b1afc572f..95e97079e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,7 @@ CHANGELOG Roundcube Webmail - Elastic: Fix folders list scrolling on touch devices (#6706) - Elastic: Fix non-working pretty selects in Chrome browser (#6705) - Managesieve: Fix bug where global includes were requested for vacation (#6716) +- Fix bug in HTML parser that could cause missing text fragments when there was no head/body tag (#6713) - Fix bug where HTML messages with a xml:namespace tag were not rendered (#6697) - Fix TinyMCE download location (#6694) - Fix so "Open in new window" consistently displays "external window" interface (#6659) diff --git a/program/lib/Roundcube/rcube_washtml.php b/program/lib/Roundcube/rcube_washtml.php index dfb57cac2..8cc85301d 100644 --- a/program/lib/Roundcube/rcube_washtml.php +++ b/program/lib/Roundcube/rcube_washtml.php @@ -562,7 +562,7 @@ class rcube_washtml if (!$this->is_xml && class_exists('Masterminds\HTML5')) { try { $html5 = new Masterminds\HTML5(); - $node = $html5->loadHTML($html); + $node = $html5->loadHTML($this->fix_html5($html)); } catch (Exception $e) { // ignore, fallback to DOMDocument @@ -778,6 +778,28 @@ class rcube_washtml } } + /** + * Cleanup and workarounds on input to Masterminds/HTML5 + */ + protected function fix_html5($html) + { + // HTML5 requires or (#6713) + // https://github.com/Masterminds/html5-php/issues/166 + if (!preg_match('/<(head|body)/i', $html)) { + $pos = stripos($html, '', $pos); + $html = substr_replace($html, '', $pos, 0); + } + } + + return $html; + } + /** * Explode css style value */ diff --git a/tests/Framework/Washtml.php b/tests/Framework/Washtml.php index 1dbb87a93..bbccd8d6d 100644 --- a/tests/Framework/Washtml.php +++ b/tests/Framework/Washtml.php @@ -444,4 +444,32 @@ class Framework_Washtml extends PHPUnit_Framework_TestCase $this->assertNotContains('<?xml:namespace"', $washed); $this->assertSame($washed, '

'); } + + /** + * Test missing main HTML hierarchy tags (#6713) + */ + function test_missing_tags() + { + $washer = new rcube_washtml(); + + $html = 'First line
Second line'; + $washed = $washer->wash($html); + + $this->assertContains('First line', $washed); + + $html = 'First line
Second line'; + $washed = $washer->wash($html); + + $this->assertContains('First line', $washed); + + $html = 'First line
Second line'; + $washed = $washer->wash($html); + + $this->assertContains('First line', $washed); + + $html = 'First line
Second line'; + $washed = $washer->wash($html); + + $this->assertContains('First line', $washed); + } }