From 215801ef954c3d9e0c60814f1131711a3d1a7d2a Mon Sep 17 00:00:00 2001 From: Mantas Masalskis Date: Thu, 11 Feb 2021 08:51:52 +0100 Subject: [PATCH] Fixes #3393 - HTML structure that is not parseable by jQuery causes JavaScript error that breaks Ticket Zoom view. --- .../javascripts/app/lib/app_post/utils.coffee | 14 +++++++++-- public/assets/tests/html_utils.js | 25 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/app/lib/app_post/utils.coffee b/app/assets/javascripts/app/lib/app_post/utils.coffee index 7430b26be..dad482357 100644 --- a/app/assets/javascripts/app/lib/app_post/utils.coffee +++ b/app/assets/javascripts/app/lib/app_post/utils.coffee @@ -771,7 +771,7 @@ class App.Utils if @isMicrosoftOffice message return @signatureIdentifyByPlaintext message - message_element = $($.parseHTML(message)) + message_element = $(App.Utils.safeParseHtml(message)) if message_element.length == 1 && $(message_element[0])?.children()?.length message_element[0].innerHTML = @signatureIdentifyByHtmlHelper(message_element[0].innerHTML) 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') _.some el.children(), (el) -> isQuoteOrSignature el - $('
').html(message).contents().each (index, node) -> + try content = $('
').html(message) + catch e then content = $('
').html('
' + message + '
') + + content.contents().each (index, node) -> text = $(node).text() if node.nodeType == Node.TEXT_NODE # convert text back to HTML as it was before @@ -1457,3 +1460,10 @@ class App.Utils htmlString = App.Utils.text2html(text) 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('
' + input + '
')[0].childNodes diff --git a/public/assets/tests/html_utils.js b/public/assets/tests/html_utils.js index f75dfd75f..4d7663670 100644 --- a/public/assets/tests/html_utils.js +++ b/public/assets/tests/html_utils.js @@ -1051,6 +1051,14 @@ test("identify signature by HTML", function() { var result = App.Utils.signatureIdentifyByHtml(message) equal(result, should) + + // test if, according to jQuery, invalid HTML does not cause a a crash + // https://github.com/zammad/zammad/issues/3393 + message = "
test 123
" + should = message + result = App.Utils.signatureIdentifyByHtml(message) + equal(result, should) + // simple case 1 message = '
actual content
quoted content
' should = '
actual content
quoted content
' @@ -3386,3 +3394,20 @@ test('App.Utils.signatureIdentifyByHtmlHelper()', function() { equal(result, "<script>alert('fish2');</script>
", 'signatureIdentifyByHtmlHelper does not reactivate alert') }); + +test("#safeParseHtml", function() { + var unwrap = input => $('
').html(input)[0].innerHTML + + var html = "
test 123
" + 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 = "
test 123
" + should = "
test 123
" + result = App.Utils.safeParseHtml(html) + equal(unwrap(result), should) +})