This commit is contained in:
Alexander Simonov 2014-01-24 11:37:38 +02:00
parent 4f9b642644
commit ec81c30382
19 changed files with 138 additions and 115 deletions

View File

@ -116,32 +116,6 @@ end
File.open(new_path, "w") {|f| f.write(buffer.string) } File.open(new_path, "w") {|f| f.write(buffer.string) }
``` ```
## Further Documentation
There is more than one way to access or create a zip archive with
rubyzip. The basic API is modeled after the classes in
java.util.zip from the Java SDK. This means there are classes such
as Zip::InputStream, Zip::OutputStream and
Zip::File. Zip::InputStream provides a basic interface for
iterating through the entries in a zip archive and reading from the
entries in the same way as from a regular File or IO
object. OutputStream is the corresponding basic output
facility. Zip::File provides a mean for accessing the archives
central directory and provides means for accessing any entry without
having to iterate through the archive. Unlike Java's
java.util.zip.ZipFile rubyzip's Zip::File is mutable, which means
it can be used to change zip files as well.
Another way to access a zip archive with rubyzip is to use rubyzip's
Zip::FileSystem API. Using this API files can be read from and
written to the archive in much the same manner as ruby's builtin
classes allows files to be read from and written to the file system.
For details about the specific behaviour of classes and methods refer
to the test suite. Finally you can generate the rdoc documentation or
visit http://rubyzip.sourceforge.net.
## Configuration ## Configuration
By default, rubyzip will not overwrite files if they already exist inside of the extracted path. To change this behavior, you may specify a configuration option like so: By default, rubyzip will not overwrite files if they already exist inside of the extracted path. To change this behavior, you may specify a configuration option like so:
@ -183,6 +157,14 @@ All settings in same time
end end
``` ```
By default Zip64 support is disabled for writing. To enable it do next:
```ruby
Zip.write_zip64_support = true
```
_NOTE_: If you will enable Zip64 writing then you will need zip extractor with Zip64 support to extract archive.
## Developing ## Developing
To run tests you need run next commands: To run tests you need run next commands:

1
TODO
View File

@ -4,7 +4,6 @@
* Suggestion: Add ZipFile/ZipInputStream example that demonstrates extracting all entries. * Suggestion: Add ZipFile/ZipInputStream example that demonstrates extracting all entries.
* Suggestion: ZipFile#extract destination should default to "." * Suggestion: ZipFile#extract destination should default to "."
* Suggestion: ZipEntry should have extract(), get_input_stream() methods etc * Suggestion: ZipEntry should have extract(), get_input_stream() methods etc
* Suggestion: ZipInputStream/ZipOutputStream should accept an IO object in addition to a filename.
* (is buffering used anywhere with write?) * (is buffering used anywhere with write?)
* Inflater.sysread should pass the buffer to produce_input. * Inflater.sysread should pass the buffer to produce_input.
* Implement ZipFsDir.glob * Implement ZipFsDir.glob

View File

@ -34,7 +34,7 @@ end
module Zip module Zip
extend self extend self
attr_accessor :unicode_names, :on_exists_proc, :continue_on_exists_proc, :sort_entries, :default_compression attr_accessor :unicode_names, :on_exists_proc, :continue_on_exists_proc, :sort_entries, :default_compression, :write_zip64_support
def reset! def reset!
@_ran_once = false @_ran_once = false
@ -43,6 +43,7 @@ module Zip
@continue_on_exists_proc = false @continue_on_exists_proc = false
@sort_entries = false @sort_entries = false
@default_compression = ::Zlib::DEFAULT_COMPRESSION @default_compression = ::Zlib::DEFAULT_COMPRESSION
@write_zip64_support = false
end end
def setup def setup

View File

@ -93,7 +93,7 @@ module Zip
@size_in_bytes = Entry.read_zip_64_long(buf) @size_in_bytes = Entry.read_zip_64_long(buf)
@cdir_offset = Entry.read_zip_64_long(buf) @cdir_offset = Entry.read_zip_64_long(buf)
@zip_64_extensible = buf.slice!(0, buf.bytesize) @zip_64_extensible = buf.slice!(0, buf.bytesize)
raise ZipError, "Zip consistency problem while reading eocd structure" unless buf.size == 0 raise Error, "Zip consistency problem while reading eocd structure" unless buf.size == 0
end end
def read_e_o_c_d(buf) #:nodoc: def read_e_o_c_d(buf) #:nodoc:
@ -110,14 +110,14 @@ module Zip
else else
buf.read(comment_length) buf.read(comment_length)
end end
raise ZipError, "Zip consistency problem while reading eocd structure" unless buf.size == 0 raise Error, "Zip consistency problem while reading eocd structure" unless buf.size == 0
end end
def read_central_directory_entries(io) #:nodoc: def read_central_directory_entries(io) #:nodoc:
begin begin
io.seek(@cdir_offset, IO::SEEK_SET) io.seek(@cdir_offset, IO::SEEK_SET)
rescue Errno::EINVAL rescue Errno::EINVAL
raise ZipError, "Zip consistency problem while reading central directory entry" raise Error, "Zip consistency problem while reading central directory entry"
end end
@entry_set = EntrySet.new @entry_set = EntrySet.new
@size.times do @size.times do
@ -137,7 +137,7 @@ module Zip
def get_e_o_c_d(buf) #:nodoc: def get_e_o_c_d(buf) #:nodoc:
sig_index = buf.rindex([END_OF_CDS].pack('V')) sig_index = buf.rindex([END_OF_CDS].pack('V'))
raise ZipError, "Zip end of central directory signature not found" unless sig_index raise Error, "Zip end of central directory signature not found" unless sig_index
buf = buf.slice!((sig_index + 4)..(buf.bytesize)) buf = buf.slice!((sig_index + 4)..(buf.bytesize))
def buf.read(count) def buf.read(count)
@ -162,9 +162,9 @@ module Zip
def get_64_e_o_c_d(buf) #:nodoc: def get_64_e_o_c_d(buf) #:nodoc:
zip_64_start = buf.rindex([ZIP64_END_OF_CDS].pack('V')) zip_64_start = buf.rindex([ZIP64_END_OF_CDS].pack('V'))
raise ZipError, "Zip64 end of central directory signature not found" unless zip_64_start raise Error, "Zip64 end of central directory signature not found" unless zip_64_start
zip_64_locator = buf.rindex([ZIP64_EOCD_LOCATOR].pack('V')) zip_64_locator = buf.rindex([ZIP64_EOCD_LOCATOR].pack('V'))
raise ZipError, "Zip64 end of central directory signature locator not found" unless zip_64_locator raise Error, "Zip64 end of central directory signature locator not found" unless zip_64_locator
buf = buf.slice!((zip_64_start + 4)..zip_64_locator) buf = buf.slice!((zip_64_start + 4)..zip_64_locator)
def buf.read(count) def buf.read(count)
@ -189,7 +189,7 @@ module Zip
cdir = new cdir = new
cdir.read_from_stream(io) cdir.read_from_stream(io)
return cdir return cdir
rescue ZipError rescue Error
return nil return nil
end end

View File

