stratagem 0.2.0 → 0.2.2
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.
- data/LICENSE +29 -0
- data/Manifest +40 -38
- data/Rakefile +3 -3
- data/lib/stratagem.rb +22 -7
- data/lib/stratagem/authentication.rb +2 -1
- data/lib/stratagem/auto_mock/aquifer.rb +88 -15
- data/lib/stratagem/auto_mock/factory.rb +19 -30
- data/lib/stratagem/auto_mock/value_generator.rb +3 -1
- data/lib/stratagem/client.rb +3 -2
- data/lib/stratagem/crawler/authentication.rb +10 -3
- data/lib/stratagem/crawler/form.rb +2 -2
- data/lib/stratagem/crawler/html_utils.rb +12 -1
- data/lib/stratagem/crawler/parameter_resolver.rb +18 -4
- data/lib/stratagem/crawler/route_invoker.rb +58 -16
- data/lib/stratagem/crawler/session.rb +13 -5
- data/lib/stratagem/crawler/site_model.rb +20 -8
- data/lib/stratagem/extensions/object.rb +2 -2
- data/lib/stratagem/extensions/string.rb +2 -2
- data/lib/stratagem/instrumentation.rb +18 -0
- data/lib/stratagem/{framework_extensions → instrumentation}/method_invocation.rb +1 -1
- data/lib/stratagem/instrumentation/models.rb +25 -0
- data/lib/stratagem/instrumentation/models/annotations.rb +114 -0
- data/lib/stratagem/instrumentation/models/association.rb +40 -0
- data/lib/stratagem/instrumentation/models/authentication.rb +7 -0
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/authentication}/authlogic/detect.rb +2 -2
- data/lib/stratagem/instrumentation/models/authentication/authlogic/instrumentation.rb +13 -0
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/authentication}/authlogic/metadata.rb +1 -3
- data/lib/stratagem/instrumentation/models/authentication/devise/detect.rb +11 -0
- data/lib/stratagem/instrumentation/models/authentication/devise/instrumentation.rb +18 -0
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/authentication}/devise/metadata.rb +7 -3
- data/lib/stratagem/{framework_extensions/models/adapters/util/authentication_metadata.rb → instrumentation/models/authentication/metadata.rb} +2 -2
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/authentication}/restful_authentication/detect.rb +2 -4
- data/lib/stratagem/{framework_extensions/models/adapters/restful_authentication/extensions.rb → instrumentation/models/authentication/restful_authentication/instrumentation.rb} +1 -1
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/authentication}/restful_authentication/metadata.rb +2 -2
- data/lib/stratagem/{framework_extensions → instrumentation}/models/detect.rb +1 -1
- data/lib/stratagem/{framework_extensions → instrumentation}/models/metadata.rb +6 -4
- data/lib/stratagem/{framework_extensions → instrumentation}/models/mocking.rb +1 -1
- data/lib/stratagem/instrumentation/models/persistence.rb +9 -0
- data/lib/stratagem/instrumentation/models/persistence/active_record/detect.rb +18 -0
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/persistence}/active_record/extensions.rb +5 -1
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/persistence}/active_record/metadata.rb +25 -9
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/persistence}/active_record/tracing.rb +4 -2
- data/lib/stratagem/instrumentation/models/persistence/common/detect.rb +7 -0
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/persistence}/common/extensions.rb +0 -0
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/persistence}/common/metadata.rb +6 -2
- data/lib/stratagem/instrumentation/models/persistence/common/tracing.rb +4 -0
- data/lib/stratagem/instrumentation/models/support_libraries.rb +7 -0
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/support_libraries}/friendly_id/detect.rb +2 -2
- data/lib/stratagem/{framework_extensions/models/adapters → instrumentation/models/support_libraries}/friendly_id/metadata.rb +2 -2
- data/lib/stratagem/instrumentation/models/support_libraries/state_machine/detect.rb +11 -0
- data/lib/stratagem/instrumentation/models/support_libraries/state_machine/metadata.rb +17 -0
- data/lib/stratagem/{framework_extensions → instrumentation}/models/tracing.rb +2 -2
- data/lib/stratagem/{framework_extensions → instrumentation}/rails.rb +0 -0
- data/lib/stratagem/{framework_extensions → instrumentation}/rails2/action_controller.rb +0 -0
- data/lib/stratagem/{framework_extensions → instrumentation}/rails2/action_mailer.rb +0 -0
- data/lib/stratagem/{framework_extensions → instrumentation}/rails3/parameters.rb +0 -0
- data/lib/stratagem/{framework_extensions → instrumentation}/request_forgery_protection.rb +0 -0
- data/lib/stratagem/model/application.rb +30 -15
- data/lib/stratagem/model/components/controller.rb +2 -2
- data/lib/stratagem/model/components/reference.rb +2 -2
- data/lib/stratagem/model/components/view.rb +1 -1
- data/lib/stratagem/model_builder.rb +19 -8
- data/lib/stratagem/scanner.rb +1 -1
- data/lib/stratagem/site_crawler.rb +4 -2
- data/stratagem.gemspec +7 -7
- data/templates/install/tasks/stratagem.rake +9 -1
- metadata +86 -82
- data/lib/stratagem/framework_extensions.rb +0 -18
- data/lib/stratagem/framework_extensions/models.rb +0 -21
- data/lib/stratagem/framework_extensions/models/adapters/active_record/detect.rb +0 -7
- data/lib/stratagem/framework_extensions/models/adapters/authlogic/extensions.rb +0 -10
- data/lib/stratagem/framework_extensions/models/adapters/authlogic/tracing.rb +0 -4
- data/lib/stratagem/framework_extensions/models/adapters/common/detect.rb +0 -7
- data/lib/stratagem/framework_extensions/models/adapters/common/tracing.rb +0 -4
- data/lib/stratagem/framework_extensions/models/adapters/devise/detect.rb +0 -11
- data/lib/stratagem/framework_extensions/models/adapters/devise/extensions.rb +0 -0
- data/lib/stratagem/framework_extensions/models/adapters/devise/tracing.rb +0 -4
- data/lib/stratagem/framework_extensions/models/adapters/friendly_id/extensions.rb +0 -0
- data/lib/stratagem/framework_extensions/models/adapters/friendly_id/tracing.rb +0 -4
- data/lib/stratagem/framework_extensions/models/adapters/restful_authentication/tracing.rb +0 -4
- data/lib/stratagem/framework_extensions/models/annotations.rb +0 -78
data/lib/stratagem/client.rb
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
79
|
-
|
|
80
|
-
|
|
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, :
|
|
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
|
-
$
|
|
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
|
-
|
|
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
|
-
|
|
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 #{
|
|
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
|
-
|
|
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
|
-
|
|
141
|
-
|
|
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 = (
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
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.
|
|
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-
|
|
11
|
-
Regexp.compile("[^A-Za-z0-
|
|
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
|
+
|