require 'cgi' class Brakeman::Report::HTML < Brakeman::Report::Base HTML_CONFIDENCE = [ "High", "Medium", "Weak" ] def initialize *args super @element_id = 0 #Used for HTML ids end def generate_report out = html_header << generate_overview << generate_warning_overview.to_s # Return early if only summarizing return out if tracker.options[:summary_only] out << generate_controllers.to_s if tracker.options[:report_routes] or tracker.options[:debug] out << generate_templates.to_s if tracker.options[:debug] out << generate_errors.to_s out << generate_warnings.to_s out << generate_controller_warnings.to_s out << generate_model_warnings.to_s out << generate_template_warnings.to_s out << generate_ignored_warnings.to_s out << "" end def generate_overview locals = { :tracker => tracker, :warnings => all_warnings.length, :warnings_summary => warnings_summary, :number_of_templates => number_of_templates(@tracker), :ignored_warnings => ignored_warnings.length } Brakeman::Report::Renderer.new('overview', :locals => locals).render end #Generate listings of templates and their output def generate_templates out_processor = Brakeman::OutputProcessor.new template_rows = {} tracker.templates.each do |name, template| template.each_output do |out| out = CGI.escapeHTML(out_processor.format(out)) template_rows[name] ||= [] template_rows[name] << out.gsub("\n", ";").gsub(/\s+/, " ") end end template_rows = template_rows.sort_by{|name, value| name.to_s} Brakeman::Report::Renderer.new('template_overview', :locals => {:template_rows => template_rows}).render end def render_array template, headings, value_array, locals return if value_array.empty? Brakeman::Report::Renderer.new(template, :locals => locals).render end def convert_warning warning, original warning["Confidence"] = HTML_CONFIDENCE[warning["Confidence"]] warning["Message"] = with_context original, warning["Message"] warning["Warning Type"] = with_link original, warning["Warning Type"] warning end def with_link warning, message "#{message}" end def convert_template_warning warning, original warning["Confidence"] = HTML_CONFIDENCE[warning["Confidence"]] warning["Message"] = with_context original, warning["Message"] warning["Warning Type"] = with_link original, warning["Warning Type"] warning["Called From"] = original.called_from warning["Template Name"] = original.template.name warning end def convert_ignored_warning warning, original warning = convert_warning(warning, original) warning['File'] = original.relative_path warning['Note'] = CGI.escapeHTML(@ignore_filter.note_for(original) || "") warning end #Return header for HTML output. Uses CSS from tracker.options[:html_style] def html_header if File.exist? tracker.options[:html_style] css = File.read tracker.options[:html_style] else raise "Cannot find CSS stylesheet for HTML: #{tracker.options[:html_style]}" end locals = { :css => css, :tracker => tracker, :checks => checks, :rails_version => rails_version, :brakeman_version => Brakeman::Version } Brakeman::Report::Renderer.new('header', :locals => locals).render end #Generate HTML for warnings, including context show/hidden via Javascript def with_context warning, message context = context_for(@app_tree, warning) full_message = nil if tracker.options[:message_limit] and tracker.options[:message_limit] > 0 and message.length > tracker.options[:message_limit] full_message = html_message(warning, message) message = message[0..tracker.options[:message_limit]] << "..." end message = html_message(warning, message) return message if context.empty? and not full_message @element_id += 1 code_id = "context#@element_id" message_id = "message#@element_id" full_message_id = "full_message#@element_id" alt = false output = "
" << if full_message "#{message}" << "" else message end << "" << "" output << <<-HTML HTML unless context.empty? if warning.line - 1 == 1 or warning.line + 1 == 1 error = " near_error" elsif 1 == warning.line error = " error" else error = "" end output << <<-HTML HTML if context.length > 1 output << context[1..-1].map do |code| alt = !alt if code[0] == warning.line - 1 or code[0] == warning.line + 1 error = " near_error" elsif code[0] == warning.line error = " error" else error = "" end <<-HTML HTML end.join end end output << "
" end #Escape warning message and highlight user input in HTML output def html_message warning, message message = CGI.escapeHTML(message) if warning.file github_url = github_url warning.file, warning.line message.gsub!(/(near line \d+)/, "\\1") if github_url end if @highlight_user_input and warning.user_input user_input = CGI.escapeHTML(warning.format_user_input) message.gsub!(user_input, "#{user_input}") end message end end