2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2025-09-05 08:59:27 +08:00

FEATURE: escape HTML when cooking plaintext emails

This commit is contained in:
Gerhard Schlager 2017-11-15 16:39:29 +01:00
parent cef64e8f03
commit 9207dee69a
5 changed files with 201 additions and 47 deletions

View file

@ -1,13 +1,19 @@
# A very simple formatter for imported emails
require_dependency 'pretty_text'
# A very simple formatter for imported emails
class EmailCook
def self.url_regexp
/((?:https?:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.])(?:[^\s()<>]+|\([^\s()<>]+\))+(?:\([^\s()<>]+\)|[^`!()\[\]{};:'".,<>?«»“”‘’\s]))/
@url_regexp ||= /((?:https?:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.])(?:[^\s()<>]+|\([^\s()<>]+\))+(?:\([^\s()<>]+\)|[^`!()\[\]{};:'".,<>?«»“”‘’\s]))/
end
def self.raw_regexp
@raw_regexp ||= /^\[plaintext\]$\n(.*)\n^\[\/plaintext\]$(?:\s^\[attachments\]$\n(.*)\n^\[\/attachments\]$)?(?:\s^\[elided\]$\n(.*)\n^\[\/elided\]$)?/m
end
def initialize(raw)
@raw = raw
@body, @attachment_html, @elided = @raw.scan(EmailCook.raw_regexp).first
end
def add_quote(result, buffer)
@ -17,53 +23,62 @@ class EmailCook
end
end
def link_string!(str)
str.scan(EmailCook.url_regexp).each do |m|
def link_string!(line, unescaped_line)
unescaped_line = unescaped_line.strip
unescaped_line.scan(EmailCook.url_regexp).each do |m|
url = m[0]
if str.strip == url
if unescaped_line == url
# this could be oneboxed
val = %|<a href="#{url}" class="onebox" target="_blank">#{url}</a>|
else
val = %|<a href="#{url}">#{url}</a>|
end
str.gsub!(url, val)
line.gsub!(url, val)
end
end
def cook
def htmlify(text)
result = ""
in_text = false
in_quote = false
quote_buffer = ""
@raw.each_line do |l|
text.each_line do |line|
if l =~ /^\s*>/
if line =~ /^\s*>/
in_quote = true
link_string!(l)
quote_buffer << l.sub(/^[\s>]*/, '') << "<br>"
line.sub!(/^[\s>]*/, '')
unescaped_line = line
line = CGI.escapeHTML(line)
link_string!(line, unescaped_line)
quote_buffer << line << "<br>"
elsif in_quote
add_quote(result, quote_buffer)
quote_buffer = ""
in_quote = false
else
sz = l.size
sz = line.size
link_string!(l)
result << l
unescaped_line = line
line = CGI.escapeHTML(line)
link_string!(line, unescaped_line)
if sz < 60
result << "<br>"
if in_text
if in_text && line == "\n"
result << "<br>"
end
result << line
result << "<br>"
in_text = false
else
result << line
in_text = true
end
end
@ -77,4 +92,14 @@ class EmailCook
result
end
def cook(opts = {})
# fallback to PrettyText if we failed to detect a body
return PrettyText.cook(@raw, opts) if @body.nil?
result = htmlify(@body)
result << "\n<br>" << @attachment_html if @attachment_html.present?
result << "\n<br><br>" << Email::Receiver.elided_html(htmlify(@elided)) if @elided.present?
result
end
end