rubyzip 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rubyzip might be problematic. Click here for more details.

@@ -2,10 +2,13 @@ module Zip
2
2
  # Info-ZIP Extra for Zip64 size
3
3
  class ExtraField::Zip64 < ExtraField::Generic
4
4
  attr_accessor :original_size, :compressed_size, :relative_header_offset, :disk_start_number
5
- HEADER_ID = "\001\000"
5
+ HEADER_ID = ['0100'].pack('H*')
6
6
  register_map
7
7
 
8
8
  def initialize(binstr = nil)
9
+ @content = nil # unparsed binary; we don't actually know what this contains
10
+ # without looking for FFs in the associated file header
11
+ # call parse after initializing with a binary string
9
12
  @original_size = nil
10
13
  @compressed_size = nil
11
14
  @relative_header_offset = nil
@@ -13,18 +16,52 @@ module Zip
13
16
  binstr and merge(binstr)
14
17
  end
15
18
 
19
+ def ==(other)
20
+ other.original_size == @original_size &&
21
+ other.compressed_size == @compressed_size &&
22
+ other.relative_header_offset == @relative_header_offset &&
23
+ other.disk_start_number == @disk_start_number
24
+ end
25
+
16
26
  def merge(binstr)
17
27
  return if binstr.empty?
18
- id, size, @original_size, @compressed_size, @relative_header_offset, @disk_start_number = binstr.to_s.unpack("vvQQQV")
28
+ _, @content = initial_parse(binstr)
29
+ end
30
+
31
+ # pass the values from the base entry (if applicable)
32
+ # wider values are only present in the extra field for base values set to all FFs
33
+ # returns the final values for the four attributes (from the base or zip64 extra record)
34
+ def parse(original_size, compressed_size, relative_header_offset = nil, disk_start_number = nil)
35
+ @original_size = extract(8, 'Q<') if original_size == 0xFFFFFFFF
36
+ @compressed_size = extract(8, 'Q<') if compressed_size == 0xFFFFFFFF
37
+ @relative_header_offset = extract(8, 'Q<') if relative_header_offset && relative_header_offset == 0xFFFFFFFF
38
+ @disk_start_number = extract(4, 'V') if disk_start_number && disk_start_number == 0xFFFF
39
+ @content = nil
40
+ [@original_size || original_size,
41
+ @compressed_size || compressed_size,
42
+ @relative_header_offset || relative_header_offset,
43
+ @disk_start_number || disk_start_number]
44
+ end
45
+
46
+ def extract(size, format)
47
+ @content.slice!(0, size).unpack(format)[0]
19
48
  end
49
+ private :extract
20
50
 
21
51
  def pack_for_local
22
- return '' unless @original_size && @compressed_sie && @relative_header_offset && @disk_start_number
23
- [1, 16, @original_size, @compressed_size, @relative_header_offset, @disk_start_number].pack("vvQQQV")
52
+ # local header entries must contain original size and compressed size; other fields do not apply
53
+ return '' unless @original_size && @compressed_size
54
+ [@original_size, @compressed_size].pack("Q<Q<")
24
55
  end
25
56
 
26
57
  def pack_for_c_dir
27
- pack_for_local
58
+ # central directory entries contain only fields that didn't fit in the main entry part
59
+ packed = ''.force_encoding('BINARY')
60
+ packed << [@original_size].pack("Q<") if @original_size
61
+ packed << [@compressed_size].pack("Q<") if @compressed_size
62
+ packed << [@relative_header_offset].pack("Q<") if @relative_header_offset
63
+ packed << [@disk_start_number].pack("V") if @disk_start_number
64
+ packed
28
65
  end
29
66
  end
30
67
  end
@@ -0,0 +1,16 @@
1
+ module Zip
2
+ # placeholder to reserve space for a Zip64 extra information record, for the
3
+ # local file header only, that we won't know if we'll need until after
4
+ # we write the file data
5
+ class ExtraField::Zip64Placeholder < ExtraField::Generic
6
+ HEADER_ID = ['9999'].pack('H*') # this ID is used by other libraries such as .NET's Ionic.zip
7
+ register_map
8
+
9
+ def initialize(binstr = nil)
10
+ end
11
+
12
+ def pack_for_local
13
+ "\x00" * 16
14
+ end
15
+ end
16
+ end
@@ -44,12 +44,12 @@ module Zip
44
44
 
45
45
  class File < CentralDirectory
46
46
 
47
- CREATE = 1
48
- SPLIT_SIGNATURE = 0x08074b50
47
+ CREATE = 1
48
+ SPLIT_SIGNATURE = 0x08074b50
49
49
  ZIP64_EOCD_SIGNATURE = 0x06064b50
50
- MAX_SEGMENT_SIZE = 3221225472
51
- MIN_SEGMENT_SIZE = 65536
52
- DATA_BUFFER_SIZE = 8192
50
+ MAX_SEGMENT_SIZE = 3221225472
51
+ MIN_SEGMENT_SIZE = 65536
52
+ DATA_BUFFER_SIZE = 8192
53
53
 
54
54
  attr_reader :name
55
55
 
@@ -64,35 +64,36 @@ module Zip
64
64
 
65
65
  # Opens a zip archive. Pass true as the second parameter to create
66
66
  # a new archive if it doesn't exist already.
67
- def initialize(fileName, create = nil, buffer = false)
67
+ def initialize(file_name, create = nil, buffer = false, options = {})
68
68
  super()
69
- @name = fileName
69
+ @name = file_name
70
70
  @comment = ''
71
- @create = create
71
+ @create = create
72
72
  case
73
- when ::File.exists?(fileName) && !buffer
73
+ when ::File.exists?(file_name) && !buffer
74
74
  @create = nil
75
+ @exist_file_perms = ::File.stat(file_name).mode
75
76
  ::File.open(name, 'rb') do |f|
76
77
  read_from_stream(f)
77
78
  end
78
79
  when create
79
80
  @entry_set = EntrySet.new
80
81
  else
81
- raise ZipError, "File #{fileName} not found"
82
+ raise ZipError, "File #{file_name} not found"
82
83
  end
83
- @storedEntries = @entry_set.dup
84
- @storedComment = @comment
85
- @restore_ownership = false
86
- @restore_permissions = false
87
- @restore_times = true
84
+ @stored_entries = @entry_set.dup
85
+ @stored_comment = @comment
86
+ @restore_ownership = options[:restore_ownership] || false
87
+ @restore_permissions = options[:restore_permissions] || true
88
+ @restore_times = options[:restore_times] || true
88
89
  end
89
90
 
90
91
  class << self
91
92
  # Same as #new. If a block is passed the ZipFile object is passed
92
93
  # to the block and is automatically closed afterwards just as with
93
94
  # ruby's builtin File.open method.
94
- def open(fileName, create = nil)
95
- zf = ::Zip::File.new(fileName, create)
95
+ def open(file_name, create = nil)
96
+ zf = ::Zip::File.new(file_name, create)
96
97
  if block_given?
97
98
  begin
98
99
  yield zf
@@ -115,12 +116,12 @@ module Zip
115
116
  # stream, and outputs data to a buffer.
116
117
  # (This can be used to extract data from a
117
118
  # downloaded zip archive without first saving it to disk.)
118
- def open_buffer(io)
119
- unless io.is_a?(IO) && io.is_a?(String)
120
- raise "Zip::ZipFile.open_buffer expects an argument of class String or IO. Found: #{io.class}"
119
+ def open_buffer(io, options = {})
120
+ unless io.is_a?(IO) || io.is_a?(String)
121
+ raise "Zip::File.open_buffer expects an argument of class String or IO. Found: #{io.class}"
121
122
  end
122
- zf = ::Zip::File.new('', true, true)
123
- if io.is_a(::String)
123
+ zf = ::Zip::File.new('', true, true, options)
124
+ if io.is_a?(::String)
124
125
  require 'stringio'
125
126
  io = ::StringIO.new(io)
126
127
  end
@@ -173,8 +174,8 @@ module Zip
173
174
  # TODO: Make the code more understandable
174
175
  #
175
176
  def save_splited_part(zip_file, partial_zip_file_name, zip_file_size, szip_file_index, segment_size, segment_count)
176
- ssegment_size = zip_file_size - zip_file.pos
177
- ssegment_size = segment_size if ssegment_size > segment_size
177
+ ssegment_size = zip_file_size - zip_file.pos
178
+ ssegment_size = segment_size if ssegment_size > segment_size
178
179
  szip_file_name = "#{partial_zip_file_name}.#{'%03d'%(szip_file_index)}"
179
180
  ::File.open(szip_file_name, 'wb') do |szip_file|
