iZsh-wwmd 0.2.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/History.txt +24 -0
  2. data/README.rdoc +87 -0
  3. data/Rakefile +34 -0
  4. data/examples/config_example.yaml +24 -0
  5. data/examples/wwmd_example.rb +73 -0
  6. data/lib/wwmd.rb +78 -0
  7. data/lib/wwmd/class_extensions.rb +2 -0
  8. data/lib/wwmd/class_extensions/extensions_base.rb +235 -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 +188 -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/auth.rb +17 -0
  17. data/lib/wwmd/page/constants.rb +64 -0
  18. data/lib/wwmd/page/form.rb +99 -0
  19. data/lib/wwmd/page/form_array.rb +296 -0
  20. data/lib/wwmd/page/headers.rb +111 -0
  21. data/lib/wwmd/page/helpers.rb +30 -0
  22. data/lib/wwmd/page/html2text_hpricot.rb +76 -0
  23. data/lib/wwmd/page/html2text_nokogiri.rb +42 -0
  24. data/lib/wwmd/page/inputs.rb +47 -0
  25. data/lib/wwmd/page/irb_helpers.rb +114 -0
  26. data/lib/wwmd/page/page.rb +241 -0
  27. data/lib/wwmd/page/parsing_convenience.rb +94 -0
  28. data/lib/wwmd/page/reporting_helpers.rb +87 -0
  29. data/lib/wwmd/page/scrape.rb +198 -0
  30. data/lib/wwmd/page/spider.rb +127 -0
  31. data/lib/wwmd/urlparse.rb +104 -0
  32. data/lib/wwmd/viewstate.rb +17 -0
  33. data/lib/wwmd/viewstate/viewstate.rb +101 -0
  34. data/lib/wwmd/viewstate/viewstate_deserializer_methods.rb +217 -0
  35. data/lib/wwmd/viewstate/viewstate_from_xml.rb +128 -0
  36. data/lib/wwmd/viewstate/viewstate_types.rb +51 -0
  37. data/lib/wwmd/viewstate/viewstate_utils.rb +162 -0
  38. data/lib/wwmd/viewstate/viewstate_yaml.rb +25 -0
  39. data/lib/wwmd/viewstate/vs_stubs.rb +22 -0
  40. data/lib/wwmd/viewstate/vs_stubs/vs_array.rb +38 -0
  41. data/lib/wwmd/viewstate/vs_stubs/vs_binary_serialized.rb +30 -0
  42. data/lib/wwmd/viewstate/vs_stubs/vs_hashtable.rb +42 -0
  43. data/lib/wwmd/viewstate/vs_stubs/vs_hybrid_dict.rb +42 -0
  44. data/lib/wwmd/viewstate/vs_stubs/vs_indexed_string.rb +6 -0
  45. data/lib/wwmd/viewstate/vs_stubs/vs_indexed_string_ref.rb +24 -0
  46. data/lib/wwmd/viewstate/vs_stubs/vs_int_enum.rb +27 -0
  47. data/lib/wwmd/viewstate/vs_stubs/vs_list.rb +34 -0
  48. data/lib/wwmd/viewstate/vs_stubs/vs_pair.rb +29 -0
  49. data/lib/wwmd/viewstate/vs_stubs/vs_read_types.rb +11 -0
  50. data/lib/wwmd/viewstate/vs_stubs/vs_read_value.rb +35 -0
  51. data/lib/wwmd/viewstate/vs_stubs/vs_sparse_array.rb +58 -0
  52. data/lib/wwmd/viewstate/vs_stubs/vs_string.rb +33 -0
  53. data/lib/wwmd/viewstate/vs_stubs/vs_string_array.rb +39 -0
  54. data/lib/wwmd/viewstate/vs_stubs/vs_string_formatted.rb +32 -0
  55. data/lib/wwmd/viewstate/vs_stubs/vs_stub_helpers.rb +37 -0
  56. data/lib/wwmd/viewstate/vs_stubs/vs_triplet.rb +31 -0
  57. data/lib/wwmd/viewstate/vs_stubs/vs_type.rb +23 -0
  58. data/lib/wwmd/viewstate/vs_stubs/vs_unit.rb +30 -0
  59. data/lib/wwmd/viewstate/vs_stubs/vs_value.rb +35 -0
  60. data/lib/wwmd/wwmd_config.rb +52 -0
  61. data/lib/wwmd/wwmd_puts.rb +9 -0
  62. data/lib/wwmd/wwmd_utils.rb +28 -0
  63. data/spec/README +3 -0
  64. data/spec/form_array.spec +49 -0
  65. data/spec/spider_csrf_test.spec +28 -0
  66. data/spec/urlparse_test.spec +101 -0
  67. data/tasks/ann.rake +80 -0
  68. data/tasks/bones.rake +20 -0
  69. data/tasks/gem.rake +201 -0
  70. data/tasks/git.rake +40 -0
  71. data/tasks/notes.rake +27 -0
  72. data/tasks/post_load.rake +34 -0
  73. data/tasks/rdoc.rake +51 -0
  74. data/tasks/rubyforge.rake +55 -0
  75. data/tasks/setup.rb +292 -0
  76. data/tasks/spec.rake +54 -0
  77. data/tasks/test.rake +40 -0
  78. data/tasks/zentest.rake +36 -0
  79. metadata +174 -0
