Permalink
Browse files

Merge remote branch 'rails/master'

  • Loading branch information...
2 parents b9fcd8d + 61001e7 commit 7f07cc364a7ee7ceae21b29b54467fde0db93389 @fxn fxn committed May 19, 2010
Showing with 1,359 additions and 872 deletions.
  1. +9 −8 Gemfile
  2. +2 −2 actionmailer/test/base_test.rb
  3. +4 −4 actionmailer/test/old_base/asset_host_test.rb
  4. +1 −1 actionmailer/test/old_base/mail_render_test.rb
  5. +14 −13 actionmailer/test/old_base/mail_service_test.rb
  6. +2 −2 actionmailer/test/test_helper_test.rb
  7. +2 −0 actionpack/CHANGELOG
  8. +1 −1 actionpack/lib/action_controller/metal/helpers.rb
  9. +2 −33 actionpack/lib/action_dispatch/http/response.rb
  10. +44 −10 actionpack/lib/action_dispatch/middleware/cookies.rb
  11. +43 −79 actionpack/lib/action_dispatch/middleware/session/abstract_store.rb
  12. +19 −165 actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
  13. +2 −2 actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb
  14. +0 −2 actionpack/lib/action_dispatch/railtie.rb
  15. +5 −0 actionpack/lib/action_dispatch/routing/mapper.rb
  16. +5 −1 actionpack/lib/action_view.rb
  17. +2 −1 actionpack/lib/action_view/base.rb
  18. +5 −2 actionpack/lib/action_view/helpers/number_helper.rb
  19. +170 −25 actionpack/lib/action_view/template.rb
  20. +18 −0 actionpack/lib/action_view/template/error.rb
  21. +94 −45 actionpack/lib/action_view/template/handlers/erb.rb
  22. +4 −1 actionpack/lib/action_view/template/resolver.rb
  23. +4 −4 actionpack/test/abstract/translation_test.rb
  24. +5 −0 actionpack/test/abstract_unit.rb
  25. +7 −1 actionpack/test/activerecord/active_record_store_test.rb
  26. +2 −2 actionpack/test/controller/assert_select_test.rb
  27. +1 −1 actionpack/test/controller/capture_test.rb
  28. +54 −1 actionpack/test/controller/cookie_test.rb
  29. +7 −7 actionpack/test/controller/filters_test.rb
  30. +10 −1 actionpack/test/controller/flash_test.rb
  31. +2 −2 actionpack/test/controller/integration_test.rb
  32. +2 −2 actionpack/test/controller/new_base/bare_metal_test.rb
  33. +2 −2 actionpack/test/controller/render_test.rb
  34. +2 −2 actionpack/test/controller/send_file_test.rb
  35. +4 −0 actionpack/test/dispatch/response_test.rb
  36. +11 −1 actionpack/test/dispatch/routing_test.rb
  37. +20 −46 actionpack/test/dispatch/session/cookie_store_test.rb
  38. +6 −1 actionpack/test/dispatch/session/mem_cache_store_test.rb
  39. +0 −12 actionpack/test/dispatch/session/test_session_test.rb
  40. +1 −2 actionpack/test/fixtures/test/content_for.erb
  41. +1 −1 actionpack/test/fixtures/test/content_for_concatenated.erb
  42. +1 −1 actionpack/test/fixtures/test/content_for_with_parameter.erb
  43. +1 −1 actionpack/test/fixtures/test/non_erb_block_content_for.builder
  44. +17 −0 actionpack/test/template/number_helper_i18n_test.rb
  45. +5 −5 actionpack/test/template/render_test.rb
  46. +130 −0 actionpack/test/template/template_test.rb
  47. +8 −3 activemodel/lib/active_model/validations/numericality.rb
  48. +1 −1 activemodel/test/cases/attribute_methods_test.rb
  49. +1 −1 activemodel/test/cases/callbacks_test.rb
  50. +2 −2 activemodel/test/cases/dirty_test.rb
  51. +6 −3 activemodel/test/cases/serializeration/xml_serialization_test.rb
  52. +1 −1 activemodel/test/cases/validations/numericality_validation_test.rb
  53. +22 −1 activerecord/lib/active_record/autosave_association.rb
  54. +13 −10 activerecord/lib/active_record/base.rb
  55. +57 −0 activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb
  56. +39 −6 activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
  57. +2 −0 activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
  58. +1 −5 activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
  59. +6 −3 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
  60. +2 −2 activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
  61. +1 −1 activerecord/lib/active_record/session_store.rb
  62. +5 −0 activerecord/test/cases/active_schema_test_mysql.rb
  63. +10 −10 activerecord/test/cases/aggregations_test.rb
  64. +2 −2 activerecord/test/cases/associations/belongs_to_associations_test.rb
  65. +1 −1 activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb
  66. +1 −1 activerecord/test/cases/associations/eager_test.rb
  67. +3 −10 activerecord/test/cases/associations/has_many_associations_test.rb
  68. +2 −2 activerecord/test/cases/associations/has_many_through_associations_test.rb
  69. +4 −4 activerecord/test/cases/associations/has_one_associations_test.rb
  70. +9 −9 activerecord/test/cases/associations/inverse_associations_test.rb
  71. +2 −2 activerecord/test/cases/associations/join_model_test.rb
  72. +1 −1 activerecord/test/cases/attribute_methods_test.rb
  73. +4 −4 activerecord/test/cases/autosave_association_test.rb
  74. +75 −25 activerecord/test/cases/base_test.rb
  75. +3 −3 activerecord/test/cases/column_definition_test.rb
  76. +2 −2 activerecord/test/cases/defaults_test.rb
  77. +2 −2 activerecord/test/cases/dirty_test.rb
  78. +11 −11 activerecord/test/cases/finder_respond_to_test.rb
  79. +1 −1 activerecord/test/cases/finder_test.rb
  80. +7 −7 activerecord/test/cases/inheritance_test.rb
  81. +1 −13 activerecord/test/cases/method_scoping_test.rb
  82. +35 −13 activerecord/test/cases/migration_test.rb
  83. +1 −1 activerecord/test/cases/modules_test.rb
  84. +80 −0 activerecord/test/cases/nested_attributes_test.rb
  85. +2 −2 activerecord/test/cases/pk_test.rb
  86. +3 −3 activerecord/test/cases/pooled_connections_test.rb
  87. +1 −1 activerecord/test/cases/query_cache_test.rb
  88. +3 −3 activerecord/test/cases/relations_test.rb
  89. +1 −1 activerecord/test/cases/reserved_word_test_mysql.rb
  90. +2 −2 activerecord/test/cases/schema_test_postgresql.rb
  91. +8 −8 activerecord/test/cases/timestamp_test.rb
  92. +37 −41 activerecord/test/cases/transaction_callbacks_test.rb
  93. +2 −1 activerecord/test/models/ship.rb
  94. +2 −0 activerecord/test/models/ship_part.rb
  95. +6 −6 activeresource/test/cases/base/schema_test.rb
  96. +6 −6 activeresource/test/cases/base_test.rb
  97. +3 −1 activesupport/CHANGELOG
  98. +1 −11 activesupport/lib/active_support/core_ext/array/random_access.rb
  99. +0 −11 activesupport/lib/active_support/core_ext/date/calculations.rb
  100. +11 −0 activesupport/lib/active_support/core_ext/string/encoding.rb
  101. +0 −11 activesupport/lib/active_support/core_ext/time/calculations.rb
  102. +1 −0 activesupport/lib/active_support/ruby/shim.rb
  103. +6 −6 activesupport/test/buffered_logger_test.rb
  104. +1 −1 activesupport/test/callbacks_test.rb
  105. +0 −4 activesupport/test/core_ext/array_ext_test.rb
  106. +4 −4 activesupport/test/core_ext/class/attribute_accessor_test.rb
  107. +2 −2 activesupport/test/core_ext/class/class_inheritable_attributes_test.rb
  108. +4 −4 activesupport/test/core_ext/class/delegating_attributes_test.rb
  109. +0 −8 activesupport/test/core_ext/date_ext_test.rb
  110. +2 −2 activesupport/test/core_ext/date_time_ext_test.rb
  111. +2 −2 activesupport/test/core_ext/duration_test.rb
  112. +4 −4 activesupport/test/core_ext/module/attribute_accessor_test.rb
  113. +3 −3 activesupport/test/core_ext/module/synchronization_test.rb
  114. +5 −5 activesupport/test/core_ext/module_test.rb
  115. +15 −7 activesupport/test/core_ext/string_ext_test.rb
  116. +0 −8 activesupport/test/core_ext/time_ext_test.rb
  117. +6 −6 activesupport/test/core_ext/time_with_zone_test.rb
  118. +3 −3 activesupport/test/multibyte_chars_test.rb
  119. +1 −1 activesupport/test/time_zone_test.rb
  120. +21 −0 railties/guides/source/getting_started.textile
  121. +1 −0 railties/lib/rails.rb
  122. +11 −7 railties/lib/rails/application/configuration.rb
  123. +0 −24 railties/lib/rails/dispatcher.rb
  124. +4 −3 railties/test/application/configuration_test.rb
  125. +2 −2 railties/test/application/initializers/frameworks_test.rb
  126. +4 −1 railties/test/application/middleware_test.rb
  127. +2 −2 railties/test/application/rackup_test.rb
