miketracy-wwmd 0.2.16 → 0.2.17
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +21 -0
- data/{README → README.rdoc} +27 -2
- data/lib/wwmd.rb +4 -4
- data/lib/wwmd/class_extensions.rb +2 -0
- data/lib/wwmd/{mixins.rb → class_extensions/extensions_base.rb} +25 -121
- data/lib/wwmd/class_extensions/extensions_encoding.rb +79 -0
- data/lib/wwmd/{mixins_external.rb → class_extensions/extensions_external.rb} +0 -0
- data/lib/wwmd/class_extensions/extensions_nilclass.rb +11 -0
- data/lib/wwmd/{mixins_extends.rb → class_extensions/extensions_rbkb.rb} +0 -0
- data/lib/wwmd/{encoding.rb → class_extensions/mixins_string_encoding.rb} +6 -6
- data/lib/wwmd/page.rb +3 -245
- data/lib/wwmd/page/auth.rb +0 -166
- data/lib/wwmd/page/constants.rb +7 -4
- data/lib/wwmd/page/form.rb +0 -15
- data/lib/wwmd/page/form_array.rb +96 -74
- data/lib/wwmd/page/headers.rb +25 -21
- data/lib/wwmd/page/helpers.rb +30 -0
- data/lib/wwmd/{hpricot_html2text.rb → page/html2text_hpricot.rb} +1 -1
- data/lib/wwmd/{nokogiri_html2text.rb → page/html2text_nokogiri.rb} +0 -0
- data/lib/wwmd/page/inputs.rb +1 -1
- data/lib/wwmd/page/irb_helpers.rb +37 -13
- data/lib/wwmd/page/page.rb +238 -0
- data/lib/wwmd/page/parsing_convenience.rb +8 -3
- data/lib/wwmd/page/scrape.rb +15 -19
- data/lib/wwmd/page/spider.rb +11 -11
- data/lib/wwmd/urlparse.rb +20 -5
- data/lib/wwmd/viewstate.rb +9 -112
- data/lib/wwmd/viewstate/viewstate.rb +101 -0
- data/lib/wwmd/viewstate/viewstate_deserializer_methods.rb +36 -36
- data/lib/wwmd/viewstate/viewstate_types.rb +0 -4
- data/lib/wwmd/viewstate/viewstate_utils.rb +6 -1
- data/lib/wwmd/viewstate/vs_stubs.rb +22 -0
- data/lib/wwmd/viewstate/{vs_array.rb → vs_stubs/vs_array.rb} +3 -1
- data/lib/wwmd/viewstate/{vs_binary_serialized.rb → vs_stubs/vs_binary_serialized.rb} +3 -1
- data/lib/wwmd/viewstate/{vs_hashtable.rb → vs_stubs/vs_hashtable.rb} +3 -1
- data/lib/wwmd/viewstate/{vs_hybrid_dict.rb → vs_stubs/vs_hybrid_dict.rb} +3 -1
- data/lib/wwmd/viewstate/{vs_indexed_string.rb → vs_stubs/vs_indexed_string.rb} +1 -1
- data/lib/wwmd/viewstate/{vs_indexed_string_ref.rb → vs_stubs/vs_indexed_string_ref.rb} +3 -1
- data/lib/wwmd/viewstate/{vs_int_enum.rb → vs_stubs/vs_int_enum.rb} +3 -1
- data/lib/wwmd/viewstate/{vs_list.rb → vs_stubs/vs_list.rb} +2 -1
- data/lib/wwmd/viewstate/{vs_pair.rb → vs_stubs/vs_pair.rb} +3 -1
- data/lib/wwmd/viewstate/vs_stubs/vs_read_types.rb +11 -0
- data/lib/wwmd/viewstate/{vs_read_value.rb → vs_stubs/vs_read_value.rb} +3 -1
- data/lib/wwmd/viewstate/{vs_sparse_array.rb → vs_stubs/vs_sparse_array.rb} +3 -1
- data/lib/wwmd/viewstate/{vs_string.rb → vs_stubs/vs_string.rb} +2 -1
- data/lib/wwmd/viewstate/{vs_string_array.rb → vs_stubs/vs_string_array.rb} +4 -2
- data/lib/wwmd/viewstate/{vs_string_formatted.rb → vs_stubs/vs_string_formatted.rb} +4 -2
- data/lib/wwmd/viewstate/{viewstate_class_helpers.rb → vs_stubs/vs_stub_helpers.rb} +2 -1
- data/lib/wwmd/viewstate/{vs_triplet.rb → vs_stubs/vs_triplet.rb} +3 -1
- data/lib/wwmd/viewstate/{vs_type.rb → vs_stubs/vs_type.rb} +3 -1
- data/lib/wwmd/viewstate/{vs_unit.rb → vs_stubs/vs_unit.rb} +3 -1
- data/lib/wwmd/viewstate/{vs_value.rb → vs_stubs/vs_value.rb} +4 -2
- data/lib/wwmd/wwmd_config.rb +44 -36
- data/lib/wwmd/wwmd_puts.rb +9 -0
- data/lib/wwmd/wwmd_utils.rb +22 -24
- data/tasks/setup.rb +1 -1
- metadata +41 -35
- data/README.txt +0 -62
- data/lib/wwmd/viewstate/vs_read_types.rb +0 -11
- data/wwmd.gemspec +0 -0
data/lib/wwmd/page/auth.rb
CHANGED
@@ -1,30 +1,6 @@
|
|
1
|
-
=begin rdoc
|
2
|
-
This is where we do all the undocumented auth stuff. NTLM is here and
|
3
|
-
hooked in.
|
4
|
-
|
5
|
-
WWMDNTLM is an incredibly naive NTLM implementation (used to get
|
6
|
-
around NTLM for one project ahwile back
|
7
|
-
=end
|
8
|
-
|
9
1
|
module WWMD
|
10
2
|
class Page
|
11
3
|
|
12
|
-
#:stopdoc:
|
13
|
-
|
14
|
-
#:section: Authentication helpers
|
15
|
-
|
16
|
-
# check if this request requires NTLM
|
17
|
-
def ntlm?
|
18
|
-
return false if self.code != 401
|
19
|
-
count = 0
|
20
|
-
self.header_data.each do |i|
|
21
|
-
if i[0] =~ /www-authenticate/i
|
22
|
-
count += 1 if (i[1] == "Negotiate" || i[1] == "NTLM")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
return (count > 0)
|
26
|
-
end
|
27
|
-
|
28
4
|
# does this request have an authenticate header?
|
29
5
|
def auth?
|
30
6
|
return false if self.code != 401
|
@@ -37,147 +13,5 @@ module WWMD
|
|
37
13
|
return (count > 0)
|
38
14
|
end
|
39
15
|
|
40
|
-
# not sure why this is here
|
41
|
-
def ntlm_perform(exp=nil)#:nodoc:
|
42
|
-
self.perform
|
43
|
-
return (self.code == exp)
|
44
|
-
end
|
45
|
-
|
46
|
-
# perform a get usig NTLM
|
47
|
-
def ntlm_get(url=nil?,debug=false)
|
48
|
-
self.clear_header('Authorization')
|
49
|
-
nobj = WWMDNTLM.new(self.opts)
|
50
|
-
self.url = @urlparse.parse(self.opts[:base_url],url) if not url.nil?
|
51
|
-
self.perform
|
52
|
-
return "This request does not appear to require NTLM" if not self.ntlm?
|
53
|
-
self.headers['Authorization'] = nobj.type_1_msg
|
54
|
-
self.perform
|
55
|
-
type2 = self.header_data.get_value('WWW-Authenticate')
|
56
|
-
nonce = nobj.get_nonce(type2)
|
57
|
-
type3 = nobj.type_3_msg(nonce)
|
58
|
-
self.headers['Authorization'] = type3
|
59
|
-
self.perform
|
60
|
-
self.clear_header('Authorization')
|
61
|
-
return self.code
|
62
|
-
end
|
63
|
-
|
64
|
-
#:startdoc:
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
class WWMDNTLM#:nodoc:
|
69
|
-
attr_accessor :hostname
|
70
|
-
attr_accessor :domain
|
71
|
-
attr_accessor :username
|
72
|
-
attr_accessor :password
|
73
|
-
attr_accessor :opts
|
74
|
-
attr_accessor :negotiate_flags
|
75
|
-
attr_accessor :debug
|
76
|
-
|
77
|
-
def initialize(opts,debug=false)
|
78
|
-
@opts = opts
|
79
|
-
@hostname = self.opts[:hostname]
|
80
|
-
@domain = self.opts[:domain]
|
81
|
-
@username = self.opts[:username]
|
82
|
-
@password = self.opts[:password]
|
83
|
-
@hostname = "LOCALHOST" if self.hostname.nil?
|
84
|
-
@negotiate_flags = 0x00002201.to_l32
|
85
|
-
@debug = debug
|
86
|
-
end
|
87
|
-
|
88
|
-
def type_1_msg
|
89
|
-
# do not add domain for now here as it doesn't seem to be needed
|
90
|
-
# it does need to be set for type3 messages
|
91
|
-
host_len = self.hostname.size
|
92
|
-
host_off = 0x20
|
93
|
-
# if self.domain.nil?
|
94
|
-
if true
|
95
|
-
dom_off = 0
|
96
|
-
dom_len = 0
|
97
|
-
else
|
98
|
-
dom_off = (host_off + hostname.size)
|
99
|
-
dom_len = self.domain.size
|
100
|
-
end
|
101
|
-
msg = ""
|
102
|
-
msg << "NTLMSSP\x00" # signature[8]
|
103
|
-
msg << 0x01.to_l32 # type[4]
|
104
|
-
msg << self.negotiate_flags # NegotiateFlags[4]
|
105
|
-
msg << dom_len.to_l16 # domain string length[2]
|
106
|
-
msg << dom_len.to_l16 # domain string length[2]
|
107
|
-
msg << dom_off.to_l32 # domain string offset[4]
|
108
|
-
msg << host_len.to_l16 # host string length[2]
|
109
|
-
msg << host_len.to_l16 # host string length[2]
|
110
|
-
msg << host_off.to_l32 # host string offset[4]
|
111
|
-
# msg << self.domain if not self.domain.nil? # domain[var]
|
112
|
-
msg << self.hostname # host name[var]
|
113
|
-
return "NTLM " + msg.b64e
|
114
|
-
end
|
115
|
-
|
116
|
-
def get_nonce(t2msg)
|
117
|
-
# Signature[8]
|
118
|
-
# MessageType[4]
|
119
|
-
# TargetNameFields[8]
|
120
|
-
# NegotiateFlags[4]
|
121
|
-
# ServerChallenge[8]
|
122
|
-
# Reserved[8] ! 0x00
|
123
|
-
# TargetInfoFields[8]
|
124
|
-
# Version[8]
|
125
|
-
# Payload[var]
|
126
|
-
msg = t2msg.split[1].b64d
|
127
|
-
return msg[24..31]
|
128
|
-
end
|
129
|
-
|
130
|
-
def type_3_msg(nonce)
|
131
|
-
hlen = 0x40
|
132
|
-
poff = hlen
|
133
|
-
domain = self.domain.to_utf16
|
134
|
-
username = self.username.to_utf16
|
135
|
-
hostname = self.hostname.to_utf16
|
136
|
-
lmresp = NTLM.lm_response(self.opts[:password],nonce,:lmhash)
|
137
|
-
ntresp = NTLM.lm_response(self.opts[:password],nonce,:nthash)
|
138
|
-
msg = ""
|
139
|
-
msg << "NTLMSSP\x00" # Signature[8]
|
140
|
-
msg << 0x03.to_l32 # MessageType[4]
|
141
|
-
# LmChallengeResonseFields[8]
|
142
|
-
msg << lmresp.size.to_l16 # LmChallengeResponseLen[2]
|
143
|
-
msg << lmresp.size.to_l16 # LmChallengeResponseMaxLen[2]
|
144
|
-
msg << poff.to_l32 # LmChallengeResponseBufferOffset[4]
|
145
|
-
poff += lmresp.size
|
146
|
-
# msg << 0x40.to_l32 # LmChallengeResponseBufferOffset[4]
|
147
|
-
# NtChallengeResponseFields[8]
|
148
|
-
msg << ntresp.size.to_l16 # NtChallengeResponseLen[2]
|
149
|
-
msg << ntresp.size.to_l16 # NtChallengeResponseMaxLen[2]
|
150
|
-
# msg << 0x58.to_l32 # NtChallengeResponseBufferOffset[4]
|
151
|
-
msg << poff.to_l32 # NtChallengeResponseBufferOffset[4]
|
152
|
-
poff += ntresp.size
|
153
|
-
# DomainNameFields[8]
|
154
|
-
msg << domain.size.to_l16 # DomainNameLen[2]
|
155
|
-
msg << domain.size.to_l16 # DomainNameMaxLen[2]
|
156
|
-
msg << poff.to_l32 # DomainNameBufferOffset[4]
|
157
|
-
poff += domain.size
|
158
|
-
# UserNameFields[8]
|
159
|
-
msg << username.size.to_l16 # UserNameLen[2]
|
160
|
-
msg << username.size.to_l16 # UserNameMaxLen[2]
|
161
|
-
msg << poff.to_l32 # UserNameBufferOffset[4]
|
162
|
-
poff += username.size
|
163
|
-
# WorkstationFields[8]
|
164
|
-
msg << hostname.size.to_l16 # WorkstationLen[2]
|
165
|
-
msg << hostname.size.to_l16 # WorkstationMaxLen[2]
|
166
|
-
msg << poff.to_l32 # WorkstationBufferOffset[4]
|
167
|
-
poff += hostname.size
|
168
|
-
# EncryptedRandomSessionKeyFields[8]
|
169
|
-
msg << 0x00.to_l16 # EncryptedRandomSessionKeyLen[2]
|
170
|
-
msg << 0x00.to_l16 # EncryptedRandomSessionKeyMaxLen[2]
|
171
|
-
msg << 0x00.to_l32 # EncryptedRandomSessionKeyBufferOffset[4]
|
172
|
-
msg << self.negotiate_flags # NegotiateFlags[4]
|
173
|
-
# Version[8] (optional do not add)
|
174
|
-
# Payload[var]
|
175
|
-
msg << lmresp # LmChallenge[var]
|
176
|
-
msg << ntresp # NtChallenge[var]
|
177
|
-
msg << domain # DomainName[var]
|
178
|
-
msg << username # UserName[var]
|
179
|
-
msg << hostname # Workstation[var]
|
180
|
-
return "NTLM " + msg.b64e
|
181
|
-
end
|
182
16
|
end
|
183
17
|
end
|
data/lib/wwmd/page/constants.rb
CHANGED
@@ -18,10 +18,11 @@ module WWMD
|
|
18
18
|
ESCAPE = {
|
19
19
|
:url => /[^a-zA-Z0-9\-_%]/,
|
20
20
|
:nalnum => /[^a-zA-Z0-9]/,
|
21
|
-
:xss => /[^a-zA-Z0-9
|
21
|
+
:xss => /[^a-zA-Z0-9=?()']/,
|
22
22
|
:ltgt => /[<>]/,
|
23
23
|
:all => /.*/,
|
24
|
-
:b64 => /[=+\/]/,
|
24
|
+
# :b64 => /[=+\/]/,
|
25
|
+
:b64 => /[^a-zA-Z0-9]/,
|
25
26
|
:none => :none,
|
26
27
|
:default => :default,
|
27
28
|
}
|
@@ -33,11 +34,13 @@ module WWMD
|
|
33
34
|
:ie7 => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
|
34
35
|
:ie8 => "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)",
|
35
36
|
:opera => "Opera/9.20 (Windows NT 6.0; U; en)",
|
36
|
-
: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"
|
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)"
|
37
40
|
}
|
38
41
|
|
39
42
|
DEFAULT_HEADERS = {
|
40
|
-
"User-Agent" => UA[:
|
43
|
+
"User-Agent" => UA[:wwmd],
|
41
44
|
"Accept" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
42
45
|
"Accept-Language" => "en-US,en;q=0.8,en-au;q=0.6,en-us;q=0.4,en;q=0.2",
|
43
46
|
"Accept-Encoding" => "gzip,deflate",
|
data/lib/wwmd/page/form.rb
CHANGED
@@ -40,21 +40,6 @@ module WWMD
|
|
40
40
|
return self.get_attribute("action")
|
41
41
|
end
|
42
42
|
|
43
|
-
def report
|
44
|
-
puts "action = #{self.action}"
|
45
|
-
self.fields.each { |field| puts field.to_text }
|
46
|
-
return nil
|
47
|
-
end
|
48
|
-
|
49
|
-
alias_method :show, :report
|
50
|
-
|
51
|
-
def to_form_array
|
52
|
-
FormArray.new(self.fields)
|
53
|
-
end
|
54
|
-
|
55
|
-
def to_array
|
56
|
-
self.to_form_array
|
57
|
-
end
|
58
43
|
end
|
59
44
|
|
60
45
|
class Field < Form
|
data/lib/wwmd/page/form_array.rb
CHANGED
@@ -6,35 +6,48 @@ Accessing this either as a hash or an array (but => won't work)
|
|
6
6
|
|
7
7
|
Some of the methods in here are kept for backward compat before the refactor
|
8
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.
|
9
12
|
=end
|
10
13
|
|
11
14
|
module WWMD
|
12
15
|
class FormArray < Array
|
16
|
+
attr_accessor :action
|
17
|
+
attr_accessor :delimiter
|
18
|
+
attr_accessor :equals
|
19
|
+
|
20
|
+
def initialize(fields=nil,action=nil,&block)
|
21
|
+
set_fields(fields)
|
22
|
+
@delimiter = "&"
|
23
|
+
@equals = "="
|
24
|
+
@action = action
|
25
|
+
instance_eval(&block) if block_given?
|
26
|
+
end
|
13
27
|
|
14
|
-
def
|
15
|
-
if
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
else
|
27
|
-
self << [ f['name'],f.get_value ]
|
28
|
+
def set_fields(fields=nil)
|
29
|
+
return nil if fields.nil?
|
30
|
+
# this first one is an array of field objects
|
31
|
+
if fields.class == Array
|
32
|
+
fields.each do |f|
|
33
|
+
name = f['name']
|
34
|
+
if self.name_exists(name)
|
35
|
+
if f['type'] == "hidden"
|
36
|
+
self.set name,f.get_value
|
37
|
+
elsif f['type'] == "checkbox" and f.to_html.grep(/checked/) != ''
|
38
|
+
self[name] = f.get_value
|
28
39
|
end
|
29
|
-
|
30
|
-
|
31
|
-
fields.each_pair { |k,v| self[k] = v }
|
32
|
-
elsif fields.class == String
|
33
|
-
fields.split("&").each do |f|
|
34
|
-
k,v = f.split("=",2)
|
35
|
-
self[k] = v
|
40
|
+
else
|
41
|
+
self << [ f['name'],f.get_value ]
|
36
42
|
end
|
37
43
|
end
|
44
|
+
elsif fields.class == Hash
|
45
|
+
fields.each_pair { |k,v| self[k] = v }
|
46
|
+
elsif fields.class == String
|
47
|
+
fields.split(@delimiter).each do |f|
|
48
|
+
k,v = f.split(@equals,2)
|
49
|
+
self[k] = v
|
50
|
+
end
|
38
51
|
end
|
39
52
|
end
|
40
53
|
|
@@ -43,6 +56,7 @@ module WWMD
|
|
43
56
|
def clone
|
44
57
|
ret = self.class.new
|
45
58
|
self.each { |r| ret << r.clone }
|
59
|
+
ret.action = self.action
|
46
60
|
return ret
|
47
61
|
end
|
48
62
|
|
@@ -64,14 +78,6 @@ module WWMD
|
|
64
78
|
self << [key,value]
|
65
79
|
end
|
66
80
|
|
67
|
-
def clear_viewstate
|
68
|
-
self.each { |k,v|
|
69
|
-
self[k] = "" if k == "__VIEWSTATE"
|
70
|
-
}
|
71
|
-
end
|
72
|
-
|
73
|
-
alias_method :extend!, :add #:nodoc (this is here for backward compat)
|
74
|
-
|
75
81
|
# key = Fixnum set value at index key
|
76
82
|
# key = String find key named string and set value
|
77
83
|
def set_value!(key,value)
|
@@ -87,6 +93,8 @@ module WWMD
|
|
87
93
|
return [key,value]
|
88
94
|
end
|
89
95
|
|
96
|
+
# get a value using its index
|
97
|
+
# override Array#[]
|
90
98
|
alias_method :old_get, :[]#:nodoc:
|
91
99
|
def [](*args)
|
92
100
|
if args.first.class == Fixnum
|
@@ -133,6 +141,10 @@ module WWMD
|
|
133
141
|
|
134
142
|
alias_method :get, :get_value
|
135
143
|
|
144
|
+
def keys
|
145
|
+
self.map { |k,v| k }
|
146
|
+
end
|
147
|
+
|
136
148
|
def setall!(value)
|
137
149
|
self.each_index { |i| self.set_value!(i,value) }
|
138
150
|
end
|
@@ -176,39 +188,38 @@ module WWMD
|
|
176
188
|
|
177
189
|
alias_method :unescape_all, :unescape_all!#:nodoc:
|
178
190
|
|
179
|
-
#
|
180
|
-
def
|
181
|
-
|
182
|
-
self.each do |i|
|
183
|
-
ret.push(i.join("="))
|
184
|
-
end
|
185
|
-
ret.join("&")
|
191
|
+
# remove form elements with null values
|
192
|
+
def remove_nulls!
|
193
|
+
self.delete_if { |x| x[1].to_s.empty? || x[1].nil? }
|
186
194
|
end
|
187
195
|
|
188
|
-
|
189
|
-
|
190
|
-
#
|
191
|
-
def
|
192
|
-
|
193
|
-
self.each do |i|
|
194
|
-
ret.push(i.join("="))
|
195
|
-
end
|
196
|
-
ret = ret.join("&")
|
197
|
-
return base.clip + "?" + ret.to_s
|
196
|
+
alias_method :squeeze!, :remove_nulls!
|
197
|
+
|
198
|
+
# remove form elements with null keys (for housekeeping returns)
|
199
|
+
def remove_null_keys!
|
200
|
+
self.delete_if { |x,y| x.to_s.empty? || x.nil? }
|
198
201
|
end
|
199
202
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
203
|
+
alias_method :squeeze_keys!, :remove_null_keys!
|
204
|
+
|
205
|
+
## viewstate
|
206
|
+
|
207
|
+
# clear viewstate variables
|
208
|
+
def clear_viewstate
|
209
|
+
self.each { |k,v|
|
210
|
+
self[k] = "" if k =~ /^__/
|
211
|
+
}
|
212
|
+
end
|
213
|
+
|
214
|
+
# remove viewstate variables
|
215
|
+
def rm_viewstate
|
216
|
+
# my least favorite ruby idiom
|
217
|
+
self.replace(self.map { |k,v| [k,v] if not k =~ /^__/ }.reject { |x| x.nil? })
|
209
218
|
end
|
210
219
|
|
211
|
-
|
220
|
+
alias_method :extend!, :add #:nodoc (this is here for backward compat)
|
221
|
+
|
222
|
+
# add viewstate stuff
|
212
223
|
def add_viewstate#:nodoc:
|
213
224
|
self.insert(0,[ "__VIEWSTATE","" ])
|
214
225
|
self.insert(0,[ "__EVENTARGUMENT","" ])
|
@@ -217,31 +228,40 @@ module WWMD
|
|
217
228
|
return nil
|
218
229
|
end
|
219
230
|
|
220
|
-
|
231
|
+
## conversions
|
221
232
|
|
222
|
-
#
|
223
|
-
def
|
224
|
-
|
233
|
+
# convert form into a post parameters string
|
234
|
+
def to_post
|
235
|
+
ret = []
|
236
|
+
self.each do |i|
|
237
|
+
ret << i.join(@equals)
|
238
|
+
end
|
239
|
+
ret.join(@delimiter)
|
225
240
|
end
|
226
241
|
|
227
|
-
|
228
|
-
|
229
|
-
#
|
230
|
-
def
|
231
|
-
|
242
|
+
# convert form into a get parameters string
|
243
|
+
#
|
244
|
+
# pass me a base to get a full url to pass to Page.get
|
245
|
+
def to_get(base="")
|
246
|
+
ret = []
|
247
|
+
self.each do |i|
|
248
|
+
ret << i.join(@equals)
|
249
|
+
end
|
250
|
+
ret = ret.join(@delimiter)
|
251
|
+
return base.clip + "?" + ret.to_s
|
232
252
|
end
|
233
253
|
|
234
|
-
|
254
|
+
## parsing convenience
|
235
255
|
|
236
256
|
# dump a web page containing a csrf example of the current FormArray
|
237
|
-
def to_csrf(action,unescval=false)
|
257
|
+
def to_csrf(action=nil,unescval=false)
|
258
|
+
action = self.action if not action
|
238
259
|
ret = ""
|
239
260
|
ret << "<html><body>\n"
|
240
261
|
ret << "<form method='post' id='wwmdtest' name='wwmdtest' action='#{action}'>\n"
|
241
262
|
self.each do |key,val|
|
242
263
|
val = val.unescape.gsub(/'/) { %q[\'] } if unescval
|
243
|
-
ret << "<input name='#{key.to_s.unescape}' type='hidden' value='#{val}' />\n"
|
244
|
-
# ret << "<input name='#{key.to_s.unescape}' type='hidden' value='#{val.to_s.unescape.gsub(/'/,"\\'")}' />\n"
|
264
|
+
ret << "<input name='#{key.to_s.unescape}' type='hidden' value='#{val.to_s.unescape}' />\n"
|
245
265
|
end
|
246
266
|
ret << "</form>\n"
|
247
267
|
ret << "<script>document.wwmdtest.submit()</script>\n"
|
@@ -249,17 +269,14 @@ module WWMD
|
|
249
269
|
return ret
|
250
270
|
end
|
251
271
|
|
252
|
-
|
253
|
-
self.map { |k,v| k }
|
254
|
-
end
|
255
|
-
|
272
|
+
# add markers for burp intruder to form
|
256
273
|
def burpify #:nodoc:
|
257
274
|
ret = self.clone
|
258
275
|
ret.each_index do |i|
|
259
276
|
next if ret[i][0] =~ /^__/
|
260
277
|
ret.set_value!(i,"#{ret.get_value(i)}" + "\302\247" + "\302\247")
|
261
278
|
end
|
262
|
-
|
279
|
+
ret.to_post.pbcopy
|
263
280
|
return ret
|
264
281
|
end
|
265
282
|
|
@@ -269,5 +286,10 @@ module WWMD
|
|
269
286
|
end
|
270
287
|
alias_method :fp, :fingerprint #:nodoc:
|
271
288
|
|
289
|
+
def from_array(arr)
|
290
|
+
self.clear
|
291
|
+
arr.each { |k,v| self[k] = v }
|
292
|
+
end
|
293
|
+
|
272
294
|
end
|
273
295
|
end
|