181 lines
3.2 KiB
Ruby
181 lines
3.2 KiB
Ruby
# -*- coding: binary -*-
|
|
|
|
module Rex
|
|
module Zip
|
|
|
|
|
|
#
|
|
# This structure holds the following data pertaining to a Zip entry's data.
|
|
#
|
|
# data crc
|
|
# compressed size
|
|
# uncompressed size
|
|
#
|
|
class CompInfo
|
|
|
|
def initialize(crc, compsz, uncompsz)
|
|
@crc, @compsz, @uncompsz = crc, compsz, uncompsz
|
|
end
|
|
|
|
def pack
|
|
[ @crc, @compsz, @uncompsz ].pack('VVV')
|
|
end
|
|
|
|
end
|
|
|
|
|
|
#
|
|
# This structure holds the following data pertaining to a Zip entry.
|
|
#
|
|
# general purpose bit flag
|
|
# compression method
|
|
# modification time
|
|
# modification date
|
|
#
|
|
class CompFlags
|
|
|
|
attr_accessor :compmeth
|
|
|
|
def initialize(gpbf, compmeth, timestamp)
|
|
@gpbf = gpbf
|
|
@compmeth = compmeth
|
|
@mod_time = ((timestamp.hour << 11) | (timestamp.min << 5) | (timestamp.sec))
|
|
@mod_date = (((timestamp.year - 1980) << 9) | (timestamp.mon << 5) | (timestamp.day))
|
|
end
|
|
|
|
def pack
|
|
[ @gpbf, @compmeth, @mod_time, @mod_date ].pack('vvvv')
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
# This structure is sometimes stored after the file data and used
|
|
# instead of the fields within the Local File Header.
|
|
#
|
|
class DataDesc
|
|
|
|
SIGNATURE = 0x8074b50
|
|
|
|
def initialize(compinfo)
|
|
@compinfo = compinfo
|
|
end
|
|
|
|
def pack
|
|
ret = [ SIGNATURE ].pack('V')
|
|
ret << @compinfo.pack
|
|
ret
|
|
end
|
|
|
|
end
|
|
|
|
|
|
#
|
|
# This structure records the compression data and flags about
|
|
# a Zip entry to a file.
|
|
#
|
|
class LocalFileHdr
|
|
|
|
SIGNATURE = 0x4034b50
|
|
|
|
def initialize(entry)
|
|
@entry = entry
|
|
end
|
|
|
|
def pack
|
|
path = @entry.relative_path
|
|
|
|
ret = [ SIGNATURE, ZIP_VERSION ].pack('Vv')
|
|
ret << @entry.flags.pack
|
|
ret << @entry.info.pack
|
|
ret << [ path.length, @entry.xtra.length ].pack('vv')
|
|
ret << path
|
|
ret << @entry.xtra
|
|
ret
|
|
end
|
|
|
|
end
|
|
|
|
|
|
#
|
|
# This structure holds all of the information about a particular Zip Entry
|
|
# as it is contained within the central directory.
|
|
#
|
|
class CentralDir
|
|
|
|
SIGNATURE = 0x2014b50
|
|
|
|
def initialize(entry, offset)
|
|
@entry = entry
|
|
@disknum_start = 0
|
|
@attr_int = 0
|
|
@attr_ext = 0x20
|
|
@hdr_offset = offset
|
|
end
|
|
|
|
def pack
|
|
path = @entry.relative_path
|
|
|
|
ret = [ SIGNATURE, ZIP_VERSION ].pack('Vv')
|
|
ret << [ ZIP_VERSION ].pack('v')
|
|
ret << @entry.flags.pack
|
|
ret << @entry.info.pack
|
|
arr = []
|
|
arr << path.length
|
|
arr << @entry.xtra.length
|
|
arr << @entry.comment.length
|
|
arr << @disknum_start
|
|
arr << @attr_int
|
|
arr << @entry.attrs
|
|
arr << @hdr_offset
|
|
ret << arr.pack('vvvvvVV')
|
|
ret << path
|
|
ret << @entry.xtra
|
|
ret << @entry.comment
|
|
# digital signature not supported
|
|
ret
|
|
end
|
|
|
|
end
|
|
|
|
|
|
#
|
|
# This structure is written after the per-entry central directory records to
|
|
# provide information about the archive as a whole.
|
|
#
|
|
class CentralDirEnd
|
|
|
|
SIGNATURE = 0x6054b50
|
|
|
|
def initialize(ncfd, cfdsz, offset, comment=nil)
|
|
@disk_no = 0
|
|
@disk_dir_start = 0
|
|
@ncfd_this_disk = ncfd
|
|
@ncfd_total = ncfd
|
|
@cfd_size = cfdsz
|
|
@start_offset = offset
|
|
@comment = comment
|
|
@comment ||= ''
|
|
end
|
|
|
|
|
|
def pack
|
|
arr = []
|
|
arr << SIGNATURE
|
|
arr << @disk_no
|
|
arr << @disk_dir_start
|
|
arr << @ncfd_this_disk
|
|
arr << @ncfd_total
|
|
arr << @cfd_size
|
|
arr << @start_offset
|
|
arr << @comment.length
|
|
(arr.pack('VvvvvVVv') + @comment)
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
end
|