actionpack 4.1.7 → 4.1.9
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +45 -0
- data/lib/action_controller/base.rb +1 -1
- data/lib/action_controller/metal/http_authentication.rb +9 -2
- data/lib/action_dispatch/http/mime_negotiation.rb +1 -1
- data/lib/action_dispatch/http/parameter_filter.rb +1 -1
- data/lib/action_dispatch/http/request.rb +1 -1
- data/lib/action_dispatch/journey/formatter.rb +1 -1
- data/lib/action_dispatch/journey/router.rb +3 -3
- data/lib/action_dispatch/middleware/cookies.rb +7 -5
- data/lib/action_dispatch/middleware/exception_wrapper.rb +11 -10
- data/lib/action_dispatch/middleware/flash.rb +1 -1
- data/lib/action_dispatch/middleware/public_exceptions.rb +5 -1
- data/lib/action_dispatch/middleware/static.rb +2 -2
- data/lib/action_dispatch/routing/route_set.rb +8 -1
- data/lib/action_dispatch/testing/assertions/routing.rb +8 -8
- data/lib/action_pack/gem_version.rb +1 -1
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db10782d837eef0e09b1e170e4f44fc747a5ac69
|
4
|
+
data.tar.gz: 08366ec637eee7308307e4bb95e443b28ff9d8cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4062ad340cd1a94d719fb2aa978a19456dbc9863177120fd3473ba36f1624e52391eae5cd04a997cffd5db750a1f63c8fab373b06bc4d5ccc480406cd2724c67
|
7
|
+
data.tar.gz: 6f10b6e27d69b0d9f4365b49d7660c7cbcf1d1a898b72d213890937aa2184805df51f7f52756bb67be387f37ef8d561f90a25e42db7192f8b132c40803df5723
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,48 @@
|
|
1
|
+
## Rails 4.1.9 (January 6, 2015) ##
|
2
|
+
|
3
|
+
* Fixed handling of positional url helper arguments when `format: false`.
|
4
|
+
|
5
|
+
Fixes #17819.
|
6
|
+
|
7
|
+
*Andrew White*, *Tatiana Soukiassian*
|
8
|
+
|
9
|
+
* Restore handling of a bare `Authorization` header, without `token=`
|
10
|
+
prefix.
|
11
|
+
|
12
|
+
Fixes #17108.
|
13
|
+
|
14
|
+
*Guo Xiang Tan*
|
15
|
+
|
16
|
+
|
17
|
+
## Rails 4.1.8 (November 16, 2014) ##
|
18
|
+
|
19
|
+
* Fix regression where path was getting overwritten when route anchor was false, and X-Cascade pass
|
20
|
+
|
21
|
+
fixes #17035.
|
22
|
+
|
23
|
+
*arthurnn*
|
24
|
+
|
25
|
+
* Fix a bug where malformed query strings lead to 500.
|
26
|
+
|
27
|
+
fixes #11502.
|
28
|
+
|
29
|
+
*Yuki Nishijima*
|
30
|
+
|
31
|
+
|
32
|
+
## Rails 4.1.7.1 (November 19, 2014) ##
|
33
|
+
|
34
|
+
* Fix arbitrary file existence disclosure in Action Pack.
|
35
|
+
|
36
|
+
CVE-2014-7829.
|
37
|
+
|
38
|
+
|
39
|
+
## Rails 4.1.7 (October 29, 2014) ##
|
40
|
+
|
41
|
+
* Fix arbitrary file existence disclosure in Action Pack.
|
42
|
+
|
43
|
+
CVE-2014-7818.
|
44
|
+
|
45
|
+
|
1
46
|
## Rails 4.1.6 (September 11, 2014) ##
|
2
47
|
|
3
48
|
* Prepend a JS comment to JSONP callbacks. Addresses CVE-2014-4671
|
@@ -44,7 +44,7 @@ module ActionController
|
|
44
44
|
# The full request object is available via the request accessor and is primarily used to query for HTTP headers:
|
45
45
|
#
|
46
46
|
# def server_ip
|
47
|
-
# location = request.env["
|
47
|
+
# location = request.env["REMOTE_ADDR"]
|
48
48
|
# render plain: "This server hosted at #{location}"
|
49
49
|
# end
|
50
50
|
#
|
@@ -397,6 +397,7 @@ module ActionController
|
|
397
397
|
#
|
398
398
|
# RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
|
399
399
|
module Token
|
400
|
+
TOKEN_KEY = 'token='
|
400
401
|
TOKEN_REGEX = /^Token /
|
401
402
|
AUTHN_PAIR_DELIMITERS = /(?:,|;|\t+)/
|
402
403
|
extend self
|
@@ -471,7 +472,13 @@ module ActionController
|
|
471
472
|
# pairs by the standardized `:`, `;`, or `\t` delimiters defined in
|
472
473
|
# `AUTHN_PAIR_DELIMITERS`.
|
473
474
|
def raw_params(auth)
|
474
|
-
auth.sub(TOKEN_REGEX, '').split(
|
475
|
+
_raw_params = auth.sub(TOKEN_REGEX, '').split(/\s*#{AUTHN_PAIR_DELIMITERS}\s*/)
|
476
|
+
|
477
|
+
if !(_raw_params.first =~ %r{\A#{TOKEN_KEY}})
|
478
|
+
_raw_params[0] = "#{TOKEN_KEY}#{_raw_params.first}"
|
479
|
+
end
|
480
|
+
|
481
|
+
_raw_params
|
475
482
|
end
|
476
483
|
|
477
484
|
# Encodes the given token and options into an Authorization header value.
|
@@ -481,7 +488,7 @@ module ActionController
|
|
481
488
|
#
|
482
489
|
# Returns String.
|
483
490
|
def encode_credentials(token, options = {})
|
484
|
-
values = ["
|
491
|
+
values = ["#{TOKEN_KEY}#{token.to_s.inspect}"] + options.map do |key, value|
|
485
492
|
"#{key}=#{value.to_s.inspect}"
|
486
493
|
end
|
487
494
|
"Token #{values * ", "}"
|
@@ -70,7 +70,7 @@ module ActionDispatch
|
|
70
70
|
def variant=(variant)
|
71
71
|
if variant.is_a?(Symbol)
|
72
72
|
@variant = [variant]
|
73
|
-
elsif variant.is_a?(Array) && variant.any? && variant.all?{ |v| v.is_a?(Symbol) }
|
73
|
+
elsif variant.nil? || variant.is_a?(Array) && variant.any? && variant.all?{ |v| v.is_a?(Symbol) }
|
74
74
|
@variant = variant
|
75
75
|
else
|
76
76
|
raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols, not a #{variant.class}. " \
|
@@ -56,7 +56,7 @@ module ActionDispatch
|
|
56
56
|
elsif value.is_a?(Array)
|
57
57
|
value = value.map { |v| v.is_a?(Hash) ? call(v) : v }
|
58
58
|
elsif blocks.any?
|
59
|
-
key = key.dup
|
59
|
+
key = key.dup if key.duplicable?
|
60
60
|
value = value.dup if value.duplicable?
|
61
61
|
blocks.each { |b| b.call(key, value) }
|
62
62
|
end
|
@@ -315,7 +315,7 @@ module ActionDispatch
|
|
315
315
|
|
316
316
|
private
|
317
317
|
def check_method(name)
|
318
|
-
HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS.
|
318
|
+
HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS[0...-1].join(', ')}, and #{HTTP_METHODS[-1]}")
|
319
319
|
name
|
320
320
|
end
|
321
321
|
end
|
@@ -34,7 +34,7 @@ module ActionDispatch
|
|
34
34
|
end
|
35
35
|
|
36
36
|
message = "No route matches #{Hash[constraints.sort].inspect}"
|
37
|
-
message << " missing required keys: #{missing_keys.sort.inspect}"
|
37
|
+
message << " missing required keys: #{missing_keys.sort.inspect}" unless missing_keys.empty?
|
38
38
|
|
39
39
|
raise ActionController::UrlGenerationError, message
|
40
40
|
end
|
@@ -63,9 +63,9 @@ module ActionDispatch
|
|
63
63
|
|
64
64
|
unless route.path.anchored
|
65
65
|
env['SCRIPT_NAME'] = (script_name.to_s + match.to_s).chomp('/')
|
66
|
-
|
67
|
-
env['PATH_INFO'] =
|
68
|
-
env['PATH_INFO'] = "/" +
|
66
|
+
matched_path = match.post_match
|
67
|
+
env['PATH_INFO'] = matched_path
|
68
|
+
env['PATH_INFO'] = "/" + matched_path unless matched_path.start_with? "/"
|
69
69
|
end
|
70
70
|
|
71
71
|
env[@params_key] = (set_params || {}).merge parameters
|
@@ -70,11 +70,13 @@ module ActionDispatch
|
|
70
70
|
# restrict to the domain level. If you use a schema like www.example.com
|
71
71
|
# and want to share session with user.example.com set <tt>:domain</tt>
|
72
72
|
# to <tt>:all</tt>. Make sure to specify the <tt>:domain</tt> option with
|
73
|
-
# <tt>:all</tt> again when deleting cookies.
|
73
|
+
# <tt>:all</tt> or <tt>Array</tt> again when deleting cookies.
|
74
74
|
#
|
75
75
|
# domain: nil # Does not sets cookie domain. (default)
|
76
76
|
# domain: :all # Allow the cookie for the top most level
|
77
77
|
# domain and subdomains.
|
78
|
+
# domain: %w(.example.com .example.org) # Allow the cookie
|
79
|
+
# for concrete domain names.
|
78
80
|
#
|
79
81
|
# * <tt>:expires</tt> - The time at which this cookie expires, as a \Time object.
|
80
82
|
# * <tt>:secure</tt> - Whether this cookie is only transmitted to HTTPS servers.
|
@@ -118,7 +120,7 @@ module ActionDispatch
|
|
118
120
|
# the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed
|
119
121
|
# cookie was tampered with by the user (or a 3rd party), nil will be returned.
|
120
122
|
#
|
121
|
-
# If +secrets.secret_key_base+ and +
|
123
|
+
# If +secrets.secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,
|
122
124
|
# legacy cookies signed with the old key generator will be transparently upgraded.
|
123
125
|
#
|
124
126
|
# This jar requires that you set a suitable secret for the verification on your app's +secrets.secret_key_base+.
|
@@ -141,7 +143,7 @@ module ActionDispatch
|
|
141
143
|
# Returns a jar that'll automatically encrypt cookie values before sending them to the client and will decrypt them for read.
|
142
144
|
# If the cookie was tampered with by the user (or a 3rd party), nil will be returned.
|
143
145
|
#
|
144
|
-
# If +secrets.secret_key_base+ and +
|
146
|
+
# If +secrets.secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,
|
145
147
|
# legacy cookies signed with the old key generator will be transparently upgraded.
|
146
148
|
#
|
147
149
|
# This jar requires that you set a suitable secret for the verification on your app's +secrets.secret_key_base+.
|
@@ -481,7 +483,7 @@ module ActionDispatch
|
|
481
483
|
end
|
482
484
|
|
483
485
|
# UpgradeLegacySignedCookieJar is used instead of SignedCookieJar if
|
484
|
-
#
|
486
|
+
# secrets.secret_token and secrets.secret_key_base are both set. It reads
|
485
487
|
# legacy cookies signed with the old dummy key generator and re-saves
|
486
488
|
# them using the new key generator to provide a smooth upgrade path.
|
487
489
|
class UpgradeLegacySignedCookieJar < SignedCookieJar #:nodoc:
|
@@ -539,7 +541,7 @@ module ActionDispatch
|
|
539
541
|
end
|
540
542
|
|
541
543
|
# UpgradeLegacyEncryptedCookieJar is used by ActionDispatch::Session::CookieStore
|
542
|
-
# instead of EncryptedCookieJar if
|
544
|
+
# instead of EncryptedCookieJar if secrets.secret_token and secrets.secret_key_base
|
543
545
|
# are both set. It reads legacy cookies signed with the old dummy key generator and
|
544
546
|
# encrypts and re-saves them using the new key generator to provide a smooth upgrade path.
|
545
547
|
class UpgradeLegacyEncryptedCookieJar < EncryptedCookieJar #:nodoc:
|
@@ -6,16 +6,17 @@ module ActionDispatch
|
|
6
6
|
cattr_accessor :rescue_responses
|
7
7
|
@@rescue_responses = Hash.new(:internal_server_error)
|
8
8
|
@@rescue_responses.merge!(
|
9
|
-
'ActionController::RoutingError'
|
10
|
-
'AbstractController::ActionNotFound'
|
11
|
-
'ActionController::MethodNotAllowed'
|
12
|
-
'ActionController::UnknownHttpMethod'
|
13
|
-
'ActionController::NotImplemented'
|
14
|
-
'ActionController::UnknownFormat'
|
15
|
-
'ActionController::InvalidAuthenticityToken'
|
16
|
-
'
|
17
|
-
'
|
18
|
-
'ActionController::
|
9
|
+
'ActionController::RoutingError' => :not_found,
|
10
|
+
'AbstractController::ActionNotFound' => :not_found,
|
11
|
+
'ActionController::MethodNotAllowed' => :method_not_allowed,
|
12
|
+
'ActionController::UnknownHttpMethod' => :method_not_allowed,
|
13
|
+
'ActionController::NotImplemented' => :not_implemented,
|
14
|
+
'ActionController::UnknownFormat' => :not_acceptable,
|
15
|
+
'ActionController::InvalidAuthenticityToken' => :unprocessable_entity,
|
16
|
+
'ActionController::InvalidCrossOriginRequest' => :unprocessable_entity,
|
17
|
+
'ActionDispatch::ParamsParser::ParseError' => :bad_request,
|
18
|
+
'ActionController::BadRequest' => :bad_request,
|
19
|
+
'ActionController::ParameterMissing' => :bad_request
|
19
20
|
)
|
20
21
|
|
21
22
|
cattr_accessor :rescue_templates
|
@@ -9,8 +9,12 @@ module ActionDispatch
|
|
9
9
|
def call(env)
|
10
10
|
status = env["PATH_INFO"][1..-1]
|
11
11
|
request = ActionDispatch::Request.new(env)
|
12
|
-
content_type = request.formats.first
|
13
12
|
body = { :status => status, :error => Rack::Utils::HTTP_STATUS_CODES.fetch(status.to_i, Rack::Utils::HTTP_STATUS_CODES[500]) }
|
13
|
+
content_type = begin
|
14
|
+
request.formats.first
|
15
|
+
rescue ActionController::BadRequest
|
16
|
+
Mime::HTML
|
17
|
+
end
|
14
18
|
|
15
19
|
render(status, content_type, body)
|
16
20
|
end
|
@@ -19,7 +19,7 @@ module ActionDispatch
|
|
19
19
|
paths = "#{full_path}#{ext}"
|
20
20
|
|
21
21
|
matches = Dir[paths]
|
22
|
-
match = matches.detect { |m| File.file?(m) }
|
22
|
+
match = matches.detect { |m| File.file?(m) && File.readable?(m) }
|
23
23
|
if match
|
24
24
|
match.sub!(@compiled_root, '')
|
25
25
|
::Rack::Utils.escape(match)
|
@@ -42,7 +42,7 @@ module ActionDispatch
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def escape_glob_chars(path)
|
45
|
-
path.gsub(/[*?{}\[\]]/, "\\\\\\&")
|
45
|
+
path.gsub(/[*?{}\[\]\\]/, "\\\\\\&")
|
46
46
|
end
|
47
47
|
|
48
48
|
private
|
@@ -235,7 +235,14 @@ module ActionDispatch
|
|
235
235
|
result = options.dup
|
236
236
|
|
237
237
|
if args.size > 0
|
238
|
-
|
238
|
+
# take format into account
|
239
|
+
if keys.include?(:format)
|
240
|
+
keys_size = keys.size - 1
|
241
|
+
else
|
242
|
+
keys_size = keys.size
|
243
|
+
end
|
244
|
+
|
245
|
+
if args.size < keys_size
|
239
246
|
keys -= t.url_options.keys if t.respond_to?(:url_options)
|
240
247
|
keys -= options.keys
|
241
248
|
end
|
@@ -38,7 +38,7 @@ module ActionDispatch
|
|
38
38
|
# # Test a custom route
|
39
39
|
# assert_recognizes({controller: 'items', action: 'show', id: '1'}, 'view/item1')
|
40
40
|
def assert_recognizes(expected_options, path, extras={}, msg=nil)
|
41
|
-
request = recognized_request_for(path, extras)
|
41
|
+
request = recognized_request_for(path, extras, msg)
|
42
42
|
|
43
43
|
expected_options = expected_options.clone
|
44
44
|
|
@@ -69,9 +69,9 @@ module ActionDispatch
|
|
69
69
|
#
|
70
70
|
# # Asserts that the generated route gives us our custom route
|
71
71
|
# assert_generates "changesets/12", { controller: 'scm', action: 'show_diff', revision: "12" }
|
72
|
-
def assert_generates(expected_path, options, defaults={}, extras
|
72
|
+
def assert_generates(expected_path, options, defaults={}, extras={}, message=nil)
|
73
73
|
if expected_path =~ %r{://}
|
74
|
-
fail_on(URI::InvalidURIError) do
|
74
|
+
fail_on(URI::InvalidURIError, message) do
|
75
75
|
uri = URI.parse(expected_path)
|
76
76
|
expected_path = uri.path.to_s.empty? ? "/" : uri.path
|
77
77
|
end
|
@@ -174,7 +174,7 @@ module ActionDispatch
|
|
174
174
|
|
175
175
|
private
|
176
176
|
# Recognizes the route for a given path.
|
177
|
-
def recognized_request_for(path, extras = {})
|
177
|
+
def recognized_request_for(path, extras = {}, msg)
|
178
178
|
if path.is_a?(Hash)
|
179
179
|
method = path[:method]
|
180
180
|
path = path[:path]
|
@@ -186,7 +186,7 @@ module ActionDispatch
|
|
186
186
|
request = ActionController::TestRequest.new
|
187
187
|
|
188
188
|
if path =~ %r{://}
|
189
|
-
fail_on(URI::InvalidURIError) do
|
189
|
+
fail_on(URI::InvalidURIError, msg) do
|
190
190
|
uri = URI.parse(path)
|
191
191
|
request.env["rack.url_scheme"] = uri.scheme || "http"
|
192
192
|
request.host = uri.host if uri.host
|
@@ -200,7 +200,7 @@ module ActionDispatch
|
|
200
200
|
|
201
201
|
request.request_method = method if method
|
202
202
|
|
203
|
-
params = fail_on(ActionController::RoutingError) do
|
203
|
+
params = fail_on(ActionController::RoutingError, msg) do
|
204
204
|
@routes.recognize_path(path, { :method => method, :extras => extras })
|
205
205
|
end
|
206
206
|
request.path_parameters = params.with_indifferent_access
|
@@ -208,10 +208,10 @@ module ActionDispatch
|
|
208
208
|
request
|
209
209
|
end
|
210
210
|
|
211
|
-
def fail_on(exception_class)
|
211
|
+
def fail_on(exception_class, message)
|
212
212
|
yield
|
213
213
|
rescue exception_class => e
|
214
|
-
raise Minitest::Assertion, e.message
|
214
|
+
raise Minitest::Assertion, message || e.message
|
215
215
|
end
|
216
216
|
end
|
217
217
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actionpack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.
|
4
|
+
version: 4.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 4.1.
|
19
|
+
version: 4.1.9
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 4.1.
|
26
|
+
version: 4.1.9
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rack
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,28 +58,28 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - '='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 4.1.
|
61
|
+
version: 4.1.9
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 4.1.
|
68
|
+
version: 4.1.9
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: activemodel
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 4.1.
|
75
|
+
version: 4.1.9
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 4.1.
|
82
|
+
version: 4.1.9
|
83
83
|
description: Web apps on Rails. Simple, battle-tested conventions for building and
|
84
84
|
testing MVC web applications. Works with any Rack-compatible server.
|
85
85
|
email: david@loudthinking.com
|
@@ -258,7 +258,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
258
258
|
requirements:
|
259
259
|
- none
|
260
260
|
rubyforge_project:
|
261
|
-
rubygems_version: 2.
|
261
|
+
rubygems_version: 2.4.5
|
262
262
|
signing_key:
|
263
263
|
specification_version: 4
|
264
264
|
summary: Web-flow and rendering framework putting the VC in MVC (part of Rails).
|