@ -46,7 +46,7 @@ module Zip
def check_name(name) def check_name(name)
if name.start_with?('/') if name.start_with?('/')
raise ::Zip::ZipEntryNameError, "Illegal ZipEntry name '#{name}', name must not start with /" raise ::Zip::EntryNameError, "Illegal ZipEntry name '#{name}', name must not start with /"
end end
end end
@ -92,7 +92,7 @@ module Zip
end end
def file_type_is?(type) def file_type_is?(type)
raise ZipInternalError, "current filetype is unknown: #{self.inspect}" unless @ftype raise InternalError, "current filetype is unknown: #{self.inspect}" unless @ftype
@ftype == type @ftype == type
end end
@ -132,7 +132,7 @@ module Zip
def verify_local_header_size! def verify_local_header_size!
return if @local_header_size == 0 return if @local_header_size == 0
new_size = calculate_local_header_size new_size = calculate_local_header_size
raise ZipError, "local header size changed (#{@local_header_size} -> #{new_size})" if @local_header_size != new_size raise Error, "local header size changed (#{@local_header_size} -> #{new_size})" if @local_header_size != new_size
end end
def cdir_header_size #:nodoc:all def cdir_header_size #:nodoc:all
@ -185,15 +185,15 @@ module Zip
entry = new(path) entry = new(path)
entry.read_c_dir_entry(io) entry.read_c_dir_entry(io)
entry entry
rescue ZipError rescue Error
nil nil
end end
def read_local_entry(io) def read_local_entry(io)
entry = self.new entry = self.new(io)
entry.read_local_entry(io) entry.read_local_entry(io)
entry entry
rescue ZipError rescue Error
nil nil
end end
@ -222,13 +222,13 @@ module Zip
static_sized_fields_buf = io.read(::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH) static_sized_fields_buf = io.read(::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH)
unless static_sized_fields_buf.bytesize == ::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH unless static_sized_fields_buf.bytesize == ::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH
raise ZipError, "Premature end of file. Not enough data for zip entry local header" raise Error, "Premature end of file. Not enough data for zip entry local header"
end end
unpack_local_entry(static_sized_fields_buf) unpack_local_entry(static_sized_fields_buf)
unless @header_signature == ::Zip::LOCAL_ENTRY_SIGNATURE unless @header_signature == ::Zip::LOCAL_ENTRY_SIGNATURE
raise ::Zip::ZipError, "Zip local header magic not found at location '#{local_header_offset}'" raise ::Zip::Error, "Zip local header magic not found at location '#{local_header_offset}'"
end end
set_time(@last_mod_date, @last_mod_time) set_time(@last_mod_date, @last_mod_time)
@ -238,7 +238,7 @@ module Zip
@name.gsub!('\\', '/') @name.gsub!('\\', '/')
if extra && extra.bytesize != @extra_length if extra && extra.bytesize != @extra_length
raise ::Zip::ZipError, "Truncated local zip entry header" raise ::Zip::Error, "Truncated local zip entry header"
else else
if ::Zip::ExtraField === @extra if ::Zip::ExtraField === @extra
@extra.merge(extra) @extra.merge(extra)
@ -332,19 +332,19 @@ module Zip
def check_c_dir_entry_static_header_length(buf) def check_c_dir_entry_static_header_length(buf)
unless buf.bytesize == ::Zip::CDIR_ENTRY_STATIC_HEADER_LENGTH unless buf.bytesize == ::Zip::CDIR_ENTRY_STATIC_HEADER_LENGTH
raise ZipError, 'Premature end of file. Not enough data for zip cdir entry header' raise Error, 'Premature end of file. Not enough data for zip cdir entry header'
end end
end end
def check_c_dir_entry_signature def check_c_dir_entry_signature
unless header_signature == ::Zip::CENTRAL_DIRECTORY_ENTRY_SIGNATURE unless header_signature == ::Zip::CENTRAL_DIRECTORY_ENTRY_SIGNATURE
raise ZipError, "Zip local header magic not found at location '#{local_header_offset}'" raise Error, "Zip local header magic not found at location '#{local_header_offset}'"
end end
end end
def check_c_dir_entry_comment_size def check_c_dir_entry_comment_size
unless @comment && @comment.bytesize == @comment_length unless @comment && @comment.bytesize == @comment_length
raise ::Zip::ZipError, "Truncated cdir zip entry header" raise ::Zip::Error, "Truncated cdir zip entry header"
end end
end end
@ -427,7 +427,10 @@ module Zip
(zip64 && zip64.disk_start_number) ? 0xFFFF : 0, # disk number start (zip64 && zip64.disk_start_number) ? 0xFFFF : 0, # disk number start
@internal_file_attributes, # file type (binary=0, text=1) @internal_file_attributes, # file type (binary=0, text=1)
@external_file_attributes, # native filesystem attributes @external_file_attributes, # native filesystem attributes
(zip64 && zip64.relative_header_offset) ? 0xFFFFFFFF : @local_header_offset (zip64 && zip64.relative_header_offset) ? 0xFFFFFFFF : @local_header_offset,
@name,
@extra,
@comment
].pack('VCCvvvvvVVVvvvvvVV') ].pack('VCCvvvvvVVVvvvvvVV')
end end
@ -516,7 +519,7 @@ module Zip
end end
:file :file
when 'directory' when 'directory'
@name += "/" unless name_is_directory? @name += '/' unless name_is_directory?
:directory :directory
when 'link' when 'link'
if name_is_directory? if name_is_directory?
@ -568,7 +571,7 @@ module Zip
def create_file(dest_path, continue_on_exists_proc = proc { Zip.continue_on_exists_proc }) def create_file(dest_path, continue_on_exists_proc = proc { Zip.continue_on_exists_proc })
if ::File.exists?(dest_path) && !yield(self, dest_path) if ::File.exists?(dest_path) && !yield(self, dest_path)
raise ::Zip::ZipDestinationFileExistsError, raise ::Zip::DestinationFileExistsError,
"Destination '#{dest_path}' already exists" "Destination '#{dest_path}' already exists"
end end
::File.open(dest_path, "wb") do |os| ::File.open(dest_path, "wb") do |os|
@ -589,7 +592,7 @@ module Zip
if block_given? && yield(self, dest_path) if block_given? && yield(self, dest_path)
::FileUtils::rm_f dest_path ::FileUtils::rm_f dest_path
else else
raise ::Zip::ZipDestinationFileExistsError, raise ::Zip::DestinationFileExistsError,
"Cannot create directory '#{dest_path}'. "+ "Cannot create directory '#{dest_path}'. "+
"A file already exists with that name" "A file already exists with that name"
end end
@ -614,12 +617,12 @@ module Zip
if ::File.readlink(dest_path) == linkto if ::File.readlink(dest_path) == linkto
return return
else else
raise ZipDestinationFileExistsError, raise ::Zip::DestinationFileExistsError,
"Cannot create symlink '#{dest_path}'. "+ "Cannot create symlink '#{dest_path}'. "+
"A symlink already exists with that name" "A symlink already exists with that name"
end end
else else
raise ZipDestinationFileExistsError, raise ::Zip::DestinationFileExistsError,
"Cannot create symlink '#{dest_path}'. "+ "Cannot create symlink '#{dest_path}'. "+
"A file already exists with that name" "A file already exists with that name"
end end
@ -642,6 +645,7 @@ module Zip
# create a zip64 extra information field if we need one # create a zip64 extra information field if we need one
def prep_zip64_extra(for_local_header) #:nodoc:all def prep_zip64_extra(for_local_header) #:nodoc:all
return unless ::Zip.write_zip64_support
need_zip64 = @size >= 0xFFFFFFFF || @compressed_size >= 0xFFFFFFFF need_zip64 = @size >= 0xFFFFFFFF || @compressed_size >= 0xFFFFFFFF
unless for_local_header unless for_local_header
need_zip64 ||= @local_header_offset >= 0xFFFFFFFF need_zip64 ||= @local_header_offset >= 0xFFFFFFFF