@@ -0,0 +1,104 @@
1
+ require 'htmlentities'
2
+ require 'wwmd/class_extensions'
3
+ module WWMD
4
+
5
+ # yay for experiments in re-inventing the wheel
6
+ class URLParse
7
+ HANDLERS = [:https,:http,:ftp,:file]
8
+ attr_reader :proto,:location,:path,:script,:rpath,:params,:base_url,:fqpath
9
+
10
+ def initialize(*args)
11
+ # nothing to see here, move along
12
+ end
13
+
14
+ def parse(*args)
15
+ if args.size == 1
16
+ base = ""
17
+ actual = args.shift
18
+ else
19
+ base = args.shift
20
+ actual = args.shift
21
+ end
22
+ @proto = @location = @path = @script = @rpath = nil
23
+ @base = base.to_s
24
+ @actual = actual
25
+ if self.has_proto?
26
+ @base = @actual
27
+ @actual = ""
28
+ end
29
+ # does this work for http://location/? probably not
30
+ @base += "/" if (!@base.has_ext? || @base.split("/").size == 3)
31
+ @rpath = make_me_path.join("/")
32
+ @rpath += "?#{@params}" if @params
33
+ @path = "/" + @rpath
34
+ if @rpath.has_ext?
35
+ @path = "/" + @rpath.dirname
36
+ @script = @rpath.basename.clip
37
+ end
38
+ @script = "" if @script.nil?
39
+ begin
40
+ @base_url = @proto + "://" + @location
41
+ rescue => e
42
+ dgb = WWMD.debug
43
+ WWMD.debug = true
44
+ putd "ERROR in urlparse TRACE:"
45
+ pp *args
46
+ putd @proto
47
+ putd @base
48
+ putd @actual
49
+ putd @location
50
+ WWMD.debug = dbg
51
+ raise e
52
+ end
53
+ @fqpath = @path + @script
54
+ self
55
+ end
56
+
57
+ def make_me_path
58
+ @proto,tpath = @base.split(":",2)
59
+ tpath ||= ""
60
+ @params = tpath.clop
61
+ tpath = tpath.clip
62
+ if @actual.empty?
63
+ a_path = tpath.split("/").reject { |x| x.empty? }
64
+ else
65
+ a_path = tpath.dirname.split("/").reject { |x| x.empty? }
66
+ end
67
+ @location = a_path.shift
68
+ if @actual.clop
69
+ @params = @actual.clop
70
+ @actual = @actual.clip
71
+ end
72
+ a_path = [] if (@actual =~ (/^\//))
73
+ b_path = @actual.split("/").reject { |x| x.empty? }
74
+ a_path.pop if (a_path[-1] =~ /^\?/).kind_of?(Fixnum) && !b_path.empty?
75
+ c_path = (a_path + @actual.split("/").reject { |x| x.empty? }).flatten
76
+ d_path = []
77
+ c_path.each do |x|
78
+ (d_path.pop;next) if x == ".."
79
+ next if (x == "." || x =~ /^\?/)
80
+ d_path << x
81
+ end
82
+ return d_path
83
+ end
84
+
85
+ def has_proto?
86
+ begin
87
+ return true if HANDLERS.include?(@actual.split(":").first.downcase.to_sym)
88
+ rescue
89
+ return false
90
+ end
91
+ end
92
+
93
+ def to_s
94
+ return "#{@proto}://#{@location}/#{rpath}"
95
+ end
96
+ end
97
+ end
98
+
99
+ class String
100
+ def has_ext? #:nodoc:
101
+ return false if self.basename.split(".",2)[1].empty?
102
+ return true
103
+ end
104
+ end
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'nokogiri'
3
+ require 'rexml/document'
4
+ require 'htmlentities'
5
+ require 'wwmd/viewstate/viewstate_utils'
6
+ module WWMD
7
+ class ViewState
8
+ include ViewStateUtils
9
+ end
10
+ end
11
+ require 'wwmd/class_extensions'
12
+ require 'wwmd/viewstate/viewstate'
13
+ require 'wwmd/viewstate/viewstate_types'
14
+ require 'wwmd/viewstate/viewstate_yaml'
15
+ require 'wwmd/viewstate/viewstate_deserializer_methods'
16
+ require 'wwmd/viewstate/viewstate_from_xml'
17
+ require 'wwmd/viewstate/vs_stubs'
@@ -0,0 +1,101 @@
1
+ module WWMD
2
+ class ViewState
3
+ attr_accessor :b64
4
+ attr_accessor :obj_queue
5
+ attr_accessor :mac
6
+ attr_accessor :debug
7
+ attr_reader :raw
8
+ attr_reader :stack
9
+ attr_reader :bufarr
10
+ attr_reader :magic
11
+ attr_reader :size
12
+ attr_reader :indexed_strings
13
+ attr_reader :last_offset
14
+ attr_reader :xml
15
+ attr_reader :ndoc
16
+ attr_reader :obj_counts
17
+
18
+ def initialize(b64=nil)
19
+ @b64 = b64
20
+ @raw = ""
21
+ @stack = ""
22
+ @obj_queue = []
23
+ @bufarr = []
24
+ @size = 0
25
+ @indexed_strings = []
26
+ @mac = nil
27
+ @debug = false
28
+ @obj_counts = {}
29
+ self.deserialize if b64
30
+ end
31
+
32
+ # mac_enabled?
33
+ def mac_enabled?
34
+ return !@mac.nil?
35
+ end
36
+
37
+ # deserialize
38
+ def deserialize(b64=nil)
39
+ @obj_queue = []
40
+ @b64 = b64 if b64
41
+ @raw = @b64.b64d
42
+ @bufarr = @raw.scan(/./m)
43
+ @size = @bufarr.size
44
+ raise "Invalid ViewState" if not self.magic?
45
+ @obj_queue << self.deserialize_value
46
+ if @bufarr.size == 20 then
47
+ @mac = @bufarr.slice!(0..19).join("")
48
+ dlog(0x00,"MAC = #{@mac.hexify}")
49
+ end
50
+ raise "Error Parsing Viewstate (left: #{@bufarr.size})" if not @bufarr.size == 0
51
+ return !self.raw.nil?
52
+ end
53
+
54
+ def serialize(objs=nil,version=2)
55
+ @obj_queue = objs if objs
56
+ @stack << "\xFF\x01"
57
+ @stack << @obj_queue.first.serialize
58
+ @stack << @mac if @mac
59
+ return !self.stack.nil?
60
+ end
61
+
62
+ def to_xml
63
+ @xml = REXML::Document.new()
64
+ header = REXML::Element.new("ViewState")
65
+ header.add_attribute("version", @magic.b64e)
66
+ header.add_attribute("version_string", @magic.hexify)
67
+ header.add_element(@obj_queue.first.to_xml)
68
+ if self.mac_enabled?
69
+ max = REXML::Element.new("Mac")
70
+ max.add_attribute("encoding","hexify")
71
+ max.add_text(@mac.hexify)
72
+ header.add_element(max)
73
+ end
74
+ @xml.add_element(header)
75
+ @ndoc = Nokogiri::XML.parse(@xml.to_s)
76
+ self
77
+ end
78
+
79
+ # xpath search the nokogiri doc if we have one
80
+ def search(*args)
81
+ return "No XML" if !@ndoc
82
+ @ndoc.search(*args)
83
+ end
84
+
85
+ # move pp due to to_xml returning self
86
+ # this is all for the sake of getting #search to work
87
+ def pp(*args)
88
+ return "Undefined" if !@xml
89
+ @xml.pp(*args)
90
+ end
91
+
92
+ def from_yaml(yaml)
93
+ @obj_queue = YAML.load(yaml)
94
+ end
95
+
96
+ def to_yaml
97
+ @obj_queue.to_yaml
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,217 @@
1
+ module WWMD
2
+ class ViewState
3
+ # complex types
4
+ def pair(t=nil)
5
+ dlog t,"next = #{next_type}"
6
+ VSStubs::VSPair.new(self.deserialize_value,self.deserialize_value)
7
+ end
8
+
9
+ def triplet(t=nil)
10
+ dlog t,"next = #{next_type}"
11
+ VSStubs::VSTriplet.new(self.deserialize_value,self.deserialize_value,self.deserialize_value)
12
+ end
13
+
14
+ def type(t=nil)
15
+ typeref,typeval = self.deserialize_type
16
+ dlog(t,"typeref = 0x#{typeref.to_s(16)} typeval = #{typeval}")
17
+ VSStubs::VSType.new(typeref,typeval)
18
+ end
19
+
20
+ def string_formatted(t=nil)
21
+ typeref,typeval = self.deserialize_type
22
+ str = self.read_string
23
+ dlog(t,"typeref = 0x#{typeref.to_s(16)} typeval = #{typeval} string = #{str}")
24
+ VSStubs::VSStringFormatted.new(typeref,typeval,str)
25
+ end
26
+
27
+ def int_enum(t=nil)
28
+ typeref,typeval = self.deserialize_type
29
+ index = self.read_7bit_encoded_int
30
+ dlog(t,"typeref = 0x#{typeref.to_s(16)} typeval = #{typeval} index = #{index}")
31
+ VSStubs::VSIntEnum.new(typeref,typeval,index)
32
+ end
33
+
34
+ def binary_serialized(t=nil)
35
+ count = self.read_7bit_encoded_int
36
+ dlog(t,count)
37
+ bin = self.read(count)
38
+ me = VSStubs::VSBinarySerialized.new()
39
+ me.set(bin)
40
+ return me
41
+ end
42
+
43
+ def sparse_array(t=nil)
44
+ typeref,typeval = self.deserialize_type
45
+ size = read_7bit_encoded_int
46
+ elems = read_7bit_encoded_int
47
+ dlog(t,"typeref = 0x#{typeref.to_s(16)} typeval = #{typeval} size = #{size} elems = #{elems}")
48
+ me = VSStubs::VSSparseArray.new(typeref,typeval,size,elems)
49
+ if elems > size
50
+ raise "Invalid sparse_array"
51
+ end
52
+ (1..elems).each do |i|
53
+ idx = read_7bit_encoded_int
54
+ me.add(idx,self.deserialize_value)
55
+ end
56
+ return me
57
+ end
58
+
59
+ def hashtable(t=nil)
60
+ len = read_7bit_encoded_int
61
+ dlog(t,"len = #{len}")
62
+ me = VSStubs::VSHashtable.new()
63
+ (1..len).each do |i|
64
+ me.add(self.deserialize_value,self.deserialize_value)
65
+ end
66
+ return me
67
+ end
68
+
69
+ def hybrid_dict(t=nil)
70
+ len = read_7bit_encoded_int
71
+ dlog(t,"len = #{len}")
72
+ me = VSStubs::VSHybridDict.new()
73
+ (1..len).each do |i|
74
+ me.add(self.deserialize_value,self.deserialize_value)
75
+ end
76
+ return me
77
+ end
78
+
79
+ def array(t=nil)
80
+ typeref,typeval = self.deserialize_type
81
+ len = read_7bit_encoded_int
82
+ dlog(t,"typeref = 0x#{typeref.to_s(16)} typeval = #{typeval} len = #{len}")
83
+ me = VSStubs::VSArray.new(typeref,typeval)
84
+ (1..len).each do |i|
85
+ me.add(self.deserialize_value)
86
+ end
87
+ return me
88
+ end
89
+
90
+ def string_array(t=nil)
91
+ len = read_7bit_encoded_int
92
+ dlog(t,"len = #{len}")
93
+ me = VSStubs::VSStringArray.new()
94
+ (1..len).each do |i|
95
+ str = self.read_string
96
+ me.add(str)
97
+ dlog(t,"string_array_elem: #{str}")
98
+ end
99
+ return me
100
+ end
101
+
102
+ def list(t=nil)
103
+ len = read_7bit_encoded_int
104
+ dlog(t,"len = #{len}")
105
+ me = VSStubs::VSList.new()
106
+ (1..len).each do |i|
107
+ me.add(self.deserialize_value)
108
+ end
109
+ return me
110
+ end
111
+
112
+ def unit(t=nil)
113
+ s1 = read_double
114
+ s2 = read_int32
115
+ dlog(t,"#{s1.to_s(16).rjust(16,"0")},#{s2.to_s(16).rjust(8,"0")}")
116
+ VSStubs::VSUnit.new(s1,s2)
117
+ end
118
+
119
+ def indexed_string(t=nil)
120
+ str = self.read_string
121
+ @indexed_strings << str
122
+ dlog(t,"idx = #{@indexed_strings.size - 1} val = #{str}")
123
+ VSStubs::VSIndexedString.new(str)
124
+ end
125
+
126
+ def indexed_string_ref(t=nil)
127
+ ref = self.read_int
128
+ dlog(t,"ref = #{ref} val = #{@indexed_strings[ref]}")
129
+ VSStubs::VSIndexedStringRef.new(ref)
130
+ end
131
+
132
+ def string(t=nil)
133
+ str = self.read_string
134
+ dlog(t,str)
135
+ VSStubs::VSString.new(str)
136
+ end
137
+
138
+ # VSStubs::VSReadValue types
139
+ def color(t=nil)
140
+ val = self.read_int32
141
+ dlog(t,val.to_s(16))
142
+ VSStubs::VSColor.new(val)
143
+ end
144
+
145
+ def known_color(t=nil)
146
+ index = self.read_7bit_encoded_int
147
+ dlog(t,"index = #{index.to_s(16)}")
148
+ VSStubs::VSKnownColor.new(index)
149
+ end
150
+
151
+ def int16(t=nil)
152
+ val = read_short
153
+ dlog(t,val)
154
+ VSStubs::VSInt16.new(val)
155
+ end
156
+
157
+ def int32(t=nil)
158
+ val = self.read_7bit_encoded_int
159
+ dlog(t,val)
160
+ VSStubs::VSInt32.new(val)
161
+ end
162
+
163
+ def byte(t=nil)
164
+ val = self.read_byte
165
+ dlog(t,val)
166
+ VSStubs::VSByte.new(val)
167
+ end
168
+
169
+ def char(t=nil)
170
+ val = self.read_byte
171
+ dlog(t,val)
172
+ VSStubs::VSChar.new(val)
173
+ end
174
+
175
+ def date_time(t=nil)
176
+ val = self.read_double
177
+ dlog(t,val)
178
+ VSStubs::VSDateTime.new(val)
179
+ end
180
+
181
+ def double(t=nil)
182
+ val = self.read_double
183
+ dlog(t,val)
184
+ VSStubs::VSDouble.new(val)
185
+ end
186
+
187
+ def single(t=nil)
188
+ val = self.read_single
189
+ dlog(t,val)
190
+ VSStubs::VSSingle.new(val)
191
+ end
192
+
193
+ # VSStubs::VSValue types
194
+ def null(t=nil); dlog(t,nil); return VSStubs::VSValue.new(t); end
195
+ def empty_byte(t=nil); dlog(t,nil); return VSStubs::VSValue.new(t); end
196
+ def zeroint32(t=nil); dlog(t,nil); return VSStubs::VSValue.new(t); end
197
+ def bool_true(t=nil); dlog(t,nil); return VSStubs::VSValue.new(t); end
198
+ def bool_false(t=nil); dlog(t,nil); return VSStubs::VSValue.new(t); end
199
+ def empty_color(t=nil); dlog(t,nil); return VSStubs::VSValue.new(t); end
200
+ def empty_unit(t=nil); dlog(t,nil); return VSStubs::VSValue.new(t); end
201
+
202
+ # deserialize_value
203
+ def deserialize_value
204
+ @last_offset = self.offset
205
+ token = self.read_byte # self.read_raw_byte
206
+ if not (tsym = VIEWSTATE_TYPES[token])
207
+ STDERR.puts "TOKEN: [0x#{token.to_s(16)}] at #{last_offset}"
208
+ STDERR.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
211
+ nobj = self.send(tsym,token)
212
+ raise "Invalid Class Returned #{nobj.class}" if not VIEWSTATE_TYPES.include?(nobj.opcode)
213
+ return nobj
214
+ end
215
+
216
+ end
217
+ end
@@ -0,0 +1,128 @@
1
+ module WWMD
2
+ class ViewState
3
+ # directly serialize into stack from received xml (the easy way)
4
+ # this is pretty silly but it didn't take me very long so...
5
+
6
+ attr_reader :xmlstack
7
+
8
+ def get_sym(str)
9
+ str.split(":").last.gsub(/[A-Z]+/,'\1_\0').downcase[1..-1].gsub(/\Avs/,"").to_sym
10
+ end
11
+
12
+ def opcode(name,val)
13
+ sym = get_sym(name)
14
+ if sym == :value
15
+ ret = VIEWSTATE_TYPES.index(val.to_sym)
16
+ else
17
+ ret = VIEWSTATE_TYPES.index(sym)
18
+ end
19
+ ret
20
+ end
21
+
22
+ def serialize_hashtable(node)
23
+ tstack = ""
24
+ tstack << self.write_7bit_encoded_int(node['size'].to_i)
25
+ node.children.each do |c|
26
+ next if c.text?
27
+ raise "Invalid Hashtable: got #{c.name}" if not c.name == "Pair"
28
+ end
29
+ tstack
30
+ end
31
+
32
+ def decode_text(node)
33
+ case node['encoding']
34
+ when "urlencoded"
35
+ node.inner_text.unescape
36
+ when "quoted-printable"
37
+ node.inner_text.from_qp
38
+ when "base64"
39
+ node.inner_text.b64d
40
+ when "hexify"
41
+ node.inner_text.dehexify
42
+ else
43
+ node.inner_text
44
+ end
45
+ end
46
+
47
+ def write_node(node)
48
+ return false if node.text?
49
+ tstack = ""
50
+ # this is a hack to get sparse_array to work
51
+ return false if ["Pair","Key","Value"].include?(node.name) # skip and fall through
52
+ if ["Index","Size","Elements"].include?(node.name)
53
+ @xmlstack << self.write_7bit_encoded_int(node.inner_text.to_i)
54
+ return false
55
+ end
56
+ if node.name == "Mac"
57
+ @xmlstack << decode_text(node)
58
+ return false
59
+ end
60
+ # end hack
61
+ flag = true # begin; sillyness; rescue => me; end
62
+ case get_sym(node.name)
63
+ when :pair, :triplet, :value, :sparse_array, :type, :string_formatted
64
+ when :int_enum, :known_color, :int32
65
+ tstack << self.write_7bit_encoded_int(node.inner_text.to_i)
66
+ when :int16
67
+ tstack << self.write_short(node.inner_text.to_i)
68
+ when :byte, :char, :indexed_string_ref
69
+ tstack << self.write_byte(node.inner_text.to_i)
70
+ when :color, :single
71
+ tstack << self.write_int32(node.inner_text.to_i)
72
+ when :double, :date_time
73
+ tstack << self.write_double(node.inner_text.to_i)
74
+ when :unit
75
+ tstack << self.write_double(node['dword'].to_i)
76
+ tstack << self.write_single(node['word'].to_i)
77
+ when :list, :string_array, :array
78
+ tstack << self.write_7bit_encoded_int(node['size'].to_i)
79
+ when :string, :indexed_string, :binary_serialized
80
+ flag = false if ([:string_array,:string_formatted].include?(get_sym(node.parent.name)))
81
+ # get encoding
82
+ str = decode_text(node)
83
+ tstack << self.write_7bit_encoded_int(str.size)
84
+ tstack << str
85
+ when :hashtable, :hybrid_dict
86
+ tstack << serialize_hashtable(node)
87
+ else
88
+ raise "Invalid Node:\n#{node.name}"
89
+ end
90
+
91
+ # [flag] is a hack to get around string_array and string_formatted emitting opcodes
92
+ @xmlstack << self.write_byte(opcode(node.name,node.inner_text)) if flag
93
+ if node.has_attribute?("typeref")
94
+ if node['typeref'].to_i == 0x2b
95
+ @xmlstack << self.serialize_type(node['typeref'].to_i,node['typeval'].to_i)
96
+ else
97
+ @xmlstack << self.serialize_type(node['typeref'].to_i,node['typeval'])
98
+ end
99
+ end
100
+ @xmlstack << tstack
101
+ end
102
+
103
+ def serialize_xml(node)
104
+ begin
105
+ write_node(node)
106
+ rescue => e
107
+ STDERR.puts "ERROR parsing node:\n#{node.to_s}"
108
+ raise e
109
+ end
110
+ node.children.each do |c|
111
+ serialize_xml(c)
112
+ end
113
+ end
114
+
115
+ def from_xml(xml)
116
+ @xmlstack = ""
117
+ doc = Nokogiri::XML.parse(xml)
118
+ root = doc.root
119
+ raise "Invalid ViewState Version" if not root.has_attribute?("version")
120
+ @xmlstack << root['version'].b64d
121
+ root.children.each do |c|
122
+ serialize_xml(c)
123
+ end
124
+ self.deserialize(@xmlstack.b64e)
125
+ end
126
+
127
+ end
128
+ end