Files
danbooru/app/logical/note_sanitizer.rb

104 lines
3.0 KiB
Ruby

# frozen_string_literal: true
# Sanitizes the HTML used in notes. Only safe HTML tags, HTML attributes, and
# CSS properties are allowed.
module NoteSanitizer
ALLOWED_ELEMENTS = %w[
code center tn h1 h2 h3 h4 h5 h6 a span div blockquote br p ul li ol em
strong small big b i font u s pre ruby rb rt rp rtc sub sup hr wbr
]
ALLOWED_ATTRIBUTES = {
:all => %w[style title],
"a" => %w[href],
"span" => %w[class],
"div" => %w[class align],
"p" => %w[class align],
"font" => %w[color size]
}
ALLOWED_PROPERTIES = %w[
align-items
background-clip -webkit-background-clip
background background-color
border border-color border-image border-radius border-style border-width
border-bottom border-bottom-color border-bottom-left-radius border-bottom-right-radius border-bottom-style border-bottom-width
border-left border-left-color border-left-style border-left-width
border-right border-right-color border-right-style border-right-width
border-top border-top-color border-top-left-radious border-top-right-radius border-top-style border-top-width
bottom left right top
box-shadow
color
display
filter
float
font font-family font-size font-size-adjust font-style font-variant font-weight
height width
justify-content
letter-spacing
line-height
margin margin-bottom margin-left margin-right margin-top
opacity
padding padding-bottom padding-left padding-right padding-top
perspective perspective-origin
position
text-align
text-decoration
text-indent
text-shadow
transform transform-origin
-webkit-text-fill-color
-webkit-text-stroke -webkit-text-stroke-color -webkit-text-stroke-width
white-space
word-break
word-spacing
word-wrap overflow-wrap
writing-mode
vertical-align
]
# Sanitize a string of HTML.
# @param text [String] the HTML to sanitize
# @return [String] the sanitized HTML
def self.sanitize(text)
text.gsub!(/<( |-|3|:|>|\Z)/, "&lt;\\1")
Sanitize.clean(
text,
:elements => ALLOWED_ELEMENTS,
:attributes => ALLOWED_ATTRIBUTES,
:add_attributes => {
"a" => { "rel" => "external noreferrer nofollow" }
},
:protocols => {
"a" => {
"href" => ["http", "https", :relative]
}
},
:css => {
allow_comments: false,
allow_hacks: false,
at_rules: [],
protocols: [],
properties: ALLOWED_PROPERTIES
},
:transformers => method(:relativize_links)
)
end
# Convert absolute Danbooru links inside notes to relative links.
# https://danbooru.donmai.us/posts/1 is converted to /posts/1.
def self.relativize_links(node:, **env)
return unless node.name == "a" && node["href"].present?
url = Addressable::URI.heuristic_parse(node["href"]).normalize
if url.authority == Danbooru.config.hostname
url.site = nil
node["href"] = url.to_s
end
rescue Addressable::URI::InvalidURIError
# do nothing for invalid urls
end
end