brakeman-lib 3.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +872 -0
  3. data/FEATURES +16 -0
  4. data/README.md +169 -0
  5. data/WARNING_TYPES +95 -0
  6. data/bin/brakeman +89 -0
  7. data/lib/brakeman.rb +495 -0
  8. data/lib/brakeman/app_tree.rb +161 -0
  9. data/lib/brakeman/brakeman.rake +17 -0
  10. data/lib/brakeman/call_index.rb +219 -0
  11. data/lib/brakeman/checks.rb +191 -0
  12. data/lib/brakeman/checks/base_check.rb +518 -0
  13. data/lib/brakeman/checks/check_basic_auth.rb +88 -0
  14. data/lib/brakeman/checks/check_basic_auth_timing_attack.rb +33 -0
  15. data/lib/brakeman/checks/check_content_tag.rb +160 -0
  16. data/lib/brakeman/checks/check_create_with.rb +75 -0
  17. data/lib/brakeman/checks/check_cross_site_scripting.rb +385 -0
  18. data/lib/brakeman/checks/check_default_routes.rb +86 -0
  19. data/lib/brakeman/checks/check_deserialize.rb +57 -0
  20. data/lib/brakeman/checks/check_detailed_exceptions.rb +55 -0
  21. data/lib/brakeman/checks/check_digest_dos.rb +38 -0
  22. data/lib/brakeman/checks/check_dynamic_finders.rb +49 -0
  23. data/lib/brakeman/checks/check_escape_function.rb +21 -0
  24. data/lib/brakeman/checks/check_evaluation.rb +36 -0
  25. data/lib/brakeman/checks/check_execute.rb +167 -0
  26. data/lib/brakeman/checks/check_file_access.rb +63 -0
  27. data/lib/brakeman/checks/check_file_disclosure.rb +35 -0
  28. data/lib/brakeman/checks/check_filter_skipping.rb +31 -0
  29. data/lib/brakeman/checks/check_forgery_setting.rb +74 -0
  30. data/lib/brakeman/checks/check_header_dos.rb +31 -0
  31. data/lib/brakeman/checks/check_i18n_xss.rb +48 -0
  32. data/lib/brakeman/checks/check_jruby_xml.rb +38 -0
  33. data/lib/brakeman/checks/check_json_encoding.rb +47 -0
  34. data/lib/brakeman/checks/check_json_parsing.rb +107 -0
  35. data/lib/brakeman/checks/check_link_to.rb +132 -0
  36. data/lib/brakeman/checks/check_link_to_href.rb +115 -0
  37. data/lib/brakeman/checks/check_mail_to.rb +49 -0
  38. data/lib/brakeman/checks/check_mass_assignment.rb +198 -0
  39. data/lib/brakeman/checks/check_mime_type_dos.rb +39 -0
  40. data/lib/brakeman/checks/check_model_attr_accessible.rb +55 -0
  41. data/lib/brakeman/checks/check_model_attributes.rb +119 -0
  42. data/lib/brakeman/checks/check_model_serialize.rb +67 -0
  43. data/lib/brakeman/checks/check_nested_attributes.rb +38 -0
  44. data/lib/brakeman/checks/check_nested_attributes_bypass.rb +58 -0
  45. data/lib/brakeman/checks/check_number_to_currency.rb +74 -0
  46. data/lib/brakeman/checks/check_quote_table_name.rb +40 -0
  47. data/lib/brakeman/checks/check_redirect.rb +215 -0
  48. data/lib/brakeman/checks/check_regex_dos.rb +69 -0
  49. data/lib/brakeman/checks/check_render.rb +92 -0
  50. data/lib/brakeman/checks/check_render_dos.rb +37 -0
  51. data/lib/brakeman/checks/check_render_inline.rb +54 -0
  52. data/lib/brakeman/checks/check_response_splitting.rb +21 -0
  53. data/lib/brakeman/checks/check_route_dos.rb +42 -0
  54. data/lib/brakeman/checks/check_safe_buffer_manipulation.rb +31 -0
  55. data/lib/brakeman/checks/check_sanitize_methods.rb +79 -0
  56. data/lib/brakeman/checks/check_secrets.rb +40 -0
  57. data/lib/brakeman/checks/check_select_tag.rb +60 -0
  58. data/lib/brakeman/checks/check_select_vulnerability.rb +60 -0
  59. data/lib/brakeman/checks/check_send.rb +48 -0
  60. data/lib/brakeman/checks/check_send_file.rb +19 -0
  61. data/lib/brakeman/checks/check_session_manipulation.rb +36 -0
  62. data/lib/brakeman/checks/check_session_settings.rb +170 -0
  63. data/lib/brakeman/checks/check_simple_format.rb +59 -0
  64. data/lib/brakeman/checks/check_single_quotes.rb +101 -0
  65. data/lib/brakeman/checks/check_skip_before_filter.rb +60 -0
  66. data/lib/brakeman/checks/check_sql.rb +660 -0
  67. data/lib/brakeman/checks/check_sql_cves.rb +101 -0
  68. data/lib/brakeman/checks/check_ssl_verify.rb +49 -0
  69. data/lib/brakeman/checks/check_strip_tags.rb +89 -0
  70. data/lib/brakeman/checks/check_symbol_dos.rb +64 -0
  71. data/lib/brakeman/checks/check_symbol_dos_cve.rb +30 -0
  72. data/lib/brakeman/checks/check_translate_bug.rb +45 -0
  73. data/lib/brakeman/checks/check_unsafe_reflection.rb +51 -0
  74. data/lib/brakeman/checks/check_unscoped_find.rb +41 -0
  75. data/lib/brakeman/checks/check_validation_regex.rb +116 -0
  76. data/lib/brakeman/checks/check_weak_hash.rb +151 -0
  77. data/lib/brakeman/checks/check_without_protection.rb +80 -0
  78. data/lib/brakeman/checks/check_xml_dos.rb +51 -0
  79. data/lib/brakeman/checks/check_yaml_parsing.rb +121 -0
  80. data/lib/brakeman/differ.rb +66 -0
  81. data/lib/brakeman/file_parser.rb +50 -0
  82. data/lib/brakeman/format/style.css +133 -0
  83. data/lib/brakeman/options.rb +301 -0
  84. data/lib/brakeman/parsers/rails2_erubis.rb +6 -0
  85. data/lib/brakeman/parsers/rails2_xss_plugin_erubis.rb +48 -0
  86. data/lib/brakeman/parsers/rails3_erubis.rb +74 -0
  87. data/lib/brakeman/parsers/template_parser.rb +89 -0
  88. data/lib/brakeman/processor.rb +102 -0
  89. data/lib/brakeman/processors/alias_processor.rb +1013 -0
  90. data/lib/brakeman/processors/base_processor.rb +277 -0
  91. data/lib/brakeman/processors/config_processor.rb +14 -0
  92. data/lib/brakeman/processors/controller_alias_processor.rb +273 -0
  93. data/lib/brakeman/processors/controller_processor.rb +326 -0
  94. data/lib/brakeman/processors/erb_template_processor.rb +80 -0
  95. data/lib/brakeman/processors/erubis_template_processor.rb +104 -0
  96. data/lib/brakeman/processors/gem_processor.rb +57 -0
  97. data/lib/brakeman/processors/haml_template_processor.rb +190 -0
  98. data/lib/brakeman/processors/lib/basic_processor.rb +37 -0
  99. data/lib/brakeman/processors/lib/find_all_calls.rb +223 -0
  100. data/lib/brakeman/processors/lib/find_call.rb +183 -0
  101. data/lib/brakeman/processors/lib/find_return_value.rb +134 -0
  102. data/lib/brakeman/processors/lib/processor_helper.rb +75 -0
  103. data/lib/brakeman/processors/lib/rails2_config_processor.rb +145 -0
  104. data/lib/brakeman/processors/lib/rails2_route_processor.rb +313 -0
  105. data/lib/brakeman/processors/lib/rails3_config_processor.rb +132 -0
  106. data/lib/brakeman/processors/lib/rails3_route_processor.rb +308 -0
  107. data/lib/brakeman/processors/lib/render_helper.rb +181 -0
  108. data/lib/brakeman/processors/lib/render_path.rb +107 -0
  109. data/lib/brakeman/processors/lib/route_helper.rb +68 -0
  110. data/lib/brakeman/processors/lib/safe_call_helper.rb +16 -0
  111. data/lib/brakeman/processors/library_processor.rb +119 -0
  112. data/lib/brakeman/processors/model_processor.rb +191 -0
  113. data/lib/brakeman/processors/output_processor.rb +171 -0
  114. data/lib/brakeman/processors/route_processor.rb +17 -0
  115. data/lib/brakeman/processors/slim_template_processor.rb +107 -0
  116. data/lib/brakeman/processors/template_alias_processor.rb +116 -0
  117. data/lib/brakeman/processors/template_processor.rb +74 -0
  118. data/lib/brakeman/report.rb +78 -0
  119. data/lib/brakeman/report/config/remediation.yml +71 -0
  120. data/lib/brakeman/report/ignore/config.rb +135 -0
  121. data/lib/brakeman/report/ignore/interactive.rb +311 -0
  122. data/lib/brakeman/report/renderer.rb +24 -0
  123. data/lib/brakeman/report/report_base.rb +286 -0
  124. data/lib/brakeman/report/report_codeclimate.rb +70 -0
  125. data/lib/brakeman/report/report_csv.rb +55 -0
  126. data/lib/brakeman/report/report_hash.rb +23 -0
  127. data/lib/brakeman/report/report_html.rb +216 -0
  128. data/lib/brakeman/report/report_json.rb +42 -0
  129. data/lib/brakeman/report/report_markdown.rb +156 -0
  130. data/lib/brakeman/report/report_table.rb +107 -0
  131. data/lib/brakeman/report/report_tabs.rb +17 -0
  132. data/lib/brakeman/report/templates/controller_overview.html.erb +22 -0
  133. data/lib/brakeman/report/templates/controller_warnings.html.erb +21 -0
  134. data/lib/brakeman/report/templates/error_overview.html.erb +29 -0
  135. data/lib/brakeman/report/templates/header.html.erb +58 -0
  136. data/lib/brakeman/report/templates/ignored_warnings.html.erb +25 -0
  137. data/lib/brakeman/report/templates/model_warnings.html.erb +21 -0
  138. data/lib/brakeman/report/templates/overview.html.erb +38 -0
  139. data/lib/brakeman/report/templates/security_warnings.html.erb +23 -0
  140. data/lib/brakeman/report/templates/template_overview.html.erb +21 -0
  141. data/lib/brakeman/report/templates/view_warnings.html.erb +34 -0
  142. data/lib/brakeman/report/templates/warning_overview.html.erb +17 -0
  143. data/lib/brakeman/rescanner.rb +483 -0
  144. data/lib/brakeman/scanner.rb +317 -0
  145. data/lib/brakeman/tracker.rb +347 -0
  146. data/lib/brakeman/tracker/collection.rb +93 -0
  147. data/lib/brakeman/tracker/config.rb +101 -0
  148. data/lib/brakeman/tracker/constants.rb +101 -0
  149. data/lib/brakeman/tracker/controller.rb +161 -0
  150. data/lib/brakeman/tracker/library.rb +17 -0
  151. data/lib/brakeman/tracker/model.rb +90 -0
  152. data/lib/brakeman/tracker/template.rb +33 -0
  153. data/lib/brakeman/util.rb +481 -0
  154. data/lib/brakeman/version.rb +3 -0
  155. data/lib/brakeman/warning.rb +255 -0
  156. data/lib/brakeman/warning_codes.rb +111 -0
  157. data/lib/ruby_parser/bm_sexp.rb +610 -0
  158. data/lib/ruby_parser/bm_sexp_processor.rb +116 -0
  159. metadata +362 -0