View
17 Gemfile
@@ -6,17 +6,18 @@ gem "rails", :path => File.dirname(__FILE__)
gem "rake", ">= 0.8.7"
gem "mocha", ">= 0.9.8"
-group :mri do
+mri = !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
+if mri && RUBY_VERSION < '1.9'
+ gem "system_timer"
+ gem "ruby-debug", ">= 0.10.3"
+end
+
+if mri || RUBY_ENGINE == "rbx"
gem 'json'
gem 'yajl-ruby'
gem "nokogiri", ">= 1.4.0"
-
- if RUBY_VERSION < '1.9'
- gem "system_timer"
- gem "ruby-debug", ">= 0.10.3"
- elsif RUBY_VERSION < '1.9.2' && !ENV['CI']
- gem "ruby-debug19"
- end
+elsif RUBY_ENGINE == "jruby"
+ gem "jruby-debug"
end
# AR
@@ -491,8 +491,8 @@ def give_a_greeting
# Class level API with method missing
test "should respond to action methods" do
- assert BaseMailer.respond_to?(:welcome)
- assert BaseMailer.respond_to?(:implicit_multipart)
+ assert_respond_to BaseMailer, :welcome
+ assert_respond_to BaseMailer, :implicit_multipart
assert !BaseMailer.respond_to?(:mail)
assert !BaseMailer.respond_to?(:headers)
end
@@ -26,7 +26,7 @@ def teardown
def test_asset_host_as_string
mail = AssetHostMailer.email_with_asset
- assert_equal "<img alt=\"Somelogo\" src=\"http://www.example.com/images/somelogo.png\" />", mail.body.to_s.strip
+ assert_equal %Q{<img alt="Somelogo" src="http://www.example.com/images/somelogo.png" />}, mail.body.to_s.strip
end
def test_asset_host_as_one_arguement_proc
@@ -38,7 +38,7 @@ def test_asset_host_as_one_arguement_proc
end
}
mail = AssetHostMailer.email_with_asset
- assert_equal "<img alt=\"Somelogo\" src=\"http://images.example.com/images/somelogo.png\" />", mail.body.to_s.strip
+ assert_equal %Q{<img alt="Somelogo" src="http://images.example.com/images/somelogo.png" />}, mail.body.to_s.strip
end
def test_asset_host_as_two_arguement_proc
@@ -51,6 +51,6 @@ def test_asset_host_as_two_arguement_proc
}
mail = nil
assert_nothing_raised { mail = AssetHostMailer.email_with_asset }
- assert_equal "<img alt=\"Somelogo\" src=\"http://www.example.com/images/somelogo.png\" />", mail.body.to_s.strip
+ assert_equal %Q{<img alt="Somelogo" src="http://www.example.com/images/somelogo.png" />}, mail.body.to_s.strip
end
-end
+end
@@ -117,7 +117,7 @@ def test_file_template
def test_rxml_template
mail = RenderMailer.rxml_template.deliver
- assert_equal "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<test/>", mail.body.to_s.strip
+ assert_equal %(<?xml version="1.0" encoding="UTF-8"?>\n<test/>), mail.body.to_s.strip
end
def test_included_subtemplate
@@ -281,23 +281,23 @@ def headers_with_nonalpha_chars(recipient)
from "One: Two <test@example.com>"
cc "Three: Four <test@example.com>"
bcc "Five: Six <test@example.com>"
- body "testing"
+ body "testing"
end
def custom_content_type_attributes
recipients "no.one@nowhere.test"
subject "custom content types"
from "some.one@somewhere.test"
content_type "text/plain; format=flowed"
- body "testing"
+ body "testing"
end
def return_path
recipients "no.one@nowhere.test"
subject "return path test"
from "some.one@somewhere.test"
headers["return-path"] = "another@somewhere.test"
- body "testing"
+ body "testing"
end
def subject_with_i18n(recipient)
@@ -417,7 +417,7 @@ def test_signed_up
end
def test_custom_template
- expected = new_mail
+ expected = new_mail
expected.to = @recipient
expected.subject = "[Signed up] Welcome #{@recipient}"
expected.body = "Hello there, \n\nMr. #{@recipient}"
@@ -436,7 +436,7 @@ def test_custom_templating_extension
assert ActionView::Template.template_handler_extensions.include?("haml"), "haml extension was not registered"
# N.b., custom_templating_extension.text.plain.haml is expected to be in fixtures/test_mailer directory
- expected = new_mail
+ expected = new_mail
expected.to = @recipient
expected.subject = "[Signed up] Welcome #{@recipient}"
expected.body = "Hello there, \n\nMr. #{@recipient}"
@@ -453,7 +453,7 @@ def test_custom_templating_extension
end
def test_cancelled_account
- expected = new_mail
+ expected = new_mail
expected.to = @recipient
expected.subject = "[Cancelled] Goodbye #{@recipient}"
expected.body = "Goodbye, Mr. #{@recipient}"
@@ -477,7 +477,7 @@ def test_cancelled_account
end
def test_cc_bcc
- expected = new_mail
+ expected = new_mail
expected.to = @recipient
expected.subject = "testing bcc/cc"
expected.body = "Nothing to see here."
@@ -602,7 +602,7 @@ def test_iso_charset
def test_unencoded_subject
TestMailer.delivery_method = :test
- expected = new_mail
+ expected = new_mail
expected.to = @recipient
expected.subject = "testing unencoded subject"
expected.body = "Nothing to see here."
@@ -1048,8 +1048,9 @@ def test_with_mail_object_deliver
def test_multipart_with_template_path_with_dots
mail = FunkyPathMailer.multipart_with_template_path_with_dots(@recipient)
assert_equal 2, mail.parts.length
- assert "text/plain", mail.parts[1].mime_type
- assert "UTF-8", mail.parts[1].charset
+ assert_equal "text/plain", mail.parts[0].mime_type
+ assert_equal "text/html", mail.parts[1].mime_type
+ assert_equal "UTF-8", mail.parts[1].charset
end
def test_custom_content_type_attributes
@@ -1150,15 +1151,15 @@ def teardown
end
def test_should_respond_to_new
- assert RespondToMailer.respond_to?(:new)
+ assert_respond_to RespondToMailer, :new
end
def test_should_respond_to_create_with_template_suffix
- assert RespondToMailer.respond_to?(:create_any_old_template)
+ assert_respond_to RespondToMailer, :create_any_old_template
end
def test_should_respond_to_deliver_with_template_suffix
- assert RespondToMailer.respond_to?(:deliver_any_old_template)
+ assert_respond_to RespondToMailer, :deliver_any_old_template
end
def test_should_not_respond_to_new_with_template_suffix
@@ -18,7 +18,7 @@ def test_setup_sets_right_action_mailer_options
end
def test_setup_creates_the_expected_mailer
- assert @expected.is_a?(Mail::Message)
+ assert_kind_of Mail::Message, @expected
assert_equal "1.0", @expected.mime_version
assert_equal "text/plain", @expected.mime_type
end
@@ -121,7 +121,7 @@ def setup
end
def test_setup_shouldnt_conflict_with_mailer_setup
- assert @expected.is_a?(Mail::Message)
+ assert_kind_of Mail::Message, @expected
assert_equal 'a value', @test_var
end
end
View
@@ -1,5 +1,7 @@
*Rails 3.0.0 [beta 4/release candidate] (unreleased)*
+* Make session stores rely on request.cookie_jar and change set_session semantics to return the cookie value instead of a boolean. [José Valim]
+
* OAuth 2: HTTP Token Authorization support to complement Basic and Digest Authorization. [Rick Olson]
* Fixed inconsistencies in form builder and view helpers #4432 [Neeraj Singh]
@@ -104,7 +104,7 @@ def modules_for_helpers(args)
def all_application_helpers
helpers = []
helpers_path.each do |path|
- extract = /^#{Regexp.quote(path)}\/?(.*)_helper.rb$/
+ extract = /^#{Regexp.quote(path.to_s)}\/?(.*)_helper.rb$/
helpers += Dir["#{path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') }
end
helpers.sort!
@@ -140,7 +140,7 @@ def location=(url)
def to_a
assign_default_content_type_and_charset!
handle_conditional_get!
- self["Set-Cookie"] = @cookie.join("\n") unless @cookie.blank?
+ self["Set-Cookie"] = self["Set-Cookie"].join("\n") if self["Set-Cookie"].respond_to?(:join)
self["ETag"] = @_etag if @_etag
super
end
@@ -170,7 +170,7 @@ def write(str)
# assert_equal 'AuthorOfNewPage', r.cookies['author']
def cookies
cookies = {}
- if header = @cookie
+ if header = self["Set-Cookie"]
header = header.split("\n") if header.respond_to?(:to_str)
header.each do |cookie|
if pair = cookie.split(';').first
@@ -182,37 +182,6 @@ def cookies
cookies
end
- def set_cookie(key, value)
- case value
- when Hash
- domain = "; domain=" + value[:domain] if value[:domain]
- path = "; path=" + value[:path] if value[:path]
- # According to RFC 2109, we need dashes here.
- # N.B.: cgi.rb uses spaces...
- expires = "; expires=" + value[:expires].clone.gmtime.
- strftime("%a, %d-%b-%Y %H:%M:%S GMT") if value[:expires]
- secure = "; secure" if value[:secure]
- httponly = "; HttpOnly" if value[:httponly]
- value = value[:value]
- end
- value = [value] unless Array === value
- cookie = Rack::Utils.escape(key) + "=" +
- value.map { |v| Rack::Utils.escape v }.join("&") +
- "#{domain}#{path}#{expires}#{secure}#{httponly}"
-
- @cookie << cookie
- end
-
- def delete_cookie(key, value={})
- @cookie.reject! { |cookie|
- cookie =~ /\A#{Rack::Utils.escape(key)}=/
- }
-
- set_cookie(key,
- {:value => '', :path => nil, :domain => nil,
- :expires => Time.at(0) }.merge(value))
- end
-
private
def assign_default_content_type_and_charset!
return if headers[CONTENT_TYPE].present?
@@ -52,9 +52,15 @@ def cookie_jar
# * <tt>:httponly</tt> - Whether this cookie is accessible via scripting or
# only HTTP. Defaults to +false+.
class Cookies
+ HTTP_HEADER = "Set-Cookie".freeze
+ TOKEN_KEY = "action_dispatch.secret_token".freeze
+
+ # Raised when storing more than 4K of session data.
+ class CookieOverflow < StandardError; end
+
class CookieJar < Hash #:nodoc:
def self.build(request)
- secret = request.env["action_dispatch.secret_token"]
+ secret = request.env[TOKEN_KEY]
new(secret).tap do |hash|
hash.update(request.cookies)
end
@@ -134,9 +140,9 @@ def signed
@signed ||= SignedCookieJar.new(self, @secret)
end
- def write(response)
- @set_cookies.each { |k, v| response.set_cookie(k, v) }
- @delete_cookies.each { |k, v| response.delete_cookie(k, v) }
+ def write(headers)
+ @set_cookies.each { |k, v| ::Rack::Utils.set_cookie_header!(headers, k, v) }
+ @delete_cookies.each { |k, v| ::Rack::Utils.delete_cookie_header!(headers, k, v) }
end
end
@@ -166,8 +172,11 @@ def method_missing(method, *arguments, &block)
end
class SignedCookieJar < CookieJar #:nodoc:
+ MAX_COOKIE_SIZE = 4096 # Cookies can typically store 4096 bytes.
+ SECRET_MIN_LENGTH = 30 # Characters
+
def initialize(parent_jar, secret)
- raise "You must set config.secret_token in your app's config" if secret.blank?
+ ensure_secret_secure(secret)
@parent_jar = parent_jar
@verifier = ActiveSupport::MessageVerifier.new(secret)
end
@@ -176,6 +185,8 @@ def [](name)
if signed_message = @parent_jar[name]
@verifier.verify(signed_message)
end
+ rescue ActiveSupport::MessageVerifier::InvalidSignature
+ nil
end
def []=(key, options)
@@ -186,12 +197,34 @@ def []=(key, options)
options = { :value => @verifier.generate(options) }
end
+ raise CookieOverflow if options[:value].size > MAX_COOKIE_SIZE
@parent_jar[key] = options
end
def method_missing(method, *arguments, &block)
@parent_jar.send(method, *arguments, &block)
end
+
+ protected
+
+ # To prevent users from using something insecure like "Password" we make sure that the
+ # secret they've provided is at least 30 characters in length.
+ def ensure_secret_secure(secret)
+ if secret.blank?
+ raise ArgumentError, "A secret is required to generate an " +
+ "integrity hash for cookie session data. Use " +
+ "config.secret_token = \"some secret phrase of at " +
+ "least #{SECRET_MIN_LENGTH} characters\"" +
+ "in config/application.rb"
+ end
+
+ if secret.length < SECRET_MIN_LENGTH
+ raise ArgumentError, "Secret should be something secure, " +
+ "like \"#{ActiveSupport::SecureRandom.hex(16)}\". The value you " +
+ "provided, \"#{secret}\", is shorter than the minimum length " +
+ "of #{SECRET_MIN_LENGTH} characters"
+ end
+ end
end
def initialize(app)
@@ -202,12 +235,13 @@ def call(env)
status, headers, body = @app.call(env)
if cookie_jar = env['action_dispatch.cookies']
- response = Rack::Response.new(body, status, headers)
- cookie_jar.write(response)
- response.to_a
- else
- [status, headers, body]
+ cookie_jar.write(headers)
+ if headers[HTTP_HEADER].respond_to?(:join)
+ headers[HTTP_HEADER] = headers[HTTP_HEADER].join("\n")
+ end
end
+
+ [status, headers, body]
end
end
end
Oops, something went wrong.

0 comments on commit 7f07cc3

Please sign in to comment.