Class for rescanning changed files after an initial scan
Create new Rescanner to scan changed files
# File lib/brakeman/rescanner.rb, line 12 def initialize options, processor, changed_files super(options, processor) @paths = changed_files.map {|f| @app_tree.expand_path(f) } @old_results = tracker.checks #Old warnings from previous scan @changes = nil #True if files had to be rescanned @reindex = Set.new end
Guess at what kind of file the path contains
# File lib/brakeman/rescanner.rb, line 293 def file_type path case path when /\/app\/controllers/ :controller when /\/app\/views/ :template when /\/app\/models/ :model when /\/lib/ :lib when /\/config\/initializers/ :initializer when /config\/routes\.rb/ :routes when /\/config\/.+\.rb/ :config when /Gemfile/ :gemfile else :unknown end end
Runs checks. Will rescan files if they have not already been scanned
# File lib/brakeman/rescanner.rb, line 23 def recheck rescan if @changes.nil? tracker.run_checks if @changes Brakeman::RescanReport.new @old_results, tracker end
Check controllers, templates, models and libs for data from file and delete it.
# File lib/brakeman/rescanner.rb, line 277 def remove_deleted_file path deleted = false [:controllers, :templates, :models, :libs].each do |collection| tracker.send(collection).delete_if do |name, data| if data[:file] == path deleted = true true end end end deleted end
Rescans changed files
# File lib/brakeman/rescanner.rb, line 32 def rescan tracker.template_cache.clear paths_by_type = {} SCAN_ORDER.each do |type| paths_by_type[type] = [] end @paths.each do |path| type = file_type(path) paths_by_type[type] << path unless type == :unknown end @changes = false SCAN_ORDER.each do |type| paths_by_type[type].each do |path| Brakeman.debug "Rescanning #{path} as #{type}" if rescan_file path, type @changes = true end end end if @changes and not @reindex.empty? tracker.reindex_call_sites @reindex end self end
# File lib/brakeman/rescanner.rb, line 110 def rescan_controller path #Process source process_controller path #Process data flow and template rendering #from the controller tracker.controllers.each do |name, controller| if controller[:file] == path tracker.templates.each do |template_name, template| next unless template[:caller] unless template[:caller].grep(/^#{name}#/).empty? tracker.reset_template template_name end end @processor.process_controller_alias controller[:name], controller[:src] end end end
# File lib/brakeman/rescanner.rb, line 231 def rescan_deleted_controller path tracker.reset_controller path end
Handle rescanning when a file is deleted
# File lib/brakeman/rescanner.rb, line 208 def rescan_deleted_file path, type case type when :controller rescan_deleted_controller path when :template rescan_deleted_template path when :model rescan_model path when :lib rescan_deleted_lib path when :initializer rescan_deleted_initializer path else if remove_deleted_file path return true else Brakeman.notify "Ignoring deleted file: #{path}" end end true end
# File lib/brakeman/rescanner.rb, line 271 def rescan_deleted_initializer path tracker.initializers.delete Pathname.new(path).basename.to_s end
# File lib/brakeman/rescanner.rb, line 258 def rescan_deleted_lib path deleted_lib = nil tracker.libs.delete_if do |name, lib| if lib[:file] == path deleted_lib = lib true end end rescan_mixin deleted_lib if deleted_lib end
# File lib/brakeman/rescanner.rb, line 235 def rescan_deleted_template path return unless path.match KNOWN_TEMPLATE_EXTENSIONS template_name = template_path_to_name(path) #Remove template tracker.reset_template template_name rendered_from_controller = /^#{template_name}\.(.+Controller)#(.+)/ rendered_from_view = /^#{template_name}\.Template:(.+)/ #Remove any rendered versions, or partials rendered from it tracker.templates.delete_if do |name, template| if template[:file] == path true elsif template[:file].nil? name = name.to_s name.match(rendered_from_controller) or name.match(rendered_from_view) end end end
Rescans a single file
# File lib/brakeman/rescanner.rb, line 66 def rescan_file path, type = nil type ||= file_type path unless @app_tree.path_exists?(path) return rescan_deleted_file path, type end case type when :controller rescan_controller path @reindex << :controllers << :templates when :template rescan_template path @reindex << :templates when :model rescan_model path when :lib rescan_lib path when :config process_config when :initializer process_initializer path when :routes # Routes affect which controller methods are treated as actions # which affects which templates are rendered, so routes, controllers, # and templates rendered from controllers must be rescanned tracker.reset_routes tracker.reset_templates :only_rendered => true process_routes process_controllers @reindex << :controllers << :templates when :gemfile if tracker.config[:gems][:rails_xss] and tracker.config[:escape_html] tracker.config[:escape_html] = false end process_gems else return false #Nothing to do, file hopefully does not need to be rescanned end true end
# File lib/brakeman/rescanner.rb, line 192 def rescan_lib path process_lib path if @app_tree.path_exists?(path) lib = nil tracker.libs.each do |name, library| if library[:file] == path lib = library break end end rescan_mixin lib if lib end
# File lib/brakeman/rescanner.rb, line 316 def rescan_mixin lib method_names = [] [:public, :private, :protected].each do |access| lib[access].each do |name, meth| method_names << name end end method_matcher = /##{method_names.map {|n| Regexp.escape(n.to_s)}.join('|')}$/ #Rescan controllers that mixed in library tracker.controllers.each do |name, controller| if controller[:includes].include? lib[:name] unless @paths.include? controller[:file] rescan_file controller[:file] end end end to_rescan = [] #Check if a method from this mixin was used to render a template. #This is not precise, because a different controller might have the #same method... tracker.templates.each do |name, template| next unless template[:caller] unless template[:caller].grep(method_matcher).empty? name.to_s.match /^([^.]+)/ original = tracker.templates[$1.to_sym] if original to_rescan << [name, original[:file]] end end end to_rescan.each do |template| tracker.reset_template template[0] rescan_file template[1] end end
# File lib/brakeman/rescanner.rb, line 177 def rescan_model path num_models = tracker.models.length tracker.reset_model path process_model path if @app_tree.path_exists?(path) #Only need to rescan other things if a model is added or removed if num_models != tracker.models.length process_templates process_controllers @reindex << :templates << :controllers end @reindex << :models end
# File lib/brakeman/rescanner.rb, line 130 def rescan_template path return unless path.match KNOWN_TEMPLATE_EXTENSIONS and @app_tree.path_exists?(path) template_name = template_path_to_name(path) tracker.reset_template template_name process_template path @processor.process_template_alias tracker.templates[template_name] rescan = Set.new template_matcher = /^Template:(.+)/ controller_matcher = /^(.+Controller)#(.+)/ template_name_matcher = /^#{template_name}\./ #Search for processed template and process it. #Search for rendered versions of template and re-render (if necessary) tracker.templates.each do |name, template| if template[:file] == path or template[:file].nil? next unless template[:caller] and name.to_s.match(template_name_matcher) template[:caller].each do |from| if from.match(template_matcher) rescan << [:template, $1.to_sym] elsif from.match(controller_matcher) rescan << [:controller, $1.to_sym, $2.to_sym] end end end end rescan.each do |r| if r[0] == :controller controller = tracker.controllers[r[1]] unless @paths.include? controller[:file] @processor.process_controller_alias controller[:name], controller[:src], r[2] end elsif r[0] == :template template = tracker.templates[r[1]] rescan_template template[:file] end end end
Generated with the Darkfish Rdoc Generator 2.