180
181
  if szip_file_index == 1
@@ -224,11 +225,18 @@ module Zip
224
225
  get_entry(entry).get_input_stream(&aProc)
225
226
  end
226
227
 
227
- # Returns an output stream to the specified entry. If a block is passed
228
- # the stream object is passed to the block and the stream is automatically
229
- # closed afterwards just as with ruby's builtin File.open method.
230
- def get_output_stream(entry, permissionInt = nil, &aProc)
231
- newEntry = entry.kind_of?(Entry) ? entry : Entry.new(@name, entry.to_s)
228
+ # Returns an output stream to the specified entry. If entry is not an instance
229
+ # of Zip::Entry, a new Zip::Entry will be initialized using the arguments
230
+ # specified. If a block is passed the stream object is passed to the block and
231
+ # the stream is automatically closed afterwards just as with ruby's builtin
232
+ # File.open method.
233
+ def get_output_stream(entry, permissionInt = nil, comment = nil, extra = nil, compressed_size = nil, crc = nil, compression_method = nil, size = nil, time = nil, &aProc)
234
+ newEntry =
235
+ if entry.kind_of?(Entry)
236
+ entry
237
+ else
238
+ Entry.new(@name, entry.to_s, comment, extra, compressed_size, crc, compression_method, size, time)
239
+ end
232
240
  if newEntry.directory?
233
241
  raise ArgumentError,
234
242
  "cannot open stream to directory entry - '#{newEntry}'"
@@ -291,30 +299,25 @@ module Zip
291
299
  # the zip archive.
292
300
  def commit
293
301
  return if !commit_required?
294
- on_success_replace(name) {
295
- |tmpFile|
296
- OutputStream.open(tmpFile) {
297
- |zos|
298
-
299
- @entry_set.each {
300
- |e|
302
+ on_success_replace do |tmpFile|
303
+ ::Zip::OutputStream.open(tmpFile) do |zos|
304
+ @entry_set.each do |e|
301
305
  e.write_to_zip_output_stream(zos)
302
306
  e.dirty = false
303
- }
307
+ end
304
308
  zos.comment = comment
305
- }
309
+ end
306
310
  true
307
- }
311
+ end
308
312
  initialize(name)
309
313
  end
310
314
 
311
315
  # Write buffer write changes to buffer and return
312
316
  def write_buffer
313
- buffer = OutputStream.write_buffer do |zos|
317
+ OutputStream.write_buffer do |zos|
314
318
  @entry_set.each { |e| e.write_to_zip_output_stream(zos) }
315
319
  zos.comment = comment
316
320
  end
317
- return buffer
318
321
  end
319
322
 
320
323
  # Closes the zip file committing any changes that has been made.
@@ -328,7 +331,7 @@ module Zip
328
331
  @entry_set.each do |e|
329
332
  return true if e.dirty
330
333
  end
331
- @comment != @storedComment || @entry_set != @storedEntries || @create == File::CREATE
334
+ @comment != @stored_comment || @entry_set != @stored_entries || @create == File::CREATE
332
335
  end
333
336
 
334
337
  # Searches for entry with the specified name. Returns nil if
@@ -345,14 +348,14 @@ module Zip
345
348
  # Searches for an entry just as find_entry, but throws Errno::ENOENT
346
349
  # if no entry is found.
347
350
  def get_entry(entry)
348
- selectedEntry = find_entry(entry)
349
- unless selectedEntry
351
+ selected_entry = find_entry(entry)
352
+ unless selected_entry
350
353
  raise Errno::ENOENT, entry
351
354
  end
352
- selectedEntry.restore_ownership = @restore_ownership
353
- selectedEntry.restore_permissions = @restore_permissions
354
- selectedEntry.restore_times = @restore_times
355
- selectedEntry
355
+ selected_entry.restore_ownership = @restore_ownership
356
+ selected_entry.restore_permissions = @restore_permissions
357
+ selected_entry.restore_times = @restore_times
358
+ selected_entry
356
359
  end
357
360
 
358
361
  # Creates a directory
@@ -362,7 +365,7 @@ module Zip
362
365
  end
363
366
  entryName = entryName.dup.to_s
364
367
  entryName << '/' unless entryName.end_with?('/')
365
- @entry_set << StreamableDirectory.new(@name, entryName, nil, permissionInt)
368
+ @entry_set << ::Zip::StreamableDirectory.new(@name, entryName, nil, permissionInt)
366
369
  end
367
370
 
368
371
  private
@@ -397,19 +400,22 @@ module Zip
397
400
  end
398
401
  end
399
402
 
400
- def on_success_replace(aFilename)
403
+ def on_success_replace
401
404
  tmpfile = get_tempfile
402
- tmpFilename = tmpfile.path
405
+ tmp_filename = tmpfile.path
403
406
  tmpfile.close
404
- if yield tmpFilename
405
- ::File.rename(tmpFilename, name)
407
+ if yield tmp_filename
408
+ ::File.rename(tmp_filename, self.name)
409
+ if defined?(@exist_file_perms)
410
+ ::File.chmod(@exist_file_perms, self.name)
411
+ end
406
412
  end
407
413
  end
408
414
 
409
415
  def get_tempfile
410
- tempFile = Tempfile.new(::File.basename(name), ::File.dirname(name))
411
- tempFile.binmode
412
- tempFile
416
+ temp_file = Tempfile.new(::File.basename(name), ::File.dirname(name))
417
+ temp_file.binmode
418
+ temp_file
413
419
  end
414
420
 
415
421
  end
@@ -6,8 +6,8 @@ module Zip
6
6
  # a zip archive that is similar to ruby's builtin File and Dir
7
7
  # classes.
8
8
  #
9
- # Requiring 'zip/zipfilesystem' includes this module in ZipFile
10
- # making the methods in this module available on ZipFile objects.
9
+ # Requiring 'zip/filesystem' includes this module in Zip::File
10
+ # making the methods in this module available on Zip::File objects.
11
11
  #
12
12
  # Using this API the following example creates a new zip file
13
13
  # <code>my.zip</code> containing a normal entry with the name
@@ -16,7 +16,7 @@ module Zip
16
16
  #
17
17
  # require 'zip/filesystem'
18
18
  #
19
- # Zip::File.open("my.zip", Zip::ZipFile::CREATE) {
19
+ # Zip::File.open("my.zip", Zip::File::CREATE) {
20
20
  # |zipfile|
21
21
  # zipfile.file.open("first.txt", "w") { |f| f.puts "Hello world" }
22
22
  # zipfile.dir.mkdir("mydir")
@@ -45,22 +45,22 @@ module Zip
45
45
  end
46
46
 
47
47
  # Returns a ZipFsDir which is much like ruby's builtin Dir (class)
48
- # object, except it works on the ZipFile on which this method is
48
+ # object, except it works on the Zip::File on which this method is
49
49
  # invoked
50
50
  def dir
51
51
  @zipFsDir
52
52
  end
53
53
 
54
54
  # Returns a ZipFsFile which is much like ruby's builtin File (class)
55
- # object, except it works on the ZipFile on which this method is
55
+ # object, except it works on the Zip::File on which this method is
56
56
  # invoked
57
57
  def file
58
58
  @zipFsFile
59
59
  end
60
60
 
61
61
  # Instances of this class are normally accessed via the accessor
62
- # ZipFile::file. An instance of ZipFsFile behaves like ruby's
63
- # builtin File (class) object, except it works on ZipFile entries.
62
+ # Zip::File::file. An instance of ZipFsFile behaves like ruby's
63
+ # builtin File (class) object, except it works on Zip::File entries.
64
64
  #
65
65
  # The individual methods are not documented due to their
66
66
  # similarity with the methods in File
@@ -543,7 +543,7 @@ module Zip
543
543
  end
544
544
  end
545
545
 
546
- # All access to ZipFile from ZipFsFile and ZipFsDir goes through a
546
+ # All access to Zip::File from ZipFsFile and ZipFsDir goes through a
547
547
  # ZipFileNameMapper, which has one responsibility: ensure
548
548
  class ZipFileNameMapper # :nodoc:all
549
549
  include Enumerable
@@ -7,9 +7,9 @@ module Zip
7
7
  @has_returned_empty_string = false
8
8
  end
9
9
 
10
- def sysread(number_of_bytes = nil, buf = nil)
10
+ def sysread(number_of_bytes = nil, buf = '')
11
11
  readEverything = number_of_bytes.nil?
12
- while (readEverything || @output_buffer.bytesize < number_of_bytes)
12
+ while readEverything || @output_buffer.bytesize < number_of_bytes
13
13
  break if internal_input_finished?
14
14
  @output_buffer << internal_produce_input(buf)
15
15
  end
@@ -37,7 +37,7 @@ module Zip
37
37
 
38
38
  private
39
39
 
40
- def internal_produce_input(buf = nil)
40
+ def internal_produce_input(buf = '')
41
41
  retried = 0
42
42
  begin
43
43
  @zlib_inflater.inflate(@input_stream.read(Decompressor::CHUNK_SIZE, buf))
@@ -1,41 +1,39 @@
1
1
  module Zip
2
- # ZipInputStream is the basic class for reading zip entries in a
3
- # zip file. It is possible to create a ZipInputStream object directly,
2
+ # InputStream is the basic class for reading zip entries in a
3
+ # zip file. It is possible to create a InputStream object directly,
4
4
  # passing the zip file name to the constructor, but more often than not
5
- # the ZipInputStream will be obtained from a ZipFile (perhaps using the
5
+ # the InputStream will be obtained from a File (perhaps using the
6
6
  # ZipFileSystem interface) object for a particular entry in the zip
7
7
  # archive.
8
8
  #
9
- # A ZipInputStream inherits IOExtras::AbstractInputStream in order
9
+ # A InputStream inherits IOExtras::AbstractInputStream in order
10
10
  # to provide an IO-like interface for reading from a single zip
11
11
  # entry. Beyond methods for mimicking an IO-object it contains
12
12
  # the method get_next_entry for iterating through the entries of
13
- # an archive. get_next_entry returns a ZipEntry object that describes
14
- # the zip entry the ZipInputStream is currently reading from.
13
+ # an archive. get_next_entry returns a Entry object that describes
14
+ # the zip entry the InputStream is currently reading from.
15
15
  #
16
16
  # Example that creates a zip archive with ZipOutputStream and reads it
17
- # back again with a ZipInputStream.
17
+ # back again with a InputStream.
18
18
  #
19
- # require 'zip/zip'
19
+ # require 'zip'
20
20
  #
21
- # Zip::ZipOutputStream::open("my.zip") {
22
- # |io|
21
+ # Zip::OutputStream.open("my.zip") do |io|
23
22
  #
24
23
  # io.put_next_entry("first_entry.txt")
25
24
  # io.write "Hello world!"
26
25
  #
27
26
  # io.put_next_entry("adir/first_entry.txt")
28
27
  # io.write "Hello again!"
29
- # }
28
+ # end
30
29
  #
31
30
  #
32
- # Zip::ZipInputStream::open("my.zip") {
33
- # |io|
31
+ # Zip::InputStream.open("my.zip") do |io|
34
32
  #
35
33
  # while (entry = io.get_next_entry)
36
34
  # puts "Contents of #{entry.name}: '#{io.read}'"
37
35
  # end
38
- # }
36
+ # end
39
37
  #
40
38
  # java.util.zip.ZipInputStream is the original inspiration for this
41
39
  # class.
@@ -46,88 +44,101 @@ module Zip
46
44
  # Opens the indicated zip file. An exception is thrown
47
45
  # if the specified offset in the specified filename is
48
46
  # not a local zip entry header.
49
- def initialize(filename, offset = 0, io = nil)
47
+ #
48
+ # @param context [String||IO||StringIO] file path or IO/StringIO object
49
+ # @param offset [Integer] offset in the IO/StringIO
50
+ def initialize(context, offset = 0)
50
51
  super()
51
- if (io.nil?)
52
- @archiveIO = ::File.open(filename, "rb")
53
- @archiveIO.seek(offset, IO::SEEK_SET)
54
- else
55
- @archiveIO = io
56
- end
57
- @decompressor = NullDecompressor.instance
58
- @currentEntry = nil
59
- end
60
-
61
- def close
62
- @archiveIO.close
63
- end
64
-
65
- # Same as #initialize but if a block is passed the opened
66
- # stream is passed to the block and closed when the block
67
- # returns.
68
- def InputStream.open(filename)
69
- return new(filename) unless block_given?
70
-
71
- zio = new(filename)
72
- yield zio
73
- ensure
74
- zio.close if zio
52
+ @archive_io = get_io(context, offset)
53
+ @decompressor = ::Zip::NullDecompressor
54
+ @current_entry = nil
75
55
  end
76
56
 
