Compare commits

..

1 Commits

Author SHA1 Message Date
Charlie Somerville
81d67c66b0 bump RAILS_VERSION to github38 2014-01-21 14:56:19 +11:00
15 changed files with 72 additions and 132 deletions

View File

@@ -1 +1 @@
2.3.14.github45
2.3.14.github38

View File

@@ -1320,14 +1320,7 @@ module ActionController #:nodoc:
render
end
CVE_2014_0310 = Class.new(StandardError)
def perform_action
# CVE-2014-0130 protection
if action_name.include? "/"
raise CVE_2014_0310
end
if action_methods.include?(action_name)
send(action_name)
default_render unless performed?

View File

@@ -87,6 +87,7 @@ module ActionController #:nodoc:
log_message << " [#{complete_request_uri rescue "unknown"}]"
logger.info(log_message)
response.headers["X-Runtime"] = "%.0f" % ms
else
perform_action_without_benchmark
end

View File

@@ -45,74 +45,37 @@ module ActionController #:nodoc:
end
def []=(k, v)
k = k.to_s
@flash[k] = v
@flash.discard(k)
v
end
def [](k)
@flash[k.to_s]
@flash[k]
end
end
class FlashHash < Hash
def self.from_session_value(value)
flash = case value
when FlashHash # Rails 2.3
value
when Hash # Rails 4.0
flashes = value['flashes'] || {}
flashes.stringify_keys!
discard = value['discard'] || []
discard = discard.map do |item|
item.kind_of?(Symbol) ? item.to_s : item
end
used = Hash[flashes.keys.map{|k| [k, discard.include?(k)] }]
new_from_values(flashes, used)
else
new
end
flash
end
def initialize #:nodoc:
super
@used = {}
end
def to_session_value
return nil if empty?
rails_3_discard_list = @used.map{|k,v| k if v}.compact
{'discard' => rails_3_discard_list, 'flashes' => Hash[to_a]}
end
def []=(k, v) #:nodoc:
k = k.to_s
keep(k)
super(k, v)
end
def [](k)
super(k.to_s)
end
def delete(k)
super(k.to_s)
super
end
def update(h) #:nodoc:
h.stringify_keys!
h.keys.each { |k| keep(k) }
super(h)
super
end
alias :merge! :update
def replace(h) #:nodoc:
@used = {}
super(h.stringify_keys)
super
end
# Sets a flash that will not be available to the next action, only to the current.
@@ -163,7 +126,8 @@ module ActionController #:nodoc:
end
def store(session, key = "flash")
session[key] = to_session_value
return if self.empty?
session[key] = self
end
private
@@ -174,20 +138,11 @@ module ActionController #:nodoc:
# use('msg', false) # marks the "msg" entry as unused (keeps it around for one more action)
def use(k=nil, v=true)
unless k.nil?
@used[k.to_s] = v
@used[k] = v
else
keys.each{ |key| use(key, v) }
end
end
def self.new_from_values(flashes, used)
new.tap do |flash_hash|
flashes.each do |k, v|
flash_hash[k] = v
end
flash_hash.instance_variable_set("@used", used)
end
end
end
module InstanceMethods #:nodoc:
@@ -213,11 +168,11 @@ module ActionController #:nodoc:
if notice = response_status_and_flash.delete(:notice)
flash[:notice] = notice
end
if other_flashes = response_status_and_flash.delete(:flash)
flash.update(other_flashes)
end
redirect_to_without_flash(options, response_status_and_flash)
end
@@ -226,19 +181,19 @@ module ActionController #:nodoc:
# to put a new one.
def flash #:doc:
if !defined?(@_flash)
@_flash = Flash::FlashHash.from_session_value(session["flash"])
@_flash = session["flash"] || FlashHash.new
@_flash.sweep
end
@_flash
end
# Convenience accessor for flash[:alert]
def alert
flash[:alert]
end
# Convenience accessor for flash[:alert]=
def alert=(message)
flash[:alert] = message
@@ -248,7 +203,7 @@ module ActionController #:nodoc:
def notice
flash[:notice]
end
# Convenience accessor for flash[:notice]=
def notice=(message)
flash[:notice] = message

