rubyzip 2.3.2 → 2.4.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35bd078119c42cd2250fadd127a0feae3299184b0bf90804c3ff0bc28d1c427f
4
- data.tar.gz: 98e034b50a428ff970f25b28348993d938a88c5d5c93506561761f260062c059
3
+ metadata.gz: 49b133beda4cc25cd86964b3d7ffdd774583a75889508916ea4dab892ea9275d
4
+ data.tar.gz: 85c81018a61dd9592e8c7081b4c1b1d07c8f40ccea75b2466be8509925abfad6
5
5
  SHA512:
6
- metadata.gz: 421a8884fbfe6f720e2e0da35f34e4208b96f83529faf5cba03501aa2693d95d51b9c19e04e4567801de1822120a0e14faf1c4d0991a164b8f0d011eaa6c0f7b
7
- data.tar.gz: 59f29c6b49a14c777605224b351d8d14f7fdfe88a2ffc75a5f2120f51152831ed9afa04d8daf1f971bad982c3bcdd86e17d5616c8c9d57ddff7509b7f59e58b1
6
+ metadata.gz: e6b95ffa49797be6cf36f0063a2013c994e6c7332fa29742d9991d35473e48dc22db94c2840de36012040790c2cd68ca49cfaedda99f3a7c921b42480d91ab94
7
+ data.tar.gz: 800b81d0d1797060e6a04a87aa1cc792fa53cfa9744d6a97d77b5890d9fbe58a1b98e6fa038bb400e30b85d2d9fc0dfd115debb8c221d4c94944639b5a1271a1
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # rubyzip
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rubyzip.svg)](http://badge.fury.io/rb/rubyzip)
4
- [![Build Status](https://secure.travis-ci.org/rubyzip/rubyzip.svg)](http://travis-ci.org/rubyzip/rubyzip)
4
+ [![Tests](https://github.com/rubyzip/rubyzip/actions/workflows/tests.yml/badge.svg)](https://github.com/rubyzip/rubyzip/actions/workflows/tests.yml)
5
5
  [![Code Climate](https://codeclimate.com/github/rubyzip/rubyzip.svg)](https://codeclimate.com/github/rubyzip/rubyzip)
6
6
  [![Coverage Status](https://img.shields.io/coveralls/rubyzip/rubyzip.svg)](https://coveralls.io/r/rubyzip/rubyzip?branch=master)
7
7
 
@@ -9,18 +9,26 @@ Rubyzip is a ruby library for reading and writing zip files.
9
9
 
10
10
  ## Important note
11
11
 
12
- The Rubyzip interface has changed!!! No need to do `require "zip/zip"` and `Zip` prefix in class names removed.
12
+ Rubyzip 2.4 is intended to be the last release in the 2.x series. Please get ready for version 3.0.
13
13
 
14
- If you have issues with any third-party gems that require an old version of rubyzip, you can use this workaround:
14
+ ### Updating to version 3.0
15
15
 
16
- ```ruby
17
- gem 'rubyzip', '>= 1.0.0' # will load new rubyzip version
18
- gem 'zip-zip' # will load compatibility for old rubyzip API.
19
- ```
16
+ The public API of some classes has been modernized to use named parameters for optional arguments. Also some methods have been changed or removed. Please check your usage of the following Rubyzip classes:
17
+ * `File`
18
+ * `Entry`
19
+ * `InputStream`
20
+ * `OutputStream`
21
+ * `DOSTime`
22
+
23
+ **Please see [Updating to version 3.x](https://github.com/rubyzip/rubyzip/wiki/Updating-to-version-3.x) in the wiki for details.**
20
24
 
21
25
  ## Requirements
22
26
 
23
- - Ruby 2.4 or greater (for rubyzip 2.0; use 1.x for older rubies)
27
+ Version 3.x requires at least Ruby 3.0.
28
+
29
+ Version 2.x requires at least Ruby 2.4, and is known to work on Ruby 3.x.
30
+
31
+ It is not recommended to use any versions of Rubyzip earlier than 2.3 due to security issues.
24
32
 
25
33
  ## Installation
26
34
 
@@ -188,7 +196,7 @@ If `::Zip::InputStream` finds such entry in the zip archive it will raise an exc
188
196
  Rubyzip supports reading/writing zip files with traditional zip encryption (a.k.a. "ZipCrypto"). AES encryption is not yet supported. It can be used with buffer streams, e.g.:
189
197
 
190
198
  ```ruby
191
- Zip::OutputStream.write_buffer(::StringIO.new(''), Zip::TraditionalEncrypter.new('password')) do |out|
199
+ Zip::OutputStream.write_buffer(::StringIO.new, Zip::TraditionalEncrypter.new('password')) do |out|
192
200
  out.put_next_entry("my_file.txt")
193
201
  out.write my_data
194
202
  end.string
data/lib/zip/dos_time.rb CHANGED
@@ -24,9 +24,17 @@ module Zip
24
24
  ((year - 1980) << 9)
25
25
  end
26
26
 
27
- # Dos time is only stored with two seconds accuracy
28
27
  def dos_equals(other)
29
- to_i / 2 == other.to_i / 2
28
+ Zip.warn_about_v3_api('DOSTime#dos_equals')
29
+
30
+ self == other
31
+ end
32
+
33
+ # Dos time is only stored with two seconds accuracy.
34
+ def <=>(other)
35
+ return unless other.kind_of?(Time)
36
+
37
+ (to_i / 2) <=> (other.to_i / 2)
30
38
  end
31
39
 
32
40
  # Create a DOSTime instance from a vanilla Time instance.
@@ -41,9 +49,8 @@ module Zip
41
49
  day = (0b11111 & bin_dos_date)
42
50
  month = (0b111100000 & bin_dos_date) >> 5
43
51
  year = ((0b1111111000000000 & bin_dos_date) >> 9) + 1980
44
- begin
45
- local(year, month, day, hour, minute, second)
46
- end
52
+
53
+ local(year, month, day, hour, minute, second)
47
54
  end
48
55
  end
49
56
  end
data/lib/zip/entry.rb CHANGED
@@ -52,26 +52,41 @@ module Zip
52
52
  raise ::Zip::EntryNameError, "Illegal ZipEntry name '#{name}', name must not start with /"
53
53
  end
54
54
 
55
- def initialize(*args)
56
- name = args[1] || ''
55
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
56
+ def initialize(zipfile = nil, name = nil, *args)
57
+ name ||= ''
57
58
  check_name(name)
58
59
 
59
60
  set_default_vars_values
60
61
  @fstype = ::Zip::RUNNING_ON_WINDOWS ? ::Zip::FSTYPE_FAT : ::Zip::FSTYPE_UNIX
61
62
 
62
- @zipfile = args[0] || ''
63
+ @zipfile = zipfile || ''
63
64
  @name = name
64
- @comment = args[2] || ''
65
- @extra = args[3] || ''
66
- @compressed_size = args[4] || 0
67
- @crc = args[5] || 0
68
- @compression_method = args[6] || ::Zip::Entry::DEFLATED
69
- @size = args[7] || 0
70
- @time = args[8] || ::Zip::DOSTime.now
65
+
66
+ if (args_hash = args.first).kind_of?(::Hash)
67
+ @comment = args_hash[:comment] || ''
68
+ @extra = args_hash[:extra] || ''
69
+ @compressed_size = args_hash[:compressed_size] || 0
70
+ @crc = args_hash[:crc] || 0
71
+ @compression_method = args_hash[:compression_method] || ::Zip::Entry::DEFLATED
72
+ @size = args_hash[:size] || 0
73
+ @time = args_hash[:time] || ::Zip::DOSTime.now
74
+ else
75
+ Zip.warn_about_v3_api('Zip::Entry.new') unless args.empty?
76
+
77
+ @comment = args[0] || ''
78
+ @extra = args[1] || ''
79
+ @compressed_size = args[2] || 0
80
+ @crc = args[3] || 0
81
+ @compression_method = args[4] || ::Zip::Entry::DEFLATED
82
+ @size = args[5] || 0
83
+ @time = args[6] || ::Zip::DOSTime.now
84
+ end
71
85
 
72
86
  @ftype = name_is_directory? ? :directory : :file
73
87
  @extra = ::Zip::ExtraField.new(@extra.to_s) unless @extra.kind_of?(::Zip::ExtraField)
74
88
  end
89
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
75
90
 
76
91
  def encrypted?
77
92
  gp_flags & 1 == 1
@@ -174,6 +189,8 @@ module Zip
174
189
  # NB: The caller is responsible for making sure dest_path is safe, if it
175
190
  # is passed.
176
191
  def extract(dest_path = nil, &block)
192
+ Zip.warn_about_v3_api('Zip::Entry#extract')
193
+
177
194
  if dest_path.nil? && !name_safe?
178
195
  warn "WARNING: skipped '#{@name}' as unsafe."
179
196
  return self
@@ -188,6 +205,28 @@ module Zip
188
205
  self
189
206
  end
190
207
 
208
+ # Extracts this entry to a file at `entry_path`, with
209
+ # `destination_directory` as the base location in the filesystem.
210
+ #
211
+ # NB: The caller is responsible for making sure `destination_directory` is
212
+ # safe, if it is passed.
213
+ def extract_v3(entry_path = @name, destination_directory: '.', &block)
214
+ dest_dir = ::File.absolute_path(destination_directory || '.')
215
+ extract_path = ::File.absolute_path(::File.join(dest_dir, entry_path))
216
+
217
+ unless extract_path.start_with?(dest_dir)
218
+ warn "WARNING: skipped extracting '#{@name}' to '#{extract_path}' as unsafe."
219
+ return self
220
+ end
221
+
222
+ block ||= proc { ::Zip.on_exists_proc }
223
+
224
+ raise "unknown file type #{inspect}" unless directory? || file? || symlink?
225
+
226
+ __send__(:"create_#{ftype}", extract_path, &block)
227
+ self
228
+ end
229
+
191
230
  def to_s
192
231
  @name
193
232
  end
@@ -506,7 +545,7 @@ module Zip
506
545
  keys_equal = %w[compression_method crc compressed_size size name extra filepath].all? do |k|
507
546
  other.__send__(k.to_sym) == __send__(k.to_sym)
508
547
  end
509
- keys_equal && time.dos_equals(other.time)
548
+ keys_equal && time == other.time
510
549
  end
511
550
 
512
551
  def <=>(other)
@@ -59,7 +59,7 @@ module Zip
59
59
 
60
60
  def pack_for_c_dir
61
61
  # central directory entries contain only fields that didn't fit in the main entry part
62
- packed = ''.force_encoding('BINARY')
62
+ packed = ''.b
63
63
  packed << [@original_size].pack('Q<') if @original_size
64
64
  packed << [@compressed_size].pack('Q<') if @compressed_size
65
65
  packed << [@relative_header_offset].pack('Q<') if @relative_header_offset
data/lib/zip/file.rb CHANGED
@@ -73,12 +73,17 @@ module Zip
73
73
 
74
74
  # Opens a zip archive. Pass true as the second parameter to create
75
75
  # a new archive if it doesn't exist already.
76
- def initialize(path_or_io, create = false, buffer = false, options = {})
76
+ def initialize(path_or_io, dep_create = false, dep_buffer = false,
77
+ create: false, buffer: false, **options)
77
78
  super()
79
+
80
+ Zip.warn_about_v3_api('File#new') if dep_create || dep_buffer
81
+
78
82
  options = DEFAULT_OPTIONS.merge(options)
79
83
  @name = path_or_io.respond_to?(:path) ? path_or_io.path : path_or_io
80
84
  @comment = ''
81
- @create = create ? true : false # allow any truthy value to mean true
85
+ @create = create || dep_create ? true : false # allow any truthy value to mean true
86
+ buffer ||= dep_buffer
82
87
 
83
88
  if ::File.size?(@name.to_s)
84
89
  # There is a file, which exists, that is associated with this zip.
@@ -94,6 +99,7 @@ module Zip
94
99
  end
95
100
  elsif buffer && path_or_io.size > 0
96
101
  # This zip is probably a non-empty StringIO.
102
+ @create = false
97
103
  read_from_stream(path_or_io)
98
104
  elsif @create
99
105
  # This zip is completely new/empty and is to be created.
@@ -117,8 +123,10 @@ module Zip
117
123
  # Similar to ::new. If a block is passed the Zip::File object is passed
118
124
  # to the block and is automatically closed afterwards, just as with
119
125
  # ruby's builtin File::open method.
120
- def open(file_name, create = false, options = {})
121
- zf = ::Zip::File.new(file_name, create, false, options)
126
+ def open(file_name, dep_create = false, create: false, **options)
127
+ Zip.warn_about_v3_api('Zip::File.open') if dep_create
128
+
129
+ zf = ::Zip::File.new(file_name, create: (dep_create || create), buffer: false, **options)
122
130
  return zf unless block_given?
123
131
 
124
132
  begin
@@ -130,7 +138,9 @@ module Zip
130
138
 
131
139
  # Same as #open. But outputs data to a buffer instead of a file
132
140
  def add_buffer
133
- io = ::StringIO.new('')
141
+ Zip.warn_about_v3_api('Zip::File.add_buffer')
142
+
143
+ io = ::StringIO.new
134
144
  zf = ::Zip::File.new(io, true, true)
135
145
  yield zf
136
146
  zf.write_buffer(io)
@@ -140,7 +150,7 @@ module Zip
140
150
  # stream, and outputs data to a buffer.
141
151
  # (This can be used to extract data from a
142
152
  # downloaded zip archive without first saving it to disk.)
143
- def open_buffer(io, options = {})
153
+ def open_buffer(io, **options)
144
154
  unless IO_METHODS.map { |method| io.respond_to?(method) }.all? || io.kind_of?(String)
145
155
  raise "Zip::File.open_buffer expects a String or IO-like argument (responds to #{IO_METHODS.join(', ')}). Found: #{io.class}"
146
156
  end
@@ -150,7 +160,7 @@ module Zip
150
160
  # https://github.com/rubyzip/rubyzip/issues/119
151
161
  io.binmode if io.respond_to?(:binmode)
152
162
 
153
- zf = ::Zip::File.new(io, true, true, options)
163
+ zf = ::Zip::File.new(io, create: true, buffer: true, **options)
154
164
  return zf unless block_given?
155
165
 
156
166
  yield zf
@@ -228,18 +238,24 @@ module Zip
228
238
  end
229
239
 
230
240
  # Splits an archive into parts with segment size
231
- def split(zip_file_name, segment_size = MAX_SEGMENT_SIZE, delete_zip_file = true, partial_zip_file_name = nil)
241
+ def split(zip_file_name,
242
+ dep_segment_size = MAX_SEGMENT_SIZE, dep_delete_zip_file = true, dep_partial_zip_file_name = nil,
243
+ segment_size: MAX_SEGMENT_SIZE, delete_zip_file: nil, partial_zip_file_name: nil)
232
244
  raise Error, "File #{zip_file_name} not found" unless ::File.exist?(zip_file_name)
233
245
  raise Errno::ENOENT, zip_file_name unless ::File.readable?(zip_file_name)
234
246
 
247
+ if dep_segment_size != MAX_SEGMENT_SIZE || !dep_delete_zip_file || dep_partial_zip_file_name
248
+ Zip.warn_about_v3_api('Zip::File.split')
249
+ end
250
+
235
251
  zip_file_size = ::File.size(zip_file_name)
236
- segment_size = get_segment_size_for_split(segment_size)
252
+ segment_size = get_segment_size_for_split(segment_size || dep_segment_size)
237
253
  return if zip_file_size <= segment_size
238
254
 
239
255
  segment_count = get_segment_count_for_split(zip_file_size, segment_size)
240
256
  # Checking for correct zip structure
241
257
  ::Zip::File.open(zip_file_name) {}
242
- partial_zip_file_name = get_partial_zip_file_name(zip_file_name, partial_zip_file_name)
258
+ partial_zip_file_name = get_partial_zip_file_name(zip_file_name, (partial_zip_file_name || dep_partial_zip_file_name))
243
259
  szip_file_index = 0
244
260
  ::File.open(zip_file_name, 'rb') do |zip_file|
245
261
  until zip_file.eof?
@@ -247,6 +263,7 @@ module Zip
247
263
  save_splited_part(zip_file, partial_zip_file_name, zip_file_size, szip_file_index, segment_size, segment_count)
248
264
  end
249
265
  end
266
+ delete_zip_file = delete_zip_file.nil? ? dep_delete_zip_file : delete_zip_file
250
267
  ::File.delete(zip_file_name) if delete_zip_file
251
268
  szip_file_index
252
269
  end
@@ -264,26 +281,45 @@ module Zip
264
281
  # specified. If a block is passed the stream object is passed to the block and
265
282
  # the stream is automatically closed afterwards just as with ruby's builtin
266
283
  # File.open method.
267
- def get_output_stream(entry, permission_int = nil, comment = nil,
268
- extra = nil, compressed_size = nil, crc = nil,
269
- compression_method = nil, size = nil, time = nil,
284
+ # rubocop:disable Metrics/ParameterLists, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
285
+ def get_output_stream(entry,
286
+ dep_permission_int = nil, dep_comment = nil,
287
+ dep_extra = nil, dep_compressed_size = nil, dep_crc = nil,
288
+ dep_compression_method = nil, dep_size = nil, dep_time = nil,
289
+ permission_int: nil, comment: nil,
290
+ extra: nil, compressed_size: nil, crc: nil,
291
+ compression_method: nil, size: nil, time: nil,
270
292
  &a_proc)
271
293
 
294
+ unless dep_permission_int.nil? && dep_comment.nil? && dep_extra.nil? &&
295
+ dep_compressed_size.nil? && dep_crc.nil? && dep_compression_method.nil? &&
296
+ dep_size.nil? && dep_time.nil?
297
+ Zip.warn_about_v3_api('Zip::File#get_output_stream')
298
+ end
299
+
272
300
  new_entry =
273
301
  if entry.kind_of?(Entry)
274
302
  entry
275
303
  else
276
- Entry.new(@name, entry.to_s, comment, extra, compressed_size, crc, compression_method, size, time)
304
+ Entry.new(@name, entry.to_s,
305
+ comment: (comment || dep_comment),
306
+ extra: (extra || dep_extra),
307
+ compressed_size: (compressed_size || dep_compressed_size),
308
+ crc: (crc || dep_crc),
309
+ compression_method: (compression_method || dep_compression_method),
310
+ size: (size || dep_size),
311
+ time: (time || dep_time))
277
312
  end
278
313
  if new_entry.directory?
279
314
  raise ArgumentError,
280
315
  "cannot open stream to directory entry - '#{new_entry}'"
281
316
  end
282
- new_entry.unix_perms = permission_int
317
+ new_entry.unix_perms = (permission_int || dep_permission_int)
283
318
  zip_streamable_entry = StreamableStream.new(new_entry)
284
319
  @entry_set << zip_streamable_entry
285
320
  zip_streamable_entry.get_output_stream(&a_proc)
286
321
  end
322
+ # rubocop:enable Metrics/ParameterLists, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
287
323
 
288
324
  # Returns the name of the zip archive
289
325
  def to_s
@@ -336,11 +372,25 @@ module Zip
336
372
 
337
373
  # Extracts entry to file dest_path.
338
374
  def extract(entry, dest_path, &block)
375
+ Zip.warn_about_v3_api('Zip::File#extract')
376
+
339
377
  block ||= proc { ::Zip.on_exists_proc }
340
378
  found_entry = get_entry(entry)
341
379
  found_entry.extract(dest_path, &block)
342
380
  end
343
381
 
382
+ # Extracts `entry` to a file at `entry_path`, with `destination_directory`
383
+ # as the base location in the filesystem.
384
+ #
385
+ # NB: The caller is responsible for making sure `destination_directory` is
386
+ # safe, if it is passed.
387
+ def extract_v3(entry, entry_path = nil, destination_directory: '.', &block)
388
+ block ||= proc { ::Zip.on_exists_proc }
389
+ found_entry = get_entry(entry)
390
+ entry_path ||= found_entry.name
391
+ found_entry.extract_v3(entry_path, destination_directory: destination_directory, &block)
392
+ end
393
+
344
394
  # Commits changes that has been made since the previous commit to
345
395
  # the zip archive.
346
396
  def commit
@@ -361,7 +411,9 @@ module Zip
361
411
  end
362
412
 
363
413
  # Write buffer write changes to buffer and return
364
- def write_buffer(io = ::StringIO.new(''))
414
+ def write_buffer(io = ::StringIO.new)
415
+ return unless commit_required?
416
+
365
417
  ::Zip::OutputStream.write_buffer(io) do |zos|
366
418
  @entry_set.each { |e| e.write_to_zip_output_stream(zos) }
367
419
  zos.comment = comment
@@ -239,7 +239,7 @@ module Zip
239
239
  end
240
240
 
241
241
  def open(filename, mode = 'r', permissions = 0o644, &block)
242
- mode.delete!('b') # ignore b option
242
+ mode = mode.delete('b') # ignore b option
243
243
  case mode
244
244
  when 'r'
245
245
  @mapped_zip.get_input_stream(filename, &block)
@@ -619,7 +619,7 @@ module Zip
619
619
  end
620
620
 
621
621
  def expand_path(path)
622
- expanded = path.start_with?('/') ? path : ::File.join(@pwd, path)
622
+ expanded = path.start_with?('/') ? path.dup : ::File.join(@pwd, path)
623
623
  expanded.gsub!(/\/\.(\/|$)/, '')
624
624
  expanded.gsub!(/[^\/]+\/\.\.(\/|$)/, '')
625
625
  expanded.empty? ? '/' : expanded
data/lib/zip/inflater.rb CHANGED
@@ -3,11 +3,11 @@ module Zip
3
3
  def initialize(*args)
4
4
  super
5
5
 
6
- @buffer = +''
6
+ @buffer = ''.b
7
7
  @zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
8
8
  end
9
9
 
10
- def read(length = nil, outbuf = '')
10
+ def read(length = nil, outbuf = ''.b)
11
11
  return (length.nil? || length.zero? ? '' : nil) if eof
12
12
 
13
13
  while length.nil? || (@buffer.bytesize < length)
@@ -49,11 +49,17 @@ module Zip
49
49
  #
50
50
  # @param context [String||IO||StringIO] file path or IO/StringIO object
51
51
  # @param offset [Integer] offset in the IO/StringIO
52
- def initialize(context, offset = 0, decrypter = nil)
52
+ def initialize(context, dep_offset = 0, dep_decrypter = nil, offset: 0, decrypter: nil)
53
53
  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?
54
60
  @archive_io = get_io(context, offset)
55
61
  @decompressor = ::Zip::NullDecompressor
56
- @decrypter = decrypter || ::Zip::NullDecrypter.new
62
+ @decrypter = decrypter || dep_decrypter || ::Zip::NullDecrypter.new
57
63
  @current_entry = nil
58
64
  end
59
65
 
@@ -89,8 +95,14 @@ module Zip
89
95
  # Same as #initialize but if a block is passed the opened
90
96
  # stream is passed to the block and closed when the block
91
97
  # returns.
92
- def open(filename_or_io, offset = 0, decrypter = nil)
93
- zio = new(filename_or_io, offset, decrypter)
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)
94
106
  return zio unless block_given?
95
107
 
96
108
  begin
@@ -101,7 +113,8 @@ module Zip
101
113
  end
102
114
 
103
115
  def open_buffer(filename_or_io, offset = 0)
104
- warn 'open_buffer is deprecated!!! Use open instead!'
116
+ Zip.warn_about_v3_api('Zip::InputStream.open_buffer')
117
+
105
118
  ::Zip::InputStream.open(filename_or_io, offset)
106
119
  end
107
120
  end
@@ -11,13 +11,13 @@ module Zip
11
11
  super
12
12
  @lineno = 0
13
13
  @pos = 0
14
- @output_buffer = ''
14
+ @output_buffer = ''.b
15
15
  end
16
16
 
17
17
  attr_accessor :lineno
18
18
  attr_reader :pos
19
19
 
20
- def read(number_of_bytes = nil, buf = '')
20
+ def read(number_of_bytes = nil, buf = ''.b)
21
21
  tbuf = if @output_buffer.bytesize > 0
22
22
  if number_of_bytes <= @output_buffer.bytesize
23
23
  @output_buffer.slice!(0, number_of_bytes)
@@ -26,7 +26,7 @@ module Zip
26
26
  rbuf = sysread(number_of_bytes, buf)
27
27
  out = @output_buffer
28
28
  out << rbuf if rbuf
29
- @output_buffer = ''
29
+ @output_buffer = ''.b
30
30
  out
31
31
  end
32
32
  else
@@ -93,7 +93,7 @@ module Zip
93
93
 
94
94
  def flush
95
95
  ret_val = @output_buffer
96
- @output_buffer = ''
96
+ @output_buffer = ''.b
97
97
  ret_val
98
98
  end
99
99
 
data/lib/zip/ioextras.rb CHANGED
@@ -6,14 +6,14 @@ module Zip
6
6
 
7
7
  class << self
8
8
  def copy_stream(ostream, istream)
9
- ostream.write(istream.read(CHUNK_SIZE, '')) until istream.eof?
9
+ ostream.write(istream.read(CHUNK_SIZE, ''.b)) 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
15
  tr = toread > CHUNK_SIZE ? CHUNK_SIZE : toread
16
- ostream.write(istream.read(tr, ''))
16
+ ostream.write(istream.read(tr, ''.b))
17
17
  toread -= tr
18
18
  end
19
19
  end
@@ -24,10 +24,13 @@ module Zip
24
24
 
25
25
  # Opens the indicated zip file. If a file with that name already
26
26
  # exists it will be overwritten.
27
- def initialize(file_name, stream = false, encrypter = nil)
27
+ def initialize(file_name, dep_stream = false, dep_encrypter = nil, stream: false, encrypter: nil)
28
28
  super()
29
+
30
+ Zip.warn_about_v3_api('Zip::OutputStream.new') if dep_stream || !dep_encrypter.nil?
31
+
29
32
  @file_name = file_name
30
- @output_stream = if stream
33
+ @output_stream = if stream || dep_stream
31
34
  iostream = @file_name.dup
32
35
  iostream.reopen(@file_name)
33
36
  iostream.rewind
@@ -37,7 +40,7 @@ module Zip
37
40
  end
38
41
  @entry_set = ::Zip::EntrySet.new
39
42
  @compressor = ::Zip::NullCompressor.instance
40
- @encrypter = encrypter || ::Zip::NullEncrypter.new
43
+ @encrypter = encrypter || dep_encrypter || ::Zip::NullEncrypter.new
41
44
  @closed = false
42
45
  @current_entry = nil
43
46
  @comment = nil
@@ -47,19 +50,23 @@ module Zip
47
50
  # stream is passed to the block and closed when the block
48
51
  # returns.
49
52
  class << self
50
- def open(file_name, encrypter = nil)
53
+ def open(file_name, dep_encrypter = nil, encrypter: nil)
51
54
  return new(file_name) unless block_given?
52
55
 
53
- zos = new(file_name, false, encrypter)
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))
54
59
  yield zos
55
60
  ensure
56
61
  zos.close if zos
57
62
  end
58
63
 
59
64
  # Same as #open but writes to a filestream instead
60
- def write_buffer(io = ::StringIO.new(''), encrypter = nil)
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
+
61
68
  io.binmode if io.respond_to?(:binmode)
62
- zos = new(io, true, encrypter)
69
+ zos = new(io, stream: true, encrypter: (encrypter || dep_encrypter))
63
70
  yield zos
64
71
  zos.close_buffer
65
72
  end
@@ -5,7 +5,7 @@ module Zip
5
5
  @read_so_far = 0
6
6
  end
7
7
 
8
- def read(length = nil, outbuf = '')
8
+ def read(length = nil, outbuf = ''.b)
9
9
  return (length.nil? || length.zero? ? '' : nil) if eof
10
10
 
11
11
  if length.nil? || (@read_so_far + length) > decompressed_size
data/lib/zip/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Zip
2
- VERSION = '2.3.2'
2
+ VERSION = '2.4.rc1'
3
3
  end
data/lib/zip.rb CHANGED
@@ -34,6 +34,21 @@ require 'zip/streamable_directory'
34
34
  require 'zip/errors'
35
35
 
36
36
  module Zip
37
+ V3_API_WARNING_MSG = <<~END_MSG
38
+ You have called '%s' which is changing or deprecated
39
+ in version 3.0.0. Please see
40
+ https://github.com/rubyzip/rubyzip/wiki/Updating-to-version-3.x
41
+ for more information.
42
+ END_MSG
43
+
44
+ def self.warn_about_v3_api(method)
45
+ warn V3_API_WARNING_MSG % method if ENV['RUBYZIP_V3_API_WARN']
46
+ end
47
+
48
+ if RUBY_VERSION < '3.0'
49
+ warn 'RubyZip 3.0 will require Ruby 3.0 or later.' if ENV['RUBYZIP_V3_API_WARN']
50
+ end
51
+
37
52
  extend self
38
53
  attr_accessor :unicode_names,
39
54
  :on_exists_proc,
metadata CHANGED
@@ -1,29 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubyzip
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.2
4
+ version: 2.4.rc1
5
5
  platform: ruby
6
6
  authors:
7
+ - Robert Haines
8
+ - John Lees-Miller
7
9
  - Alexander Simonov
8
- autorequire:
10
+ autorequire:
9
11
  bindir: bin
10
12
  cert_chain: []
11
- date: 2021-07-05 00:00:00.000000000 Z
13
+ date: 2024-04-08 00:00:00.000000000 Z
12
14
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: coveralls
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '0.7'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '0.7'
27
15
  - !ruby/object:Gem::Dependency
28
16
  name: minitest
29
17
  requirement: !ruby/object:Gem::Requirement
@@ -86,8 +74,10 @@ dependencies:
86
74
  - - "~>"
87
75
  - !ruby/object:Gem::Version
88
76
  version: '0.79'
89
- description:
77
+ description:
90
78
  email:
79
+ - hainesr@gmail.com
80
+ - jdleesmiller@gmail.com
91
81
  - alex@simonov.me
92
82
  executables: []
93
83
  extensions: []
@@ -146,9 +136,9 @@ licenses:
146
136
  - BSD 2-Clause
147
137
  metadata:
148
138
  bug_tracker_uri: https://github.com/rubyzip/rubyzip/issues
149
- changelog_uri: https://github.com/rubyzip/rubyzip/blob/v2.3.2/Changelog.md
150
- documentation_uri: https://www.rubydoc.info/gems/rubyzip/2.3.2
151
- source_code_uri: https://github.com/rubyzip/rubyzip/tree/v2.3.2
139
+ changelog_uri: https://github.com/rubyzip/rubyzip/blob/v2.4.rc1/Changelog.md
140
+ documentation_uri: https://www.rubydoc.info/gems/rubyzip/2.4.rc1
141
+ source_code_uri: https://github.com/rubyzip/rubyzip/tree/v2.4.rc1
152
142
  wiki_uri: https://github.com/rubyzip/rubyzip/wiki
153
143
  post_install_message: |
154
144
  RubyZip 3.0 is coming!
@@ -161,6 +151,13 @@ post_install_message: |
161
151
  * `Zip::Entry`
162
152
  * `Zip::InputStream`
163
153
  * `Zip::OutputStream`
154
+ * `Zip::DOSTime`
155
+
156
+ Run your test suite with the `RUBYZIP_V3_API_WARN` environment
157
+ variable set to see warnings about usage of the old API. This will
158
+ help you to identify any changes that you need to make to your code.
159
+ See https://github.com/rubyzip/rubyzip/wiki/Updating-to-version-3.x for
160
+ more information.
164
161
 
165
162
  Please ensure that your Gemfiles and .gemspecs are suitably restrictive
166
163
  to avoid an unexpected breakage when 3.0 is released (e.g. ~> 2.3.0).
@@ -177,12 +174,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
177
174
  version: '2.4'
178
175
  required_rubygems_version: !ruby/object:Gem::Requirement
179
176
  requirements:
180
- - - ">="
177
+ - - ">"
181
178
  - !ruby/object:Gem::Version
182
- version: '0'
179
+ version: 1.3.1
183
180
  requirements: []
184
- rubygems_version: 3.1.4
185
- signing_key:
181
+ rubygems_version: 3.3.23
182
+ signing_key:
186
183
  specification_version: 4
187
184
  summary: rubyzip is a ruby module for reading and writing zip files
188
185
  test_files: []