Fixes #3393 - HTML structure that is not parseable by jQuery causes JavaScript error that breaks Ticket Zoom view.

This commit is contained in:
Mantas Masalskis 2021-02-11 08:51:52 +01:00 committed by Thorsten Eckel
parent b706c86fde
commit 215801ef95
2 changed files with 37 additions and 2 deletions

View file

@ -771,7 +771,7 @@ class App.Utils
if @isMicrosoftOffice message if @isMicrosoftOffice message
return @signatureIdentifyByPlaintext message return @signatureIdentifyByPlaintext message
message_element = $($.parseHTML(message)) message_element = $(App.Utils.safeParseHtml(message))
if message_element.length == 1 && $(message_element[0])?.children()?.length if message_element.length == 1 && $(message_element[0])?.children()?.length
message_element[0].innerHTML = @signatureIdentifyByHtmlHelper(message_element[0].innerHTML) message_element[0].innerHTML = @signatureIdentifyByHtmlHelper(message_element[0].innerHTML)
return message_element[0].outerHTML return message_element[0].outerHTML
@ -792,7 +792,10 @@ class App.Utils
return true if tag is 'DIV' && (el.data('signature') || el.prop('class') is 'yahoo_quoted') return true if tag is 'DIV' && (el.data('signature') || el.prop('class') is 'yahoo_quoted')
_.some el.children(), (el) -> isQuoteOrSignature el _.some el.children(), (el) -> isQuoteOrSignature el
$('<div/>').html(message).contents().each (index, node) -> try content = $('<div/>').html(message)
catch e then content = $('<div/>').html('<div>' + message + '</div>')
content.contents().each (index, node) ->
text = $(node).text() text = $(node).text()
if node.nodeType == Node.TEXT_NODE if node.nodeType == Node.TEXT_NODE
# convert text back to HTML as it was before # convert text back to HTML as it was before
@ -1457,3 +1460,10 @@ class App.Utils
htmlString = App.Utils.text2html(text) htmlString = App.Utils.text2html(text)
htmlString htmlString
# Parses HTML text to DOM tree
# jQuery's parseHTML sometimes fail when element does not have a single root element
# in that case, fall back to fake root element and try again
@safeParseHtml: (input) ->
try $.parseHTML(input)
catch e then $.parseHTML('<div>' + input + '</div>')[0].childNodes

View file

@ -1051,6 +1051,14 @@ test("identify signature by HTML", function() {
var result = App.Utils.signatureIdentifyByHtml(message) var result = App.Utils.signatureIdentifyByHtml(message)
equal(result, should) equal(result, should)
// test if, according to jQuery, invalid HTML does not cause a a crash
// https://github.com/zammad/zammad/issues/3393
message = "<td></td><table></table><div>test 123 </div>"
should = message
result = App.Utils.signatureIdentifyByHtml(message)
equal(result, should)
// simple case 1 // simple case 1
message = '<div>actual content</div><blockquote>quoted content</blockquote>' message = '<div>actual content</div><blockquote>quoted content</blockquote>'
should = '<div>actual content</div><span class="js-signatureMarker"></span><blockquote>quoted content</blockquote>' should = '<div>actual content</div><span class="js-signatureMarker"></span><blockquote>quoted content</blockquote>'
@ -3386,3 +3394,20 @@ test('App.Utils.signatureIdentifyByHtmlHelper()', function() {
equal(result, "&lt;script&gt;alert('fish2');&lt;/script&gt;<span class=\"js-signatureMarker\"></span><blockquote></blockquote>", 'signatureIdentifyByHtmlHelper does not reactivate alert') equal(result, "&lt;script&gt;alert('fish2');&lt;/script&gt;<span class=\"js-signatureMarker\"></span><blockquote></blockquote>", 'signatureIdentifyByHtmlHelper does not reactivate alert')
}); });
test("#safeParseHtml", function() {
var unwrap = input => $('<div>').html(input)[0].innerHTML
var html = "<div>test 123 </div>"
var result = App.Utils.safeParseHtml(html)
var should = html
equal(unwrap(result), html)
// test if, according to jQuery, invalid HTML does not cause a a crash
// https://github.com/zammad/zammad/issues/3393
html = "<td></td><table></table><div>test 123 </div>"
should = "<table></table><div>test 123 </div>"
result = App.Utils.safeParseHtml(html)
equal(unwrap(result), should)
})