class Brakeman::Rails2RoutesProcessor
Processes the Sexp
from routes.rb. Stores results in tracker.routes.
Note that it is only interested in determining what methods on which controllers are used as routes, not the generated URLs for routes.
Attributes
Public Class Methods
Brakeman::BasicProcessor::new
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 12 def initialize tracker super @map = Sexp.new(:lvar, :map) @nested = nil #used for identifying nested targets @prefix = [] #Controller name prefix (a module name, usually) @current_controller = nil @with_options = nil #For use inside map.with_options @current_file = "config/routes.rb" end
Public Instance Methods
Looking for mapping of routes
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 31 def process_call exp target = exp.target if target == map or (not target.nil? and target == nested) process_map exp else process_default exp end exp end
Process collection option
:collection => { :some_action => :http_actions }
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 257 def process_collection exp return unless exp.node_type == :hash routes = @tracker.routes[@current_controller] hash_iterate(exp) do |action, _type| routes << action.value end end
Process
map.connect '/something', :controller => 'blah', :action => 'whatever'
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 182 def process_connect exp return if exp.empty? controller = check_for_controller_name exp self.current_controller = controller if controller #Check for default route if string? exp.first if exp.first.value == ":controller/:action/:id" @tracker.routes[:allow_all_actions] = exp.first elsif exp.first.value.include? ":action" @tracker.routes[@current_controller] = [:allow_all_actions, exp.line] return end end #This -seems- redundant, but people might connect actions #to a controller which already allows them all return if @tracker.routes[@current_controller].is_a? Array and @tracker.routes[@current_controller][0] == :allow_all_actions exp.last.each_with_index do |e,i| if symbol? e and e.value == :action action = exp.last[i + 1] if node_type? action, :lit @tracker.routes[@current_controller] << action.value.to_sym end return end end end
Look for map calls that take a block. Otherwise, just do the default processing.
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 64 def process_iter exp target = exp.block_call.target if target == map or target == nested method = exp.block_call.method case method when :namespace process_namespace exp when :resources, :resource process_resources exp.block_call.args process_default exp.block if exp.block when :with_options process_with_options exp end exp else process_default exp end end
Process a map.something call based on the method used
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 45 def process_map exp args = exp.args case exp.method when :resource process_resource args when :resources process_resources args when :connect, :root process_connect args else process_named_route args end exp end
map.something_abnormal ‘/blah’, :controller => ‘something’, :action => ‘wohoo’
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 251 def process_named_route exp process_connect exp end
map.namespace :something do |something|
something.resources :blah
end
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 234 def process_namespace exp call = exp.block_call formal_args = exp.block_args block = exp.block @prefix << camelize(call.first_arg.value) if formal_args @nested = Sexp.new(:lvar, formal_args.value) end process block @prefix.pop end
Process route option :except => …
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 154 def process_option_except exp return unless exp.node_type == :array routes = @tracker.routes[@current_controller] exp[1..-1].each do |e| routes.delete e.value end end
Process route option :only => …
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 140 def process_option_only exp routes = @tracker.routes[@current_controller] [:index, :new, :create, :show, :edit, :update, :destroy].each do |r| routes.delete r end if exp.node_type == :array exp[1..-1].each do |e| routes << e.value end end end
map.resource :x, ..
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 164 def process_resource exp controller = check_for_controller_name exp if controller self.current_controller = controller process_resource_options exp.last else exp.each do |argument| if node_type? argument, :lit self.current_controller = pluralize(exp.first.value.to_s) add_resource_routes process_resource_options exp.last end end end end
Process all the options that might be in the hash passed to map.resource, et al.
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 105 def process_resource_options exp if exp.nil? and @with_options exp = @with_options elsif @with_options exp = exp.concat @with_options[1..-1] end return unless exp.node_type == :hash hash_iterate(exp) do |option, value| case option[1] when :controller, :requirements, :singular, :path_prefix, :as, :path_names, :shallow, :name_prefix, :member_path, :nested_member_path, :belongs_to, :conditions, :active_scaffold #should be able to skip when :collection, :member, :new process_collection value when :has_one save_controller = current_controller process_resource value[1..-1] #Verify this is proper behavior self.current_controller = save_controller when :has_many save_controller = current_controller process_resources value[1..-1] self.current_controller = save_controller when :only process_option_only value when :except process_option_except value else Brakeman.notify "[Notice] Unhandled resource option, please report: #{option}" end end end
Process
map.resources :x, :controller => :y, :member => ...
etc.
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 87 def process_resources exp controller = check_for_controller_name exp if controller self.current_controller = controller process_resource_options exp[-1] else exp.each do |argument| if node_type? argument, :lit self.current_controller = exp.first.value add_resources_routes process_resource_options exp.last end end end end
Call this with parsed route file information.
This method first calls RouteAliasProcessor#process_safely on the exp
, so it does not modify the exp
.
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 26 def process_routes exp process Brakeman::RouteAliasProcessor.new.process_safely(exp, nil, @current_file) end
map.with_options :controller => ‘something’ do |something|
something.resources :blah
end
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 218 def process_with_options exp @with_options = exp.block_call.last_arg @nested = Sexp.new(:lvar, exp.block_args.value) self.current_controller = check_for_controller_name exp.block_call.args #process block process exp.block @with_options = nil @nested = nil end
Private Instance Methods
Checks an argument list for a hash that has a key :controller. If it does, returns the value.
Otherwise, returns nil.
# File lib/brakeman/processors/lib/rails2_route_processor.rb, line 272 def check_for_controller_name args args.each do |a| if hash? a and value = hash_access(a, :controller) return value.value if string? value or symbol? value end end nil end