antisamy 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/CHANGELOG.rdoc +13 -0
  2. data/LICENSE.txt +20 -20
  3. data/README.rdoc +41 -41
  4. data/lib/antisamy.rb +46 -46
  5. data/lib/antisamy/css/css_filter.rb +187 -187
  6. data/lib/antisamy/css/css_scanner.rb +84 -84
  7. data/lib/antisamy/css/css_validator.rb +128 -128
  8. data/lib/antisamy/csspool/rsac.rb +1 -1
  9. data/lib/antisamy/csspool/rsac/sac.rb +14 -14
  10. data/lib/antisamy/csspool/rsac/sac/conditions.rb +5 -5
  11. data/lib/antisamy/csspool/rsac/sac/conditions/attribute_condition.rb +50 -50
  12. data/lib/antisamy/csspool/rsac/sac/conditions/begin_hyphen_condition.rb +18 -18
  13. data/lib/antisamy/csspool/rsac/sac/conditions/class_condition.rb +18 -18
  14. data/lib/antisamy/csspool/rsac/sac/conditions/combinator_condition.rb +36 -36
  15. data/lib/antisamy/csspool/rsac/sac/conditions/condition.rb +29 -29
  16. data/lib/antisamy/csspool/rsac/sac/conditions/id_condition.rb +23 -23
  17. data/lib/antisamy/csspool/rsac/sac/conditions/one_of_condition.rb +18 -18
  18. data/lib/antisamy/csspool/rsac/sac/conditions/pseudo_class_condition.rb +20 -20
  19. data/lib/antisamy/csspool/rsac/sac/document_handler.rb +66 -66
  20. data/lib/antisamy/csspool/rsac/sac/error_handler.rb +13 -13
  21. data/lib/antisamy/csspool/rsac/sac/generated_parser.rb +1012 -1012
  22. data/lib/antisamy/csspool/rsac/sac/generated_property_parser.rb +9284 -9284
  23. data/lib/antisamy/csspool/rsac/sac/lexeme.rb +27 -27
  24. data/lib/antisamy/csspool/rsac/sac/lexical_unit.rb +201 -201
  25. data/lib/antisamy/csspool/rsac/sac/parse_exception.rb +4 -4
  26. data/lib/antisamy/csspool/rsac/sac/parser.rb +109 -109
  27. data/lib/antisamy/csspool/rsac/sac/property_parser.rb +44 -44
  28. data/lib/antisamy/csspool/rsac/sac/selectors.rb +5 -5
  29. data/lib/antisamy/csspool/rsac/sac/selectors/child_selector.rb +36 -36
  30. data/lib/antisamy/csspool/rsac/sac/selectors/conditional_selector.rb +45 -45
  31. data/lib/antisamy/csspool/rsac/sac/selectors/descendant_selector.rb +36 -36
  32. data/lib/antisamy/csspool/rsac/sac/selectors/element_selector.rb +35 -35
  33. data/lib/antisamy/csspool/rsac/sac/selectors/selector.rb +25 -25
  34. data/lib/antisamy/csspool/rsac/sac/selectors/sibling_selector.rb +35 -35
  35. data/lib/antisamy/csspool/rsac/sac/selectors/simple_selector.rb +21 -21
  36. data/lib/antisamy/csspool/rsac/sac/token.rb +25 -25
  37. data/lib/antisamy/csspool/rsac/sac/tokenizer.rb +185 -185
  38. data/lib/antisamy/csspool/rsac/stylesheet.rb +3 -3
  39. data/lib/antisamy/csspool/rsac/stylesheet/rule.rb +20 -20
  40. data/lib/antisamy/csspool/rsac/stylesheet/stylesheet.rb +76 -76
  41. data/lib/antisamy/html/handler.rb +112 -99
  42. data/lib/antisamy/html/sax_filter.rb +305 -302
  43. data/lib/antisamy/html/scanner.rb +47 -43
  44. data/lib/antisamy/model/attribute.rb +19 -19
  45. data/lib/antisamy/model/css_property.rb +39 -39
  46. data/lib/antisamy/model/tag.rb +31 -31
  47. data/lib/antisamy/policy.rb +577 -545
  48. data/lib/antisamy/scan_results.rb +89 -89
  49. data/spec/antisamy_spec.rb +208 -142
  50. data/spec/spec_helper.rb +12 -12
  51. metadata +79 -81
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,13 @@
1
+ == 0.0.1
2
+
3
+ * Initial commit.
4
+ * CSS scanning is currently not implmented so any CSS will be passed alonger verbatim
5
+
6
+ == 0.2.1
7
+
8
+ * CSS version2 implemented
9
+
10
+ == 0.3
11
+
12
+ * Proper fragment support and policy now provides a allowed-empty section to customize
13
+
data/LICENSE.txt CHANGED
@@ -1,20 +1,20 @@
1
- Copyright (c) 2011 Sal Scotto
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2011 Sal Scotto
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc CHANGED
@@ -1,41 +1,41 @@
1
- = Antisamy
2
-
3
- This project is a port of the java AntiSamy project to the ruby runtime. Its intended to provide a library for developers to add protection to their web applications from malicious
4
- user-supplier HTML and CSS. Please check out the AntiSamy project over at OWASP[http://www.owasp.org/index.php/Category:OWASP_AntiSamy_Project].
5
-
6
- == TODO
7
-
8
- * At some point support CSS3
9
-
10
- == Synopsis
11
-
12
- require 'antisamy'
13
- policy = AntiSamy.policy('antisamy.xml')
14
- tainted_html = 'User supplied markup'
15
- scan_results = AntiSamy.scan(tainted_html,policy)
16
- clean_html = scan_results.clean_html
17
-
18
- == Example Policies
19
-
20
- Please check policy-examples[https://github.com/washu/antisamy-ruby/tree/master/policy-examples] for sample policy files.
21
-
22
- == Contributing to antisamy
23
-
24
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
25
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
26
- * Fork the project
27
- * Start a feature/bugfix branch
28
- * Commit and push until you are happy with your contribution
29
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
30
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
31
-
32
- == csspool
33
-
34
- We use a forked version of csspool 0.2.6 within antysamy, you can find the license
35
- for csspool in the rsac[https://github.com/washu/antisamy-ruby/tree/master/lib/antisamy/csspool] directory. csspool was re-namespaced to avoid any conflicts and updated for 1.9.2 ruby compatabilty
36
-
37
- == Copyright
38
-
39
- Copyright (c) 2011 Sal Scotto. See LICENSE.txt for
40
- further details.
41
-
1
+ = Antisamy
2
+
3
+ This project is a port of the java AntiSamy project to the ruby runtime. Its intended to provide a library for developers to add protection to their web applications from malicious
4
+ user-supplier HTML and CSS. Please check out the AntiSamy project over at OWASP[http://www.owasp.org/index.php/Category:OWASP_AntiSamy_Project].
5
+
6
+ == TODO
7
+
8
+ * At some point support CSS3
9
+
10
+ == Synopsis
11
+
12
+ require 'antisamy'
13
+ policy = AntiSamy.policy('antisamy.xml')
14
+ tainted_html = 'User supplied markup'
15
+ scan_results = AntiSamy.scan(tainted_html,policy)
16
+ clean_html = scan_results.clean_html
17
+
18
+ == Example Policies
19
+
20
+ Please check policy-examples[https://github.com/washu/antisamy-ruby/tree/master/policy-examples] for sample policy files.
21
+
22
+ == Contributing to antisamy
23
+
24
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
25
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
26
+ * Fork the project
27
+ * Start a feature/bugfix branch
28
+ * Commit and push until you are happy with your contribution
29
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
30
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
31
+
32
+ == csspool
33
+
34
+ We use a forked version of csspool 0.2.6 within antysamy, you can find the license
35
+ for csspool in the rsac[https://github.com/washu/antisamy-ruby/tree/master/lib/antisamy/csspool] directory. csspool was re-namespaced to avoid any conflicts and updated for 1.9.2 ruby compatabilty
36
+
37
+ == Copyright
38
+
39
+ Copyright (c) 2011 Sal Scotto. See LICENSE.txt for
40
+ further details.
41
+
data/lib/antisamy.rb CHANGED
@@ -1,46 +1,46 @@
1
- require 'nokogiri'
2
- require 'antisamy/csspool/rsac'
3
- require 'antisamy/model/attribute'
4
- require 'antisamy/model/tag'
5
- require 'antisamy/model/css_property'
6
- require 'antisamy/policy'
7
- require 'antisamy/scan_results'
8
- require 'antisamy/html/handler'
9
- require 'antisamy/css/css_validator'
10
- require 'antisamy/css/css_filter'
11
- require 'antisamy/css/css_scanner'
12
- require 'antisamy/html/sax_filter'
13
- require 'antisamy/html/scanner'
14
-
15
- module AntiSamy
16
- class << self
17
-
18
- # Setup the input encoding, defaults to UTF-8
19
- def input_encoding=(encoding)
20
- @@input_encoding = encoding
21
- end
22
-
23
- # Setup the output encoding defaults to UTF-8
24
- def output_encoding=(encoding)
25
- @@output_encoding = encoding
26
- end
27
-
28
- # Scan the input using the provided policy.
29
- # will raise an exception if there is some form of scannign error
30
- def scan(input,policy)
31
- scanner = Scanner.new(policy)
32
- @@input_encoding ||= Scanner::DEFAULT_ENCODE
33
- @@output_encoding ||= Scanner::DEFAULT_ENCODE
34
- clean = scanner.scan(input,@@input_encoding, @output_encoding)
35
- clean
36
- end
37
-
38
- # Create a policy out of the provided file
39
- # will use a string or any IO object that can be read
40
- # will raise an exception if the policy fails to validate
41
- def policy(policy_file)
42
- Policy.new(policy_file)
43
- end
44
-
45
- end
46
- end
1
+ require 'nokogiri'
2
+ require 'antisamy/csspool/rsac'
3
+ require 'antisamy/model/attribute'
4
+ require 'antisamy/model/tag'
5
+ require 'antisamy/model/css_property'
6
+ require 'antisamy/policy'
7
+ require 'antisamy/scan_results'
8
+ require 'antisamy/html/handler'
9
+ require 'antisamy/css/css_validator'
10
+ require 'antisamy/css/css_filter'
11
+ require 'antisamy/css/css_scanner'
12
+ require 'antisamy/html/sax_filter'
13
+ require 'antisamy/html/scanner'
14
+
15
+ module AntiSamy
16
+ class << self
17
+
18
+ # Setup the input encoding, defaults to UTF-8
19
+ def input_encoding=(encoding)
20
+ @@input_encoding = encoding
21
+ end
22
+
23
+ # Setup the output encoding defaults to UTF-8
24
+ def output_encoding=(encoding)
25
+ @@output_encoding = encoding
26
+ end
27
+
28
+ # Scan the input using the provided policy.
29
+ # will raise an exception if there is some form of scannign error
30
+ def scan(input,policy)
31
+ scanner = Scanner.new(policy)
32
+ @@input_encoding ||= Scanner::DEFAULT_ENCODE
33
+ @@output_encoding ||= Scanner::DEFAULT_ENCODE
34
+ clean = scanner.scan(input,@@input_encoding, @output_encoding)
35
+ clean
36
+ end
37
+
38
+ # Create a policy out of the provided file
39
+ # will use a string or any IO object that can be read
40
+ # will raise an exception if the policy fails to validate
41
+ def policy(policy_file)
42
+ Policy.new(policy_file)
43
+ end
44
+
45
+ end
46
+ end
@@ -1,187 +1,187 @@
1
- require 'uri'
2
- module AntiSamy
3
- class CssFilter < RSAC::DocumentHandler
4
-
5
- attr_accessor :clean, :errors, :style_sheets
6
-
7
- def initialize(policy,tag)
8
- @policy = policy
9
- @validator = CssValidator.new(@policy)
10
- @errors = []
11
- @clean = ''
12
- @tag = tag
13
- @selector_open = false
14
- @style_sheets = []
15
- @inline = !tag.nil?
16
- @media_open = false
17
- @current_media = nil
18
- end
19
- # Start of document
20
- def start_document(input_source) #:nodoc:
21
- end
22
-
23
- # Receive notification of the end of a style sheet.
24
- def end_document(input_source) #:nodoc:
25
- end
26
-
27
- # Receive notification of a comment
28
- def comment(text)
29
- @errors << ScanMessage.new(ScanMessage::ERROR_COMMENT_REMOVED,@tag,text)
30
- end
31
-
32
- def error(exception)
33
- #puts exception
34
- end
35
-
36
- def fatal_error(exception)
37
- #puts exception
38
- end
39
-
40
- def error(t)
41
- #puts t
42
- end
43
-
44
- def warn(t)
45
- #puts t
46
- end
47
-
48
- def warning_error(exception)
49
- #puts exception
50
- end
51
- # Receive notification of an unknown at rule not supported by this parser.
52
- def ignorable_at_rule(at_rule)
53
- if inline
54
- @errors << ScanMessage.new(ScanMessage::ERROR_CSS_TAG_RULE_NOTFOUND,@tag,at_rule)
55
- else
56
- @errors << ScanMessage.new(ScanMessage::ERROR_STYLESHEET_RULE_NOTFOUND,@tag,at_rule)
57
- end
58
- end
59
-
60
- # Namespace declaration
61
- def namespace_declaration(prefix, uri) #:nodoc:
62
- end
63
-
64
- # Called on an import statement
65
- def import_style(uri, media, default_namespace_uri = nil)
66
- # check directive
67
- unless @policy.directive(Policy::EMBED_STYLESHEETS)
68
- @errors << ScanMessage.new(ScanMessage::ERROR_CSS_IMPORT_DISABLED,@tag,uri)
69
- return
70
- end
71
- # check for null uri
72
- if uri.nil?
73
- @errors << ScanMessage.new(ScanMessage::ERROR_CSS_IMPORT_URL_INVALID,@tag)
74
- end
75
- # check uri rules
76
- begin
77
- luri = RSAC::LexicalURI.new(uri)
78
- link = URI.parse(luri.string_value)
79
- link.normalize!
80
- onsite = @policy.expression("offsiteURL")
81
- offsite = @policy.expression("onsiteURL")
82
- # bad uri
83
- raise "Invalid URI Pattern" if link.to_s !~ onsite and link.to_s !~ offsite
84
- raise "Invalid URI" unless link.absolute?
85
- @style_sheets << link
86
- rescue Exception => e
87
- @errors << ScanMessage.new(ScanMessage::ERROR_CSS_IMPORT_URL_INVALID,@tag,uri)
88
- end
89
- end
90
-
91
- # Notification of the start of a media statement
92
- def start_media(media)
93
- @media_open = true
94
- @current_media = media
95
- end
96
-
97
- # Notification of the end of a media statement
98
- def end_media(media)
99
- @media_open = false
100
- @current_media = nil
101
- end
102
-
103
- # Notification of the start of a page statement
104
- def start_page(name = nil, pseudo_page = nil) #:nodoc:
105
- end
106
-
107
- # Notification of the end of a page statement
108
- def end_page(name = nil, pseudo_page = nil) # :nodoc:
109
- end
110
-
111
- # Notification of the beginning of a font face statement.
112
- def start_font_face #:nodoc:
113
- end
114
-
115
- # Notification of the end of a font face statement.
116
- def end_font_face #:nodoc:
117
- end
118
-
119
- # Notification of the beginning of a rule statement.
120
- def start_selector(selectors)
121
- count = 0
122
- selectors.each do |s|
123
- name = s.to_css
124
- valid = false
125
- begin
126
- @validator.valid_selector?(name,s)
127
- valid = true
128
- rescue Exception => e
129
- if @inline
130
- @errors << ScanMessage.new(ScanMessage::ERROR_CSS_TAG_SELECTOR_NOTFOUND,@tag,name)
131
- else
132
- @errors << ScanMessage.new(ScanMessage::ERROR_STYLESHEET_SELECTOR_NOTFOUND,@tag,name)
133
- end
134
-
135
- end
136
- if valid
137
- if count > 0
138
- clean << ", "
139
- end
140
- clean << name
141
- count += 1
142
- else
143
- # not allowed selector
144
- if @inline
145
- @errors << ScanMessage.new(ScanMessage::ERROR_CSS_TAG_SELECTOR_DISALLOWED,@tag,name)
146
- else
147
- @errors << ScanMessage.new(ScanMessage::ERROR_STYLESHEET_SELECTOR_DISALLOWED,@tag,name)
148
- end
149
- end
150
- end
151
- if count > 0
152
- clean << " {\n"
153
- @selector_open = true
154
- end
155
- end
156
-
157
- # Notification of the end of a rule statement.
158
- def end_selector(selectors)
159
- if @selector_open
160
- clean << "}\n"
161
- end
162
- @selector_open = false
163
- end
164
-
165
- # Notification of a declaration.
166
- def property(name, value, important)
167
- return unless @selector_open and @inline
168
- if @validator.valid_property?(name,value)
169
- clean << "\t" unless @inline
170
- clean << "#{name}:"
171
- value.each do |v|
172
- clean << " #{v.to_s}"
173
- end
174
- clean << ";"
175
- clean << "\n" unless @inline
176
- else
177
- cval = value.to_s
178
- if @inline
179
- @errors << ScanMessage.new(ScanMessage::ERROR_CSS_TAG_PROPERTY_INVALID,@tag,name,cval)
180
- else
181
- @errors << ScanMessage.new(ScanMessage::ERROR_STYLESHEET_PROPERTY_INVALID,@tag,name,cval)
182
- end
183
- end
184
-
185
- end
186
- end
187
- end
1
+ require 'uri'
2
+ module AntiSamy
3
+ class CssFilter < RSAC::DocumentHandler
4
+
5
+ attr_accessor :clean, :errors, :style_sheets
6
+
7
+ def initialize(policy,tag)
8
+ @policy = policy
9
+ @validator = CssValidator.new(@policy)
10
+ @errors = []
11
+ @clean = ''
12
+ @tag = tag
13
+ @selector_open = false
14
+ @style_sheets = []
15
+ @inline = !tag.nil?
16
+ @media_open = false
17
+ @current_media = nil
18
+ end
19
+ # Start of document
20
+ def start_document(input_source) #:nodoc:
21
+ end
22
+
23
+ # Receive notification of the end of a style sheet.
24
+ def end_document(input_source) #:nodoc:
25
+ end
26
+
27
+ # Receive notification of a comment
28
+ def comment(text)
29
+ @errors << ScanMessage.new(ScanMessage::ERROR_COMMENT_REMOVED,@tag,text)
30
+ end
31
+
32
+ def error(exception)
33
+ #puts exception
34
+ end
35
+
36
+ def fatal_error(exception)
37
+ #puts exception
38
+ end
39
+
40
+ def error(t)
41
+ #puts t
42
+ end
43
+
44
+ def warn(t)
45
+ #puts t
46
+ end
47
+
48
+ def warning_error(exception)
49
+ #puts exception
50
+ end
51
+ # Receive notification of an unknown at rule not supported by this parser.
52
+ def ignorable_at_rule(at_rule)
53
+ if inline
54
+ @errors << ScanMessage.new(ScanMessage::ERROR_CSS_TAG_RULE_NOTFOUND,@tag,at_rule)
55
+ else
56
+ @errors << ScanMessage.new(ScanMessage::ERROR_STYLESHEET_RULE_NOTFOUND,@tag,at_rule)
57
+ end
58
+ end
59
+
60
+ # Namespace declaration
61
+ def namespace_declaration(prefix, uri) #:nodoc:
62
+ end
63
+
64
+ # Called on an import statement
65
+ def import_style(uri, media, default_namespace_uri = nil)
66
+ # check directive
67
+ unless @policy.directive(Policy::EMBED_STYLESHEETS)
68
+ @errors << ScanMessage.new(ScanMessage::ERROR_CSS_IMPORT_DISABLED,@tag,uri)
69
+ return
70
+ end
71
+ # check for null uri
72
+ if uri.nil?
73
+ @errors << ScanMessage.new(ScanMessage::ERROR_CSS_IMPORT_URL_INVALID,@tag)
74
+ end
75
+ # check uri rules
76
+ begin
77
+ luri = RSAC::LexicalURI.new(uri)
78
+ link = URI.parse(luri.string_value)
79
+ link.normalize!
80
+ onsite = @policy.expression("offsiteURL")
81
+ offsite = @policy.expression("onsiteURL")
82
+ # bad uri
83
+ raise "Invalid URI Pattern" if link.to_s !~ onsite and link.to_s !~ offsite
84
+ raise "Invalid URI" unless link.absolute?
85
+ @style_sheets << link
86
+ rescue Exception => e
87
+ @errors << ScanMessage.new(ScanMessage::ERROR_CSS_IMPORT_URL_INVALID,@tag,uri)
88
+ end
89
+ end
90
+
91
+ # Notification of the start of a media statement
92
+ def start_media(media)
93
+ @media_open = true
94
+ @current_media = media
95
+ end
96
+
97
+ # Notification of the end of a media statement
98
+ def end_media(media)
99
+ @media_open = false
100
+ @current_media = nil
101
+ end
102
+
103
+ # Notification of the start of a page statement
104
+ def start_page(name = nil, pseudo_page = nil) #:nodoc:
105
+ end
106
+
107
+ # Notification of the end of a page statement
108
+ def end_page(name = nil, pseudo_page = nil) # :nodoc:
109
+ end
110
+
111
+ # Notification of the beginning of a font face statement.
112
+ def start_font_face #:nodoc:
113
+ end
114
+
115
+ # Notification of the end of a font face statement.
116
+ def end_font_face #:nodoc:
117
+ end
118
+
119
+ # Notification of the beginning of a rule statement.
120
+ def start_selector(selectors)
121
+ count = 0
122
+ selectors.each do |s|
123
+ name = s.to_css
124
+ valid = false
125
+ begin
126
+ @validator.valid_selector?(name,s)
127
+ valid = true
128
+ rescue Exception => e
129
+ if @inline
130
+ @errors << ScanMessage.new(ScanMessage::ERROR_CSS_TAG_SELECTOR_NOTFOUND,@tag,name)
131
+ else
132
+ @errors << ScanMessage.new(ScanMessage::ERROR_STYLESHEET_SELECTOR_NOTFOUND,@tag,name)
133
+ end
134
+
135
+ end
136
+ if valid
137
+ if count > 0
138
+ clean << ", "
139
+ end
140
+ clean << name
141
+ count += 1
142
+ else
143
+ # not allowed selector
144
+ if @inline
145
+ @errors << ScanMessage.new(ScanMessage::ERROR_CSS_TAG_SELECTOR_DISALLOWED,@tag,name)
146
+ else
147
+ @errors << ScanMessage.new(ScanMessage::ERROR_STYLESHEET_SELECTOR_DISALLOWED,@tag,name)
148
+ end
149
+ end
150
+ end
151
+ if count > 0
152
+ clean << " {\n"
153
+ @selector_open = true
154
+ end
155
+ end
156
+
157
+ # Notification of the end of a rule statement.
158
+ def end_selector(selectors)
159
+ if @selector_open
160
+ clean << "}\n"
161
+ end
162
+ @selector_open = false
163
+ end
164
+
165
+ # Notification of a declaration.
166
+ def property(name, value, important)
167
+ return unless @selector_open and @inline
168
+ if @validator.valid_property?(name,value)
169
+ clean << "\t" unless @inline
170
+ clean << "#{name}:"
171
+ value.each do |v|
172
+ clean << " #{v.to_s}"
173
+ end
174
+ clean << ";"
175
+ clean << "\n" unless @inline
176
+ else
177
+ cval = value.to_s
178
+ if @inline
179
+ @errors << ScanMessage.new(ScanMessage::ERROR_CSS_TAG_PROPERTY_INVALID,@tag,name,cval)
180
+ else
181
+ @errors << ScanMessage.new(ScanMessage::ERROR_STYLESHEET_PROPERTY_INVALID,@tag,name,cval)
182
+ end
183
+ end
184
+
185
+ end
186
+ end
187
+ end