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)
+})