@@ -0,0 +1,311 @@
1
+ Brakeman.load_brakeman_dependency 'highline'
2
+
3
+ module Brakeman
4
+ class InteractiveIgnorer
5
+ def initialize file, warnings
6
+ @ignore_config = Brakeman::IgnoreConfig.new(file, warnings)
7
+ @new_warnings = warnings
8
+ @skip_ignored = false
9
+ @skip_rest = false
10
+ @ignore_rest = false
11
+ @quit = false
12
+ @restart = false
13
+ end
14
+
15
+ def start
16
+ file_menu
17
+ initial_menu
18
+
19
+ @ignore_config.filter_ignored
20
+
21
+ unless @quit
22
+ final_menu
23
+ end
24
+
25
+ if @restart
26
+ @restart = false
27
+ start
28
+ end
29
+
30
+ @ignore_config
31
+ end
32
+
33
+ private
34
+
35
+ def file_menu
36
+ loop do
37
+ @ignore_config.file = HighLine.new.ask "Input file: " do |q|
38
+ if @ignore_config.file and not @ignore_config.file.empty?
39
+ q.default = @ignore_config.file
40
+ else
41
+ q.default = "config/brakeman.ignore"
42
+ end
43
+ end
44
+
45
+ if File.exist? @ignore_config.file
46
+ @ignore_config.read_from_file
47
+ return
48
+ else
49
+ if yes_or_no "No such file. Continue with empty config? "
50
+ return
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ def initial_menu
57
+ HighLine.new.choose do |m|
58
+ m.choice "Inspect all warnings" do
59
+ @skip_ignored = false
60
+ process_warnings
61
+ end
62
+
63
+ m.choice "Hide previously ignored warnings" do
64
+ @skip_ignored = true
65
+ process_warnings
66
+ end
67
+
68
+ m.choice "Skip - use current ignore configuration" do
69
+ @quit = true
70
+ @ignore_config.filter_ignored
71
+ end
72
+ end
73
+ end
74
+
75
+ def warning_menu
76
+ HighLine.new.choose do |m|
77
+ m.prompt = "Action: "
78
+ m.layout = :one_line
79
+ m.list_option = ", "
80
+ m.select_by = :name
81
+
82
+ m.choice "i"
83
+ m.choice "n"
84
+ m.choice "k"
85
+ m.choice "u"
86
+ m.choice "a"
87
+ m.choice "s"
88
+ m.choice "q"
89
+ m.choice "?" do
90
+ say <<-HELP
91
+ i - Add warning to ignore list
92
+ n - Add warning to ignore list and add note
93
+ s - Skip this warning (will remain ignored or shown)
94
+ u - Remove this warning from ignore list
95
+ a - Ignore this warning and all remaining warnings
96
+ k - Skip this warning and all remaining warnings
97
+ q - Quit, do not update ignored warnings
98
+ ? - Display this help
99
+ HELP
100
+
101
+ "?"
102
+ end
103
+ end
104
+ end
105
+
106
+ def final_menu
107
+ summarize_changes
108
+
109
+ HighLine.new.choose do |m|
110
+ m.choice "Save changes" do
111
+ save
112
+ end
113
+
114
+ m.choice "Start over" do
115
+ start_over
116
+ end
117
+
118
+ m.choice "Quit, do not save changes" do
119
+ quit
120
+ end
121
+ end
122
+ end
123
+
124
+ def save
125
+ @ignore_config.file = HighLine.new.ask "Output file: " do |q|
126
+ if @ignore_config.file and not @ignore_config.file.empty?
127
+ q.default = @ignore_config.file
128
+ else
129
+ q.default = "config/brakeman.ignore"
130
+ end
131
+ end
132
+
133
+ @ignore_config.save_with_old
134
+ end
135
+
136
+ def start_over
137
+ reset_config
138
+ @restart = true
139
+ end
140
+
141
+ def reset_config
142
+ @ignore_config = Brakeman::IgnoreConfig.new(@ignore_config.file, @new_warnings)
143
+ end
144
+
145
+ def process_warnings
146
+ @new_warnings.each do |w|
147
+ if skip_ignored? w or @skip_rest
148
+ next
149
+ elsif @ignore_rest
150
+ ignore w
151
+ elsif @quit or @restart
152
+ return
153
+ else
154
+ ask_about w
155
+ end
156
+ end
157
+ end
158
+
159
+ def ask_about warning
160
+ pretty_display warning
161
+ warning_action warning_menu, warning
162
+ end
163
+
164
+ def warning_action action, warning
165
+ case action
166
+ when "i"
167
+ ignore warning
168
+ when "n"
169
+ ignore_and_note warning
170
+ when "s"
171
+ # do nothing
172
+ when "u"
173
+ unignore warning
174
+ when "a"
175
+ ignore_rest warning
176
+ when "k"
177
+ skip_rest warning
178
+ when "q"
179
+ quit
180
+ when "?"
181
+ ask_about warning
182
+ else
183
+ raise "Unexpected action"
184
+ end
185
+ end
186
+
187
+ def ignore warning
188
+ @ignore_config.ignore warning
189
+ end
190
+
191
+ def ignore_and_note warning
192
+ note = HighLine.new.ask("Note: ")
193
+ @ignore_config.ignore warning
194
+ @ignore_config.add_note warning, note
195
+ end
196
+
197
+ def unignore warning
198
+ @ignore_config.unignore warning
199
+ end
200
+
201
+ def skip_rest warning
202
+ @skip_rest = true
203
+ end
204
+
205
+ def ignore_rest warning
206
+ ignore warning
207
+ @ignore_rest = true
208
+ end
209
+
210
+ def quit
211
+ reset_config
212
+ @ignore_config.read_from_file
213
+ @ignore_config.filter_ignored
214
+ @quit = true
215
+ end
216
+
217
+ def pretty_display warning
218
+ say "-" * 20
219
+ show_confidence warning
220
+
221
+ label "Category"
222
+ say warning.warning_type
223
+
224
+ label "Message"
225
+ say warning.message
226
+
227
+ if warning.code
228
+ label "Code"
229
+ say warning.format_code
230
+ end
231
+
232
+ if warning.relative_path
233
+ label "File"
234
+ say warning.relative_path
235
+ end
236
+
237
+ if warning.line
238
+ label "Line"
239
+ say warning.line
240
+ end
241
+
242
+ if already_ignored? warning
243
+ show_note warning
244
+ say "Already ignored", :red
245
+ end
246
+
247
+ say ""
248
+ end
249
+
250
+ def already_ignored? warning
251
+ @ignore_config.ignored? warning
252
+ end
253
+
254
+ def skip_ignored? warning
255
+ @skip_ignored and already_ignored? warning
256
+ end
257
+
258
+ def summarize_changes
259
+ say "-" * 20
260
+
261
+ say "Ignoring #{@ignore_config.ignored_warnings.length} warnings", :yellow
262
+ say "Showing #{@ignore_config.shown_warnings.length} warnings", :green
263
+ end
264
+
265
+ def label name
266
+ say "#{name}: ", :green
267
+ end
268
+
269
+ def show_confidence warning
270
+ label "Confidence"
271
+
272
+ case warning.confidence
273
+ when 0
274
+ say "High", :red
275
+ when 1
276
+ say "Medium", :yellow
277
+ when 2
278
+ say "Weak", :cyan
279
+ else
280
+ say "Unknown"
281
+ end
282
+ end
283
+
284
+ def show_note warning
285
+ note = @ignore_config.note_for warning
286
+
287
+ if note
288
+ label "Note"
289
+ say note
290
+ end
291
+ end
292
+
293
+ def say text, color = nil
294
+ text = text.to_s
295
+
296
+ if color
297
+ HighLine.new.say HighLine.new.color(text, color)
298
+ else
299
+ HighLine.new.say text
300
+ end
301
+ end
302
+
303
+ def yes_or_no message
304
+ answer = HighLine.new.ask message do |q|
305
+ q.in = ["y", "n", "yes", "no"]
306
+ end
307
+
308
+ answer.match /^y/i
309
+ end
310
+ end
311
+ end
@@ -0,0 +1,24 @@
1
+ require 'erb'
2
+
3
+ class Brakeman::Report
4
+ class Renderer
5
+ def initialize(template_file, hash = {})
6
+ hash[:locals] ||= {}
7
+ singleton = class << self; self end
8
+
9
+ hash[:locals].each do |attribute_name, attribute_value|
10
+ singleton.send(:define_method, attribute_name) { attribute_value }
11
+ end
12
+
13
+ # There are last, so as to make overwriting these using locals impossible.
14
+ singleton.send(:define_method, 'template_file') { template_file }
15
+ singleton.send(:define_method, 'template') {
16
+ File.read(File.expand_path("templates/#{template_file}.html.erb", File.dirname(__FILE__)))
17
+ }
18
+ end
19
+
20
+ def render
21
+ ERB.new(template).result(binding)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,286 @@
1
+ require 'set'
2
+ require 'brakeman/util'
3
+ require 'brakeman/version'
4
+ require 'brakeman/report/renderer'
5
+ require 'brakeman/processors/output_processor'
6
+
7
+ # Base class for report formats
8
+ class Brakeman::Report::Base
9
+ include Brakeman::Util
10
+
11
+ attr_reader :tracker, :checks
12
+
13
+ TEXT_CONFIDENCE = [ "High", "Medium", "Weak" ]
14
+
15
+ def initialize app_tree, tracker
16
+ @app_tree = app_tree
17
+ @tracker = tracker
18
+ @checks = tracker.checks
19
+ @ignore_filter = tracker.ignored_filter
20
+ @highlight_user_input = tracker.options[:highlight_user_input]
21
+ @warnings_summary = nil
22
+ end
23
+
24
+ #Generate table of how many warnings of each warning type were reported
25
+ def generate_warning_overview
26
+ types = warnings_summary.keys
27
+ types.delete :high_confidence
28
+ values = types.sort.collect{|warning_type| [warning_type, warnings_summary[warning_type]] }
29
+ locals = {:types => types, :warnings_summary => warnings_summary}
30
+
31
+ render_array('warning_overview', ['Warning Type', 'Total'], values, locals)
32
+ end
33
+
34
+ #Generate table of controllers and routes found for those controllers
35
+ def generate_controllers
36
+ controller_rows = []
37
+
38
+ tracker.controllers.keys.map{|k| k.to_s}.sort.each do |name|
39
+ name = name.to_sym
40
+ c = tracker.controllers[name]
41
+
42
+ if tracker.routes.include? :allow_all_actions or (tracker.routes[name] and tracker.routes[name].include? :allow_all_actions)
43
+ routes = c.methods_public.keys.map{|e| e.to_s}.sort.join(", ")
44
+ elsif tracker.routes[name].nil?
45
+ #No routes defined for this controller.
46
+ #This can happen when it is only a parent class
47
+ #for other controllers, for example.
48
+ routes = "[None]"
49
+
50
+ else
51
+ routes = (Set.new(c.methods_public.keys) & tracker.routes[name.to_sym]).
52
+ to_a.
53
+ map {|e| e.to_s}.
54
+ sort.
55
+ join(", ")
56
+ end
57
+
58
+ if routes == ""
59
+ routes = "[None]"
60
+ end
61
+
62
+ controller_rows << { "Name" => name.to_s,
63
+ "Parent" => c.parent.to_s,
64
+ "Includes" => c.includes.join(", "),
65
+ "Routes" => routes
66
+ }
67
+ end
68
+
69
+ cols = ['Name', 'Parent', 'Includes', 'Routes']
70
+
71
+ locals = {:controller_rows => controller_rows}
72
+ values = controller_rows.collect{|row| row.values_at(*cols) }
73
+ render_array('controller_overview', cols, values, locals)
74
+ end
75
+
76
+ #Generate table of errors or return nil if no errors
77
+ def generate_errors
78
+ values = tracker.errors.collect{|error| [error[:error], error[:backtrace][0]]}
79
+ render_array('error_overview', ['Error', 'Location'], values, {:tracker => tracker})
80
+ end
81
+
82
+ def generate_warnings
83
+ render_warnings generic_warnings,
84
+ :warning,
85
+ 'security_warnings',
86
+ ["Confidence", "Class", "Method", "Warning Type", "Message"],
87
+ 'Class'
88
+ end
89
+
90
+ #Generate table of template warnings or return nil if no warnings
91
+ def generate_template_warnings
92
+ render_warnings template_warnings,
93
+ :template,
94
+ 'view_warnings',
95
+ ['Confidence', 'Template', 'Warning Type', 'Message'],
96
+ 'Template'
97
+
98
+ end
99
+
100
+ #Generate table of model warnings or return nil if no warnings
101
+ def generate_model_warnings
102
+ render_warnings model_warnings,
103
+ :model,
104
+ 'model_warnings',
105
+ ['Confidence', 'Model', 'Warning Type', 'Message'],
106
+ 'Model'
107
+ end
108
+
109
+ #Generate table of controller warnings or nil if no warnings
110
+ def generate_controller_warnings
111
+ render_warnings controller_warnings,
112
+ :controller,
113
+ 'controller_warnings',
114
+ ['Confidence', 'Controller', 'Warning Type', 'Message'],
115
+ 'Controller'
116
+ end
117
+
118
+ def generate_ignored_warnings
119
+ render_warnings ignored_warnings,
120
+ :ignored,
121
+ 'ignored_warnings',
122
+ ['Confidence', 'Warning Type', 'File', 'Message'],
123
+ 'Warning Type'
124
+ end
125
+
126
+ def render_warnings warnings, type, template, cols, sort_col
127
+ unless warnings.empty?
128
+ rows = sort(convert_to_rows(warnings, type), sort_col)
129
+
130
+ values = rows.collect { |row| row.values_at(*cols) }
131
+
132
+ locals = { :warnings => rows }
133
+
134
+ render_array(template, cols, values, locals)
135
+ else
136
+ nil
137
+ end
138
+ end
139
+
140
+ def convert_to_rows warnings, type = :warning
141
+ warnings.map do |warning|
142
+ w = warning.to_row type
143
+
144
+ case type
145
+ when :warning
146
+ convert_warning w, warning
147
+ when :template
148
+ convert_template_warning w, warning
149
+ when :model
150
+ convert_model_warning w, warning
151
+ when :controller
152
+ convert_controller_warning w, warning
153
+ when :ignored
154
+ convert_ignored_warning w, warning
155
+ end
156
+ end
157
+ end
158
+
159
+ def convert_warning warning, original
160
+ warning["Confidence"] = TEXT_CONFIDENCE[warning["Confidence"]]
161
+ warning["Message"] = text_message original, warning["Message"]
162
+ warning
163
+ end
164
+
165
+ def convert_template_warning warning, original
166
+ convert_warning warning, original
167
+ end
168
+
169
+ def convert_model_warning warning, original
170
+ convert_warning warning, original
171
+ end
172
+
173
+ def convert_controller_warning warning, original
174
+ convert_warning warning, original
175
+ end
176
+
177
+ def convert_ignored_warning warning, original
178
+ convert_warning warning, original
179
+ end
180
+
181
+ def sort rows, sort_col
182
+ stabilizer = 0
183
+ rows.sort_by do |row|
184
+ stabilizer += 1
185
+
186
+ row.values_at("Confidence", "Warning Type", sort_col) << stabilizer
187
+ end
188
+ end
189
+
190
+ #Return summary of warnings in hash and store in @warnings_summary
191
+ def warnings_summary
192
+ return @warnings_summary if @warnings_summary
193
+
194
+ summary = Hash.new(0)
195
+ high_confidence_warnings = 0
196
+
197
+ [all_warnings].each do |warnings|
198
+ warnings.each do |warning|
199
+ summary[warning.warning_type.to_s] += 1
200
+ high_confidence_warnings += 1 if warning.confidence == 0
201
+ end
202
+ end
203
+
204
+ summary[:high_confidence] = high_confidence_warnings
205
+ @warnings_summary = summary
206
+ end
207
+
208
+ def all_warnings
209
+ if @ignore_filter
210
+ @all_warnings ||= @ignore_filter.shown_warnings
211
+ else
212
+ @all_warnings ||= tracker.checks.all_warnings
213
+ end
214
+ end
215
+
216
+ def filter_warnings warnings
217
+ if @ignore_filter
218
+ warnings.reject do |w|
219
+ @ignore_filter.ignored? w
220
+ end
221
+ else
222
+ warnings
223
+ end
224
+ end
225
+
226
+ def generic_warnings
227
+ filter_warnings tracker.checks.warnings
228
+ end
229
+
230
+ def template_warnings
231
+ filter_warnings tracker.checks.template_warnings
232
+ end
233
+
234
+ def model_warnings
235
+ filter_warnings tracker.checks.model_warnings
236
+ end
237
+
238
+ def controller_warnings
239
+ filter_warnings tracker.checks.controller_warnings
240
+ end
241
+
242
+ def ignored_warnings
243
+ if @ignore_filter
244
+ @ignore_filter.ignored_warnings
245
+ else
246
+ []
247
+ end
248
+ end
249
+
250
+ def number_of_templates tracker
251
+ Set.new(tracker.templates.map {|k,v| v.name.to_s[/[^.]+/]}).length
252
+ end
253
+
254
+ def warning_file warning, absolute = @tracker.options[:absolute_paths]
255
+ return nil if warning.file.nil?
256
+
257
+ if absolute
258
+ warning.file
259
+ else
260
+ relative_path warning.file
261
+ end
262
+ end
263
+
264
+ def rails_version
265
+ case
266
+ when tracker.config.rails_version
267
+ tracker.config.rails_version
268
+ when tracker.options[:rails4]
269
+ "4.x"
270
+ when tracker.options[:rails3]
271
+ "3.x"
272
+ else
273
+ "Unknown"
274
+ end
275
+ end
276
+
277
+ #Escape warning message and highlight user input in text output
278
+ def text_message warning, message
279
+ if @highlight_user_input and warning.user_input
280
+ user_input = warning.format_user_input
281
+ message.gsub(user_input, "+#{user_input}+")
282
+ else
283
+ message
284
+ end
285
+ end
286
+ end