View File

@ -1,8 +1,8 @@
module Zip module Zip
class ZipError < StandardError; end class Error < StandardError; end
class ZipEntryExistsError < ZipError; end class EntryExistsError < Error; end
class ZipDestinationFileExistsError < ZipError; end class DestinationFileExistsError < Error; end
class ZipCompressionMethodError < ZipError; end class CompressionMethodError < Error; end
class ZipEntryNameError < ZipError; end class EntryNameError < Error; end
class ZipInternalError < ZipError; end class InternalError < Error; end
end end

View File

@ -52,7 +52,7 @@ module Zip
def create(name) def create(name)
unless field_class = ID_MAP.values.find { |k| k.name == name } unless field_class = ID_MAP.values.find { |k| k.name == name }
raise ZipError, "Unknown extra field '#{name}'" raise Error, "Unknown extra field '#{name}'"
end end
self[name] = field_class.new self[name] = field_class.new
end end

View File

@ -79,7 +79,7 @@ module Zip
when create when create
@entry_set = EntrySet.new @entry_set = EntrySet.new
else else
raise ZipError, "File #{file_name} not found" raise Error, "File #{file_name} not found"
end end
@stored_entries = @entry_set.dup @stored_entries = @entry_set.dup
@stored_comment = @comment @stored_comment = @comment
@ -94,15 +94,12 @@ module Zip
# ruby's builtin File.open method. # ruby's builtin File.open method.
def open(file_name, create = nil) def open(file_name, create = nil)
zf = ::Zip::File.new(file_name, create) zf = ::Zip::File.new(file_name, create)
if block_given? return zf unless block_given?
begin begin
yield zf yield zf
ensure ensure
zf.close zf.close
end end
else
zf
end
end end
# Same as #open. But outputs data to a buffer instead of a file # Same as #open. But outputs data to a buffer instead of a file
@ -197,7 +194,7 @@ module Zip
# Splits an archive into parts with segment size # Splits an archive into parts with segment size
def split(zip_file_name, segment_size = MAX_SEGMENT_SIZE, delete_zip_file = true, partial_zip_file_name = nil) def split(zip_file_name, segment_size = MAX_SEGMENT_SIZE, delete_zip_file = true, partial_zip_file_name = nil)
raise ZipError, "File #{zip_file_name} not found" unless ::File.exists?(zip_file_name) raise Error, "File #{zip_file_name} not found" unless ::File.exists?(zip_file_name)
raise Errno::ENOENT, zip_file_name unless ::File.readable?(zip_file_name) raise Errno::ENOENT, zip_file_name unless ::File.readable?(zip_file_name)
zip_file_size = ::File.size(zip_file_name) zip_file_size = ::File.size(zip_file_name)
segment_size = get_segment_size_for_split(segment_size) segment_size = get_segment_size_for_split(segment_size)
@ -259,12 +256,13 @@ module Zip
end end
# Convenience method for adding the contents of a file to the archive # Convenience method for adding the contents of a file to the archive
def add(entry, srcPath, &continue_on_exists_proc) def add(entry, src_path, &continue_on_exists_proc)
continue_on_exists_proc ||= proc { Zip.continue_on_exists_proc } continue_on_exists_proc ||= proc { ::Zip.continue_on_exists_proc }
check_entry_exists(entry, continue_on_exists_proc, "add") check_entry_exists(entry, continue_on_exists_proc, "add")
newEntry = entry.kind_of?(Entry) ? entry : Entry.new(@name, entry.to_s) new_entry = entry.kind_of?(::Zip::Entry) ? entry : ::Zip::Entry.new(@name, entry.to_s)
newEntry.gather_fileinfo_from_srcpath(srcPath) new_entry.gather_fileinfo_from_srcpath(src_path)
@entry_set << newEntry new_entry.dirty = true
@entry_set << new_entry
end end
# Removes the specified entry. # Removes the specified entry.
@ -299,9 +297,9 @@ module Zip
# Commits changes that has been made since the previous commit to # Commits changes that has been made since the previous commit to
# the zip archive. # the zip archive.
def commit def commit
return if !commit_required? return unless commit_required?
on_success_replace do |tmpFile| on_success_replace do |tmp_file|
::Zip::OutputStream.open(tmpFile) do |zos| ::Zip::OutputStream.open(tmp_file) do |zos|
@entry_set.each do |e| @entry_set.each do |e|
e.write_to_zip_output_stream(zos) e.write_to_zip_output_stream(zos)
e.dirty = false e.dirty = false
@ -315,7 +313,7 @@ module Zip
# Write buffer write changes to buffer and return # Write buffer write changes to buffer and return
def write_buffer(io) def write_buffer(io)
OutputStream.write_buffer(io) do |zos| ::Zip::OutputStream.write_buffer(io) do |zos|
@entry_set.each { |e| e.write_to_zip_output_stream(zos) } @entry_set.each { |e| e.write_to_zip_output_stream(zos) }
zos.comment = comment zos.comment = comment
end end
@ -332,7 +330,7 @@ module Zip
@entry_set.each do |e| @entry_set.each do |e|
return true if e.dirty return true if e.dirty
end end
@comment != @stored_comment || @entry_set != @stored_entries || @create == File::CREATE @comment != @stored_comment || @entry_set != @stored_entries || @create == ::Zip::File::CREATE
end end
# Searches for entry with the specified name. Returns nil if # Searches for entry with the specified name. Returns nil if
@ -389,7 +387,7 @@ module Zip
if continue_on_exists_proc.call if continue_on_exists_proc.call
remove get_entry(entryName) remove get_entry(entryName)
else else
raise ZipEntryExistsError, raise ::Zip::EntryExistsError,
procedureName + " failed. Entry #{entryName} already exists" procedureName + " failed. Entry #{entryName} already exists"
end end
end end

