Merge branch 'master' into compression_level
This commit is contained in:
commit
a0345420d8
|
@ -1,6 +1,7 @@
|
||||||
# X.X.X (Next)
|
# X.X.X (Next)
|
||||||
|
|
||||||
- Set compression level on a per-zipfile basis. [#448](https://github.com/rubyzip/rubyzip/pull/448)
|
- Set compression level on a per-zipfile basis. [#448](https://github.com/rubyzip/rubyzip/pull/448)
|
||||||
|
- Fix input stream partial read error. [#462](https://github.com/rubyzip/rubyzip/pull/462)
|
||||||
|
|
||||||
Tooling:
|
Tooling:
|
||||||
|
|
||||||
|
|
|
@ -124,10 +124,37 @@ module Zip
|
||||||
end
|
end
|
||||||
@entry_set = EntrySet.new
|
@entry_set = EntrySet.new
|
||||||
@size.times do
|
@size.times do
|
||||||
@entry_set << Entry.read_c_dir_entry(io)
|
entry = Entry.read_c_dir_entry(io)
|
||||||
|
next unless entry
|
||||||
|
|
||||||
|
offset = if entry.extra['Zip64']
|
||||||
|
entry.extra['Zip64'].relative_header_offset
|
||||||
|
else
|
||||||
|
entry.local_header_offset
|
||||||
|
end
|
||||||
|
|
||||||
|
unless offset.nil?
|
||||||
|
io_save = io.tell
|
||||||
|
io.seek(offset, IO::SEEK_SET)
|
||||||
|
entry.read_extra_field(read_local_extra_field(io))
|
||||||
|
io.seek(io_save, IO::SEEK_SET)
|
||||||
|
end
|
||||||
|
|
||||||
|
@entry_set << entry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def read_local_extra_field(io)
|
||||||
|
buf = io.read(::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH) || ''
|
||||||
|
return '' unless buf.bytesize == ::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH
|
||||||
|
|
||||||
|
head, _, _, _, _, _, _, _, _, _, n_len, e_len = buf.unpack('VCCvvvvVVVvv')
|
||||||
|
return '' unless head == ::Zip::LOCAL_ENTRY_SIGNATURE
|
||||||
|
|
||||||
|
io.seek(n_len, IO::SEEK_CUR) # Skip over the entry name.
|
||||||
|
io.read(e_len)
|
||||||
|
end
|
||||||
|
|
||||||
def read_from_stream(io) #:nodoc:
|
def read_from_stream(io) #:nodoc:
|
||||||
buf = start_buf(io)
|
buf = start_buf(io)
|
||||||
if zip64_file?(buf)
|
if zip64_file?(buf)
|
||||||
|
|
|
@ -13,16 +13,16 @@ module Zip
|
||||||
val = data.to_s
|
val = data.to_s
|
||||||
@crc = Zlib.crc32(val, @crc)
|
@crc = Zlib.crc32(val, @crc)
|
||||||
@size += val.bytesize
|
@size += val.bytesize
|
||||||
buffer = @zlib_deflater.deflate(data)
|
buffer = @zlib_deflater.deflate(data, Zlib::SYNC_FLUSH)
|
||||||
if buffer.empty?
|
return @output_stream if buffer.empty?
|
||||||
@output_stream
|
|
||||||
else
|
@output_stream << @encrypter.encrypt(buffer)
|
||||||
@output_stream << @encrypter.encrypt(buffer)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def finish
|
def finish
|
||||||
@output_stream << @encrypter.encrypt(@zlib_deflater.finish) until @zlib_deflater.finished?
|
buffer = @zlib_deflater.finish
|
||||||
|
@output_stream << @encrypter.encrypt(buffer) unless buffer.empty?
|
||||||
|
@zlib_deflater.close
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :size, :crc
|
attr_reader :size, :crc
|
||||||
|
|
|
@ -303,12 +303,7 @@ module Zip
|
||||||
raise ::Zip::Error, 'Truncated local zip entry header'
|
raise ::Zip::Error, 'Truncated local zip entry header'
|
||||||
end
|
end
|
||||||
|
|
||||||
if @extra.kind_of?(::Zip::ExtraField)
|
read_extra_field(extra)
|
||||||
@extra.merge(extra) if extra
|
|
||||||
else
|
|
||||||
@extra = ::Zip::ExtraField.new(extra)
|
|
||||||
end
|
|
||||||
|
|
||||||
parse_zip64_extra(true)
|
parse_zip64_extra(true)
|
||||||
@local_header_size = calculate_local_header_size
|
@local_header_size = calculate_local_header_size
|
||||||
end
|
end
|
||||||
|
@ -411,11 +406,11 @@ module Zip
|
||||||
raise ::Zip::Error, 'Truncated cdir zip entry header'
|
raise ::Zip::Error, 'Truncated cdir zip entry header'
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_c_dir_extra_field(io)
|
def read_extra_field(buf)
|
||||||
if @extra.kind_of?(::Zip::ExtraField)
|
if @extra.kind_of?(::Zip::ExtraField)
|
||||||
@extra.merge(io.read(@extra_length))
|
@extra.merge(buf) if buf
|
||||||
else
|
else
|
||||||
@extra = ::Zip::ExtraField.new(io.read(@extra_length))
|
@extra = ::Zip::ExtraField.new(buf)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -429,7 +424,7 @@ module Zip
|
||||||
if ::Zip.force_entry_names_encoding
|
if ::Zip.force_entry_names_encoding
|
||||||
@name.force_encoding(::Zip.force_entry_names_encoding)
|
@name.force_encoding(::Zip.force_entry_names_encoding)
|
||||||
end
|
end
|
||||||
read_c_dir_extra_field(io)
|
read_extra_field(io.read(@extra_length))
|
||||||
@comment = io.read(@comment_length)
|
@comment = io.read(@comment_length)
|
||||||
check_c_dir_entry_comment_size
|
check_c_dir_entry_comment_size
|
||||||
set_ftype_from_c_dir_entry
|
set_ftype_from_c_dir_entry
|
||||||
|
|
|
@ -22,15 +22,6 @@ module Zip
|
||||||
[binstr[2, 2].unpack1('v'), binstr[4..-1]]
|
[binstr[2, 2].unpack1('v'), binstr[4..-1]]
|
||||||
end
|
end
|
||||||
|
|
||||||
def ==(other)
|
|
||||||
return false if self.class != other.class
|
|
||||||
|
|
||||||
each do |k, v|
|
|
||||||
return false if v != other[k]
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_local_bin
|
def to_local_bin
|
||||||
s = pack_for_local
|
s = pack_for_local
|
||||||
self.class.const_get(:HEADER_ID) + [s.bytesize].pack('v') << s
|
self.class.const_get(:HEADER_ID) + [s.bytesize].pack('v') << s
|
||||||
|
|
|
@ -20,8 +20,8 @@ module Zip
|
||||||
return if !size || size == 0
|
return if !size || size == 0
|
||||||
|
|
||||||
uid, gid = content.unpack('vv')
|
uid, gid = content.unpack('vv')
|
||||||
@uid ||= uid
|
@uid = uid
|
||||||
@gid ||= gid # rubocop:disable Naming/MemoizedInstanceVariableName
|
@gid = gid
|
||||||
end
|
end
|
||||||
|
|
||||||
def ==(other)
|
def ==(other)
|
||||||
|
|
|
@ -19,7 +19,7 @@ module Zip
|
||||||
|
|
||||||
def read(number_of_bytes = nil, buf = '')
|
def read(number_of_bytes = nil, buf = '')
|
||||||
tbuf = if @output_buffer.bytesize > 0
|
tbuf = if @output_buffer.bytesize > 0
|
||||||
if number_of_bytes <= @output_buffer.bytesize
|
if number_of_bytes && number_of_bytes <= @output_buffer.bytesize
|
||||||
@output_buffer.slice!(0, number_of_bytes)
|
@output_buffer.slice!(0, number_of_bytes)
|
||||||
else
|
else
|
||||||
number_of_bytes -= @output_buffer.bytesize if number_of_bytes
|
number_of_bytes -= @output_buffer.bytesize if number_of_bytes
|
||||||
|
|
|
@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
||||||
s.summary = 'rubyzip is a ruby module for reading and writing zip files'
|
s.summary = 'rubyzip is a ruby module for reading and writing zip files'
|
||||||
s.files = Dir.glob('{samples,lib}/**/*.rb') + %w[README.md TODO Rakefile]
|
s.files = Dir.glob('{samples,lib}/**/*.rb') + %w[README.md TODO Rakefile]
|
||||||
s.require_paths = ['lib']
|
s.require_paths = ['lib']
|
||||||
s.license = 'BSD 2-Clause'
|
s.license = 'BSD-2-Clause'
|
||||||
s.metadata = {
|
s.metadata = {
|
||||||
'bug_tracker_uri' => 'https://github.com/rubyzip/rubyzip/issues',
|
'bug_tracker_uri' => 'https://github.com/rubyzip/rubyzip/issues',
|
||||||
'changelog_uri' => "https://github.com/rubyzip/rubyzip/blob/v#{s.version}/Changelog.md",
|
'changelog_uri' => "https://github.com/rubyzip/rubyzip/blob/v#{s.version}/Changelog.md",
|
||||||
|
|
Binary file not shown.
|
@ -13,20 +13,28 @@ class EncryptionTest < MiniTest::Test
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_encrypt
|
def test_encrypt
|
||||||
test_file = ::File.open(ENCRYPT_ZIP_TEST_FILE, 'rb').read
|
content = File.open(INPUT_FILE1, 'r').read
|
||||||
|
test_filename = 'top_secret_file.txt'
|
||||||
|
|
||||||
@rand = [250, 143, 107, 13, 143, 22, 155, 75, 228, 150, 12]
|
password = 'swordfish'
|
||||||
@output = ::Zip::DOSTime.stub(:now, ::Zip::DOSTime.new(2014, 12, 17, 15, 56, 24)) do
|
|
||||||
Random.stub(:rand, ->(_range) { @rand.shift }) do
|
encrypted_zip = Zip::OutputStream.write_buffer(::StringIO.new(''), Zip::TraditionalEncrypter.new(password)) do |out|
|
||||||
Zip::OutputStream.write_buffer(::StringIO.new(''), Zip::TraditionalEncrypter.new('password')) do |zos|
|
out.put_next_entry(test_filename)
|
||||||
zos.put_next_entry('file1.txt')
|
out.write content
|
||||||
zos.write ::File.open(INPUT_FILE1).read
|
|
||||||
end.string
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@output.unpack('C*').each_with_index do |c, i|
|
Zip::InputStream.open(encrypted_zip, 0, Zip::TraditionalDecrypter.new(password)) do |zis|
|
||||||
assert_equal test_file[i].ord, c
|
entry = zis.get_next_entry
|
||||||
|
assert_equal test_filename, entry.name
|
||||||
|
assert_equal 1327, entry.size
|
||||||
|
assert_equal content, zis.read
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_raises(Zip::DecompressionError) do
|
||||||
|
Zip::InputStream.open(encrypted_zip, 0, Zip::TraditionalDecrypter.new(password + 'wrong')) do |zis|
|
||||||
|
zis.get_next_entry
|
||||||
|
assert_equal content, zis.read
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,16 @@ class ZipExtraFieldTest < MiniTest::Test
|
||||||
assert_equal(extra.to_s, 'fooabarbaz')
|
assert_equal(extra.to_s, 'fooabarbaz')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_bad_header_id
|
||||||
|
str = "ut\x5\0\x3\250$\r@"
|
||||||
|
ut = nil
|
||||||
|
assert_output('', /WARNING/) do
|
||||||
|
ut = ::Zip::ExtraField::UniversalTime.new(str)
|
||||||
|
end
|
||||||
|
assert_instance_of(::Zip::ExtraField::UniversalTime, ut)
|
||||||
|
assert_nil(ut.mtime)
|
||||||
|
end
|
||||||
|
|
||||||
def test_ntfs
|
def test_ntfs
|
||||||
str = "\x0A\x00 \x00\x00\x00\x00\x00\x01\x00\x18\x00\xC0\x81\x17\xE8B\xCE\xCF\x01\xC0\x81\x17\xE8B\xCE\xCF\x01\xC0\x81\x17\xE8B\xCE\xCF\x01"
|
str = "\x0A\x00 \x00\x00\x00\x00\x00\x01\x00\x18\x00\xC0\x81\x17\xE8B\xCE\xCF\x01\xC0\x81\x17\xE8B\xCE\xCF\x01\xC0\x81\x17\xE8B\xCE\xCF\x01"
|
||||||
extra = ::Zip::ExtraField.new(str)
|
extra = ::Zip::ExtraField.new(str)
|
||||||
|
@ -25,6 +35,8 @@ class ZipExtraFieldTest < MiniTest::Test
|
||||||
assert_equal(t, extra['NTFS'].mtime)
|
assert_equal(t, extra['NTFS'].mtime)
|
||||||
assert_equal(t, extra['NTFS'].atime)
|
assert_equal(t, extra['NTFS'].atime)
|
||||||
assert_equal(t, extra['NTFS'].ctime)
|
assert_equal(t, extra['NTFS'].ctime)
|
||||||
|
|
||||||
|
assert_equal(str.force_encoding('BINARY'), extra.to_local_bin)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_merge
|
def test_merge
|
||||||
|
@ -73,4 +85,16 @@ class ZipExtraFieldTest < MiniTest::Test
|
||||||
extra1.create('IUnix')
|
extra1.create('IUnix')
|
||||||
assert_equal(extra1, extra3)
|
assert_equal(extra1, extra3)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_read_local_extra_field
|
||||||
|
::Zip::File.open('test/data/local_extra_field.zip') do |zf|
|
||||||
|
['file1.txt', 'file2.txt'].each do |file|
|
||||||
|
entry = zf.get_entry(file)
|
||||||
|
|
||||||
|
assert_instance_of(::Zip::ExtraField, entry.extra)
|
||||||
|
assert_equal(1_000, entry.extra['IUnix'].uid)
|
||||||
|
assert_equal(1_000, entry.extra['IUnix'].gid)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -295,8 +295,10 @@ class ZipFsFileNonmutatingTest < MiniTest::Test
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_atime
|
def test_atime
|
||||||
assert_nil(@zip_file.file.atime('file1'))
|
assert_equal(::Zip::DOSTime.at(1_027_694_306),
|
||||||
assert_nil(@zip_file.file.stat('file1').atime)
|
@zip_file.file.atime('file1'))
|
||||||
|
assert_equal(::Zip::DOSTime.at(1_027_694_306),
|
||||||
|
@zip_file.file.stat('file1').atime)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_ntfs_time
|
def test_ntfs_time
|
||||||
|
|
|
@ -19,11 +19,11 @@ class ZipFsFileStatTest < MiniTest::Test
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_uid
|
def test_uid
|
||||||
assert_equal(0, @zip_file.file.stat('file1').uid)
|
assert_equal(500, @zip_file.file.stat('file1').uid)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_gid
|
def test_gid
|
||||||
assert_equal(0, @zip_file.file.stat('file1').gid)
|
assert_equal(500, @zip_file.file.stat('file1').gid)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_ftype
|
def test_ftype
|
||||||
|
|
|
@ -179,4 +179,14 @@ class ZipInputStreamTest < MiniTest::Test
|
||||||
assert_equal('$VERBOSE =', zis.read(10))
|
assert_equal('$VERBOSE =', zis.read(10))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_readline_then_read
|
||||||
|
::Zip::InputStream.open(TestZipFile::TEST_ZIP2.zip_name) do |zis|
|
||||||
|
zis.get_next_entry
|
||||||
|
assert_equal("#!/usr/bin/env ruby\n", zis.readline)
|
||||||
|
refute(zis.eof?)
|
||||||
|
refute_empty(zis.read) # Also should not raise an error.
|
||||||
|
assert(zis.eof?)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue