class EventMachine::HttpDecoders::GZipHeader

Partial implementation of RFC 1952 to extract the deflate stream from a gzip file

Public Class Methods

new() click to toggle source
# File lib/em-http/decoders.rb, line 97
def initialize
  @state = :begin
  @data = ""
  @pos = 0
end

Public Instance Methods

eof?() click to toggle source
# File lib/em-http/decoders.rb, line 124
def eof?
  @pos >= @data.size
end
extract_stream(compressed) click to toggle source
# File lib/em-http/decoders.rb, line 128
def extract_stream(compressed)
  @data << compressed
  pos = @pos

  while !eof? && !finished?
    buffer = ""

    case @state
    when :begin
      break if !read(10, buffer)

      if buffer.getbyte(0) != 0x1f || buffer.getbyte(1) != 0x8b
        raise DecoderError.new("magic header not found")
      end

      if buffer.getbyte(2) != 0x08
        raise DecoderError.new("unknown compression method")
      end

      @flags = buffer.getbyte(3)
      if (@flags & 0xe0).nonzero?
        raise DecoderError.new("unknown header flags set")
      end

      # We don't care about these values, I'm leaving the code for reference
      # @time = buffer[4..7].unpack("V")[0] # little-endian uint32
      # @extra_flags = buffer.getbyte(8)
      # @os = buffer.getbyte(9)

      @state = :extra_length

    when :extra_length
      if (@flags & 0x04).nonzero?
        break if !read(2, buffer)
        @extra_length = buffer.unpack("v")[0] # little-endian uint16
        @state = :extra
      else
        @state = :extra
      end

    when :extra
      if (@flags & 0x04).nonzero?
        break if read(@extra_length, buffer)
        @state = :name
      else
        @state = :name
      end

    when :name
      if (@flags & 0x08).nonzero?
        while !(buffer = readbyte).nil?
          if buffer == 0
            @state = :comment
            break
          end
        end
      else
        @state = :comment
      end

    when :comment
      if (@flags & 0x10).nonzero?
        while !(buffer = readbyte).nil?
          if buffer == 0
            @state = :hcrc
            break
          end
        end
      else
        @state = :hcrc
      end

    when :hcrc
      if (@flags & 0x02).nonzero?
        break if !read(2, buffer)
        @state = :finish
      else
        @state = :finish
      end
    end
  end

  if finished?
    compressed[(@pos - pos)..-1]
  else
    ""
  end
end
finished?() click to toggle source
# File lib/em-http/decoders.rb, line 103
def finished?
  @state == :finish
end
read(n, buffer) click to toggle source
# File lib/em-http/decoders.rb, line 107
def read(n, buffer)
  if (@pos + n) <= @data.size
    buffer << @data[@pos..(@pos + n - 1)]
    @pos += n
    return true
  else
    return false
  end
end
readbyte() click to toggle source
# File lib/em-http/decoders.rb, line 117
def readbyte
  if (@pos + 1) <= @data.size
    @pos += 1
    @data.getbyte(@pos - 1)
  end
end