View File

@ -138,7 +138,7 @@ module Zip
when @current_entry.compression_method == ::Zip::Entry::DEFLATED when @current_entry.compression_method == ::Zip::Entry::DEFLATED
::Zip::Inflater.new(@archive_io) ::Zip::Inflater.new(@archive_io)
else else
raise ZipCompressionMethodError, raise ::Zip::CompressionMethodError,
"Unsupported compression method #{@current_entry.compression_method}" "Unsupported compression method #{@current_entry.compression_method}"
end end
end end

View File

@ -84,26 +84,26 @@ module Zip
# Closes the current entry and opens a new for writing. # Closes the current entry and opens a new for writing.
# +entry+ can be a ZipEntry object or a string. # +entry+ can be a ZipEntry object or a string.
def put_next_entry(entryname, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zip.default_compression) def put_next_entry(entry_name, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zip.default_compression)
raise ZipError, "zip stream is closed" if @closed raise Error, "zip stream is closed" if @closed
if entryname.kind_of?(Entry) if entry_name.kind_of?(Entry)
new_entry = entryname new_entry = entry_name
else else
new_entry = Entry.new(@file_name, entryname.to_s) new_entry = Entry.new(@file_name, entry_name.to_s)
end end
new_entry.comment = comment if !comment.nil? new_entry.comment = comment unless comment.nil?
if (!extra.nil?) unless extra.nil?
new_entry.extra = ExtraField === extra ? extra : ExtraField.new(extra.to_s) new_entry.extra = ExtraField === extra ? extra : ExtraField.new(extra.to_s)
end end
new_entry.compression_method = compression_method if !compression_method.nil? new_entry.compression_method = compression_method unless compression_method.nil?
init_next_entry(new_entry, level) init_next_entry(new_entry, level)
@current_entry = new_entry @current_entry = new_entry
end end
def copy_raw_entry(entry) def copy_raw_entry(entry)
entry = entry.dup entry = entry.dup
raise ZipError, "zip stream is closed" if @closed raise Error, "zip stream is closed" if @closed
raise ZipError, "entry is not a ZipEntry" unless entry.is_a?(Entry) raise Error, "entry is not a ZipEntry" unless entry.is_a?(Entry)
finalize_current_entry finalize_current_entry
@entry_set << entry @entry_set << entry
src_pos = entry.local_entry_offset src_pos = entry.local_entry_offset
@ -126,7 +126,7 @@ module Zip
@current_entry.size = @compressor.size @current_entry.size = @compressor.size
@current_entry.crc = @compressor.crc @current_entry.crc = @compressor.crc
@current_entry = nil @current_entry = nil
@compressor = NullCompressor.instance @compressor = ::Zip::NullCompressor.instance
end end
def init_next_entry(entry, level = Zip.default_compression) def init_next_entry(entry, level = Zip.default_compression)
@ -139,11 +139,11 @@ module Zip
def get_compressor(entry, level) def get_compressor(entry, level)
case entry.compression_method case entry.compression_method
when Entry::DEFLATED then when Entry::DEFLATED then
Deflater.new(@output_stream, level) ::Zip::Deflater.new(@output_stream, level)
when Entry::STORED then when Entry::STORED then
PassThruCompressor.new(@output_stream) ::Zip::PassThruCompressor.new(@output_stream)
else else
raise ZipCompressionMethodError, raise ::Zip::CompressionMethodError,
"Invalid compression method: '#{entry.compression_method}'" "Invalid compression method: '#{entry.compression_method}'"
end end
end end

