Class: RubyAMF::IO::AMFDeserializer
- Includes:
- Configuration, Exceptions, BinaryReader, Constants, VoHelper
- Defined in:
- lib/revent/amf3/io/amf_deserializer.rb
Instance Attribute Summary collapse
-
#stream ⇒ Object
Returns the value of attribute stream.
-
#stream_position ⇒ Object
Returns the value of attribute stream_position.
Instance Method Summary collapse
-
#initialize ⇒ AMFDeserializer
constructor
A new instance of AMFDeserializer.
- #read_amf3 ⇒ Object
- #read_amf3_array ⇒ Object
-
#read_amf3_byte_array ⇒ Object
according to the charles amf3 deserializer, they store byte array.
- #read_amf3_date ⇒ Object
- #read_amf3_integer ⇒ Object
- #read_amf3_number ⇒ Object
- #read_amf3_object ⇒ Object
- #read_amf3_string ⇒ Object
- #read_amf3_xml ⇒ Object
- #reset ⇒ Object
- #reset_referencables ⇒ Object
Constructor Details
#initialize ⇒ AMFDeserializer
Returns a new instance of AMFDeserializer.
16 17 18 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 16 def initialize reset end |
Instance Attribute Details
#stream ⇒ Object
Returns the value of attribute stream.
13 14 15 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 13 def stream @stream end |
#stream_position ⇒ Object
Returns the value of attribute stream_position.
14 15 16 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 14 def stream_position @stream_position end |
Instance Method Details
#read_amf3 ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 32 def read_amf3 type = read_word8 case type when AMF3_UNDEFINED nil when AMF3_NULL nil when AMF3_FALSE false when AMF3_TRUE true when AMF3_INTEGER read_amf3_integer when AMF3_NUMBER read_amf3_number when AMF3_STRING read_amf3_string when AMF3_XML read_amf3_xml_string when AMF3_DATE read_amf3_date when AMF3_ARRAY read_amf3_array when AMF3_OBJECT read_amf3_object when AMF3_XML_STRING read_amf3_xml when AMF3_BYTE_ARRAY read_amf3_byte_array end end |
#read_amf3_array ⇒ Object
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 155 def read_amf3_array type = read_amf3_integer isReference = (type & 0x01) == 0 if isReference reference = type >> 1 if reference < @stored_objects.length if @stored_objects[reference] == nil raise(RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "Reference to non existant array at index #{reference}, please tell [email protected]")) end return @stored_objects[reference] else raise Exception.new("Reference to non-existent array at index #{reference}, please tell [email protected]") end else length = type >> 1 propertyName = read_amf3_string if propertyName != nil array = {} @stored_objects << array begin while(propertyName.length) value = read_amf3 array[propertyName] = value propertyName = read_amf3_string end rescue Exception => e #end of object exception, because propertyName.length will be non existent end 0.upto(length - 1) do |i| array["" + i.to_s] = read_amf3 end else array = [] @stored_objects << array 0.upto(length - 1) do array << read_amf3 end end array end end |
#read_amf3_byte_array ⇒ Object
according to the charles amf3 deserializer, they store byte array
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 282 def read_amf3_byte_array # according to the charles amf3 deserializer, they store byte array type = read_amf3_integer isReference = (type & 0x01) == 0 if isReference reference = type >> 1 if reference < @stored_objects.length if @stored_objects[reference] == nil raise( RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "Reference to non existant byteArray at index #{reference}, please tell [email protected]")) end return @stored_objects[reference] else raise( RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "Reference to non existant byteArray #{reference}")) end else length = type >> 1 begin # first assume its gzipped and rescue an exception if its not bytes = Zlib::Inflate.inflate(self.stream[self.stream_position, length]) rescue Exception => e bytes = self.stream[self.stream_position, length] end self.stream_position += length @stored_objects << bytes bytes end end |
#read_amf3_date ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 129 def read_amf3_date type = read_amf3_integer isReference = (type & 0x01) == 0 if isReference reference = type >> 1 if reference < @stored_objects.length if @stored_objects[reference] == nil raise( RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "Reference to non existant date at index #{reference}, please tell [email protected]")) end return @stored_objects[reference] else raise( RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "Undefined date object reference when deserialing AMF3: #{reference}") ) end else seconds = read_double.to_f/1000 time = if (seconds < 0) || ClassMappings.use_ruby_date_time # we can't use Time if its a negative second value DateTime.strptime(seconds.to_s, "%s") else Time.at(seconds) end @stored_objects << time time end end |
#read_amf3_integer ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 64 def read_amf3_integer n = 0 b = read_word8||0 result = 0 while ((b & 0x80) != 0 && n < 3) result = result << 7 result = result | (b & 0x7f) b = read_word8||0 n = n + 1 end if (n < 3) result = result << 7 result = result | b else #Use all 8 bits from the 4th byte result = result << 8 result = result | b #Check if the integer should be negative if (result > AMF3_INTEGER_MAX) result -= (1 << 29) end end return result end |
#read_amf3_number ⇒ Object
308 309 310 311 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 308 def read_amf3_number res = read_double res.is_a?(Float)&&res.nan? ? nil : res # check for NaN and convert them to nil end |
#read_amf3_object ⇒ Object
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 197 def read_amf3_object type = read_amf3_integer isReference = (type & 0x01) == 0 if isReference reference = type >> 1 if reference < @stored_objects.length if @stored_objects[reference] == nil raise( RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "Reference to non existant object at index #{reference}, please tell [email protected].")) end return @stored_objects[reference] else raise( RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "Reference to non existant object #{reference}")) end else class_type = type >> 1 class_is_reference = (class_type & 0x01) == 0 if class_is_reference class_reference = class_type >> 1 if class_reference < @stored_defs.length class_definition = @stored_defs[class_reference] else raise RUBYAMFException.new(RUBYAMFException.UNDEFINED_DEFINITION_REFERENCE_ERROR, "Reference to non existant class definition #{class_reference}") end else actionscript_class_name = read_amf3_string externalizable = (class_type & 0x02) != 0 dynamic = (class_type & 0x04) != 0 attribute_count = class_type >> 3 class_attributes = [] attribute_count.times{class_attributes << read_amf3_string} # Read class members class_definition = {"as_class_name" => actionscript_class_name, "members" => class_attributes, "externalizable" => externalizable, "dynamic" => dynamic} @stored_defs << class_definition end action_class_name = class_definition['as_class_name'] #get the className according to type # check to see if its the first main amf object or a flex message obj, because then we need a _explicitType field type and skip some things skip_mapping = if action_class_name && action_class_name.include?("flex.messaging") obj = VoHash.new # initialize an empty VoHash value holder obj._explicitType = action_class_name true else # otherwise just use a normal hash obj = {} false end obj_position = @stored_objects.size # need to replace the object later for referencing (MUST be before inserting the object into stored_objs) @stored_objects << obj if class_definition['externalizable'] if ['flex.messaging.io.ObjectProxy','flex.messaging.io.ArrayCollection'].include?(action_class_name) obj = read_amf3 else raise( RUBYAMFException.new(RUBYAMFException.USER_ERROR, "Unable to read externalizable data type #{type}")) end else translate_case = !skip_mapping&&ClassMappings.translate_case # remove the need for a method call / also, don't want to convert on main remoting object class_definition['members'].each do |key| value = read_amf3 #if (value)&& value != 'NaN'# have to read key to move the reader ahead in the stream key.to_snake! if translate_case obj[key] = value #end end if class_definition['dynamic'] while (key = read_amf3_string) && key.length != 0 do # read next key value = read_amf3 #if (value) && value != 'NaN' key.to_snake! if translate_case obj[key] = value #end end end obj = VoUtil.get_vo_for_incoming(obj,action_class_name) unless skip_mapping end @stored_objects[obj_position] = obj # put the new object into the same position as the original object since it was worked on obj end end |
#read_amf3_string ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 92 def read_amf3_string type = read_amf3_integer isReference = (type & 0x01) == 0 if isReference reference = type >> 1 if reference < @stored_strings.length if @stored_strings[reference] == nil raise( RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "Reference to non existant string at index #{reference}, please tell [email protected]")) end return @stored_strings[reference] else raise( RUBYAMFException.new(RUBYAMFException.UNDEFINED_STRING_REFERENCE_ERROR, "Reference to non existant string at index #{reference}, please tell [email protected]") ) end else length = type >> 1 #Note that we have to read the string into a byte buffer and then #convert to a UTF-8 string, because for standard readUTF() it #reads an unsigned short to get the string length. #A string isn't stored as a reference if it is the empty string #thanks Karl von Randow for this if length > 0 str = String.new(readn(length)) #specifically cast as string, as we're reading verbatim from the stream str.toutf8 #convert to utf8 @stored_strings << str end return str end end |
#read_amf3_xml ⇒ Object
123 124 125 126 127 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 123 def read_amf3_xml type = read_amf3_integer length = type >> 1 readn(length) end |
#reset ⇒ Object
20 21 22 23 24 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 20 def reset @stream = '' @stream_position = 0 reset_referencables end |
#reset_referencables ⇒ Object
26 27 28 29 30 |
# File 'lib/revent/amf3/io/amf_deserializer.rb', line 26 def reset_referencables @stored_strings = [] @stored_objects = [] @stored_defs = [] end |