Hello community, here is the log from the commit of package rubygem-rubyzip for openSUSE:Factory checked in at 2020-02-28 15:21:53 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-rubyzip (Old) and /work/SRC/openSUSE:Factory/.rubygem-rubyzip.new.26092 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-rubyzip" Fri Feb 28 15:21:53 2020 rev:17 rq:780191 version:2.2.0 Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-rubyzip/rubygem-rubyzip.changes 2019-11-13 13:25:58.199550331 +0100 +++ /work/SRC/openSUSE:Factory/.rubygem-rubyzip.new.26092/rubygem-rubyzip.changes 2020-02-28 15:21:54.785962970 +0100 @@ -1,0 +2,47 @@ +Fri Feb 28 09:21:54 UTC 2020 - Stephan Kulow <co...@suse.com> + +- Fix rpmlint complains (removing rubygem-rubyzip.rpmlintrc) + +------------------------------------------------------------------- +Mon Feb 3 08:25:11 UTC 2020 - Dan Čermák <dcer...@suse.com> + +- New upstream release 2.2.0 + + - Add support for decompression plugin gems #427 + +------------------------------------------------------------------- +Mon Jan 27 08:28:47 UTC 2020 - Dan Čermák <dcer...@suse.com> + +- New upstream release 2.1.0 + + - Fix (at least partially) the `restore_times` and `restore_permissions` + options to `Zip::File.new` + [#413](https://github.com/rubyzip/rubyzip/pull/413) + - Previously, neither option did anything, regardless of what it was set + to. We have therefore defaulted them to `false` to preserve the current + behavior, for the time being. If you have explicitly set either to + `true`, it will now have an effect. + - Fix handling of UniversalTime (`mtime`, `atime`, `ctime`) + fields. [#421](https://github.com/rubyzip/rubyzip/pull/421) + - Previously, `Zip::File` did not pass the options to `Zip::Entry` in some + cases. [#423](https://github.com/rubyzip/rubyzip/pull/423) + - Note that `restore_times` in this release does nothing on Windows and + only restores `mtime`, not `atime` or `ctime`. + - Allow `Zip::File.open` to take an options hash like `Zip::File.new` + [#418](https://github.com/rubyzip/rubyzip/pull/418) + - Always print warnings with `warn`, instead of a mix of `puts` and `warn` + [#416](https://github.com/rubyzip/rubyzip/pull/416) + - Create temporary files in the system temporary directory instead of the + directory of the zip file + [#411](https://github.com/rubyzip/rubyzip/pull/411) + - Drop unused `tmpdir` requirement + [#411](https://github.com/rubyzip/rubyzip/pull/411) + + Tooling + + - Move CI to xenial and include jruby on JDK11 + [#419](https://github.com/rubyzip/rubyzip/pull/419/files) + +- Add rubygem-rubyzip.rpmlintrc + +------------------------------------------------------------------- Old: ---- rubyzip-2.0.0.gem New: ---- rubyzip-2.2.0.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-rubyzip.spec ++++++ --- /var/tmp/diff_new_pack.SimrFa/_old 2020-02-28 15:21:56.689966846 +0100 +++ /var/tmp/diff_new_pack.SimrFa/_new 2020-02-28 15:21:56.689966846 +0100 @@ -1,7 +1,7 @@ # # spec file for package rubygem-rubyzip # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -24,7 +24,7 @@ # Name: rubygem-rubyzip -Version: 2.0.0 +Version: 2.2.0 Release: 0 %define mod_name rubyzip %define mod_full_name %{mod_name}-%{version} @@ -32,10 +32,10 @@ BuildRequires: %{ruby >= 2.4} BuildRequires: %{rubygem gem2rpm} BuildRequires: ruby-macros >= 5 -Url: http://github.com/rubyzip/rubyzip +URL: http://github.com/rubyzip/rubyzip Source: https://rubygems.org/gems/%{mod_full_name}.gem Source1: gem2rpm.yml -Summary: rubyzip is a ruby module for reading and writing zip files +Summary: Ruby module for reading and writing zip files License: BSD-2-Clause Group: Development/Languages/Ruby ++++++ gem2rpm.yml ++++++ --- /var/tmp/diff_new_pack.SimrFa/_old 2020-02-28 15:21:56.725966920 +0100 +++ /var/tmp/diff_new_pack.SimrFa/_new 2020-02-28 15:21:56.725966920 +0100 @@ -1,6 +1,5 @@ -# --- -# ## used by gem2rpm -# :summary: this is a custom summary +--- +:summary: Ruby module for reading and writing zip files # ## used by gem2rpm # :description: |- # this is a custom description ++++++ rubyzip-2.0.0.gem -> rubyzip-2.2.0.gem ++++++ Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/constants.rb new/lib/zip/constants.rb --- old/lib/zip/constants.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/constants.rb 2020-02-01 16:37:23.000000000 +0100 @@ -60,4 +60,56 @@ FSTYPE_MAC_OSX => 'Mac OS/X (Darwin)'.freeze, FSTYPE_ATHEOS => 'AtheOS'.freeze }.freeze + + COMPRESSION_METHOD_STORE = 0 + COMPRESSION_METHOD_SHRINK = 1 + COMPRESSION_METHOD_REDUCE_1 = 2 + COMPRESSION_METHOD_REDUCE_2 = 3 + COMPRESSION_METHOD_REDUCE_3 = 4 + COMPRESSION_METHOD_REDUCE_4 = 5 + COMPRESSION_METHOD_IMPLODE = 6 + # RESERVED = 7 + COMPRESSION_METHOD_DEFLATE = 8 + COMPRESSION_METHOD_DEFLATE_64 = 9 + COMPRESSION_METHOD_PKWARE_DCLI = 10 + # RESERVED = 11 + COMPRESSION_METHOD_BZIP2 = 12 + # RESERVED = 13 + COMPRESSION_METHOD_LZMA = 14 + # RESERVED = 15 + COMPRESSION_METHOD_IBM_CMPSC = 16 + # RESERVED = 17 + COMPRESSION_METHOD_IBM_TERSE = 18 + COMPRESSION_METHOD_IBM_LZ77 = 19 + COMPRESSION_METHOD_JPEG = 96 + COMPRESSION_METHOD_WAVPACK = 97 + COMPRESSION_METHOD_PPMD = 98 + COMPRESSION_METHOD_AES = 99 + + COMPRESSION_METHODS = { + COMPRESSION_METHOD_STORE => 'Store (no compression)', + COMPRESSION_METHOD_SHRINK => 'Shrink', + COMPRESSION_METHOD_REDUCE_1 => 'Reduce with compression factor 1', + COMPRESSION_METHOD_REDUCE_2 => 'Reduce with compression factor 2', + COMPRESSION_METHOD_REDUCE_3 => 'Reduce with compression factor 3', + COMPRESSION_METHOD_REDUCE_4 => 'Reduce with compression factor 4', + COMPRESSION_METHOD_IMPLODE => 'Implode', + # RESERVED = 7 + COMPRESSION_METHOD_DEFLATE => 'Deflate', + COMPRESSION_METHOD_DEFLATE_64 => 'Deflate64(tm)', + COMPRESSION_METHOD_PKWARE_DCLI => 'PKWARE Data Compression Library Imploding (old IBM TERSE)', + # RESERVED = 11 + COMPRESSION_METHOD_BZIP2 => 'BZIP2', + # RESERVED = 13 + COMPRESSION_METHOD_LZMA => 'LZMA', + # RESERVED = 15 + COMPRESSION_METHOD_IBM_CMPSC => 'IBM z/OS CMPSC Compression', + # RESERVED = 17 + COMPRESSION_METHOD_IBM_TERSE => 'IBM TERSE (new)', + COMPRESSION_METHOD_IBM_LZ77 => 'IBM LZ77 z Architecture (PFS)', + COMPRESSION_METHOD_JPEG => 'JPEG variant', + COMPRESSION_METHOD_WAVPACK => 'WavPack compressed data', + COMPRESSION_METHOD_PPMD => 'PPMd version I, Rev 1', + COMPRESSION_METHOD_AES => 'AES encryption', + }.freeze end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/crypto/decrypted_io.rb new/lib/zip/crypto/decrypted_io.rb --- old/lib/zip/crypto/decrypted_io.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/lib/zip/crypto/decrypted_io.rb 2020-02-01 16:37:23.000000000 +0100 @@ -0,0 +1,39 @@ +module Zip + class DecryptedIo #:nodoc:all + CHUNK_SIZE = 32_768 + + def initialize(io, decrypter) + @io = io + @decrypter = decrypter + end + + def read(length = nil, outbuf = '') + return ((length.nil? || length.zero?) ? "" : nil) if eof + + while length.nil? || (buffer.bytesize < length) + break if input_finished? + buffer << produce_input + end + + outbuf.replace(buffer.slice!(0...(length || output_buffer.bytesize))) + end + + private + + def eof + buffer.empty? && input_finished? + end + + def buffer + @buffer ||= ''.dup + end + + def input_finished? + @io.eof + end + + def produce_input + @decrypter.decrypt(@io.read(CHUNK_SIZE)) + end + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/decompressor.rb new/lib/zip/decompressor.rb --- old/lib/zip/decompressor.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/decompressor.rb 2020-02-01 16:37:23.000000000 +0100 @@ -1,9 +1,27 @@ module Zip class Decompressor #:nodoc:all CHUNK_SIZE = 32_768 - def initialize(input_stream) + + def self.decompressor_classes + @decompressor_classes ||= {} + end + + def self.register(compression_method, decompressor_class) + decompressor_classes[compression_method] = decompressor_class + end + + def self.find_by_compression_method(compression_method) + decompressor_classes[compression_method] + end + + attr_reader :input_stream + attr_reader :decompressed_size + + def initialize(input_stream, decompressed_size = nil) super() + @input_stream = input_stream + @decompressed_size = decompressed_size end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/dos_time.rb new/lib/zip/dos_time.rb --- old/lib/zip/dos_time.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/dos_time.rb 2020-02-01 16:37:23.000000000 +0100 @@ -29,6 +29,11 @@ to_i / 2 == other.to_i / 2 end + # Create a DOSTime instance from a vanilla Time instance. + def self.from_time(time) + local(time.year, time.month, time.day, time.hour, time.min, time.sec) + end + def self.parse_binary_dos_format(binaryDosDate, binaryDosTime) second = 2 * (0b11111 & binaryDosTime) minute = (0b11111100000 & binaryDosTime) >> 5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/entry.rb new/lib/zip/entry.rb --- old/lib/zip/entry.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/entry.rb 2020-02-01 16:37:23.000000000 +0100 @@ -34,7 +34,7 @@ end @follow_symlinks = false - @restore_times = true + @restore_times = false @restore_permissions = false @restore_ownership = false # BUG: need an extra field to support uid/gid's @@ -72,6 +72,14 @@ @extra = ::Zip::ExtraField.new(@extra.to_s) unless @extra.is_a?(::Zip::ExtraField) end + def encrypted? + gp_flags & 1 == 1 + end + + def incomplete? + gp_flags & 8 == 8 + end + def time if @extra['UniversalTime'] @extra['UniversalTime'].mtime @@ -163,7 +171,7 @@ # is passed. def extract(dest_path = nil, &block) if dest_path.nil? && !name_safe? - puts "WARNING: skipped #{@name} as unsafe" + warn "WARNING: skipped '#{@name}' as unsafe." return self end @@ -406,16 +414,20 @@ @unix_uid = stat.uid @unix_gid = stat.gid @unix_perms = stat.mode & 0o7777 + @time = ::Zip::DOSTime.from_time(stat.mtime) end - def set_unix_permissions_on_path(dest_path) - # BUG: does not update timestamps into account + def set_unix_attributes_on_path(dest_path) # ignore setuid/setgid bits by default. honor if @restore_ownership unix_perms_mask = 0o1777 unix_perms_mask = 0o7777 if @restore_ownership ::FileUtils.chmod(@unix_perms & unix_perms_mask, dest_path) if @restore_permissions && @unix_perms ::FileUtils.chown(@unix_uid, @unix_gid, dest_path) if @restore_ownership && @unix_uid && @unix_gid && ::Process.egid == 0 - # File::utimes() + + # Restore the timestamp on a file. This will either have come from the + # original source file that was copied into the archive, or from the + # creation date of the archive if there was no original source file. + ::FileUtils.touch(dest_path, mtime: time) if @restore_times end def set_extra_attributes_on_path(dest_path) # :nodoc: @@ -423,7 +435,7 @@ case @fstype when ::Zip::FSTYPE_UNIX - set_unix_permissions_on_path(dest_path) + set_unix_attributes_on_path(dest_path) end end @@ -591,7 +603,7 @@ def set_time(binary_dos_date, binary_dos_time) @time = ::Zip::DOSTime.parse_binary_dos_format(binary_dos_date, binary_dos_time) rescue ArgumentError - warn 'Invalid date/time in zip entry' if ::Zip.warn_invalid_date + warn 'WARNING: invalid date/time in zip entry.' if ::Zip.warn_invalid_date end def create_file(dest_path, _continue_on_exists_proc = proc { Zip.continue_on_exists_proc }) @@ -601,8 +613,6 @@ end ::File.open(dest_path, 'wb') do |os| get_input_stream do |is| - set_extra_attributes_on_path(dest_path) - bytes_written = 0 warned = false buf = ''.dup @@ -610,17 +620,19 @@ os << buf bytes_written += buf.bytesize if bytes_written > size && !warned - message = "Entry #{name} should be #{size}B but is larger when inflated" + message = "entry '#{name}' should be #{size}B, but is larger when inflated." if ::Zip.validate_entry_sizes raise ::Zip::EntrySizeError, message else - puts "WARNING: #{message}" + warn "WARNING: #{message}" warned = true end end end end end + + set_extra_attributes_on_path(dest_path) end def create_directory(dest_path) @@ -642,7 +654,7 @@ def create_symlink(dest_path) # TODO: Symlinks pose security challenges. Symlink support temporarily # removed in view of https://github.com/rubyzip/rubyzip/issues/369 . - puts "WARNING: skipped symlink #{dest_path}" + warn "WARNING: skipped symlink '#{dest_path}'." end # apply missing data from the zip64 extra information field, if present diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/errors.rb new/lib/zip/errors.rb --- old/lib/zip/errors.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/errors.rb 2020-02-01 16:37:23.000000000 +0100 @@ -7,6 +7,7 @@ class EntrySizeError < Error; end class InternalError < Error; end class GPFBit3Error < Error; end + class DecompressionError < Error; end # Backwards compatibility with v1 (delete in v2) ZipError = Error diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/extra_field/generic.rb new/lib/zip/extra_field/generic.rb --- old/lib/zip/extra_field/generic.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/extra_field/generic.rb 2020-02-01 16:37:23.000000000 +0100 @@ -16,7 +16,7 @@ # If nil, start with empty. return false elsif binstr[0, 2] != self.class.const_get(:HEADER_ID) - $stderr.puts 'Warning: weired extra feild header ID. skip parsing' + warn 'WARNING: weird extra field header ID. Skip parsing it.' return false end [binstr[2, 2].unpack('v')[0], binstr[4..-1]] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/extra_field/universal_time.rb new/lib/zip/extra_field/universal_time.rb --- old/lib/zip/extra_field/universal_time.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/extra_field/universal_time.rb 2020-02-01 16:37:23.000000000 +0100 @@ -4,24 +4,51 @@ HEADER_ID = 'UT' register_map + ATIME_MASK = 0b010 + CTIME_MASK = 0b100 + MTIME_MASK = 0b001 + def initialize(binstr = nil) @ctime = nil @mtime = nil @atime = nil - @flag = nil - binstr && merge(binstr) + @flag = 0 + + merge(binstr) unless binstr.nil? + end + + attr_reader :atime, :ctime, :mtime, :flag + + def atime=(time) + @flag = time.nil? ? @flag & ~ATIME_MASK : @flag | ATIME_MASK + @atime = time end - attr_accessor :atime, :ctime, :mtime, :flag + def ctime=(time) + @flag = time.nil? ? @flag & ~CTIME_MASK : @flag | CTIME_MASK + @ctime = time + end + + def mtime=(time) + @flag = time.nil? ? @flag & ~MTIME_MASK : @flag | MTIME_MASK + @mtime = time + end def merge(binstr) return if binstr.empty? + size, content = initial_parse(binstr) - size || return - @flag, mtime, atime, ctime = content.unpack('CVVV') - mtime && @mtime ||= ::Zip::DOSTime.at(mtime) - atime && @atime ||= ::Zip::DOSTime.at(atime) - ctime && @ctime ||= ::Zip::DOSTime.at(ctime) + return if !size || size <= 0 + + @flag, *times = content.unpack('Cl<l<l<') + + # Parse the timestamps, in order, based on which flags are set. + return if times[0].nil? + @mtime ||= ::Zip::DOSTime.at(times.shift) unless @flag & MTIME_MASK == 0 + return if times[0].nil? + @atime ||= ::Zip::DOSTime.at(times.shift) unless @flag & ATIME_MASK == 0 + return if times[0].nil? + @ctime ||= ::Zip::DOSTime.at(times.shift) unless @flag & CTIME_MASK == 0 end def ==(other) @@ -32,15 +59,15 @@ def pack_for_local s = [@flag].pack('C') - @flag & 1 != 0 && s << [@mtime.to_i].pack('V') - @flag & 2 != 0 && s << [@atime.to_i].pack('V') - @flag & 4 != 0 && s << [@ctime.to_i].pack('V') + s << [@mtime.to_i].pack('l<') unless @flag & MTIME_MASK == 0 + s << [@atime.to_i].pack('l<') unless @flag & ATIME_MASK == 0 + s << [@ctime.to_i].pack('l<') unless @flag & CTIME_MASK == 0 s end def pack_for_c_dir s = [@flag].pack('C') - @flag & 1 == 1 && s << [@mtime.to_i].pack('V') + s << [@mtime.to_i].pack('l<') unless @flag & MTIME_MASK == 0 s end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/file.rb new/lib/zip/file.rb --- old/lib/zip/file.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/file.rb 2020-02-01 16:37:23.000000000 +0100 @@ -49,16 +49,25 @@ MAX_SEGMENT_SIZE = 3_221_225_472 MIN_SEGMENT_SIZE = 65_536 DATA_BUFFER_SIZE = 8192 - IO_METHODS = [:tell, :seek, :read, :close] + IO_METHODS = [:tell, :seek, :read, :eof, :close] + + DEFAULT_OPTIONS = { + restore_ownership: false, + restore_permissions: false, + restore_times: false + }.freeze attr_reader :name - # default -> false + # default -> false. attr_accessor :restore_ownership - # default -> false + + # default -> false, but will be set to true in a future version. attr_accessor :restore_permissions - # default -> true + + # default -> false, but will be set to true in a future version. attr_accessor :restore_times + # Returns the zip files comment, if it has one attr_accessor :comment @@ -66,6 +75,7 @@ # a new archive if it doesn't exist already. def initialize(path_or_io, create = false, buffer = false, options = {}) super() + options = DEFAULT_OPTIONS.merge(options) @name = path_or_io.respond_to?(:path) ? path_or_io.path : path_or_io @comment = '' @create = create ? true : false # allow any truthy value to mean true @@ -98,17 +108,17 @@ @stored_entries = @entry_set.dup @stored_comment = @comment - @restore_ownership = options[:restore_ownership] || false - @restore_permissions = options[:restore_permissions] || true - @restore_times = options[:restore_times] || true + @restore_ownership = options[:restore_ownership] + @restore_permissions = options[:restore_permissions] + @restore_times = options[:restore_times] end class << self - # Same as #new. If a block is passed the ZipFile object is passed - # to the block and is automatically closed afterwards just as with - # ruby's builtin File.open method. - def open(file_name, create = false) - zf = ::Zip::File.new(file_name, create) + # Similar to ::new. If a block is passed the Zip::File object is passed + # to the block and is automatically closed afterwards, just as with + # ruby's builtin File::open method. + def open(file_name, create = false, options = {}) + zf = ::Zip::File.new(file_name, create, false, options) return zf unless block_given? begin yield zf @@ -366,7 +376,13 @@ # Searches for entry with the specified name. Returns nil if # no entry is found. See also get_entry def find_entry(entry_name) - @entry_set.find_entry(entry_name) + selected_entry = @entry_set.find_entry(entry_name) + return if selected_entry.nil? + + selected_entry.restore_ownership = @restore_ownership + selected_entry.restore_permissions = @restore_permissions + selected_entry.restore_times = @restore_times + selected_entry end # Searches for entries given a glob @@ -378,10 +394,8 @@ # if no entry is found. def get_entry(entry) selected_entry = find_entry(entry) - raise Errno::ENOENT, entry unless selected_entry - selected_entry.restore_ownership = @restore_ownership - selected_entry.restore_permissions = @restore_permissions - selected_entry.restore_times = @restore_times + raise Errno::ENOENT, entry if selected_entry.nil? + selected_entry end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/inflater.rb new/lib/zip/inflater.rb --- old/lib/zip/inflater.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/inflater.rb 2020-02-01 16:37:23.000000000 +0100 @@ -1,64 +1,50 @@ module Zip class Inflater < Decompressor #:nodoc:all - def initialize(input_stream, decrypter = NullDecrypter.new) - super(input_stream) - @zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS) - @output_buffer = ''.dup - @has_returned_empty_string = false - @decrypter = decrypter - end + def initialize(*args) + super - def sysread(number_of_bytes = nil, buf = '') - readEverything = number_of_bytes.nil? - while readEverything || @output_buffer.bytesize < number_of_bytes - break if internal_input_finished? - @output_buffer << internal_produce_input(buf) - end - return value_when_finished if @output_buffer.bytesize == 0 && input_finished? - end_index = number_of_bytes.nil? ? @output_buffer.bytesize : number_of_bytes - @output_buffer.slice!(0...end_index) + @buffer = ''.dup + @zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS) end - def produce_input - if @output_buffer.empty? - internal_produce_input - else - @output_buffer.slice!(0...(@output_buffer.length)) + def read(length = nil, outbuf = '') + return ((length.nil? || length.zero?) ? "" : nil) if eof + + while length.nil? || (@buffer.bytesize < length) + break if input_finished? + @buffer << produce_input end + + outbuf.replace(@buffer.slice!(0...(length || @buffer.bytesize))) end - # to be used with produce_input, not read (as read may still have more data cached) - # is data cached anywhere other than @outputBuffer? the comment above may be wrong - def input_finished? - @output_buffer.empty? && internal_input_finished? + def eof + @buffer.empty? && input_finished? end - alias :eof input_finished? - alias :eof? input_finished? + alias_method :eof?, :eof private - def internal_produce_input(buf = '') + def produce_input retried = 0 begin - @zlib_inflater.inflate(@decrypter.decrypt(@input_stream.read(Decompressor::CHUNK_SIZE, buf))) + @zlib_inflater.inflate(input_stream.read(Decompressor::CHUNK_SIZE)) rescue Zlib::BufError raise if retried >= 5 # how many times should we retry? retried += 1 retry end + rescue Zlib::Error + raise(::Zip::DecompressionError, 'zlib error while inflating') end - def internal_input_finished? + def input_finished? @zlib_inflater.finished? end - - def value_when_finished # mimic behaviour of ruby File object. - return if @has_returned_empty_string - @has_returned_empty_string = true - '' - end end + + ::Zip::Decompressor.register(::Zip::COMPRESSION_METHOD_DEFLATE, ::Zip::Inflater) end # Copyright (C) 2002, 2003 Thomas Sondergaard diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/input_stream.rb new/lib/zip/input_stream.rb --- old/lib/zip/input_stream.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/input_stream.rb 2020-02-01 16:37:23.000000000 +0100 @@ -39,6 +39,8 @@ # class. class InputStream + CHUNK_SIZE = 32_768 + include ::Zip::IOExtras::AbstractInputStream # Opens the indicated zip file. An exception is thrown @@ -78,16 +80,10 @@ end # Modeled after IO.sysread - def sysread(number_of_bytes = nil, buf = nil) - @decompressor.sysread(number_of_bytes, buf) - end - - def eof - @output_buffer.empty? && @decompressor.eof + def sysread(length = nil, outbuf = '') + @decompressor.read(length, outbuf) end - alias :eof? eof - class << self # Same as #initialize but if a block is passed the opened # stream is passed to the block and closed when the block @@ -103,7 +99,7 @@ end def open_buffer(filename_or_io, offset = 0) - puts 'open_buffer is deprecated!!! Use open instead!' + warn 'open_buffer is deprecated!!! Use open instead!' open(filename_or_io, offset) end end @@ -124,46 +120,54 @@ def open_entry @current_entry = ::Zip::Entry.read_local_entry(@archive_io) - if @current_entry && @current_entry.gp_flags & 1 == 1 && @decrypter.is_a?(NullEncrypter) + if @current_entry && @current_entry.encrypted? && @decrypter.is_a?(NullEncrypter) raise Error, 'password required to decode zip file' end - if @current_entry && @current_entry.gp_flags & 8 == 8 && @current_entry.crc == 0 \ + if @current_entry && @current_entry.incomplete? && @current_entry.crc == 0 \ && @current_entry.compressed_size == 0 \ && @current_entry.size == 0 && !@complete_entry raise GPFBit3Error, 'General purpose flag Bit 3 is set so not possible to get proper info from local header.' \ 'Please use ::Zip::File instead of ::Zip::InputStream' end + @decrypted_io = get_decrypted_io @decompressor = get_decompressor flush @current_entry end + def get_decrypted_io + header = @archive_io.read(@decrypter.header_bytesize) + @decrypter.reset!(header) + + ::Zip::DecryptedIo.new(@archive_io, @decrypter) + end + def get_decompressor - if @current_entry.nil? - ::Zip::NullDecompressor - elsif @current_entry.compression_method == ::Zip::Entry::STORED - if @current_entry.gp_flags & 8 == 8 && @current_entry.crc == 0 && @current_entry.size == 0 && @complete_entry - ::Zip::PassThruDecompressor.new(@archive_io, @complete_entry.size) + return ::Zip::NullDecompressor if @current_entry.nil? + + decompressed_size = + if @current_entry.incomplete? && @current_entry.crc == 0 && @current_entry.size == 0 && @complete_entry + @complete_entry.size else - ::Zip::PassThruDecompressor.new(@archive_io, @current_entry.size) + @current_entry.size end - elsif @current_entry.compression_method == ::Zip::Entry::DEFLATED - header = @archive_io.read(@decrypter.header_bytesize) - @decrypter.reset!(header) - ::Zip::Inflater.new(@archive_io, @decrypter) - else + + decompressor_class = ::Zip::Decompressor.find_by_compression_method(@current_entry.compression_method) + if decompressor_class.nil? raise ::Zip::CompressionMethodError, "Unsupported compression method #{@current_entry.compression_method}" end + + decompressor_class.new(@decrypted_io, decompressed_size) end def produce_input - @decompressor.produce_input + @decompressor.read(CHUNK_SIZE) end def input_finished? - @decompressor.input_finished? + @decompressor.eof end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/ioextras/abstract_input_stream.rb new/lib/zip/ioextras/abstract_input_stream.rb --- old/lib/zip/ioextras/abstract_input_stream.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/ioextras/abstract_input_stream.rb 2020-02-01 16:37:23.000000000 +0100 @@ -106,6 +106,12 @@ end alias_method :each, :each_line + + def eof + @output_buffer.empty? && input_finished? + end + + alias_method :eof?, :eof end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/null_decompressor.rb new/lib/zip/null_decompressor.rb --- old/lib/zip/null_decompressor.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/null_decompressor.rb 2020-02-01 16:37:23.000000000 +0100 @@ -2,18 +2,10 @@ module NullDecompressor #:nodoc:all module_function - def sysread(_numberOfBytes = nil, _buf = nil) + def read(_length = nil, _outbuf = nil) nil end - def produce_input - nil - end - - def input_finished? - true - end - def eof true end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/pass_thru_decompressor.rb new/lib/zip/pass_thru_decompressor.rb --- old/lib/zip/pass_thru_decompressor.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/pass_thru_decompressor.rb 2020-02-01 16:37:23.000000000 +0100 @@ -1,38 +1,29 @@ module Zip class PassThruDecompressor < Decompressor #:nodoc:all - def initialize(input_stream, chars_to_read) - super(input_stream) - @chars_to_read = chars_to_read + def initialize(*args) + super @read_so_far = 0 - @has_returned_empty_string = false end - def sysread(number_of_bytes = nil, buf = '') - if input_finished? - has_returned_empty_string_val = @has_returned_empty_string - @has_returned_empty_string = true - return '' unless has_returned_empty_string_val - return - end + def read(length = nil, outbuf = '') + return ((length.nil? || length.zero?) ? "" : nil) if eof - if number_of_bytes.nil? || @read_so_far + number_of_bytes > @chars_to_read - number_of_bytes = @chars_to_read - @read_so_far + if length.nil? || (@read_so_far + length) > decompressed_size + length = decompressed_size - @read_so_far end - @read_so_far += number_of_bytes - @input_stream.read(number_of_bytes, buf) - end - def produce_input - sysread(::Zip::Decompressor::CHUNK_SIZE) + @read_so_far += length + input_stream.read(length, outbuf) end - def input_finished? - @read_so_far >= @chars_to_read + def eof + @read_so_far >= decompressed_size end - alias eof input_finished? - alias eof? input_finished? + alias_method :eof?, :eof end + + ::Zip::Decompressor.register(::Zip::COMPRESSION_METHOD_STORE, ::Zip::PassThruDecompressor) end # Copyright (C) 2002, 2003 Thomas Sondergaard diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/streamable_stream.rb new/lib/zip/streamable_stream.rb --- old/lib/zip/streamable_stream.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/streamable_stream.rb 2020-02-01 16:37:23.000000000 +0100 @@ -2,12 +2,7 @@ class StreamableStream < DelegateClass(Entry) # nodoc:all def initialize(entry) super(entry) - dirname = if zipfile.is_a?(::String) - ::File.dirname(zipfile) - else - nil - end - @temp_file = Tempfile.new(::File.basename(name), dirname) + @temp_file = Tempfile.new(::File.basename(name)) @temp_file.binmode end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip/version.rb new/lib/zip/version.rb --- old/lib/zip/version.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip/version.rb 2020-02-01 16:37:23.000000000 +0100 @@ -1,3 +1,3 @@ module Zip - VERSION = '2.0.0' + VERSION = '2.2.0' end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/zip.rb new/lib/zip.rb --- old/lib/zip.rb 2019-09-25 22:37:53.000000000 +0200 +++ new/lib/zip.rb 2020-02-01 16:37:23.000000000 +0100 @@ -1,10 +1,10 @@ require 'delegate' require 'singleton' require 'tempfile' -require 'tmpdir' require 'fileutils' require 'stringio' require 'zlib' +require 'zip/constants' require 'zip/dos_time' require 'zip/ioextras' require 'rbconfig' @@ -22,6 +22,7 @@ require 'zip/null_input_stream' require 'zip/pass_thru_compressor' require 'zip/pass_thru_decompressor' +require 'zip/crypto/decrypted_io' require 'zip/crypto/encryption' require 'zip/crypto/null_encryption' require 'zip/crypto/traditional_encryption' @@ -29,7 +30,6 @@ require 'zip/deflater' require 'zip/streamable_stream' require 'zip/streamable_directory' -require 'zip/constants' require 'zip/errors' module Zip diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 2019-09-25 22:37:53.000000000 +0200 +++ new/metadata 2020-02-01 16:37:23.000000000 +0100 @@ -1,14 +1,14 @@ --- !ruby/object:Gem::Specification name: rubyzip version: !ruby/object:Gem::Version - version: 2.0.0 + version: 2.2.0 platform: ruby authors: - Alexander Simonov autorequire: bindir: bin cert_chain: [] -date: 2019-09-25 00:00:00.000000000 Z +date: 2020-02-01 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: rake @@ -94,6 +94,7 @@ - lib/zip/central_directory.rb - lib/zip/compressor.rb - lib/zip/constants.rb +- lib/zip/crypto/decrypted_io.rb - lib/zip/crypto/encryption.rb - lib/zip/crypto/null_encryption.rb - lib/zip/crypto/traditional_encryption.rb @@ -139,9 +140,9 @@ - BSD 2-Clause metadata: bug_tracker_uri: https://github.com/rubyzip/rubyzip/issues - changelog_uri: https://github.com/rubyzip/rubyzip/blob/v2.0.0/Changelog.md - documentation_uri: https://www.rubydoc.info/gems/rubyzip/2.0.0 - source_code_uri: https://github.com/rubyzip/rubyzip/tree/v2.0.0 + changelog_uri: https://github.com/rubyzip/rubyzip/blob/v2.2.0/Changelog.md + documentation_uri: https://www.rubydoc.info/gems/rubyzip/2.2.0 + source_code_uri: https://github.com/rubyzip/rubyzip/tree/v2.2.0 wiki_uri: https://github.com/rubyzip/rubyzip/wiki post_install_message: rdoc_options: []