module Zipography

Constants

HIDDEN_BLOB_HEADER_SIZE
HIDDEN_BLOB_VERSION

Public Instance Methods

adler2hex(i;) click to toggle source
# File lib.rb, line 161
def adler2hex i; "0x" + i.to_i.to_s(16); end
adler32_file(file, bufsiz: 1 << 16) click to toggle source
# File lib.rb, line 115
def adler32_file file, bufsiz: 1 << 16
  r = nil
  File.open(file, 'rb') do |f|
    while (chunk = f.read bufsiz)
      r = Zlib.adler32 chunk, r
    end
  end
  r
end
adler32_file_slice(file, start, length, bufsiz: 1 << 16) click to toggle source
# File lib.rb, line 135
def adler32_file_slice file, start, length, bufsiz: 1 << 16
  r = nil
  File.open(file, 'rb') do |f|
    f.seek start
    bytes_read = 0
    idx = 0
    finito = false
    while (chunk = f.read bufsiz)
      bytes_read += chunk.bytesize

      if bytes_read > length
        if idx == 0
          chunk = chunk.byteslice(0, length)
        else
          chunk = chunk.byteslice(0, chunk.bytesize - (bytes_read - length))
        end
        finito = true
      end
      r = Zlib.adler32 chunk, r
      break if finito
      idx += 1
    end
  end
  r
end
blob_write(file, dest) click to toggle source
# File lib.rb, line 125
def blob_write file, dest
  blob_size = File.stat(file).size

  header = HiddenBlobHeader.new len: blob_size, checksum: adler32_file(file)
  IO.copy_stream file, dest
  dest.write header.to_binary_s

  blob_size + header.num_bytes
end
cd_offset_start_overflow(zip_file, offset) click to toggle source
# File lib.rb, line 181
def cd_offset_start_overflow zip_file, offset
  max = (2**32)-1
  actual = offset + File.stat(zip_file).size + HIDDEN_BLOB_HEADER_SIZE
  actual - max
end
eocd_parse(file, pos) click to toggle source
# File lib.rb, line 95
def eocd_parse file, pos
  File.open(file, 'rb') do |f|
    f.seek pos
    r = Eocd.read f
    fail "no support for zip64 format" if r[:cd_offset_start] == 0xFFFFFFFF
    r
  end
end
eocd_position(file) click to toggle source
# File lib.rb, line 91
def eocd_position file
  file_rindex(file, [0x06054b50].pack('V')) || fail("#{file}: not a zip")
end
file_rindex(file, substring) click to toggle source
# File lib.rb, line 61
def file_rindex file, substring
  my_rindex = ->(s1, s2) { s1.rindex s2.dup.force_encoding('ASCII-8BIT') }

  r = nil
  File.open(file, 'rb') do |io|
    iorc = IOReverseChunks.new io
    prev_chunk = ''
    bytes_read = 0

    r = iorc.each do |chunk|
      bytes_read += chunk.size

      if (idx = my_rindex.call(chunk, substring))
        break iorc.fsize - bytes_read + idx
      end

      if my_rindex.call(chunk, substring[0])
        two_chunks = chunk + prev_chunk
        if (idx = my_rindex.call(two_chunks, substring))
          break iorc.fsize - bytes_read + idx
        end
      end

      prev_chunk = chunk
    end
  end

  r
end
hbh_validate(header) click to toggle source
# File lib.rb, line 176
def hbh_validate header
  header[:len] <= 2**32 - 70 &&
    header[:version] > 0 && header[:version] <= HIDDEN_BLOB_VERSION
end
options(usage, argv_size) click to toggle source
# File lib.rb, line 163
def options usage, argv_size
  opt = {}; op = OptionParser.new do |o|
    o.banner = "Usage: #{File.basename $0} #{usage}"
    o.on("-o FILE", "output") do |arg|
      opt[:output] = File.open arg, 'wb'
    end
  end
  op.parse!

  abort op.help if ARGV.size < argv_size
  opt[:output] || $stdout
end