actionpack 3.0.0.rc → 3.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- data/CHANGELOG +11 -2
- data/README.rdoc +3 -3
- data/lib/abstract_controller/base.rb +13 -1
- data/lib/action_controller.rb +2 -1
- data/lib/action_controller/base.rb +1 -1
- data/lib/action_controller/deprecated/base.rb +11 -1
- data/lib/action_controller/deprecated/url_writer.rb +14 -0
- data/lib/action_controller/metal/http_authentication.rb +3 -3
- data/lib/action_controller/metal/responder.rb +2 -8
- data/lib/action_controller/middleware.rb +1 -1
- data/lib/action_controller/test_case.rb +1 -1
- data/lib/action_controller/vendor/html-scanner/html/document.rb +2 -2
- data/lib/action_controller/vendor/html-scanner/html/node.rb +29 -29
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +25 -25
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +1 -1
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +8 -8
- data/lib/action_dispatch.rb +1 -0
- data/lib/action_dispatch/http/cache.rb +2 -2
- data/lib/action_dispatch/http/mime_type.rb +10 -10
- data/lib/action_dispatch/http/parameters.rb +2 -2
- data/lib/action_dispatch/http/request.rb +7 -0
- data/lib/action_dispatch/http/url.rb +10 -0
- data/lib/action_dispatch/middleware/best_standards_support.rb +22 -0
- data/lib/action_dispatch/middleware/cookies.rb +18 -8
- data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -5
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +1 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +2 -9
- data/lib/action_dispatch/middleware/stack.rb +1 -1
- data/lib/action_dispatch/railtie.rb +2 -1
- data/lib/action_dispatch/routing.rb +4 -4
- data/lib/action_dispatch/routing/deprecated_mapper.rb +1 -0
- data/lib/action_dispatch/routing/mapper.rb +34 -21
- data/lib/action_dispatch/routing/route_set.rb +8 -5
- data/lib/action_dispatch/routing/url_for.rb +1 -1
- data/lib/action_dispatch/testing/assertions/routing.rb +37 -14
- data/lib/action_dispatch/testing/integration.rb +1 -0
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view/base.rb +1 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +12 -0
- data/lib/action_view/helpers/debug_helper.rb +1 -1
- data/lib/action_view/helpers/form_helper.rb +7 -6
- data/lib/action_view/helpers/form_options_helper.rb +21 -18
- data/lib/action_view/helpers/form_tag_helper.rb +9 -9
- data/lib/action_view/helpers/number_helper.rb +1 -1
- data/lib/action_view/helpers/raw_output_helper.rb +1 -1
- data/lib/action_view/helpers/sanitize_helper.rb +4 -2
- data/lib/action_view/helpers/text_helper.rb +5 -2
- data/lib/action_view/helpers/translation_helper.rb +9 -9
- data/lib/action_view/log_subscriber.rb +1 -1
- data/lib/action_view/render/layouts.rb +8 -4
- data/lib/action_view/render/partials.rb +1 -1
- data/lib/action_view/template/handler.rb +1 -1
- data/lib/action_view/template/handlers.rb +1 -1
- data/lib/action_view/template/resolver.rb +15 -0
- data/lib/action_view/test_case.rb +1 -1
- data/lib/action_view/testing/resolvers.rb +1 -1
- metadata +18 -16
data/CHANGELOG
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
*Rails 3.0.0 [release candidate 2] (August 23rd, 2010)*
|
2
|
+
|
3
|
+
* See http://github.com/rails/rails/compare/v3.0.0_RC...v3.0.0_RC2 for gory details
|
4
|
+
|
5
|
+
* Support routing constraints in functional tests. [Andrew White]
|
6
|
+
|
7
|
+
* Add a header that tells Internet Explorer (all versions) to use the best available standards support. [Yehuda Katz]
|
8
|
+
|
9
|
+
|
1
10
|
*Rails 3.0.0 [release candidate] (July 26th, 2010)*
|
2
11
|
|
3
12
|
* Allow stylesheet/javascript extensions to be changed through railties. [Josh Kalderimis]
|
@@ -26,7 +35,7 @@
|
|
26
35
|
resources :comments
|
27
36
|
end
|
28
37
|
end
|
29
|
-
|
38
|
+
|
30
39
|
You can now use comment_path for /comments/1 instead of post_comment_path for /posts/1/comments/1.
|
31
40
|
|
32
41
|
* Add support for multi-subdomain session by setting cookie host in session cookie so you can share session between www.example.com, example.com and user.example.com. #4818 [Guillermo Álvarez]
|
@@ -110,7 +119,7 @@
|
|
110
119
|
* ActionDispatch::Request#content_type returns a String to be compatible with
|
111
120
|
Rack::Request. Use #content_mime_type for the Mime::Type instance [YK]
|
112
121
|
|
113
|
-
* Updated Prototype to 1.6.1 and Scriptaculous to 1.8.3 [ML]
|
122
|
+
* Updated Prototype to 1.6.1 and Scriptaculous to 1.8.3 [ML]
|
114
123
|
|
115
124
|
* Change the preferred way that URL helpers are included into a class[YK & CL]
|
116
125
|
|
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= Action Pack -- From request to response
|
2
2
|
|
3
|
-
Action Pack is a framework for handling and responding to web requests. It
|
3
|
+
Action Pack is a framework for handling and responding to web requests. It
|
4
4
|
provides mechanisms for *routing* (mapping request URLs to actions), defining
|
5
5
|
*controllers* that implement actions, and generating responses by rendering
|
6
6
|
*views*, which are templates of various formats. In short, Action Pack
|
@@ -102,10 +102,10 @@ A short rundown of some of the major features:
|
|
102
102
|
class WeblogController < ActionController::Base
|
103
103
|
# filters as methods
|
104
104
|
before_filter :authenticate, :cache, :audit
|
105
|
-
|
105
|
+
|
106
106
|
# filter as a proc
|
107
107
|
after_filter { |c| c.response.body = Gzip::compress(c.response.body) }
|
108
|
-
|
108
|
+
|
109
109
|
# class filter
|
110
110
|
after_filter LocalizeFilter
|
111
111
|
|
@@ -72,6 +72,13 @@ module AbstractController
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
+
# action_methods are cached and there is sometimes need to refresh
|
76
|
+
# them. clear_action_methods! allows you to do that, so next time
|
77
|
+
# you run action_methods, they will be recalculated
|
78
|
+
def clear_action_methods!
|
79
|
+
@action_methods = nil
|
80
|
+
end
|
81
|
+
|
75
82
|
# Returns the full controller name, underscored, without the ending Controller.
|
76
83
|
# For instance, MyApp::MyPostsController would return "my_app/my_posts" for
|
77
84
|
# controller_name.
|
@@ -81,6 +88,11 @@ module AbstractController
|
|
81
88
|
def controller_path
|
82
89
|
@controller_path ||= name.sub(/Controller$/, '').underscore unless anonymous?
|
83
90
|
end
|
91
|
+
|
92
|
+
def method_added(name)
|
93
|
+
super
|
94
|
+
clear_action_methods!
|
95
|
+
end
|
84
96
|
end
|
85
97
|
|
86
98
|
abstract!
|
@@ -97,7 +109,7 @@ module AbstractController
|
|
97
109
|
@_action_name = action_name = action.to_s
|
98
110
|
|
99
111
|
unless action_name = method_for_action(action_name)
|
100
|
-
raise ActionNotFound, "The action '#{action}' could not be found for #{self.class.name}"
|
112
|
+
raise ActionNotFound, "The action '#{action}' could not be found for #{self.class.name}"
|
101
113
|
end
|
102
114
|
|
103
115
|
@_response_body = nil
|
data/lib/action_controller.rb
CHANGED
@@ -35,10 +35,11 @@ module ActionController
|
|
35
35
|
end
|
36
36
|
|
37
37
|
autoload :Dispatcher, 'action_controller/deprecated/dispatcher'
|
38
|
+
autoload :UrlWriter, 'action_controller/deprecated/url_writer'
|
39
|
+
autoload :UrlRewriter, 'action_controller/deprecated/url_writer'
|
38
40
|
autoload :Integration, 'action_controller/deprecated/integration_test'
|
39
41
|
autoload :IntegrationTest, 'action_controller/deprecated/integration_test'
|
40
42
|
autoload :PerformanceTest, 'action_controller/deprecated/performance_test'
|
41
|
-
autoload :UrlWriter, 'action_controller/deprecated'
|
42
43
|
autoload :Routing, 'action_controller/deprecated'
|
43
44
|
autoload :TestCase, 'action_controller/test_case'
|
44
45
|
|
@@ -81,6 +81,11 @@ module ActionController
|
|
81
81
|
def session=(value)
|
82
82
|
ActiveSupport::Deprecation.warn "ActionController::Base.session= is deprecated. " <<
|
83
83
|
"Please configure it on your application with config.session_store :cookie_store, :key => '....'", caller
|
84
|
+
|
85
|
+
if secret = value.delete(:secret)
|
86
|
+
Rails.application.config.secret_token = secret
|
87
|
+
end
|
88
|
+
|
84
89
|
if value.delete(:disabled)
|
85
90
|
Rails.application.config.session_store :disabled
|
86
91
|
else
|
@@ -120,9 +125,14 @@ module ActionController
|
|
120
125
|
|
121
126
|
# This was moved to a plugin
|
122
127
|
def verify(*args)
|
123
|
-
ActiveSupport::Deprecation.warn "verify was removed from Rails and is now available as a plugin. "
|
128
|
+
ActiveSupport::Deprecation.warn "verify was removed from Rails and is now available as a plugin. " \
|
124
129
|
"Please install it with `rails plugin install git://github.com/rails/verification.git`.", caller
|
125
130
|
end
|
131
|
+
|
132
|
+
def exempt_from_layout(*)
|
133
|
+
ActiveSupport::Deprecation.warn "exempt_from_layout is no longer needed, because layouts in Rails 3 " \
|
134
|
+
"are restricted to the content-type of the template that was rendered.", caller
|
135
|
+
end
|
126
136
|
end
|
127
137
|
|
128
138
|
extend DeprecatedBehavior
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ActionController
|
2
|
+
module UrlWriter
|
3
|
+
def self.included(klass)
|
4
|
+
ActiveSupport::Deprecation.warn "include ActionController::UrlWriter is deprecated. Instead, " \
|
5
|
+
"include Rails.application.routes.url_helpers"
|
6
|
+
klass.class_eval { include Rails.application.routes.url_helpers }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class UrlRewriter
|
11
|
+
def initialize(*)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -63,7 +63,7 @@ module ActionController
|
|
63
63
|
# def test_access_granted_from_xml
|
64
64
|
# get(
|
65
65
|
# "/notes/1.xml", nil,
|
66
|
-
#
|
66
|
+
# 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(users(:dhh).name, users(:dhh).password)
|
67
67
|
# )
|
68
68
|
#
|
69
69
|
# assert_equal 200, status
|
@@ -392,11 +392,11 @@ module ActionController
|
|
392
392
|
end
|
393
393
|
end
|
394
394
|
|
395
|
-
# If token Authorization header is present, call the login procedure with
|
395
|
+
# If token Authorization header is present, call the login procedure with
|
396
396
|
# the present token and options.
|
397
397
|
#
|
398
398
|
# controller - ActionController::Base instance for the current request.
|
399
|
-
# login_procedure - Proc to call if a token is present. The Proc should
|
399
|
+
# login_procedure - Proc to call if a token is present. The Proc should
|
400
400
|
# take 2 arguments:
|
401
401
|
# authenticate(controller) { |token, options| ... }
|
402
402
|
#
|
@@ -89,6 +89,8 @@ module ActionController #:nodoc:
|
|
89
89
|
|
90
90
|
def initialize(controller, resources, options={})
|
91
91
|
@controller = controller
|
92
|
+
@request = @controller.request
|
93
|
+
@format = @controller.formats.first
|
92
94
|
@resource = resources.last
|
93
95
|
@resources = resources
|
94
96
|
@options = options
|
@@ -99,14 +101,6 @@ module ActionController #:nodoc:
|
|
99
101
|
delegate :head, :render, :redirect_to, :to => :controller
|
100
102
|
delegate :get?, :post?, :put?, :delete?, :to => :request
|
101
103
|
|
102
|
-
def request
|
103
|
-
@request ||= @controller.request
|
104
|
-
end
|
105
|
-
|
106
|
-
def format
|
107
|
-
@format ||= @controller.formats.first
|
108
|
-
end
|
109
|
-
|
110
104
|
# Undefine :to_json and :to_yaml since it's defined on Object
|
111
105
|
undef_method(:to_json) if method_defined?(:to_json)
|
112
106
|
undef_method(:to_yaml) if method_defined?(:to_yaml)
|
@@ -311,7 +311,7 @@ module ActionController
|
|
311
311
|
def tests(controller_class)
|
312
312
|
self.controller_class = controller_class
|
313
313
|
end
|
314
|
-
|
314
|
+
|
315
315
|
def controller_class=(new_class)
|
316
316
|
prepare_controller_class(new_class) if new_class
|
317
317
|
write_inheritable_attribute(:controller_class, new_class)
|
@@ -48,7 +48,7 @@ EOF
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
# Search the tree for (and return) the first node that matches the given
|
53
53
|
# conditions. The conditions are interpreted differently for different node
|
54
54
|
# types, see HTML::Text#find and HTML::Tag#find.
|
@@ -62,7 +62,7 @@ EOF
|
|
62
62
|
def find_all(conditions)
|
63
63
|
@root.find_all(conditions)
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
end
|
67
67
|
|
68
68
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'strscan'
|
2
2
|
|
3
3
|
module HTML #:nodoc:
|
4
|
-
|
4
|
+
|
5
5
|
class Conditions < Hash #:nodoc:
|
6
6
|
def initialize(hash)
|
7
7
|
super()
|
@@ -57,17 +57,17 @@ module HTML #:nodoc:
|
|
57
57
|
class Node #:nodoc:
|
58
58
|
# The array of children of this node. Not all nodes have children.
|
59
59
|
attr_reader :children
|
60
|
-
|
60
|
+
|
61
61
|
# The parent node of this node. All nodes have a parent, except for the
|
62
62
|
# root node.
|
63
63
|
attr_reader :parent
|
64
|
-
|
64
|
+
|
65
65
|
# The line number of the input where this node was begun
|
66
66
|
attr_reader :line
|
67
|
-
|
67
|
+
|
68
68
|
# The byte position in the input where this node was begun
|
69
69
|
attr_reader :position
|
70
|
-
|
70
|
+
|
71
71
|
# Create a new node as a child of the given parent.
|
72
72
|
def initialize(parent, line=0, pos=0)
|
73
73
|
@parent = parent
|
@@ -92,7 +92,7 @@ module HTML #:nodoc:
|
|
92
92
|
# returns non +nil+. Returns the result of the #find call that succeeded.
|
93
93
|
def find(conditions)
|
94
94
|
conditions = validate_conditions(conditions)
|
95
|
-
@children.each do |child|
|
95
|
+
@children.each do |child|
|
96
96
|
node = child.find(conditions)
|
97
97
|
return node if node
|
98
98
|
end
|
@@ -133,7 +133,7 @@ module HTML #:nodoc:
|
|
133
133
|
|
134
134
|
equivalent
|
135
135
|
end
|
136
|
-
|
136
|
+
|
137
137
|
class <<self
|
138
138
|
def parse(parent, line, pos, content, strict=true)
|
139
139
|
if content !~ /^<\S/
|
@@ -160,11 +160,11 @@ module HTML #:nodoc:
|
|
160
160
|
|
161
161
|
return CDATA.new(parent, line, pos, scanner.pre_match.gsub(/<!\[CDATA\[/, ''))
|
162
162
|
end
|
163
|
-
|
163
|
+
|
164
164
|
closing = ( scanner.scan(/\//) ? :close : nil )
|
165
165
|
return Text.new(parent, line, pos, content) unless name = scanner.scan(/[\w:-]+/)
|
166
166
|
name.downcase!
|
167
|
-
|
167
|
+
|
168
168
|
unless closing
|
169
169
|
scanner.skip(/\s*/)
|
170
170
|
attributes = {}
|
@@ -191,13 +191,13 @@ module HTML #:nodoc:
|
|
191
191
|
attributes[attr.downcase] = value
|
192
192
|
scanner.skip(/\s*/)
|
193
193
|
end
|
194
|
-
|
194
|
+
|
195
195
|
closing = ( scanner.scan(/\//) ? :self : nil )
|
196
196
|
end
|
197
|
-
|
197
|
+
|
198
198
|
unless scanner.scan(/\s*>/)
|
199
199
|
if strict
|
200
|
-
raise "expected > (got #{scanner.rest.inspect} for #{content}, #{attributes.inspect})"
|
200
|
+
raise "expected > (got #{scanner.rest.inspect} for #{content}, #{attributes.inspect})"
|
201
201
|
else
|
202
202
|
# throw away all text until we find what we're looking for
|
203
203
|
scanner.skip_until(/>/) or scanner.terminate
|
@@ -212,9 +212,9 @@ module HTML #:nodoc:
|
|
212
212
|
|
213
213
|
# A node that represents text, rather than markup.
|
214
214
|
class Text < Node #:nodoc:
|
215
|
-
|
215
|
+
|
216
216
|
attr_reader :content
|
217
|
-
|
217
|
+
|
218
218
|
# Creates a new text node as a child of the given parent, with the given
|
219
219
|
# content.
|
220
220
|
def initialize(parent, line, pos, content)
|
@@ -240,7 +240,7 @@ module HTML #:nodoc:
|
|
240
240
|
def find(conditions)
|
241
241
|
match(conditions) && self
|
242
242
|
end
|
243
|
-
|
243
|
+
|
244
244
|
# Returns non-+nil+ if this node meets the given conditions, or +nil+
|
245
245
|
# otherwise. See the discussion of #find for the valid conditions.
|
246
246
|
def match(conditions)
|
@@ -268,7 +268,7 @@ module HTML #:nodoc:
|
|
268
268
|
content == node.content
|
269
269
|
end
|
270
270
|
end
|
271
|
-
|
271
|
+
|
272
272
|
# A CDATA node is simply a text node with a specialized way of displaying
|
273
273
|
# itself.
|
274
274
|
class CDATA < Text #:nodoc:
|
@@ -281,16 +281,16 @@ module HTML #:nodoc:
|
|
281
281
|
# closing tag, or a self-closing tag. It has a name, and may have a hash of
|
282
282
|
# attributes.
|
283
283
|
class Tag < Node #:nodoc:
|
284
|
-
|
284
|
+
|
285
285
|
# Either +nil+, <tt>:close</tt>, or <tt>:self</tt>
|
286
286
|
attr_reader :closing
|
287
|
-
|
287
|
+
|
288
288
|
# Either +nil+, or a hash of attributes for this node.
|
289
289
|
attr_reader :attributes
|
290
290
|
|
291
291
|
# The name of this tag.
|
292
292
|
attr_reader :name
|
293
|
-
|
293
|
+
|
294
294
|
# Create a new node as a child of the given parent, using the given content
|
295
295
|
# to describe the node. It will be parsed and the node name, attributes and
|
296
296
|
# closing status extracted.
|
@@ -344,7 +344,7 @@ module HTML #:nodoc:
|
|
344
344
|
def tag?
|
345
345
|
true
|
346
346
|
end
|
347
|
-
|
347
|
+
|
348
348
|
# Returns +true+ if the node meets any of the given conditions. The
|
349
349
|
# +conditions+ parameter must be a hash of any of the following keys
|
350
350
|
# (all are optional):
|
@@ -404,7 +404,7 @@ module HTML #:nodoc:
|
|
404
404
|
# node.match :descendant => { :tag => "strong" }
|
405
405
|
#
|
406
406
|
# # test if the node has between 2 and 4 span tags as immediate children
|
407
|
-
# node.match :children => { :count => 2..4, :only => { :tag => "span" } }
|
407
|
+
# node.match :children => { :count => 2..4, :only => { :tag => "span" } }
|
408
408
|
#
|
409
409
|
# # get funky: test to see if the node is a "div", has a "ul" ancestor
|
410
410
|
# # and an "li" parent (with "class" = "enum"), and whether or not it has
|
@@ -439,7 +439,7 @@ module HTML #:nodoc:
|
|
439
439
|
|
440
440
|
# test children
|
441
441
|
return false unless children.find { |child| child.match(conditions[:child]) } if conditions[:child]
|
442
|
-
|
442
|
+
|
443
443
|
# test ancestors
|
444
444
|
if conditions[:ancestor]
|
445
445
|
return false unless catch :found do
|
@@ -457,13 +457,13 @@ module HTML #:nodoc:
|
|
457
457
|
child.match(:descendant => conditions[:descendant])
|
458
458
|
end
|
459
459
|
end
|
460
|
-
|
460
|
+
|
461
461
|
# count children
|
462
462
|
if opts = conditions[:children]
|
463
463
|
matches = children.select do |c|
|
464
464
|
(c.kind_of?(HTML::Tag) and (c.closing == :self or ! c.childless?))
|
465
465
|
end
|
466
|
-
|
466
|
+
|
467
467
|
matches = matches.select { |c| c.match(opts[:only]) } if opts[:only]
|
468
468
|
opts.each do |key, value|
|
469
469
|
next if key == :only
|
@@ -489,24 +489,24 @@ module HTML #:nodoc:
|
|
489
489
|
self_index = siblings.index(self)
|
490
490
|
|
491
491
|
if conditions[:sibling]
|
492
|
-
return false unless siblings.detect do |s|
|
492
|
+
return false unless siblings.detect do |s|
|
493
493
|
s != self && s.match(conditions[:sibling])
|
494
494
|
end
|
495
495
|
end
|
496
496
|
|
497
497
|
if conditions[:before]
|
498
|
-
return false unless siblings[self_index+1..-1].detect do |s|
|
498
|
+
return false unless siblings[self_index+1..-1].detect do |s|
|
499
499
|
s != self && s.match(conditions[:before])
|
500
500
|
end
|
501
501
|
end
|
502
502
|
|
503
503
|
if conditions[:after]
|
504
|
-
return false unless siblings[0,self_index].detect do |s|
|
504
|
+
return false unless siblings[0,self_index].detect do |s|
|
505
505
|
s != self && s.match(conditions[:after])
|
506
506
|
end
|
507
507
|
end
|
508
508
|
end
|
509
|
-
|
509
|
+
|
510
510
|
true
|
511
511
|
end
|
512
512
|
|
@@ -515,7 +515,7 @@ module HTML #:nodoc:
|
|
515
515
|
return false unless closing == node.closing && self.name == node.name
|
516
516
|
attributes == node.attributes
|
517
517
|
end
|
518
|
-
|
518
|
+
|
519
519
|
private
|
520
520
|
# Match the given value to the given condition.
|
521
521
|
def match_condition(value, condition)
|
@@ -7,11 +7,11 @@ module HTML
|
|
7
7
|
return text unless sanitizeable?(text)
|
8
8
|
tokenize(text, options).join
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def sanitizeable?(text)
|
12
12
|
!(text.nil? || text.empty? || !text.index("<"))
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
protected
|
16
16
|
def tokenize(text, options)
|
17
17
|
tokenizer = HTML::Tokenizer.new(text)
|
@@ -22,12 +22,12 @@ module HTML
|
|
22
22
|
end
|
23
23
|
result
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def process_node(node, result, options)
|
27
27
|
result << node.to_s
|
28
28
|
end
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
class FullSanitizer < Sanitizer
|
32
32
|
def sanitize(text, options = {})
|
33
33
|
result = super
|
@@ -37,12 +37,12 @@ module HTML
|
|
37
37
|
# Recurse - handle all dirty nested tags
|
38
38
|
result == text ? result : sanitize(result, options)
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def process_node(node, result, options)
|
42
42
|
result << node.to_s if node.class == HTML::Text
|
43
43
|
end
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
class LinkSanitizer < FullSanitizer
|
47
47
|
cattr_accessor :included_tags, :instance_writer => false
|
48
48
|
self.included_tags = Set.new(%w(a href))
|
@@ -50,13 +50,13 @@ module HTML
|
|
50
50
|
def sanitizeable?(text)
|
51
51
|
!(text.nil? || text.empty? || !((text.index("<a") || text.index("<href")) && text.index(">")))
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
protected
|
55
55
|
def process_node(node, result, options)
|
56
|
-
result << node.to_s unless node.is_a?(HTML::Tag) && included_tags.include?(node.name)
|
56
|
+
result << node.to_s unless node.is_a?(HTML::Tag) && included_tags.include?(node.name)
|
57
57
|
end
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
class WhiteListSanitizer < Sanitizer
|
61
61
|
[:protocol_separator, :uri_attributes, :allowed_attributes, :allowed_tags, :allowed_protocols, :bad_tags,
|
62
62
|
:allowed_css_properties, :allowed_css_keywords, :shorthand_css_properties].each do |attr|
|
@@ -66,35 +66,35 @@ module HTML
|
|
66
66
|
# A regular expression of the valid characters used to separate protocols like
|
67
67
|
# the ':' in 'http://foo.com'
|
68
68
|
self.protocol_separator = /:|(�*58)|(p)|(%|%)3A/
|
69
|
-
|
69
|
+
|
70
70
|
# Specifies a Set of HTML attributes that can have URIs.
|
71
71
|
self.uri_attributes = Set.new(%w(href src cite action longdesc xlink:href lowsrc))
|
72
72
|
|
73
73
|
# Specifies a Set of 'bad' tags that the #sanitize helper will remove completely, as opposed
|
74
74
|
# to just escaping harmless tags like <font>
|
75
75
|
self.bad_tags = Set.new(%w(script))
|
76
|
-
|
76
|
+
|
77
77
|
# Specifies the default Set of tags that the #sanitize helper will allow unscathed.
|
78
|
-
self.allowed_tags = Set.new(%w(strong em b i p code pre tt samp kbd var sub
|
79
|
-
sup dfn cite big small address hr br div span h1 h2 h3 h4 h5 h6 ul ol li dl dt dd abbr
|
78
|
+
self.allowed_tags = Set.new(%w(strong em b i p code pre tt samp kbd var sub
|
79
|
+
sup dfn cite big small address hr br div span h1 h2 h3 h4 h5 h6 ul ol li dl dt dd abbr
|
80
80
|
acronym a img blockquote del ins))
|
81
81
|
|
82
|
-
# Specifies the default Set of html attributes that the #sanitize helper will leave
|
82
|
+
# Specifies the default Set of html attributes that the #sanitize helper will leave
|
83
83
|
# in the allowed tag.
|
84
84
|
self.allowed_attributes = Set.new(%w(href src width height alt cite datetime title class name xml:lang abbr))
|
85
|
-
|
85
|
+
|
86
86
|
# Specifies the default Set of acceptable css properties that #sanitize and #sanitize_css will accept.
|
87
|
-
self.allowed_protocols = Set.new(%w(ed2k ftp http https irc mailto news gopher nntp telnet webcal xmpp callto
|
87
|
+
self.allowed_protocols = Set.new(%w(ed2k ftp http https irc mailto news gopher nntp telnet webcal xmpp callto
|
88
88
|
feed svn urn aim rsync tag ssh sftp rtsp afs))
|
89
|
-
|
89
|
+
|
90
90
|
# Specifies the default Set of acceptable css keywords that #sanitize and #sanitize_css will accept.
|
91
|
-
self.allowed_css_properties = Set.new(%w(azimuth background-color border-bottom-color border-collapse
|
92
|
-
border-color border-left-color border-right-color border-top-color clear color cursor direction display
|
91
|
+
self.allowed_css_properties = Set.new(%w(azimuth background-color border-bottom-color border-collapse
|
92
|
+
border-color border-left-color border-right-color border-top-color clear color cursor direction display
|
93
93
|
elevation float font font-family font-size font-style font-variant font-weight height letter-spacing line-height
|
94
94
|
overflow pause pause-after pause-before pitch pitch-range richness speak speak-header speak-numeral speak-punctuation
|
95
95
|
speech-rate stress text-align text-decoration text-indent unicode-bidi vertical-align voice-family volume white-space
|
96
96
|
width))
|
97
|
-
|
97
|
+
|
98
98
|
# Specifies the default Set of acceptable css keywords that #sanitize and #sanitize_css will accept.
|
99
99
|
self.allowed_css_keywords = Set.new(%w(auto aqua black block blue bold both bottom brown center
|
100
100
|
collapse dashed dotted fuchsia gray green !important italic left lime maroon medium none navy normal
|
@@ -118,9 +118,9 @@ module HTML
|
|
118
118
|
style.scan(/([-\w]+)\s*:\s*([^:;]*)/) do |prop,val|
|
119
119
|
if allowed_css_properties.include?(prop.downcase)
|
120
120
|
clean << prop + ': ' + val + ';'
|
121
|
-
elsif shorthand_css_properties.include?(prop.split('-')[0].downcase)
|
121
|
+
elsif shorthand_css_properties.include?(prop.split('-')[0].downcase)
|
122
122
|
unless val.split().any? do |keyword|
|
123
|
-
!allowed_css_keywords.include?(keyword) &&
|
123
|
+
!allowed_css_keywords.include?(keyword) &&
|
124
124
|
keyword !~ /^(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$/
|
125
125
|
end
|
126
126
|
clean << prop + ': ' + val + ';'
|
@@ -146,7 +146,7 @@ module HTML
|
|
146
146
|
else
|
147
147
|
options[:parent].unshift node.name
|
148
148
|
end
|
149
|
-
|
149
|
+
|
150
150
|
process_attributes_for node, options
|
151
151
|
|
152
152
|
options[:tags].include?(node.name) ? node : nil
|
@@ -154,7 +154,7 @@ module HTML
|
|
154
154
|
bad_tags.include?(options[:parent].first) ? nil : node.to_s.gsub(/</, "<")
|
155
155
|
end
|
156
156
|
end
|
157
|
-
|
157
|
+
|
158
158
|
def process_attributes_for(node, options)
|
159
159
|
return unless node.attributes
|
160
160
|
node.attributes.keys.each do |attr_name|
|
@@ -169,7 +169,7 @@ module HTML
|
|
169
169
|
end
|
170
170
|
|
171
171
|
def contains_bad_protocols?(attr_name, value)
|
172
|
-
uri_attributes.include?(attr_name) &&
|
172
|
+
uri_attributes.include?(attr_name) &&
|
173
173
|
(value =~ /(^[^\/:]*):|(�*58)|(p)|(%|%)3A/ && !allowed_protocols.include?(value.split(protocol_separator).first))
|
174
174
|
end
|
175
175
|
end
|