View File

@@ -2,7 +2,7 @@ require 'rack/utils'
module ActionController
module Session
class AbstractStore
class AbstractStore
ENV_SESSION_KEY = 'rack.session'.freeze
ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze
@@ -55,17 +55,17 @@ module ActionController
def [](key)
load_for_read!
super(key.to_s) || super(key)
super
end
def has_key?(key)
load_for_read!
super(key.to_s) || super(key)
super
end
def []=(key, value)
load_for_write!
super(key.to_s, value)
super
end
def clear
@@ -87,9 +87,7 @@ module ActionController
def delete(key)
load_for_write!
value = super(key)
string_value = super(key.to_s)
string_value || value
super
end
def data
@@ -121,7 +119,7 @@ module ActionController
end
private
def load_for_read!
load! if !loaded? && exists?
end
@@ -185,7 +183,7 @@ module ActionController
request = ActionController::Request.new(env)
return response if (options[:secure] && !request.ssl?)
session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.loaded?
sid = options[:id] || generate_sid
@@ -207,12 +205,12 @@ module ActionController
end
private
def prepare!(env)
env[ENV_SESSION_KEY] = SessionHash.new(self, env)
env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options)
end
def generate_sid
ActiveSupport::SecureRandom.hex(16)
end
@@ -224,7 +222,7 @@ module ActionController
[sid, session]
end
end
def extract_session_id(env)
stale_session_check! do
request = Rack::Request.new(env)
@@ -237,7 +235,7 @@ module ActionController
def current_session_id(env)
env[ENV_SESSION_OPTIONS_KEY][:id]
end
def exists?(env)
current_session_id(env).present?
end
@@ -249,11 +247,11 @@ module ActionController
def set_session(env, sid, session_data)
raise '#set_session needs to be implemented.'
end
def destroy(env)
raise '#destroy needs to be implemented.'
end
module SessionUtils
private
def stale_session_check!

View File

@@ -37,7 +37,7 @@ module ActionController
# Note that changing digest or secret invalidates all existing sessions!
class CookieStore
include AbstractStore::SessionUtils
# Cookies can typically store 4096 bytes.
MAX = 4096
SECRET_MIN_LENGTH = 30 # characters
@@ -86,8 +86,7 @@ module ActionController
@secret = options.delete(:secret).freeze
@digest = options.delete(:digest) || 'SHA1'
@serializer = options.delete(:serializer) || Marshal
@verifier = verifier_for(@secret, @digest, @serializer)
@verifier = verifier_for(@secret, @digest)
@default_options = DEFAULT_OPTIONS.merge(options).freeze
@@ -96,21 +95,14 @@ module ActionController
def call(env)
prepare!(env)
status, headers, body = @app.call(env)
session_data = env[ENV_SESSION_KEY]
options = env[ENV_SESSION_OPTIONS_KEY]
request = ActionController::Request.new(env)
if !(options[:secure] && !request.ssl?) && (!session_data.is_a?(AbstractStore::SessionHash) || session_data.loaded? || options[:expire_after])
# Backport standard Rack::Session::Cookie behavior
# Skip writing session if env['rack.session.options'][:skip] is set
if options[:skip]
return [status, headers, body]
end
session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.loaded?
persistent_session_id!(session_data)
@@ -130,7 +122,7 @@ module ActionController
end
private
def prepare!(env)
env[ENV_SESSION_KEY] = AbstractStore::SessionHash.new(self, env)
env[ENV_SESSION_OPTIONS_KEY] = AbstractStore::OptionsHash.new(self, env, @default_options)
@@ -139,13 +131,13 @@ module ActionController
def load_session(env)
data = unpacked_cookie_data(env)
data = persistent_session_id!(data)
[data["session_id"] || data[:session_id], data]
[data[:session_id], data]
end
def extract_session_id(env)
if data = unpacked_cookie_data(env)
persistent_session_id!(data) unless data.empty?
data["session_id"] || data[:session_id]
data[:session_id]
else
nil
end
@@ -215,9 +207,9 @@ module ActionController
end
end
def verifier_for(secret, digest, serializer)
def verifier_for(secret, digest)
key = secret.respond_to?(:call) ? secret.call : secret
ActiveSupport::MessageVerifier.new(key, digest: digest, serializer: serializer)
ActiveSupport::MessageVerifier.new(key, digest: digest)
end
def generate_sid
@@ -233,12 +225,12 @@ module ActionController
end
def inject_persistent_session_id(data)
requires_session_id?(data) ? { "session_id" => generate_sid } : {}
requires_session_id?(data) ? { :session_id => generate_sid } : {}
end
def requires_session_id?(data)
if data
data.respond_to?(:key?) && !(data.key?("session_id") || data.key?(:session_id))
data.respond_to?(:key?) && !data.key?(:session_id)
else
true
end

