stratagem 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/LICENSE +29 -0
  2. data/Manifest +40 -38
  3. data/Rakefile +3 -3
  4. data/lib/stratagem.rb +22 -7
  5. data/lib/stratagem/authentication.rb +2 -1
  6. data/lib/stratagem/auto_mock/aquifer.rb +88 -15
  7. data/lib/stratagem/auto_mock/factory.rb +19 -30
  8. data/lib/stratagem/auto_mock/value_generator.rb +3 -1
  9. data/lib/stratagem/client.rb +3 -2
  10. data/lib/stratagem/crawler/authentication.rb +10 -3
  11. data/lib/stratagem/crawler/form.rb +2 -2
  12. data/lib/stratagem/crawler/html_utils.rb +12 -1
  13. data/lib/stratagem/crawler/parameter_resolver.rb +18 -4
  14. data/lib/stratagem/crawler/route_invoker.rb +58 -16
  15. data/lib/stratagem/crawler/session.rb +13 -5
  16. data/lib/stratagem/crawler/site_model.rb +20 -8
  17. data/lib/stratagem/extensions/object.rb +2 -2
  18. data/lib/stratagem/extensions/string.rb +2 -2
  19. data/lib/stratagem/instrumentation.rb +18 -0
  20. data/lib/stratagem/{framework_extensions → instrumentation}/method_invocation.rb +1 -1
  21. data/lib/stratagem/instrumentation/models.rb +25 -0
  22. data/lib/stratagem/instrumentation/models/annotations.rb +114 -0
  23. data/lib/stratagem/instrumentation/models/association.rb +40 -0
  24. data/lib/stratagem/instrumentation/models/authentication.rb +7 -0
  25. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/authentication}/authlogic/detect.rb +2 -2
  26. data/lib/stratagem/instrumentation/models/authentication/authlogic/instrumentation.rb +13 -0
  27. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/authentication}/authlogic/metadata.rb +1 -3
  28. data/lib/stratagem/instrumentation/models/authentication/devise/detect.rb +11 -0
  29. data/lib/stratagem/instrumentation/models/authentication/devise/instrumentation.rb +18 -0
  30. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/authentication}/devise/metadata.rb +7 -3
  31. data/lib/stratagem/{framework_extensions/models/adapters/util/authentication_metadata.rb → instrumentation/models/authentication/metadata.rb} +2 -2
  32. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/authentication}/restful_authentication/detect.rb +2 -4
  33. data/lib/stratagem/{framework_extensions/models/adapters/restful_authentication/extensions.rb → instrumentation/models/authentication/restful_authentication/instrumentation.rb} +1 -1
  34. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/authentication}/restful_authentication/metadata.rb +2 -2
  35. data/lib/stratagem/{framework_extensions → instrumentation}/models/detect.rb +1 -1
  36. data/lib/stratagem/{framework_extensions → instrumentation}/models/metadata.rb +6 -4
  37. data/lib/stratagem/{framework_extensions → instrumentation}/models/mocking.rb +1 -1
  38. data/lib/stratagem/instrumentation/models/persistence.rb +9 -0
  39. data/lib/stratagem/instrumentation/models/persistence/active_record/detect.rb +18 -0
  40. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/persistence}/active_record/extensions.rb +5 -1
  41. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/persistence}/active_record/metadata.rb +25 -9
  42. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/persistence}/active_record/tracing.rb +4 -2
  43. data/lib/stratagem/instrumentation/models/persistence/common/detect.rb +7 -0
  44. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/persistence}/common/extensions.rb +0 -0
  45. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/persistence}/common/metadata.rb +6 -2
  46. data/lib/stratagem/instrumentation/models/persistence/common/tracing.rb +4 -0
  47. data/lib/stratagem/instrumentation/models/support_libraries.rb +7 -0
  48. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/support_libraries}/friendly_id/detect.rb +2 -2
  49. data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/support_libraries}/friendly_id/metadata.rb +2 -2
  50. data/lib/stratagem/instrumentation/models/support_libraries/state_machine/detect.rb +11 -0
  51. data/lib/stratagem/instrumentation/models/support_libraries/state_machine/metadata.rb +17 -0
  52. data/lib/stratagem/{framework_extensions → instrumentation}/models/tracing.rb +2 -2
  53. data/lib/stratagem/{framework_extensions → instrumentation}/rails.rb +0 -0
  54. data/lib/stratagem/{framework_extensions → instrumentation}/rails2/action_controller.rb +0 -0
  55. data/lib/stratagem/{framework_extensions → instrumentation}/rails2/action_mailer.rb +0 -0
  56. data/lib/stratagem/{framework_extensions → instrumentation}/rails3/parameters.rb +0 -0
  57. data/lib/stratagem/{framework_extensions → instrumentation}/request_forgery_protection.rb +0 -0
  58. data/lib/stratagem/model/application.rb +30 -15
  59. data/lib/stratagem/model/components/controller.rb +2 -2
  60. data/lib/stratagem/model/components/reference.rb +2 -2
  61. data/lib/stratagem/model/components/view.rb +1 -1
  62. data/lib/stratagem/model_builder.rb +19 -8
  63. data/lib/stratagem/scanner.rb +1 -1
  64. data/lib/stratagem/site_crawler.rb +4 -2
  65. data/stratagem.gemspec +7 -7
  66. data/templates/install/tasks/stratagem.rake +9 -1
  67. metadata +86 -82
  68. data/lib/stratagem/framework_extensions.rb +0 -18
  69. data/lib/stratagem/framework_extensions/models.rb +0 -21
  70. data/lib/stratagem/framework_extensions/models/adapters/active_record/detect.rb +0 -7
  71. data/lib/stratagem/framework_extensions/models/adapters/authlogic/extensions.rb +0 -10
  72. data/lib/stratagem/framework_extensions/models/adapters/authlogic/tracing.rb +0 -4
  73. data/lib/stratagem/framework_extensions/models/adapters/common/detect.rb +0 -7
  74. data/lib/stratagem/framework_extensions/models/adapters/common/tracing.rb +0 -4
  75. data/lib/stratagem/framework_extensions/models/adapters/devise/detect.rb +0 -11
  76. data/lib/stratagem/framework_extensions/models/adapters/devise/extensions.rb +0 -0
  77. data/lib/stratagem/framework_extensions/models/adapters/devise/tracing.rb +0 -4
  78. data/lib/stratagem/framework_extensions/models/adapters/friendly_id/extensions.rb +0 -0
  79. data/lib/stratagem/framework_extensions/models/adapters/friendly_id/tracing.rb +0 -4
  80. data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/tracing.rb +0 -4
  81. data/lib/stratagem/framework_extensions/models/annotations.rb +0 -78
