wwmd 0.2.20.3

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.
Files changed (80) hide show
  1. data/History.txt +38 -0
  2. data/README.rdoc +87 -0
  3. data/Rakefile +33 -0
  4. data/examples/config_example.yaml +24 -0
  5. data/examples/wwmd_example.rb +73 -0
  6. data/lib/wwmd.rb +84 -0
  7. data/lib/wwmd/class_extensions.rb +4 -0
  8. data/lib/wwmd/class_extensions/extensions_base.rb +251 -0
  9. data/lib/wwmd/class_extensions/extensions_encoding.rb +79 -0
  10. data/lib/wwmd/class_extensions/extensions_external.rb +18 -0
  11. data/lib/wwmd/class_extensions/extensions_nilclass.rb +11 -0
  12. data/lib/wwmd/class_extensions/extensions_rbkb.rb +193 -0
  13. data/lib/wwmd/class_extensions/mixins_string_encoding.rb +40 -0
  14. data/lib/wwmd/guid.rb +155 -0
  15. data/lib/wwmd/page.rb +3 -0
  16. data/lib/wwmd/page/_fa.old +302 -0
  17. data/lib/wwmd/page/auth.rb +17 -0
  18. data/lib/wwmd/page/constants.rb +63 -0
  19. data/lib/wwmd/page/form.rb +99 -0
  20. data/lib/wwmd/page/form_array.rb +304 -0
  21. data/lib/wwmd/page/headers.rb +118 -0
  22. data/lib/wwmd/page/helpers.rb +41 -0
  23. data/lib/wwmd/page/html2text_hpricot.rb +76 -0
  24. data/lib/wwmd/page/html2text_nokogiri.rb +42 -0
  25. data/lib/wwmd/page/inputs.rb +47 -0
  26. data/lib/wwmd/page/irb_helpers.rb +114 -0
  27. data/lib/wwmd/page/page.rb +257 -0
  28. data/lib/wwmd/page/parsing_convenience.rb +98 -0
  29. data/lib/wwmd/page/reporting_helpers.rb +89 -0
  30. data/lib/wwmd/page/scrape.rb +196 -0
  31. data/lib/wwmd/page/spider.rb +127 -0
  32. data/lib/wwmd/urlparse.rb +125 -0
  33. data/lib/wwmd/viewstate.rb +17 -0
  34. data/lib/wwmd/viewstate/viewstate.rb +101 -0
  35. data/lib/wwmd/viewstate/viewstate_deserializer_methods.rb +217 -0
  36. data/lib/wwmd/viewstate/viewstate_from_xml.rb +129 -0
  37. data/lib/wwmd/viewstate/viewstate_types.rb +51 -0
  38. data/lib/wwmd/viewstate/viewstate_utils.rb +164 -0
  39. data/lib/wwmd/viewstate/viewstate_yaml.rb +25 -0
  40. data/lib/wwmd/viewstate/vs_stubs.rb +22 -0
  41. data/lib/wwmd/viewstate/vs_stubs/vs_array.rb +38 -0
  42. data/lib/wwmd/viewstate/vs_stubs/vs_binary_serialized.rb +30 -0
  43. data/lib/wwmd/viewstate/vs_stubs/vs_hashtable.rb +42 -0
  44. data/lib/wwmd/viewstate/vs_stubs/vs_hybrid_dict.rb +42 -0
  45. data/lib/wwmd/viewstate/vs_stubs/vs_indexed_string.rb +6 -0
  46. data/lib/wwmd/viewstate/vs_stubs/vs_indexed_string_ref.rb +24 -0
  47. data/lib/wwmd/viewstate/vs_stubs/vs_int_enum.rb +27 -0
  48. data/lib/wwmd/viewstate/vs_stubs/vs_list.rb +34 -0
  49. data/lib/wwmd/viewstate/vs_stubs/vs_pair.rb +29 -0
  50. data/lib/wwmd/viewstate/vs_stubs/vs_read_types.rb +11 -0
  51. data/lib/wwmd/viewstate/vs_stubs/vs_read_value.rb +35 -0
  52. data/lib/wwmd/viewstate/vs_stubs/vs_sparse_array.rb +58 -0
  53. data/lib/wwmd/viewstate/vs_stubs/vs_string.rb +33 -0
  54. data/lib/wwmd/viewstate/vs_stubs/vs_string_array.rb +39 -0
  55. data/lib/wwmd/viewstate/vs_stubs/vs_string_formatted.rb +32 -0
  56. data/lib/wwmd/viewstate/vs_stubs/vs_stub_helpers.rb +37 -0
  57. data/lib/wwmd/viewstate/vs_stubs/vs_triplet.rb +31 -0
  58. data/lib/wwmd/viewstate/vs_stubs/vs_type.rb +23 -0
  59. data/lib/wwmd/viewstate/vs_stubs/vs_unit.rb +30 -0
  60. data/lib/wwmd/viewstate/vs_stubs/vs_value.rb +35 -0
  61. data/lib/wwmd/wwmd_config.rb +52 -0
  62. data/lib/wwmd/wwmd_puts.rb +9 -0
  63. data/lib/wwmd/wwmd_utils.rb +28 -0
  64. data/spec/README +3 -0
  65. data/spec/form_array.spec +49 -0
  66. data/spec/spider_csrf_test.spec +28 -0
  67. data/spec/urlparse_test.spec +101 -0
  68. data/tasks/ann.rake +80 -0
  69. data/tasks/bones.rake +20 -0
  70. data/tasks/gem.rake +201 -0
  71. data/tasks/git.rake +40 -0
  72. data/tasks/notes.rake +27 -0
  73. data/tasks/post_load.rake +34 -0
  74. data/tasks/rdoc.rake +51 -0
  75. data/tasks/rubyforge.rake +55 -0
  76. data/tasks/setup.rb +292 -0
  77. data/tasks/spec.rake +54 -0
  78. data/tasks/test.rake +40 -0
  79. data/tasks/zentest.rake +36 -0
  80. metadata +222 -0
