@@ -7,22 +7,22 @@ module HTML5 # :nodoc:
7
7
module Scrub
8
8
CONTROL_CHARACTERS = /[`\u0000 -\u0020 \u007f \u0080 -\u0101 ]/
9
9
CSS_KEYWORDISH = /\A (#[0-9a-fA-F]+|rgb\( \d +%?,\d *%?,?\d *%?\) ?|-?\d {0,3}\. ?\d {0,10}(ch|cm|r?em|ex|in|lh|mm|pc|pt|px|Q|vmax|vmin|vw|vh|%|,|\) )?)\z /
10
- CRASS_SEMICOLON = { : node => :semicolon , : raw => ";" }
10
+ CRASS_SEMICOLON = { node : :semicolon , raw : ";" }
11
11
CSS_IMPORTANT = '!important'
12
12
13
13
class << self
14
14
def allowed_element? ( element_name )
15
- ::Loofah ::HTML5 ::SafeList ::ALLOWED_ELEMENTS_WITH_LIBXML2 . include? element_name
15
+ ::Loofah ::HTML5 ::SafeList ::ALLOWED_ELEMENTS_WITH_LIBXML2 . include? ( element_name )
16
16
end
17
17
18
18
# alternative implementation of the html5lib attribute scrubbing algorithm
19
19
def scrub_attributes ( node )
20
20
node . attribute_nodes . each do |attr_node |
21
21
attr_name = if attr_node . namespace
22
- "#{ attr_node . namespace . prefix } :#{ attr_node . node_name } "
23
- else
24
- attr_node . node_name
25
- end
22
+ "#{ attr_node . namespace . prefix } :#{ attr_node . node_name } "
23
+ else
24
+ attr_node . node_name
25
+ end
26
26
27
27
if attr_name =~ /\A data-[\w -]+\z /
28
28
next
@@ -58,13 +58,13 @@ def scrub_attributes(node)
58
58
end
59
59
end
60
60
61
- scrub_css_attribute node
61
+ scrub_css_attribute ( node )
62
62
63
63
node . attribute_nodes . each do |attr_node |
64
64
node . remove_attribute ( attr_node . name ) if attr_node . value !~ /[^[:space:]]/
65
65
end
66
66
67
- force_correct_attribute_escaping! node
67
+ force_correct_attribute_escaping! ( node )
68
68
end
69
69
70
70
def scrub_css_attribute ( node )
@@ -73,33 +73,50 @@ def scrub_css_attribute(node)
73
73
end
74
74
75
75
def scrub_css ( style )
76
- style_tree = Crass . parse_properties style
76
+ style_tree = Crass . parse_properties ( style )
77
77
sanitized_tree = [ ]
78
78
79
79
style_tree . each do |node |
80
80
next unless node [ :node ] == :property
81
81
next if node [ :children ] . any? do |child |
82
- [ :url , :bad_url ] . include? ( child [ :node ] ) || ( child [ :node ] == :function && ! SafeList :: ALLOWED_CSS_FUNCTIONS . include? ( child [ :name ] . downcase ) )
82
+ [ :url , :bad_url ] . include? ( child [ :node ] )
83
83
end
84
+
84
85
name = node [ :name ] . downcase
85
- if SafeList ::ALLOWED_CSS_PROPERTIES . include? ( name ) || SafeList ::ALLOWED_SVG_PROPERTIES . include? ( name )
86
- sanitized_tree << node << CRASS_SEMICOLON
87
- elsif SafeList ::SHORTHAND_CSS_PROPERTIES . include? ( name . split ( "-" ) . first )
88
- value = node [ :value ] . split . map do |keyword |
89
- if SafeList ::ALLOWED_CSS_KEYWORDS . include? ( keyword ) || keyword =~ CSS_KEYWORDISH
86
+ next unless SafeList ::ALLOWED_CSS_PROPERTIES . include? ( name ) ||
87
+ SafeList ::ALLOWED_SVG_PROPERTIES . include? ( name ) ||
88
+ SafeList ::SHORTHAND_CSS_PROPERTIES . include? ( name . split ( "-" ) . first )
89
+
90
+ value = node [ :children ] . map do |child |
91
+ case child [ :node ]
92
+ when :whitespace
93
+ nil
94
+ when :string
95
+ nil
96
+ when :function
97
+ if SafeList ::ALLOWED_CSS_FUNCTIONS . include? ( child [ :name ] . downcase )
98
+ Crass ::Parser . stringify ( child )
99
+ end
100
+ when :ident
101
+ keyword = child [ :value ]
102
+ if !SafeList ::SHORTHAND_CSS_PROPERTIES . include? ( name . split ( "-" ) . first ) ||
103
+ SafeList ::ALLOWED_CSS_KEYWORDS . include? ( keyword ) ||
104
+ ( keyword =~ CSS_KEYWORDISH )
90
105
keyword
91
106
end
92
- end . compact
93
- unless value . empty?
94
- value << CSS_IMPORTANT if node [ :important ]
95
- propstring = sprintf "%s:%s" , name , value . join ( " " )
96
- sanitized_node = Crass . parse_properties ( propstring ) . first
97
- sanitized_tree << sanitized_node << CRASS_SEMICOLON
107
+ else
108
+ child [ :raw ]
98
109
end
99
- end
110
+ end . compact
111
+
112
+ next if value . empty?
113
+ value << CSS_IMPORTANT if node [ :important ]
114
+ propstring = format ( "%s:%s" , name , value . join ( " " ) )
115
+ sanitized_node = Crass . parse_properties ( propstring ) . first
116
+ sanitized_tree << sanitized_node << CRASS_SEMICOLON
100
117
end
101
118
102
- Crass ::Parser . stringify sanitized_tree
119
+ Crass ::Parser . stringify ( sanitized_tree )
103
120
end
104
121
105
122
#
0 commit comments