parent
4f9b642644
commit
ec81c30382
34
README.md
34
README.md
|
@ -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
1
TODO
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
Loading…
Reference in New Issue