Instiki 0.17.2: Security Release
This release upgrades Instiki to Rails 2.3.4, which patches two security holes in Rails. See http://weblog.rubyonrails.org/2009/9/4/ruby-on-rails-2-3-4 There are also some new features, and the usual boatload of bugfixes. See the CHANGELOG for details.
This commit is contained in:
parent
34c4306867
commit
4bdf703ab2
211 changed files with 3959 additions and 1325 deletions
|
@ -64,7 +64,9 @@ module ActionController
|
|||
# Support partial arguments for hash redirections
|
||||
if options.is_a?(Hash) && @response.redirected_to.is_a?(Hash)
|
||||
if options.all? {|(key, value)| @response.redirected_to[key] == value}
|
||||
::ActiveSupport::Deprecation.warn("Using assert_redirected_to with partial hash arguments is deprecated. Specify the full set arguments instead", caller)
|
||||
callstack = caller.dup
|
||||
callstack.slice!(0, 2)
|
||||
::ActiveSupport::Deprecation.warn("Using assert_redirected_to with partial hash arguments is deprecated. Specify the full set arguments instead", callstack)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -493,7 +493,12 @@ module ActionController #:nodoc:
|
|||
filtered_parameters[key] = filter_parameters(value)
|
||||
elsif value.is_a?(Array)
|
||||
filtered_parameters[key] = value.collect do |item|
|
||||
filter_parameters(item)
|
||||
case item
|
||||
when Hash, Array
|
||||
filter_parameters(item)
|
||||
else
|
||||
item
|
||||
end
|
||||
end
|
||||
elsif block_given?
|
||||
key = key.dup
|
||||
|
@ -814,7 +819,6 @@ module ActionController #:nodoc:
|
|||
# render :text => proc { |response, output|
|
||||
# 10_000_000.times do |i|
|
||||
# output.write("This is line #{i}\n")
|
||||
# output.flush
|
||||
# end
|
||||
# }
|
||||
#
|
||||
|
|
|
@ -51,7 +51,7 @@ module ActionController #:nodoc:
|
|||
protected
|
||||
# Returns the cookie container, which operates as described above.
|
||||
def cookies
|
||||
CookieJar.new(self)
|
||||
@cookies ||= CookieJar.new(self)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,13 +2,12 @@ module ActionController
|
|||
# Dispatches requests to the appropriate controller and takes care of
|
||||
# reloading the app after each request when Dependencies.load? is true.
|
||||
class Dispatcher
|
||||
@@cache_classes = true
|
||||
|
||||
class << self
|
||||
def define_dispatcher_callbacks(cache_classes)
|
||||
@@cache_classes = cache_classes
|
||||
unless cache_classes
|
||||
unless self.middleware.include?(Reloader)
|
||||
self.middleware.insert_after(Failsafe, Reloader)
|
||||
end
|
||||
|
||||
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
|
||||
end
|
||||
|
||||
|
@ -79,7 +78,7 @@ module ActionController
|
|||
# DEPRECATE: Remove arguments, since they are only used by CGI
|
||||
def initialize(output = $stdout, request = nil, response = nil)
|
||||
@output = output
|
||||
@app = @@middleware.build(lambda { |env| self.dup._call(env) })
|
||||
build_middleware_stack if @@cache_classes
|
||||
end
|
||||
|
||||
def dispatch
|
||||
|
@ -103,7 +102,18 @@ module ActionController
|
|||
end
|
||||
|
||||
def call(env)
|
||||
@app.call(env)
|
||||
if @@cache_classes
|
||||
@app.call(env)
|
||||
else
|
||||
Reloader.run do
|
||||
# When class reloading is turned on, we will want to rebuild the
|
||||
# middleware stack every time we process a request. If we don't
|
||||
# rebuild the middleware stack, then the stack may contain references
|
||||
# to old classes metal classes, which will b0rk class reloading.
|
||||
build_middleware_stack
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def _call(env)
|
||||
|
@ -114,5 +124,10 @@ module ActionController
|
|||
def flush_logger
|
||||
Base.logger.flush
|
||||
end
|
||||
|
||||
private
|
||||
def build_middleware_stack
|
||||
@app = @@middleware.build(lambda { |env| self.dup._call(env) })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -139,7 +139,7 @@ module ActionController
|
|||
end
|
||||
|
||||
def decode_credentials(request)
|
||||
ActiveSupport::Base64.decode64(authorization(request).split.last || '')
|
||||
ActiveSupport::Base64.decode64(authorization(request).split(' ', 2).last || '')
|
||||
end
|
||||
|
||||
def encode_credentials(user_name, password)
|
||||
|
@ -195,9 +195,10 @@ module ActionController
|
|||
return false unless password
|
||||
|
||||
method = request.env['rack.methodoverride.original_method'] || request.env['REQUEST_METHOD']
|
||||
uri = credentials[:uri][0,1] == '/' ? request.request_uri : request.url
|
||||
|
||||
[true, false].any? do |password_is_ha1|
|
||||
expected = expected_response(method, request.env['REQUEST_URI'], credentials, password, password_is_ha1)
|
||||
expected = expected_response(method, uri, credentials, password, password_is_ha1)
|
||||
expected == credentials[:response]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -47,6 +47,8 @@ module ActionController
|
|||
false
|
||||
end
|
||||
rescue Exception => e # YAML, XML or Ruby code block errors
|
||||
logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}"
|
||||
|
||||
raise
|
||||
{ "body" => request.raw_post,
|
||||
"content_type" => request.content_type,
|
||||
|
@ -67,5 +69,9 @@ module ActionController
|
|||
|
||||
nil
|
||||
end
|
||||
|
||||
def logger
|
||||
defined?(Rails.logger) ? Rails.logger : Logger.new($stderr)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
require 'thread'
|
||||
|
||||
module ActionController
|
||||
class Reloader
|
||||
@@default_lock = Mutex.new
|
||||
cattr_accessor :default_lock
|
||||
|
||||
class BodyWrapper
|
||||
def initialize(body)
|
||||
def initialize(body, lock)
|
||||
@body = body
|
||||
@lock = lock
|
||||
end
|
||||
|
||||
def close
|
||||
@body.close if @body.respond_to?(:close)
|
||||
ensure
|
||||
Dispatcher.cleanup_application
|
||||
@lock.unlock
|
||||
end
|
||||
|
||||
def method_missing(*args, &block)
|
||||
|
@ -20,26 +27,28 @@ module ActionController
|
|||
end
|
||||
end
|
||||
|
||||
def initialize(app)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
Dispatcher.reload_application
|
||||
status, headers, body = @app.call(env)
|
||||
# We do not want to call 'cleanup_application' in an ensure block
|
||||
# because the returned Rack response body may lazily generate its data. This
|
||||
# is for example the case if one calls
|
||||
#
|
||||
# render :text => lambda { ... code here which refers to application models ... }
|
||||
#
|
||||
# in an ActionController.
|
||||
#
|
||||
# Instead, we will want to cleanup the application code after the request is
|
||||
# completely finished. So we wrap the body in a BodyWrapper class so that
|
||||
# when the Rack handler calls #close during the end of the request, we get to
|
||||
# run our cleanup code.
|
||||
[status, headers, BodyWrapper.new(body)]
|
||||
def self.run(lock = @@default_lock)
|
||||
lock.lock
|
||||
begin
|
||||
Dispatcher.reload_application
|
||||
status, headers, body = yield
|
||||
# We do not want to call 'cleanup_application' in an ensure block
|
||||
# because the returned Rack response body may lazily generate its data. This
|
||||
# is for example the case if one calls
|
||||
#
|
||||
# render :text => lambda { ... code here which refers to application models ... }
|
||||
#
|
||||
# in an ActionController.
|
||||
#
|
||||
# Instead, we will want to cleanup the application code after the request is
|
||||
# completely finished. So we wrap the body in a BodyWrapper class so that
|
||||
# when the Rack handler calls #close during the end of the request, we get to
|
||||
# run our cleanup code.
|
||||
[status, headers, BodyWrapper.new(body, lock)]
|
||||
rescue Exception
|
||||
lock.unlock
|
||||
raise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -81,12 +81,13 @@ module ActionController #:nodoc:
|
|||
|
||||
# Returns true or false if a request is verified. Checks:
|
||||
#
|
||||
# * is the format restricted? By default, only HTML and AJAX requests are checked.
|
||||
# * is the format restricted? By default, only HTML requests are checked.
|
||||
# * is it a GET request? Gets should be safe and idempotent
|
||||
# * Does the form_authenticity_token match the given token value from the params?
|
||||
def verified_request?
|
||||
!protect_against_forgery? ||
|
||||
request.method == :get ||
|
||||
request.xhr? ||
|
||||
!verifiable_request_format? ||
|
||||
form_authenticity_token == params[request_forgery_protection_token]
|
||||
end
|
||||
|
|
|
@ -317,9 +317,10 @@ module ActionController
|
|||
# notes.resources :attachments
|
||||
# end
|
||||
#
|
||||
# * <tt>:path_names</tt> - Specify different names for the 'new' and 'edit' actions. For example:
|
||||
# * <tt>:path_names</tt> - Specify different path names for the actions. For example:
|
||||
# # new_products_path == '/productos/nuevo'
|
||||
# map.resources :products, :as => 'productos', :path_names => { :new => 'nuevo', :edit => 'editar' }
|
||||
# # bids_product_path(1) == '/productos/1/licitacoes'
|
||||
# map.resources :products, :as => 'productos', :member => { :bids => :get }, :path_names => { :new => 'nuevo', :bids => 'licitacoes' }
|
||||
#
|
||||
# You can also set default action names from an environment, like this:
|
||||
# config.action_controller.resources_path_names = { :new => 'nuevo', :edit => 'editar' }
|
||||
|
@ -525,16 +526,16 @@ module ActionController
|
|||
resource = Resource.new(entities, options)
|
||||
|
||||
with_options :controller => resource.controller do |map|
|
||||
map_collection_actions(map, resource)
|
||||
map_default_collection_actions(map, resource)
|
||||
map_new_actions(map, resource)
|
||||
map_member_actions(map, resource)
|
||||
|
||||
map_associations(resource, options)
|
||||
|
||||
if block_given?
|
||||
with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
|
||||
end
|
||||
|
||||
map_collection_actions(map, resource)
|
||||
map_default_collection_actions(map, resource)
|
||||
map_new_actions(map, resource)
|
||||
map_member_actions(map, resource)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -542,16 +543,16 @@ module ActionController
|
|||
resource = SingletonResource.new(entities, options)
|
||||
|
||||
with_options :controller => resource.controller do |map|
|
||||
map_collection_actions(map, resource)
|
||||
map_new_actions(map, resource)
|
||||
map_member_actions(map, resource)
|
||||
map_default_singleton_actions(map, resource)
|
||||
|
||||
map_associations(resource, options)
|
||||
|
||||
if block_given?
|
||||
with_options(options.slice(*INHERITABLE_OPTIONS).merge(:path_prefix => resource.nesting_path_prefix, :name_prefix => resource.nesting_name_prefix), &block)
|
||||
end
|
||||
|
||||
map_collection_actions(map, resource)
|
||||
map_new_actions(map, resource)
|
||||
map_member_actions(map, resource)
|
||||
map_default_singleton_actions(map, resource)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -586,7 +587,10 @@ module ActionController
|
|||
resource.collection_methods.each do |method, actions|
|
||||
actions.each do |action|
|
||||
[method].flatten.each do |m|
|
||||
map_resource_routes(map, resource, action, "#{resource.path}#{resource.action_separator}#{action}", "#{action}_#{resource.name_prefix}#{resource.plural}", m)
|
||||
action_path = resource.options[:path_names][action] if resource.options[:path_names].is_a?(Hash)
|
||||
action_path ||= action
|
||||
|
||||
map_resource_routes(map, resource, action, "#{resource.path}#{resource.action_separator}#{action_path}", "#{action}_#{resource.name_prefix}#{resource.plural}", m)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -166,6 +166,12 @@ module ActionController # :nodoc:
|
|||
str
|
||||
end
|
||||
|
||||
def flush #:nodoc:
|
||||
ActiveSupport::Deprecation.warn(
|
||||
'Calling output.flush is no longer needed for streaming output ' +
|
||||
'because ActionController::Response automatically handles it', caller)
|
||||
end
|
||||
|
||||
def set_cookie(key, value)
|
||||
if value.has_key?(:http_only)
|
||||
ActiveSupport::Deprecation.warn(
|
||||
|
|
|
@ -271,6 +271,9 @@ module ActionController
|
|||
|
||||
ALLOWED_REQUIREMENTS_FOR_OPTIMISATION = [:controller, :action].to_set
|
||||
|
||||
mattr_accessor :generate_best_match
|
||||
self.generate_best_match = true
|
||||
|
||||
# The root paths which may contain controller files
|
||||
mattr_accessor :controller_paths
|
||||
self.controller_paths = []
|
||||
|
|
|
@ -405,11 +405,14 @@ module ActionController
|
|||
end
|
||||
|
||||
# don't use the recalled keys when determining which routes to check
|
||||
routes = routes_by_controller[controller][action][options.reject {|k,v| !v}.keys.sort_by { |x| x.object_id }]
|
||||
future_routes, deprecated_routes = routes_by_controller[controller][action][options.reject {|k,v| !v}.keys.sort_by { |x| x.object_id }]
|
||||
routes = Routing.generate_best_match ? deprecated_routes : future_routes
|
||||
|
||||
routes.each do |route|
|
||||
routes.each_with_index do |route, index|
|
||||
results = route.__send__(method, options, merged, expire_on)
|
||||
return results if results && (!results.is_a?(Array) || results.first)
|
||||
if results && (!results.is_a?(Array) || results.first)
|
||||
return results
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -448,7 +451,10 @@ module ActionController
|
|||
@routes_by_controller ||= Hash.new do |controller_hash, controller|
|
||||
controller_hash[controller] = Hash.new do |action_hash, action|
|
||||
action_hash[action] = Hash.new do |key_hash, keys|
|
||||
key_hash[keys] = routes_for_controller_and_action_and_keys(controller, action, keys)
|
||||
key_hash[keys] = [
|
||||
routes_for_controller_and_action_and_keys(controller, action, keys),
|
||||
deprecated_routes_for_controller_and_action_and_keys(controller, action, keys)
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -460,10 +466,11 @@ module ActionController
|
|||
merged = options if expire_on[:controller]
|
||||
action = merged[:action] || 'index'
|
||||
|
||||
routes_by_controller[controller][action][merged.keys]
|
||||
routes_by_controller[controller][action][merged.keys][1]
|
||||
end
|
||||
|
||||
def routes_for_controller_and_action(controller, action)
|
||||
ActiveSupport::Deprecation.warn "routes_for_controller_and_action() has been deprecated. Please use routes_for()"
|
||||
selected = routes.select do |route|
|
||||
route.matches_controller_and_action? controller, action
|
||||
end
|
||||
|
@ -471,6 +478,12 @@ module ActionController
|
|||
end
|
||||
|
||||
def routes_for_controller_and_action_and_keys(controller, action, keys)
|
||||
routes.select do |route|
|
||||
route.matches_controller_and_action? controller, action
|
||||
end
|
||||
end
|
||||
|
||||
def deprecated_routes_for_controller_and_action_and_keys(controller, action, keys)
|
||||
selected = routes.select do |route|
|
||||
route.matches_controller_and_action? controller, action
|
||||
end
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
require 'active_support/core_ext/string/bytesize'
|
||||
|
||||
module ActionController #:nodoc:
|
||||
# Methods for sending arbitrary data and for streaming files to the browser,
|
||||
# instead of rendering.
|
||||
|
@ -137,7 +139,7 @@ module ActionController #:nodoc:
|
|||
# instead. See ActionController::Base#render for more information.
|
||||
def send_data(data, options = {}) #:doc:
|
||||
logger.info "Sending data #{options[:filename]}" if logger
|
||||
send_file_headers! options.merge(:length => data.size)
|
||||
send_file_headers! options.merge(:length => data.bytesize)
|
||||
@performed_render = false
|
||||
render :status => options[:status], :text => data
|
||||
end
|
||||
|
|
|
@ -184,7 +184,7 @@ module ActionController
|
|||
path = rewrite_path(options)
|
||||
rewritten_url << ActionController::Base.relative_url_root.to_s unless options[:skip_relative_url_root]
|
||||
rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
|
||||
rewritten_url << "##{options[:anchor]}" if options[:anchor]
|
||||
rewritten_url << "##{CGI.escape(options[:anchor].to_param.to_s)}" if options[:anchor]
|
||||
|
||||
rewritten_url
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue