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:
Jacques Distler 2009-09-05 02:01:46 -05:00
parent 34c4306867
commit 4bdf703ab2
211 changed files with 3959 additions and 1325 deletions

View file

@ -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

View file

@ -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
# }
#

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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(

View file

@ -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 = []

View file

@ -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

View file

@ -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

View file

@ -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