PNG  IHDR;IDATxܻn0K )(pA 7LeG{ §㻢|ذaÆ 6lذaÆ 6lذaÆ 6lom$^yذag5bÆ 6lذaÆ 6lذa{ 6lذaÆ `}HFkm,mӪôô! x|'ܢ˟;E:9&ᶒ}{v]n&6 h_tڠ͵-ҫZ;Z$.Pkž)!o>}leQfJTu іچ\X=8Rن4`Vwl>nG^is"ms$ui?wbs[m6K4O.4%/bC%t Mז -lG6mrz2s%9s@-k9=)kB5\+͂Zsٲ Rn~GRC wIcIn7jJhۛNCS|j08yiHKֶۛkɈ+;SzL/F*\Ԕ#"5m2[S=gnaPeғL lذaÆ 6l^ḵaÆ 6lذaÆ 6lذa; _ذaÆ 6lذaÆ 6lذaÆ RIENDB` # Copyright (c) 2005 Norman Timmler (inlet media e.K., Hamburg, Germany) # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class AMFStringBuffer def initialize(str = nil) @buffer = str || '' @pos = 0 end def seek(pos) @pos = pos end def read(length) raise EOFError if @pos + length > @buffer.length rt = @buffer[@pos, length] @pos += length rt end def readchar read(1).unpack('C').first end def write(str) if @pos + str.length > @buffer.length @buffer << ' ' * (@pos + str.length - @buffer.length) end @buffer[@pos, str.length] = str @pos += str.length end def close end def to_s @buffer end def length @buffer.length end def eof? @pos == length end def pos @pos end def read__AMF_string read(read__UI16) end def read__AMF_double num = read(8).unpack('G').first.to_f end def read__AMF_boolean read__UI8 == 1 end def read__AMF_mixed_array size = read__UI32 # is not used hash = {} while !eof? key = read__AMF_string break if key.empty? && (type = read__UI8) == 9 hash[key] = read__AMF_data(type) end hash end def read__AMF_object object = Object.new while !eof? key = read__AMF_string break if key.empty? && (type = read__UI8) == 9 object.instance_variable_set( eval(":@#{key}"), read__AMF_data(type) ) end object end def read__AMF_array size = read__UI32 array = [] (1..size).step do |pos| break if eof? array << read__AMF_data end array end def read__AMF_date utc_time = Time.at((read__AMF_double / 1000).to_i) utc_time + (read__SI16 * 60) - Time.now.gmtoff end def read__AMF_data(type = nil) type ||= read__UI8 value = case type.to_i when 0 read__AMF_double when 1 read__AMF_boolean when 2 read__AMF_string when 3 read__AMF_object when 8 read__AMF_mixed_array when 10 read__AMF_array when 11 read__AMF_date else end return value end def write__AMF_string(str) write__UI8 2 write__UI16 str.length write str end def write__AMF_double(value) write__UI8 0 write [value].pack('G') end def write__AMF_boolean(value) write__UI8 1 value = value ? 1 : 0 write [value].pack('C') end def write__AMF_date(time) write__UI8 11 write [(time.to_f * 1000.0)].pack('G') write__SI16( (Time.now.gmtoff / 60).to_i ) end def write__AMF_data(object) if object === true || object === false write__AMF_boolean object elsif object.kind_of? Numeric write__AMF_double object elsif object.kind_of? Time write__AMF_date object elsif object.kind_of? Hash write__AMF_mixed_array object elsif object.kind_of? String write__AMF_string object elsif object.kind_of? Array write__AMF_array object else write__AMF_object object end end def write__AMF_key(key) write__UI16 key.length write key end def write__AMF_mixed_array(hash) write__UI8 8 write__UI32 hash.length # length will never be read hash.each_pair do |key, value| write__AMF_key key write__AMF_data value end write__UI16 0 write__UI8 9 end def write__AMF_array(array) write__UI8 10 write__UI32 array.length array.each do |value| write__AMF_data value end end def write__AMF_object(object) write__UI8 3 object.instance_variables.each do |variable| write__AMF_key variable.gsub('@', '') write__AMF_data object.instance_variable_get( variable.intern ) end write__UI16 0 write__UI8 9 end # FIXME: This methods are copied from flv_stream.rb. Should get in here per # include? or something like this. def read__UI8 readchar end def read__UI16 (readchar << 8) + readchar end def read__UI24 (readchar << 16) + (readchar << 8) + readchar end def read__UI32 (readchar << 24) + (readchar << 16) + (readchar << 8) + readchar end def read__STRING(length) read length end def read__SI16 read(2).reverse.unpack('s').first.to_i end def write__UI8(value) write [value].pack('C') end def write__UI16(value) write [(value >> 8) & 0xff].pack('c') write [value & 0xff].pack('c') end def write__UI24(value) write [value >> 16].pack('c') write [(value >> 8) & 0xff].pack('c') write [value & 0xff].pack('c') end def write__UI32(value) write [value].pack('N') end def write__SI16(value) write [(value >> 8) & 0xff].pack('c') write [value & 0xff].pack('c') end def write__STRING(string) write string end alias_method :<<, :write__STRING end