lib/processors/route_processor.rb in brakeman-min-0.4.0 vs lib/processors/route_processor.rb in brakeman-min-0.4.1

- old
+ new

@@ -1,338 +1,11 @@ require 'processors/base_processor' require 'processors/alias_processor' +require 'processors/lib/route_helper' require 'util' require 'set' -#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. -class RoutesProcessor < BaseProcessor - attr_reader :map, :nested, :current_controller - - 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 - 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+. - def process_routes exp - process RouteAliasProcessor.new.process_safely(exp) - end - - #Looking for mapping of routes - def process_call exp - target = exp[1] - - if target == map or target == nested - process_map exp - - else - process_default exp - end - - exp - end - - #Process a map.something call - #based on the method used - def process_map exp - args = exp[3][1..-1] - - case exp[2] - when :resource - process_resource args - when :resources - process_resources args - when :connect, :root - process_connect args - else - process_named_route args - end - - exp - end - - #Look for map calls that take a block. - #Otherwise, just do the default processing. - def process_iter exp - if exp[1][1] == map or exp[1][1] == nested - method = exp[1][2] - case method - when :namespace - process_namespace exp - when :resources, :resource - process_resources exp[1][3][1..-1] - process_default exp[3] - when :with_options - process_with_options exp - end - exp - else - super - end - end - - #Process - # map.resources :x, :controller => :y, :member => ... - #etc. - 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 sexp? argument and argument.node_type == :lit - self.current_controller = exp[0][1] - add_resources_routes - process_resource_options exp[-1] - end - end - end - end - - #Add default routes - def add_resources_routes - @tracker.routes[@current_controller].merge [:index, :new, :create, :show, :edit, :update, :destroy] - end - - #Process all the options that might be in the hash passed to - #map.resource, et al. - 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 - #should be able to skip - when :collection, :member, :new - process_collection value - when :has_one - save_controller = current_controller - process_resource value[1..-1] - 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 - raise "Unhandled resource option: #{option}" - end - end - end - - #Process route option :only => ... - 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[1] - end - end - end - - #Process route option :except => ... - 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[1] - end - end - - # map.resource :x, .. - def process_resource exp - controller = check_for_controller_name exp - if controller - self.current_controller = controller - process_resource_options exp[-1] - else - exp.each do |argument| - if argument.node_type == :lit - self.current_controller = pluralize(exp[0][1].to_s) - add_resource_routes - process_resource_options exp[-1] - end - end - end - end - - #Add default routes minus :index - def add_resource_routes - @tracker.routes[@current_controller].merge [:new, :create, :show, :edit, :update, :destroy] - end - - #Process - # map.connect '/something', :controller => 'blah', :action => 'whatever' - def process_connect exp - controller = check_for_controller_name exp - self.current_controller = controller if controller - - #Check for default route - if string? exp[0] - if exp[0][1] == ":controller/:action/:id" - @tracker.routes[:allow_all_actions] = exp[0] - elsif exp[0][1].include? ":action" - @tracker.routes[@current_controller] = :allow_all_actions - 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] == :allow_all_actions - - exp[-1].each_with_index do |e,i| - if symbol? e and e[1] == :action - @tracker.routes[@current_controller] << exp[-1][i + 1][1].to_sym - return - end - end - end - - # map.with_options :controller => 'something' do |something| - # something.resources :blah - # end - def process_with_options exp - @with_options = exp[1][3][-1] - @nested = Sexp.new(:lvar, exp[2][1]) - - self.current_controller = check_for_controller_name exp[1][3] - - #process block - process exp[3] - - @with_options = nil - @nested = nil - end - - # map.namespace :something do |something| - # something.resources :blah - # end - def process_namespace exp - call = exp[1] - formal_args = exp[2] - block = exp[3] - - @prefix << camelize(call[3][1][1]) - - @nested = Sexp.new(:lvar, formal_args[1]) - - process block - - @prefix.pop - end - - # map.something_abnormal '/blah', :controller => 'something', :action => 'wohoo' - def process_named_route exp - process_connect exp - end - - #Process collection option - # :collection => { :some_action => :http_actions } - def process_collection exp - return unless exp.node_type == :hash - routes = @tracker.routes[@current_controller] - - hash_iterate(exp) do |action, type| - routes << action[1] - end - end - - #Manage Controller prefixes - #@prefix is an Array, but this method returns a string - #suitable for prefixing onto a controller name. - def prefix - if @prefix.length > 0 - @prefix.join("::") << "::" - else - '' - end - end - - #Sets the controller name to a proper class name. - #For example - # self.current_controller = :session - # @controller == :SessionController #true - # - #Also prepends the prefix if there is one set. - def current_controller= name - @current_controller = (prefix + camelize(name) + "Controller").to_sym - @tracker.routes[@current_controller] ||= Set.new - end - - private - - #Checks an argument list for a hash that has a key :controller. - #If it does, returns the value. - # - #Otherwise, returns nil. - def check_for_controller_name args - args.each do |a| - if hash? a - hash_iterate(a) do |k, v| - if k[1] == :controller - return v[1] - end - end - end - end - - nil - end -end - -#This is for a really specific case where a hash is used as arguments -#to one of the map methods. -class RouteAliasProcessor < AliasProcessor - - #This replaces - # { :some => :hash }.keys - #with - # [:some] - def process_call exp - process_default exp - - if hash? exp[1] and exp[2] == :keys - keys = get_keys exp[1] - exp.clear - keys.each_with_index do |e,i| - exp[i] = e - end - end - exp - end - - #Returns an array Sexp containing the keys from the hash - def get_keys hash - keys = Sexp.new(:array) - hash_iterate(hash) do |key, value| - keys << key - end - - keys - end +if OPTIONS[:rails3] + require 'processors/lib/rails3_route_processor' +else + require 'processors/lib/rails2_route_processor' end