77
- def InputStream.open_buffer(io)
78
- return new('',0,io) unless block_given?
79
- zio = new('',0,io)
80
- yield zio
81
- ensure
82
- zio.close if zio
57
+ def close
58
+ @archive_io.close
83
59
  end
84
60
 
85
- # Returns a ZipEntry object. It is necessary to call this
86
- # method on a newly created ZipInputStream before reading from
61
+ # Returns a Entry object. It is necessary to call this
62
+ # method on a newly created InputStream before reading from
87
63
  # the first entry in the archive. Returns nil when there are
88
64
  # no more entries.
89
-
90
65
  def get_next_entry
91
- @archiveIO.seek(@currentEntry.next_header_offset, IO::SEEK_SET) if @currentEntry
66
+ @archive_io.seek(@current_entry.next_header_offset, IO::SEEK_SET) if @current_entry
92
67
  open_entry
93
68
  end
94
69
 
95
70
  # Rewinds the stream to the beginning of the current entry
96
71
  def rewind
97
- return if @currentEntry.nil?
72
+ return if @current_entry.nil?
98
73
  @lineno = 0
99
- @pos = 0
100
- @archiveIO.seek(@currentEntry.local_header_offset,
101
- IO::SEEK_SET)
74
+ @pos = 0
75
+ @archive_io.seek(@current_entry.local_header_offset, IO::SEEK_SET)
102
76
  open_entry
103
77
  end
104
78
 
105
79
  # Modeled after IO.sysread
106
- def sysread(numberOfBytes = nil, buf = nil)
107
- @decompressor.sysread(numberOfBytes, buf)
80
+ def sysread(number_of_bytes = nil, buf = nil)
81
+ @decompressor.sysread(number_of_bytes, buf)
108
82
  end
109
83
 
110
84
  def eof
111
85
  @output_buffer.empty? && @decompressor.eof
112
86
  end
87
+
113
88
  alias :eof? :eof
114
89
 
90
+ class << self
91
+ # Same as #initialize but if a block is passed the opened
92
+ # stream is passed to the block and closed when the block
93
+ # returns.
94
+ def open(filename_or_io, offset = 0)
95
+ zio = self.new(filename_or_io, offset)
96
+ return zio unless block_given?
97
+ begin
98
+ yield zio
99
+ ensure
100
+ zio.close if zio
101
+ end
102
+ end
103
+
104
+ def open_buffer(filename_or_io, offset = 0)
105
+ puts "open_buffer is deprecated!!! Use open instead!"
106
+ self.open(filename_or_io, offset)
107
+ end
108
+ end
109
+
115
110
  protected
116
111
 
117
- def open_entry
118
- @currentEntry = Entry.read_local_entry(@archiveIO)
119
- if @currentEntry.nil?
120
- @decompressor = NullDecompressor.instance
121
- elsif @currentEntry.compression_method == Entry::STORED
122
- @decompressor = PassThruDecompressor.new(@archiveIO, @currentEntry.size)
123
- elsif @currentEntry.compression_method == Entry::DEFLATED
124
- @decompressor = Inflater.new(@archiveIO)
112
+ def get_io(io_or_file, offset = 0)
113
+ case io_or_file
114
+ when IO, StringIO
115
+ io_or_file
125
116
  else
126
- raise ZipCompressionMethodError,
127
- "Unsupported compression method #{@currentEntry.compression_method}"
117
+ file = ::File.open(io_or_file, 'rb')
118
+ file.seek(offset, ::IO::SEEK_SET)
119
+ file
128
120
  end
121
+ end
122
+
123
+ def open_entry
124
+ @current_entry = ::Zip::Entry.read_local_entry(@archive_io)
125
+ @decompressor = get_decompressor
129
126
  flush
130
- return @currentEntry
127
+ @current_entry
128
+ end
129
+
130
+ def get_decompressor
131
+ case
132
+ when @current_entry.nil?
133
+ ::Zip::NullDecompressor
134
+ when @current_entry.compression_method == ::Zip::Entry::STORED
135
+ ::Zip::PassThruDecompressor.new(@archive_io, @current_entry.size)
136
+ when @current_entry.compression_method == ::Zip::Entry::DEFLATED
137
+ ::Zip::Inflater.new(@archive_io)
138
+ else
139
+ raise ZipCompressionMethodError,
140
+ "Unsupported compression method #{@current_entry.compression_method}"
141
+ end
131
142
  end
132
143
 
133
144
  def produce_input