Skip to content
Snippets Groups Projects
Commit 40823adc authored by Andrew Lee's avatar Andrew Lee
Browse files

Merge branch 'collabora' into 'collabora'

obs-api: embed sanitize-4.0.0 to fix runtime issue

See merge request !1
parents 3a1fe003 bb9d59ac
No related branches found
No related tags found
1 merge request!1obs-api: embed sanitize-4.0.0 to fix runtime issue
Showing
with 1761 additions and 6 deletions
open-build-service (2.7.1-10co6) tools; urgency=medium
* Embed sanitize 4.0.0 ruby gem to fix breakeage. (T7297)
- add obs-api runtime depends on ruby-nokogumbo and ruby-crass.
-- Héctor Orón Martínez <hector.oron@collabora.co.uk> Thu, 19 Oct 2017 16:27:27 +0200
open-build-service (2.7.1-10co5) tools; urgency=medium open-build-service (2.7.1-10co5) tools; urgency=medium
* Remove stray debug print from backend-Handle-ERROR_WANT_-READ-WRITE-from-ssl-reads.patch * Remove stray debug print from backend-Handle-ERROR_WANT_-READ-WRITE-from-ssl-reads.patch
......
...@@ -161,6 +161,7 @@ Depends: apache2, ...@@ -161,6 +161,7 @@ Depends: apache2,
ruby-codemirror-rails, ruby-codemirror-rails,
ruby-coderay, ruby-coderay,
ruby-crack, ruby-crack,
ruby-crass,
ruby-cssmin, ruby-cssmin,
ruby-daemons, ruby-daemons,
ruby-dalli, ruby-dalli,
...@@ -189,6 +190,7 @@ Depends: apache2, ...@@ -189,6 +190,7 @@ Depends: apache2,
ruby-mime-types, ruby-mime-types,
ruby-mysql2, ruby-mysql2,
ruby-nokogiri, ruby-nokogiri,
ruby-nokogumbo,
ruby-parser, ruby-parser,
ruby-pkg-config (>= 1.1.6), ruby-pkg-config (>= 1.1.6),
ruby-pundit, ruby-pundit,
......
# encoding: utf-8
require 'nokogumbo'
require 'set'
require_relative 'sanitize/version'
require_relative 'sanitize/config'
require_relative 'sanitize/config/default'
require_relative 'sanitize/config/restricted'
require_relative 'sanitize/config/basic'
require_relative 'sanitize/config/relaxed'
require_relative 'sanitize/css'
require_relative 'sanitize/transformers/clean_cdata'
require_relative 'sanitize/transformers/clean_comment'
require_relative 'sanitize/transformers/clean_css'
require_relative 'sanitize/transformers/clean_doctype'
require_relative 'sanitize/transformers/clean_element'
class Sanitize
attr_reader :config
# Matches an attribute value that could be treated by a browser as a URL
# with a protocol prefix, such as "http:" or "javascript:". Any string of zero
# or more characters followed by a colon is considered a match, even if the
# colon is encoded as an entity and even if it's an incomplete entity (which
# IE6 and Opera will still parse).
REGEX_PROTOCOL = /\A\s*([^\/#]*?)(?:\:|&#0*58|&#x0*3a)/i
# Matches Unicode characters that should be stripped from HTML before passing
# it to the parser.
#
# http://www.w3.org/TR/unicode-xml/#Charlist
REGEX_UNSUITABLE_CHARS = /[\u0340\u0341\u17a3\u17d3\u2028\u2029\u202a-\u202e\u206a-\u206f\ufff9-\ufffb\ufeff\ufffc\u{1d173}-\u{1d17a}\u{e0000}-\u{e007f}]/u
#--
# Class Methods
#++
# Returns a sanitized copy of the given full _html_ document, using the
# settings in _config_ if specified.
#
# When sanitizing a document, the `<html>` element must be whitelisted or an
# error will be raised. If this is undesirable, you should probably use
# {#fragment} instead.
def self.document(html, config = {})
Sanitize.new(config).document(html)
end
# Returns a sanitized copy of the given _html_ fragment, using the settings in
# _config_ if specified.
def self.fragment(html, config = {})
Sanitize.new(config).fragment(html)
end
# Sanitizes the given `Nokogiri::XML::Node` instance and all its children.
def self.node!(node, config = {})
Sanitize.new(config).node!(node)
end
# Aliases for pre-3.0.0 backcompat.
class << Sanitize
# @deprecated Use {.document} instead.
alias_method :clean_document, :document
# @deprecated Use {.fragment} instead.
alias_method :clean, :fragment
# @deprecated Use {.node!} instead.
alias_method :clean_node!, :node!
end
#--
# Instance Methods
#++
# Returns a new Sanitize object initialized with the settings in _config_.
def initialize(config = {})
@config = Config.merge(Config::DEFAULT, config)
@transformers = Array(@config[:transformers].dup)
# Default transformers always run at the end of the chain, after any custom
# transformers.
@transformers << Transformers::CleanComment unless @config[:allow_comments]
@transformers << Transformers::CleanDoctype unless @config[:allow_doctype]
if @config[:elements].include?('style')
scss = Sanitize::CSS.new(config)
@transformers << Transformers::CSS::CleanElement.new(scss)
end
if @config[:attributes].values.any? {|attr| attr.include?('style') }
scss ||= Sanitize::CSS.new(config)
@transformers << Transformers::CSS::CleanAttribute.new(scss)
end
@transformers <<
Transformers::CleanCDATA <<
Transformers::CleanElement.new(@config)
end
# Returns a sanitized copy of the given _html_ document.
#
# When sanitizing a document, the `<html>` element must be whitelisted or an
# error will be raised. If this is undesirable, you should probably use
# {#fragment} instead.
def document(html)
return '' unless html
doc = Nokogiri::HTML5.parse(preprocess(html))
node!(doc)
to_html(doc)
end
# @deprecated Use {#document} instead.
alias_method :clean_document, :document
# Returns a sanitized copy of the given _html_ fragment.
def fragment(html)
return '' unless html
html = preprocess(html)
doc = Nokogiri::HTML5.parse("<html><body>#{html}")
# Hack to allow fragments containing <body>. Borrowed from
# Nokogiri::HTML::DocumentFragment.
if html =~ /\A<body(?:\s|>)/i
path = '/html/body'
else
path = '/html/body/node()'
end
frag = doc.fragment
frag << doc.xpath(path)
node!(frag)
to_html(frag)
end
# @deprecated Use {#fragment} instead.
alias_method :clean, :fragment
# Sanitizes the given `Nokogiri::XML::Node` and all its children, modifying it
# in place.
#
# If _node_ is a `Nokogiri::XML::Document`, the `<html>` element must be
# whitelisted or an error will be raised.
def node!(node)
raise ArgumentError unless node.is_a?(Nokogiri::XML::Node)
if node.is_a?(Nokogiri::XML::Document)
unless @config[:elements].include?('html')
raise Error, 'When sanitizing a document, "<html>" must be whitelisted.'
end
end
node_whitelist = Set.new
traverse(node) do |n|
transform_node!(n, node_whitelist)
end
node
end
# @deprecated Use {#node!} instead.
alias_method :clean_node!, :node!
private
# Preprocesses HTML before parsing to remove undesirable Unicode chars.
def preprocess(html)
html = html.to_s.dup
unless html.encoding.name == 'UTF-8'
html.encode!('UTF-8',
:invalid => :replace,
:undef => :replace)
end
html.gsub!(REGEX_UNSUITABLE_CHARS, '')
html
end
def to_html(node)
replace_meta = false
# Hacky workaround for a libxml2 bug that adds an undesired Content-Type
# meta tag to all serialized HTML documents.
#
# https://github.com/sparklemotion/nokogiri/issues/1008
if node.type == Nokogiri::XML::Node::DOCUMENT_NODE ||
node.type == Nokogiri::XML::Node::HTML_DOCUMENT_NODE
regex_meta = %r|(<html[^>]*>\s*<head[^>]*>\s*)<meta http-equiv="Content-Type" content="text/html; charset=utf-8">|i
# Only replace the content-type meta tag if <meta> isn't whitelisted or
# the original document didn't actually include a content-type meta tag.
replace_meta = !@config[:elements].include?('meta') ||
node.xpath('/html/head/meta[@http-equiv]').none? do |meta|
meta['http-equiv'].downcase == 'content-type'
end
end
so = Nokogiri::XML::Node::SaveOptions
# Serialize to HTML without any formatting to prevent Nokogiri from adding
# newlines after certain tags.
html = node.to_html(
:encoding => 'utf-8',
:indent => 0,
:save_with => so::NO_DECLARATION | so::NO_EMPTY_TAGS | so::AS_HTML
)
html.gsub!(regex_meta, '\1') if replace_meta
html
end
def transform_node!(node, node_whitelist)
@transformers.each do |transformer|
result = transformer.call(
:config => @config,
:is_whitelisted => node_whitelist.include?(node),
:node => node,
:node_name => node.name.downcase,
:node_whitelist => node_whitelist
)
if result.is_a?(Hash) && result[:node_whitelist].respond_to?(:each)
node_whitelist.merge(result[:node_whitelist])
end
end
node
end
# Performs top-down traversal of the given node, operating first on the node
# itself, then traversing each child (if any) in order.
def traverse(node, &block)
yield node
child = node.child
while child do
prev = child.previous_sibling
traverse(child, &block)
if child.parent == node
child = child.next_sibling
else
# The child was unlinked or reparented, so traverse the previous node's
# next sibling, or the parent's first child if there is no previous
# node.
child = prev ? prev.next_sibling : node.child
end
end
end
class Error < StandardError; end
end
# encoding: utf-8
require 'set'
class Sanitize
module Config
# Deeply freezes and returns the given configuration Hash.
def self.freeze_config(config)
if Hash === config
config.each_value {|c| freeze_config(c) }
elsif Array === config || Set === config
config.each {|c| freeze_config(c) }
end
config.freeze
end
# Returns a new Hash containing the result of deeply merging *other_config*
# into *config*. Does not modify *config* or *other_config*.
#
# This is the safest way to use a built-in Sanitize config as the basis for
# your own custom config.
def self.merge(config, other_config = {})
raise ArgumentError, 'config must be a Hash' unless Hash === config
raise ArgumentError, 'other_config must be a Hash' unless Hash === other_config
merged = {}
keys = Set.new(config.keys + other_config.keys)
keys.each do |key|
oldval = config[key]
if other_config.has_key?(key)
newval = other_config[key]
if Hash === oldval && Hash === newval
merged[key] = oldval.empty? ? newval.dup : merge(oldval, newval)
elsif Array === newval && key != :transformers
merged[key] = Set.new(newval)
else
merged[key] = can_dupe?(newval) ? newval.dup : newval
end
else
merged[key] = can_dupe?(oldval) ? oldval.dup : oldval
end
end
merged
end
# Returns `true` if `dup` may be safely called on _value_, `false`
# otherwise.
def self.can_dupe?(value)
!(true == value || false == value || value.nil? || Numeric === value || Symbol === value)
end
private_class_method :can_dupe?
end
end
# encoding: utf-8
class Sanitize
module Config
BASIC = freeze_config(
:elements => RESTRICTED[:elements] + %w[
a abbr blockquote br cite code dd dfn dl dt kbd li mark ol p pre q s
samp small strike sub sup time ul var
],
:attributes => {
'a' => %w[href],
'abbr' => %w[title],
'blockquote' => %w[cite],
'dfn' => %w[title],
'q' => %w[cite],
'time' => %w[datetime pubdate]
},
:add_attributes => {
'a' => {'rel' => 'nofollow'}
},
:protocols => {
'a' => {'href' => ['ftp', 'http', 'https', 'mailto', :relative]},
'blockquote' => {'cite' => ['http', 'https', :relative]},
'q' => {'cite' => ['http', 'https', :relative]}
}
)
end
end
# encoding: utf-8
class Sanitize
module Config
DEFAULT = freeze_config(
# HTML attributes to add to specific elements. By default, no attributes
# are added.
:add_attributes => {},
# Whether or not to allow HTML comments. Allowing comments is strongly
# discouraged, since IE allows script execution within conditional
# comments.
:allow_comments => false,
# Whether or not to allow well-formed HTML doctype declarations such as
# "<!DOCTYPE html>" when sanitizing a document. This setting is ignored
# when sanitizing fragments.
:allow_doctype => false,
# HTML attributes to allow in specific elements. By default, no attributes
# are allowed. Use the symbol :data to indicate that arbitrary HTML5
# data-* attributes should be allowed.
:attributes => {},
# CSS sanitization settings.
:css => {
# Whether or not to allow CSS comments.
:allow_comments => false,
# Whether or not to allow browser compatibility hacks such as the IE *
# and _ hacks. These are generally harmless, but technically result in
# invalid CSS.
:allow_hacks => false,
# CSS at-rules to allow that may not have associated blocks (e.g.
# "import").
#
# https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule
:at_rules => [],
# CSS at-rules to allow whose blocks may contain properties (e.g.
# "font-face").
:at_rules_with_properties => [],
# CSS at-rules to allow whose blocks may contain styles (e.g. "media").
:at_rules_with_styles => [],
# CSS properties to allow.
:properties => [],
# URL protocols to allow in CSS URLs.
:protocols => []
},
# HTML elements to allow. By default, no elements are allowed (which means
# that all HTML will be stripped).
:elements => [],
# URL handling protocols to allow in specific attributes. By default, no
# protocols are allowed. Use :relative in place of a protocol if you want
# to allow relative URLs sans protocol.
:protocols => {},
# If this is true, Sanitize will remove the contents of any filtered
# elements in addition to the elements themselves. By default, Sanitize
# leaves the safe parts of an element's contents behind when the element
# is removed.
#
# If this is an Array of element names, then only the contents of the
# specified elements (when filtered) will be removed, and the contents of
# all other filtered elements will be left behind.
:remove_contents => false,
# Transformers allow you to filter or alter nodes using custom logic. See
# README.md for details and examples.
:transformers => [],
# Elements which, when removed, should have their contents surrounded by
# values specified with `before` and `after` keys to preserve readability.
# For example, `foo<div>bar</div>baz` will become 'foo bar baz' when the
# <div> is removed.
:whitespace_elements => {
'address' => { :before => ' ', :after => ' ' },
'article' => { :before => ' ', :after => ' ' },
'aside' => { :before => ' ', :after => ' ' },
'blockquote' => { :before => ' ', :after => ' ' },
'br' => { :before => ' ', :after => ' ' },
'dd' => { :before => ' ', :after => ' ' },
'div' => { :before => ' ', :after => ' ' },
'dl' => { :before => ' ', :after => ' ' },
'dt' => { :before => ' ', :after => ' ' },
'footer' => { :before => ' ', :after => ' ' },
'h1' => { :before => ' ', :after => ' ' },
'h2' => { :before => ' ', :after => ' ' },
'h3' => { :before => ' ', :after => ' ' },
'h4' => { :before => ' ', :after => ' ' },
'h5' => { :before => ' ', :after => ' ' },
'h6' => { :before => ' ', :after => ' ' },
'header' => { :before => ' ', :after => ' ' },
'hgroup' => { :before => ' ', :after => ' ' },
'hr' => { :before => ' ', :after => ' ' },
'li' => { :before => ' ', :after => ' ' },
'nav' => { :before => ' ', :after => ' ' },
'ol' => { :before => ' ', :after => ' ' },
'p' => { :before => ' ', :after => ' ' },
'pre' => { :before => ' ', :after => ' ' },
'section' => { :before => ' ', :after => ' ' },
'ul' => { :before => ' ', :after => ' ' }
}
)
end
end
# encoding: utf-8
class Sanitize
module Config
RELAXED = freeze_config(
:elements => BASIC[:elements] + %w[
address article aside bdi bdo body caption col colgroup data del div
figcaption figure footer h1 h2 h3 h4 h5 h6 head header hgroup hr html
img ins main nav rp rt ruby section span style summary sup table tbody
td tfoot th thead title tr wbr
],
:allow_doctype => true,
:attributes => merge(BASIC[:attributes],
:all => %w[class dir hidden id lang style tabindex title translate],
'a' => %w[href hreflang name rel],
'col' => %w[span width],
'colgroup' => %w[span width],
'data' => %w[value],
'del' => %w[cite datetime],
'img' => %w[align alt border height src width],
'ins' => %w[cite datetime],
'li' => %w[value],
'ol' => %w[reversed start type],
'style' => %w[media scoped 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],
'ul' => %w[type]
),
:protocols => merge(BASIC[:protocols],
'del' => {'cite' => ['http', 'https', :relative]},
'img' => {'src' => ['http', 'https', :relative]},
'ins' => {'cite' => ['http', 'https', :relative]}
),
:css => {
:allow_comments => true,
:allow_hacks => true,
:at_rules_with_properties => %w[
bottom-center
bottom-left
bottom-left-corner
bottom-right
bottom-right-corner
font-face
left-bottom
left-middle
left-top
page
right-bottom
right-middle
right-top
top-center
top-left
top-left-corner
top-right
top-right-corner
],
:at_rules_with_styles => %w[
-moz-keyframes
-o-keyframes
-webkit-keyframes
document
keyframes
media
supports
],
:protocols => ['http', 'https', :relative],
:properties => %w[
-moz-appearance
-moz-background-inline-policy
-moz-box-sizing
-moz-column-count
-moz-column-fill
-moz-column-gap
-moz-column-rule
-moz-column-rule-color
-moz-column-rule-style
-moz-column-rule-width
-moz-column-width
-moz-font-feature-settings
-moz-font-language-override
-moz-hyphens
-moz-text-align-last
-moz-text-decoration-color
-moz-text-decoration-line
-moz-text-decoration-style
-moz-text-size-adjust
-ms-background-position-x
-ms-background-position-y
-ms-block-progression
-ms-content-zoom-chaining
-ms-content-zoom-limit
-ms-content-zoom-limit-max
-ms-content-zoom-limit-min
-ms-content-zoom-snap
-ms-content-zoom-snap-points
-ms-content-zoom-snap-type
-ms-content-zooming
-ms-filter
-ms-flex
-ms-flex-align
-ms-flex-direction
-ms-flex-order
-ms-flex-pack
-ms-flex-wrap
-ms-flow-from
-ms-flow-into
-ms-grid-column
-ms-grid-column-align
-ms-grid-column-span
-ms-grid-columns
-ms-grid-row
-ms-grid-row-align
-ms-grid-row-span
-ms-grid-rows
-ms-high-contrast-adjust
-ms-hyphenate-limit-chars
-ms-hyphenate-limit-lines
-ms-hyphenate-limit-zone
-ms-hyphens
-ms-ime-mode
-ms-interpolation-mode
-ms-layout-flow
-ms-layout-grid
-ms-layout-grid-char
-ms-layout-grid-line
-ms-layout-grid-mode
-ms-layout-grid-type
-ms-overflow-style
-ms-overflow-x
-ms-overflow-y
-ms-progress-appearance
-ms-scroll-chaining
-ms-scroll-limit
-ms-scroll-limit-x-max
-ms-scroll-limit-x-min
-ms-scroll-limit-y-max
-ms-scroll-limit-y-min
-ms-scroll-rails
-ms-scroll-snap-points-x
-ms-scroll-snap-points-y
-ms-scroll-snap-type
-ms-scroll-snap-x
-ms-scroll-snap-y
-ms-scroll-translation
-ms-scrollbar-arrow-color
-ms-scrollbar-base-color
-ms-scrollbar-darkshadow-color
-ms-scrollbar-face-color
-ms-scrollbar-highlight-color
-ms-scrollbar-shadow-color
-ms-scrollbar-track-color
-ms-text-align-last
-ms-text-autospace
-ms-text-justify
-ms-text-kashida-space
-ms-text-overflow
-ms-text-size-adjust
-ms-text-underline-position
-ms-touch-action
-ms-user-select
-ms-word-break
-ms-word-wrap
-ms-wrap-flow
-ms-wrap-margin
-ms-wrap-through
-ms-writing-mode
-ms-zoom
-webkit-align-content
-webkit-align-items
-webkit-align-self
-webkit-animation
-webkit-animation-delay
-webkit-animation-direction
-webkit-animation-duration
-webkit-animation-fill-mode
-webkit-animation-iteration-count
-webkit-animation-name
-webkit-animation-play-state
-webkit-animation-timing-function
-webkit-appearance
-webkit-backface-visibility
-webkit-background-blend-mode
-webkit-background-clip
-webkit-background-composite
-webkit-background-origin
-webkit-background-size
-webkit-blend-mode
-webkit-border-after
-webkit-border-after-color
-webkit-border-after-style
-webkit-border-after-width
-webkit-border-before
-webkit-border-before-color
-webkit-border-before-style
-webkit-border-before-width
-webkit-border-bottom-left-radius
-webkit-border-bottom-right-radius
-webkit-border-end
-webkit-border-end-color
-webkit-border-end-style
-webkit-border-end-width
-webkit-border-fit
-webkit-border-image
-webkit-border-radius
-webkit-border-start
-webkit-border-start-color
-webkit-border-start-style
-webkit-border-start-width
-webkit-border-top-left-radius
-webkit-border-top-right-radius
-webkit-box-align
-webkit-box-decoration-break
-webkit-box-flex
-webkit-box-flex-group
-webkit-box-lines
-webkit-box-ordinal-group
-webkit-box-orient
-webkit-box-pack
-webkit-box-reflect
-webkit-box-shadow
-webkit-box-sizing
-webkit-clip-path
-webkit-column-axis
-webkit-column-break-after
-webkit-column-break-before
-webkit-column-break-inside
-webkit-column-count
-webkit-column-gap
-webkit-column-progression
-webkit-column-rule
-webkit-column-rule-color
-webkit-column-rule-style
-webkit-column-rule-width
-webkit-column-span
-webkit-column-width
-webkit-columns
-webkit-filter
-webkit-flex
-webkit-flex-basis
-webkit-flex-direction
-webkit-flex-flow
-webkit-flex-grow
-webkit-flex-shrink
-webkit-flex-wrap
-webkit-flow-from
-webkit-flow-into
-webkit-font-size-delta
-webkit-grid-area
-webkit-grid-auto-columns
-webkit-grid-auto-flow
-webkit-grid-auto-rows
-webkit-grid-column
-webkit-grid-column-end
-webkit-grid-column-start
-webkit-grid-definition-columns
-webkit-grid-definition-rows
-webkit-grid-row
-webkit-grid-row-end
-webkit-grid-row-start
-webkit-justify-content
-webkit-line-clamp
-webkit-logical-height
-webkit-logical-width
-webkit-margin-after
-webkit-margin-after-collapse
-webkit-margin-before
-webkit-margin-before-collapse
-webkit-margin-bottom-collapse
-webkit-margin-collapse
-webkit-margin-end
-webkit-margin-start
-webkit-margin-top-collapse
-webkit-marquee
-webkit-marquee-direction
-webkit-marquee-increment
-webkit-marquee-repetition
-webkit-marquee-speed
-webkit-marquee-style
-webkit-mask
-webkit-mask-box-image
-webkit-mask-box-image-outset
-webkit-mask-box-image-repeat
-webkit-mask-box-image-slice
-webkit-mask-box-image-source
-webkit-mask-box-image-width
-webkit-mask-clip
-webkit-mask-composite
-webkit-mask-image
-webkit-mask-origin
-webkit-mask-position
-webkit-mask-position-x
-webkit-mask-position-y
-webkit-mask-repeat
-webkit-mask-repeat-x
-webkit-mask-repeat-y
-webkit-mask-size
-webkit-mask-source-type
-webkit-max-logical-height
-webkit-max-logical-width
-webkit-min-logical-height
-webkit-min-logical-width
-webkit-opacity
-webkit-order
-webkit-padding-after
-webkit-padding-before
-webkit-padding-end
-webkit-padding-start
-webkit-perspective
-webkit-perspective-origin
-webkit-perspective-origin-x
-webkit-perspective-origin-y
-webkit-region-break-after
-webkit-region-break-before
-webkit-region-break-inside
-webkit-region-fragment
-webkit-shape-inside
-webkit-shape-margin
-webkit-shape-outside
-webkit-shape-padding
-webkit-svg-shadow
-webkit-tap-highlight-color
-webkit-text-decoration
-webkit-text-decoration-color
-webkit-text-decoration-line
-webkit-text-decoration-style
-webkit-text-size-adjust
-webkit-touch-callout
-webkit-transform
-webkit-transform-origin
-webkit-transform-origin-x
-webkit-transform-origin-y
-webkit-transform-origin-z
-webkit-transform-style
-webkit-transition
-webkit-transition-delay
-webkit-transition-duration
-webkit-transition-property
-webkit-transition-timing-function
-webkit-user-drag
-webkit-wrap-flow
-webkit-wrap-through
align-content
align-items
align-self
alignment-adjust
alignment-baseline
all
anchor-point
animation
animation-delay
animation-direction
animation-duration
animation-fill-mode
animation-iteration-count
animation-name
animation-play-state
animation-timing-function
azimuth
backface-visibility
background
background-attachment
background-clip
background-color
background-image
background-origin
background-position
background-repeat
background-size
baseline-shift
binding
bleed
bookmark-label
bookmark-level
bookmark-state
border
border-bottom
border-bottom-color
border-bottom-left-radius
border-bottom-right-radius
border-bottom-style
border-bottom-width
border-collapse
border-color
border-image
border-image-outset
border-image-repeat
border-image-slice
border-image-source
border-image-width
border-left
border-left-color
border-left-style
border-left-width
border-radius
border-right
border-right-color
border-right-style
border-right-width
border-spacing
border-style
border-top
border-top-color
border-top-left-radius
border-top-right-radius
border-top-style
border-top-width
border-width
bottom
box-decoration-break
box-shadow
box-sizing
box-snap
box-suppress
break-after
break-before
break-inside
caption-side
chains
clear
clip
clip-path
clip-rule
color
color-interpolation-filters
column-count
column-fill
column-gap
column-rule
column-rule-color
column-rule-style
column-rule-width
column-span
column-width
columns
contain
content
counter-increment
counter-reset
counter-set
crop
cue
cue-after
cue-before
cursor
direction
display
display-inside
display-list
display-outside
dominant-baseline
elevation
empty-cells
filter
flex
flex-basis
flex-direction
flex-flow
flex-grow
flex-shrink
flex-wrap
float
float-offset
flood-color
flood-opacity
flow-from
flow-into
font
font-family
font-feature-settings
font-kerning
font-language-override
font-size
font-size-adjust
font-stretch
font-style
font-synthesis
font-variant
font-variant-alternates
font-variant-caps
font-variant-east-asian
font-variant-ligatures
font-variant-numeric
font-variant-position
font-weight
grid
grid-area
grid-auto-columns
grid-auto-flow
grid-auto-rows
grid-column
grid-column-end
grid-column-start
grid-row
grid-row-end
grid-row-start
grid-template
grid-template-areas
grid-template-columns
grid-template-rows
hanging-punctuation
height
hyphens
icon
image-orientation
image-rendering
image-resolution
ime-mode
initial-letters
inline-box-align
justify-content
justify-items
justify-self
left
letter-spacing
lighting-color
line-box-contain
line-break
line-grid
line-height
line-snap
line-stacking
line-stacking-ruby
line-stacking-shift
line-stacking-strategy
list-style
list-style-image
list-style-position
list-style-type
margin
margin-bottom
margin-left
margin-right
margin-top
marker-offset
marker-side
marks
mask
mask-box
mask-box-outset
mask-box-repeat
mask-box-slice
mask-box-source
mask-box-width
mask-clip
mask-image
mask-origin
mask-position
mask-repeat
mask-size
mask-source-type
mask-type
max-height
max-lines
max-width
min-height
min-width
move-to
nav-down
nav-index
nav-left
nav-right
nav-up
object-fit
object-position
opacity
order
orphans
outline
outline-color
outline-offset
outline-style
outline-width
overflow
overflow-wrap
overflow-x
overflow-y
padding
padding-bottom
padding-left
padding-right
padding-top
page
page-break-after
page-break-before
page-break-inside
page-policy
pause
pause-after
pause-before
perspective
perspective-origin
pitch
pitch-range
play-during
position
presentation-level
quotes
region-fragment
resize
rest
rest-after
rest-before
richness
right
rotation
rotation-point
ruby-align
ruby-merge
ruby-position
shape-image-threshold
shape-margin
shape-outside
size
speak
speak-as
speak-header
speak-numeral
speak-punctuation
speech-rate
stress
string-set
tab-size
table-layout
text-align
text-align-last
text-combine-horizontal
text-combine-upright
text-decoration
text-decoration-color
text-decoration-line
text-decoration-skip
text-decoration-style
text-emphasis
text-emphasis-color
text-emphasis-position
text-emphasis-style
text-height
text-indent
text-justify
text-orientation
text-overflow
text-rendering
text-shadow
text-size-adjust
text-space-collapse
text-transform
text-underline-position
text-wrap
top
touch-action
transform
transform-origin
transform-style
transition
transition-delay
transition-duration
transition-property
transition-timing-function
unicode-bidi
unicode-range
vertical-align
visibility
voice-balance
voice-duration
voice-family
voice-pitch
voice-range
voice-rate
voice-stress
voice-volume
volume
white-space
widows
width
will-change
word-break
word-spacing
word-wrap
wrap-flow
wrap-through
writing-mode
z-index
]
}
)
end
end
# encoding: utf-8
class Sanitize
module Config
RESTRICTED = freeze_config(
:elements => %w[b em i strong u]
)
end
end
# encoding: utf-8
require 'crass'
require 'set'
class Sanitize; class CSS
attr_reader :config
# -- Class Methods -----------------------------------------------------------
# Sanitizes inline CSS style properties.
#
# This is most useful for sanitizing non-stylesheet fragments of CSS like you
# would find in the `style` attribute of an HTML element. To sanitize a full
# CSS stylesheet, use {.stylesheet}.
#
# @example
# Sanitize::CSS.properties("background: url(foo.png); color: #fff;")
#
# @return [String] Sanitized CSS properties.
def self.properties(css, config = {})
self.new(config).properties(css)
end
# Sanitizes a full CSS stylesheet.
#
# A stylesheet may include selectors, at-rules, and comments. To sanitize only
# inline style properties such as the contents of an HTML `style` attribute,
# use {.properties}.
#
# @example
# css = %[
# .foo {
# background: url(foo.png);
# color: #fff;
# }
#
# #bar {
# font: 42pt 'Comic Sans MS';
# }
# ]
#
# Sanitize::CSS.stylesheet(css, Sanitize::Config::RELAXED)
#
# @return [String] Sanitized CSS stylesheet.
def self.stylesheet(css, config = {})
self.new(config).stylesheet(css)
end
# Sanitizes the given Crass CSS parse tree and all its children, modifying it
# in place.
#
# @example
# css = %[
# .foo {
# background: url(foo.png);
# color: #fff;
# }
#
# #bar {
# font: 42pt 'Comic Sans MS';
# }
# ]
#
# tree = Crass.parse(css)
# Sanitize::CSS.tree!(tree, Sanitize::Config::RELAXED)
#
# @return [Array] Sanitized Crass CSS parse tree.
def self.tree!(tree, config = {})
self.new(config).tree!(tree)
end
# -- Instance Methods --------------------------------------------------------
# Returns a new Sanitize::CSS object initialized with the settings in
# _config_.
def initialize(config = {})
@config = Config.merge(Config::DEFAULT[:css], config[:css] || config)
@at_rules = Set.new(@config[:at_rules])
@at_rules_with_properties = Set.new(@config[:at_rules_with_properties])
@at_rules_with_styles = Set.new(@config[:at_rules_with_styles])
end
# Sanitizes inline CSS style properties.
#
# This is most useful for sanitizing non-stylesheet fragments of CSS like you
# would find in the `style` attribute of an HTML element. To sanitize a full
# CSS stylesheet, use {#stylesheet}.
#
# @example
# scss = Sanitize::CSS.new(Sanitize::Config::RELAXED)
# scss.properties("background: url(foo.png); color: #fff;")
#
# @return [String] Sanitized CSS properties.
def properties(css)
tree = Crass.parse_properties(css,
:preserve_comments => @config[:allow_comments],
:preserve_hacks => @config[:allow_hacks])
tree!(tree)
Crass::Parser.stringify(tree)
end
# Sanitizes a full CSS stylesheet.
#
# A stylesheet may include selectors, at-rules, and comments. To sanitize only
# inline style properties such as the contents of an HTML `style` attribute,
# use {#properties}.
#
# @example
# css = %[
# .foo {
# background: url(foo.png);
# color: #fff;
# }
#
# #bar {
# font: 42pt 'Comic Sans MS';
# }
# ]
#
# scss = Sanitize::CSS.new(Sanitize::Config::RELAXED)
# scss.stylesheet(css)
#
# @return [String] Sanitized CSS stylesheet.
def stylesheet(css)
tree = Crass.parse(css,
:preserve_comments => @config[:allow_comments],
:preserve_hacks => @config[:allow_hacks])
tree!(tree)
Crass::Parser.stringify(tree)
end
# Sanitizes the given Crass CSS parse tree and all its children, modifying it
# in place.
#
# @example
# css = %[
# .foo {
# background: url(foo.png);
# color: #fff;
# }
#
# #bar {
# font: 42pt 'Comic Sans MS';
# }
# ]
#
# scss = Sanitize::CSS.new(Sanitize::Config::RELAXED)
# tree = Crass.parse(css)
#
# scss.tree!(tree)
#
# @return [Array] Sanitized Crass CSS parse tree.
def tree!(tree)
preceded_by_property = false
tree.map! do |node|
next nil if node.nil?
case node[:node]
when :at_rule
preceded_by_property = false
next at_rule!(node)
when :comment
next node if @config[:allow_comments]
when :property
prop = property!(node)
preceded_by_property = !prop.nil?
next prop
when :semicolon
# Only preserve the semicolon if it was preceded by a whitelisted
# property. Otherwise, omit it in order to prevent redundant semicolons.
if preceded_by_property
preceded_by_property = false
next node
end
when :style_rule
preceded_by_property = false
tree!(node[:children])
next node
when :whitespace
next node
end
nil
end
tree
end
# -- Protected Instance Methods ----------------------------------------------
protected
# Sanitizes a CSS at-rule node. Returns the sanitized node, or `nil` if the
# current config doesn't allow this at-rule.
def at_rule!(rule)
name = rule[:name].downcase
if @at_rules_with_styles.include?(name)
styles = Crass::Parser.parse_rules(rule[:block],
:preserve_comments => @config[:allow_comments],
:preserve_hacks => @config[:allow_hacks])
rule[:block] = tree!(styles)
elsif @at_rules_with_properties.include?(name)
props = Crass::Parser.parse_properties(rule[:block],
:preserve_comments => @config[:allow_comments],
:preserve_hacks => @config[:allow_hacks])
rule[:block] = tree!(props)
elsif @at_rules.include?(name)
return nil if rule.has_key?(:block)
else
return nil
end
rule
end
# Sanitizes a CSS property node. Returns the sanitized node, or `nil` if the
# current config doesn't allow this property.
def property!(prop)
name = prop[:name].downcase
# Preserve IE * and _ hacks if desired.
if @config[:allow_hacks]
name.slice!(0) if name =~ /\A[*_]/
end
return nil unless @config[:properties].include?(name)
nodes = prop[:children].dup
combined_value = ''
nodes.each do |child|
value = child[:value]
case child[:node]
when :ident
combined_value << value.downcase if String === value
when :function
if child.key?(:name)
name = child[:name].downcase
if name == 'url'
return nil unless valid_url?(child)
end
combined_value << name
return nil if name == 'expression' || combined_value == 'expression'
end
if Array === value
nodes.concat(value)
elsif String === value
lowercase_value = value.downcase
combined_value << lowercase_value
return nil if lowercase_value == 'expression' || combined_value == 'expression'
end
when :url
return nil unless valid_url?(child)
when :bad_url
return nil
end
end
prop
end
# Returns `true` if the given node (which may be of type `:url` or
# `:function`, since the CSS syntax can produce both) uses a whitelisted
# protocol.
def valid_url?(node)
type = node[:node]
if type == :function
return false unless node.key?(:name) && node[:name].downcase == 'url'
return false unless Array === node[:value]
# A URL function's `:value` should be an array containing no more than one
# `:string` node and any number of `:whitespace` nodes.
#
# If it contains more than one `:string` node, or if it contains any other
# nodes except `:whitespace` nodes, it's not valid.
url_string_node = nil
node[:value].each do |token|
return false unless Hash === token
case token[:node]
when :string
return false unless url_string_node.nil?
url_string_node = token
when :whitespace
next
else
return false
end
end
return false if url_string_node.nil?
url = url_string_node[:value]
elsif type == :url
url = node[:value]
else
return false
end
if url =~ Sanitize::REGEX_PROTOCOL
return @config[:protocols].include?($1.downcase)
else
return @config[:protocols].include?(:relative)
end
false
end
end; end
# encoding: utf-8
class Sanitize; module Transformers
CleanCDATA = lambda do |env|
node = env[:node]
if node.type == Nokogiri::XML::Node::CDATA_SECTION_NODE
node.replace(Nokogiri::XML::Text.new(node.text, node.document))
end
end
end; end
# encoding: utf-8
class Sanitize; module Transformers
CleanComment = lambda do |env|
node = env[:node]
if node.type == Nokogiri::XML::Node::COMMENT_NODE
node.unlink unless env[:is_whitelisted]
end
end
end; end
class Sanitize; module Transformers; module CSS
# Enforces a CSS whitelist on the contents of `style` attributes.
class CleanAttribute
def initialize(sanitizer_or_config)
if Sanitize::CSS === sanitizer_or_config
@scss = sanitizer_or_config
else
@scss = Sanitize::CSS.new(sanitizer_or_config)
end
end
def call(env)
node = env[:node]
return unless node.type == Nokogiri::XML::Node::ELEMENT_NODE &&
node.key?('style') && !env[:is_whitelisted]
attr = node.attribute('style')
css = @scss.properties(attr.value)
if css.strip.empty?
attr.unlink
else
attr.value = css
end
end
end
# Enforces a CSS whitelist on the contents of `<style>` elements.
class CleanElement
def initialize(sanitizer_or_config)
if Sanitize::CSS === sanitizer_or_config
@scss = sanitizer_or_config
else
@scss = Sanitize::CSS.new(sanitizer_or_config)
end
end
def call(env)
node = env[:node]
return unless node.type == Nokogiri::XML::Node::ELEMENT_NODE &&
env[:node_name] == 'style'
css = @scss.stylesheet(node.content)
if css.strip.empty?
node.unlink
else
node.children.unlink
node << Nokogiri::XML::Text.new(css, node.document)
end
end
end
end; end; end
# encoding: utf-8
class Sanitize; module Transformers
CleanDoctype = lambda do |env|
node = env[:node]
if node.type == Nokogiri::XML::Node::DTD_NODE
node.unlink unless env[:is_whitelisted]
end
end
end; end
# encoding: utf-8
require 'set'
class Sanitize; module Transformers; class CleanElement
# Matches a valid HTML5 data attribute name. The unicode ranges included here
# are a conservative subset of the full range of characters that are
# technically allowed, with the intent of matching the most common characters
# used in data attribute names while excluding uncommon or potentially
# misleading characters, or characters with the potential to be normalized
# into unsafe or confusing forms.
#
# If you need data attr names with characters that aren't included here (such
# as combining marks, full-width characters, or CJK), please consider creating
# a custom transformer to validate attributes according to your needs.
#
# http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#embedding-custom-non-visible-data-with-the-data-*-attributes
REGEX_DATA_ATTR = /\Adata-(?!xml)[a-z_][\w.\u00E0-\u00F6\u00F8-\u017F\u01DD-\u02AF-]*\z/u
def initialize(config)
@add_attributes = config[:add_attributes]
@attributes = config[:attributes].dup
@elements = config[:elements]
@protocols = config[:protocols]
@remove_all_contents = false
@remove_element_contents = Set.new
@whitespace_elements = {}
@attributes.each do |element_name, attrs|
unless element_name == :all
@attributes[element_name] = Set.new(attrs).merge(@attributes[:all] || [])
end
end
# Backcompat: if :whitespace_elements is a Set, convert it to a hash.
if config[:whitespace_elements].is_a?(Set)
config[:whitespace_elements].each do |element|
@whitespace_elements[element] = {:before => ' ', :after => ' '}
end
else
@whitespace_elements = config[:whitespace_elements]
end
if config[:remove_contents].is_a?(Set)
@remove_element_contents.merge(config[:remove_contents].map(&:to_s))
else
@remove_all_contents = !!config[:remove_contents]
end
end
def call(env)
node = env[:node]
return if node.type != Nokogiri::XML::Node::ELEMENT_NODE || env[:is_whitelisted]
name = env[:node_name]
# Delete any element that isn't in the config whitelist, unless the node has
# already been deleted from the document.
#
# It's important that we not try to reparent the children of a node that has
# already been deleted, since that seems to trigger a memory leak in
# Nokogiri.
unless @elements.include?(name) || node.parent.nil?
# Elements like br, div, p, etc. need to be replaced with whitespace in
# order to preserve readability.
if @whitespace_elements.include?(name)
node.add_previous_sibling(Nokogiri::XML::Text.new(@whitespace_elements[name][:before].to_s, node.document))
unless node.children.empty?
node.add_next_sibling(Nokogiri::XML::Text.new(@whitespace_elements[name][:after].to_s, node.document))
end
end
unless @remove_all_contents || @remove_element_contents.include?(name)
node.add_previous_sibling(node.children)
end
node.unlink
return
end
attr_whitelist = @attributes[name] || @attributes[:all]
if attr_whitelist.nil?
# Delete all attributes from elements with no whitelisted attributes.
node.attribute_nodes.each {|attr| attr.unlink }
else
allow_data_attributes = attr_whitelist.include?(:data)
# Delete any attribute that isn't allowed on this element.
node.attribute_nodes.each do |attr|
attr_name = attr.name.downcase
if attr_whitelist.include?(attr_name)
# The attribute is whitelisted.
# Remove any attributes that use unacceptable protocols.
if @protocols.include?(name) && @protocols[name].include?(attr_name)
attr_protocols = @protocols[name][attr_name]
if attr.value.to_s.downcase =~ REGEX_PROTOCOL
attr.unlink unless attr_protocols.include?($1.downcase)
else
attr.unlink unless attr_protocols.include?(:relative)
end
end
else
# The attribute isn't whitelisted.
if allow_data_attributes && attr_name.start_with?('data-')
# Arbitrary data attributes are allowed. Verify that the attribute
# is a valid data attribute.
attr.unlink unless attr_name =~ REGEX_DATA_ATTR
else
# Either the attribute isn't a data attribute, or arbitrary data
# attributes aren't allowed. Remove the attribute.
attr.unlink
end
end
end
end
# Add required attributes.
if @add_attributes.include?(name)
@add_attributes[name].each {|key, val| node[key] = val }
end
end
end; end; end
# encoding: utf-8
class Sanitize
VERSION = '4.0.0'
end
--- a/src/api/Gemfile.lock Index: open-build-service-2.7.1/src/api/Gemfile.lock
+++ b/src/api/Gemfile.lock ===================================================================
--- open-build-service-2.7.1.orig/src/api/Gemfile.lock 2017-10-19 16:20:52.913823051 +0200
+++ open-build-service-2.7.1/src/api/Gemfile.lock 2017-10-19 16:20:52.909822989 +0200
@@ -1,402 +1 @@ @@ -1,402 +1 @@
-GEM -GEM
- remote: https://rubygems.org/ - remote: https://rubygems.org/
...@@ -404,8 +406,19 @@ ...@@ -404,8 +406,19 @@
-BUNDLED WITH -BUNDLED WITH
- 1.10.6 - 1.10.6
+## Nothing here +## Nothing here
--- a/src/api/Gemfile Index: open-build-service-2.7.1/src/api/Gemfile
+++ b/src/api/Gemfile ===================================================================
--- open-build-service-2.7.1.orig/src/api/Gemfile 2017-10-19 16:20:52.913823051 +0200
+++ open-build-service-2.7.1/src/api/Gemfile 2017-10-19 16:25:40.650174731 +0200
@@ -34,7 +34,7 @@
# to escape HTML (FIXME: do we still use this?)
gem 'escape_utils'
# to sanitize HTML/CSS
-gem 'sanitize'
+gem 'sanitize', '4.0.0', path: "vendor/gems/sanitize-4.0.0"
# as authorization system
gem "pundit"
#
@@ -134,7 +134,7 @@ @@ -134,7 +134,7 @@
# to use sass in the asset pipeline # to use sass in the asset pipeline
gem 'sass-rails', '~> 5.0.1' gem 'sass-rails', '~> 5.0.1'
......
--- a/src/api/Rakefile --- a/src/api/Rakefile
+++ b/src/api/Rakefile +++ b/src/api/Rakefile
@@ -1,6 +1,9 @@ @@ -1,6 +1,10 @@
# Add your own tasks in files placed in lib/tasks ending in .rake, # Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+# Work around for jquery-datatables-rails-1.12.2 +# Work around for jquery-datatables-rails-1.12.2 and sanitize-4.0.0
+$LOAD_PATH.unshift '/usr/share/obs/api/vendor/gems/jquery-datatables-rails-1.12.2/lib' +$LOAD_PATH.unshift '/usr/share/obs/api/vendor/gems/jquery-datatables-rails-1.12.2/lib'
+$LOAD_PATH.unshift '/usr/share/obs/api/vendor/gems/sanitize-4.0.0/lib'
+ +
require File.expand_path('../config/application', __FILE__) require File.expand_path('../config/application', __FILE__)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment