rubyzip 2.4.1 → 3.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +419 -0
  3. data/LICENSE.md +24 -0
  4. data/README.md +137 -37
  5. data/Rakefile +11 -7
  6. data/lib/zip/central_directory.rb +169 -123
  7. data/lib/zip/compressor.rb +3 -1
  8. data/lib/zip/constants.rb +29 -21
  9. data/lib/zip/crypto/decrypted_io.rb +4 -2
  10. data/lib/zip/crypto/encryption.rb +4 -2
  11. data/lib/zip/crypto/null_encryption.rb +6 -4
  12. data/lib/zip/crypto/traditional_encryption.rb +8 -6
  13. data/lib/zip/decompressor.rb +4 -3
  14. data/lib/zip/deflater.rb +10 -8
  15. data/lib/zip/dirtyable.rb +32 -0
  16. data/lib/zip/dos_time.rb +43 -4
  17. data/lib/zip/entry.rb +333 -242
  18. data/lib/zip/entry_set.rb +11 -9
  19. data/lib/zip/errors.rb +136 -16
  20. data/lib/zip/extra_field/generic.rb +6 -13
  21. data/lib/zip/extra_field/ntfs.rb +6 -4
  22. data/lib/zip/extra_field/old_unix.rb +3 -1
  23. data/lib/zip/extra_field/universal_time.rb +3 -1
  24. data/lib/zip/extra_field/unix.rb +5 -3
  25. data/lib/zip/extra_field/unknown.rb +33 -0
  26. data/lib/zip/extra_field/zip64.rb +12 -5
  27. data/lib/zip/extra_field.rb +16 -22
  28. data/lib/zip/file.rb +166 -264
  29. data/lib/zip/file_split.rb +91 -0
  30. data/lib/zip/filesystem/dir.rb +86 -0
  31. data/lib/zip/filesystem/directory_iterator.rb +48 -0
  32. data/lib/zip/filesystem/file.rb +262 -0
  33. data/lib/zip/filesystem/file_stat.rb +110 -0
  34. data/lib/zip/filesystem/zip_file_name_mapper.rb +81 -0
  35. data/lib/zip/filesystem.rb +27 -596
  36. data/lib/zip/inflater.rb +7 -5
  37. data/lib/zip/input_stream.rb +50 -50
  38. data/lib/zip/ioextras/abstract_input_stream.rb +16 -11
  39. data/lib/zip/ioextras/abstract_output_stream.rb +5 -3
  40. data/lib/zip/ioextras.rb +7 -7
  41. data/lib/zip/null_compressor.rb +3 -1
  42. data/lib/zip/null_decompressor.rb +3 -1
  43. data/lib/zip/null_input_stream.rb +3 -1
  44. data/lib/zip/output_stream.rb +55 -56
  45. data/lib/zip/pass_thru_compressor.rb +3 -1
  46. data/lib/zip/pass_thru_decompressor.rb +4 -2
  47. data/lib/zip/streamable_directory.rb +3 -1
  48. data/lib/zip/streamable_stream.rb +3 -0
  49. data/lib/zip/version.rb +3 -1
  50. data/lib/zip.rb +18 -22
  51. data/rubyzip.gemspec +39 -0
  52. data/samples/example.rb +8 -3
  53. data/samples/example_filesystem.rb +3 -2
  54. data/samples/example_recursive.rb +3 -1
  55. data/samples/gtk_ruby_zip.rb +4 -2
  56. data/samples/qtzip.rb +6 -5
  57. data/samples/write_simple.rb +2 -1
  58. data/samples/zipfind.rb +1 -0
  59. metadata +87 -51
  60. data/TODO +0 -15
  61. data/lib/zip/extra_field/zip64_placeholder.rb +0 -15
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
1
4
  module Zip
2
5
  # InputStream is the basic class for reading zip entries in a
3
6
  # zip file. It is possible to create a InputStream object directly,
@@ -37,9 +40,8 @@ module Zip
37
40
  #
38
41
  # java.util.zip.ZipInputStream is the original inspiration for this
39
42
  # class.
40
-
41
43
  class InputStream
42
- CHUNK_SIZE = 32_768
44
+ CHUNK_SIZE = 32_768 # :nodoc:
43
45
 
44
46
  include ::Zip::IOExtras::AbstractInputStream
45
47
 
@@ -49,34 +51,35 @@ module Zip
49
51
  #
50
52
  # @param context [String||IO||StringIO] file path or IO/StringIO object
51
53
  # @param offset [Integer] offset in the IO/StringIO
52
- def initialize(context, dep_offset = 0, dep_decrypter = nil, offset: 0, decrypter: nil)
54
+ def initialize(context, offset: 0, decrypter: nil)
53
55
  super()
54
-
55
- if !dep_offset.zero? || !dep_decrypter.nil?
56
- Zip.warn_about_v3_api('Zip::InputStream.new')
57
- end
58
-
59
- offset = dep_offset if offset.zero?
60
- @archive_io = get_io(context, offset)
61
- @decompressor = ::Zip::NullDecompressor
62
- @decrypter = decrypter || dep_decrypter || ::Zip::NullDecrypter.new
56
+ @archive_io = get_io(context, offset)
57
+ @decompressor = ::Zip::NullDecompressor
58
+ @decrypter = decrypter || ::Zip::NullDecrypter.new
63
59
  @current_entry = nil
60
+ @complete_entry = nil
64
61
  end
65
62
 
63
+ # Close this InputStream. All further IO will raise an IOError.
66
64
  def close
67
65
  @archive_io.close
68
66
  end
69
67
 
70
- # Returns a Entry object. It is necessary to call this
71
- # method on a newly created InputStream before reading from
72
- # the first entry in the archive. Returns nil when there are
73
- # no more entries.
68
+ # Returns an Entry object and positions the stream at the beginning of
69
+ # the entry data. It is necessary to call this method on a newly created
70
+ # InputStream before reading from the first entry in the archive.
71
+ # Returns nil when there are no more entries.
74
72
  def get_next_entry
75
- @archive_io.seek(@current_entry.next_header_offset, IO::SEEK_SET) if @current_entry
73
+ unless @current_entry.nil?
74
+ raise StreamingError, @current_entry if @current_entry.incomplete?
75
+
76
+ @archive_io.seek(@current_entry.next_header_offset, IO::SEEK_SET)
77
+ end
78
+
76
79
  open_entry
77
80
  end
78
81
 
79
- # Rewinds the stream to the beginning of the current entry
82
+ # Rewinds the stream to the beginning of the current entry.
80
83
  def rewind
81
84
  return if @current_entry.nil?
82
85
 
@@ -91,18 +94,19 @@ module Zip
91
94
  @decompressor.read(length, outbuf)
92
95
  end
93
96
 
97
+ # Returns the size of the current entry, or `nil` if there isn't one.
98
+ def size
99
+ return if @current_entry.nil?
100
+
101
+ @current_entry.size
102
+ end
103
+
94
104
  class << self
95
105
  # Same as #initialize but if a block is passed the opened
96
106
  # stream is passed to the block and closed when the block
97
107
  # returns.
98
- def open(filename_or_io, dep_offset = 0, dep_decrypter = nil, offset: 0, decrypter: nil)
99
- if !dep_offset.zero? || !dep_decrypter.nil?
100
- Zip.warn_about_v3_api('Zip::InputStream.new')
101
- end
102
-
103
- offset = dep_offset if offset.zero?
104
-
105
- zio = new(filename_or_io, offset: offset, decrypter: decrypter || dep_decrypter)
108
+ def open(filename_or_io, offset: 0, decrypter: nil)
109
+ zio = new(filename_or_io, offset: offset, decrypter: decrypter)
106
110
  return zio unless block_given?
107
111
 
108
112
  begin
@@ -111,17 +115,11 @@ module Zip
111
115
  zio.close if zio
112
116
  end
113
117
  end
114
-
115
- def open_buffer(filename_or_io, offset = 0)
116
- Zip.warn_about_v3_api('Zip::InputStream.open_buffer')
117
-
118
- ::Zip::InputStream.open(filename_or_io, offset)
119
- end
120
118
  end
121
119
 
122
120
  protected
123
121
 
124
- def get_io(io_or_file, offset = 0)
122
+ def get_io(io_or_file, offset = 0) # :nodoc:
125
123
  if io_or_file.respond_to?(:seek)
126
124
  io = io_or_file.dup
127
125
  io.seek(offset, ::IO::SEEK_SET)
@@ -133,56 +131,58 @@ module Zip
133
131
  end
134
132
  end
135
133
 
136
- def open_entry
134
+ def open_entry # :nodoc:
137
135
  @current_entry = ::Zip::Entry.read_local_entry(@archive_io)
138
- if @current_entry && @current_entry.encrypted? && @decrypter.kind_of?(NullEncrypter)
139
- raise Error, 'password required to decode zip file'
136
+ return if @current_entry.nil?
137
+
138
+ if @current_entry.encrypted? && @decrypter.kind_of?(NullDecrypter)
139
+ raise Error,
140
+ 'A password is required to decode this zip file'
140
141
  end
141
142
 
142
- if @current_entry && @current_entry.incomplete? && @current_entry.crc == 0 \
143
- && @current_entry.compressed_size == 0 \
144
- && @current_entry.size == 0 && !@complete_entry
145
- raise GPFBit3Error,
146
- 'General purpose flag Bit 3 is set so not possible to get proper info from local header.' \
147
- 'Please use ::Zip::File instead of ::Zip::InputStream'
143
+ if @current_entry.incomplete? && @current_entry.compressed_size == 0 && !@complete_entry
144
+ raise StreamingError, @current_entry
148
145
  end
146
+
149
147
  @decrypted_io = get_decrypted_io
150
148
  @decompressor = get_decompressor
151
149
  flush
152
150
  @current_entry
153
151
  end
154
152
 
155
- def get_decrypted_io
153
+ def get_decrypted_io # :nodoc:
156
154
  header = @archive_io.read(@decrypter.header_bytesize)
157
155
  @decrypter.reset!(header)
158
156
 
159
157
  ::Zip::DecryptedIo.new(@archive_io, @decrypter)
160
158
  end
161
159
 
162
- def get_decompressor
160
+ def get_decompressor # :nodoc:
163
161
  return ::Zip::NullDecompressor if @current_entry.nil?
164
162
 
165
163
  decompressed_size =
166
- if @current_entry.incomplete? && @current_entry.crc == 0 && @current_entry.size == 0 && @complete_entry
164
+ if @current_entry.incomplete? && @current_entry.crc == 0 &&
165
+ @current_entry.size == 0 && @complete_entry
167
166
  @complete_entry.size
168
167
  else
169
168
  @current_entry.size
170
169
  end
171
170
 
172
- decompressor_class = ::Zip::Decompressor.find_by_compression_method(@current_entry.compression_method)
171
+ decompressor_class = ::Zip::Decompressor.find_by_compression_method(
172
+ @current_entry.compression_method
173
+ )
173
174
  if decompressor_class.nil?
174
- raise ::Zip::CompressionMethodError,
175
- "Unsupported compression method #{@current_entry.compression_method}"
175
+ raise ::Zip::CompressionMethodError, @current_entry.compression_method
176
176
  end
177
177
 
178
178
  decompressor_class.new(@decrypted_io, decompressed_size)
179
179
  end
180
180
 
181
- def produce_input
181
+ def produce_input # :nodoc:
182
182
  @decompressor.read(CHUNK_SIZE)
183
183
  end
184
184
 
185
- def input_finished?
185
+ def input_finished? # :nodoc:
186
186
  @decompressor.eof
187
187
  end
188
188
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Zip
2
- module IOExtras
4
+ module IOExtras # :nodoc:
3
5
  # Implements many of the convenience methods of IO
4
6
  # such as gets, getc, readline and readlines
5
7
  # depends on: input_finished?, produce_input and read
6
- module AbstractInputStream
8
+ module AbstractInputStream # :nodoc:
7
9
  include Enumerable
8
10
  include FakeIO
9
11
 
@@ -11,22 +13,22 @@ module Zip
11
13
  super
12
14
  @lineno = 0
13
15
  @pos = 0
14
- @output_buffer = ''.b
16
+ @output_buffer = +''
15
17
  end
16
18
 
17
19
  attr_accessor :lineno
18
20
  attr_reader :pos
19
21
 
20
- def read(number_of_bytes = nil, buf = ''.b)
22
+ def read(number_of_bytes = nil, buf = +'')
21
23
  tbuf = if @output_buffer.bytesize > 0
22
- if number_of_bytes <= @output_buffer.bytesize
24
+ if number_of_bytes && number_of_bytes <= @output_buffer.bytesize
23
25
  @output_buffer.slice!(0, number_of_bytes)
24
26
  else
25
27
  number_of_bytes -= @output_buffer.bytesize if number_of_bytes
26
28
  rbuf = sysread(number_of_bytes, buf)
27
29
  out = @output_buffer
28
30
  out << rbuf if rbuf
29
- @output_buffer = ''.b
31
+ @output_buffer = ''
30
32
  out
31
33
  end
32
34
  else
@@ -34,7 +36,7 @@ module Zip
34
36
  end
35
37
 
36
38
  if tbuf.nil? || tbuf.empty?
37
- return nil if number_of_bytes
39
+ return nil if number_of_bytes&.positive?
38
40
 
39
41
  return ''
40
42
  end
@@ -74,15 +76,18 @@ module Zip
74
76
  a_sep_string = "#{$INPUT_RECORD_SEPARATOR}#{$INPUT_RECORD_SEPARATOR}" if a_sep_string.empty?
75
77
 
76
78
  buffer_index = 0
77
- over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
79
+ over_limit = number_of_bytes && @output_buffer.bytesize >= number_of_bytes
78
80
  while (match_index = @output_buffer.index(a_sep_string, buffer_index)).nil? && !over_limit
79
81
  buffer_index = [buffer_index, @output_buffer.bytesize - a_sep_string.bytesize].max
80
82
  return @output_buffer.empty? ? nil : flush if input_finished?
81
83
 
82
84
  @output_buffer << produce_input
83
- over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
85
+ over_limit = number_of_bytes && @output_buffer.bytesize >= number_of_bytes
84
86
  end
85
- sep_index = [match_index + a_sep_string.bytesize, number_of_bytes || @output_buffer.bytesize].min
87
+ sep_index = [
88
+ match_index + a_sep_string.bytesize,
89
+ number_of_bytes || @output_buffer.bytesize
90
+ ].min
86
91
  @pos += sep_index
87
92
  @output_buffer.slice!(0...sep_index)
88
93
  end
@@ -93,7 +98,7 @@ module Zip
93
98
 
94
99
  def flush
95
100
  ret_val = @output_buffer
96
- @output_buffer = ''.b
101
+ @output_buffer = +''
97
102
  ret_val
98
103
  end
99
104
 
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Zip
2
- module IOExtras
4
+ module IOExtras # :nodoc:
3
5
  # Implements many of the output convenience methods of IO.
4
6
  # relies on <<
5
- module AbstractOutputStream
7
+ module AbstractOutputStream # :nodoc:
6
8
  include FakeIO
7
9
 
8
10
  def write(data)
@@ -11,7 +13,7 @@ module Zip
11
13
  end
12
14
 
13
15
  def print(*params)
14
- self << params.join($OUTPUT_FIELD_SEPARATOR) << $OUTPUT_RECORD_SEPARATOR.to_s
16
+ self << params.join << $OUTPUT_RECORD_SEPARATOR.to_s
15
17
  end
16
18
 
17
19
  def printf(a_format_string, *params)
data/lib/zip/ioextras.rb CHANGED
@@ -1,26 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Zip
2
- module IOExtras #:nodoc:
4
+ module IOExtras # :nodoc:
3
5
  CHUNK_SIZE = 131_072
4
6
 
5
- RANGE_ALL = 0..-1
6
-
7
7
  class << self
8
8
  def copy_stream(ostream, istream)
9
- ostream.write(istream.read(CHUNK_SIZE, ''.b)) until istream.eof?
9
+ ostream.write(istream.read(CHUNK_SIZE, +'')) until istream.eof?
10
10
  end
11
11
 
12
12
  def copy_stream_n(ostream, istream, nbytes)
13
13
  toread = nbytes
14
14
  while toread > 0 && !istream.eof?
15
- tr = toread > CHUNK_SIZE ? CHUNK_SIZE : toread
16
- ostream.write(istream.read(tr, ''.b))
15
+ tr = [toread, CHUNK_SIZE].min
16
+ ostream.write(istream.read(tr, +''))
17
17
  toread -= tr
18
18
  end
19
19
  end
20
20
  end
21
21
 
22
22
  # Implements kind_of? in order to pretend to be an IO object
23
- module FakeIO
23
+ module FakeIO # :nodoc:
24
24
  def kind_of?(object)
25
25
  object == IO || super
26
26
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Zip
2
- class NullCompressor < Compressor #:nodoc:all
4
+ class NullCompressor < Compressor # :nodoc:all
3
5
  include Singleton
4
6
 
5
7
  def <<(_data)
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Zip
2
- module NullDecompressor #:nodoc:all
4
+ module NullDecompressor # :nodoc:all
3
5
  module_function
4
6
 
5
7
  def read(_length = nil, _outbuf = nil)
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Zip
2
- module NullInputStream #:nodoc:all
4
+ module NullInputStream # :nodoc:all
3
5
  include ::Zip::NullDecompressor
4
6
  include ::Zip::IOExtras::AbstractInputStream
5
7
  end
@@ -1,3 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ ##
1
6
  module Zip
2
7
  # ZipOutputStream is the basic class for writing zip files. It is
3
8
  # possible to create a ZipOutputStream object directly, passing
@@ -16,57 +21,49 @@ module Zip
16
21
  #
17
22
  # java.util.zip.ZipOutputStream is the original inspiration for this
18
23
  # class.
19
-
20
24
  class OutputStream
25
+ extend Forwardable
21
26
  include ::Zip::IOExtras::AbstractOutputStream
22
27
 
23
- attr_accessor :comment
28
+ def_delegators :@cdir, :comment, :comment=
24
29
 
25
30
  # Opens the indicated zip file. If a file with that name already
26
31
  # exists it will be overwritten.
27
- def initialize(file_name, dep_stream = false, dep_encrypter = nil, stream: false, encrypter: nil)
32
+ def initialize(file_name, stream: false, encrypter: nil)
28
33
  super()
29
-
30
- Zip.warn_about_v3_api('Zip::OutputStream.new') if dep_stream || !dep_encrypter.nil?
31
-
32
34
  @file_name = file_name
33
- @output_stream = if stream || dep_stream
34
- iostream = @file_name.dup
35
+ @output_stream = if stream
36
+ iostream = Zip::RUNNING_ON_WINDOWS ? @file_name : @file_name.dup
35
37
  iostream.reopen(@file_name)
36
38
  iostream.rewind
37
39
  iostream
38
40
  else
39
41
  ::File.new(@file_name, 'wb')
40
42
  end
41
- @entry_set = ::Zip::EntrySet.new
43
+ @cdir = ::Zip::CentralDirectory.new
42
44
  @compressor = ::Zip::NullCompressor.instance
43
- @encrypter = encrypter || dep_encrypter || ::Zip::NullEncrypter.new
45
+ @encrypter = encrypter || ::Zip::NullEncrypter.new
44
46
  @closed = false
45
47
  @current_entry = nil
46
- @comment = nil
47
48
  end
48
49
 
49
- # Same as #initialize but if a block is passed the opened
50
- # stream is passed to the block and closed when the block
51
- # returns.
52
50
  class << self
53
- def open(file_name, dep_encrypter = nil, encrypter: nil)
51
+ # Same as #initialize but if a block is passed the opened
52
+ # stream is passed to the block and closed when the block
53
+ # returns.
54
+ def open(file_name, encrypter: nil)
54
55
  return new(file_name) unless block_given?
55
56
 
56
- Zip.warn_about_v3_api('Zip::OutputStream.open') unless dep_encrypter.nil?
57
-
58
- zos = new(file_name, stream: false, encrypter: (encrypter || dep_encrypter))
57
+ zos = new(file_name, stream: false, encrypter: encrypter)
59
58
  yield zos
60
59
  ensure
61
60
  zos.close if zos
62
61
  end
63
62
 
64
63
  # Same as #open but writes to a filestream instead
65
- def write_buffer(io = ::StringIO.new, dep_encrypter = nil, encrypter: nil)
66
- Zip.warn_about_v3_api('Zip::OutputStream.write_buffer') unless dep_encrypter.nil?
67
-
64
+ def write_buffer(io = ::StringIO.new, encrypter: nil)
68
65
  io.binmode if io.respond_to?(:binmode)
69
- zos = new(io, stream: true, encrypter: (encrypter || dep_encrypter))
66
+ zos = new(io, stream: true, encrypter: encrypter)
70
67
  yield zos
71
68
  zos.close_buffer
72
69
  end
@@ -78,7 +75,7 @@ module Zip
78
75
 
79
76
  finalize_current_entry
80
77
  update_local_headers
81
- write_central_directory
78
+ @cdir.write_to_stream(@output_stream)
82
79
  @output_stream.close
83
80
  @closed = true
84
81
  end
@@ -89,37 +86,41 @@ module Zip
89
86
 
90
87
  finalize_current_entry
91
88
  update_local_headers
92
- write_central_directory
89
+ @cdir.write_to_stream(@output_stream)
93
90
  @closed = true
91
+ @output_stream.flush
94
92
  @output_stream
95
93
  end
96
94
 
97
95
  # Closes the current entry and opens a new for writing.
98
96
  # +entry+ can be a ZipEntry object or a string.
99
- def put_next_entry(entry_name, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zip.default_compression)
97
+ def put_next_entry(
98
+ entry_name, comment = '', extra = ExtraField.new,
99
+ compression_method = Entry::DEFLATED, level = Zip.default_compression
100
+ )
100
101
  raise Error, 'zip stream is closed' if @closed
101
102
 
102
- new_entry = if entry_name.kind_of?(Entry)
103
- entry_name
104
- else
105
- Entry.new(@file_name, entry_name.to_s)
106
- end
107
- new_entry.comment = comment unless comment.nil?
108
- unless extra.nil?
109
- new_entry.extra = extra.kind_of?(ExtraField) ? extra : ExtraField.new(extra.to_s)
110
- end
111
- new_entry.compression_method = compression_method unless compression_method.nil?
112
- init_next_entry(new_entry, level)
103
+ new_entry =
104
+ if entry_name.kind_of?(Entry) || entry_name.kind_of?(StreamableStream)
105
+ entry_name
106
+ else
107
+ Entry.new(
108
+ @file_name, entry_name.to_s, comment: comment, extra: extra,
109
+ compression_method: compression_method, compression_level: level
110
+ )
111
+ end
112
+
113
+ init_next_entry(new_entry)
113
114
  @current_entry = new_entry
114
115
  end
115
116
 
116
- def copy_raw_entry(entry)
117
+ def copy_raw_entry(entry) # :nodoc:
117
118
  entry = entry.dup
118
119
  raise Error, 'zip stream is closed' if @closed
119
120
  raise Error, 'entry is not a ZipEntry' unless entry.kind_of?(Entry)
120
121
 
121
122
  finalize_current_entry
122
- @entry_set << entry
123
+ @cdir << entry
123
124
  src_pos = entry.local_header_offset
124
125
  entry.write_local_entry(@output_stream)
125
126
  @compressor = NullCompressor.instance
@@ -138,55 +139,53 @@ module Zip
138
139
  return unless @current_entry
139
140
 
140
141
  finish
141
- @current_entry.compressed_size = @output_stream.tell - \
142
- @current_entry.local_header_offset - \
142
+ @current_entry.compressed_size = @output_stream.tell -
143
+ @current_entry.local_header_offset -
143
144
  @current_entry.calculate_local_header_size
144
145
  @current_entry.size = @compressor.size
