rubyzip 3.0.0.alpha → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog.md +51 -0
- data/LICENSE.md +24 -0
- data/README.md +37 -12
- data/Rakefile +1 -1
- data/lib/zip/central_directory.rb +10 -10
- data/lib/zip/constants.rb +4 -0
- data/lib/zip/crypto/decrypted_io.rb +1 -1
- data/lib/zip/crypto/null_encryption.rb +1 -1
- data/lib/zip/crypto/traditional_encryption.rb +3 -3
- data/lib/zip/dos_time.rb +11 -1
- data/lib/zip/entry.rb +74 -47
- data/lib/zip/entry_set.rb +2 -2
- data/lib/zip/errors.rb +24 -3
- data/lib/zip/extra_field/generic.rb +3 -3
- data/lib/zip/extra_field/ntfs.rb +2 -2
- data/lib/zip/extra_field.rb +2 -2
- data/lib/zip/file.rb +38 -15
- data/lib/zip/file_split.rb +1 -7
- data/lib/zip/filesystem/dir.rb +2 -2
- data/lib/zip/filesystem/zip_file_name_mapper.rb +1 -1
- data/lib/zip/filesystem.rb +1 -1
- data/lib/zip/input_stream.rb +13 -18
- data/lib/zip/ioextras/abstract_input_stream.rb +2 -2
- data/lib/zip/ioextras.rb +1 -1
- data/lib/zip/output_stream.rb +8 -8
- data/lib/zip/version.rb +1 -1
- data/lib/zip.rb +4 -3
- data/rubyzip.gemspec +16 -15
- data/samples/example_filesystem.rb +1 -1
- data/samples/write_simple.rb +1 -1
- metadata +23 -21
data/lib/zip/entry.rb
CHANGED
@@ -9,16 +9,19 @@ module Zip
|
|
9
9
|
class Entry
|
10
10
|
include Dirtyable
|
11
11
|
|
12
|
+
# Constant used to specify that the entry is stored (i.e., not compressed).
|
12
13
|
STORED = ::Zip::COMPRESSION_METHOD_STORE
|
14
|
+
|
15
|
+
# Constant used to specify that the entry is deflated (i.e., compressed).
|
13
16
|
DEFLATED = ::Zip::COMPRESSION_METHOD_DEFLATE
|
14
17
|
|
15
18
|
# Language encoding flag (EFS) bit
|
16
|
-
EFS = 0b100000000000
|
19
|
+
EFS = 0b100000000000 # :nodoc:
|
17
20
|
|
18
21
|
# Compression level flags (used as part of the gp flags).
|
19
|
-
COMPRESSION_LEVEL_SUPERFAST_GPFLAG = 0b110
|
20
|
-
COMPRESSION_LEVEL_FAST_GPFLAG = 0b100
|
21
|
-
COMPRESSION_LEVEL_MAX_GPFLAG = 0b010
|
22
|
+
COMPRESSION_LEVEL_SUPERFAST_GPFLAG = 0b110 # :nodoc:
|
23
|
+
COMPRESSION_LEVEL_FAST_GPFLAG = 0b100 # :nodoc:
|
24
|
+
COMPRESSION_LEVEL_MAX_GPFLAG = 0b010 # :nodoc:
|
22
25
|
|
23
26
|
attr_accessor :comment, :compressed_size, :follow_symlinks, :name,
|
24
27
|
:restore_ownership, :restore_permissions, :restore_times,
|
@@ -35,7 +38,7 @@ module Zip
|
|
35
38
|
:fstype=, :gp_flags=, :name=, :size=,
|
36
39
|
:unix_gid=, :unix_perms=, :unix_uid=
|
37
40
|
|
38
|
-
def set_default_vars_values
|
41
|
+
def set_default_vars_values # :nodoc:
|
39
42
|
@local_header_offset = 0
|
40
43
|
@local_header_size = nil # not known until local entry is created or read
|
41
44
|
@internal_file_attributes = 1
|
@@ -63,11 +66,12 @@ module Zip
|
|
63
66
|
@unix_perms = nil
|
64
67
|
end
|
65
68
|
|
66
|
-
def check_name(name)
|
69
|
+
def check_name(name) # :nodoc:
|
67
70
|
raise EntryNameError, name if name.start_with?('/')
|
68
71
|
raise EntryNameError if name.length > 65_535
|
69
72
|
end
|
70
73
|
|
74
|
+
# Create a new Zip::Entry.
|
71
75
|
def initialize(
|
72
76
|
zipfile = '', name = '',
|
73
77
|
comment: '', size: nil, compressed_size: 0, crc: 0,
|
@@ -103,18 +107,23 @@ module Zip
|
|
103
107
|
set_compression_level_flags
|
104
108
|
end
|
105
109
|
|
110
|
+
# Is this entry encrypted?
|
106
111
|
def encrypted?
|
107
112
|
gp_flags & 1 == 1
|
108
113
|
end
|
109
114
|
|
110
|
-
def incomplete?
|
115
|
+
def incomplete? # :nodoc:
|
111
116
|
gp_flags & 8 == 8
|
112
117
|
end
|
113
118
|
|
119
|
+
# The uncompressed size of the entry.
|
114
120
|
def size
|
115
121
|
@size || 0
|
116
122
|
end
|
117
123
|
|
124
|
+
# Get a timestamp component of this entry.
|
125
|
+
#
|
126
|
+
# Returns modification time by default.
|
118
127
|
def time(component: :mtime)
|
119
128
|
time =
|
120
129
|
if @extra['UniversalTime']
|
@@ -130,14 +139,19 @@ module Zip
|
|
130
139
|
|
131
140
|
alias mtime time
|
132
141
|
|
142
|
+
# Get the last access time of this entry, if available.
|
133
143
|
def atime
|
134
144
|
time(component: :atime)
|
135
145
|
end
|
136
146
|
|
147
|
+
# Get the creation time of this entry, if available.
|
137
148
|
def ctime
|
138
149
|
time(component: :ctime)
|
139
150
|
end
|
140
151
|
|
152
|
+
# Set a timestamp component of this entry.
|
153
|
+
#
|
154
|
+
# Sets modification time by default.
|
141
155
|
def time=(value, component: :mtime)
|
142
156
|
@dirty = true
|
143
157
|
unless @extra.member?('UniversalTime') || @extra.member?('NTFS')
|
@@ -152,30 +166,43 @@ module Zip
|
|
152
166
|
|
153
167
|
alias mtime= time=
|
154
168
|
|
169
|
+
# Set the last access time of this entry.
|
155
170
|
def atime=(value)
|
156
171
|
send(:time=, value, component: :atime)
|
157
172
|
end
|
158
173
|
|
174
|
+
# Set the creation time of this entry.
|
159
175
|
def ctime=(value)
|
160
176
|
send(:time=, value, component: :ctime)
|
161
177
|
end
|
162
178
|
|
179
|
+
# Does this entry return time fields with accurate timezone information?
|
180
|
+
def absolute_time?
|
181
|
+
@extra.member?('UniversalTime') || @extra.member?('NTFS')
|
182
|
+
end
|
183
|
+
|
184
|
+
# Return the compression method for this entry.
|
185
|
+
#
|
186
|
+
# Returns STORED if the entry is a directory or if the compression
|
187
|
+
# level is 0.
|
163
188
|
def compression_method
|
164
189
|
return STORED if ftype == :directory || @compression_level == 0
|
165
190
|
|
166
191
|
@compression_method
|
167
192
|
end
|
168
193
|
|
194
|
+
# Set the compression method for this entry.
|
169
195
|
def compression_method=(method)
|
170
196
|
@dirty = true
|
171
197
|
@compression_method = (ftype == :directory ? STORED : method)
|
172
198
|
end
|
173
199
|
|
200
|
+
# Does this entry use the ZIP64 extensions?
|
174
201
|
def zip64?
|
175
202
|
!@extra['Zip64'].nil?
|
176
203
|
end
|
177
204
|
|
178
|
-
def file_type_is?(type)
|
205
|
+
def file_type_is?(type) # :nodoc:
|
179
206
|
ftype == type
|
180
207
|
end
|
181
208
|
|
@@ -185,19 +212,19 @@ module Zip
|
|
185
212
|
|
186
213
|
# Dynamic checkers
|
187
214
|
%w[directory file symlink].each do |k|
|
188
|
-
define_method "#{k}?" do
|
215
|
+
define_method :"#{k}?" do
|
189
216
|
file_type_is?(k.to_sym)
|
190
217
|
end
|
191
218
|
end
|
192
219
|
|
193
|
-
def name_is_directory?
|
220
|
+
def name_is_directory? # :nodoc:
|
194
221
|
@name.end_with?('/')
|
195
222
|
end
|
196
223
|
|
197
224
|
# Is the name a relative path, free of `..` patterns that could lead to
|
198
225
|
# path traversal attacks? This does NOT handle symlinks; if the path
|
199
226
|
# contains symlinks, this check is NOT enough to guarantee safety.
|
200
|
-
def name_safe?
|
227
|
+
def name_safe? # :nodoc:
|
201
228
|
cleanpath = Pathname.new(@name).cleanpath
|
202
229
|
return false unless cleanpath.relative?
|
203
230
|
|
@@ -207,29 +234,29 @@ module Zip
|
|
207
234
|
::File.absolute_path(cleanpath.to_s, root).match?(/([A-Z]:)?#{naive}/i)
|
208
235
|
end
|
209
236
|
|
210
|
-
def local_entry_offset
|
237
|
+
def local_entry_offset # :nodoc:
|
211
238
|
local_header_offset + @local_header_size
|
212
239
|
end
|
213
240
|
|
214
|
-
def name_size
|
241
|
+
def name_size # :nodoc:
|
215
242
|
@name ? @name.bytesize : 0
|
216
243
|
end
|
217
244
|
|
218
|
-
def extra_size
|
245
|
+
def extra_size # :nodoc:
|
219
246
|
@extra ? @extra.local_size : 0
|
220
247
|
end
|
221
248
|
|
222
|
-
def comment_size
|
249
|
+
def comment_size # :nodoc:
|
223
250
|
@comment ? @comment.bytesize : 0
|
224
251
|
end
|
225
252
|
|
226
|
-
def calculate_local_header_size
|
253
|
+
def calculate_local_header_size # :nodoc:
|
227
254
|
LOCAL_ENTRY_STATIC_HEADER_LENGTH + name_size + extra_size
|
228
255
|
end
|
229
256
|
|
230
257
|
# check before rewriting an entry (after file sizes are known)
|
231
258
|
# that we didn't change the header size (and thus clobber file data or something)
|
232
|
-
def verify_local_header_size!
|
259
|
+
def verify_local_header_size! # :nodoc:
|
233
260
|
return if @local_header_size.nil?
|
234
261
|
|
235
262
|
new_size = calculate_local_header_size
|
@@ -239,12 +266,12 @@ module Zip
|
|
239
266
|
"Local header size changed (#{@local_header_size} -> #{new_size})"
|
240
267
|
end
|
241
268
|
|
242
|
-
def cdir_header_size
|
269
|
+
def cdir_header_size # :nodoc:
|
243
270
|
CDIR_ENTRY_STATIC_HEADER_LENGTH + name_size +
|
244
271
|
(@extra ? @extra.c_dir_size : 0) + comment_size
|
245
272
|
end
|
246
273
|
|
247
|
-
def next_header_offset
|
274
|
+
def next_header_offset # :nodoc:
|
248
275
|
local_entry_offset + compressed_size
|
249
276
|
end
|
250
277
|
|
@@ -266,16 +293,16 @@ module Zip
|
|
266
293
|
|
267
294
|
raise "unknown file type #{inspect}" unless directory? || file? || symlink?
|
268
295
|
|
269
|
-
__send__("create_#{ftype}", extract_path, &block)
|
296
|
+
__send__(:"create_#{ftype}", extract_path, &block)
|
270
297
|
self
|
271
298
|
end
|
272
299
|
|
273
|
-
def to_s
|
300
|
+
def to_s # :nodoc:
|
274
301
|
@name
|
275
302
|
end
|
276
303
|
|
277
304
|
class << self
|
278
|
-
def read_c_dir_entry(io)
|
305
|
+
def read_c_dir_entry(io) # :nodoc:
|
279
306
|
path = if io.respond_to?(:path)
|
280
307
|
io.path
|
281
308
|
else
|
@@ -288,7 +315,7 @@ module Zip
|
|
288
315
|
nil
|
289
316
|
end
|
290
317
|
|
291
|
-
def read_local_entry(io)
|
318
|
+
def read_local_entry(io) # :nodoc:
|
292
319
|
entry = new(io)
|
293
320
|
entry.read_local_entry(io)
|
294
321
|
entry
|
@@ -299,7 +326,7 @@ module Zip
|
|
299
326
|
end
|
300
327
|
end
|
301
328
|
|
302
|
-
def unpack_local_entry(buf)
|
329
|
+
def unpack_local_entry(buf) # :nodoc:
|
303
330
|
@header_signature,
|
304
331
|
@version,
|
305
332
|
@fstype,
|
@@ -314,7 +341,7 @@ module Zip
|
|
314
341
|
@extra_length = buf.unpack('VCCvvvvVVVvv')
|
315
342
|
end
|
316
343
|
|
317
|
-
def read_local_entry(io)
|
344
|
+
def read_local_entry(io) # :nodoc:
|
318
345
|
@dirty = false # No changes at this point.
|
319
346
|
@local_header_offset = io.tell
|
320
347
|
|
@@ -356,7 +383,7 @@ module Zip
|
|
356
383
|
@local_header_size = calculate_local_header_size
|
357
384
|
end
|
358
385
|
|
359
|
-
def pack_local_entry
|
386
|
+
def pack_local_entry # :nodoc:
|
360
387
|
zip64 = @extra['Zip64']
|
361
388
|
[::Zip::LOCAL_ENTRY_SIGNATURE,
|
362
389
|
@version_needed_to_extract, # version needed to extract
|
@@ -371,7 +398,7 @@ module Zip
|
|
371
398
|
@extra ? @extra.local_size : 0].pack('VvvvvvVVVvv')
|
372
399
|
end
|
373
400
|
|
374
|
-
def write_local_entry(io, rewrite: false)
|
401
|
+
def write_local_entry(io, rewrite: false) # :nodoc:
|
375
402
|
prep_local_zip64_extra
|
376
403
|
verify_local_header_size! if rewrite
|
377
404
|
@local_header_offset = io.tell
|
@@ -383,7 +410,7 @@ module Zip
|
|
383
410
|
@local_header_size = io.tell - @local_header_offset
|
384
411
|
end
|
385
412
|
|
386
|
-
def unpack_c_dir_entry(buf)
|
413
|
+
def unpack_c_dir_entry(buf) # :nodoc:
|
387
414
|
@header_signature,
|
388
415
|
@version, # version of encoding software
|
389
416
|
@fstype, # filesystem type
|
@@ -407,7 +434,7 @@ module Zip
|
|
407
434
|
@comment = buf.unpack('VCCvvvvvVVVvvvvvVV')
|
408
435
|
end
|
409
436
|
|
410
|
-
def set_ftype_from_c_dir_entry
|
437
|
+
def set_ftype_from_c_dir_entry # :nodoc:
|
411
438
|
@ftype = case @fstype
|
412
439
|
when ::Zip::FSTYPE_UNIX
|
413
440
|
@unix_perms = (@external_file_attributes >> 16) & 0o7777
|
@@ -437,25 +464,25 @@ module Zip
|
|
437
464
|
end
|
438
465
|
end
|
439
466
|
|
440
|
-
def check_c_dir_entry_static_header_length(buf)
|
467
|
+
def check_c_dir_entry_static_header_length(buf) # :nodoc:
|
441
468
|
return unless buf.nil? || buf.bytesize != ::Zip::CDIR_ENTRY_STATIC_HEADER_LENGTH
|
442
469
|
|
443
470
|
raise Error, 'Premature end of file. Not enough data for zip cdir entry header'
|
444
471
|
end
|
445
472
|
|
446
|
-
def check_c_dir_entry_signature
|
473
|
+
def check_c_dir_entry_signature # :nodoc:
|
447
474
|
return if @header_signature == ::Zip::CENTRAL_DIRECTORY_ENTRY_SIGNATURE
|
448
475
|
|
449
476
|
raise Error, "Zip local header magic not found at location '#{local_header_offset}'"
|
450
477
|
end
|
451
478
|
|
452
|
-
def check_c_dir_entry_comment_size
|
479
|
+
def check_c_dir_entry_comment_size # :nodoc:
|
453
480
|
return if @comment && @comment.bytesize == @comment_length
|
454
481
|
|
455
482
|
raise ::Zip::Error, 'Truncated cdir zip entry header'
|
456
483
|
end
|
457
484
|
|
458
|
-
def read_extra_field(buf, local: false)
|
485
|
+
def read_extra_field(buf, local: false) # :nodoc:
|
459
486
|
if @extra.kind_of?(::Zip::ExtraField)
|
460
487
|
@extra.merge(buf, local: local) if buf
|
461
488
|
else
|
@@ -463,7 +490,7 @@ module Zip
|
|
463
490
|
end
|
464
491
|
end
|
465
492
|
|
466
|
-
def read_c_dir_entry(io)
|
493
|
+
def read_c_dir_entry(io) # :nodoc:
|
467
494
|
@dirty = false # No changes at this point.
|
468
495
|
static_sized_fields_buf = io.read(::Zip::CDIR_ENTRY_STATIC_HEADER_LENGTH)
|
469
496
|
check_c_dir_entry_static_header_length(static_sized_fields_buf)
|
@@ -503,7 +530,7 @@ module Zip
|
|
503
530
|
end
|
504
531
|
|
505
532
|
# rubocop:disable Style/GuardClause
|
506
|
-
def set_unix_attributes_on_path(dest_path)
|
533
|
+
def set_unix_attributes_on_path(dest_path) # :nodoc:
|
507
534
|
# Ignore setuid/setgid bits by default. Honour if @restore_ownership.
|
508
535
|
unix_perms_mask = (@restore_ownership ? 0o7777 : 0o1777)
|
509
536
|
if @restore_permissions && @unix_perms
|
@@ -529,7 +556,7 @@ module Zip
|
|
529
556
|
::FileUtils.touch(dest_path, mtime: time) if @restore_times
|
530
557
|
end
|
531
558
|
|
532
|
-
def pack_c_dir_entry
|
559
|
+
def pack_c_dir_entry # :nodoc:
|
533
560
|
zip64 = @extra['Zip64']
|
534
561
|
[
|
535
562
|
@header_signature,
|
@@ -556,7 +583,7 @@ module Zip
|
|
556
583
|
].pack('VCCvvvvvVVVvvvvvVV')
|
557
584
|
end
|
558
585
|
|
559
|
-
def write_c_dir_entry(io)
|
586
|
+
def write_c_dir_entry(io) # :nodoc:
|
560
587
|
prep_cdir_zip64_extra
|
561
588
|
|
562
589
|
case @fstype
|
@@ -574,7 +601,7 @@ module Zip
|
|
574
601
|
end
|
575
602
|
|
576
603
|
unless ft.nil?
|
577
|
-
@external_file_attributes = (ft << 12 | (@unix_perms & 0o7777)) << 16
|
604
|
+
@external_file_attributes = ((ft << 12) | (@unix_perms & 0o7777)) << 16
|
578
605
|
end
|
579
606
|
end
|
580
607
|
|
@@ -585,7 +612,7 @@ module Zip
|
|
585
612
|
io << @comment
|
586
613
|
end
|
587
614
|
|
588
|
-
def ==(other)
|
615
|
+
def ==(other) # :nodoc:
|
589
616
|
return false unless other.class == self.class
|
590
617
|
|
591
618
|
# Compares contents of local entry and exposed fields
|
@@ -594,7 +621,7 @@ module Zip
|
|
594
621
|
end
|
595
622
|
end
|
596
623
|
|
597
|
-
def <=>(other)
|
624
|
+
def <=>(other) # :nodoc:
|
598
625
|
to_s <=> other.to_s
|
599
626
|
end
|
600
627
|
|
@@ -639,7 +666,7 @@ module Zip
|
|
639
666
|
if name_is_directory?
|
640
667
|
raise ArgumentError,
|
641
668
|
"entry name '#{newEntry}' indicates directory entry, but " \
|
642
|
-
|
669
|
+
"'#{src_path}' is not a directory"
|
643
670
|
end
|
644
671
|
:file
|
645
672
|
when 'directory'
|
@@ -649,7 +676,7 @@ module Zip
|
|
649
676
|
if name_is_directory?
|
650
677
|
raise ArgumentError,
|
651
678
|
"entry name '#{newEntry}' indicates directory entry, but " \
|
652
|
-
|
679
|
+
"'#{src_path}' is not a directory"
|
653
680
|
end
|
654
681
|
:symlink
|
655
682
|
else
|
@@ -661,7 +688,7 @@ module Zip
|
|
661
688
|
get_extra_attributes_from_path(@filepath)
|
662
689
|
end
|
663
690
|
|
664
|
-
def write_to_zip_output_stream(zip_output_stream)
|
691
|
+
def write_to_zip_output_stream(zip_output_stream) # :nodoc:
|
665
692
|
if ftype == :directory
|
666
693
|
zip_output_stream.put_next_entry(self)
|
667
694
|
elsif @filepath
|
@@ -674,13 +701,13 @@ module Zip
|
|
674
701
|
end
|
675
702
|
end
|
676
703
|
|
677
|
-
def parent_as_string
|
704
|
+
def parent_as_string # :nodoc:
|
678
705
|
entry_name = name.chomp('/')
|
679
706
|
slash_index = entry_name.rindex('/')
|
680
707
|
slash_index ? entry_name.slice(0, slash_index + 1) : nil
|
681
708
|
end
|
682
709
|
|
683
|
-
def get_raw_input_stream(&block)
|
710
|
+
def get_raw_input_stream(&block) # :nodoc:
|
684
711
|
if @zipfile.respond_to?(:seek) && @zipfile.respond_to?(:read)
|
685
712
|
yield @zipfile
|
686
713
|
else
|
@@ -688,7 +715,7 @@ module Zip
|
|
688
715
|
end
|
689
716
|
end
|
690
717
|
|
691
|
-
def clean_up
|
718
|
+
def clean_up # :nodoc:
|
692
719
|
@dirty = false # Any changes are written at this point.
|
693
720
|
end
|
694
721
|
|
@@ -749,7 +776,7 @@ module Zip
|
|
749
776
|
|
750
777
|
# apply missing data from the zip64 extra information field, if present
|
751
778
|
# (required when file sizes exceed 2**32, but can be used for all files)
|
752
|
-
def parse_zip64_extra(for_local_header)
|
779
|
+
def parse_zip64_extra(for_local_header) # :nodoc:
|
753
780
|
return unless zip64?
|
754
781
|
|
755
782
|
if for_local_header
|
data/lib/zip/entry_set.rb
CHANGED
@@ -61,12 +61,12 @@ module Zip
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def glob(pattern, flags = ::File::FNM_PATHNAME | ::File::FNM_DOTMATCH | ::File::FNM_EXTGLOB)
|
64
|
-
entries.
|
64
|
+
entries.filter_map do |entry|
|
65
65
|
next nil unless ::File.fnmatch(pattern, entry.name.chomp('/'), flags)
|
66
66
|
|
67
67
|
yield(entry) if block_given?
|
68
68
|
entry
|
69
|
-
end
|
69
|
+
end
|
70
70
|
end
|
71
71
|
|
72
72
|
protected
|
data/lib/zip/errors.rb
CHANGED
@@ -7,13 +7,17 @@ module Zip
|
|
7
7
|
|
8
8
|
# Error raised if an unsupported compression method is used.
|
9
9
|
class CompressionMethodError < Error
|
10
|
+
# The compression method that has caused this error.
|
10
11
|
attr_reader :compression_method
|
11
12
|
|
13
|
+
# Create a new CompressionMethodError with the specified incorrect
|
14
|
+
# compression method.
|
12
15
|
def initialize(method)
|
13
16
|
super()
|
14
17
|
@compression_method = method
|
15
18
|
end
|
16
19
|
|
20
|
+
# The message returned by this error.
|
17
21
|
def message
|
18
22
|
"Unsupported compression method: #{COMPRESSION_METHODS[@compression_method]}."
|
19
23
|
end
|
@@ -21,13 +25,17 @@ module Zip
|
|
21
25
|
|
22
26
|
# Error raised if there is a problem while decompressing an archive entry.
|
23
27
|
class DecompressionError < Error
|
28
|
+
# The error from the underlying Zlib library that caused this error.
|
24
29
|
attr_reader :zlib_error
|
25
30
|
|
31
|
+
# Create a new DecompressionError with the specified underlying Zlib
|
32
|
+
# error.
|
26
33
|
def initialize(zlib_error)
|
27
34
|
super()
|
28
35
|
@zlib_error = zlib_error
|
29
36
|
end
|
30
37
|
|
38
|
+
# The message returned by this error.
|
31
39
|
def message
|
32
40
|
"Zlib error ('#{@zlib_error.message}') while inflating."
|
33
41
|
end
|
@@ -36,26 +44,30 @@ module Zip
|
|
36
44
|
# Error raised when trying to extract an archive entry over an
|
37
45
|
# existing file.
|
38
46
|
class DestinationExistsError < Error
|
47
|
+
# Create a new DestinationExistsError with the clashing destination.
|
39
48
|
def initialize(destination)
|
40
49
|
super()
|
41
50
|
@destination = destination
|
42
51
|
end
|
43
52
|
|
53
|
+
# The message returned by this error.
|
44
54
|
def message
|
45
55
|
"Cannot create file or directory '#{@destination}'. " \
|
46
|
-
|
56
|
+
'A file already exists with that name.'
|
47
57
|
end
|
48
58
|
end
|
49
59
|
|
50
60
|
# Error raised when trying to add an entry to an archive where the
|
51
61
|
# entry name already exists.
|
52
62
|
class EntryExistsError < Error
|
63
|
+
# Create a new EntryExistsError with the specified source and name.
|
53
64
|
def initialize(source, name)
|
54
65
|
super()
|
55
66
|
@source = source
|
56
67
|
@name = name
|
57
68
|
end
|
58
69
|
|
70
|
+
# The message returned by this error.
|
59
71
|
def message
|
60
72
|
"'#{@source}' failed. Entry #{@name} already exists."
|
61
73
|
end
|
@@ -63,11 +75,13 @@ module Zip
|
|
63
75
|
|
64
76
|
# Error raised when an entry name is invalid.
|
65
77
|
class EntryNameError < Error
|
78
|
+
# Create a new EntryNameError with the specified name.
|
66
79
|
def initialize(name = nil)
|
67
80
|
super()
|
68
81
|
@name = name
|
69
82
|
end
|
70
83
|
|
84
|
+
# The message returned by this error.
|
71
85
|
def message
|
72
86
|
if @name.nil?
|
73
87
|
'Illegal entry name. Names must have fewer than 65,536 characters.'
|
@@ -80,13 +94,16 @@ module Zip
|
|
80
94
|
# Error raised if an entry is larger on extraction than it is advertised
|
81
95
|
# to be.
|
82
96
|
class EntrySizeError < Error
|
97
|
+
# The entry that has caused this error.
|
83
98
|
attr_reader :entry
|
84
99
|
|
100
|
+
# Create a new EntrySizeError with the specified entry.
|
85
101
|
def initialize(entry)
|
86
102
|
super()
|
87
103
|
@entry = entry
|
88
104
|
end
|
89
105
|
|
106
|
+
# The message returned by this error.
|
90
107
|
def message
|
91
108
|
"Entry '#{@entry.name}' should be #{@entry.size}B, but is larger when inflated."
|
92
109
|
end
|
@@ -95,6 +112,7 @@ module Zip
|
|
95
112
|
# Error raised if a split archive is read. Rubyzip does not support reading
|
96
113
|
# split archives.
|
97
114
|
class SplitArchiveError < Error
|
115
|
+
# The message returned by this error.
|
98
116
|
def message
|
99
117
|
'Rubyzip cannot extract from split archives at this time.'
|
100
118
|
end
|
@@ -102,17 +120,20 @@ module Zip
|
|
102
120
|
|
103
121
|
# Error raised if there is not enough metadata for the entry to be streamed.
|
104
122
|
class StreamingError < Error
|
123
|
+
# The entry that has caused this error.
|
105
124
|
attr_reader :entry
|
106
125
|
|
126
|
+
# Create a new StreamingError with the specified entry.
|
107
127
|
def initialize(entry)
|
108
128
|
super()
|
109
129
|
@entry = entry
|
110
130
|
end
|
111
131
|
|
132
|
+
# The message returned by this error.
|
112
133
|
def message
|
113
134
|
"The local header of this entry ('#{@entry.name}') does not contain " \
|
114
|
-
|
115
|
-
|
135
|
+
'the correct metadata for `Zip::InputStream` to be able to ' \
|
136
|
+
'uncompress it. Please use `Zip::File` instead of `Zip::InputStream`.'
|
116
137
|
end
|
117
138
|
end
|
118
139
|
end
|
@@ -21,17 +21,17 @@ module Zip
|
|
21
21
|
return false
|
22
22
|
end
|
23
23
|
|
24
|
-
[binstr[2, 2].unpack1('v'), binstr[4
|
24
|
+
[binstr[2, 2].unpack1('v'), binstr[4..]]
|
25
25
|
end
|
26
26
|
|
27
27
|
def to_local_bin
|
28
28
|
s = pack_for_local
|
29
|
-
self.class.const_get(:HEADER_ID) + [s.bytesize].pack('v') << s
|
29
|
+
(self.class.const_get(:HEADER_ID) + [s.bytesize].pack('v')) << s
|
30
30
|
end
|
31
31
|
|
32
32
|
def to_c_dir_bin
|
33
33
|
s = pack_for_c_dir
|
34
|
-
self.class.const_get(:HEADER_ID) + [s.bytesize].pack('v') << s
|
34
|
+
(self.class.const_get(:HEADER_ID) + [s.bytesize].pack('v')) << s
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
data/lib/zip/extra_field/ntfs.rb
CHANGED
@@ -25,7 +25,7 @@ module Zip
|
|
25
25
|
size, content = initial_parse(binstr)
|
26
26
|
(size && content) || return
|
27
27
|
|
28
|
-
content = content[4
|
28
|
+
content = content[4..]
|
29
29
|
tags = parse_tags(content)
|
30
30
|
|
31
31
|
tag1 = tags[1]
|
@@ -86,7 +86,7 @@ module Zip
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def from_ntfs_time(ntfs_time)
|
89
|
-
::Zip::DOSTime.at(ntfs_time / WINDOWS_TICK - SEC_TO_UNIX_EPOCH)
|
89
|
+
::Zip::DOSTime.at((ntfs_time / WINDOWS_TICK) - SEC_TO_UNIX_EPOCH)
|
90
90
|
end
|
91
91
|
|
92
92
|
def to_ntfs_time(time)
|
data/lib/zip/extra_field.rb
CHANGED
@@ -21,8 +21,8 @@ module Zip
|
|
21
21
|
def extra_field_type_unknown(binstr, len, index, local)
|
22
22
|
self['Unknown'] ||= Unknown.new
|
23
23
|
|
24
|
-
if !len || len + 4 > binstr[index
|
25
|
-
self['Unknown'].merge(binstr[index
|
24
|
+
if !len || len + 4 > binstr[index..].bytesize
|
25
|
+
self['Unknown'].merge(binstr[index..], local: local)
|
26
26
|
return
|
27
27
|
end
|
28
28
|
|