View File

@@ -219,7 +219,7 @@ module ActionController #:nodoc:
# A shortcut to the flash. Returns an empty hash if no session flash exists.
def flash
ActionController::Flash::FlashHash.from_session_value(session["flash"]) || {}
session['flash'] || {}
end
# Do we have a flash?

View File

@@ -73,8 +73,6 @@ module ActionView
def number_to_currency(number, options = {})
options.symbolize_keys!
options[:format] = ERB::Util.html_escape(options[:format]) if options[:format]
defaults = I18n.translate(:'number.format', :locale => options[:locale], :raise => true) rescue {}
currency = I18n.translate(:'number.currency.format', :locale => options[:locale], :raise => true) rescue {}
defaults = defaults.merge(currency)

View File

@@ -3,12 +3,6 @@ require 'abstract_unit'
class NumberHelperTest < ActionView::TestCase
tests ActionView::Helpers::NumberHelper
def test_number_helpers_escape_delimiter_and_separator
assert_equal "$1&lt;script&gt;&lt;/script&gt;01", number_to_currency(1.01, :separator => "<script></script>")
assert_equal "$1&lt;script&gt;&lt;/script&gt;000.00", number_to_currency(1000, :delimiter => "<script></script>")
assert_equal "&lt;script&gt;1,000.00$&lt;/script&gt;", number_to_currency(1000, :format => "<script>%n%u</script>")
end
def test_number_to_phone
assert_equal("555-1234", number_to_phone(5551234))
assert_equal("800-555-1212", number_to_phone(8005551212))

View File

@@ -195,9 +195,7 @@ module ActiveRecord
def log_info(sql, name, ms)
if @logger && @logger.debug?
name = '%s (%.1fms)' % [name || 'SQL', ms]
if sql.respond_to?(:force_encoding)
sql = sql.dup.force_encoding 'binary'
end
sql.force_encoding 'binary' if sql.respond_to?(:force_encoding)
@logger.debug(format_log_entry(name, sql.squeeze(' ')))
end
end
@@ -214,7 +212,13 @@ module ActiveRecord
log_info(sql, name, 0)
nil
end
rescue => e
rescue SystemExit, SignalException, NoMemoryError => e
# Don't re-wrap these exceptions. They are probably not being caused by invalid
# sql, but rather some external stimulus beyond the responsibilty of this code.
# Additionaly, wrapping these exceptions with StatementInvalid would lead to
# meaningful loss of data, such as losing SystemExit#status.
raise e
rescue Exception => e
# Log message and raise exception.
# Set last_verification to 0, so that connection gets verified
# upon reentering the request loop

View File

@@ -1,4 +1,5 @@
require 'active_support/core_ext/kernel/daemonizing'
require 'active_support/core_ext/kernel/reporting'
require 'active_support/core_ext/kernel/agnostics'
require 'active_support/core_ext/kernel/requires'
require 'active_support/core_ext/kernel/debugger'

View File