@@ -9,7 +9,7 @@ module Stratagem
9
9
  def send(snapshot)
10
10
  Stratagem.logger.debug "Sending report to server"
11
11
  url = URI.parse("#{@authentication.base_url}/snapshots")
12
- req = Net::HTTPS::Post.new(url.path)
12
+ req = Stratagem.ssl? ? Net::HTTPS::Post.new(url.path) : Net::HTTP::Post.new(url.path)
13
13
 
14
14
  req.set_form_data({
15
15
  'auth_token' => @authentication.credentials[:token],
@@ -17,7 +17,8 @@ module Stratagem
17
17
  'timestamp' => snapshot.timestamp.to_i,
18
18
  'model' => snapshot.model.export.to_json
19
19
  }, ';')
20
- res = Net::HTTPS.new(url.host, url.port).start {|http| http.request(req) }
20
+ client = Stratagem.ssl? ? Net::HTTPS.new(url.host, url.port) : Net::HTTP.new(url.host, url.port)
21
+ res = client.start {|http| http.request(req) }
21
22
  puts "response:"
22
23
  case res
23
24
  when Net::HTTPSuccess, Net::HTTPRedirection
@@ -75,9 +75,15 @@ module Stratagem::Crawler
75
75
  if authentication.login_page.nil?
76
76
  puts "locating login page"