145
146
  @current_entry.crc = @compressor.crc
146
- @output_stream << @encrypter.data_descriptor(@current_entry.crc, @current_entry.compressed_size, @current_entry.size)
147
+ @output_stream << @encrypter.data_descriptor(
148
+ @current_entry.crc,
149
+ @current_entry.compressed_size,
150
+ @current_entry.size
151
+ )
147
152
  @current_entry.gp_flags |= @encrypter.gp_flags
148
153
  @current_entry = nil
149
154
  @compressor = ::Zip::NullCompressor.instance
150
155
  end
151
156
 
152
- def init_next_entry(entry, level = Zip.default_compression)
157
+ def init_next_entry(entry)
153
158
  finalize_current_entry
154
- @entry_set << entry
159
+ @cdir << entry
155
160
  entry.write_local_entry(@output_stream)
156
161
  @encrypter.reset!
157
162
  @output_stream << @encrypter.header(entry.mtime)
158
- @compressor = get_compressor(entry, level)
163
+ @compressor = get_compressor(entry)
159
164
  end
160
165
 
161
- def get_compressor(entry, level)
166
+ def get_compressor(entry)
162
167
  case entry.compression_method
163
168
  when Entry::DEFLATED
164
- ::Zip::Deflater.new(@output_stream, level, @encrypter)
169
+ ::Zip::Deflater.new(@output_stream, entry.compression_level, @encrypter)
165
170
  when Entry::STORED
166
171
  ::Zip::PassThruCompressor.new(@output_stream)
167
172
  else
168
- raise ::Zip::CompressionMethodError,
169
- "Invalid compression method: '#{entry.compression_method}'"
173
+ raise ::Zip::CompressionMethodError, entry.compression_method
170
174
  end
171
175
  end
172
176
 
173
177
  def update_local_headers
174
178
  pos = @output_stream.pos
175
- @entry_set.each do |entry|
179
+ @cdir.each do |entry|
176
180
  @output_stream.pos = entry.local_header_offset
177
- entry.write_local_entry(@output_stream, true)
181
+ entry.write_local_entry(@output_stream, rewrite: true)
178
182
  end
179
183
  @output_stream.pos = pos
180
184
  end
181
185
 
182
- def write_central_directory
183
- cdir = CentralDirectory.new(@entry_set, @comment)
184
- cdir.write_to_stream(@output_stream)
185
- end
186
-
187
186
  protected
188
187
 
189
- def finish
188
+ def finish # :nodoc:
190
189
  @compressor.finish
191
190
  end
192
191
 
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Zip
2
- class PassThruCompressor < Compressor #:nodoc:all
4
+ class PassThruCompressor < Compressor # :nodoc:all
3
5
  def initialize(output_stream)
4
6
  super()
5
7
  @output_stream = output_stream
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Zip
2
- class PassThruDecompressor < Decompressor #:nodoc:all
4
+ class PassThruDecompressor < Decompressor # :nodoc:all
3
5
  def initialize(*args)
4
6
  super
5
7
  @read_so_far = 0
6
8
  end
7
9
 
8
- def read(length = nil, outbuf = ''.b)
10
+ def read(length = nil, outbuf = +'')
9
11
  return (length.nil? || length.zero? ? '' : nil) if eof
10
12
 
11
13
  if length.nil? || (@read_so_far + length) > decompressed_size
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Zip
2
- class StreamableDirectory < Entry
4
+ class StreamableDirectory < Entry # :nodoc:
3
5
  def initialize(zipfile, entry, src_path = nil, permission = nil)
4
6
  super(zipfile, entry)
5
7
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Zip
2
4
  class StreamableStream < DelegateClass(Entry) # :nodoc:all
3
5
  def initialize(entry)
@@ -42,6 +44,7 @@ module Zip
42
44
  end
43
45
 
44
46
  def clean_up
47
+ super
45
48
  @temp_file.unlink
46
49
  end
47
50
  end
data/lib/zip/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Zip
2
- VERSION = '2.4.1'
4
+ VERSION = '3.0.0.rc1' # :nodoc:
3
5
  end