@@ -0,0 +1,11 @@
class Object
# Makes backticks behave (somewhat more) similarly on all platforms.
# On win32 `nonexistent_command` raises Errno::ENOENT; on Unix, the
# spawned shell prints a message to stderr and sets $?. We emulate
# Unix on the former but not the latter.
def `(command) #:nodoc:
super
rescue Errno::ENOENT => e
STDERR.puts "#$0: #{e}"
end
end

View File

@@ -1,6 +1,3 @@
require 'active_support/core_ext/kernel/singleton_class'
require 'active_support/core_ext/module/aliasing'
module ActiveSupport
module Memoizable
def self.memoized_ivar_for(symbol)
@@ -44,10 +41,10 @@ module ActiveSupport
end
end
def flush_cache(*syms)
def flush_cache(*syms, &block)
syms.each do |sym|
(methods + private_methods + protected_methods).each do |m|
if m.to_s =~ /^_unmemoized_(#{sym.to_s.gsub(/\?\Z/, '\?')})/
if m.to_s =~ /^_unmemoized_(#{sym})/
ivar = ActiveSupport::Memoizable.memoized_ivar_for($1)
instance_variable_get(ivar).clear if instance_variable_defined?(ivar)
end
@@ -72,7 +69,7 @@ module ActiveSupport
if instance_method(:#{symbol}).arity == 0 # if instance_method(:mime_type).arity == 0
def #{symbol}(reload = false) # def mime_type(reload = false)
if reload || !defined?(#{memoized_ivar}) || #{memoized_ivar}.empty? # if reload || !defined?(@_memoized_mime_type) || @_memoized_mime_type.empty?
#{memoized_ivar} = [#{original_method}] # @_memoized_mime_type = [_unmemoized_mime_type]
#{memoized_ivar} = [#{original_method}.freeze] # @_memoized_mime_type = [_unmemoized_mime_type.freeze]
end # end
#{memoized_ivar}[0] # @_memoized_mime_type[0]
end # end
@@ -85,7 +82,7 @@ module ActiveSupport
if !reload && #{memoized_ivar}.has_key?(args) # if !reload && @_memoized_mime_type.has_key?(args)
#{memoized_ivar}[args] # @_memoized_mime_type[args]
elsif #{memoized_ivar} # elsif @_memoized_mime_type
#{memoized_ivar}[args] = #{original_method}(*args) # @_memoized_mime_type[args] = _unmemoized_mime_type(*args)
#{memoized_ivar}[args] = #{original_method}(*args).freeze # @_memoized_mime_type[args] = _unmemoized_mime_type(*args).freeze
end # end
else # else
#{original_method}(*args) # _unmemoized_mime_type(*args)

View File

@@ -1,4 +1,3 @@
require 'abstract_unit'
require 'active_support'
require 'test/unit'

View File

@@ -4,13 +4,12 @@ class MemoizableTest < Test::Unit::TestCase
class Person
extend ActiveSupport::Memoizable
attr_reader :name_calls, :age_calls, :is_developer_calls, :name_query_calls
attr_reader :name_calls, :age_calls, :is_developer_calls
def initialize
@name_calls = 0
@age_calls = 0
@is_developer_calls = 0
@name_query_calls = 0
end
def name
@@ -19,7 +18,6 @@ class MemoizableTest < Test::Unit::TestCase
end
def name?
@name_query_calls += 1
true
end
memoize :name?
@@ -125,13 +123,6 @@ class MemoizableTest < Test::Unit::TestCase
end
end
def test_memoization_flush_with_punctuation
assert_equal true, @person.name?
@person.flush_cache(:name?)
3.times { assert_equal true, @person.name? }
assert_equal 2, @person.name_query_calls
end
def test_memoization_with_nil_value
assert_equal nil, @person.age
assert_equal 1, @person.age_calls
@@ -140,7 +131,13 @@ class MemoizableTest < Test::Unit::TestCase
assert_equal 1, @person.age_calls
end
def test_memorized_results_are_immutable
assert_equal "Josh", @person.name
assert_raise(ActiveSupport::FrozenObjectError) { @person.name.gsub!("Josh", "Gosh") }
end
def test_reloadable
counter = @calculator.counter
assert_equal 1, @calculator.counter
assert_equal 2, @calculator.counter(:reload)
assert_equal 2, @calculator.counter