2013-08-27 04:26:14 +08:00
|
|
|
module Zip
|
|
|
|
# Info-ZIP Extra for Zip64 size
|
|
|
|
class ExtraField::Zip64 < ExtraField::Generic
|
|
|
|
attr_accessor :original_size, :compressed_size, :relative_header_offset, :disk_start_number
|
2013-09-28 11:45:08 +08:00
|
|
|
HEADER_ID = ['0100'].pack('H*')
|
2013-08-27 04:26:14 +08:00
|
|
|
register_map
|
|
|
|
|
|
|
|
def initialize(binstr = nil)
|
Add read/write support for zip64 extensions
This commit adds the capability of creating archives larger than
4GB via zip64 extensions. It also fixes bugs reading archives of
this size (specifically, the 64-bit offset of the local file
header was not being read from the central directory entry).
To maximize compatibility, zip64 extensions are used only when
required. Unfortunately, at the time we write a local file header,
we don't know the size of the file and thus whether a Zip64
Extended Information Extra Field will be required. Therefore
this commit writes a 'placeholder' extra field to reserve space
for the zip64 entry, which will be written if necessary when
we update the local entry with the final sizes and CRC. I use
the signature "\x99\x99" for this field, following the example
of DotNetZip which does the same.
This commit also adds a rake task, zip64_full_test, which
fully tests zip64 by actually creating and verifying a 4GB zip
file. Please note, however, that this test requires UnZip
version 6.00 or newer, which may not be supplied by your OS.
This test doesn't run along with the main unit tests because
it takes a few minutes to complete.
2013-09-28 10:41:00 +08:00
|
|
|
@content = nil # unparsed binary; we don't actually know what this contains
|
|
|
|
# without looking for FFs in the associated file header
|
|
|
|
# call parse after initializing with a binary string
|
2013-08-27 04:26:14 +08:00
|
|
|
@original_size = nil
|
|
|
|
@compressed_size = nil
|
|
|
|
@relative_header_offset = nil
|
|
|
|
@disk_start_number = nil
|
2015-03-21 15:45:46 +08:00
|
|
|
binstr && merge(binstr)
|
2013-08-27 04:26:14 +08:00
|
|
|
end
|
|
|
|
|
Add read/write support for zip64 extensions
This commit adds the capability of creating archives larger than
4GB via zip64 extensions. It also fixes bugs reading archives of
this size (specifically, the 64-bit offset of the local file
header was not being read from the central directory entry).
To maximize compatibility, zip64 extensions are used only when
required. Unfortunately, at the time we write a local file header,
we don't know the size of the file and thus whether a Zip64
Extended Information Extra Field will be required. Therefore
this commit writes a 'placeholder' extra field to reserve space
for the zip64 entry, which will be written if necessary when
we update the local entry with the final sizes and CRC. I use
the signature "\x99\x99" for this field, following the example
of DotNetZip which does the same.
This commit also adds a rake task, zip64_full_test, which
fully tests zip64 by actually creating and verifying a 4GB zip
file. Please note, however, that this test requires UnZip
version 6.00 or newer, which may not be supplied by your OS.
This test doesn't run along with the main unit tests because
it takes a few minutes to complete.
2013-09-28 10:41:00 +08:00
|
|
|
def ==(other)
|
|
|
|
other.original_size == @original_size &&
|
|
|
|
other.compressed_size == @compressed_size &&
|
2015-03-24 00:10:39 +08:00
|
|
|
other.relative_header_offset == @relative_header_offset &&
|
|
|
|
other.disk_start_number == @disk_start_number
|
Add read/write support for zip64 extensions
This commit adds the capability of creating archives larger than
4GB via zip64 extensions. It also fixes bugs reading archives of
this size (specifically, the 64-bit offset of the local file
header was not being read from the central directory entry).
To maximize compatibility, zip64 extensions are used only when
required. Unfortunately, at the time we write a local file header,
we don't know the size of the file and thus whether a Zip64
Extended Information Extra Field will be required. Therefore
this commit writes a 'placeholder' extra field to reserve space
for the zip64 entry, which will be written if necessary when
we update the local entry with the final sizes and CRC. I use
the signature "\x99\x99" for this field, following the example
of DotNetZip which does the same.
This commit also adds a rake task, zip64_full_test, which
fully tests zip64 by actually creating and verifying a 4GB zip
file. Please note, however, that this test requires UnZip
version 6.00 or newer, which may not be supplied by your OS.
This test doesn't run along with the main unit tests because
it takes a few minutes to complete.
2013-09-28 10:41:00 +08:00
|
|
|
end
|
|
|
|
|
2013-08-27 04:26:14 +08:00
|
|
|
def merge(binstr)
|
|
|
|
return if binstr.empty?
|
Add read/write support for zip64 extensions
This commit adds the capability of creating archives larger than
4GB via zip64 extensions. It also fixes bugs reading archives of
this size (specifically, the 64-bit offset of the local file
header was not being read from the central directory entry).
To maximize compatibility, zip64 extensions are used only when
required. Unfortunately, at the time we write a local file header,
we don't know the size of the file and thus whether a Zip64
Extended Information Extra Field will be required. Therefore
this commit writes a 'placeholder' extra field to reserve space
for the zip64 entry, which will be written if necessary when
we update the local entry with the final sizes and CRC. I use
the signature "\x99\x99" for this field, following the example
of DotNetZip which does the same.
This commit also adds a rake task, zip64_full_test, which
fully tests zip64 by actually creating and verifying a 4GB zip
file. Please note, however, that this test requires UnZip
version 6.00 or newer, which may not be supplied by your OS.
This test doesn't run along with the main unit tests because
it takes a few minutes to complete.
2013-09-28 10:41:00 +08:00
|
|
|
_, @content = initial_parse(binstr)
|
|
|
|
end
|
|
|
|
|
|
|
|
# pass the values from the base entry (if applicable)
|
|
|
|
# wider values are only present in the extra field for base values set to all FFs
|
|
|
|
# returns the final values for the four attributes (from the base or zip64 extra record)
|
|
|
|
def parse(original_size, compressed_size, relative_header_offset = nil, disk_start_number = nil)
|
|
|
|
@original_size = extract(8, 'Q<') if original_size == 0xFFFFFFFF
|
|
|
|
@compressed_size = extract(8, 'Q<') if compressed_size == 0xFFFFFFFF
|
|
|
|
@relative_header_offset = extract(8, 'Q<') if relative_header_offset && relative_header_offset == 0xFFFFFFFF
|
|
|
|
@disk_start_number = extract(4, 'V') if disk_start_number && disk_start_number == 0xFFFF
|
|
|
|
@content = nil
|
|
|
|
[@original_size || original_size,
|
|
|
|
@compressed_size || compressed_size,
|
|
|
|
@relative_header_offset || relative_header_offset,
|
|
|
|
@disk_start_number || disk_start_number]
|
|
|
|
end
|
|
|
|
|
|
|
|
def extract(size, format)
|
|
|
|
@content.slice!(0, size).unpack(format)[0]
|
2013-08-27 04:26:14 +08:00
|
|
|
end
|
Add read/write support for zip64 extensions
This commit adds the capability of creating archives larger than
4GB via zip64 extensions. It also fixes bugs reading archives of
this size (specifically, the 64-bit offset of the local file
header was not being read from the central directory entry).
To maximize compatibility, zip64 extensions are used only when
required. Unfortunately, at the time we write a local file header,
we don't know the size of the file and thus whether a Zip64
Extended Information Extra Field will be required. Therefore
this commit writes a 'placeholder' extra field to reserve space
for the zip64 entry, which will be written if necessary when
we update the local entry with the final sizes and CRC. I use
the signature "\x99\x99" for this field, following the example
of DotNetZip which does the same.
This commit also adds a rake task, zip64_full_test, which
fully tests zip64 by actually creating and verifying a 4GB zip
file. Please note, however, that this test requires UnZip
version 6.00 or newer, which may not be supplied by your OS.
This test doesn't run along with the main unit tests because
it takes a few minutes to complete.
2013-09-28 10:41:00 +08:00
|
|
|
private :extract
|
2013-08-27 04:26:14 +08:00
|
|
|
|
|
|
|
def pack_for_local
|
Add read/write support for zip64 extensions
This commit adds the capability of creating archives larger than
4GB via zip64 extensions. It also fixes bugs reading archives of
this size (specifically, the 64-bit offset of the local file
header was not being read from the central directory entry).
To maximize compatibility, zip64 extensions are used only when
required. Unfortunately, at the time we write a local file header,
we don't know the size of the file and thus whether a Zip64
Extended Information Extra Field will be required. Therefore
this commit writes a 'placeholder' extra field to reserve space
for the zip64 entry, which will be written if necessary when
we update the local entry with the final sizes and CRC. I use
the signature "\x99\x99" for this field, following the example
of DotNetZip which does the same.
This commit also adds a rake task, zip64_full_test, which
fully tests zip64 by actually creating and verifying a 4GB zip
file. Please note, however, that this test requires UnZip
version 6.00 or newer, which may not be supplied by your OS.
This test doesn't run along with the main unit tests because
it takes a few minutes to complete.
2013-09-28 10:41:00 +08:00
|
|
|
# local header entries must contain original size and compressed size; other fields do not apply
|
|
|
|
return '' unless @original_size && @compressed_size
|
2015-03-21 16:27:44 +08:00
|
|
|
[@original_size, @compressed_size].pack('Q<Q<')
|
2013-08-27 04:26:14 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def pack_for_c_dir
|
Add read/write support for zip64 extensions
This commit adds the capability of creating archives larger than
4GB via zip64 extensions. It also fixes bugs reading archives of
this size (specifically, the 64-bit offset of the local file
header was not being read from the central directory entry).
To maximize compatibility, zip64 extensions are used only when
required. Unfortunately, at the time we write a local file header,
we don't know the size of the file and thus whether a Zip64
Extended Information Extra Field will be required. Therefore
this commit writes a 'placeholder' extra field to reserve space
for the zip64 entry, which will be written if necessary when
we update the local entry with the final sizes and CRC. I use
the signature "\x99\x99" for this field, following the example
of DotNetZip which does the same.
This commit also adds a rake task, zip64_full_test, which
fully tests zip64 by actually creating and verifying a 4GB zip
file. Please note, however, that this test requires UnZip
version 6.00 or newer, which may not be supplied by your OS.
This test doesn't run along with the main unit tests because
it takes a few minutes to complete.
2013-09-28 10:41:00 +08:00
|
|
|
# central directory entries contain only fields that didn't fit in the main entry part
|
|
|
|
packed = ''.force_encoding('BINARY')
|
2015-03-21 16:27:44 +08:00
|
|
|
packed << [@original_size].pack('Q<') if @original_size
|
|
|
|
packed << [@compressed_size].pack('Q<') if @compressed_size
|
|
|
|
packed << [@relative_header_offset].pack('Q<') if @relative_header_offset
|
|
|
|
packed << [@disk_start_number].pack('V') if @disk_start_number
|
Add read/write support for zip64 extensions
This commit adds the capability of creating archives larger than
4GB via zip64 extensions. It also fixes bugs reading archives of
this size (specifically, the 64-bit offset of the local file
header was not being read from the central directory entry).
To maximize compatibility, zip64 extensions are used only when
required. Unfortunately, at the time we write a local file header,
we don't know the size of the file and thus whether a Zip64
Extended Information Extra Field will be required. Therefore
this commit writes a 'placeholder' extra field to reserve space
for the zip64 entry, which will be written if necessary when
we update the local entry with the final sizes and CRC. I use
the signature "\x99\x99" for this field, following the example
of DotNetZip which does the same.
This commit also adds a rake task, zip64_full_test, which
fully tests zip64 by actually creating and verifying a 4GB zip
file. Please note, however, that this test requires UnZip
version 6.00 or newer, which may not be supplied by your OS.
This test doesn't run along with the main unit tests because
it takes a few minutes to complete.
2013-09-28 10:41:00 +08:00
|
|
|
packed
|
2013-08-27 04:26:14 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|