rubyzip 1.2.1 → 2.0.0
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.
- checksums.yaml +5 -5
- data/README.md +83 -35
- data/lib/zip.rb +11 -1
- data/lib/zip/central_directory.rb +3 -3
- data/lib/zip/compressor.rb +1 -2
- data/lib/zip/constants.rb +3 -3
- data/lib/zip/crypto/null_encryption.rb +2 -4
- data/lib/zip/decompressor.rb +1 -1
- data/lib/zip/dos_time.rb +1 -1
- data/lib/zip/entry.rb +67 -57
- data/lib/zip/entry_set.rb +3 -3
- data/lib/zip/errors.rb +1 -0
- data/lib/zip/extra_field.rb +2 -2
- data/lib/zip/extra_field/generic.rb +1 -1
- data/lib/zip/extra_field/zip64_placeholder.rb +1 -2
- data/lib/zip/file.rb +47 -27
- data/lib/zip/filesystem.rb +17 -13
- data/lib/zip/inflater.rb +2 -2
- data/lib/zip/input_stream.rb +10 -7
- data/lib/zip/ioextras/abstract_input_stream.rb +1 -1
- data/lib/zip/ioextras/abstract_output_stream.rb +1 -1
- data/lib/zip/output_stream.rb +5 -5
- data/lib/zip/pass_thru_decompressor.rb +1 -1
- data/lib/zip/streamable_stream.rb +1 -1
- data/lib/zip/version.rb +1 -1
- data/samples/example_recursive.rb +14 -15
- data/samples/gtk_ruby_zip.rb +1 -1
- data/samples/qtzip.rb +1 -1
- data/samples/zipfind.rb +2 -2
- metadata +25 -121
- data/test/basic_zip_file_test.rb +0 -60
- data/test/case_sensitivity_test.rb +0 -69
- data/test/central_directory_entry_test.rb +0 -69
- data/test/central_directory_test.rb +0 -100
- data/test/crypto/null_encryption_test.rb +0 -57
- data/test/crypto/traditional_encryption_test.rb +0 -80
- data/test/data/WarnInvalidDate.zip +0 -0
- data/test/data/file1.txt +0 -46
- data/test/data/file1.txt.deflatedData +0 -0
- data/test/data/file2.txt +0 -1504
- data/test/data/globTest.zip +0 -0
- data/test/data/globTest/foo.txt +0 -0
- data/test/data/globTest/foo/bar/baz/foo.txt +0 -0
- data/test/data/globTest/food.txt +0 -0
- data/test/data/mimetype +0 -1
- data/test/data/notzippedruby.rb +0 -7
- data/test/data/ntfs.zip +0 -0
- data/test/data/oddExtraField.zip +0 -0
- data/test/data/rubycode.zip +0 -0
- data/test/data/rubycode2.zip +0 -0
- data/test/data/test.xls +0 -0
- data/test/data/testDirectory.bin +0 -0
- data/test/data/zip64-sample.zip +0 -0
- data/test/data/zipWithDirs.zip +0 -0
- data/test/data/zipWithEncryption.zip +0 -0
- data/test/deflater_test.rb +0 -65
- data/test/encryption_test.rb +0 -42
- data/test/entry_set_test.rb +0 -163
- data/test/entry_test.rb +0 -154
- data/test/errors_test.rb +0 -34
- data/test/extra_field_test.rb +0 -76
- data/test/file_extract_directory_test.rb +0 -54
- data/test/file_extract_test.rb +0 -83
- data/test/file_permissions_test.rb +0 -69
- data/test/file_split_test.rb +0 -57
- data/test/file_test.rb +0 -583
- data/test/filesystem/dir_iterator_test.rb +0 -58
- data/test/filesystem/directory_test.rb +0 -121
- data/test/filesystem/file_mutating_test.rb +0 -88
- data/test/filesystem/file_nonmutating_test.rb +0 -508
- data/test/filesystem/file_stat_test.rb +0 -64
- data/test/gentestfiles.rb +0 -126
- data/test/inflater_test.rb +0 -14
- data/test/input_stream_test.rb +0 -182
- data/test/ioextras/abstract_input_stream_test.rb +0 -102
- data/test/ioextras/abstract_output_stream_test.rb +0 -106
- data/test/ioextras/fake_io_test.rb +0 -18
- data/test/local_entry_test.rb +0 -154
- data/test/output_stream_test.rb +0 -128
- data/test/pass_thru_compressor_test.rb +0 -30
- data/test/pass_thru_decompressor_test.rb +0 -14
- data/test/samples/example_recursive_test.rb +0 -37
- data/test/settings_test.rb +0 -95
- data/test/test_helper.rb +0 -234
- data/test/unicode_file_names_and_comments_test.rb +0 -50
- data/test/zip64_full_test.rb +0 -51
- data/test/zip64_support_test.rb +0 -14
data/lib/zip/entry_set.rb
CHANGED
@@ -5,7 +5,7 @@ module Zip
|
|
5
5
|
|
6
6
|
def initialize(an_enumerable = [])
|
7
7
|
super()
|
8
|
-
@entry_set
|
8
|
+
@entry_set = {}
|
9
9
|
an_enumerable.each { |o| push(o) }
|
10
10
|
end
|
11
11
|
|
@@ -33,9 +33,9 @@ module Zip
|
|
33
33
|
entry if @entry_set.delete(to_key(entry))
|
34
34
|
end
|
35
35
|
|
36
|
-
def each
|
36
|
+
def each
|
37
37
|
@entry_set = sorted_entries.dup.each do |_, value|
|
38
|
-
|
38
|
+
yield(value)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
data/lib/zip/errors.rb
CHANGED
data/lib/zip/extra_field.rb
CHANGED
@@ -8,7 +8,7 @@ module Zip
|
|
8
8
|
|
9
9
|
def extra_field_type_exist(binstr, id, len, i)
|
10
10
|
field_name = ID_MAP[id].name
|
11
|
-
if
|
11
|
+
if member?(field_name)
|
12
12
|
self[field_name].merge(binstr[i, len + 4])
|
13
13
|
else
|
14
14
|
field_obj = ID_MAP[id].new(binstr[i, len + 4])
|
@@ -26,7 +26,7 @@ module Zip
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def create_unknown_item
|
29
|
-
s = ''
|
29
|
+
s = ''.dup
|
30
30
|
class << s
|
31
31
|
alias_method :to_c_dir_bin, :to_s
|
32
32
|
alias_method :to_local_bin, :to_s
|
data/lib/zip/file.rb
CHANGED
@@ -64,25 +64,38 @@ module Zip
|
|
64
64
|
|
65
65
|
# Opens a zip archive. Pass true as the second parameter to create
|
66
66
|
# a new archive if it doesn't exist already.
|
67
|
-
def initialize(
|
67
|
+
def initialize(path_or_io, create = false, buffer = false, options = {})
|
68
68
|
super()
|
69
|
-
@name =
|
69
|
+
@name = path_or_io.respond_to?(:path) ? path_or_io.path : path_or_io
|
70
70
|
@comment = ''
|
71
71
|
@create = create ? true : false # allow any truthy value to mean true
|
72
|
-
|
73
|
-
|
72
|
+
|
73
|
+
if ::File.size?(@name.to_s)
|
74
|
+
# There is a file, which exists, that is associated with this zip.
|
74
75
|
@create = false
|
75
|
-
@file_permissions = ::File.stat(
|
76
|
-
|
77
|
-
|
76
|
+
@file_permissions = ::File.stat(@name).mode
|
77
|
+
|
78
|
+
if buffer
|
79
|
+
read_from_stream(path_or_io)
|
80
|
+
else
|
81
|
+
::File.open(@name, 'rb') do |f|
|
82
|
+
read_from_stream(f)
|
83
|
+
end
|
78
84
|
end
|
79
|
-
|
85
|
+
elsif buffer && path_or_io.size > 0
|
86
|
+
# This zip is probably a non-empty StringIO.
|
87
|
+
read_from_stream(path_or_io)
|
88
|
+
elsif @create
|
89
|
+
# This zip is completely new/empty and is to be created.
|
80
90
|
@entry_set = EntrySet.new
|
81
|
-
|
82
|
-
|
91
|
+
elsif ::File.zero?(@name)
|
92
|
+
# A file exists, but it is empty.
|
93
|
+
raise Error, "File #{@name} has zero size. Did you mean to pass the create flag?"
|
83
94
|
else
|
84
|
-
|
95
|
+
# Everything is wrong.
|
96
|
+
raise Error, "File #{@name} not found"
|
85
97
|
end
|
98
|
+
|
86
99
|
@stored_entries = @entry_set.dup
|
87
100
|
@stored_comment = @comment
|
88
101
|
@restore_ownership = options[:restore_ownership] || false
|
@@ -120,17 +133,16 @@ module Zip
|
|
120
133
|
unless IO_METHODS.map { |method| io.respond_to?(method) }.all? || io.is_a?(String)
|
121
134
|
raise "Zip::File.open_buffer expects a String or IO-like argument (responds to #{IO_METHODS.join(', ')}). Found: #{io.class}"
|
122
135
|
end
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
end
|
136
|
+
|
137
|
+
io = ::StringIO.new(io) if io.is_a?(::String)
|
138
|
+
|
139
|
+
# https://github.com/rubyzip/rubyzip/issues/119
|
140
|
+
io.binmode if io.respond_to?(:binmode)
|
141
|
+
|
130
142
|
zf = ::Zip::File.new(io, true, true, options)
|
131
|
-
zf.read_from_stream(io)
|
132
143
|
return zf unless block_given?
|
133
144
|
yield zf
|
145
|
+
|
134
146
|
begin
|
135
147
|
zf.write_buffer(io)
|
136
148
|
rescue IOError => e
|
@@ -151,10 +163,9 @@ module Zip
|
|
151
163
|
end
|
152
164
|
|
153
165
|
def get_segment_size_for_split(segment_size)
|
154
|
-
|
155
|
-
when MIN_SEGMENT_SIZE > segment_size
|
166
|
+
if MIN_SEGMENT_SIZE > segment_size
|
156
167
|
MIN_SEGMENT_SIZE
|
157
|
-
|
168
|
+
elsif MAX_SEGMENT_SIZE < segment_size
|
158
169
|
MAX_SEGMENT_SIZE
|
159
170
|
else
|
160
171
|
segment_size
|
@@ -162,8 +173,10 @@ module Zip
|
|
162
173
|
end
|
163
174
|
|
164
175
|
def get_partial_zip_file_name(zip_file_name, partial_zip_file_name)
|
165
|
-
partial_zip_file_name
|
166
|
-
|
176
|
+
unless partial_zip_file_name.nil?
|
177
|
+
partial_zip_file_name = zip_file_name.sub(/#{::File.basename(zip_file_name)}\z/,
|
178
|
+
partial_zip_file_name + ::File.extname(zip_file_name))
|
179
|
+
end
|
167
180
|
partial_zip_file_name ||= zip_file_name
|
168
181
|
partial_zip_file_name
|
169
182
|
end
|
@@ -237,7 +250,7 @@ module Zip
|
|
237
250
|
# specified. If a block is passed the stream object is passed to the block and
|
238
251
|
# the stream is automatically closed afterwards just as with ruby's builtin
|
239
252
|
# File.open method.
|
240
|
-
def get_output_stream(entry, permission_int = nil, comment = nil, extra = nil, compressed_size = nil, crc = nil, compression_method = nil, size = nil, time = nil,
|
253
|
+
def get_output_stream(entry, permission_int = nil, comment = nil, extra = nil, compressed_size = nil, crc = nil, compression_method = nil, size = nil, time = nil, &aProc)
|
241
254
|
new_entry =
|
242
255
|
if entry.kind_of?(Entry)
|
243
256
|
entry
|
@@ -274,6 +287,13 @@ module Zip
|
|
274
287
|
@entry_set << new_entry
|
275
288
|
end
|
276
289
|
|
290
|
+
# Convenience method for adding the contents of a file to the archive
|
291
|
+
# in Stored format (uncompressed)
|
292
|
+
def add_stored(entry, src_path, &continue_on_exists_proc)
|
293
|
+
entry = ::Zip::Entry.new(@name, entry.to_s, nil, nil, nil, nil, ::Zip::Entry::STORED)
|
294
|
+
add(entry, src_path, &continue_on_exists_proc)
|
295
|
+
end
|
296
|
+
|
277
297
|
# Removes the specified entry.
|
278
298
|
def remove(entry)
|
279
299
|
@entry_set.delete(get_entry(entry))
|
@@ -306,7 +326,7 @@ module Zip
|
|
306
326
|
# Commits changes that has been made since the previous commit to
|
307
327
|
# the zip archive.
|
308
328
|
def commit
|
309
|
-
return
|
329
|
+
return if name.is_a?(StringIO) || !commit_required?
|
310
330
|
on_success_replace do |tmp_file|
|
311
331
|
::Zip::OutputStream.open(tmp_file) do |zos|
|
312
332
|
@entry_set.each do |e|
|
@@ -366,7 +386,7 @@ module Zip
|
|
366
386
|
end
|
367
387
|
|
368
388
|
# Creates a directory
|
369
|
-
def mkdir(entryName, permissionInt =
|
389
|
+
def mkdir(entryName, permissionInt = 0o755)
|
370
390
|
raise Errno::EEXIST, "File exists - #{entryName}" if find_entry(entryName)
|
371
391
|
entryName = entryName.dup.to_s
|
372
392
|
entryName << '/' unless entryName.end_with?('/')
|
data/lib/zip/filesystem.rb
CHANGED
@@ -142,9 +142,9 @@ module Zip
|
|
142
142
|
|
143
143
|
def ftype
|
144
144
|
if file?
|
145
|
-
|
145
|
+
'file'
|
146
146
|
elsif directory?
|
147
|
-
|
147
|
+
'directory'
|
148
148
|
else
|
149
149
|
raise StandardError, 'Unknown file type'
|
150
150
|
end
|
@@ -198,30 +198,30 @@ module Zip
|
|
198
198
|
alias grpowned? exists?
|
199
199
|
|
200
200
|
def readable?(fileName)
|
201
|
-
unix_mode_cmp(fileName,
|
201
|
+
unix_mode_cmp(fileName, 0o444)
|
202
202
|
end
|
203
203
|
alias readable_real? readable?
|
204
204
|
|
205
205
|
def writable?(fileName)
|
206
|
-
unix_mode_cmp(fileName,
|
206
|
+
unix_mode_cmp(fileName, 0o222)
|
207
207
|
end
|
208
208
|
alias writable_real? writable?
|
209
209
|
|
210
210
|
def executable?(fileName)
|
211
|
-
unix_mode_cmp(fileName,
|
211
|
+
unix_mode_cmp(fileName, 0o111)
|
212
212
|
end
|
213
213
|
alias executable_real? executable?
|
214
214
|
|
215
215
|
def setuid?(fileName)
|
216
|
-
unix_mode_cmp(fileName,
|
216
|
+
unix_mode_cmp(fileName, 0o4000)
|
217
217
|
end
|
218
218
|
|
219
219
|
def setgid?(fileName)
|
220
|
-
unix_mode_cmp(fileName,
|
220
|
+
unix_mode_cmp(fileName, 0o2000)
|
221
221
|
end
|
222
222
|
|
223
223
|
def sticky?(fileName)
|
224
|
-
unix_mode_cmp(fileName,
|
224
|
+
unix_mode_cmp(fileName, 0o1000)
|
225
225
|
end
|
226
226
|
|
227
227
|
def umask(*args)
|
@@ -237,8 +237,8 @@ module Zip
|
|
237
237
|
expand_path(fileName) == '/' || (!entry.nil? && entry.directory?)
|
238
238
|
end
|
239
239
|
|
240
|
-
def open(fileName, openMode = 'r', permissionInt =
|
241
|
-
openMode.
|
240
|
+
def open(fileName, openMode = 'r', permissionInt = 0o644, &block)
|
241
|
+
openMode.delete!('b') # ignore b option
|
242
242
|
case openMode
|
243
243
|
when 'r'
|
244
244
|
@mappedZip.get_input_stream(fileName, &block)
|
@@ -260,7 +260,7 @@ module Zip
|
|
260
260
|
# Returns nil for not found and nil for directories
|
261
261
|
def size?(fileName)
|
262
262
|
entry = @mappedZip.find_entry(fileName)
|
263
|
-
|
263
|
+
entry.nil? || entry.directory? ? nil : entry.size
|
264
264
|
end
|
265
265
|
|
266
266
|
def chown(ownerInt, groupInt, *filenames)
|
@@ -498,7 +498,7 @@ module Zip
|
|
498
498
|
alias rmdir delete
|
499
499
|
alias unlink delete
|
500
500
|
|
501
|
-
def mkdir(entryName, permissionInt =
|
501
|
+
def mkdir(entryName, permissionInt = 0o755)
|
502
502
|
@mappedZip.mkdir(entryName, permissionInt)
|
503
503
|
end
|
504
504
|
|
@@ -573,6 +573,10 @@ module Zip
|
|
573
573
|
@zipFile.get_output_stream(expand_to_entry(fileName), permissionInt, &aProc)
|
574
574
|
end
|
575
575
|
|
576
|
+
def glob(pattern, *flags, &block)
|
577
|
+
@zipFile.glob(expand_to_entry(pattern), *flags, &block)
|
578
|
+
end
|
579
|
+
|
576
580
|
def read(fileName)
|
577
581
|
@zipFile.read(expand_to_entry(fileName))
|
578
582
|
end
|
@@ -586,7 +590,7 @@ module Zip
|
|
586
590
|
&continueOnExistsProc)
|
587
591
|
end
|
588
592
|
|
589
|
-
def mkdir(fileName, permissionInt =
|
593
|
+
def mkdir(fileName, permissionInt = 0o755)
|
590
594
|
@zipFile.mkdir(expand_to_entry(fileName), permissionInt)
|
591
595
|
end
|
592
596
|
|
data/lib/zip/inflater.rb
CHANGED
@@ -3,9 +3,9 @@ module Zip
|
|
3
3
|
def initialize(input_stream, decrypter = NullDecrypter.new)
|
4
4
|
super(input_stream)
|
5
5
|
@zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
6
|
-
@output_buffer = ''
|
6
|
+
@output_buffer = ''.dup
|
7
7
|
@has_returned_empty_string = false
|
8
|
-
@decrypter
|
8
|
+
@decrypter = decrypter
|
9
9
|
end
|
10
10
|
|
11
11
|
def sysread(number_of_bytes = nil, buf = '')
|
data/lib/zip/input_stream.rb
CHANGED
@@ -129,23 +129,26 @@ module Zip
|
|
129
129
|
end
|
130
130
|
if @current_entry && @current_entry.gp_flags & 8 == 8 && @current_entry.crc == 0 \
|
131
131
|
&& @current_entry.compressed_size == 0 \
|
132
|
-
&& @current_entry.size == 0 && !@
|
132
|
+
&& @current_entry.size == 0 && !@complete_entry
|
133
133
|
raise GPFBit3Error,
|
134
134
|
'General purpose flag Bit 3 is set so not possible to get proper info from local header.' \
|
135
135
|
'Please use ::Zip::File instead of ::Zip::InputStream'
|
136
136
|
end
|
137
|
-
@decompressor
|
137
|
+
@decompressor = get_decompressor
|
138
138
|
flush
|
139
139
|
@current_entry
|
140
140
|
end
|
141
141
|
|
142
142
|
def get_decompressor
|
143
|
-
|
144
|
-
when @current_entry.nil?
|
143
|
+
if @current_entry.nil?
|
145
144
|
::Zip::NullDecompressor
|
146
|
-
|
147
|
-
|
148
|
-
|
145
|
+
elsif @current_entry.compression_method == ::Zip::Entry::STORED
|
146
|
+
if @current_entry.gp_flags & 8 == 8 && @current_entry.crc == 0 && @current_entry.size == 0 && @complete_entry
|
147
|
+
::Zip::PassThruDecompressor.new(@archive_io, @complete_entry.size)
|
148
|
+
else
|
149
|
+
::Zip::PassThruDecompressor.new(@archive_io, @current_entry.size)
|
150
|
+
end
|
151
|
+
elsif @current_entry.compression_method == ::Zip::Entry::DEFLATED
|
149
152
|
header = @archive_io.read(@decrypter.header_bytesize)
|
150
153
|
@decrypter.reset!(header)
|
151
154
|
::Zip::Inflater.new(@archive_io, @decrypter)
|
data/lib/zip/output_stream.rb
CHANGED
@@ -87,11 +87,11 @@ module Zip
|
|
87
87
|
# +entry+ can be a ZipEntry object or a string.
|
88
88
|
def put_next_entry(entry_name, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zip.default_compression)
|
89
89
|
raise Error, 'zip stream is closed' if @closed
|
90
|
-
if entry_name.kind_of?(Entry)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
90
|
+
new_entry = if entry_name.kind_of?(Entry)
|
91
|
+
entry_name
|
92
|
+
else
|
93
|
+
Entry.new(@file_name, entry_name.to_s)
|
94
|
+
end
|
95
95
|
new_entry.comment = comment unless comment.nil?
|
96
96
|
unless extra.nil?
|
97
97
|
new_entry.extra = extra.is_a?(ExtraField) ? extra : ExtraField.new(extra.to_s)
|
data/lib/zip/version.rb
CHANGED
@@ -19,37 +19,36 @@ class ZipFileGenerator
|
|
19
19
|
|
20
20
|
# Zip the input directory.
|
21
21
|
def write
|
22
|
-
entries = Dir.entries(@input_dir) - %w
|
22
|
+
entries = Dir.entries(@input_dir) - %w[. ..]
|
23
23
|
|
24
|
-
::Zip::File.open(@output_file, ::Zip::File::CREATE) do |
|
25
|
-
write_entries entries, '',
|
24
|
+
::Zip::File.open(@output_file, ::Zip::File::CREATE) do |zipfile|
|
25
|
+
write_entries entries, '', zipfile
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
private
|
30
30
|
|
31
31
|
# A helper method to make the recursion work.
|
32
|
-
def write_entries(entries, path,
|
32
|
+
def write_entries(entries, path, zipfile)
|
33
33
|
entries.each do |e|
|
34
|
-
|
35
|
-
disk_file_path = File.join(@input_dir,
|
36
|
-
puts "Deflating #{disk_file_path}"
|
34
|
+
zipfile_path = path == '' ? e : File.join(path, e)
|
35
|
+
disk_file_path = File.join(@input_dir, zipfile_path)
|
37
36
|
|
38
37
|
if File.directory? disk_file_path
|
39
|
-
recursively_deflate_directory(disk_file_path,
|
38
|
+
recursively_deflate_directory(disk_file_path, zipfile, zipfile_path)
|
40
39
|
else
|
41
|
-
put_into_archive(disk_file_path,
|
40
|
+
put_into_archive(disk_file_path, zipfile, zipfile_path)
|
42
41
|
end
|
43
42
|
end
|
44
43
|
end
|
45
44
|
|
46
|
-
def recursively_deflate_directory(disk_file_path,
|
47
|
-
|
48
|
-
subdir = Dir.entries(disk_file_path) - %w
|
49
|
-
write_entries subdir,
|
45
|
+
def recursively_deflate_directory(disk_file_path, zipfile, zipfile_path)
|
46
|
+
zipfile.mkdir zipfile_path
|
47
|
+
subdir = Dir.entries(disk_file_path) - %w[. ..]
|
48
|
+
write_entries subdir, zipfile_path, zipfile
|
50
49
|
end
|
51
50
|
|
52
|
-
def put_into_archive(disk_file_path,
|
53
|
-
|
51
|
+
def put_into_archive(disk_file_path, zipfile, zipfile_path)
|
52
|
+
zipfile.add(zipfile_path, disk_file_path)
|
54
53
|
end
|
55
54
|
end
|