View File

@ -67,7 +67,7 @@ class ZipCentralDirectoryEntryTest < MiniTest::Unit::TestCase
entry = ::Zip::Entry.new entry = ::Zip::Entry.new
entry.read_c_dir_entry(fragment) entry.read_c_dir_entry(fragment)
fail "ZipError expected" fail "ZipError expected"
rescue ::Zip::ZipError rescue ::Zip::Error
end end
end end

View File

@ -23,7 +23,7 @@ class ZipCentralDirectoryTest < MiniTest::Unit::TestCase
cdir.read_from_stream(zipFile) cdir.read_from_stream(zipFile)
} }
fail "ZipError expected!" fail "ZipError expected!"
rescue ::Zip::ZipError rescue ::Zip::Error
end end
def test_ReadFromTruncatedZipFile def test_ReadFromTruncatedZipFile
@ -34,7 +34,7 @@ class ZipCentralDirectoryTest < MiniTest::Unit::TestCase
entry = ::Zip::CentralDirectory.new entry = ::Zip::CentralDirectory.new
entry.read_from_stream(fragment) entry.read_from_stream(fragment)
fail "ZipError expected" fail "ZipError expected"
rescue ::Zip::ZipError rescue ::Zip::Error
end end
def test_write_to_stream def test_write_to_stream
@ -50,6 +50,7 @@ class ZipCentralDirectoryTest < MiniTest::Unit::TestCase
end end
def test_write64_to_stream def test_write64_to_stream
::Zip.write_zip64_support = true
entries = [::Zip::Entry.new("file.zip", "file1-little", "comment1", "", 200, 101, ::Zip::Entry::STORED, 200), entries = [::Zip::Entry.new("file.zip", "file1-little", "comment1", "", 200, 101, ::Zip::Entry::STORED, 200),
::Zip::Entry.new("file.zip", "file2-big", "comment2", "", 18000000000, 102, ::Zip::Entry::DEFLATED, 20000000000), ::Zip::Entry.new("file.zip", "file2-big", "comment2", "", 18000000000, 102, ::Zip::Entry::DEFLATED, 20000000000),
::Zip::Entry.new("file.zip", "file3-alsobig", "comment3", "", 15000000000, 103, ::Zip::Entry::DEFLATED, 21000000000), ::Zip::Entry.new("file.zip", "file3-alsobig", "comment3", "", 15000000000, 103, ::Zip::Entry::DEFLATED, 21000000000),

View File

@ -127,6 +127,6 @@ class ZipEntryTest < MiniTest::Unit::TestCase
end end
def test_entry_name_cannot_start_with_slash def test_entry_name_cannot_start_with_slash
assert_raises(::Zip::ZipEntryNameError) { ::Zip::Entry.new("zf.zip", "/hej/der") } assert_raises(::Zip::EntryNameError) { ::Zip::Entry.new("zf.zip", "/hej/der") }
end end
end end

View File

@ -36,7 +36,7 @@ class ZipFileExtractDirectoryTest < MiniTest::Unit::TestCase
def test_extractDirectoryExistsAsFile def test_extractDirectoryExistsAsFile
File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" }
assert_raises(::Zip::ZipDestinationFileExistsError) { extract_test_dir } assert_raises(::Zip::DestinationFileExistsError) { extract_test_dir }
end end
def test_extractDirectoryExistsAsFileOverwrite def test_extractDirectoryExistsAsFileOverwrite

View File

@ -36,7 +36,7 @@ class ZipFileExtractTest < MiniTest::Unit::TestCase
writtenText = "written text" writtenText = "written text"
::File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } ::File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) }
assert_raises(::Zip::ZipDestinationFileExistsError) { assert_raises(::Zip::DestinationFileExistsError) {
::Zip::File.open(TEST_ZIP.zip_name) { |zf| ::Zip::File.open(TEST_ZIP.zip_name) { |zf|
zf.extract(zf.entries.first, EXTRACTED_FILENAME) zf.extract(zf.entries.first, EXTRACTED_FILENAME)
} }

View File

@ -4,6 +4,10 @@ require 'test_helper'
class ZipFileTest < MiniTest::Unit::TestCase class ZipFileTest < MiniTest::Unit::TestCase
include CommonZipFileFixture include CommonZipFileFixture
def teardown
::Zip.write_zip64_support = false
end
def test_createFromScratchToBuffer def test_createFromScratchToBuffer
comment = "a short comment" comment = "a short comment"
@ -115,7 +119,7 @@ class ZipFileTest < MiniTest::Unit::TestCase
end end
def test_addExistingEntryName def test_addExistingEntryName
assert_raises(::Zip::ZipEntryExistsError) { assert_raises(::Zip::EntryExistsError) {
::Zip::File.open(TEST_ZIP.zip_name) { ::Zip::File.open(TEST_ZIP.zip_name) {
|zf| |zf|
zf.add(zf.entries.first.name, "test/data/file2.txt") zf.add(zf.entries.first.name, "test/data/file2.txt")
@ -228,7 +232,7 @@ class ZipFileTest < MiniTest::Unit::TestCase
oldEntries = nil oldEntries = nil
::Zip::File.open(TEST_ZIP.zip_name) { |zf| oldEntries = zf.entries } ::Zip::File.open(TEST_ZIP.zip_name) { |zf| oldEntries = zf.entries }
assert_raises(::Zip::ZipEntryExistsError) do assert_raises(::Zip::EntryExistsError) do
::Zip::File.open(TEST_ZIP.zip_name) do |zf| ::Zip::File.open(TEST_ZIP.zip_name) do |zf|
zf.rename(zf.entries[0], zf.entries[1].name) zf.rename(zf.entries[0], zf.entries[1].name)
end end
@ -275,7 +279,7 @@ class ZipFileTest < MiniTest::Unit::TestCase
def test_renameEntryToExistingEntry def test_renameEntryToExistingEntry
entry1, entry2, * = TEST_ZIP.entry_names entry1, entry2, * = TEST_ZIP.entry_names
zf = ::Zip::File.new(TEST_ZIP.zip_name) zf = ::Zip::File.new(TEST_ZIP.zip_name)
assert_raises(::Zip::ZipEntryExistsError) { assert_raises(::Zip::EntryExistsError) {
zf.rename(entry1, entry2) zf.rename(entry1, entry2)
} }
ensure ensure
@ -324,6 +328,24 @@ class ZipFileTest < MiniTest::Unit::TestCase
zfRead.close zfRead.close
zf.close zf.close
res = system("unzip -t #{TEST_ZIP.zip_name}")
assert_equal(res, true)
end
def test_double_commit
::FileUtils.touch('test/data/generated/test_double_commit1.txt')
::FileUtils.touch('test/data/generated/test_double_commit2.txt')
zf = ::Zip::File.open('test/data/generated/double_commit_test.zip', ::Zip::File::CREATE)
zf.add('test1.txt', 'test/data/generated/test_double_commit1.txt')
zf.commit
zf.add('test2.txt', 'test/data/generated/test_double_commit2.txt')
zf.commit
zf.close
zf2 = ::Zip::File.open('test/data/generated/double_commit_test.zip')
assert(zf2.entries.detect {|e| e.name == 'test1.txt'} != nil )
assert(zf2.entries.detect {|e| e.name == 'test2.txt'} != nil )
res = system("unzip -t test/data/generated/double_commit_test.zip")
assert_equal(res, true)
end end
def test_write_buffer def test_write_buffer

View File

@ -1,6 +1,11 @@
require 'test_helper' require 'test_helper'
class ZipLocalEntryTest < MiniTest::Unit::TestCase class ZipLocalEntryTest < MiniTest::Unit::TestCase
def teardown
::Zip.write_zip64_support = false
end
def test_read_local_entryHeaderOfFirstTestZipEntry def test_read_local_entryHeaderOfFirstTestZipEntry
::File.open(TestZipFile::TEST_ZIP3.zip_name, "rb") do |file| ::File.open(TestZipFile::TEST_ZIP3.zip_name, "rb") do |file|
entry = ::Zip::Entry.read_local_entry(file) entry = ::Zip::Entry.read_local_entry(file)
@ -42,10 +47,22 @@ class ZipLocalEntryTest < MiniTest::Unit::TestCase
entry = ::Zip::Entry.new entry = ::Zip::Entry.new
entry.read_local_entry(zipFragment) entry.read_local_entry(zipFragment)
fail "ZipError expected" fail "ZipError expected"
rescue ::Zip::ZipError rescue ::Zip::Error
end end
def test_writeEntry def test_writeEntry
entry = ::Zip::Entry.new("file.zip", "entryName", "my little comment",
"thisIsSomeExtraInformation", 100, 987654,
::Zip::Entry::DEFLATED, 400)
write_to_file("localEntryHeader.bin", "centralEntryHeader.bin", entry)
entryReadLocal, entryReadCentral = read_from_file("localEntryHeader.bin", "centralEntryHeader.bin")
assert(entryReadCentral.extra['Zip64Placeholder'].nil?, 'zip64 placeholder should not be used in central directory')
compare_local_entry_headers(entry, entryReadLocal)
compare_c_dir_entry_headers(entry, entryReadCentral)
end
def test_writeEntryWithZip64
::Zip.write_zip64_support = true
entry = ::Zip::Entry.new("file.zip", "entryName", "my little comment", entry = ::Zip::Entry.new("file.zip", "entryName", "my little comment",
"thisIsSomeExtraInformation", 100, 987654, "thisIsSomeExtraInformation", 100, 987654,
::Zip::Entry::DEFLATED, 400) ::Zip::Entry::DEFLATED, 400)
@ -59,6 +76,7 @@ class ZipLocalEntryTest < MiniTest::Unit::TestCase
end end
def test_write64Entry def test_write64Entry
::Zip.write_zip64_support = true
entry = ::Zip::Entry.new("bigfile.zip", "entryName", "my little equine", entry = ::Zip::Entry.new("bigfile.zip", "entryName", "my little equine",
"malformed extra field because why not", "malformed extra field because why not",
0x7766554433221100, 0xDEADBEEF, ::Zip::Entry::DEFLATED, 0x7766554433221100, 0xDEADBEEF, ::Zip::Entry::DEFLATED,
@ -70,6 +88,7 @@ class ZipLocalEntryTest < MiniTest::Unit::TestCase
end end
def test_rewriteLocalHeader64 def test_rewriteLocalHeader64
::Zip.write_zip64_support = true
buf1 = StringIO.new buf1 = StringIO.new
entry = ::Zip::Entry.new("file.zip", "entryName") entry = ::Zip::Entry.new("file.zip", "entryName")
entry.write_local_entry(buf1) entry.write_local_entry(buf1)
@ -94,6 +113,7 @@ class ZipLocalEntryTest < MiniTest::Unit::TestCase
end end
def test_read64LocalOffset def test_read64LocalOffset
::Zip.write_zip64_support = true
entry = ::Zip::Entry.new("file.zip", "entryName") entry = ::Zip::Entry.new("file.zip", "entryName")
entry.local_header_offset = 0x0123456789ABCDEF entry.local_header_offset = 0x0123456789ABCDEF
::File.open('centralEntryHeader.bin', 'wb') { |f| entry.write_c_dir_entry(f) } ::File.open('centralEntryHeader.bin', 'wb') { |f| entry.write_c_dir_entry(f) }

View File

@ -34,13 +34,13 @@ class ZipSettingsTest < MiniTest::Unit::TestCase
def test_false_on_exists_proc def test_false_on_exists_proc
Zip.on_exists_proc = false Zip.on_exists_proc = false
File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" }
assert_raises(Zip::ZipDestinationFileExistsError) { extract_test_dir } assert_raises(Zip::DestinationFileExistsError) { extract_test_dir }
end end
def test_false_continue_on_exists_proc def test_false_continue_on_exists_proc
Zip.continue_on_exists_proc = false Zip.continue_on_exists_proc = false
assert_raises(::Zip::ZipEntryExistsError) do assert_raises(::Zip::EntryExistsError) do
::Zip::File.open(TEST_ZIP.zip_name) do |zf| ::Zip::File.open(TEST_ZIP.zip_name) do |zf|
zf.add(zf.entries.first.name, "test/data/file2.txt") zf.add(zf.entries.first.name, "test/data/file2.txt")
end end

View File

@ -1,4 +0,0 @@
for i in ree 1.8.7 1.9.2 1.9.3; do
git clean -nfx
rvm $i do rake
done