77
77
  puts "testing #{site_models.first.pages.size} pages"
78
- site_models.first.pages.sort {|a,b| b.inbound_edges(:redirect).size <=> a.inbound_edges(:redirect).size }.each do |page|
79
- if (page.login_form)
80
- puts "\tfound login form - #{page.login_form}"
78
+ possibilities = site_models.first.pages.select {|page| page.login_form != nil }
79
+ possibilities.sort! {|a,b| b.inbound_edges(:redirect).size <=> a.inbound_edges(:redirect).size }
80
+
81
+ # if the first page has one or more redirects to it then use it; otherwise select with page with the fewest inputs
82
+ if (possibilities.first.inbound_edges(:redirect).size > 0)
83
+ return possibilities.first
84
+ else
85
+ page = possibilities.sort {|a,b| a.login_form.inputs.size <=> b.login_form.inputs.size }.first
86
+ if (page)
81
87
  authentication.login_page = page
82
88
  return page
83
89
  end
@@ -94,6 +100,7 @@ module Stratagem::Crawler
94
100
 
95
101
  def login(user)
96
102
  populate_login_form(user).submit {|action,params|
103
+ p params
97
104
  post(action, params)
98
105
  }
99
106
  end
@@ -1,7 +1,7 @@
1
1
  # Primarily used to fill out login forms rather than trying to fudge the before_filters
2
2
  module Stratagem::Crawler
3
3
  class Form
4
- attr_accessor :action, :method, :fields, :buttons, :page
4
+ attr_accessor :action, :method, :buttons, :page
5
5
  attr_reader :inputs, :buttons
6
6
 
7
7
  def initialize
@@ -70,7 +70,7 @@ module Stratagem::Crawler
70
70
 
71
71
  def guess_alternate_attribute
72
72
  if (name =~ /(.*)\[(.*)\]/)
73
- $1.to_sym
73
+ $2.to_sym
74
74
  else
75
75
  name.to_sym
76
76
  end
@@ -13,12 +13,22 @@ module Stratagem::Crawler
13
13
  # this maps to the form action, not the controller action
14
14
  form.action =~ /log[-]*in/ ||
15
15
  form.action =~ /sign[-]*in/ ||
16
- !form.inputs.find {|input| input.type == 'password' }.nil?
16
+ begin
17
+ password_field = form.inputs.find {|input| input.type == 'password' }
18
+ if (password_field)
19
+ confirmation_field = form.inputs.find {|input| input.name.include?('_confirmation') && (input.name.to_s.sub('_confirmation','') == password_field.name) }
20
+ confirmation_field.nil?
21
+ else
22
+ false
23
+ end
24
+ end
17
25
  }.sort {|a,b| a.inputs.size <=> b.inputs.size }
18
26
  possibilities.first
19
27
  end
20
28
 
21
29
  def parse_forms(document)
30
+ return [] if document.nil?
31
+
22
32
  document.xpath('//form').map do |form_tag|
23
33
  form = Form.new()
24
34
  form.action = form_load_attribute(form_tag, 'action')
@@ -49,6 +59,7 @@ module Stratagem::Crawler
49
59
  value = (value ? value.value : option_tag.inner_html).strip
50
60
  input << value unless value.empty?
51
61
  end
62
+ form << input
52
63
  end
53
64
 
54
65
  def form_add_input(form, input_tag)
@@ -10,7 +10,7 @@ module Stratagem::Crawler
10
10
  if (unknown_params.size > 0)
11
11
  resolve_with_convention(unknown_params, resolved_params)
12
12
  resolve_with_instrumentation(route_container, resolved_params)
13
-
13
+ resolve_id_with_convention(route_container, unknown_params, resolved_params)
14
14
  log "\tresolved parameter types - #{resolved_params.inspect}"
