mirror of
https://github.com/github/rails.git
synced 2026-01-11 23:58:03 -05:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
730e6a273c | ||
|
|
aa1b6d1284 | ||
|
|
5f6c95e29e | ||
|
|
7403667b89 | ||
|
|
1a45ec57bf | ||
|
|
9070fbcffe | ||
|
|
364b534815 | ||
|
|
14da203564 | ||
|
|
f46a4bab08 | ||
|
|
198aa6ef99 | ||
|
|
b3ae51c9fc | ||
|
|
1e6e438f6e | ||
|
|
2b01f832a3 | ||
|
|
1e5fda763e | ||
|
|
7c3d4ec43c | ||
|
|
7343ed7b05 | ||
|
|
2a70c9691d | ||
|
|
a141d9de0d | ||
|
|
74492f43a8 | ||
|
|
c2894170bf | ||
|
|
057aed6e18 | ||
|
|
02fc012b42 |
@@ -1 +1 @@
|
||||
2.3.14.github40
|
||||
2.3.14.github45
|
||||
|
||||
@@ -1320,7 +1320,14 @@ 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?
|
||||
|
||||
@@ -45,37 +45,74 @@ module ActionController #:nodoc:
|
||||
end
|
||||
|
||||
def []=(k, v)
|
||||
k = k.to_s
|
||||
@flash[k] = v
|
||||
@flash.discard(k)
|
||||
v
|
||||
end
|
||||
|
||||
def [](k)
|
||||
@flash[k]
|
||||
@flash[k.to_s]
|
||||
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
|
||||
super(k, v)
|
||||
end
|
||||
|
||||
def [](k)
|
||||
super(k.to_s)
|
||||
end
|
||||
|
||||
def delete(k)
|
||||
super(k.to_s)
|
||||
end
|
||||
|
||||
def update(h) #:nodoc:
|
||||
h.stringify_keys!
|
||||
h.keys.each { |k| keep(k) }
|
||||
super
|
||||
super(h)
|
||||
end
|
||||
|
||||
alias :merge! :update
|
||||
|
||||
def replace(h) #:nodoc:
|
||||
@used = {}
|
||||
super
|
||||
super(h.stringify_keys)
|
||||
end
|
||||
|
||||
# Sets a flash that will not be available to the next action, only to the current.
|
||||
@@ -126,8 +163,7 @@ module ActionController #:nodoc:
|
||||
end
|
||||
|
||||
def store(session, key = "flash")
|
||||
return if self.empty?
|
||||
session[key] = self
|
||||
session[key] = to_session_value
|
||||
end
|
||||
|
||||
private
|
||||
@@ -138,11 +174,20 @@ 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] = v
|
||||
@used[k.to_s] = 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:
|
||||
@@ -168,11 +213,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
|
||||
|
||||
@@ -181,19 +226,19 @@ module ActionController #:nodoc:
|
||||
# to put a new one.
|
||||
def flash #:doc:
|
||||
if !defined?(@_flash)
|
||||
@_flash = session["flash"] || FlashHash.new
|
||||
@_flash = Flash::FlashHash.from_session_value(session["flash"])
|
||||
@_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
|
||||
@@ -203,7 +248,7 @@ module ActionController #:nodoc:
|
||||
def notice
|
||||
flash[:notice]
|
||||
end
|
||||
|
||||
|
||||
# Convenience accessor for flash[:notice]=
|
||||
def notice=(message)
|
||||
flash[:notice] = message
|
||||
|
||||
@@ -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
|
||||
super(key.to_s) || super(key)
|
||||
end
|
||||
|
||||
def has_key?(key)
|
||||
load_for_read!
|
||||
super
|
||||
super(key.to_s) || super(key)
|
||||
end
|
||||
|
||||
def []=(key, value)
|
||||
load_for_write!
|
||||
super
|
||||
super(key.to_s, value)
|
||||
end
|
||||
|
||||
def clear
|
||||
@@ -87,7 +87,9 @@ module ActionController
|
||||
|
||||
def delete(key)
|
||||
load_for_write!
|
||||
super
|
||||
value = super(key)
|
||||
string_value = super(key.to_s)
|
||||
string_value || value
|
||||
end
|
||||
|
||||
def data
|
||||
@@ -119,7 +121,7 @@ module ActionController
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
def load_for_read!
|
||||
load! if !loaded? && exists?
|
||||
end
|
||||
@@ -183,7 +185,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
|
||||
@@ -205,12 +207,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
|
||||
@@ -222,7 +224,7 @@ module ActionController
|
||||
[sid, session]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def extract_session_id(env)
|
||||
stale_session_check! do
|
||||
request = Rack::Request.new(env)
|
||||
@@ -235,7 +237,7 @@ module ActionController
|
||||
def current_session_id(env)
|
||||
env[ENV_SESSION_OPTIONS_KEY][:id]
|
||||
end
|
||||
|
||||
|
||||
def exists?(env)
|
||||
current_session_id(env).present?
|
||||
end
|
||||
@@ -247,11 +249,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!
|
||||
|
||||
@@ -86,7 +86,8 @@ module ActionController
|
||||
@secret = options.delete(:secret).freeze
|
||||
|
||||
@digest = options.delete(:digest) || 'SHA1'
|
||||
@verifier = verifier_for(@secret, @digest)
|
||||
@serializer = options.delete(:serializer) || Marshal
|
||||
@verifier = verifier_for(@secret, @digest, @serializer)
|
||||
|
||||
@default_options = DEFAULT_OPTIONS.merge(options).freeze
|
||||
|
||||
@@ -138,13 +139,13 @@ module ActionController
|
||||
def load_session(env)
|
||||
data = unpacked_cookie_data(env)
|
||||
data = persistent_session_id!(data)
|
||||
[data[:session_id], data]
|
||||
[data["session_id"] || 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
|
||||
@@ -214,9 +215,9 @@ module ActionController
|
||||
end
|
||||
end
|
||||
|
||||
def verifier_for(secret, digest)
|
||||
def verifier_for(secret, digest, serializer)
|
||||
key = secret.respond_to?(:call) ? secret.call : secret
|
||||
ActiveSupport::MessageVerifier.new(key, digest: digest)
|
||||
ActiveSupport::MessageVerifier.new(key, digest: digest, serializer: serializer)
|
||||
end
|
||||
|
||||
def generate_sid
|
||||
@@ -232,12 +233,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.respond_to?(:key?) && !(data.key?("session_id") || data.key?(:session_id))
|
||||
else
|
||||
true
|
||||
end
|
||||
|
||||
@@ -219,7 +219,7 @@ module ActionController #:nodoc:
|
||||
|
||||
# A shortcut to the flash. Returns an empty hash if no session flash exists.
|
||||
def flash
|
||||
session['flash'] || {}
|
||||
ActionController::Flash::FlashHash.from_session_value(session["flash"]) || {}
|
||||
end
|
||||
|
||||
# Do we have a flash?
|
||||
|
||||
@@ -195,7 +195,9 @@ module ActiveRecord
|
||||
def log_info(sql, name, ms)
|
||||
if @logger && @logger.debug?
|
||||
name = '%s (%.1fms)' % [name || 'SQL', ms]
|
||||
sql.force_encoding 'binary' if sql.respond_to?(:force_encoding)
|
||||
if sql.respond_to?(:force_encoding)
|
||||
sql = sql.dup.force_encoding 'binary'
|
||||
end
|
||||
@logger.debug(format_log_entry(name, sql.squeeze(' ')))
|
||||
end
|
||||
end
|
||||
@@ -212,13 +214,7 @@ module ActiveRecord
|
||||
log_info(sql, name, 0)
|
||||
nil
|
||||
end
|
||||
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
|
||||
rescue => e
|
||||
# Log message and raise exception.
|
||||
# Set last_verification to 0, so that connection gets verified
|
||||
# upon reentering the request loop
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
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'
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
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
|
||||
@@ -1,3 +1,6 @@
|
||||
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)
|
||||
@@ -41,10 +44,10 @@ module ActiveSupport
|
||||
end
|
||||
end
|
||||
|
||||
def flush_cache(*syms, &block)
|
||||
def flush_cache(*syms)
|
||||
syms.each do |sym|
|
||||
(methods + private_methods + protected_methods).each do |m|
|
||||
if m.to_s =~ /^_unmemoized_(#{sym})/
|
||||
if m.to_s =~ /^_unmemoized_(#{sym.to_s.gsub(/\?\Z/, '\?')})/
|
||||
ivar = ActiveSupport::Memoizable.memoized_ivar_for($1)
|
||||
instance_variable_get(ivar).clear if instance_variable_defined?(ivar)
|
||||
end
|
||||
@@ -69,7 +72,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}.freeze] # @_memoized_mime_type = [_unmemoized_mime_type.freeze]
|
||||
#{memoized_ivar} = [#{original_method}] # @_memoized_mime_type = [_unmemoized_mime_type]
|
||||
end # end
|
||||
#{memoized_ivar}[0] # @_memoized_mime_type[0]
|
||||
end # end
|
||||
@@ -82,7 +85,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).freeze # @_memoized_mime_type[args] = _unmemoized_mime_type(*args).freeze
|
||||
#{memoized_ivar}[args] = #{original_method}(*args) # @_memoized_mime_type[args] = _unmemoized_mime_type(*args)
|
||||
end # end
|
||||
else # else
|
||||
#{original_method}(*args) # _unmemoized_mime_type(*args)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
require 'abstract_unit'
|
||||
require 'active_support'
|
||||
require 'test/unit'
|
||||
|
||||
|
||||
@@ -4,12 +4,13 @@ class MemoizableTest < Test::Unit::TestCase
|
||||
class Person
|
||||
extend ActiveSupport::Memoizable
|
||||
|
||||
attr_reader :name_calls, :age_calls, :is_developer_calls
|
||||
attr_reader :name_calls, :age_calls, :is_developer_calls, :name_query_calls
|
||||
|
||||
def initialize
|
||||
@name_calls = 0
|
||||
@age_calls = 0
|
||||
@is_developer_calls = 0
|
||||
@name_query_calls = 0
|
||||
end
|
||||
|
||||
def name
|
||||
@@ -18,6 +19,7 @@ class MemoizableTest < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def name?
|
||||
@name_query_calls += 1
|
||||
true
|
||||
end
|
||||
memoize :name?
|
||||
@@ -123,6 +125,13 @@ 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
|
||||
@@ -131,13 +140,7 @@ 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
|
||||
|
||||
Reference in New Issue
Block a user