miketracy-wwmd 0.2.12 → 0.2.14

Sign up to get free protection for your applications and to get access to all the features.
data/lib/wwmd.rb CHANGED
@@ -15,7 +15,7 @@ require 'rexml/document'
15
15
  module WWMD
16
16
 
17
17
  # :stopdoc:
18
- VERSION = "0.2.12"
18
+ VERSION = "0.2.14"
19
19
  PARSER = :nokogiri # :nokogiri || :hpricot
20
20
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
21
21
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
data/lib/wwmd/mixins.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'htmlentities'
2
+
1
3
  =begin rdoc
2
4
  mixins all around
3
5
  =end
@@ -50,6 +52,10 @@ class String
50
52
 
51
53
  @@he = HTMLEntities.new
52
54
 
55
+ def strip_up
56
+ self.gsub(/[^\x20-\x7e,\n]/,"").gsub(/^\n/,"")
57
+ end
58
+
53
59
  # ip address to int
54
60
  def ip_to_int
55
61
  self.split('.').inject(0) { |a,e| (a << 8) + e.to_i }
@@ -36,6 +36,7 @@ module WWMD
36
36
  ret += s
37
37
  end
38
38
  ret.gsub(/\n+/) { "\n" }
39
+ ret.gsub(/[^\x20-\x7e,\n]/,"").gsub(/^\n/,"")
39
40
  end
40
41
  end
41
42
  end
data/lib/wwmd/page.rb CHANGED
@@ -122,7 +122,7 @@ module WWMD
122
122
  rescue => e
123
123
  @last_error = e
124
124
  putw "WARN: #{e.class}" if e.class =~ /Curl::Err/
125
- self.logged_in = false
125
+ # self.logged_in = false
126
126
  end
127
127
  self.set_data
128
128
  return [self.code,self.page_status,self.body_data.size]
@@ -139,9 +139,7 @@ module WWMD
139
139
  #
140
140
  # returns: <tt>array [ code, body_data.size ]</tt>
141
141
  def submit(iform=nil,reg=WWMD::ESCAPE[:default])
142
- =begin
143
- this is just getting worse and worse
144
- =end
142
+ ##### this is just getting worse and worse
145
143
  if iform.class == "Symbol"
146
144
  reg = iform
147
145
  iform = nil
@@ -191,15 +189,8 @@ module WWMD
191
189
  #
192
190
  # returns: <tt>array [ code, body_data.size ]</tt>
193
191
  def get(url=nil,parse=true)
