actionpack 3.0.20 → 3.1.0.beta1
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 +88 -142
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -6
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +24 -19
- data/lib/abstract_controller/callbacks.rb +19 -19
- data/lib/abstract_controller/helpers.rb +11 -13
- data/lib/abstract_controller/layouts.rb +4 -5
- data/lib/abstract_controller/railties/routes_helpers.rb +18 -0
- data/lib/abstract_controller/rendering.rb +34 -31
- data/lib/abstract_controller/url_for.rb +27 -0
- data/lib/abstract_controller/view_paths.rb +31 -6
- data/lib/action_controller.rb +5 -3
- data/lib/action_controller/base.rb +15 -16
- data/lib/action_controller/caching.rb +2 -2
- data/lib/action_controller/caching/actions.rb +11 -12
- data/lib/action_controller/caching/fragments.rb +41 -19
- data/lib/action_controller/caching/pages.rb +3 -9
- data/lib/action_controller/caching/sweeping.rb +0 -1
- data/lib/action_controller/deprecated.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +1 -1
- data/lib/action_controller/metal.rb +78 -20
- data/lib/action_controller/metal/compatibility.rb +0 -9
- data/lib/action_controller/metal/conditional_get.rb +9 -9
- data/lib/action_controller/metal/data_streaming.rb +145 -0
- data/lib/action_controller/metal/force_ssl.rb +35 -0
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/helpers.rb +37 -44
- data/lib/action_controller/metal/hide_actions.rb +2 -3
- data/lib/action_controller/metal/http_authentication.rb +41 -38
- data/lib/action_controller/metal/implicit_render.rb +13 -13
- data/lib/action_controller/metal/instrumentation.rb +2 -2
- data/lib/action_controller/metal/mime_responds.rb +25 -19
- data/lib/action_controller/metal/params_wrapper.rb +224 -0
- data/lib/action_controller/metal/redirecting.rb +6 -2
- data/lib/action_controller/metal/renderers.rb +50 -36
- data/lib/action_controller/metal/rendering.rb +34 -25
- data/lib/action_controller/metal/request_forgery_protection.rb +18 -36
- data/lib/action_controller/metal/responder.rb +47 -12
- data/lib/action_controller/metal/streaming.rb +244 -138
- data/lib/action_controller/metal/testing.rb +0 -9
- data/lib/action_controller/metal/url_for.rb +12 -14
- data/lib/action_controller/railtie.rb +19 -37
- data/lib/action_controller/railties/paths.rb +24 -0
- data/lib/action_controller/record_identifier.rb +4 -10
- data/lib/action_controller/test_case.rb +36 -19
- data/lib/action_controller/vendor/html-scanner/html/node.rb +5 -5
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +3 -3
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -0
- data/lib/action_dispatch.rb +4 -1
- data/lib/action_dispatch/http/cache.rb +5 -32
- data/lib/action_dispatch/http/filter_parameters.rb +3 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +22 -3
- data/lib/action_dispatch/http/mime_type.rb +45 -5
- data/lib/action_dispatch/http/rack_cache.rb +58 -0
- data/lib/action_dispatch/http/request.rb +27 -41
- data/lib/action_dispatch/http/response.rb +56 -54
- data/lib/action_dispatch/http/upload.rb +1 -11
- data/lib/action_dispatch/http/url.rb +102 -42
- data/lib/action_dispatch/middleware/callbacks.rb +8 -25
- data/lib/action_dispatch/middleware/closed_error.rb +7 -0
- data/lib/action_dispatch/middleware/cookies.rb +37 -15
- data/lib/action_dispatch/middleware/flash.rb +80 -11
- data/lib/action_dispatch/middleware/params_parser.rb +2 -2
- data/lib/action_dispatch/middleware/reloader.rb +76 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +56 -226
- data/lib/action_dispatch/middleware/session/cookie_store.rb +20 -44
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -46
- data/lib/action_dispatch/middleware/show_exceptions.rb +15 -2
- data/lib/action_dispatch/middleware/stack.rb +50 -17
- data/lib/action_dispatch/middleware/static.rb +41 -29
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +2 -6
- data/lib/action_dispatch/railtie.rb +8 -0
- data/lib/action_dispatch/routing.rb +13 -1
- data/lib/action_dispatch/routing/mapper.rb +345 -227
- data/lib/action_dispatch/routing/polymorphic_routes.rb +33 -13
- data/lib/action_dispatch/routing/redirection.rb +110 -0
- data/lib/action_dispatch/routing/route.rb +15 -13
- data/lib/action_dispatch/routing/route_set.rb +116 -90
- data/lib/action_dispatch/routing/routes_proxy.rb +35 -0
- data/lib/action_dispatch/routing/url_for.rb +25 -1
- data/lib/action_dispatch/testing/assertions/response.rb +8 -10
- data/lib/action_dispatch/testing/assertions/routing.rb +15 -15
- data/lib/action_dispatch/testing/assertions/selector.rb +13 -220
- data/lib/action_dispatch/testing/integration.rb +37 -28
- data/lib/action_dispatch/testing/performance_test.rb +1 -3
- data/lib/action_dispatch/testing/test_process.rb +1 -1
- data/lib/action_dispatch/testing/test_request.rb +9 -3
- data/lib/action_dispatch/testing/test_response.rb +4 -111
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +3 -3
- data/lib/action_view.rb +39 -24
- data/lib/action_view/base.rb +61 -86
- data/lib/action_view/buffers.rb +43 -0
- data/lib/action_view/context.rb +21 -24
- data/lib/action_view/flows.rb +79 -0
- data/lib/action_view/helpers.rb +8 -6
- data/lib/action_view/helpers/active_model_helper.rb +0 -23
- data/lib/action_view/helpers/asset_paths.rb +79 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +30 -500
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +147 -0
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +101 -0
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +200 -0
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +152 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
- data/lib/action_view/helpers/cache_helper.rb +11 -19
- data/lib/action_view/helpers/capture_helper.rb +19 -8
- data/lib/action_view/helpers/controller_helper.rb +21 -0
- data/lib/action_view/helpers/csrf_helper.rb +22 -4
- data/lib/action_view/helpers/date_helper.rb +36 -22
- data/lib/action_view/helpers/form_helper.rb +199 -113
- data/lib/action_view/helpers/form_options_helper.rb +10 -11
- data/lib/action_view/helpers/form_tag_helper.rb +94 -22
- data/lib/action_view/helpers/javascript_helper.rb +24 -107
- data/lib/action_view/helpers/number_helper.rb +36 -33
- data/lib/action_view/helpers/output_safety_helper.rb +38 -0
- data/lib/action_view/helpers/record_tag_helper.rb +6 -6
- data/lib/action_view/helpers/rendering_helper.rb +90 -0
- data/lib/action_view/helpers/sanitize_helper.rb +2 -2
- data/lib/action_view/helpers/sprockets_helper.rb +69 -0
- data/lib/action_view/helpers/tag_helper.rb +34 -12
- data/lib/action_view/helpers/text_helper.rb +30 -145
- data/lib/action_view/helpers/translation_helper.rb +10 -17
- data/lib/action_view/helpers/url_helper.rb +70 -67
- data/lib/action_view/locale/en.yml +1 -1
- data/lib/action_view/lookup_context.rb +36 -14
- data/lib/action_view/{paths.rb → path_set.rb} +9 -8
- data/lib/action_view/railtie.rb +12 -4
- data/lib/action_view/renderer/abstract_renderer.rb +36 -0
- data/lib/action_view/{render/partials.rb → renderer/partial_renderer.rb} +147 -146
- data/lib/action_view/renderer/renderer.rb +54 -0
- data/lib/action_view/renderer/streaming_template_renderer.rb +106 -0
- data/lib/action_view/renderer/template_renderer.rb +74 -0
- data/lib/action_view/template.rb +91 -54
- data/lib/action_view/template/error.rb +11 -8
- data/lib/action_view/template/handler.rb +9 -1
- data/lib/action_view/template/handlers.rb +9 -9
- data/lib/action_view/template/handlers/builder.rb +4 -4
- data/lib/action_view/template/handlers/erb.rb +21 -41
- data/lib/action_view/template/resolver.rb +171 -57
- data/lib/action_view/template/text.rb +0 -4
- data/lib/action_view/test_case.rb +32 -16
- data/lib/action_view/testing/resolvers.rb +16 -10
- data/lib/sprockets/railtie.rb +100 -0
- metadata +162 -140
- checksums.yaml +0 -7
- data/lib/action_controller/deprecated/base.rb +0 -143
- data/lib/action_controller/deprecated/dispatcher.rb +0 -28
- data/lib/action_controller/deprecated/url_writer.rb +0 -14
- data/lib/action_dispatch/routing/deprecated_mapper.rb +0 -525
- data/lib/action_view/helpers/prototype_helper.rb +0 -851
- data/lib/action_view/helpers/raw_output_helper.rb +0 -18
- data/lib/action_view/helpers/scriptaculous_helper.rb +0 -263
- data/lib/action_view/render/layouts.rb +0 -83
- data/lib/action_view/render/rendering.rb +0 -67
- data/lib/action_view/template/handlers/rjs.rb +0 -17
@@ -4,7 +4,7 @@ module ActionDispatch
|
|
4
4
|
attr_accessor :original_filename, :content_type, :tempfile, :headers
|
5
5
|
|
6
6
|
def initialize(hash)
|
7
|
-
@original_filename =
|
7
|
+
@original_filename = hash[:filename]
|
8
8
|
@content_type = hash[:type]
|
9
9
|
@headers = hash[:head]
|
10
10
|
@tempfile = hash[:tempfile]
|
@@ -30,16 +30,6 @@ module ActionDispatch
|
|
30
30
|
def size
|
31
31
|
@tempfile.size
|
32
32
|
end
|
33
|
-
|
34
|
-
private
|
35
|
-
def encode_filename(filename)
|
36
|
-
# Encode the filename in the utf8 encoding, unless it is nil or we're in 1.8
|
37
|
-
if "ruby".encoding_aware? && filename
|
38
|
-
filename.force_encoding("UTF-8").encode!
|
39
|
-
else
|
40
|
-
filename
|
41
|
-
end
|
42
|
-
end
|
43
33
|
end
|
44
34
|
|
45
35
|
module Upload
|
@@ -1,24 +1,89 @@
|
|
1
1
|
module ActionDispatch
|
2
2
|
module Http
|
3
3
|
module URL
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
mattr_accessor :tld_length
|
5
|
+
self.tld_length = 1
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def extract_domain(host, tld_length = @@tld_length)
|
9
|
+
return nil unless named_host?(host)
|
10
|
+
host.split('.').last(1 + tld_length).join('.')
|
11
|
+
end
|
12
|
+
|
13
|
+
def extract_subdomains(host, tld_length = @@tld_length)
|
14
|
+
return [] unless named_host?(host)
|
15
|
+
parts = host.split('.')
|
16
|
+
parts[0..-(tld_length+2)]
|
17
|
+
end
|
18
|
+
|
19
|
+
def extract_subdomain(host, tld_length = @@tld_length)
|
20
|
+
extract_subdomains(host, tld_length).join('.')
|
21
|
+
end
|
22
|
+
|
23
|
+
def url_for(options = {})
|
24
|
+
unless options[:host].present? || options[:only_path].present?
|
25
|
+
raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true'
|
26
|
+
end
|
27
|
+
|
28
|
+
rewritten_url = ""
|
29
|
+
|
30
|
+
unless options[:only_path]
|
31
|
+
unless options[:protocol] == false
|
32
|
+
rewritten_url << (options[:protocol] || "http")
|
33
|
+
rewritten_url << ":" unless rewritten_url.match(%r{:|//})
|
34
|
+
end
|
35
|
+
rewritten_url << "//" unless rewritten_url.match("//")
|
36
|
+
rewritten_url << rewrite_authentication(options)
|
37
|
+
rewritten_url << host_or_subdomain_and_domain(options)
|
38
|
+
rewritten_url << ":#{options.delete(:port)}" if options[:port]
|
39
|
+
end
|
40
|
+
|
41
|
+
path = options.delete(:path) || ''
|
42
|
+
|
43
|
+
params = options[:params] || {}
|
44
|
+
params.reject! {|k,v| v.to_param.nil? }
|
45
|
+
|
46
|
+
rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
|
47
|
+
rewritten_url << "?#{params.to_query}" unless params.empty?
|
48
|
+
rewritten_url << "##{Rack::Mount::Utils.escape_uri(options[:anchor].to_param.to_s)}" if options[:anchor]
|
49
|
+
rewritten_url
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def named_host?(host)
|
55
|
+
!(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host))
|
56
|
+
end
|
57
|
+
|
58
|
+
def rewrite_authentication(options)
|
59
|
+
if options[:user] && options[:password]
|
60
|
+
"#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
|
61
|
+
else
|
62
|
+
""
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def host_or_subdomain_and_domain(options)
|
67
|
+
return options[:host] unless options[:subdomain] || options[:domain]
|
68
|
+
|
69
|
+
tld_length = options[:tld_length] || @@tld_length
|
70
|
+
|
71
|
+
host = ""
|
72
|
+
host << (options[:subdomain] || extract_subdomain(options[:host], tld_length))
|
73
|
+
host << "."
|
74
|
+
host << (options[:domain] || extract_domain(options[:host], tld_length))
|
75
|
+
host
|
76
|
+
end
|
7
77
|
end
|
8
78
|
|
9
|
-
# Returns
|
10
|
-
def
|
11
|
-
|
79
|
+
# Returns the complete URL used for this request.
|
80
|
+
def url
|
81
|
+
protocol + host_with_port + fullpath
|
12
82
|
end
|
13
83
|
|
14
84
|
# Returns 'https://' if this is an SSL request and 'http://' otherwise.
|
15
85
|
def protocol
|
16
|
-
ssl? ? 'https://' : 'http://'
|
17
|
-
end
|
18
|
-
|
19
|
-
# Is this an SSL request?
|
20
|
-
def ssl?
|
21
|
-
@env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
|
86
|
+
@protocol ||= ssl? ? 'https://' : 'http://'
|
22
87
|
end
|
23
88
|
|
24
89
|
# Returns the \host for this request, such as "example.com".
|
@@ -43,10 +108,12 @@ module ActionDispatch
|
|
43
108
|
|
44
109
|
# Returns the port number of this request as an integer.
|
45
110
|
def port
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
111
|
+
@port ||= begin
|
112
|
+
if raw_host_with_port =~ /:(\d+)$/
|
113
|
+
$1.to_i
|
114
|
+
else
|
115
|
+
standard_port
|
116
|
+
end
|
50
117
|
end
|
51
118
|
end
|
52
119
|
|
@@ -63,10 +130,16 @@ module ActionDispatch
|
|
63
130
|
port == standard_port
|
64
131
|
end
|
65
132
|
|
66
|
-
# Returns a \port suffix like
|
133
|
+
# Returns a number \port suffix like 8080 if the \port number of this request
|
67
134
|
# is not the default HTTP \port 80 or HTTPS \port 443.
|
135
|
+
def optional_port
|
136
|
+
standard_port? ? nil : port
|
137
|
+
end
|
138
|
+
|
139
|
+
# Returns a string \port suffix, including colon, like ":8080" if the \port
|
140
|
+
# number of this request is not the default HTTP \port 80 or HTTPS \port 443.
|
68
141
|
def port_string
|
69
|
-
|
142
|
+
standard_port? ? '' : ":#{port}"
|
70
143
|
end
|
71
144
|
|
72
145
|
def server_port
|
@@ -75,38 +148,25 @@ module ActionDispatch
|
|
75
148
|
|
76
149
|
# Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify
|
77
150
|
# a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
|
78
|
-
def domain(tld_length =
|
79
|
-
|
80
|
-
|
81
|
-
host.split('.').last(1 + tld_length).join('.')
|
151
|
+
def domain(tld_length = @@tld_length)
|
152
|
+
ActionDispatch::Http::URL.extract_domain(host, tld_length)
|
82
153
|
end
|
83
154
|
|
84
155
|
# Returns all the \subdomains as an array, so <tt>["dev", "www"]</tt> would be
|
85
156
|
# returned for "dev.www.rubyonrails.org". You can specify a different <tt>tld_length</tt>,
|
86
157
|
# such as 2 to catch <tt>["www"]</tt> instead of <tt>["www", "rubyonrails"]</tt>
|
87
158
|
# in "www.rubyonrails.co.uk".
|
88
|
-
def subdomains(tld_length =
|
89
|
-
|
90
|
-
parts = host.split('.')
|
91
|
-
parts[0..-(tld_length+2)]
|
92
|
-
end
|
93
|
-
|
94
|
-
def subdomain(tld_length = 1)
|
95
|
-
subdomains(tld_length).join('.')
|
96
|
-
end
|
97
|
-
|
98
|
-
# Returns the request URI, accounting for server idiosyncrasies.
|
99
|
-
# WEBrick includes the full \URL. IIS leaves REQUEST_URI blank.
|
100
|
-
def request_uri
|
101
|
-
ActiveSupport::Deprecation.warn "Using #request_uri is deprecated. Use fullpath instead.", caller
|
102
|
-
fullpath
|
159
|
+
def subdomains(tld_length = @@tld_length)
|
160
|
+
ActionDispatch::Http::URL.extract_subdomains(host, tld_length)
|
103
161
|
end
|
104
162
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
163
|
+
# Returns all the \subdomains as a string, so <tt>"dev.www"</tt> would be
|
164
|
+
# returned for "dev.www.rubyonrails.org". You can specify a different <tt>tld_length</tt>,
|
165
|
+
# such as 2 to catch <tt>["www"]</tt> instead of <tt>"www.rubyonrails"</tt>
|
166
|
+
# in "www.rubyonrails.co.uk".
|
167
|
+
def subdomain(tld_length = @@tld_length)
|
168
|
+
subdomains(tld_length).join(".")
|
109
169
|
end
|
110
170
|
end
|
111
171
|
end
|
112
|
-
end
|
172
|
+
end
|
@@ -1,30 +1,14 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
2
|
+
|
1
3
|
module ActionDispatch
|
2
4
|
# Provide callbacks to be executed before and after the request dispatch.
|
3
|
-
#
|
4
|
-
# It also provides a to_prepare callback, which is performed in all requests
|
5
|
-
# in development by only once in production and notification callback for async
|
6
|
-
# operations.
|
7
|
-
#
|
8
5
|
class Callbacks
|
9
6
|
include ActiveSupport::Callbacks
|
10
7
|
|
11
8
|
define_callbacks :call, :rescuable => true
|
12
|
-
define_callbacks :prepare, :scope => :name
|
13
9
|
|
14
|
-
|
15
|
-
|
16
|
-
#
|
17
|
-
# If a symbol with a block is given, the symbol is used as an identifier.
|
18
|
-
# That allows to_prepare to be called again with the same identifier to
|
19
|
-
# replace the existing callback. Passing an identifier is a suggested
|
20
|
-
# practice if the code adding a preparation block may be reloaded.
|
21
|
-
def self.to_prepare(*args, &block)
|
22
|
-
if args.first.is_a?(Symbol) && block_given?
|
23
|
-
define_method :"__#{args.first}", &block
|
24
|
-
set_callback(:prepare, :"__#{args.first}")
|
25
|
-
else
|
26
|
-
set_callback(:prepare, *args, &block)
|
27
|
-
end
|
10
|
+
class << self
|
11
|
+
delegate :to_prepare, :to_cleanup, :to => "ActionDispatch::Reloader"
|
28
12
|
end
|
29
13
|
|
30
14
|
def self.before(*args, &block)
|
@@ -35,14 +19,13 @@ module ActionDispatch
|
|
35
19
|
set_callback(:call, :after, *args, &block)
|
36
20
|
end
|
37
21
|
|
38
|
-
def initialize(app,
|
39
|
-
|
40
|
-
|
22
|
+
def initialize(app, unused = nil)
|
23
|
+
ActiveSupport::Deprecation.warn "Passing a second argument to ActionDispatch::Callbacks.new is deprecated." unless unused.nil?
|
24
|
+
@app = app
|
41
25
|
end
|
42
26
|
|
43
27
|
def call(env)
|
44
|
-
|
45
|
-
_run_prepare_callbacks if @prepare_each_request
|
28
|
+
run_callbacks :call do
|
46
29
|
@app.call(env)
|
47
30
|
end
|
48
31
|
end
|
@@ -83,24 +83,21 @@ module ActionDispatch
|
|
83
83
|
# Raised when storing more than 4K of session data.
|
84
84
|
class CookieOverflow < StandardError; end
|
85
85
|
|
86
|
-
class CookieJar
|
86
|
+
class CookieJar #:nodoc:
|
87
87
|
|
88
88
|
# This regular expression is used to split the levels of a domain.
|
89
89
|
# The top level domain can be any string without a period or
|
90
90
|
# **.**, ***.** style TLDs like co.uk or com.au
|
91
91
|
#
|
92
92
|
# www.example.co.uk gives:
|
93
|
-
#
|
94
|
-
# $2 => co.uk
|
93
|
+
# $& => example.co.uk
|
95
94
|
#
|
96
95
|
# example.com gives:
|
97
|
-
#
|
98
|
-
# $2 => com
|
96
|
+
# $& => example.com
|
99
97
|
#
|
100
98
|
# lots.of.subdomains.example.local gives:
|
101
|
-
#
|
102
|
-
|
103
|
-
DOMAIN_REGEXP = /([^.]*)\.([^.]*|..\...|...\...)$/
|
99
|
+
# $& => example.local
|
100
|
+
DOMAIN_REGEXP = /[^.]*\.([^.]*|..\...|...\...)$/
|
104
101
|
|
105
102
|
def self.build(request)
|
106
103
|
secret = request.env[TOKEN_KEY]
|
@@ -118,27 +115,46 @@ module ActionDispatch
|
|
118
115
|
@delete_cookies = {}
|
119
116
|
@host = host
|
120
117
|
@secure = secure
|
121
|
-
|
122
|
-
|
118
|
+
@closed = false
|
119
|
+
@cookies = {}
|
123
120
|
end
|
124
121
|
|
122
|
+
attr_reader :closed
|
123
|
+
alias :closed? :closed
|
124
|
+
def close!; @closed = true end
|
125
|
+
|
125
126
|
# Returns the value of the cookie by +name+, or +nil+ if no such cookie exists.
|
126
127
|
def [](name)
|
127
|
-
|
128
|
+
@cookies[name.to_s]
|
129
|
+
end
|
130
|
+
|
131
|
+
def update(other_hash)
|
132
|
+
@cookies.update other_hash
|
133
|
+
self
|
128
134
|
end
|
129
135
|
|
130
136
|
def handle_options(options) #:nodoc:
|
131
137
|
options[:path] ||= "/"
|
132
138
|
|
133
139
|
if options[:domain] == :all
|
134
|
-
|
135
|
-
options[:
|
140
|
+
# if there is a provided tld length then we use it otherwise default domain regexp
|
141
|
+
domain_regexp = options[:tld_length] ? /([^.]+\.?){#{options[:tld_length]}}$/ : DOMAIN_REGEXP
|
142
|
+
|
143
|
+
# if host is not ip and matches domain regexp
|
144
|
+
# (ip confirms to domain regexp so we explicitly check for ip)
|
145
|
+
options[:domain] = if (@host !~ /^[\d.]+$/) && (@host =~ domain_regexp)
|
146
|
+
".#{$&}"
|
147
|
+
end
|
148
|
+
elsif options[:domain].is_a? Array
|
149
|
+
# if host matches one of the supplied domains without a dot in front of it
|
150
|
+
options[:domain] = options[:domain].find {|domain| @host.include? domain[/^\.?(.*)$/, 1] }
|
136
151
|
end
|
137
152
|
end
|
138
153
|
|
139
154
|
# Sets the cookie named +name+. The second argument may be the very cookie
|
140
155
|
# value, or a hash of options as documented above.
|
141
156
|
def []=(key, options)
|
157
|
+
raise ClosedError, :cookies if closed?
|
142
158
|
if options.is_a?(Hash)
|
143
159
|
options.symbolize_keys!
|
144
160
|
value = options[:value]
|
@@ -147,7 +163,7 @@ module ActionDispatch
|
|
147
163
|
options = { :value => value }
|
148
164
|
end
|
149
165
|
|
150
|
-
value =
|
166
|
+
value = @cookies[key.to_s] = value
|
151
167
|
|
152
168
|
handle_options(options)
|
153
169
|
|
@@ -164,7 +180,7 @@ module ActionDispatch
|
|
164
180
|
|
165
181
|
handle_options(options)
|
166
182
|
|
167
|
-
value =
|
183
|
+
value = @cookies.delete(key.to_s)
|
168
184
|
@delete_cookies[key] = options
|
169
185
|
value
|
170
186
|
end
|
@@ -219,6 +235,7 @@ module ActionDispatch
|
|
219
235
|
end
|
220
236
|
|
221
237
|
def []=(key, options)
|
238
|
+
raise ClosedError, :cookies if closed?
|
222
239
|
if options.is_a?(Hash)
|
223
240
|
options.symbolize_keys!
|
224
241
|
else
|
@@ -257,6 +274,7 @@ module ActionDispatch
|
|
257
274
|
end
|
258
275
|
|
259
276
|
def []=(key, options)
|
277
|
+
raise ClosedError, :cookies if closed?
|
260
278
|
if options.is_a?(Hash)
|
261
279
|
options.symbolize_keys!
|
262
280
|
options[:value] = @verifier.generate(options[:value])
|
@@ -299,6 +317,7 @@ module ActionDispatch
|
|
299
317
|
end
|
300
318
|
|
301
319
|
def call(env)
|
320
|
+
cookie_jar = nil
|
302
321
|
status, headers, body = @app.call(env)
|
303
322
|
|
304
323
|
if cookie_jar = env['action_dispatch.cookies']
|
@@ -309,6 +328,9 @@ module ActionDispatch
|
|
309
328
|
end
|
310
329
|
|
311
330
|
[status, headers, body]
|
331
|
+
ensure
|
332
|
+
cookie_jar = ActionDispatch::Request.new(env).cookie_jar unless cookie_jar
|
333
|
+
cookie_jar.close!
|
312
334
|
end
|
313
335
|
end
|
314
336
|
end
|
@@ -4,7 +4,7 @@ module ActionDispatch
|
|
4
4
|
# read a notice you put there or <tt>flash["notice"] = "hello"</tt>
|
5
5
|
# to put a new one.
|
6
6
|
def flash
|
7
|
-
@env[
|
7
|
+
@env[Flash::KEY] ||= (session["flash"] || Flash::FlashHash.new)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -40,7 +40,11 @@ module ActionDispatch
|
|
40
40
|
#
|
41
41
|
# See docs on the FlashHash class for more details about the flash.
|
42
42
|
class Flash
|
43
|
+
KEY = 'action_dispatch.request.flash_hash'.freeze
|
44
|
+
|
43
45
|
class FlashNow #:nodoc:
|
46
|
+
attr_accessor :flash
|
47
|
+
|
44
48
|
def initialize(flash)
|
45
49
|
@flash = flash
|
46
50
|
end
|
@@ -66,27 +70,75 @@ module ActionDispatch
|
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
69
|
-
class FlashHash
|
73
|
+
class FlashHash
|
74
|
+
include Enumerable
|
75
|
+
|
70
76
|
def initialize #:nodoc:
|
77
|
+
@used = Set.new
|
78
|
+
@closed = false
|
79
|
+
@flashes = {}
|
80
|
+
@now = nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def initialize_copy(other)
|
84
|
+
if other.now_is_loaded?
|
85
|
+
@now = other.now.dup
|
86
|
+
@now.flash = self
|
87
|
+
end
|
71
88
|
super
|
72
|
-
@used = Set.new
|
73
89
|
end
|
74
90
|
|
75
91
|
def []=(k, v) #:nodoc:
|
92
|
+
raise ClosedError, :flash if closed?
|
76
93
|
keep(k)
|
77
|
-
|
94
|
+
@flashes[k] = v
|
95
|
+
end
|
96
|
+
|
97
|
+
def [](k)
|
98
|
+
@flashes[k]
|
78
99
|
end
|
79
100
|
|
80
101
|
def update(h) #:nodoc:
|
81
102
|
h.keys.each { |k| keep(k) }
|
82
|
-
|
103
|
+
@flashes.update h
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
def keys
|
108
|
+
@flashes.keys
|
109
|
+
end
|
110
|
+
|
111
|
+
def key?(name)
|
112
|
+
@flashes.key? name
|
113
|
+
end
|
114
|
+
|
115
|
+
def delete(key)
|
116
|
+
@flashes.delete key
|
117
|
+
self
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_hash
|
121
|
+
@flashes.dup
|
122
|
+
end
|
123
|
+
|
124
|
+
def empty?
|
125
|
+
@flashes.empty?
|
126
|
+
end
|
127
|
+
|
128
|
+
def clear
|
129
|
+
@flashes.clear
|
130
|
+
end
|
131
|
+
|
132
|
+
def each(&block)
|
133
|
+
@flashes.each(&block)
|
83
134
|
end
|
84
135
|
|
85
136
|
alias :merge! :update
|
86
137
|
|
87
138
|
def replace(h) #:nodoc:
|
88
139
|
@used = Set.new
|
89
|
-
|
140
|
+
@flashes.replace h
|
141
|
+
self
|
90
142
|
end
|
91
143
|
|
92
144
|
# Sets a flash that will not be available to the next action, only to the current.
|
@@ -100,9 +152,13 @@ module ActionDispatch
|
|
100
152
|
#
|
101
153
|
# Entries set via <tt>now</tt> are accessed the same way as standard entries: <tt>flash['my-key']</tt>.
|
102
154
|
def now
|
103
|
-
FlashNow.new(self)
|
155
|
+
@now ||= FlashNow.new(self)
|
104
156
|
end
|
105
157
|
|
158
|
+
attr_reader :closed
|
159
|
+
alias :closed? :closed
|
160
|
+
def close!; @closed = true; end
|
161
|
+
|
106
162
|
# Keeps either the entire current flash or a specific flash entry available for the next action:
|
107
163
|
#
|
108
164
|
# flash.keep # keeps the entire flash
|
@@ -156,7 +212,12 @@ module ActionDispatch
|
|
156
212
|
self[:notice] = message
|
157
213
|
end
|
158
214
|
|
159
|
-
|
215
|
+
protected
|
216
|
+
|
217
|
+
def now_is_loaded?
|
218
|
+
!!@now
|
219
|
+
end
|
220
|
+
|
160
221
|
# Used internally by the <tt>keep</tt> and <tt>discard</tt> methods
|
161
222
|
# use() # marks the entire flash as used
|
162
223
|
# use('msg') # marks the "msg" entry as used
|
@@ -182,10 +243,18 @@ module ActionDispatch
|
|
182
243
|
@app.call(env)
|
183
244
|
ensure
|
184
245
|
session = env['rack.session'] || {}
|
185
|
-
flash_hash = env[
|
246
|
+
flash_hash = env[KEY]
|
247
|
+
|
248
|
+
if flash_hash
|
249
|
+
if !flash_hash.empty? || session.key?('flash')
|
250
|
+
session["flash"] = flash_hash
|
251
|
+
new_hash = flash_hash.dup
|
252
|
+
else
|
253
|
+
new_hash = flash_hash
|
254
|
+
end
|
186
255
|
|
187
|
-
|
188
|
-
|
256
|
+
env[KEY] = new_hash
|
257
|
+
new_hash.close!
|
189
258
|
end
|
190
259
|
|
191
260
|
if session.key?('flash') && session['flash'].empty?
|