miketracy-wwmd 0.2.16 → 0.2.17
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/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
|