194
- if url && parse
192
+ if !(url =~ /[a-z]+:\/\//) && parse
195
193
  self.url = @urlparse.parse(self.opts[:base_url],url).to_s if url
196
- =begin
197
- base = url.clip
198
- args = url.clop
199
- base = @urlparse.parse(self.opts[:base_url],base).to_s
200
- self.url = base
201
- self.url += ("?" + args) if args
202
- =end
203
194
  elsif url
204
195
  self.url = url
205
196
  end
@@ -220,174 +211,14 @@ module WWMD
220
211
  self.submit(form)
221
212
  end
222
213
 
223
- def furl(url)
224
- self.url = @urlparse.parse(self.opts[:base_url],url).to_s
225
- end
226
-
227
- #:section: Reporting helper methods
228
- # These are methods that generate data for a parsed page
229
-
230
- # return text representation of page code
231
- #
232
- # override with specific statuses in helper depending on page text
233
- # etc to include statuses outside 200 = OK and other = ERR
234
- def page_status
235
- return "ERR" if self.response_code != 200
236
- return "OK"
237
- end
238
-
239
- alias_method :status, :page_status#:nodoc:
240
-
241
- # return value of @logged_in
242
- def logged_in?
243
- return @logged_in
244
- end
245
-
246
- # return a string of flags:
247
- # Ll links
248
- # Jj javascript includes
249
- # Ff forms
250
- # Cc comments
251
- def report_flags
252
- self.has_links? ? ret = "L" : ret = "l"
253
- self.has_jlinks? ? ret += "J" : ret += "j"
254
- self.has_form? ? ret += "F" : ret += "f"
255
- self.has_comments? ? ret += "C" : ret += "c"
256
- return ret
257
- end
258
-
259
- def has_links?; return !@links.empty?; end
260
- def has_jlinks?; return !@jlinks.empty?; end
261
- def has_form?; return !(@forms.size < 1); end
262
- def has_comments?; return !@comments.empty?; end
263
-
264
- # return page size in bytes
265
- def size
266
- return self.body_data.size
267
- end
268
-
269
- #:section: Other methods
270
-
271
- def all_tags#:nodoc:
272
- return self.search("*").map { |x| x.name }
273
- end
274
-
275
- # return MD5 for DOM fingerprint
276
- # take all tag names in page.to_s.md5
277
- def fingerprint
278
- self.all_tags.to_s.md5
279
- end
280
- alias_method :fp, :fingerprint #:nodoc:
281
-
282
- # set link using an integer link from self.report
283
- #--
284
- # NOTE: I always use page.get(page.l(1)) anyway.
285
- #++
286
- def set_link(index)
287
- self.url = @links[index]
288
- end
289
-
290
- # return link at index from @links array
291
- def get_link(index)
292
- @links[index]
293
- end
294
-
295
- alias_method :link, :get_link #:nodoc:
296
- alias_method :l, :get_link #:nodoc:
297
-
298
- # alias_method for body_data
299
- def raw
300
- self.body_data
301
- end
302
-
303
- # alias_method for last_effective_url
304
- def current_url
305
- self.last_effective_url
306
- end
307
-
308
- alias_method :current, :current_url
309
- alias_method :cur, :current_url
310
-
311
- # the last http response code
312
- def code
313
- self.response_code # .to_s
314
- end
315
-
316
- #:section: Parsing convenience methods
317
- # methods that help parse and find information on a page including
318
- # access to forms etc.
319
-
320
- # grep for regexp and remove leading whitespace
321
- def grep(reg)
322
- self.body_data.grep(reg).map { |i| i.gsub(/^\s+/, "") }
323
- end
324
-
325
- # return this page's form (at index id) as a FormArray
326
- def get_form(id=nil)
327
- id = 0 if not id
328
- return nil if forms.empty?
329
- @forms[id].to_form_array
330
- end
331
-
332
- # return the complete url to the form action on this page
333
- def action(id=nil)
334
- id = 0 if not id
335
- act = self.forms[id].action
336
- return self.last_effective_url if (act.nil? || act.empty?)
337
- return @urlparse.parse(self.last_effective_url,act).to_s
338
- end
339
-
340
- # return an array of Element objects for an xpath search
341
- def search(xpath)
342
- self.scrape.hdoc.search(xpath)
343
- end
344
-
345
- # return an array of inner_html for each <script> tag encountered
346
- def dump_scripts
347
- self.get_tags("//script").map { |s| s.inner_html if s.inner_html.strip != '' }
348
- end
349
-
350
- alias_method :scripts, :dump_scripts
351
-
352
- #:section: Input and Output Helpers
353
-
354
- # set self.opts[:base_url]
355
- def setbase(url=nil)
356
- return nil if not url
357
- self.opts[:base_url] = url
358
- self.base_url = url
359
- end
360
-
361
- # return md5sum for self.body_data
362
- def md5
363
- return self.body_data.md5
364
- end
365
-
366
- # write self.body_data to file
367
- def write(filename)
368
- File.write(filename,self.body_data)
369
- return "wrote to " + filename
370
- end
371
-
372
- # read self.body_data from file
373
- def read(filename)
374
- self.body_data = File.read(filename)
214
+ # send arbitrary verb (only works with patch to taf2-curb
215
+ def verb(verb)
216
+ return false if !@curl_object.respond_to?(:http_verb)
217
+ self.clear_data
218
+ self.headers["Referer"] = self.cur if self.use_referer
219
+ self.http_verb(verb)
375
220
  self.set_data
376
- end
377
-
378
- # does this response have SET-COOKIE headers?
379
- def set_cookies?
380
- ret = []
381
- self.header_data.each do |x|
382
- if x[0].upcase == "SET-COOKIE"
383
- ret << x[1]
384
- end
385
- end
386
- return ret
387
- end
388
-
389
- def time
390
- self.total_time
221
+ return [self.code, self.body_data.size]
391
222
  end
392
223
 
393
224
  #:section: Data callbacks and method_missing
File without changes
@@ -234,12 +234,12 @@ module WWMD
234
234
  alias_method :squeeze_keys!, :remove_null_keys!
235
235
 
236
236
  # dump a web page containing a csrf example of the current FormArray
237
- def to_csrf(action)
237
+ def to_csrf(action,unescval=false)
238
238
  ret = ""
239
239
  ret << "<html><body>\n"
240
240
  ret << "<form method='post' id='wwmdtest' name='wwmdtest' action='#{action}'>\n"
241
241
  self.each do |key,val|
242
- val = val.unescape.gsub(/'/) { %q[\'] }
242
+ val = val.unescape.gsub(/'/) { %q[\'] } if unescval
243
243
  ret << "<input name='#{key.to_s.unescape}' type='hidden' value='#{val}' />\n"
244
244
  # ret << "<input name='#{key.to_s.unescape}' type='hidden' value='#{val.to_s.unescape.gsub(/'/,"\\'")}' />\n"
245
245
  end
@@ -0,0 +1,87 @@
1
+ module WWMD
2
+ class Page
3
+ #:section: Parsing convenience methods
4
+ # methods that help parse and find information on a page including
5
+ # access to forms etc.
6
+
7
+ # grep for regexp and remove leading whitespace
8
+ def grep(reg)
9
+ self.body_data.grep(reg).map { |i| i.gsub(/^\s+/, "") }
10
+ end
11
+
12
+ # return this page's form (at index id) as a FormArray
13
+ def get_form(id=nil)
14
+ id = 0 if not id
15
+ return nil if forms.empty?
16
+ @forms[id].to_form_array
17
+ end
18
+
19
+ # return the complete url to the form action on this page
20
+ def action(id=nil)
21
+ id = 0 if not id
22
+ act = self.forms[id].action
23
+ return self.last_effective_url if (act.nil? || act.empty?)
24
+ return @urlparse.parse(self.last_effective_url,act).to_s
25
+ end
26
+
27
+ # return an array of Element objects for an xpath search
28
+ def search(xpath)
29
+ self.scrape.hdoc.search(xpath)
30
+ end
31
+
32
+ # return an array of inner_html for each <script> tag encountered
33
+ def dump_scripts
34
+ self.get_tags("//script").map { |s| s.inner_html if s.inner_html.strip != '' }
35
+ end
36
+
37
+ alias_method :scripts, :dump_scripts
38
+
39
+ # set link using an integer link from self.report
40
+ #--
41
+ # NOTE: I always use page.get(page.l(1)) anyway.
42
+ #++
43
+ def set_link(index)
44
+ self.url = @links[index]
45
+ end
46
+
47
+ # return link at index from @links array
48
+ def get_link(index)
49
+ @links[index]
50
+ end
51
+
52
+ alias_method :link, :get_link #:nodoc:
53
+ alias_method :l, :get_link #:nodoc:
54
+
55
+ def all_tags#:nodoc:
56
+ return self.search("*").map { |x| x.name }
57
+ end
58
+
59
+ def furl(url)
60
+ self.url = @urlparse.parse(self.opts[:base_url],url).to_s
61
+ end
62
+
63
+ # set self.opts[:base_url]
64
+ def setbase(url=nil)
65
+ return nil if not url
66
+ self.opts[:base_url] = url
67
+ self.base_url = url
68
+ end
69
+
70
+ # write self.body_data to file
71
+ def write(filename)
72
+ File.write(filename,self.body_data)
73
+ return "wrote to " + filename
74
+ end
75
+
76
+ # read self.body_data from file
77
+ def read(filename)
78
+ self.body_data = File.read(filename)
79
+ self.set_data
80
+ end
81
+
82
+ # alias_method for body_data
83
+ def raw
84
+ self.body_data
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,86 @@
1
+ module WWMD
2
+ class Page
3
+ #:section: Reporting helper methods
4
+ # These are methods that generate data for a parsed page
5
+
6
+ # return text representation of page code
7
+ #
8
+ # override with specific statuses in helper depending on page text
9
+ # etc to include statuses outside 200 = OK and other = ERR
10
+ def page_status
11
+ return "ERR" if self.response_code != 200
12
+ return "OK"
13
+ end
14
+
15
+ alias_method :status, :page_status#:nodoc:
16
+
17
+ # return value of @logged_in
18
+ def logged_in?
19
+ return @logged_in
20
+ end
21
+
22
+ # return a string of flags:
23
+ # Ll links
24
+ # Jj javascript includes
25
+ # Ff forms
26
+ # Cc comments
27
+ def report_flags
28
+ self.has_links? ? ret = "L" : ret = "l"
29
+ self.has_jlinks? ? ret += "J" : ret += "j"
30
+ self.has_form? ? ret += "F" : ret += "f"
31
+ self.has_comments? ? ret += "C" : ret += "c"
32
+ return ret
33
+ end
34
+
35
+ def has_links?; return !@links.empty?; end
36
+ def has_jlinks?; return !@jlinks.empty?; end
37
+ def has_form?; return !(@forms.size < 1); end
38
+ def has_comments?; return !@comments.empty?; end
39
+
40
+ # return page size in bytes
41
+ def size
42
+ return self.body_data.size
43
+ end
44
+
45
+ # return md5sum for self.body_data
46
+ def md5
47
+ return self.body_data.md5
48
+ end
49
+
50
+ # does this response have SET-COOKIE headers?
51
+ def set_cookies?
52
+ ret = []
53
+ self.header_data.each do |x|
54
+ if x[0].upcase == "SET-COOKIE"
55
+ ret << x[1]
56
+ end
57
+ end
58
+ return ret
59
+ end
60
+
61
+ def time
62
+ self.total_time
63
+ end
64
+
65
+ # return MD5 for DOM fingerprint
66
+ # take all tag names in page.to_s.md5
67
+ def fingerprint
68
+ self.all_tags.to_s.md5
69
+ end
70
+ alias_method :fp, :fingerprint #:nodoc:
71
+
72
+ # alias_method for last_effective_url
73
+ def current_url
74
+ self.last_effective_url
75
+ end
76
+
77
+ alias_method :current, :current_url
78
+ alias_method :cur, :current_url
79
+
80
+ # the last http response code
81
+ def code
82
+ self.response_code # .to_s
83
+ end
84
+
85
+ end
86
+ end
@@ -1,10 +1,14 @@
1
+ require 'htmlentities'
2
+ require 'wwmd/mixins'
3
+ require 'wwmd/mixins_extends'
1
4
  module WWMD
5
+
2
6
  # yay for experiments in re-inventing the wheel
3
7
  class URLParse
4
8
  HANDLERS = [:https,:http,:ftp,:file]
5
9
  attr_reader :proto,:location,:path,:script,:rpath,:params,:base_url,:fqpath
6
10
 
7
- def initialize()
11
+ def initialize(*args)
8
12
  # nothing to see here, move along
9
13
  end
10
14
 
@@ -26,7 +30,7 @@ module WWMD
26
30
  # does this work for http://location/? probably not
27
31
  @base += "/" if (!@base.has_ext? || @base.split("/").size == 3)
28
32
  @rpath = make_me_path.join("/")
29
- @params = @rpath.clop
33
+ @rpath += "?#{@params}" if @params
30
34
  @path = "/" + @rpath
31
35
  if @rpath.has_ext?
32
36
  @path = "/" + @rpath.dirname
@@ -41,12 +45,18 @@ module WWMD
41
45
  def make_me_path
42
46
  @proto,tpath = @base.split(":",2)
43
47
  tpath ||= ""
48
+ @params = tpath.clop
49
+ tpath = tpath.clip
44
50
  if @actual.empty?
45
51
  a_path = tpath.split("/").reject { |x| x.empty? }
46
52
  else
47
53
  a_path = tpath.dirname.split("/").reject { |x| x.empty? }
48
54
  end
49
55
  @location = a_path.shift
56
+ if @actual.clop
57
+ @params = @actual.clop
58
+ @actual = @actual.clip
59
+ end
50
60
  a_path = [] if (@actual =~ (/^\//))
51
61
  b_path = @actual.split("/").reject { |x| x.empty? }
52
62
  a_path.pop if (a_path[-1] =~ /^\?/).kind_of?(Fixnum) && !b_path.empty?
@@ -54,7 +64,7 @@ module WWMD
54
64
  d_path = []
55
65
  c_path.each do |x|
56
66
  (d_path.pop;next) if x == ".."
57
- next if x == "."
67
+ next if (x == "." || x =~ /^\?/)
58
68
  d_path << x
59
69
  end
60
70
  return d_path
@@ -5,8 +5,8 @@ module WWMD
5
5
  end
6
6
  require 'rubygems'
7
7
  require 'nokogiri'
8
- require 'htmlentities'
9
8
  require 'rexml/document'
9
+ require 'htmlentities'
10
10
  require 'wwmd/mixins'
11
11
  require 'wwmd/mixins_extends'
12
12
  require 'wwmd/mixins_external'
@@ -59,6 +59,7 @@ module WWMD
59
59
  @indexed_strings = []
60
60
  @mac = nil
61
61
  @debug = false
62
+ self.deserialize if b64
62
63
  end
63
64
 
64
65
  # mac_enabled?
@@ -1,5 +1,6 @@
1
1
  module WWMD
2
2
  class VSClassHelpers < ViewStateUtils
3
+
3
4
  def to_sym
4
5
  self.class.to_s.split(":").last.gsub(/[A-Z]+/,'\1_\0').downcase[1..-1].gsub(/\Avs/,"").to_sym
5
6
  end
@@ -13,21 +13,21 @@ module WWMD
13
13
 
14
14
  def type(t=nil)
15
15
  typeref,typeval = self.deserialize_type
16
- dlog(t,"typeref = #{typeref} typeval = #{typeval}")
16
+ dlog(t,"typeref = 0x#{typeref.to_s(16)} typeval = #{typeval}")
17
17
  VSType.new(typeref,typeval)
18
18
  end
19
19
 
20
20
  def string_formatted(t=nil)
21
21
  typeref,typeval = self.deserialize_type
22
22
  str = self.read_string
23
- dlog(t,"typeref = #{typeref} typeval = #{typeval} string = #{str}")
23
+ dlog(t,"typeref = 0x#{typeref.to_s(16)} typeval = #{typeval} string = #{str}")
24
24
  VSStringFormatted.new(typeref,typeval,str)
25
25
  end
26
26
 
27
27
  def int_enum(t=nil)
28
28
  typeref,typeval = self.deserialize_type
29
29
  index = self.read_7bit_encoded_int
30
- dlog(t,"typeref = #{typeref} typeval = #{typeval} index = #{index}")
30
+ dlog(t,"typeref = 0x#{typeref.to_s(16)} typeval = #{typeval} index = #{index}")
31
31
  VSIntEnum.new(typeref,typeval,index)
32
32
  end
33
33
 
@@ -44,7 +44,7 @@ module WWMD
44
44
  typeref,typeval = self.deserialize_type
45
45
  size = read_7bit_encoded_int
46
46
  elems = read_7bit_encoded_int
47
- dlog(t,"typeref = #{typeref} typeval = #{typeval} size = #{size} elems = #{elems}")
47
+ dlog(t,"typeref = 0x#{typeref.to_s(16)} typeval = #{typeval} size = #{size} elems = #{elems}")
48
48
  me = VSSparseArray.new(typeref,typeval,size,elems)
49
49
  if elems > size
50
50
  raise "Invalid sparse_array"
@@ -79,7 +79,7 @@ module WWMD
79
79
  def array(t=nil)
80
80
  typeref,typeval = self.deserialize_type
81
81
  len = read_7bit_encoded_int
82
- dlog(t,"typeref = #{typeref} typeval = #{typeval} len = #{len}")
82
+ dlog(t,"typeref = 0x#{typeref.to_s(16)} typeval = #{typeval} len = #{len}")
83
83
  me = VSArray.new(typeref,typeval)
84
84
  (1..len).each do |i|
85
85
  me.add(self.deserialize_value)
@@ -203,7 +203,11 @@ module WWMD
203
203
  def deserialize_value
204
204
  @last_offset = self.offset
205
205
  token = self.read_byte # self.read_raw_byte
206
- raise "Invalid Type #{token.hexify} at #{last_offset}" if not (tsym = VIEWSTATE_TYPES[token])
206
+ if not (tsym = VIEWSTATE_TYPES[token])
207
+ puts "TOKEN: [0x#{token.to_s(16)}] at #{last_offset}"
208
+ puts @bufarr.slice(0..31).join("").hexdump
209
+ raise "Invalid Type [0x#{token.to_s(16)}] at #{last_offset}" if not (tsym = VIEWSTATE_TYPES[token])
210
+ end
207
211
  nobj = self.send(tsym,token)
208
212
  raise "Invalid Class Returned #{nobj.class}" if not VIEWSTATE_TYPES.include?(nobj.opcode)
209
213
  return nobj
@@ -49,3 +49,7 @@ module WWMD
49
49
  } unless defined?(VIEWSTATE_TYPES)
50
50
 
51
51
  end
52
+
53
+ if __FILE__ == $0
54
+ puts "size: #{WWMD::VIEWSTATE_TYPES.size}"
55
+ end
File without changes
File without changes
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- require 'wwmd'
2
+ require 'wwmd/urlparse'
3
3
  include WWMD
4
4
  require 'spec'
5
5
 
@@ -34,6 +34,11 @@ describe URLParse do
34
34
  @up.script.should == "test.php"
35
35
  end
36
36
 
37
+ it "should parse GET params correctly" do
38
+ @up.parse(@base,"http://www.location.com/test.php?foo=bar&baz=eep").to_s.should \
39
+ == "http://www.location.com/test.php?foo=bar&baz=eep"
40
+ end
41
+
37
42
  it "should return the path if the path is fully qualified" do
38
43
  @up.parse(@base,"http://www.location.com/").to_s.should == "http://www.location.com/"
39
44
  @up.parse(@base,"http://www.location.com").to_s.should == "http://www.location.com/"
@@ -86,4 +91,11 @@ describe URLParse do
86
91
  @up.parse("http://www.example.com:8888/foobar/barBaz.do?logFile=../../../../../../../../../../../../etc/passwd&foo=foobar.log&bazeep=false").to_s.should \
87
92
  == "http://www.example.com:8888/foobar/barBaz.do?logFile=../../../../../../../../../../../../etc/passwd&foo=foobar.log&bazeep=false"
88
93
  end
94
+
95
+ it "should not remove directory traversal params 2" do
96
+ @up.parse("http://www.example.com:8888", "/foobar/barBaz.do?logFile=../../../../../../../../../../../../etc/passwd&foo=foobar.log&bazeep=false").to_s.should \
97
+ == "http://www.example.com:8888/foobar/barBaz.do?logFile=../../../../../../../../../../../../etc/passwd&foo=foobar.log&bazeep=false"
98
+ end
99
+
89
100
  end
101
+
data/wwmd.gemspec CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: miketracy-wwmd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.12
4
+ version: 0.2.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael L. Tracy
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-21 00:00:00 -07:00
12
+ date: 2009-06-02 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.3.4
33
+ version: 0.2.8.0
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: nokogiri
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: 2.5.0
53
+ version: 2.5.1
54
54
  version:
55
55
  description: WWMD was originally intended to provide a console helper tool for conducting web application security assessments (which is something I find myself doing alot of). I've spent alot of time and had alot of success writing application specific fuzzers + scrapers to test with. WWMD provides a base of useful code to help you work with web sites both in IRB and by writing scripts that can be as generic or as application specific as you choose. There's alot of helpful stuff crammed in here and its usage has evolved alot. It's not intended to replace, remove or be better than any of the tools you currently use. In fact, WWMD works best *with* the tools you currently use to get stuff done. You get convenience methods for getting, scraping, spidering, decoding, decrypting and munging user inputs, pages and web applications. It doesn't try to be smart. That's up to you. What's here is the basic framework for getting started. There's a raft of cookbook scripts and examples that are coming soon so make sure you check the wiki regularly.
56
56
  email: mtracy@matasano.com
@@ -70,8 +70,6 @@ files:
70
70
  - examples/wwmd_example.rb
71
71
  - lib/wwmd.rb
72
72
  - lib/wwmd/encoding.rb
73
- - lib/wwmd/form.rb
74
- - lib/wwmd/form_array.rb
75
73
  - lib/wwmd/guid.rb
76
74
  - lib/wwmd/hpricot_html2text.rb
77
75
  - lib/wwmd/mixins.rb
@@ -80,15 +78,17 @@ files:
80
78
  - lib/wwmd/nokogiri_html2text.rb
81
79
  - lib/wwmd/page.rb
82
80
  - lib/wwmd/page/auth.rb
83
- - lib/wwmd/page/config.rb
84
81
  - lib/wwmd/page/constants.rb
82
+ - lib/wwmd/page/form.rb
83
+ - lib/wwmd/page/form_array.rb
85
84
  - lib/wwmd/page/headers.rb
86
85
  - lib/wwmd/page/inputs.rb
87
86
  - lib/wwmd/page/irb_helpers.rb
87
+ - lib/wwmd/page/parsing_convenience.rb
88
+ - lib/wwmd/page/reporting_helpers.rb
88
89
  - lib/wwmd/page/scrape.rb
89
90
  - lib/wwmd/page/spider.rb
90
- - lib/wwmd/page/urlparse.rb
91
- - lib/wwmd/page/utils.rb
91
+ - lib/wwmd/urlparse.rb
92
92
  - lib/wwmd/viewstate.rb
93
93
  - lib/wwmd/viewstate/viewstate_class_helpers.rb
94
94
  - lib/wwmd/viewstate/viewstate_deserializer_methods.rb
@@ -115,6 +115,8 @@ files:
115
115
  - lib/wwmd/viewstate/vs_type.rb
116
116
  - lib/wwmd/viewstate/vs_unit.rb
117
117
  - lib/wwmd/viewstate/vs_value.rb
118
+ - lib/wwmd/wwmd_config.rb
119
+ - lib/wwmd/wwmd_utils.rb
118
120
  - spec/README
119
121
  - spec/form_array.spec
120
122
  - spec/spider_csrf_test.spec