2010-02-10 17:27:40 +00:00
|
|
|
##
|
|
|
|
# $Id$
|
|
|
|
##
|
|
|
|
|
|
|
|
module Rex
|
|
|
|
module Zip
|
|
|
|
|
2011-05-25 16:45:20 +00:00
|
|
|
#
|
|
|
|
# An Entry represents a logical file or directory to be stored in an Archive
|
|
|
|
#
|
2010-02-10 17:27:40 +00:00
|
|
|
class Entry
|
|
|
|
|
|
|
|
attr_accessor :name, :flags, :info, :xtra, :comment, :attrs
|
2010-11-30 03:52:46 +00:00
|
|
|
attr_reader :data
|
2010-02-10 17:27:40 +00:00
|
|
|
|
|
|
|
def initialize(fname, data, compmeth, timestamp=nil, attrs=nil, xtra=nil, comment=nil)
|
|
|
|
@name = fname
|
|
|
|
@data = data
|
|
|
|
@xtra = xtra
|
|
|
|
@xtra ||= ''
|
|
|
|
@comment = comment
|
|
|
|
@comment ||= ''
|
|
|
|
@attrs = attrs
|
|
|
|
@attrs ||= 0
|
|
|
|
|
|
|
|
# XXX: sanitize timestmap (assume now)
|
|
|
|
timestamp ||= Time.now
|
|
|
|
@flags = CompFlags.new(0, compmeth, timestamp)
|
|
|
|
|
|
|
|
if (@data)
|
|
|
|
compress
|
|
|
|
else
|
|
|
|
@data = ''
|
|
|
|
@info = CompInfo.new(0, 0, 0)
|
|
|
|
end
|
|
|
|
@compdata ||= ''
|
|
|
|
end
|
|
|
|
|
2010-11-30 03:52:46 +00:00
|
|
|
def data=(val)
|
|
|
|
@data = val
|
|
|
|
compress
|
|
|
|
end
|
2010-02-10 17:27:40 +00:00
|
|
|
|
2011-05-25 16:45:20 +00:00
|
|
|
#
|
|
|
|
# Compress the #data and store it for later use. If this entry's compression method
|
|
|
|
# produces a larger blob than the original data, the method is changed to CM_STORE.
|
|
|
|
#
|
2010-02-10 17:27:40 +00:00
|
|
|
def compress
|
|
|
|
@crc = Zlib.crc32(@data, 0)
|
|
|
|
case @flags.compmeth
|
|
|
|
|
|
|
|
when CM_STORE
|
|
|
|
@compdata = @data
|
|
|
|
|
|
|
|
when CM_DEFLATE
|
|
|
|
z = Zlib::Deflate.new(Zlib::BEST_COMPRESSION)
|
|
|
|
@compdata = z.deflate(@data, Zlib::FINISH)
|
|
|
|
z.close
|
2010-02-21 01:37:04 +00:00
|
|
|
@compdata = @compdata[2, @compdata.length-6]
|
2010-02-10 17:27:40 +00:00
|
|
|
|
|
|
|
else
|
|
|
|
raise 'Unsupported compression method: %u' % @flags.compmeth
|
|
|
|
end
|
|
|
|
|
2010-02-21 01:37:04 +00:00
|
|
|
# if compressing doesn't help, just store it
|
|
|
|
if (@compdata.length > @data.length)
|
|
|
|
@compdata = @data
|
|
|
|
@flags.compmeth = CM_STORE
|
|
|
|
end
|
|
|
|
|
2010-02-10 17:27:40 +00:00
|
|
|
@info = CompInfo.new(@crc, @compdata.length, @data.length)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def relative_path
|
|
|
|
if (@name[0,1] == '/')
|
|
|
|
return @name[1,@name.length]
|
|
|
|
end
|
|
|
|
@name
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2011-05-25 16:45:20 +00:00
|
|
|
#
|
|
|
|
# Return the compressed data in a format suitable for adding to an Archive
|
|
|
|
#
|
2010-02-10 17:27:40 +00:00
|
|
|
def pack
|
|
|
|
ret = ''
|
|
|
|
|
|
|
|
# - lfh 1
|
|
|
|
lfh = LocalFileHdr.new(self)
|
|
|
|
ret << lfh.pack
|
|
|
|
|
|
|
|
# - data 1
|
|
|
|
if (@compdata)
|
|
|
|
ret << @compdata
|
|
|
|
end
|
|
|
|
|
|
|
|
if (@gpbf & GPBF_USE_DATADESC)
|
|
|
|
# - data desc 1
|
|
|
|
dd = DataDesc.new(@info)
|
|
|
|
ret << dd.pack
|
|
|
|
end
|
|
|
|
|
|
|
|
ret
|
|
|
|
end
|
|
|
|
|
2010-08-19 17:04:42 +00:00
|
|
|
def inspect
|
|
|
|
"#<#{self.class} name:#{name}, data:#{@data.length} bytes>"
|
|
|
|
end
|
|
|
|
|
2010-02-10 17:27:40 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|