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 +4 -4
- data/README.md +17 -9
- data/lib/zip/dos_time.rb +12 -5
- data/lib/zip/entry.rb +50 -11
- data/lib/zip/extra_field/zip64.rb +1 -1
- data/lib/zip/file.rb +68 -16
- data/lib/zip/filesystem.rb +2 -2
- data/lib/zip/inflater.rb +2 -2
- data/lib/zip/input_stream.rb +18 -5
- data/lib/zip/ioextras/abstract_input_stream.rb +4 -4
- data/lib/zip/ioextras.rb +2 -2
- data/lib/zip/output_stream.rb +14 -7
- data/lib/zip/pass_thru_decompressor.rb +1 -1
- data/lib/zip/version.rb +1 -1
- data/lib/zip.rb +15 -0
- metadata +22 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49b133beda4cc25cd86964b3d7ffdd774583a75889508916ea4dab892ea9275d
|
4
|
+
data.tar.gz: 85c81018a61dd9592e8c7081b4c1b1d07c8f40ccea75b2466be8509925abfad6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
[![
|
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
|
-
|
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
|
-
|
14
|
+
### Updating to version 3.0
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
45
|
-
|
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
|
-
|
56
|
-
|
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 =
|
63
|
+
@zipfile = zipfile || ''
|
63
64
|
@name = name
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
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 = ''.
|
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,
|
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,
|
121
|
-
|
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
|
-
|
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,
|
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
|
-
|
268
|
-
|
269
|
-
|
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,
|
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
|
data/lib/zip/filesystem.rb
CHANGED
@@ -239,7 +239,7 @@ module Zip
|
|
239
239
|
end
|
240
240
|
|
241
241
|
def open(filename, mode = 'r', permissions = 0o644, &block)
|
242
|
-
mode.delete
|
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)
|
data/lib/zip/input_stream.rb
CHANGED
@@ -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,
|
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,
|
93
|
-
|
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
|
-
|
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
|
data/lib/zip/output_stream.rb
CHANGED
@@ -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,
|
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,
|
53
|
+
def open(file_name, dep_encrypter = nil, encrypter: nil)
|
51
54
|
return new(file_name) unless block_given?
|
52
55
|
|
53
|
-
|
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
|
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
|
data/lib/zip/version.rb
CHANGED
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.
|
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:
|
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.
|
150
|
-
documentation_uri: https://www.rubydoc.info/gems/rubyzip/2.
|
151
|
-
source_code_uri: https://github.com/rubyzip/rubyzip/tree/v2.
|
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:
|
179
|
+
version: 1.3.1
|
183
180
|
requirements: []
|
184
|
-
rubygems_version: 3.
|
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: []
|