railroader 4.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGES.md +1091 -0
- data/FEATURES +16 -0
- data/README.md +174 -0
- data/bin/railroader +8 -0
- data/lib/railroader/app_tree.rb +191 -0
- data/lib/railroader/call_index.rb +219 -0
- data/lib/railroader/checks/base_check.rb +505 -0
- data/lib/railroader/checks/check_basic_auth.rb +88 -0
- data/lib/railroader/checks/check_basic_auth_timing_attack.rb +33 -0
- data/lib/railroader/checks/check_content_tag.rb +200 -0
- data/lib/railroader/checks/check_create_with.rb +74 -0
- data/lib/railroader/checks/check_cross_site_scripting.rb +381 -0
- data/lib/railroader/checks/check_default_routes.rb +86 -0
- data/lib/railroader/checks/check_deserialize.rb +56 -0
- data/lib/railroader/checks/check_detailed_exceptions.rb +55 -0
- data/lib/railroader/checks/check_digest_dos.rb +38 -0
- data/lib/railroader/checks/check_divide_by_zero.rb +42 -0
- data/lib/railroader/checks/check_dynamic_finders.rb +48 -0
- data/lib/railroader/checks/check_escape_function.rb +21 -0
- data/lib/railroader/checks/check_evaluation.rb +35 -0
- data/lib/railroader/checks/check_execute.rb +189 -0
- data/lib/railroader/checks/check_file_access.rb +71 -0
- data/lib/railroader/checks/check_file_disclosure.rb +35 -0
- data/lib/railroader/checks/check_filter_skipping.rb +31 -0
- data/lib/railroader/checks/check_forgery_setting.rb +81 -0
- data/lib/railroader/checks/check_header_dos.rb +31 -0
- data/lib/railroader/checks/check_i18n_xss.rb +48 -0
- data/lib/railroader/checks/check_jruby_xml.rb +36 -0
- data/lib/railroader/checks/check_json_encoding.rb +47 -0
- data/lib/railroader/checks/check_json_parsing.rb +107 -0
- data/lib/railroader/checks/check_link_to.rb +132 -0
- data/lib/railroader/checks/check_link_to_href.rb +146 -0
- data/lib/railroader/checks/check_mail_to.rb +49 -0
- data/lib/railroader/checks/check_mass_assignment.rb +196 -0
- data/lib/railroader/checks/check_mime_type_dos.rb +39 -0
- data/lib/railroader/checks/check_model_attr_accessible.rb +55 -0
- data/lib/railroader/checks/check_model_attributes.rb +119 -0
- data/lib/railroader/checks/check_model_serialize.rb +67 -0
- data/lib/railroader/checks/check_nested_attributes.rb +38 -0
- data/lib/railroader/checks/check_nested_attributes_bypass.rb +58 -0
- data/lib/railroader/checks/check_number_to_currency.rb +74 -0
- data/lib/railroader/checks/check_permit_attributes.rb +43 -0
- data/lib/railroader/checks/check_quote_table_name.rb +40 -0
- data/lib/railroader/checks/check_redirect.rb +256 -0
- data/lib/railroader/checks/check_regex_dos.rb +68 -0
- data/lib/railroader/checks/check_render.rb +97 -0
- data/lib/railroader/checks/check_render_dos.rb +37 -0
- data/lib/railroader/checks/check_render_inline.rb +53 -0
- data/lib/railroader/checks/check_response_splitting.rb +21 -0
- data/lib/railroader/checks/check_route_dos.rb +42 -0
- data/lib/railroader/checks/check_safe_buffer_manipulation.rb +31 -0
- data/lib/railroader/checks/check_sanitize_methods.rb +112 -0
- data/lib/railroader/checks/check_secrets.rb +40 -0
- data/lib/railroader/checks/check_select_tag.rb +59 -0
- data/lib/railroader/checks/check_select_vulnerability.rb +60 -0
- data/lib/railroader/checks/check_send.rb +47 -0
- data/lib/railroader/checks/check_send_file.rb +19 -0
- data/lib/railroader/checks/check_session_manipulation.rb +35 -0
- data/lib/railroader/checks/check_session_settings.rb +176 -0
- data/lib/railroader/checks/check_simple_format.rb +58 -0
- data/lib/railroader/checks/check_single_quotes.rb +101 -0
- data/lib/railroader/checks/check_skip_before_filter.rb +60 -0
- data/lib/railroader/checks/check_sql.rb +700 -0
- data/lib/railroader/checks/check_sql_cves.rb +106 -0
- data/lib/railroader/checks/check_ssl_verify.rb +48 -0
- data/lib/railroader/checks/check_strip_tags.rb +89 -0
- data/lib/railroader/checks/check_symbol_dos.rb +71 -0
- data/lib/railroader/checks/check_symbol_dos_cve.rb +30 -0
- data/lib/railroader/checks/check_translate_bug.rb +45 -0
- data/lib/railroader/checks/check_unsafe_reflection.rb +50 -0
- data/lib/railroader/checks/check_unscoped_find.rb +57 -0
- data/lib/railroader/checks/check_validation_regex.rb +116 -0
- data/lib/railroader/checks/check_weak_hash.rb +148 -0
- data/lib/railroader/checks/check_without_protection.rb +80 -0
- data/lib/railroader/checks/check_xml_dos.rb +45 -0
- data/lib/railroader/checks/check_yaml_parsing.rb +121 -0
- data/lib/railroader/checks.rb +209 -0
- data/lib/railroader/codeclimate/engine_configuration.rb +97 -0
- data/lib/railroader/commandline.rb +179 -0
- data/lib/railroader/differ.rb +66 -0
- data/lib/railroader/file_parser.rb +54 -0
- data/lib/railroader/format/style.css +133 -0
- data/lib/railroader/options.rb +339 -0
- data/lib/railroader/parsers/rails2_erubis.rb +6 -0
- data/lib/railroader/parsers/rails2_xss_plugin_erubis.rb +48 -0
- data/lib/railroader/parsers/rails3_erubis.rb +81 -0
- data/lib/railroader/parsers/template_parser.rb +108 -0
- data/lib/railroader/processor.rb +102 -0
- data/lib/railroader/processors/alias_processor.rb +1229 -0
- data/lib/railroader/processors/base_processor.rb +295 -0
- data/lib/railroader/processors/config_processor.rb +14 -0
- data/lib/railroader/processors/controller_alias_processor.rb +278 -0
- data/lib/railroader/processors/controller_processor.rb +249 -0
- data/lib/railroader/processors/erb_template_processor.rb +77 -0
- data/lib/railroader/processors/erubis_template_processor.rb +92 -0
- data/lib/railroader/processors/gem_processor.rb +64 -0
- data/lib/railroader/processors/haml_template_processor.rb +191 -0
- data/lib/railroader/processors/lib/basic_processor.rb +37 -0
- data/lib/railroader/processors/lib/call_conversion_helper.rb +90 -0
- data/lib/railroader/processors/lib/find_all_calls.rb +224 -0
- data/lib/railroader/processors/lib/find_call.rb +183 -0
- data/lib/railroader/processors/lib/find_return_value.rb +166 -0
- data/lib/railroader/processors/lib/module_helper.rb +111 -0
- data/lib/railroader/processors/lib/processor_helper.rb +88 -0
- data/lib/railroader/processors/lib/rails2_config_processor.rb +145 -0
- data/lib/railroader/processors/lib/rails2_route_processor.rb +313 -0
- data/lib/railroader/processors/lib/rails3_config_processor.rb +132 -0
- data/lib/railroader/processors/lib/rails3_route_processor.rb +308 -0
- data/lib/railroader/processors/lib/render_helper.rb +181 -0
- data/lib/railroader/processors/lib/render_path.rb +107 -0
- data/lib/railroader/processors/lib/route_helper.rb +68 -0
- data/lib/railroader/processors/lib/safe_call_helper.rb +16 -0
- data/lib/railroader/processors/library_processor.rb +74 -0
- data/lib/railroader/processors/model_processor.rb +91 -0
- data/lib/railroader/processors/output_processor.rb +144 -0
- data/lib/railroader/processors/route_processor.rb +17 -0
- data/lib/railroader/processors/slim_template_processor.rb +111 -0
- data/lib/railroader/processors/template_alias_processor.rb +118 -0
- data/lib/railroader/processors/template_processor.rb +85 -0
- data/lib/railroader/report/config/remediation.yml +71 -0
- data/lib/railroader/report/ignore/config.rb +153 -0
- data/lib/railroader/report/ignore/interactive.rb +362 -0
- data/lib/railroader/report/pager.rb +112 -0
- data/lib/railroader/report/renderer.rb +24 -0
- data/lib/railroader/report/report_base.rb +292 -0
- data/lib/railroader/report/report_codeclimate.rb +79 -0
- data/lib/railroader/report/report_csv.rb +55 -0
- data/lib/railroader/report/report_hash.rb +23 -0
- data/lib/railroader/report/report_html.rb +216 -0
- data/lib/railroader/report/report_json.rb +45 -0
- data/lib/railroader/report/report_markdown.rb +107 -0
- data/lib/railroader/report/report_table.rb +117 -0
- data/lib/railroader/report/report_tabs.rb +17 -0
- data/lib/railroader/report/report_text.rb +198 -0
- data/lib/railroader/report/templates/controller_overview.html.erb +22 -0
- data/lib/railroader/report/templates/controller_warnings.html.erb +21 -0
- data/lib/railroader/report/templates/error_overview.html.erb +29 -0
- data/lib/railroader/report/templates/header.html.erb +58 -0
- data/lib/railroader/report/templates/ignored_warnings.html.erb +25 -0
- data/lib/railroader/report/templates/model_warnings.html.erb +21 -0
- data/lib/railroader/report/templates/overview.html.erb +38 -0
- data/lib/railroader/report/templates/security_warnings.html.erb +23 -0
- data/lib/railroader/report/templates/template_overview.html.erb +21 -0
- data/lib/railroader/report/templates/view_warnings.html.erb +34 -0
- data/lib/railroader/report/templates/warning_overview.html.erb +17 -0
- data/lib/railroader/report.rb +88 -0
- data/lib/railroader/rescanner.rb +483 -0
- data/lib/railroader/scanner.rb +321 -0
- data/lib/railroader/tracker/collection.rb +93 -0
- data/lib/railroader/tracker/config.rb +154 -0
- data/lib/railroader/tracker/constants.rb +171 -0
- data/lib/railroader/tracker/controller.rb +161 -0
- data/lib/railroader/tracker/library.rb +17 -0
- data/lib/railroader/tracker/model.rb +90 -0
- data/lib/railroader/tracker/template.rb +33 -0
- data/lib/railroader/tracker.rb +362 -0
- data/lib/railroader/util.rb +503 -0
- data/lib/railroader/version.rb +3 -0
- data/lib/railroader/warning.rb +294 -0
- data/lib/railroader/warning_codes.rb +117 -0
- data/lib/railroader.rb +544 -0
- data/lib/ruby_parser/bm_sexp.rb +626 -0
- data/lib/ruby_parser/bm_sexp_processor.rb +116 -0
- metadata +386 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
require 'railroader/options'
|
|
2
|
+
|
|
3
|
+
module Railroader
|
|
4
|
+
|
|
5
|
+
# Implements handling of running Railroader from the command line.
|
|
6
|
+
class Commandline
|
|
7
|
+
class << self
|
|
8
|
+
|
|
9
|
+
# Main method to run Railroader from the command line.
|
|
10
|
+
#
|
|
11
|
+
# If no options are provided, ARGV will be parsed and used instead.
|
|
12
|
+
# Otherwise, the options are expected to be a Hash like the one returned
|
|
13
|
+
# after ARGV is parsed.
|
|
14
|
+
def start options = nil, app_path = "."
|
|
15
|
+
|
|
16
|
+
unless options
|
|
17
|
+
options, app_path = parse_options ARGV
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
run options, app_path
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Runs everything:
|
|
24
|
+
#
|
|
25
|
+
# - `set_interrupt_handler`
|
|
26
|
+
# - `early_exit_options`
|
|
27
|
+
# - `set_options`
|
|
28
|
+
# - `check_latest`
|
|
29
|
+
# - `run_report`
|
|
30
|
+
def run options, default_app_path = "."
|
|
31
|
+
set_interrupt_handler options
|
|
32
|
+
early_exit_options options
|
|
33
|
+
set_options options, default_app_path
|
|
34
|
+
check_latest if options[:ensure_latest]
|
|
35
|
+
run_report options
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Check for the latest version.
|
|
39
|
+
#
|
|
40
|
+
# If the latest version is newer, quit with a message.
|
|
41
|
+
def check_latest
|
|
42
|
+
if error = Railroader.ensure_latest
|
|
43
|
+
quit Railroader::Not_Latest_Version_Exit_Code, error
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Runs a comparison report based on the options provided.
|
|
48
|
+
def compare_results options
|
|
49
|
+
require 'json'
|
|
50
|
+
vulns = Railroader.compare options.merge(:quiet => options[:quiet])
|
|
51
|
+
|
|
52
|
+
if options[:comparison_output_file]
|
|
53
|
+
File.open options[:comparison_output_file], "w" do |f|
|
|
54
|
+
f.puts JSON.pretty_generate(vulns)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
Railroader.notify "Comparison saved in '#{options[:comparison_output_file]}'"
|
|
58
|
+
else
|
|
59
|
+
puts JSON.pretty_generate(vulns)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
if options[:exit_on_warn] && vulns[:new].count > 0
|
|
63
|
+
quit Railroader::Warnings_Found_Exit_Code
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Handle options that exit without generating a report.
|
|
68
|
+
def early_exit_options options
|
|
69
|
+
if options[:list_checks] or options[:list_optional_checks]
|
|
70
|
+
Railroader.list_checks options
|
|
71
|
+
quit
|
|
72
|
+
elsif options[:create_config]
|
|
73
|
+
Railroader.dump_config options
|
|
74
|
+
quit
|
|
75
|
+
elsif options[:show_help]
|
|
76
|
+
puts Railroader::Options.create_option_parser({})
|
|
77
|
+
quit
|
|
78
|
+
elsif options[:show_version]
|
|
79
|
+
require 'railroader/version'
|
|
80
|
+
puts "railroader #{Railroader::Version}"
|
|
81
|
+
quit
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Parse ARGV-style array of options.
|
|
86
|
+
#
|
|
87
|
+
# Exits if options are invalid.
|
|
88
|
+
#
|
|
89
|
+
# Returns an option hash and the app_path.
|
|
90
|
+
def parse_options argv
|
|
91
|
+
begin
|
|
92
|
+
options, _ = Railroader::Options.parse! argv
|
|
93
|
+
rescue OptionParser::ParseError => e
|
|
94
|
+
$stderr.puts e.message
|
|
95
|
+
$stderr.puts "Please see `railroader --help` for valid options"
|
|
96
|
+
quit(-1)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
if argv[-1]
|
|
100
|
+
app_path = argv[-1]
|
|
101
|
+
else
|
|
102
|
+
app_path = "."
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
return options, app_path
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Exits with the given exit code and prints out the message, if given.
|
|
109
|
+
#
|
|
110
|
+
# Override this method for different behavior.
|
|
111
|
+
def quit exit_code = 0, message = nil
|
|
112
|
+
warn message if message
|
|
113
|
+
exit exit_code
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Runs a regular report based on the options provided.
|
|
117
|
+
def regular_report options
|
|
118
|
+
tracker = run_railroader options
|
|
119
|
+
|
|
120
|
+
if tracker.options[:exit_on_warn] and not tracker.filtered_warnings.empty?
|
|
121
|
+
quit Railroader::Warnings_Found_Exit_Code
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
if tracker.options[:exit_on_error] and tracker.errors.any?
|
|
125
|
+
quit Railroader::Errors_Found_Exit_Code
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Actually run Railroader.
|
|
130
|
+
#
|
|
131
|
+
# Returns a Tracker object.
|
|
132
|
+
def run_railroader options
|
|
133
|
+
Railroader.run options.merge(:print_report => true, :quiet => options[:quiet])
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Run either a comparison or regular report based on options provided.
|
|
137
|
+
def run_report options
|
|
138
|
+
begin
|
|
139
|
+
if options[:previous_results_json]
|
|
140
|
+
compare_results options
|
|
141
|
+
else
|
|
142
|
+
regular_report options
|
|
143
|
+
end
|
|
144
|
+
rescue Railroader::NoApplication => e
|
|
145
|
+
quit Railroader::No_App_Found_Exit_Code, e.message
|
|
146
|
+
rescue Railroader::MissingChecksError => e
|
|
147
|
+
quit Railroader::Missing_Checks_Exit_Code, e.message
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Sets interrupt handler to gracefully handle Ctrl+C
|
|
152
|
+
def set_interrupt_handler options
|
|
153
|
+
trap("INT") do
|
|
154
|
+
warn "\nInterrupted - exiting."
|
|
155
|
+
|
|
156
|
+
if options[:debug]
|
|
157
|
+
warn caller
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
exit!
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Modifies options, including setting the app_path
|
|
165
|
+
# if none is given in the options hash.
|
|
166
|
+
def set_options options, default_app_path = "."
|
|
167
|
+
unless options[:app_path]
|
|
168
|
+
options[:app_path] = default_app_path
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
if options[:quiet].nil?
|
|
172
|
+
options[:quiet] = :command_line
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
options
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# extracting the diff logic to it's own class for consistency. Currently handles
|
|
2
|
+
# an array of Railroader::Warnings or plain hash representations.
|
|
3
|
+
class Railroader::Differ
|
|
4
|
+
DEFAULT_HASH = {:new => [], :fixed => []}
|
|
5
|
+
OLD_WARNING_KEYS = [:warning_type, :location, :code, :message, :file, :link, :confidence, :user_input]
|
|
6
|
+
attr_reader :old_warnings, :new_warnings
|
|
7
|
+
|
|
8
|
+
def initialize new_warnings, old_warnings
|
|
9
|
+
@new_warnings = new_warnings
|
|
10
|
+
@old_warnings = old_warnings
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def diff
|
|
14
|
+
# get the type of elements
|
|
15
|
+
return DEFAULT_HASH if @new_warnings.empty?
|
|
16
|
+
|
|
17
|
+
warnings = {}
|
|
18
|
+
warnings[:new] = @new_warnings - @old_warnings
|
|
19
|
+
warnings[:fixed] = @old_warnings - @new_warnings
|
|
20
|
+
|
|
21
|
+
second_pass(warnings)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# second pass to cleanup any vulns which have changed in line number only.
|
|
25
|
+
# Given a list of new warnings, delete pairs of new/fixed vulns that differ
|
|
26
|
+
# only by line number.
|
|
27
|
+
# Horrible O(n^2) performance. Keep n small :-/
|
|
28
|
+
def second_pass(warnings)
|
|
29
|
+
# keep track of the number of elements deleted because the index numbers
|
|
30
|
+
# won't update as the list is modified
|
|
31
|
+
elements_deleted_offset = 0
|
|
32
|
+
|
|
33
|
+
# dup this list since we will be deleting from it and the iterator gets confused.
|
|
34
|
+
# use _with_index for fast deletion as opposed to .reject!{|obj| obj == *_warning}
|
|
35
|
+
warnings[:new].dup.each_with_index do |new_warning, new_warning_id|
|
|
36
|
+
warnings[:fixed].each_with_index do |fixed_warning, fixed_warning_id|
|
|
37
|
+
if eql_except_line_number new_warning, fixed_warning
|
|
38
|
+
warnings[:new].delete_at(new_warning_id - elements_deleted_offset)
|
|
39
|
+
elements_deleted_offset += 1
|
|
40
|
+
warnings[:fixed].delete_at(fixed_warning_id)
|
|
41
|
+
break
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
warnings
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def eql_except_line_number new_warning, fixed_warning
|
|
50
|
+
# can't do this ahead of time, as callers may be expecting a Railroader::Warning
|
|
51
|
+
if new_warning.is_a? Railroader::Warning
|
|
52
|
+
new_warning = new_warning.to_hash
|
|
53
|
+
fixed_warning = fixed_warning.to_hash
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if new_warning[:fingerprint] and fixed_warning[:fingerprint]
|
|
57
|
+
new_warning[:fingerprint] == fixed_warning[:fingerprint]
|
|
58
|
+
else
|
|
59
|
+
OLD_WARNING_KEYS.each do |attr|
|
|
60
|
+
return false if new_warning[attr] != fixed_warning[attr]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Railroader
|
|
2
|
+
ASTFile = Struct.new(:path, :ast)
|
|
3
|
+
|
|
4
|
+
# This class handles reading and parsing files.
|
|
5
|
+
class FileParser
|
|
6
|
+
attr_reader :file_list
|
|
7
|
+
|
|
8
|
+
def initialize tracker, app_tree
|
|
9
|
+
@tracker = tracker
|
|
10
|
+
@timeout = @tracker.options[:parser_timeout]
|
|
11
|
+
@app_tree = app_tree
|
|
12
|
+
@file_list = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def parse_files list, type
|
|
16
|
+
read_files list, type do |path, contents|
|
|
17
|
+
if ast = parse_ruby(contents, path)
|
|
18
|
+
ASTFile.new(path, ast)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def read_files list, type
|
|
24
|
+
@file_list[type] ||= []
|
|
25
|
+
|
|
26
|
+
list.each do |path|
|
|
27
|
+
result = yield path, read_path(path)
|
|
28
|
+
if result
|
|
29
|
+
@file_list[type] << result
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def parse_ruby input, path
|
|
35
|
+
begin
|
|
36
|
+
Railroader.debug "Parsing #{path}"
|
|
37
|
+
RubyParser.new.parse input, path, @timeout
|
|
38
|
+
rescue Racc::ParseError => e
|
|
39
|
+
@tracker.error e, "Could not parse #{path}"
|
|
40
|
+
nil
|
|
41
|
+
rescue Timeout::Error => e
|
|
42
|
+
@tracker.error Exception.new("Parsing #{path} took too long (> #{@timeout} seconds). Try increasing the limit with --parser-timeout"), caller
|
|
43
|
+
nil
|
|
44
|
+
rescue => e
|
|
45
|
+
@tracker.error e.exception(e.message + "\nWhile processing #{path}"), e.backtrace
|
|
46
|
+
nil
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def read_path path
|
|
51
|
+
@app_tree.read_path path
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/* CSS style used for HTML reports */
|
|
2
|
+
|
|
3
|
+
body {
|
|
4
|
+
font-family: sans-serif;
|
|
5
|
+
color: #161616;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
a {
|
|
9
|
+
color: #161616;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
p {
|
|
13
|
+
font-weight: bold;
|
|
14
|
+
font-size: 11pt;
|
|
15
|
+
color: #2D0200;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
th {
|
|
19
|
+
background-color: #980905;
|
|
20
|
+
border-bottom: 5px solid #530200;
|
|
21
|
+
color: white;
|
|
22
|
+
font-size: 11pt;
|
|
23
|
+
padding: 1px 8px 1px 8px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
td {
|
|
27
|
+
border-bottom: 2px solid white;
|
|
28
|
+
font-family: monospace;
|
|
29
|
+
padding: 5px 8px 1px 8px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
table {
|
|
33
|
+
background-color: #FCF4D4;
|
|
34
|
+
border-collapse: collapse;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
h1 {
|
|
38
|
+
color: #2D0200;
|
|
39
|
+
font-size: 14pt;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
h2 {
|
|
43
|
+
color: #2D0200;
|
|
44
|
+
font-size: 12pt;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
span.high-confidence {
|
|
48
|
+
font-weight:bold;
|
|
49
|
+
color: red;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
span.med-confidence {
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
span.weak-confidence {
|
|
56
|
+
color:gray;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
div.warning_message {
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
div.warning_message:hover {
|
|
64
|
+
background-color: white;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
table caption {
|
|
68
|
+
background-color: #FFE;
|
|
69
|
+
padding: 2px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
table.context {
|
|
73
|
+
margin-top: 5px;
|
|
74
|
+
margin-bottom: 5px;
|
|
75
|
+
border-left: 1px solid #90e960;
|
|
76
|
+
color: #212121;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
tr.context {
|
|
80
|
+
background-color: white;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
tr.first {
|
|
84
|
+
border-top: 1px solid #7ecc54;
|
|
85
|
+
padding-top: 2px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
tr.error {
|
|
89
|
+
background-color: #f4c1c1 !important
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
tr.near_error {
|
|
93
|
+
background-color: #f4d4d4 !important
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
tr.alt {
|
|
97
|
+
background-color: #e8f4d4;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
td.context {
|
|
101
|
+
padding: 2px 10px 0px 6px;
|
|
102
|
+
border-bottom: none;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
td.context_line {
|
|
106
|
+
padding: 2px 8px 0px 7px;
|
|
107
|
+
border-right: 1px solid #b3bda4;
|
|
108
|
+
border-bottom: none;
|
|
109
|
+
color: #6e7465;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
pre.context {
|
|
113
|
+
margin-bottom: 1px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.user_input {
|
|
117
|
+
background-color: #fcecab;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
div.render_path {
|
|
121
|
+
display: none;
|
|
122
|
+
background-color: #ffe;
|
|
123
|
+
padding: 5px;
|
|
124
|
+
margin: 2px 0px 2px 0px;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
div.template_name {
|
|
128
|
+
cursor: pointer;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
div.template_name:hover {
|
|
132
|
+
background-color: white;
|
|
133
|
+
}
|