rubyzip 2.4.1 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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