Implemented issue #930 - view support for html tables.

This commit is contained in:
Martin Edenhofer 2017-04-28 12:16:15 +02:00
parent ee9046e3e9
commit 7a08b9266b
9 changed files with 609 additions and 470 deletions

View file

@ -8411,26 +8411,11 @@ output {
}
table {
border: none;
table-layout: auto;
display: block;
width: 100%;
overflow: auto;
word-break: keep-all;
td, th {
padding: 7px 12px;
border: 1px solid hsl(0,0%,87%);
}
th {
font-weight: bold;
text-align: center;
}
tbody tr:nth-child(even) {
background: hsl(0,0%,97%);
}
word-break: break-all;
col {
width: auto;

View file

@ -37,17 +37,87 @@ Rails.application.config.html_sanitizer_attributes_whitelist = {
'ins' => %w(cite datetime),
'li' => %w(value),
'ol' => %w(reversed start type),
'table' => %w(align bgcolor border cellpadding cellspacing frame rules sortable summary width),
'td' => %w(abbr align axis colspan headers rowspan valign width),
'th' => %w(abbr align axis colspan headers rowspan scope sorted valign width),
'table' => %w(align bgcolor border cellpadding cellspacing frame rules sortable summary width style),
'td' => %w(abbr align axis colspan headers rowspan valign width style),
'th' => %w(abbr align axis colspan headers rowspan scope sorted valign width style),
'ul' => %w(type),
'q' => %w(cite),
'span' => %w(style),
'time' => %w(datetime pubdate),
}
# only this css properties are allowed
Rails.application.config.html_sanitizer_css_properties_whitelist = %w(
Rails.application.config.html_sanitizer_css_properties_whitelist = {
'img' => %w(
width height
max-width min-width
max-height min-height
)
),
'span' => %w(
color
),
'table' => %w(
background-color color
padding margin
text-align
border border-collapse border-style
border-top-width
border-right-width
border-bottom-width
border-left-width
border-top-color
border-right-color
border-bottom-color
border-left-color
),
'th' => %w(
background-color color
padding margin
text-align
border border-collapse border-style
border-top-width
border-right-width
border-bottom-width
border-left-width
border-top-color
border-right-color
border-bottom-color
border-left-color
),
'tr' => %w(
background-color color
padding margin
text-align
border border-collapse border-style
border-top-width
border-right-width
border-bottom-width
border-left-width
border-top-color
border-right-color
border-bottom-color
border-left-color
),
'td' => %w(
background-color color
padding margin
text-align
border border-collapse border-style
border-top-width
border-right-width
border-bottom-width
border-left-width
border-top-color
border-right-color
border-bottom-color
border-left-color
),
}

View file

@ -289,8 +289,9 @@ class String
def html2html_strict
string = "#{self}" # rubocop:disable Style/UnneededInterpolation
string = HtmlSanitizer.cleanup(string).strip
string = HtmlSanitizer.cleanup_replace_tags(string)
string = HtmlSanitizer.strict(string, true).strip
string = HtmlSanitizer.cleanup(string).strip
# as fallback, use html2text and text2html
if string.blank?
@ -313,6 +314,7 @@ class String
string.gsub!(%r{<p>[[:space:]]+</p>}im, '<p>&nbsp;</p>')
string.gsub!(%r{\A(<br(|\/)>[[:space:]]*)*}i, '')
string.gsub!(%r{[[:space:]]*(<br(|\/)>[[:space:]]*)*\Z}i, '')
string.gsub!(%r{(<p></p>){1,10}\Z}i, '')
string.signature_identify('html')

View file

@ -22,14 +22,27 @@ satinize html string based on whiltelist
scrubber_link = Loofah::Scrubber.new do |node|
# check if href is different to text
if external && node.name == 'a' && !url_same?(node['href'], node.text)
if node.name == 'a' && !url_same?(node['href'], node.text)
if node['href'].blank?
node.replace node.children.to_s
Loofah::Scrubber::STOP
elsif (node.children.empty? || node.children.first.class == Nokogiri::XML::Text) && node.text.present?
text = Nokogiri::XML::Text.new("#{node['href']} (", node.document)
elsif ((node.children.empty? || node.children.first.class == Nokogiri::XML::Text) && node.text.present?) || (node.children.size == 1 && node.children.first.content == node.content && node.content.present?)
if node.text.downcase.start_with?('http', 'ftp', '//')
a = Nokogiri::XML::Node.new 'a', node.document
a['href'] = node['href']
a['rel'] = 'nofollow noreferrer noopener'
a['target'] = '_blank'
a.content = node['href']
node.add_previous_sibling(a)
text = Nokogiri::XML::Text.new(' (', node.document)
node.add_previous_sibling(text)
node['href'] = cleanup_target(node.text)
else
text = Nokogiri::XML::Text.new("#{node.text} (", node.document)
node.add_previous_sibling(text)
node.content = cleanup_target(node['href'])
node['href'] = cleanup_target(node['href'])
end
text = Nokogiri::XML::Text.new(')', node.document)
node.add_next_sibling(text)
else
@ -145,7 +158,8 @@ satinize html string based on whiltelist
prop = local_pear.split(':')
next if !prop[0]
key = prop[0].strip
next if !css_properties_whitelist.include?(key)
next if !css_properties_whitelist.include?(node.name)
next if !css_properties_whitelist[node.name].include?(key)
style += "#{local_pear};"
}
node['style'] = style
@ -198,7 +212,7 @@ satinize html string based on whiltelist
cleanup html string:
* remove empty nodes (p, div, span)
* remove empty nodes (p, div, span, table)
* remove nodes in general (keep content - span)
string = HtmlSanitizer.cleanup(string)
@ -216,44 +230,43 @@ cleanup html string:
# remove double multiple empty lines
string.gsub!(/\n\n\n+/, "\n\n")
string = cleanup_structure(string, 'pre')
string = cleanup_replace_tags(string)
cleanup_structure(string)
string = cleanup_structure(string)
string
end
def self.cleanup_replace_tags(string)
string.gsub!(%r{(<table(.+?|)>.+?</table>)}mxi) { |table|
table.gsub!(/<table(.+?|)>/im, '<br>')
table.gsub!(%r{</table>}im, ' ')
table.gsub!(/<thead(.+?|)>/im, '')
table.gsub!(%r{</thead>}im, ' ')
table.gsub!(/<tbody(.+?|)>/im, '')
table.gsub!(%r{</tbody>}im, ' ')
table.gsub!(/<tr(.+?|)>/im, "<br>\n")
#table.gsub!(%r{</td>}im, '')
#table.gsub!(%r{</td>}im, "\n<br>\n")
table.gsub!(%r{</td>}im, ' ')
table.gsub!(/<td(.+?|)>/im, '')
#table.gsub!(%r{</tr>}im, '')
table.gsub!(%r{</tr>}im, "\n<br>")
table.gsub!(/<br>[[:space:]]?<br>/im, '<br>')
table.gsub!(/<br>[[:space:]]?<br>/im, '<br>')
table.gsub!(%r{<br/>[[:space:]]?<br/>}im, '<br/>')
table.gsub!(%r{<br/>[[:space:]]?<br/>}im, '<br/>')
table
}
tags_backlist = %w(span table thead tbody td tr center)
#return string
tags_backlist = %w(span center)
scrubber = Loofah::Scrubber.new do |node|
next if !tags_backlist.include?(node.name)
hit = false
local_node = nil
(1..5).each { |_count|
local_node = if local_node
local_node.parent
else
node.parent
end
break if !local_node
next if local_node.name != 'td'
hit = true
}
next if hit && node.keys.count.positive?
node.replace cleanup_replace_tags(node.children.to_s)
Loofah::Scrubber::STOP
end
Loofah.fragment(string).scrub!(scrubber).to_s
end
def self.cleanup_structure(string)
remove_empty_nodes = %w(p div span small)
remove_empty_last_nodes = %w(b i u small)
def self.cleanup_structure(string, type = 'all')
remove_empty_nodes = if type == 'pre'
%w(span)
else
%w(p div span small table)
end
remove_empty_last_nodes = %w(b i u small table)
# remove last empty nodes and empty -not needed- parrent nodes
scrubber_structure = Loofah::Scrubber.new do |node|
@ -261,10 +274,24 @@ cleanup html string:
node.remove
Loofah::Scrubber::STOP
end
if remove_empty_nodes.include?(node.name) && node.children.size == 1 && remove_empty_nodes.include?(node.children.first.name)
# remove empty childs
if node.content.blank? && remove_empty_nodes.include?(node.name) && node.children.size == 1 && remove_empty_nodes.include?(node.children.first.name)
node.replace node.children.to_s
Loofah::Scrubber::STOP
end
# remove empty childs
if remove_empty_nodes.include?(node.name) && node.children.size == 1 && remove_empty_nodes.include?(node.children.first.name) && node.children.first.content == node.content
node.replace node.children.to_s
Loofah::Scrubber::STOP
end
# remove node if empty and parent was already a remove node
if node.content.blank? && remove_empty_nodes.include?(node.name) && node.parent && node.children.size.zero? && remove_empty_nodes.include?(node.parent.name)
node.remove
Loofah::Scrubber::STOP
end
end
new_string = ''
@ -290,23 +317,6 @@ cleanup html string:
end
end
# check if href is different to text
if node.name == 'a' && !url_same?(node['href'], node.text)
if node['href'].blank?
node.replace cleanup_structure(node.children.to_s)
Loofah::Scrubber::STOP
elsif node.children.empty? || node.children.first.class == Nokogiri::XML::Text
text = Nokogiri::XML::Text.new("#{node.text} (", node.document)
node.add_previous_sibling(text)
node.content = cleanup_target(node['href'])
node['href'] = cleanup_target(node['href'])
text = Nokogiri::XML::Text.new(')', node.document)
node.add_next_sibling(text)
else
node.content = cleanup_target(node['href'])
end
end
# remove not needed new lines
if node.class == Nokogiri::XML::Text
if !node.parent || (node.parent.name != 'pre' && node.parent.name != 'code')

View file

@ -468,8 +468,7 @@ Men-----------------------'
html = "<div><p> </p><p> </p></div>"
result = "<div>
<p>&nbsp;</p>
</div>"
<p>&nbsp;</p></div>"
assert_equal(result, html.html2html_strict)
html = "<div><div> </div><div> </div></div>"
@ -489,8 +488,7 @@ Men-----------------------'
<br> <p><b>Description</b></p>
<br> <br> </div>'
result = '<div>
<br> <p><b>Description</b></p>
<br> <br> </div>'
<br> <p><b>Description</b></p><br> <br> </div>'
assert_equal(result, html.html2html_strict)
html = '<div>
@ -522,13 +520,7 @@ Men-----------------------'
<div>'
result = '<div>
<p>Guten Morgen, Frau Koppenhagen,</p>
<p>&nbsp;</p>
<p>vielen Dank für die Reservierung. Dabei allerdings die Sprache (Niederländisch) nicht erwähnt. Können Sie bitte dieses in Ihrer Reservierung vormerken?</p>
<p>&nbsp;</p>
<p>Nochmals vielen Dank und herzliche Grüße</p>
<div></div>
</div>'
<p>Guten Morgen, Frau Koppenhagen,</p><p>&nbsp;</p><p>vielen Dank für die Reservierung. Dabei allerdings die Sprache (Niederländisch) nicht erwähnt. Können Sie bitte dieses in Ihrer Reservierung vormerken?</p><p>&nbsp;</p><p>Nochmals vielen Dank und herzliche Grüße</p></div>'
assert_equal(result, html.html2html_strict)
html = '<a href="http://example.com">http://example.com</a>'
@ -552,7 +544,8 @@ Men-----------------------'
assert_equal(result, html.html2html_strict)
html = '<div>https://www.facebook.com/test</div>'
result = '<div><a href="https://www.facebook.com/test" rel="nofollow noreferrer noopener" target="_blank">https://www.facebook.com/test</a>
result = '<div>
<a href="https://www.facebook.com/test" rel="nofollow noreferrer noopener" target="_blank">https://www.facebook.com/test</a>
</div>'
assert_equal(result, html.html2html_strict)
@ -595,8 +588,7 @@ Men-----------------------'
assert_equal(result, html.html2html_strict)
html = '<a href="http://example.com">http://what-different.example.com</a>'
#result = 'http://example.com (<a href="http://what-different.example.com" rel="nofollow noreferrer noopener" target="_blank">http://what-different.example.com</a>)'
result = '<a href="http://what-different.example.com" rel="nofollow noreferrer noopener" target="_blank">http://what-different.example.com</a> (<a href="http://example.com" rel="nofollow noreferrer noopener" target="_blank">http://example.com</a>)'
result = "<a href=\"http://example.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://example.com</a> (<a href=\"http://what-different.example.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://what-different.example.com</a>)"
assert_equal(result, html.html2html_strict)
html = '<a href="http://example.com">http://EXAMPLE.com</a>'
@ -640,11 +632,11 @@ Men-----------------------'
assert_equal(result, html.html2html_strict)
html = "<div>http://example.com</div>"
result = "<div><a href=\"http://example.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://example.com</a>\n</div>"
result = "<div>\n<a href=\"http://example.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://example.com</a>\n</div>"
assert_equal(result, html.html2html_strict)
html = "<div>http://example.com.</div>"
result = "<div><a href=\"http://example.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://example.com</a>.</div>"
result = "<div>\n<a href=\"http://example.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://example.com</a>.</div>"
assert_equal(result, html.html2html_strict)
html = "<div>lala http://example.com.</div>"
@ -652,11 +644,11 @@ Men-----------------------'
assert_equal(result, html.html2html_strict)
html = "<div>http://example.com, and so on</div>"
result = "<div><a href=\"http://example.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://example.com</a>, and so on</div>"
result = "<div>\n<a href=\"http://example.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://example.com</a>, and so on</div>"
assert_equal(result, html.html2html_strict)
html = "<div>http://example.com?lala=me, and so on</div>"
result = "<div><a href=\"http://example.com?lala=me\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://example.com?lala=me</a>, and so on</div>"
result = "<div>\n<a href=\"http://example.com?lala=me\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://example.com?lala=me</a>, and so on</div>"
assert_equal(result, html.html2html_strict)
html = "<a href=\"http://facebook.de/examplesrbog\"><span lang=\"EN-US\" style='color:blue'>http://facebook.de/examplesrbog</span></a>"
@ -682,19 +674,22 @@ Men-----------------------'
html = "<div>
abc<p><b>Von:</b> Fritz Bauer [mailto:me@example.com] <br><b>Gesendet:</b> Donnerstag, 3. Mai 2012 11:51<br><b>An:</b> John Smith<br><b>Cc:</b> Smith, John Marian; johnel.fratczak@example.com; ole.brei@example.com; Günther John | Example GmbH; bkopon@example.com; john.heisterhagen@team.example.com; sven.rocked@example.com; michael.house@example.com; tgutzeit@example.com<br><b>Betreff:</b> Re: OTRS::XXX Erweiterung - Anhänge an CI's </p></div>"
result = "<div>abc<span class=\"js-signatureMarker\"></span><p><b>Von:</b> Fritz Bauer [mailto:me@example.com] <br><b>Gesendet:</b> Donnerstag, 3. Mai 2012 11:51<br><b>An:</b> John Smith<br><b>Cc:</b> Smith, John Marian; johnel.fratczak@example.com; ole.brei@example.com; Günther John | Example GmbH; bkopon@example.com; john.heisterhagen@team.example.com; sven.rocked@example.com; michael.house@example.com; tgutzeit@example.com<br><b>Betreff:</b> Re: OTRS::XXX Erweiterung - Anhänge an CI's </p>\n</div>"
result = "<div>abc<span class=\"js-signatureMarker\"></span><p><b>Von:</b> Fritz Bauer [mailto:me@example.com] <br><b>Gesendet:</b> Donnerstag, 3. Mai 2012 11:51<br><b>An:</b> John Smith<br><b>Cc:</b> Smith, John Marian; johnel.fratczak@example.com; ole.brei@example.com; Günther John | Example GmbH; bkopon@example.com; john.heisterhagen@team.example.com; sven.rocked@example.com; michael.house@example.com; tgutzeit@example.com<br><b>Betreff:</b> Re: OTRS::XXX Erweiterung - Anhänge an CI's </p></div>"
assert_equal(result, html.html2html_strict)
html = "<div> abc<p> <b>Von:</b> Fritz Bauer [mailto:me@example.com] <br><b>Gesendet:</b> Donnerstag, 3. Mai 2012 11:51<br><b>An:</b> John Smith<br><b>Cc:</b> Smith, John Marian; johnel.fratczak@example.com; ole.brei@example.com; Günther John | Example GmbH; bkopon@example.com; john.heisterhagen@team.example.com; sven.rocked@example.com; michael.house@example.com; tgutzeit@example.com<br><b>Betreff:</b> Re: OTRS::XXX Erweiterung - Anhänge an CI's </p></div>"
result = "<div>abc<span class=\"js-signatureMarker\"></span><p> <b>Von:</b> Fritz Bauer [mailto:me@example.com] <br><b>Gesendet:</b> Donnerstag, 3. Mai 2012 11:51<br><b>An:</b> John Smith<br><b>Cc:</b> Smith, John Marian; johnel.fratczak@example.com; ole.brei@example.com; Günther John | Example GmbH; bkopon@example.com; john.heisterhagen@team.example.com; sven.rocked@example.com; michael.house@example.com; tgutzeit@example.com<br><b>Betreff:</b> Re: OTRS::XXX Erweiterung - Anhänge an CI's </p>\n</div>"
result = "<div>abc<span class=\"js-signatureMarker\"></span><p> <b>Von:</b> Fritz Bauer [mailto:me@example.com] <br><b>Gesendet:</b> Donnerstag, 3. Mai 2012 11:51<br><b>An:</b> John Smith<br><b>Cc:</b> Smith, John Marian; johnel.fratczak@example.com; ole.brei@example.com; Günther John | Example GmbH; bkopon@example.com; john.heisterhagen@team.example.com; sven.rocked@example.com; michael.house@example.com; tgutzeit@example.com<br><b>Betreff:</b> Re: OTRS::XXX Erweiterung - Anhänge an CI's </p></div>"
assert_equal(result, html.html2html_strict)
html = "<div> abc<p> <b>Von:</b> Fritz Bauer [mailto:me@example.com] <br><b>Gesendet:</b> Donnerstag, 3. Mai 2012 11:51<br><b>An:</b> John Smith<br><b>Cc:</b> Smith, John Marian; johnel.fratczak@example.com; ole.brei@example.com; Günther John | Example GmbH; bkopon@example.com; john.heisterhagen@team.example.com; sven.rocked@example.com; michael.house@example.com; tgutzeit@example.com<br><b>Betreff:</b> Re: OTRS::XXX Erweiterung - Anhänge an CI's </p> </div>"
result = "<div>abc<span class=\"js-signatureMarker\"></span><p> <b>Von:</b> Fritz Bauer [mailto:me@example.com] <br><b>Gesendet:</b> Donnerstag, 3. Mai 2012 11:51<br><b>An:</b> John Smith<br><b>Cc:</b> Smith, John Marian; johnel.fratczak@example.com; ole.brei@example.com; Günther John | Example GmbH; bkopon@example.com; john.heisterhagen@team.example.com; sven.rocked@example.com; michael.house@example.com; tgutzeit@example.com<br><b>Betreff:</b> Re: OTRS::XXX Erweiterung - Anhänge an CI's </p>\n</div>"
result = "<div>abc<span class=\"js-signatureMarker\"></span><p> <b>Von:</b> Fritz Bauer [mailto:me@example.com] <br><b>Gesendet:</b> Donnerstag, 3. Mai 2012 11:51<br><b>An:</b> John Smith<br><b>Cc:</b> Smith, John Marian; johnel.fratczak@example.com; ole.brei@example.com; Günther John | Example GmbH; bkopon@example.com; john.heisterhagen@team.example.com; sven.rocked@example.com; michael.house@example.com; tgutzeit@example.com<br><b>Betreff:</b> Re: OTRS::XXX Erweiterung - Anhänge an CI's </p></div>"
assert_equal(result, html.html2html_strict)
html = "<div style=\"margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif; \"><span style=\"font-size: 10pt; font-family: Arial, sans-serif; \">Mit freundlichem Gruß<span class=\"Apple-converted-space\">&nbsp;</span><br><br>John Smith<br>Service und Support<br><br>Example Service AG &amp; Co.<o:p></o:p></span></div><div style=\"margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif; \"><span style=\"font-size: 10pt; font-family: Arial, sans-serif; \">Management OHG<br>Someware-Str. 4<br>xxxxx Someware<br><br></span><span style=\"font-size: 10pt; font-family: Arial, sans-serif; \"><o:p></o:p></span></div><div style=\"margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif; \"><span style=\"font-size: 10pt; font-family: Arial, sans-serif; \">Tel.: +49 001 7601 462<br>Fax: +49 001 7601 472</span><span style=\"font-size: 10pt; font-family: Arial, sans-serif; \"><o:p></o:p></span></div><div style=\"margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif; \"><span style=\"font-size: 10pt; font-family: Arial, sans-serif; \"><a href=\"mailto:john.smith@example.com\" style=color: blue; text-decoration: underline; \">john.smith@example.com</a></span><span style=\"font-size: 10pt; font-family: Arial, sans-serif; \"><o:p></o:p></span></div><div style=\"margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif; \"><span style=\"font-size: 10pt; font-family: Arial, sans-serif; \"><a href=\"http://www.example.com\" style=\"color: blue; text-decoration: underline; \">www.example.com</a></span><span style=\"font-size: 10pt; font-family: Arial, sans-serif; \"><o:p></o:p></span></div>"
result = "<div>Mit freundlichem Gruß<br><br>John Smith<br>Service und Support<br><br>Example Service AG &amp; Co.</div><div>Management OHG<br>Someware-Str. 4<br>xxxxx Someware<br><br>\n</div><div>Tel.: +49 001 7601 462<br>Fax: +49 001 7601 472</div><div>john.smith@example.com</div><div><a href=\"http://www.example.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">www.example.com</a></div>"
result = "<div>Mit freundlichem Gruß<br><br>John Smith<br>Service und Support<br><br>Example Service AG &amp; Co. </div><div>Management OHG<br>Someware-Str. 4<br>xxxxx Someware<br><br>
</div><div>Tel.: +49 001 7601 462<br>Fax: +49 001 7601 472 </div><div>john.smith@example.com</div><div>
<a href=\"http://www.example.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">www.example.com</a>
</div>"
assert_equal(result, html.html2html_strict)
html = '<b >test</b>'
@ -728,14 +723,26 @@ abc<p><b>Von:</b> Fritz Bauer [mailto:me@example.com] <br><b>Gesendet:</b> Donne
<br>
<table>'
result = "<b>Franz Schäfer</b><br><br><br><br>Telefon\n+49 000 000 8565<br>\nchristian.schaefer@example.com<br><br><br>"
result = '<b>Franz Schäfer</b>
result = '<table>
<tr>
<td>
<b>Franz Schäfer</b>
</td>
</tr>
<tr>
<td>Manager Information Systems</td>
</tr>
</table>
<br>
Manager Information Systems <br>
<br>
Telefon
+49 000 000 8565
<br>
christian.schaefer@example.com'
<table>
<tr>
<td> Telefon </td>
<td> +49 000 000 8565 </td>
</tr>
<tr>
<td colspan="2">christian.schaefer@example.com</td>
</tr>
</table>'
assert_equal(result, html.html2html_strict)
html = "<b id=123 classs=\"\nsome_class\">test</b>"
@ -752,6 +759,7 @@ christian.schaefer@example.com'
html = '<div><div>Hello Martin,</div></div>'
result = '<div>Hello Martin,</div>'
html.html2html_strict
assert_equal(result, html.html2html_strict)
html = '<div lang="DE"><div><div>Hello Martin,</div></div></div>'
@ -759,7 +767,7 @@ christian.schaefer@example.com'
assert_equal(result, html.html2html_strict)
html = '<div lang="DE"><div><div>Hello Martin,</div> </div></div>'
result = "<div>\n<div>Hello Martin,</div>\n</div>"
result = "<div>\n<div>Hello Martin,</div></div>"
assert_equal(result, html.html2html_strict)
html = '<span></span>'
@ -797,8 +805,7 @@ christian.schaefer@example.com'
<p> </p>
</div>'
result = '<div>
<p>&nbsp;</p>
</div>'
<p>&nbsp;</p></div>'
assert_equal(result, html.html2html_strict)
html = '<p lang="DE"><b><span></span></b></p>'
@ -806,7 +813,8 @@ christian.schaefer@example.com'
assert_equal(result, html.html2html_strict)
html = '<div>lala<div lang="DE"><p><span>Hello Martin,</span></p></div></div>'
result = "<div>lala<p>Hello Martin,</p>\n</div>"
result = "<div>lala<p>Hello Martin,</p></div>"
html.html2html_strict
assert_equal(result, html.html2html_strict)
html = '<p lang="DE"><b><span>Hello Martin,</span></b></p>'
@ -835,27 +843,7 @@ christian.schaefer@example.com'
</span><a href="http://www.ABC.com/"><span style="font-size:9.0pt">www.ABC.com</span></a><span style="font-size:9.0pt;color:#1F497D"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:8.0pt;color:#1F497D">Geschäftsführer Vor Nach, VorUndZu Nach&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp;&nbsp;&nbsp; Amtsgericht Dort HRB 12345&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp;&nbsp; Ein Unternehmer der ABC Gruppe<o:p></o:p></span></p>'
result = '<div>
<p>Guten Morgen, Frau ABC,</p>
<p>&nbsp;</p>
<p>vielen Dank für die Reservierung. Dabei allerdings die Sprache (Niederländisch) nicht erwähnt. Können Sie bitte dieses in Ihrer Reservierung vormerken?</p>
<p>&nbsp;</p>
<p>Nochmals vielen Dank und herzliche Grüße</p>
<div>
<p><b> </b></p>
<p><b>Anna Smith</b></p>
<p><b>art abc SEV GmbH</b></p>
<p><b>art abc TRAV</b></p>
<p>Marktstätte 123</p>
<p>123456 Dorten</p>
<p>T: +49 (0) 12345/1234560-1</p>
<p>T: +49 (0) 12345/1234560-0</p>
<p>F: +49 (0) 12345/1234560-2</p>
<p>annad@example.com</p>
<p><a href="http://www.example.com/" rel="nofollow noreferrer noopener" target="_blank">www.example.com</a> <a href="http://www.ABC.com/" rel="nofollow noreferrer noopener" target="_blank">www.ABC.com</a></p>
<p>Geschäftsführer Vor Nach, VorUndZu Nach - Amtsgericht Dort HRB 12345 - Ein Unternehmer der ABC Gruppe</p>
</div>
</div>'
result = "<div>\n<p>Guten Morgen, Frau ABC,</p><p>&nbsp;</p><p>vielen Dank für die Reservierung. Dabei allerdings die Sprache (Niederländisch) nicht erwähnt. Können Sie bitte dieses in Ihrer Reservierung vormerken?</p><p>&nbsp;</p><p>Nochmals vielen Dank und herzliche Grüße</p><div> <p>&nbsp;</p><p><b>Anna Smith</b></p><p><b>art abc SEV GmbH</b></p><p><b>art abc TRAV</b></p><p>Marktstätte 123</p><p>123456 Dorten</p><p>T: +49 (0) 12345/1234560-1</p><p>T: +49 (0) 12345/1234560-0</p><p>F: +49 (0) 12345/1234560-2</p><p>annad@example.com</p><p><a href=\"http://www.example.com/\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">www.example.com</a> <a href=\"http://www.ABC.com/\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">www.ABC.com</a></p><p>Geschäftsführer Vor Nach, VorUndZu Nach - Amtsgericht Dort HRB 12345 - Ein Unternehmer der ABC Gruppe</p></div></div>"
assert_equal(result, html.html2html_strict)
html = '<p class="MsoNormal"><span style="color:#1F497D"><o:p>&nbsp;</o:p></span></p>
@ -878,9 +866,7 @@ christian.schaefer@example.com'
<span class="js-signatureMarker"></span><p><b>Von:</b> Besucherbüro, MKuk [besucherbuero@example.com] <br>
<b>Gesendet:</b> Freitag, 16. Dezember 2016 08:05<br>
<b>An:</b> \'Amaia Epalza\'<br>
<b>Betreff:</b> AW: Gruppe vtb Kultuur // 28.06.2017</p>
</div>
</div><p>&nbsp;</p><p><b>Reservierungsbestätigung Führung Skulptur-Projekte 2017 am </b></p><p>&nbsp;</p><p>Guten Morgen Frau Epalza,</p>'
<b>Betreff:</b> AW: Gruppe vtb Kultuur // 28.06.2017</p></div></div><p>&nbsp;</p><p><b>Reservierungsbestätigung Führung Skulptur-Projekte 2017 am </b></p><p>&nbsp;</p><p>Guten Morgen Frau Epalza,</p>'
assert_equal(result, html.html2html_strict)
html = '<html><head><base href="x-msg://2849/"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><span class="Apple-style-span" style="border-collapse: separate; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; font-size: medium; "><div lang="DE" link="blue" vlink="purple"><div class="Section1" style="page: Section1; "><div style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 11pt; font-family: Calibri, sans-serif; "><span style="font-size: 10pt; font-family: Arial, sans-serif; ">Hello Martin,<o:p></o:p></span></div>'
@ -928,9 +914,7 @@ christian.schaefer@example.com'
assert_equal(result, html.html2html_strict)
html = '<div class="">Wir brauchen also die Instanz <a href="http://example.zammad.com" class="">example.zammad.com</a>, kann die aber nicht mehr nutzen.</div><div class=""><br class=""></div><div class="">Bitte um Freischaltung.</div><div class=""><br class=""></div><div class=""><br class=""><div class="">'
result = '<div>Wir brauchen also die Instanz <a href="http://example.zammad.com" rel="nofollow noreferrer noopener" target="_blank">example.zammad.com</a>, kann die aber nicht mehr nutzen.</div><div> </div><div>Bitte um Freischaltung.</div><div> </div><div>
<br><div></div>
</div>'
result = '<div>Wir brauchen also die Instanz <a href="http://example.zammad.com" rel="nofollow noreferrer noopener" target="_blank">example.zammad.com</a>, kann die aber nicht mehr nutzen.</div><div> </div><div>Bitte um Freischaltung.</div><div> </div>'
assert_equal(result, html.html2html_strict)
html = '<p class="MsoNormal"><span style="font-size:11.0pt;font-family:&quot;Calibri&quot;,sans-serif;color:#1F497D;mso-fareast-language:EN-US">oh jeee Zauberwort vergessen ;-) Können Sie mir
@ -940,9 +924,39 @@ christian.schaefer@example.com'
assert_equal(result, html.html2html_strict)
html = '<div><a href="http://www.example.com/Community/Passwort-Vergessen/?module_fnc=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805" title="http://www.example.com/Community/Passwort-Vergessen/?module_fnc%5BextranetHandler%5D=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805" rel="nofollow" target="_blank">http://www.example.com/Community/Passwort-Vergessen/?module_fnc%5BextranetHandler%5D=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805</a></div>'
result = '<div><a href="http://www.example.com/Community/Passwort-Vergessen/?module_fnc%5BextranetHandler%5D=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805" rel="nofollow noreferrer noopener" target="_blank">http://www.example.com/Community/Passwort-Vergessen/?module_fnc%5BextranetHandler%5D=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805</a> (<a href="http://www.example.com/Community/Passwort-Vergessen/?module_fnc=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805" title="http://www.example.com/Community/Passwort-Vergessen/?module_fnc%5BextranetHandler%5D=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805" rel="nofollow noreferrer noopener" target="_blank">http://www.example.com/Community/Passwort-Vergessen/?module_fnc=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805</a>)</div>'
result = "<div>\n<a href=\"http://www.example.com/Community/Passwort-Vergessen/?module_fnc=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://www.example.com/Community/Passwort-Vergessen/?module_fnc=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805</a> (<a href=\"http://www.example.com/Community/Passwort-Vergessen/?module_fnc=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805\" title=\"http://www.example.com/Community/Passwort-Vergessen/?module_fnc%5BextranetHandler%5D=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://www.example.com/Community/Passwort-Vergessen/?module_fnc%5BextranetHandler%5D=ChangeForgotPassword&amp;pwchangekey=66901c449dda98a098de4b57ccdf0805</a>)</div>"
assert_equal(result, html.html2html_strict)
html = '<tr style="height: 15pt;" class=""><td width="170" nowrap="" valign="bottom" style="width: 127.5pt; border-style: none none none solid; border-left-width: 1pt; border-left-color: windowtext; padding: 0cm 5.4pt; height: 15pt;" class=""><p class="MsoNormal" align="center" style="margin: 0cm 0cm 0.0001pt; font-size: 12pt; font-family: \'Times New Roman\', serif; text-align: center;"><span style="" class="">&nbsp;</span></p></td><td width="58" nowrap="" valign="bottom" style="width: 43.5pt; padding: 0cm 5.4pt; height: 15pt;" class=""><div style="margin: 0cm 0cm 0.0001pt; font-size: 12pt; font-family: \'Times New Roman\', serif; text-align: center;" class=""><span style="" class="">20-29</span></div></td><td width="47" nowrap="" valign="bottom" style="width: 35pt; background-color: rgb(255, 199, 206); padding: 0cm 5.4pt; height: 15pt; background-position: initial initial; background-repeat: initial initial;" class=""><div style="margin: 0cm 0cm 0.0001pt; font-size: 12pt; font-family: \'Times New Roman\', serif; text-align: center;" class=""><span style="color: rgb(156, 0, 6);" class="">200</span></div></td><td width="76" nowrap="" valign="bottom" style="width: 57pt; background-color: rgb(255, 199, 206); padding: 0cm 5.4pt; height: 15pt; background-position: initial initial; background-repeat: initial initial;" class=""><div style="margin: 0cm 0cm 0.0001pt; font-size: 12pt; font-family: \'Times New Roman\', serif; text-align: center;" class=""><span style="color: rgb(156, 0, 6);" class="">-1</span></div></td><td width="76" nowrap="" valign="bottom" style="width: 57pt; border-style: none solid none none; border-right-width: 1pt; border-right-color: windowtext; background-color: rgb(255, 199, 206); padding: 0cm 5.4pt; height: 15pt; background-position: initial initial; background-repeat: initial initial;" class=""><div style="margin: 0cm 0cm 0.0001pt; font-size: 12pt; font-family: \'Times New Roman\', serif; text-align: center;" class=""><span style="color: rgb(156, 0, 6);" class="">201</span></div></td><td width="107" nowrap="" valign="bottom" style="width: 80pt; padding: 0cm 5.4pt; height: 15pt;" class=""></td><td width="85" nowrap="" valign="bottom" style="width: 64pt; padding: 0cm 5.4pt; height: 15pt;" class=""></td><td width="101" nowrap="" valign="bottom" style="width: 76pt; border-style: none solid solid; border-left-width: 1pt; border-left-color: windowtext; border-bottom-width: 1pt; border-bottom-color: gray; border-right-width: 1pt; border-right-color: gray; background-color: rgb(242, 242, 242); padding: 0cm 5.4pt; height: 15pt; background-position: initial initial; background-repeat: initial initial;" class=""><div style="margin: 0cm 0cm 0.0001pt; font-size: 12pt; font-family: \'Times New Roman\', serif; text-align: center;" class=""><b class=""><span style="font-size: 10pt; font-family: Arial, sans-serif;" class="">country</span></b><span style="font-size: 11pt; font-family: Calibri, sans-serif;" class=""></span></div></td><td width="87" nowrap="" valign="bottom" style="width: 65pt; border-style: none solid solid none; border-bottom-width: 1pt; border-bottom-color: gray; border-right-width: 1pt; border-right-color: gray; background-color: rgb(242, 242, 242); padding: 0cm 5.4pt; height: 15pt; background-position: initial initial; background-repeat: initial initial;" class=""><div style="margin: 0cm 0cm 0.0001pt; font-size: 12pt; font-family: \'Times New Roman\', serif; text-align: center;" class=""><span style="font-size: 10pt; font-family: Arial, sans-serif;" class="">Target (gross)</span></div></td><td width="123" nowrap="" valign="bottom" style="width: 92pt; border-style: none solid solid none; border-bottom-width: 1pt; border-bottom-color: gray; border-right-width: 1pt; border-right-color: gray; background-color: rgb(242, 242, 242); padding: 0cm 5.4pt; height: 15pt; background-position: initial initial; background-repeat: initial initial;" class=""><div style="margin: 0cm 0cm 0.0001pt; font-size: 12pt; font-family: \'Times New Roman\', serif; text-align: center;" class=""><span style="font-size: 10pt; font-family: Arial, sans-serif;" class="">Remaining Recruits</span></div></td><td width="87" nowrap="" valign="bottom" style="width: 65pt; border-style: none solid solid none; border-bottom-width: 1pt; border-bottom-color: gray; border-right-width: 1pt; border-right-color: windowtext; background-color: rgb(242, 242, 242); padding: 0cm 5.4pt; height: 15pt; background-position: initial initial; background-repeat: initial initial;" class=""><div style="margin: 0cm 0cm 0.0001pt; font-size: 12pt; font-family: \'Times New Roman\', serif; text-align: center;" class=""><span style="font-size: 10pt; font-family: Arial, sans-serif;" class="">Total Recruits</span></div></td></tr>'
result = "<tr>
<td valign=\"bottom\" style=\" border-style: none none none solid; border-left-width: 1pt; border-left-color: windowtext; padding: 0cm 5.4pt;\"><p>&nbsp;</p></td>
<td valign=\"bottom\" style=\" padding: 0cm 5.4pt;\"><div>20-29</div></td>
<td valign=\"bottom\" style=\" background-color: rgb(255, 199, 206); padding: 0cm 5.4pt;\"><span style=\"color: rgb(156, 0, 6);\">200</span></td>
<td valign=\"bottom\" style=\" background-color: rgb(255, 199, 206); padding: 0cm 5.4pt;\"><span style=\"color: rgb(156, 0, 6);\">-1</span></td>
<td valign=\"bottom\" style=\" border-style: none solid none none; border-right-width: 1pt; border-right-color: windowtext; background-color: rgb(255, 199, 206); padding: 0cm 5.4pt;\"><span style=\"color: rgb(156, 0, 6);\">201</span></td>
<td valign=\"bottom\" style=\" padding: 0cm 5.4pt;\"></td>
<td valign=\"bottom\" style=\" padding: 0cm 5.4pt;\"></td>
<td valign=\"bottom\" style=\" border-style: none solid solid; border-left-width: 1pt; border-left-color: windowtext; border-bottom-width: 1pt; border-bottom-color: gray; border-right-width: 1pt; border-right-color: gray; background-color: rgb(242, 242, 242); padding: 0cm 5.4pt;\"><div>
<b>country</b>
</div></td>
<td valign=\"bottom\" style=\" border-style: none solid solid none; border-bottom-width: 1pt; border-bottom-color: gray; border-right-width: 1pt; border-right-color: gray; background-color: rgb(242, 242, 242); padding: 0cm 5.4pt;\"><div>Target (gross)</div></td>
<td valign=\"bottom\" style=\" border-style: none solid solid none; border-bottom-width: 1pt; border-bottom-color: gray; border-right-width: 1pt; border-right-color: gray; background-color: rgb(242, 242, 242); padding: 0cm 5.4pt;\"><div>Remaining Recruits</div></td>
<td valign=\"bottom\" style=\" border-style: none solid solid none; border-bottom-width: 1pt; border-bottom-color: gray; border-right-width: 1pt; border-right-color: windowtext; background-color: rgb(242, 242, 242); padding: 0cm 5.4pt;\"><div>Total Recruits</div></td>
</tr>"
assert_equal(result, html.html2html_strict)
html = "<div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div>Dear Bob<span style=\"line-height: 23.8px;\">:</span><span style=\"color: rgb(255, 255, 255); line-height: 1.7;\">Mr/Mrs</span></div><div><br></div><div><span style=\"line-height: 1.7;\">We&nbsp;are&nbsp;one&nbsp;of&nbsp;the&nbsp;leading&nbsp;manufacturer&nbsp;and&nbsp;supplier&nbsp;of&nbsp;</span>conduits and cars since 3000.</div><div><br></div><div>Could you inform me the specification you need?</div><div><br></div><div>May I sent you our products catalogues for your reference?</div><div><br></div><div><img src=\"cid:5cb2783c$1$15ae9b384c8$Coremail$zhanabcdzhao$example.com\" orgwidth=\"1101\" orgheight=\"637\" data-image=\"1\" style=\"width: 722.7px; height: 418px; border: none;\"></div><div>Best regards!</div><div><br></div><div><b style=\"line-height: 1.7;\"><i><u><span lang=\"EL\" style=\"font-size:11.0pt;font-family:&quot;Calibri&quot;,sans-serif;color:#17365D;\nmso-ansi-language:EL\">Welcome to our booth B11/1 Hall 13 during SOMEWHERE\n9999.</span></u></i></b></div><div style=\"position:relative;zoom:1\"><div>Bob Smith</div><div><div>Exp. &amp; Imp.</div><div>Town Example Electric Co., Ltd.</div><div>Tel: 0000-11-12345678 (Ext-220) &nbsp;Fax: 0000-11-12345678&nbsp;</div><div>Room1234, NO. 638, Smith Road, Town, 200000, Somewhere</div><div>Web: www.example.com</div></div><div style=\"clear:both\"></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>"
result = "<div>
<div>Dear Bob:Mr/Mrs</div><div> </div><div>We are one of the leading manufacturer and supplier of conduits and cars since 3000.</div><div> </div><div>Could you inform me the specification you need?</div><div> </div><div>May I sent you our products catalogues for your reference?</div><div> </div><div><img src=\"cid:5cb2783c%241%2415ae9b384c8%24Coremail%24zhanabcdzhao%24example.com\" style=\"width: 722.7px; height: 418px;\"></div><div>Best regards!</div><div> </div><div><b><i><u>Welcome to our booth B11/1 Hall 13 during SOMEWHERE 9999.</u></i></b></div><div>
<div>Bob Smith</div><div>
<div>Exp. &amp; Imp.</div><div>Town Example Electric Co., Ltd.</div><div>Tel: 0000-11-12345678 (Ext-220) Fax: 0000-11-12345678</div><div>Room1234, NO. 638, Smith Road, Town, 200000, Somewhere</div><div>Web: <a href=\"http://www.example.com\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://www.example.com</a>
</div></div></div></div>"
assert_equal(result, html.html2html_strict)
html = '<li><a style="font-size:15px; font-family:Arial;color:#0f7246" class="text_link" href="http://business-catalogs.example.com/ODtpbGs5MWIzbjUyYzExLTA4Yy06Mmg7N3AvL3R0bmFvY3B0LXlhbW9sc2Nhb3NnYy5lL3RpbXJlZi9lbS9ycnJuaWFpZXMsdGxnY25pLGUsdXJ0b3NVTGVpNWZ8fGZh"><span style="color: rgb(0, 0, 0);">Luxemburg</span></a></li>'
result = '<li>Luxemburg (<a href="http://business-catalogs.example.com/ODtpbGs5MWIzbjUyYzExLTA4Yy06Mmg7N3AvL3R0bmFvY3B0LXlhbW9sc2Nhb3NnYy5lL3RpbXJlZi9lbS9ycnJuaWFpZXMsdGxnY25pLGUsdXJ0b3NVTGVpNWZ8fGZh" rel="nofollow noreferrer noopener" target="_blank">http://business-catalogs.example.com/ODtpbGs5MWIzbjUyYzExLTA4Yy06Mmg7N3AvL3R0bmFvY3B0LXlhbW9sc2Nhb3NnYy5lL3RpbXJlZi9lbS9ycnJuaWFpZXMsdGxnY25pLGUsdXJ0b3NVTGVpNWZ8fGZh</a>)</li>'
html.html2html_strict
assert_equal(result, html.html2html_strict)
end
test 'inline attachment replace' do
@ -1102,8 +1116,7 @@ christian.schaefer@example.com'
result = '<div>
<span class="js-signatureMarker"></span><p><b>Von: </b>Johanna Kiefer via Znuny Projects &lt;projects@example.com&gt;<br>
<b>Organisation: </b>Znuny Group<br>
<b>Datum: </b>Montag, 6. März 2017 um 13:32<br></p>
</div>'
<b>Datum: </b>Montag, 6. März 2017 um 13:32<br></p></div>'
assert_equal(result, html.html2html_strict)
html = '<div><br>
@ -1112,22 +1125,18 @@ christian.schaefer@example.com'
&nbsp;</font><font size=1 face="sans-serif">Hotel &lt;info@example.com&gt;</font>
<br><font size=1 color=#5f5f5f face="sans-serif">An: &nbsp; &nbsp; &nbsp;
&nbsp;</font></div>'
result = '<span class="js-signatureMarker"></span><div><br>Von: Hotel &lt;info@example.com&gt;
<br>An:
</div>'
result = '<span class="js-signatureMarker"></span><div><br>Von: Hotel &lt;info@example.com&gt; <br>An: </div>'
assert_equal(result, html.html2html_strict)
html = '<br class=""><div><blockquote type="cite" class=""><div class="">On 04 Mar 2017, at 14:47, Oliver Ruhm &lt;<a href="mailto:oliver@example.com" class="">oliver@example.com</a>&gt; wrote:</div><br class="Apple-interchange-newline">'
result = '<div><span class="js-signatureMarker"></span><blockquote type="cite">
<div>On 04 Mar 2017, at 14:47, Oliver Ruhm &lt;oliver@example.com&gt; wrote:</div>
<br>
<div>On 04 Mar 2017, at 14:47, Oliver Ruhm &lt;oliver@example.com&gt; wrote:</div><br>
</blockquote></div>'
assert_equal(result, html.html2html_strict)
html = '<br class=""><div><blockquote type="cite" class=""><div class="">some note</div><br class="Apple-interchange-newline">'
result = '<div><blockquote type="cite">
<div>some note</div>
<br>
<div>some note</div><br>
</blockquote></div>'
assert_equal(result, html.html2html_strict)
@ -1154,40 +1163,9 @@ christian.schaefer@example.com'
<br>
</div><blockquote type="cite">
<div>Dear Mr. Smith,<br>
</div>
</blockquote>'
</div></blockquote>'
assert_equal(result, html.html2html_strict)
html = "<div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div style=\"line-height:1.7;color:#000000;font-size:14px;font-family:Arial\"><div>Dear Bob<span style=\"line-height: 23.8px;\">:</span><span style=\"color: rgb(255, 255, 255); line-height: 1.7;\">Mr/Mrs</span></div><div><br></div><div><span style=\"line-height: 1.7;\">We&nbsp;are&nbsp;one&nbsp;of&nbsp;the&nbsp;leading&nbsp;manufacturer&nbsp;and&nbsp;supplier&nbsp;of&nbsp;</span>conduits and cars since 3000.</div><div><br></div><div>Could you inform me the specification you need?</div><div><br></div><div>May I sent you our products catalogues for your reference?</div><div><br></div><div><img src=\"cid:5cb2783c$1$15ae9b384c8$Coremail$zhanabcdzhao$example.com\" orgwidth=\"1101\" orgheight=\"637\" data-image=\"1\" style=\"width: 722.7px; height: 418px; border: none;\"></div><div>Best regards!</div><div><br></div><div><b style=\"line-height: 1.7;\"><i><u><span lang=\"EL\" style=\"font-size:11.0pt;font-family:&quot;Calibri&quot;,sans-serif;color:#17365D;\nmso-ansi-language:EL\">Welcome to our booth B11/1 Hall 13 during SOMEWHERE\n9999.</span></u></i></b></div><div style=\"position:relative;zoom:1\"><div>Bob Smith</div><div><div>Exp. &amp; Imp.</div><div>Town Example Electric Co., Ltd.</div><div>Tel: 0000-11-12345678 (Ext-220) &nbsp;Fax: 0000-11-12345678&nbsp;</div><div>Room1234, NO. 638, Smith Road, Town, 200000, Somewhere</div><div>Web: www.example.com</div></div><div style=\"clear:both\"></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>"
result = '<div>
<div>Dear Bob:Mr/Mrs</div>
<div> </div>
<div>We are one of the leading manufacturer and supplier of conduits and cars since 3000.</div>
<div> </div>
<div>Could you inform me the specification you need?</div>
<div> </div>
<div>May I sent you our products catalogues for your reference?</div>
<div> </div>
<div><img src="cid:5cb2783c%241%2415ae9b384c8%24Coremail%24zhanabcdzhao%24example.com" style="width: 722.7px; height: 418px;"></div>
<div>Best regards!</div>
<div> </div>
<div><b><i><u>Welcome to our booth B11/1 Hall 13 during SOMEWHERE 9999.</u></i></b></div>
<div>
<div>Bob Smith</div>
<div>
<div>Exp. &amp; Imp.</div>
<div>Town Example Electric Co., Ltd.</div>
<div>Tel: 0000-11-12345678 (Ext-220) Fax: 0000-11-12345678</div>
<div>Room1234, NO. 638, Smith Road, Town, 200000, Somewhere</div>
<div>Web: <a href="http://www.example.com" rel="nofollow noreferrer noopener" target="_blank">http://www.example.com</a>
</div>
</div>
<div></div>
</div>
</div>'
assert_equal(result, html.html2html_strict)
end
end

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -46,22 +46,22 @@ class HtmlSanitizerTest < ActiveSupport::TestCase
assert_equal(HtmlSanitizer.strict('<IFRAME SRC="javascript:alert(\'XSS\');"></IFRAME>'), '')
assert_equal(HtmlSanitizer.strict('<TABLE><TD BACKGROUND="javascript:alert(\'XSS\')">'), '<table><td></td></table>')
assert_equal(HtmlSanitizer.strict('<DIV STYLE="background-image: url(javascript:alert(\'XSS\'), \'\')">'), '<div></div>')
assert_equal(HtmlSanitizer.strict('<a href="/some/path">test</a>'), '<a href="/some/path">test</a>')
assert_equal(HtmlSanitizer.strict('<a href="https://some/path">test</a>'), '<a href="https://some/path" rel="nofollow noreferrer noopener" target="_blank">test</a>')
assert_equal(HtmlSanitizer.strict('<a href="https://some/path">test</a>', true), 'https://some/path (<a href="http://test" rel="nofollow noreferrer noopener" target="_blank">test</a>)')
assert_equal(HtmlSanitizer.strict('<a href="/some/path">test</a>'), 'test (<a href="/some/path">/some/path</a>)')
assert_equal(HtmlSanitizer.strict('<a href="https://some/path">test</a>'), 'test (<a href="https://some/path" rel="nofollow noreferrer noopener" target="_blank">https://some/path</a>)')
assert_equal(HtmlSanitizer.strict('<a href="https://some/path">test</a>', true), 'test (<a href="https://some/path" rel="nofollow noreferrer noopener" target="_blank">https://some/path</a>)')
assert_equal(HtmlSanitizer.strict('<XML ID="xss"><I><B><IMG SRC="javas<!-- -->cript:alert(\'XSS\')"></B></I></XML>'), '<i><b></b></i>')
assert_equal(HtmlSanitizer.strict('<IMG SRC="javas<!-- -->cript:alert(\'XSS\')">'), '')
assert_equal(HtmlSanitizer.strict(' <HEAD><META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=UTF-7"> </HEAD>+ADw-SCRIPT+AD4-alert(\'XSS\');+ADw-/SCRIPT+AD4-'), ' +ADw-SCRIPT+AD4-alert(\'XSS\');+ADw-/SCRIPT+AD4-')
assert_equal(HtmlSanitizer.strict('<SCRIPT a=">" SRC="httx://xss.rocks/xss.js"></SCRIPT>'), '')
assert_equal(HtmlSanitizer.strict('<A HREF="h
tt p://6 6.000146.0x7.147/">XSS</A>'), '<a href="http://66.000146.0x7.147/" rel="nofollow noreferrer noopener" target="_blank">XSS</a>')
tt p://6 6.000146.0x7.147/">XSS</A>'), 'XSS (<a href="http://66.000146.0x7.147/" rel="nofollow noreferrer noopener" target="_blank">http://66.000146.0x7.147/</a>)')
assert_equal(HtmlSanitizer.strict('<A HREF="h
tt p://6 6.000146.0x7.147/">XSS</A>', true), 'h%0Att%20%20p://6%206.000146.0x7.147/ (<a href="http://XSS" rel="nofollow noreferrer noopener" target="_blank">XSS</a>)')
assert_equal(HtmlSanitizer.strict('<A HREF="//www.google.com/">XSS</A>'), '<a href="//www.google.com/" rel="nofollow noreferrer noopener" target="_blank">XSS</a>')
assert_equal(HtmlSanitizer.strict('<A HREF="//www.google.com/">XSS</A>', true), '//www.google.com/ (<a href="http://XSS" rel="nofollow noreferrer noopener" target="_blank">XSS</a>)')
tt p://6 6.000146.0x7.147/">XSS</A>', true), 'XSS (<a href="http://66.000146.0x7.147/" rel="nofollow noreferrer noopener" target="_blank">http://66.000146.0x7.147/</a>)')
assert_equal(HtmlSanitizer.strict('<A HREF="//www.google.com/">XSS</A>'), 'XSS (<a href="//www.google.com/" rel="nofollow noreferrer noopener" target="_blank">//www.google.com/</a>)')
assert_equal(HtmlSanitizer.strict('<A HREF="//www.google.com/">XSS</A>', true), 'XSS (<a href="//www.google.com/" rel="nofollow noreferrer noopener" target="_blank">//www.google.com/</a>)')
assert_equal(HtmlSanitizer.strict('<form id="test"></form><button form="test" formaction="javascript:alert(1)">X</button>'), 'X')
assert_equal(HtmlSanitizer.strict('<maction actiontype="statusline#http://google.com" xlink:href="javascript:alert(2)">CLICKME</maction>'), 'CLICKME')
assert_equal(HtmlSanitizer.strict('<a xlink:href="javascript:alert(2)">CLICKME</a>'), '<a>CLICKME</a>')
assert_equal(HtmlSanitizer.strict('<a xlink:href="javascript:alert(2)">CLICKME</a>'), 'CLICKME')
assert_equal(HtmlSanitizer.strict('<a xlink:href="javascript:alert(2)">CLICKME</a>', true), 'CLICKME')
assert_equal(HtmlSanitizer.strict('<!--<img src="--><img src=x onerror=alert(1)//">'), '<img src="x">')
assert_equal(HtmlSanitizer.strict('<![><img src="]><img src=x onerror=alert(1)//">'), '<img src="%5D&gt;&lt;img%20src=x%20onerror=alert(1)//">')
@ -70,10 +70,10 @@ tt p://6 6.000146.0x7.147/">XSS</A>', true), 'h%0Att%20%20p://6%206.000146.0x7.
assert_equal(HtmlSanitizer.strict('<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>'), '')
assert_equal(HtmlSanitizer.strict('<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></embed>'), '')
assert_equal(HtmlSanitizer.strict('<img[a][b]src=x[d]onerror[c]=[e]"alert(1)">'), '<img>')
assert_equal(HtmlSanitizer.strict('<a href="[a]java[b]script[c]:alert(1)">XXX</a>'), '<a>XXX</a>')
assert_equal(HtmlSanitizer.strict('<a href="[a]java[b]script[c]:alert(1)">XXX</a>'), 'XXX')
assert_equal(HtmlSanitizer.strict('<a href="[a]java[b]script[c]:alert(1)">XXX</a>', true), 'XXX')
assert_equal(HtmlSanitizer.strict('<svg xmlns="http://www.w3.org/2000/svg"><script>alert(1)</script></svg>'), 'alert(1)')
assert_equal(HtmlSanitizer.strict('<a style="position:fixed;top:0;left:0;width: 260px;height:100vh;background-color:red;display: block;" href="http://example.com"></a>'), '<a href="http://example.com" rel="nofollow noreferrer noopener" target="_blank"></a>')
assert_equal(HtmlSanitizer.strict('<a style="position:fixed;top:0;left:0;width: 260px;height:100vh;background-color:red;display: block;" href="http://example.com"></a>'), '<a href="http://example.com" rel="nofollow noreferrer noopener" target="_blank">http://example.com</a>')
assert_equal(HtmlSanitizer.strict('<a style="position:fixed;top:0;left:0;width: 260px;height:100vh;background-color:red;display: block;" href="http://example.com"></a>', true), '<a href="http://example.com" rel="nofollow noreferrer noopener" target="_blank">http://example.com</a>')
end

View file

@ -66,7 +66,7 @@ class TicketXssTest < ActiveSupport::TestCase
)
assert_equal("please tell me this doesn't work: <table>ada<tr></tr>
</table><div></div><div>
<a>LINK</a><a href=\"http://lalal.de\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">aa</a>ABC</div>", article3.body, 'article3.body verify - inbound')
LINKaa (<a href=\"http://lalal.de\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">http://lalal.de</a>)ABC</div>", article3.body, 'article3.body verify - inbound')
article4 = Ticket::Article.create(
ticket_id: ticket.id,
@ -150,7 +150,7 @@ class TicketXssTest < ActiveSupport::TestCase
updated_by_id: 1,
created_by_id: 1,
)
assert_equal('some message article helper test1 <a href="#">abc</a> <a href="https://example.com" rel="nofollow noreferrer noopener" target="_blank">123</a>123', article8.body, 'article8.body verify - inbound')
assert_equal('some message article helper test1 abc (<a href="#">#</a>) 123 (<a href="https://example.com" rel="nofollow noreferrer noopener" target="_blank">https://example.com</a>)123', article8.body, 'article8.body verify - inbound')
end