15
15
  end
16
16
 
@@ -67,13 +67,27 @@ module Stratagem::Crawler
67
67
  unknown_params.delete(param)
68
68
  puts "\t\tresolved #{param} to #{model} using convention"
69
69
  rescue NameError
70
- puts $!
71
- puts $!.backtrace
72
- # not a model
70
+ puts "ERROR: #{$!.message}"
73
71
  end
74
72
  end
75
73
  end
76
74
  end
77
75
 
76
+ # resolve the ID parameter by looking at the previous segment of the URL
77
+ def resolve_id_with_convention(route_container, unknown_params, resolved_params)
78
+ if (unknown_params.include?('id'))
79
+ route_container.path.split('/').inject(nil) {|prev,part|
80
+ if (prev && part == ':id')
81
+ begin
82
+ resolved_params['id'] = prev.singularize.camelize.constantize
83
+ unknown_params.delete('id')
84
+ rescue
85
+ puts $!.message
86
+ end
87
+ end
88
+ part
89
+ }
90
+ end
91
+ end
78
92
  end
79
93
  end
@@ -14,16 +14,17 @@ module Stratagem::Crawler
14
14
  def call_route(route_info, track_invocations=true)
15
15
  begin
16
16
  call_route!(route_info, track_invocations)
17
- rescue
17
+ rescue Exception
18
18
  # TODO - add exception as a response page
19
19
  puts "ERROR: #{$!.message}"
20
+ puts $!.backtrace
20
21
  end
21
22
  end
22
23
 
23
24
  def call_route!(route_info, track_invocations=true)
24
25
  return if route_info.nil?
25
26
 
26
- puts route_info[:verb].downcase+" "+route_info[:path]
27
+ puts route_info[:verb].downcase+" "+route_info[:path]+" - #{route_info[:route_container].path}"
27
28
  verb = route_info[:verb].downcase
28
29
  verb = 'get' if verb == '' || verb == 'any'
29
30
 
@@ -33,6 +34,7 @@ module Stratagem::Crawler
33
34
  do_get(route_info)
34
35
  puts "\tresponse code: #{response.code}" if response
35
36
  when 'post'
37
+ do_post(route_info)
36
38
  when 'put'
37
39
  do_put(route_info)
38
40
  when 'delete'
@@ -48,8 +50,10 @@ module Stratagem::Crawler
48
50
  invocations.each do |i|
49
51
  puts "\t\t#{i.controller_action} -> #{i.model_class}"
50
52
  end
51
- puts "\tchanges: #{changes.values.inspect}" if changes.size > 0
53
+
54
+ puts "\tchanges values: #{changes.values.inspect}" if changes.size > 0
52
55
  site_model.add(route_info[:route_container], controller, request, response, invocations, changes) {|redirect_url| redirect_proc.call(redirect_url) }
56
+ puts "\tadded to site model"
53
57
  end
54
58
  else
55
59
  puts "ERROR: did not call #{route_info.inspect}"
@@ -61,9 +65,12 @@ module Stratagem::Crawler
61
65
  end
62
66
 
63
67
  def do_put(route_info)
64
- raise "unable to invoke PUT requests, application must first be crawled with GET requests for phase #{phase}." unless site_model.pages.size > 0
68
+ # raise "unable to invoke PUT requests, application must first be crawled with GET requests for phase #{site_model.name}." unless site_model.pages.size > 0
65
69
 
66
70
  form = guess_form_for_route(route_info)
71
+ if (form.nil?)
72
+ puts "WARNING: could not locate form for route #{route_info[:route_container].path}"
73
+ end
67
74
 
68
75
  params = {}
69
76
 
@@ -77,15 +84,11 @@ module Stratagem::Crawler
77
84
  end
78
85
  end
79
86
 
80
- p hash_reads
81
-
82
87
  # let's find out what the method is looking for in the params object
