wwmd 0.2.20.3

Sign up to get free protection for your applications and to get access to all the features.
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