@@ -0,0 +1,3 @@
1
+ require 'wwmd/wwmd_utils'
2
+ require 'wwmd/wwmd_config'
3
+ require 'wwmd/page/page'
@@ -0,0 +1,302 @@
1
+ =begin rdoc
2
+ This is a weird kind of data structure for no other reason than
3
+ I wanted to keep the form inputs in order when they come in.
4
+
5
+ Accessing this either as a hash or an array (but => won't work)
6
+
7
+ Some of the methods in here are kept for backward compat before the refactor
8
+ and now everything in this array should be accessed with []= and []
9
+
10
+ Set :action and take a block. Page#submit_form should take this and do the
11
+ right thing.
12
+ =end
13
+
14
+ module WWMD
15
+ class FormArray < Array
16
+ attr_accessor :action
17
+ attr_accessor :type
18
+ attr_accessor :delimiter
19
+ attr_accessor :equals
20
+
21
+ def initialize(fields=nil,action=nil,&block)
22
+ set_fields(fields)
23
+ @delimiter = "&"
24
+ @equals = "="
25
+ @action = action
26
+ instance_eval(&block) if block_given?
27
+ end
28
+
29
+ def set_fields(fields=nil)
30
+ return nil if fields.nil?
31
+ # this first one is an array of field objects
32
+ if fields.class == Array
33
+ fields.each do |f|
34
+ name = f['name']
35
+ if self.name_exists(name)
36
+ if f['type'] == "hidden"
37
+ self.set name,f.get_value
38
+ elsif f['type'] == "checkbox" and f.to_html.grep(/checked/) != ''
39
+ self[name] = f.get_value
40
+ end
41
+ else
42
+ self << [ f['name'],f.get_value ]
43
+ end
44
+ end
45
+ elsif fields.class == Hash
46
+ fields.each_pair { |k,v| self[k] = v }
47
+ elsif fields.class == String
48
+ fields.split(@delimiter).each do |f|
49
+ k,v = f.split(@equals,2)
50
+ self[k] = v
51
+ end
52
+ end
53
+ end
54
+
55
+ # "deep enough" copy of this object to make it a real copy
56
+ # instead of references to the arrays that already exist
57
+ def clone
58
+ ret = self.class.new
59
+ self.each { |r| ret << r.clone }
60
+ ret.action = self.action
61
+ return ret
62
+ end
63
+
64
+ def clear
65
+ self.delete_if { |x| true }
66
+ end
67
+
68
+ # check if the passed name exists in the form
69
+ def include?(key)
70
+ self.map { |x| x.first }.flatten.include?(key)
71
+ end
72
+
73
+ alias_method :name_exists, :include?#:nodoc:
74
+ alias_method :name_exists?, :include?#:nodoc:
75
+ alias_method :has_key?, :include?#:nodoc:
76
+
77
+ # add key/value pairs to form
78
+ def add(key,value)
79
+ self << [key,value]
80
+ end
81
+
82
+ # key = Fixnum set value at index key
83
+ # key = String find key named string and set value
84
+ def set_value!(key,value)
85
+ if key.class == Fixnum
86
+ self[key][1] = value
87
+ return [self[key][0], value]
88
+ end
89
+ self.each_index do |i|
90
+ if self[i][0] == key
91
+ self[i] = [key,value]
92
+ end
93
+ end
94
+ return [key,value]
95
+ end
96
+
97
+ # get a value using its index
98
+ # override Array#[]
99
+ alias_method :old_get, :[]#:nodoc:
100
+ def [](*args)
101
+ if args.first.class == Fixnum
102
+ self.old_get(args.first)
103
+ else
104
+ self.get_value(args.first)
105
+ end
106
+ end
107
+
108
+ alias_method :old_set, :[]=#:nodoc:
109
+ # set a key using its index, array key or add using a new key i.e.:
110
+ # if setting:
111
+ # form = [['key','value'],['foo','bar']]
112
+ # form[0] = ["replacekey","newalue"]
113
+ # form["replacekey"] = "newervalue"
114
+ # if adding:
115
+ # form["newkey"] = "value"
116
+ #
117
+ def []=(*args)
118
+ key,value = args
119
+ if args.first.kind_of?(Fixnum)
120
+ return self.old_set(*args)
121
+ elsif self.has_key?(key)
122
+ return self.set_value(key,value)
123
+ else
124
+ return self.add(key,value)
125
+ end
126
+ end
127
+
128
+ alias_method :set_value, :set_value!
129
+ alias_method :set, :set_value!
130
+
131
+ def get_value(key)
132
+ if key.class == Fixnum
133
+ return self[key][1]
134
+ end
135
+ self.each_index do |i|
136
+ if self[i][0] == key
137
+ return self[i][1]
138
+ end
139
+ end
140
+ return nil
141
+ end
142
+
143
+ alias_method :get, :get_value
144
+
145
+ def keys
146
+ self.map { |k,v| k }
147
+ end
148
+
149
+ def setall!(value)
150
+ self.each_index { |i| self.set_value!(i,value) }
151
+ end
152
+
153
+ alias_method :setall, :setall!#:nodoc:
154
+ alias_method :set_all!, :setall!#:nodoc:
155
+ alias_method :set_all, :setall!#:nodoc:
156
+
157
+ # delete all key = value pairs from self where key = key
158
+ def delete_key(key)
159
+ self.reject! { |x,y| x == key }
160
+ end
161
+
162
+ alias_method :delete_keys!, :delete_key #:nodoc:
163
+ alias_method :delete_key!, :delete_key #:nodoc:
164
+
165
+ # escape form keys in place
166
+ def escape_keys!(reg=WWMD::ESCAPE[:url])
167
+ return nil if reg == :none
168
+ self.map! { |x,y| [x.escape(reg),y] }
169
+ end
170
+
171
+ # unescape form keys in place
172
+ def unescape_keys!(reg=WWMD::ESCAPE[:url])
173
+ return nil if reg == :none
174
+ self.map! { |x,y| [x.unescape,y] }
175
+ end
176
+
177
+ # escape form values in place
178
+ def escape_all!(reg=WWMD::ESCAPE[:url])
179
+ return nil if reg == :none
180
+ self.map! { |x,y| [x,y.escape(reg)] }
181
+ end
182
+
183
+ alias_method :escape_all, :escape_all!#:nodoc:
184
+
185
+ # unescape all form values in place
186
+ def unescape_all!
187
+ self.map! { |x,y| [x,y.unescape] }
188
+ end
189
+
190
+ alias_method :unescape_all, :unescape_all!#:nodoc:
191
+
192
+ # remove form elements with null values
193
+ def remove_nulls!
194
+ self.delete_if { |x| x[1].to_s.empty? || x[1].nil? }
195
+ end
196
+
197
+ alias_method :squeeze!, :remove_nulls!
198
+
199
+ # remove form elements with null keys (for housekeeping returns)
200
+ def remove_null_keys!
201
+ self.delete_if { |x,y| x.to_s.empty? || x.nil? }
202
+ end
203
+
204
+ alias_method :squeeze_keys!, :remove_null_keys!
205
+
206
+ ## viewstate
207
+
208
+ # clear viewstate variables
209
+ def clear_viewstate
210
+ self.each { |k,v|
211
+ self[k] = "" if k =~ /^__/
212
+ }
213
+ end
214
+
215
+ # remove viewstate variables
216
+ def rm_viewstate
217
+ # my least favorite ruby idiom
218
+ self.replace(self.map { |k,v| [k,v] if not k =~ /^__/ }.reject { |x| x.nil? })
219
+ end
220
+
221
+ alias_method :extend!, :add #:nodoc (this is here for backward compat)
222
+
223
+ # add viewstate stuff
224
+ def add_viewstate#:nodoc:
225
+ self.insert(0,[ "__VIEWSTATE","" ])
226
+ self.insert(0,[ "__EVENTARGUMENT","" ])
227
+ self.insert(0,[ "__EVENTTARGET","" ])
228
+ self.insert(0,[ "__EVENTVALIDATION","" ])
229
+ return nil
230
+ end
231
+
232
+ ## conversions
233
+
234
+ # convert form into a post parameters string
235
+ def to_post
236
+ ret = []
237
+ self.each do |i|
238
+ ret << i.join(@equals)
239
+ end
240
+ ret.join(@delimiter)
241
+ end
242
+
243
+ # convert form into a get parameters string
244
+ #
245
+ # pass me a base to get a full url to pass to Page.get
246
+ def to_get(base="")
247
+ return base if self.empty?
248
+ ret = []
249
+ self.each do |i|
250
+ ret << i.join(@equals)
251
+ end
252
+ ret = ret.join(@delimiter)
253
+ return base.to_s.clip + "?" + ret.to_s
254
+ end
255
+
256
+ ## parsing convenience
257
+
258
+ # dump a web page containing a csrf example of the current FormArray
259
+ def to_csrf(action=nil,unescval=false)
260
+ action = self.action if not action
261
+ ret = ""
262
+ ret << "<html><body>\n"
263
+ ret << "<form method='post' id='wwmdtest' name='wwmdtest' action='#{action}'>\n"
264
+ self.each do |key,val|
265
+ val = val.unescape.gsub(/'/) { %q[\'] } if unescval
266
+ ret << "<input name='#{key.to_s.unescape}' type='hidden' value='#{val.to_s.unescape}' />\n"
267
+ end
268
+ ret << "</form>\n"
269
+ ret << "<script>document.wwmdtest.submit()</script>\n"
270
+ ret << "</body></html>\n"
271
+ return ret
272
+ end
273
+
274
+ # add markers for burp intruder to form
275
+ def burpify(all=true) #:nodoc:
276
+ ret = self.clone
277
+ ret.each_index do |i|
278
+ next if ret[i][0] =~ /^__/
279
+ # ret.set_value!(i,"#{ret.get_value(i)}" + "\302\247" + "\302\247")
280
+ if all
281
+ ret.set_value!(i,"\244" + "#{ret.get_value(i)}" + "\244")
282
+ else
283
+ ret.set_value!(i,"#{ret.get_value(i)}" + "\244" + "\244")
284
+ end
285
+ end
286
+ ret.to_post.pbcopy
287
+ return ret
288
+ end
289
+
290
+ # return md5 hash of sorted list of keys
291
+ def fingerprint
292
+ return (self.action.to_s + self.map { |k,v| k }.sort.to_s).md5
293
+ end
294
+ alias_method :fp, :fingerprint #:nodoc:
295
+
296
+ def from_array(arr)
297
+ self.clear
298
+ arr.each { |k,v| self[k] = v }
299
+ end
300
+
301
+ end
302
+ end
@@ -0,0 +1,17 @@
1
+ module WWMD
2
+ class Page
3
+
4
+ # does this request have an authenticate header?
5
+ def auth?
6
+ return false if self.code != 401
7
+ count = 0
8
+ self.header_data.each do |i|
9
+ if i[0] =~ /www-authenticate/i
10
+ count += 1
11
+ end
12
+ end
13
+ return (count > 0)
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,63 @@
1
+ module WWMD
2
+ XSSFISH = "<;'\"}()[]>{"
3
+
4
+ DEFAULTS = {
5
+ :base_url => "",
6
+ :use_auth => true,
7
+ :enable_cookies => true,
8
+ :cookiejar => "./__cookiejar",
9
+ :follow_location => true,
10
+ :max_redirects => 20,
11
+ :use_proxy => false,
12
+ :debug => false,
13
+ :scrape_warn => true,
14
+ :parse => true,
15
+ :timeout => 20,
16
+ }
17
+
18
+ ESCAPE = {
19
+ :url => /[^a-zA-Z0-9\-_%]/,
20
+ :nalnum => /[^a-zA-Z0-9]/,
21
+ :xss => /[^a-zA-Z0-9=?()']/,
22
+ :ltgt => /[<>]/,
23
+ :all => /.*/,
24
+ # :b64 => /[=+\/]/,
25
+ :b64 => /[^a-zA-Z0-9]/,
26
+ :none => :none,
27
+ :default => :default,
28
+ }
29
+
30
+ UA = {
31
+ :mozilla => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.16) Gecko/20080702 Firefox/2.0.0.16",
32
+ :moz3 => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.0.1) Gecko/2008070206 Firefox/3.0.1",
33
+ :ie6 => "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
34
+ :ie7 => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
35
+ :ie8 => "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)",
36
+ :opera => "Opera/9.20 (Windows NT 6.0; U; en)",
37
+ :safari => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_4_11; en) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.22",
38
+ :safari4 => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17",
39
+ :wwmd => "Mozilla/5.0 (compatible; WWMD #{WWMD::VERSION}; o_hai)"
40
+ }
41
+
42
+ DEFAULT_HEADERS = {
43
+ "User-Agent" => UA[:wwmd],
44
+ "Accept" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
45
+ "Accept-Language" => "en-US,en;q=0.8,en-au;q=0.6,en-us;q=0.4,en;q=0.2",
46
+ "Accept-Encoding" => "gzip,deflate",
47
+ "Accept-Charset" => "SO-8859-1,utf-8;q=0.7,*;q=0.7",
48
+ "Keep-Alive" => "300",
49
+ "Connection" => "keep-alive",
50
+ }
51
+
52
+ HEADERS = {
53
+ :default => nil,
54
+ :utf7 => {
55
+ "Content-Type" => "application/x-www-form-urlencoded;charset=UTF-7",
56
+ "Content-Transfer-Encoding" => "7bit",
57
+ },
58
+ :ajax => {
59
+ "X-Requested-With" => "XMLHttpRequest",
60
+ "X-Prototype-Version" => "1.5.0",
61
+ },
62
+ }
63
+ end
@@ -0,0 +1,99 @@
1
+ =begin rdoc
2
+ =end
3
+ module WWMD
4
+ # == original author of hpricot_form
5
+ #
6
+ # Chew Choon Keat <choonkeat at gmail>
7
+ # http://blog.yanime.org/
8
+ # 19 July 2006
9
+ #
10
+ # updated by mtracy at matasano.com for use with Nokogiri and WWMD
11
+ #
12
+ class Form
13
+ attr_accessor :hdoc
14
+ attr_accessor :fields
15
+ attr_accessor :formtag
16
+
17
+ def initialize(doc)
18
+ @hdoc = doc
19
+ @formtag = @hdoc.search("//form")
20
+ end
21
+
22
+ def method_missing(*args)
23
+ hdoc.send(*args)
24
+ end
25
+
26
+ alias_method :old_fields, :fields
27
+ def fields
28
+ if PARSER == :nokogiri
29
+ @fields ||= (hdoc.search(".//input[@name]",".//select[@name]",".//textarea")).map { |x| Field.new(x) }
30
+ else
31
+ @fields ||= (hdoc.search("//input[@name]") + hdoc.search("//select[@name]") + hdoc.search("//textarea")).map { |x| Field.new(x) }
32
+ end
33
+ end
34
+
35
+ def field_names
36
+ fields.map { |x| x.get_attribute("name") }
37
+ end
38
+
39
+ def action
40
+ return self.get_attribute("action")
41
+ end
42
+
43
+ def type
44
+ return self.get_attribute("method")
45
+ end
46
+
47
+ end
48
+
49
+ class Field < Form
50
+ def value
51
+ self._value.nil? ? self.get_attribute("value") : self._value
52
+ end
53
+
54
+ alias_method :get_value, :value #:nodoc:
55
+ alias_method :fvalue, :value #:nodoc:
56
+
57
+ def fname
58
+ self.get_attribute('name')
59
+ end
60
+
61
+ def ftype
62
+ self.get_attribute('type')
63
+ end
64
+
65
+ def _value
66
+ # selection (array)
67
+ if PARSER == :nokogiri
68
+ ret = hdoc.search(".//option[@selected]").collect { |x| x.get_attribute("value") }
69
+ else
70
+ ret = hdoc.search("//option[@selected]").collect { |x| x.get_attribute("value") }
71
+ end
72
+ case ret.size
73
+ when 0
74
+ if name == "textarea"
75
+ if PARSER == :nokogiri
76
+ hdoc.text
77
+ else
78
+ hdoc.innerHTML
79
+ end
80
+ else
81
+ hdoc.get_attribute("value") if (hdoc.get_attribute("checked") || !hdoc.get_attribute("type") =~ /radio|checkbox/)
82
+ end
83
+ when 1
84
+ ret.first
85
+ else
86
+ ret
87
+ end
88
+ end
89
+
90
+ def to_arr
91
+ return [self.name, self.ftype, self.fname, self.fvalue]
92
+ end
93
+
94
+ def to_text
95
+ return "tag=#{self.name} type=#{self.ftype} name=#{self.fname} value=#{self.fvalue}"
96
+ end
97
+
98
+ end
99
+ end