83
88
  models_by_hash_key = infer_models_for_param_reads(route_info[:route_container],hash_reads)
84
89
  params = map_models_to_attributes(models_by_hash_key)
85
90
 
86
- p params
87
-
88
- guess_unknown_params(models_by_hash_key, params, form)
91
+ guess_unknown_params(models_by_hash_key, params, form) if form
89
92
 
90
93
  # run again with the params
91
94
  puts "PUTTING: #{route_info[:path]} with #{params.inspect}"
@@ -95,13 +98,47 @@ module Stratagem::Crawler
95
98
  end
96
99
  end
97
100
 
101
+ def do_post(route_info)
102
+ raise "unable to invoke PUT requests, application must first be crawled with GET requests for phase #{phase}." unless site_model.pages.size > 0
103
+
104
+ form = guess_form_for_route(route_info)
105
+ if (form.nil?)
106
+ puts "WARNING: could not locate form for route #{route_info[:route_container].path}"
107
+ end
108
+
109
+ params = {}
110
+
111
+ # note: this should fail to generate anything meaningful, as we have not yet set up the parameters
112
+ hash_reads = Hash.track_parameter_reads do
113
+ begin
114
+ post route_info[:path], params
115
+ rescue
116
+ # TODO - log error as page response
117
+ puts "ERROR: #{response.code}"
118
+ end
119
+ end
120
+
121
+ # let's find out what the method is looking for in the params object
122
+ models_by_hash_key = infer_models_for_param_reads(route_info[:route_container],hash_reads)
123
+ params = map_models_to_attributes(models_by_hash_key)
124
+
125
+ guess_unknown_params(models_by_hash_key, params, form) if form
126
+
127
+ # run again with the params
128
+ puts "POSTING: #{route_info[:path]} with #{params.inspect}"
129
+
130
+ invocation_delta = model_invocations_for_request(:write) do
131
+ post route_info[:path], params
132
+ end
133
+ end
134
+
98
135
  private
99
136
 
100
137
  def guess_unknown_params(models_by_hash_key, known_params, form)
101
138
  (form.parameter_keys - IGNORE_PARAMETERS) .each {|path_s|
102
139
  path = path_s.split('[')
103
140
  path.last.gsub!(']', '')
104
- value = known_params
141
+ value = known_params || {}
105
142
  model = nil
106
143
  path.each do |key|
107
144
  key = key.to_sym
@@ -137,8 +174,11 @@ module Stratagem::Crawler
137
174
  site_model.pages.each do |page|
138
175
  page.forms.each do |form|
139
176
  usable = route_info[:route_container].responds_to?(form.action, form.implied_method || form.method)
140
- # puts "\t#{form.action} - #{form.method} - #{form.implied_method}"
141
- # puts "\tUSABLE" if usable
177
+ usable ||= begin
178
+ (route_info[:path].sub(/\.\(\:format\)*/, '') == form.action) &&
179
+ ((form.implied_method || form.method).to_s.downcase == route_info[:verb].to_s.downcase)
180
+ end
181
+ puts "\tform: #{form.action} - #{form.implied_method || form.method} - #{usable}"
142
182
  forms << form if (usable)
143
183
  end
144
184
  end
@@ -183,9 +223,12 @@ module Stratagem::Crawler
183
223
  if (invocation.model_instance)
184
224
  model = application_model.models.find {|m| m.klass == invocation.model_instance.class }
185
225
 
186
- puts "\t\t#{invocation.model_class}.#{invocation.method} - #{invocation.model_instance}"
226
+ puts "\t\t#{invocation.model_class}.#{invocation.method} - #{invocation.model_instance} - #{invocation.model_instance.id}"
227
+ ids = aquifer.instances_of(invocation.model_instance.class).map {|i| i.id }
228
+ puts "\t\tinstances: #{ids.inspect}"
187
229
  prior = aquifer.instances_of(invocation.model_instance.class).find {|m| m.id == invocation.model_instance.id }
188
230
  post = invocation.model_instance
231
+ prior ||= post
189
232
  attribute_names = (prior.stratagem.attribute_names + prior.stratagem.foreign_keys)
190
233
  changes[model] = attribute_names.select {|an|
191
234
  begin
@@ -216,7 +259,7 @@ module Stratagem::Crawler
216
259
  yield path
217
260
  else
218
261
  combinations = segment_values[0].product(*segment_values.slice(1,segment_values.size-1))
219
- combinations.each do |combination|
262
+ combinations.uniq.each do |combination|
220
263
  url = path.clone
221
264
  route.segment_keys.each_with_index {|segment_key,i| url.gsub!(':'+segment_key.to_s, combination[i].to_s) }
222
265
  yield url
@@ -232,7 +275,7 @@ module Stratagem::Crawler
232
275
 
233
276
 
234
277
  i = 12345
235
- insert_values = (route.segment_keys - [:format]).map {|segment_key|
278
+ insert_values = (route_container.segment_keys - [:format]).map {|segment_key|
236
279
  model = parameter_types[segment_key.to_s]
237
280
  value = nil
238
281
  if (model)
@@ -250,7 +293,6 @@ module Stratagem::Crawler
250
293
  permutation = {:verb => verb, :path => path, :route_container => route_container}
251
294
  routes << permutation
252
295
  end
253
-
254
296
  [routes, params]
255
297
  end
256
298
 
@@ -91,21 +91,29 @@ module Stratagem::Crawler::Session
91
91
 
92
92
  def print
93
93
  # print out pages and inbound / outbound links
94
+ # debugger
94
95
  site_model.pages.each do |page|
95
96
  title = page.title
96
97
  title ||= page.redirected_to.url if page.redirected_to
97
98
  title ||= page.response.code
98
99
  log "Page: #{page.url} - #{title} - #{page.response.code}"
99
- page.outbound_edges.each do |edge|
100
- log "\tout: #{edge.to.url} - #{edge.to.title} - #{edge.to.route}"
101
- end
102
- page.inbound_edges.each do |edge|
103
- log "\tin: #{edge.from.url} - #{edge.from.title}"
100
+ begin
101
+ page.outbound_edges.each do |edge|
102
+ log "\tout: #{edge.to.url} - #{edge.to.title} - #{edge.to.route}"
103
+ end
104
+ page.inbound_edges.each do |edge|
105
+ log "\tin: #{edge.from.url} - #{edge.from.title}"
106
+ end
107
+ rescue Exception
108
+ puts $!.message
109
+ puts $!.backtrace
104
110
  end
105
111
  end
112
+ puts "end of site model"
106
113
  end
107
114
 
108
115
  def crawl(verbs=[:any,:get])
116
+ puts "crawling site for verbs #{verbs.inspect}"
109
117
  verbs = [verbs] unless verbs.kind_of?(Array)
110
118
 
111
119
  # grab all pages independently
@@ -17,6 +17,7 @@ module Stratagem::Crawler
17
17
  :pages => @pages.map {|page| page.export },
18
18
  :edges => @edges.map {|edge| edge.export },
19
19
  :authentication => authentication.nil? ? nil : {
20
+ :authenticated_user_id => authentication.authenticated_with.object_id,
20
21
  :success => authentication.success,
21
22
  :login_page_external_id => authentication.login_page.object_id,
22
23
  :response_page_external_id => authentication.response_page.object_id,
@@ -74,12 +75,13 @@ module Stratagem::Crawler
74
75
  attr_accessor :method
75
76
  attr_accessor :redirected_to
76
77
  attr_accessor :document
78
+ attr_accessor :response_body
77
79
 
78
80
  def initialize(site_model, controller, request, response, invocations, model_changes, &block)
79
81
  @site_model = site_model
80
82
  @invocations = invocations
81
83
  @model_changes = model_changes
82
- @authenticity_checked = controller.authenticity_checked?
84
+ @authenticity_checked = (controller && controller.methods.include?(:authenticity_checked?)) ? controller.authenticity_checked? : true
83
85
  init(request, response, &block)
84
86
  end
85
87
 
@@ -98,7 +100,8 @@ module Stratagem::Crawler
98
100
  :references => @invocations.map {|i| i.to_reference.export },
99
101
  :model_changes => Hash[@model_changes.map {|model,changes| [model.object_id, changes] }].to_json,
100
102
  :authenticity_checked => @authenticity_checked,
101
- :parameters => @request.parameters.to_json
103
+ :parameters => @request.parameters.to_json,
104
+ :response_body => @response_body
102
105
  }
103
106
  h
104
107
  end
@@ -109,7 +112,12 @@ module Stratagem::Crawler
109
112
  @url = request.url
110
113
  @path = request.path
111
114
  @method = request.method
112
- @document = Nokogiri::HTML(response.body)
115
+ begin
116
+ @document = Nokogiri::HTML(response.body)
117
+ rescue
118
+ puts "ERROR: Could not parse html: #{$!.message} - #{response.body}"
119
+ end
120
+ @response_body = response.body
113
121
  self.redirected_to = block.call(response.redirect_url) if response.redirect?
114
122
  end
115
123
 
@@ -126,11 +134,15 @@ module Stratagem::Crawler
126
134
 
127
135
  def forms
128
136
  @forms ||= begin
129
- forms = self.parse_forms(@document)
130
- forms.each do |form|
131
- form.page = self
137
+ if (@document)
138
+ forms = self.parse_forms(@document)
139
+ forms.each do |form|
140
+ form.page = self
141
+ end
142
+ forms
143
+ else
144
+ []
132
145
  end
133
- forms
134
146
  end
135
147
  end
136
148
 
@@ -151,7 +163,7 @@ module Stratagem::Crawler
151
163
  end
152
164
 
153
165
  def title
154
- unless @title
166
+ if ((@document) && !(@title))
155
167
  title = (@document/'head title').first
156
168
  @title = title.inner_html if title
157
169
  end
@@ -2,8 +2,8 @@ class Object
2
2
  def methods_include?(name)
3
3
  methods.include?(name.to_sym) || methods.include?(name.to_s)
4
4
  end
5
-
6
- def self.subclasses
5
+
6
+ def self.sg_subclasses
7
7
  classes = []
8
8
  ObjectSpace.each_object(Class) do |c|
9
9
  next unless c.superclass == self || c.ancestors.include?(self)
@@ -7,8 +7,8 @@ class String
7
7
  match = false
8
8
  [
9
9
  Regexp.compile("^#{token}$", true),
10
- Regexp.compile("^#{token}[^A-Za-z0-9]", true),
11
- Regexp.compile("[^A-Za-z0-9]#{token}$", true),
10
+ Regexp.compile("^#{token}[^A-Za-z0-9_\-]*", true),
11
+ Regexp.compile("[^A-Za-z0-9_\-]*#{token}$", true),
12
12
  ].each do |regex|
13
13
  if (regex.match(self))
14
14
  match = true
@@ -0,0 +1,18 @@
1
+ module Stratagem::Instrumentation; end
2
+
3
+ require 'stratagem/instrumentation/rails'
4
+ require 'stratagem/instrumentation/method_invocation'
5
+ require 'stratagem/instrumentation/models'
6
+ require 'stratagem/instrumentation/request_forgery_protection'
7
+
8
+ if (Stratagem.rails_3?)
9
+ require 'stratagem/instrumentation/rails3/parameters'
10
+ elsif (Stratagem.rails_2?)
11
+ require 'stratagem/instrumentation/rails2/action_controller'
12
+ require 'stratagem/instrumentation/rails2/action_mailer'
13
+ else
14
+ raise "Unsupported Rails version #{Stratagem.rails_version}"
15
+ end
16
+
17
+
18
+