📄 amf_deserializer.rb
字号:
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 aaron@rubyamf.org")) end return @stored_objects[reference] else raise Exception.new("Reference to non-existent array at index #{reference}, please tell aaron@rubyamf.org") end else length = type >> 1 propertyName = read_amf3_string if propertyName != nil 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 @stored_objects << array return array else array = [] 0.upto(length - 1) do array << read_amf3 end @stored_objects << array return array end end end 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 aaron@rubyamf.org.")) end obj = @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 @stored_objects << class_definition #have to put in stored objects to keep the index count correct end action_class_name = class_definition['as_class_name'] #get the className according to type @stored_objects << VoHash.new # add to stored objects first, cicular references are needed. 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 # check to see if its the first main amf object or a flex message obj, because then we need a _explicitType field type if action_class_name && action_class_name.include?("flex.messaging") obj = VoHash.new # initialize an empty VoHash value holder obj._explicitType = action_class_name else # otherwise just use a normal hash obj = {} end class_definition['members'].each do |key| if (value = read_amf3)&& value != 'NaN'# have to read key to move the reader ahead in the stream key.to_snake! if ClassMappings.translate_case obj[key] = value end end if class_definition['dynamic'] while (key = read_amf3_string) && key.length != 0 do # read next key if value = read_amf3 && value != 'NaN' key.to_snake! if ClassMappings.translate_case obj[key] = value end end end obj.reject!{|k,v| !v||v=='NaN'} if map = ClassMappings.get_vo_mapping_for_actionscript_class(action_class_name) # if there is a map use, that class obj.reject!{|k,v| map[:ignore_fields]&&map[:ignore_fields][k]} ruby_obj = map[:ruby].constantize.new if map[:type] == "active_record" # put all the attributes fields into the attribute instance variable attributes = {} # extract attributes obj.each_key do |field| attributes[field] = obj.delete(field) if ClassMappings.attribute_names[map[:ruby]][field] end ruby_obj.instance_variable_set("@attributes", attributes) # bypasses any overwriting of the attributes=(value) method (also allows 'id' to be set) ruby_obj.instance_variable_set("@new_record", false) if attributes["id"] # then the record already exists in the database obj.each_key do |field| if reflection = ruby_obj.class.reflections[field.to_sym] # is it an association value = obj.delete(field) # get rid of the field so it doesnt get added in the next loop case reflection.macro when :belongs_to, :has_one ruby_obj.send("set_#{field}_target", value) when :has_many, :has_many_and_belongs_to ruby_obj.send("#{field}").target = value when :composed_of ruby_obj.send("#{field}=", value) # this sets the attributes to the corresponding values end end end end obj.each do |field, value| # whatever is left, set them as instance variables in the object ruby_obj.instance_variable_set("@#{field}", value) end obj = ruby_obj end end end obj end def read_amf3_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 aaron@rubyamf.org")) 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 ob = readn(length) @stored_objects << ob return ob end end #AMF0 def read_number res = read_double res end def read_booleanr read_boolean end def read_string read_utf end def read_array ret = [] #create new array length = read_word32_network # Grab the length of the array #catch empty arguments if !length return [] end #Loop over all the elements in the data 0.upto(length - 1) do type = read_byte #Grab the type for each element data = read(type) #Grab the element ret << data end ret end def read_date #epoch time comes in millis from 01/01/1970, convert to seconds. seconds = (read_double) / 1000 #flash client timezone offset (which comes in minutes, #but incorrectly signed), convert to seconds, and fix the sign. client_zone_offset = (read_int16_network) * 60 * -1 # now we have seconds #get server timezone offset server_zone_offset = Time.zone_offset(Time.now.zone) #diff the timezone offset's and subtract from seconds #create a time object from the result time = Time.at(seconds - server_zone_offset + client_zone_offset) if ClassMappings.use_ruby_date_time time = DateTime.new(time.year, time.month, time.day, time.hour, time.min, time.sec) end #TODO: handle daylight savings #sent_time_zone = sent.get_time_zone #we have to handle daylight savings ms as well #if (sent_time_zone.in_daylight_time(sent.get_time)) #sent.set_time_in_millis(sent.get_time_in_millis - sent_time_zone.get_dst_savings) #end time end #Reads and instantiates a custom incoming ValueObject def read_custom_class type = read_utf value = read_object #if type not nil and it is an VoHash, check VO Mapping if type && value.is_a?(VoHash) map = ClassMappings.get_vo_mapping_for_actionscript_class(type) vo = VoUtil.get_vo_hash_for_incoming(value, type) key.to_snake! if ClassMappings.translate_case if map && map[:ignore_fields] if map[:ignore_fields][key] next end end if vo return vo #prematurly return the new VO end end value #return value if no VO was created end #reads a mixed array def read_mixed_array ash = Hash.new key = read_utf type = read_byte while(type != 9) value = read(type) ash[key] = value key = read_utf type = read_byte end ash end def read_object aso = VoHash.new key = read_utf #read the value's key type = read_byte #read the value's type while (type != 9) do map = ClassMappings.get_vo_mapping_for_actionscript_class(type) value = read(type) key.to_snake! if ClassMappings.translate_case if map && map[:ignore_fields] if map[:ignore_fields][key] next end end if amf0_object_default_members_ignore[key] && !value == nil aso[key] = val end key = read_utf # Read the next key type = read_byte # Read the next type end return aso end def read_xml read_long_utf end end endend
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -