class PureRubyZip::ZipDecompressor

Public Instance Methods

bit_lengths_to_tree(bit_lengths) click to toggle source
# File lib/pure_ruby_zip.rb, line 72
def bit_lengths_to_tree(bit_lengths)
  max_bits = bit_lengths.max
  bitlen_counts = (0..max_bits).map { |count| bit_lengths.count { |length| length == count && length != 0 } }
  next_code = [0, 0]
  (2..max_bits).each do |i|
    next_code[i] = ((next_code[i - 1] || 0) + bitlen_counts[i - 1]) << 1
  end
  tree = {}
  bit_lengths.each.with_index do |length, index|
    if length != 0
      tree[next_code[length].to_s(2).rjust(length, "0")] = index
      next_code[length] += 1
    end
  end
  tree
end
decode_dynamic_huffman_compressed_block(file_data, file_bitstream) click to toggle source
# File lib/pure_ruby_zip.rb, line 101
def decode_dynamic_huffman_compressed_block(file_data, file_bitstream)
  hlit = file_bitstream.read_int(5) + 257
  hdist = file_bitstream.read_int(5) + 1
  hclen = file_bitstream.read_int(4) + 4
  code_length_bit_lengths = [0] * 19
  (0..(hclen - 1)).each { |len| code_length_bit_lengths[CODE_LENGTH_CODES_ORDER[len]] = file_bitstream.read_int(3) }
  code_length_tree = bit_lengths_to_tree(code_length_bit_lengths)
  bit_lengths = []
  while bit_lengths.count < hlit + hdist
    sym = decode_symbol(code_length_tree, file_bitstream)
    if sym < 16
      bit_lengths += [sym]
    elsif sym == 16
      prev_byte = bit_lengths[-1]
      bit_lengths += [prev_byte] * (file_bitstream.read_int(2) + 3)
    elsif sym == 17
      bit_lengths += [0] * (file_bitstream.read_int(3) + 3)
    elsif sym == 18
      bit_lengths += [0] * (file_bitstream.read_int(7) + 11)
    end
  end
  litlen_tree = bit_lengths_to_tree(bit_lengths[0..(hlit - 1)])
  dist_tree = bit_lengths_to_tree(bit_lengths[hlit..-1])
  inflate_block_data(litlen_tree, dist_tree, file_data, file_bitstream)
end
decode_fixed_huffman_compressed_block(file_data, file_bitstream) click to toggle source
# File lib/pure_ruby_zip.rb, line 94
def decode_fixed_huffman_compressed_block(file_data, file_bitstream)
  litlen_bit_lengths = [8] * 144 + [9] * (256 - 144) + [7] * (280 - 256) + [8] * (286 - 280)
  litlen_tree = bit_lengths_to_tree(litlen_bit_lengths)
  dist_bit_lengths = [5] * 30
  dist_tree = bit_lengths_to_tree(dist_bit_lengths)
  inflate_block_data(litlen_tree, dist_tree, file_data, file_bitstream)
end
decode_symbol(tree, file_bitstream) click to toggle source
# File lib/pure_ruby_zip.rb, line 39
def decode_symbol(tree, file_bitstream)
  bits = []
  while true
    bit = file_bitstream.read_bit
    bits += [bit]
    key = bits.map { |x| x ? "1" : "0" }.join("")
    return tree[key] if tree[key]
  end
end
decode_uncompressed_block(file_data, file_bitstream) click to toggle source
# File lib/pure_ruby_zip.rb, line 88
def decode_uncompressed_block(file_data, file_bitstream)
  file_bitstream.read_int(5)
  length = file_bitstream.read_int(16)
  file_bitstream.read_int(16)
  (0..(length - 1)).map { |x| file_bitstream.read_int(8).chr }.join("")
end
decode_zipped_file(file_bitstream) click to toggle source
# File lib/pure_ruby_zip.rb, line 126
def decode_zipped_file(file_bitstream)
  file_data = ""
  is_last_block = false
  until is_last_block
    is_last_block = file_bitstream.read_bit
    block_type = file_bitstream.read_int(2)
    file_data += if block_type == 0
      decode_uncompressed_block(file_data, file_bitstream)
    elsif block_type == 1
      decode_fixed_huffman_compressed_block(file_data, file_bitstream)
    else
      decode_dynamic_huffman_compressed_block(file_data, file_bitstream)
    end
  end
  file_data
end
inflate_block_data(litlen_tree, dist_tree, file_data, file_bitstream) click to toggle source
# File lib/pure_ruby_zip.rb, line 48
def inflate_block_data(litlen_tree, dist_tree, file_data, file_bitstream)
  data = file_data
  loop do
    sym = decode_symbol(litlen_tree, file_bitstream)
    if sym < 256
      data += sym.chr
    elsif sym == 256
      return data
    else
      sym -= 257
      length = file_bitstream.read_int(LENGTH_EXTRA_BITS[sym]) + LENGTH_BASE[sym]
      dist_sym = decode_symbol(dist_tree, file_bitstream)
      dist = file_bitstream.read_int(DISTANCE_EXTRA_BITS[dist_sym]) + DISTANCE_BASE[dist_sym]
      reference_data = []
      (0..(length - 1)).each {
        char = data[-dist]
        data += char
        reference_data += [char]
      }
      x = reference_data[0..10].join("").codepoints.join(" ")
    end
  end
  data
end