?? amf_deserializer.rb
字號:
module RubyAMF module IO class AMFDeserializer require 'io/read_write' include RubyAMF::AMF include RubyAMF::App include RubyAMF::Configuration include RubyAMF::Exceptions include RubyAMF::IO::BinaryReader include RubyAMF::IO::Constants include RubyAMF::VoHelper attr_accessor :stream attr_accessor :stream_position attr_accessor :amf0_object_default_members_ignore def initialize @raw = true @rawkickoff = true @stream_position = 0 reset_referencables end #do an entire read operation on a complete amf request def rubyamf_read(amfobj) RequestStore.amf_encoding = 'amf0' @amfobj = amfobj @stream = @amfobj.input_stream preamble headers bodys end def reset_referencables @amf0_stored_objects = [] @amf0_object_default_members_ignore = {} @class_member_defs = {} @stored_strings = [] @stored_objects = [] @stored_defs = [] end def preamble version = read_int8 #first byte, not anything important if version != 0 && version != 3 raise RUBYAMFException.new(RUBYAMFException.VERSION_ERROR, "The amf version is incorrect") end #read the client. (0x00 - Flash Player, 0x01 - FlashComm) client = read_int8 end def headers @amf0_object_default_members_ignore = { 'Credentials' => true, 'coldfusion' => true, 'amfheaders' => true, 'amf' => true, 'httpheaders' => true, 'recordset' => true, 'error' => true, 'trace' => true, 'm_debug' => true} #Find total number of header elements header_count = read_word16_network 0.upto(header_count - 1) do #find the key of the header name = read_utf #Find the must understand flag required = read_booleanr #Grab the length of the header element length = read_word32_network #Grab the type of the element type = read_byte #Turn the element into real data value = read(type) #create new header header = AMFHeader.new(name,required,value) #add header to the amfbody object @amfobj.add_header(header) end end def bodys @amf0_object_default_members_ignore = {} #find the total number of body elements body_count = read_int16_network #Loop over all the body elements 0.upto(body_count - 1) do reset_referencables #The target method target = read_utf #The unique id that the client understands response = read_utf #Get the length of the body element length = read_word32_network #Grab the type of the element type = read_byte #Turn the argument elements into real data value = read(type) #new body body = AMFBody.new(target,response,value) #add the body to the amfobj @amfobj.add_body(body) end end #Reads object data by type from @input_stream def read(type) case type when AMF3_TYPE RequestStore.amf_encoding = 'amf3' read_amf3 when AMF_NUMBER read_number when AMF_BOOLEAN read_booleanr when AMF_STRING read_string when AMF_OBJECT read_object when AMF_MOVIE_CLIP raise RUBYAMFException.new(RUBYAMFException.UNSUPPORTED_AMF0_TYPE, 'You cannot send a movie clip') when AMF_NULL return nil when AMF_UNDEFINED return nil when AMF_REFERENCE return nil #TODO Implement this when AMF_MIXED_ARRAY length = read_int32_network #long, don't do anything with it read_mixed_array when AMF_EOO return nil when AMF_ARRAY read_array when AMF_DATE read_date when AMF_LONG_STRING utflen = read_int32_network #don't touch the length read_utf when AMF_UNSUPPORTED raise RUBYAMFException.new(RUBYAMFException.UNSUPPORTED_AMF0_TYPE, 'Unsupported type') when AMF_RECORDSET raise RUBYAMFException.new(RUBYAMFException.UNSUPPORTED_AMF0_TYPE, 'You cannot send a RecordSet to RubyAMF, although you can receive them from RubyAMF.') when AMF_XML read_xml when AMF_TYPED_OBJECT read_custom_class end end #AMF3 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_number #read standard AMF0 number, a double 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 def read_amf3_integer n = 0 b = read_word8 result = 0 while ((b & 0x80) != 0 && n < 3) result = result << 7 result = result | (b.to_i & 0x7f) b = read_word8 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 & 0x10000000) != 0) result |= 0xe0000000 end end return result end 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 aaron@rubyamf.org")) end return @stored_strings[reference] else raise( RUBYAMFException.new(RUBYAMFException.UNDEFINED_STRING_REFERENCE_ERROR, "Reference to non existant string at index #{reference}, please tell aaron@rubyamf.org") ) 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 def read_amf3_xml type = read_amf3_integer isReference = (type & 0x01) == 0 if isReference reference = type >> 1 if @stored_objects[reference] == nil raise( RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "Reference to non existant xml string at index #{reference}, please tell aaron@rubyamf.org")) end xml = @stored_objects[reference] else length = type >> 1 xml = readn(length) end @stored_objects << xml return xml end 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 aaron@rubyamf.org")) end return @stored_objects[reference] else raise( RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "Undefined date object reference when deserialing AMF3: #{reference}") ) end else milliseconds = read_double time = Time.at( milliseconds.to_f / 1000.0 ) if ClassMappings.use_ruby_date_time time = DateTime.new(time.year, time.month, time.day, time.hour, time.min, time.sec) end @stored_objects << time time end end
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -