rubyzip 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/zip.rb +0 -1
- data/lib/zip/dos_time.rb +5 -0
- data/lib/zip/entry.rb +16 -12
- data/lib/zip/extra_field/generic.rb +1 -1
- data/lib/zip/extra_field/universal_time.rb +39 -12
- data/lib/zip/file.rb +30 -16
- data/lib/zip/input_stream.rb +1 -1
- data/lib/zip/streamable_stream.rb +1 -6
- data/lib/zip/version.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7befb1c4855935534788418759d90641e37bd31c53428b5ba04c6c8c4bc4a544
|
4
|
+
data.tar.gz: 9b5669fc4b3c8a03cc39c73c7ae0e26ece01a2e51a401274f737a43798592b5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a537f87d0051073f2a31ced8f732d0b3b5c7376e792d02d3c1a52b597133f0f4be16b6c2c2564624104b179e501b7016ec6fecdde3681709d9730b5fb124dc72
|
7
|
+
data.tar.gz: 37ed030e2ffbb243bc639e969d050d21836448f746c1d47a49b8f77417b286438bee60dd80a6ba1e333642db218a56d32908ccbce4b3b6873082c42a709c6c77
|
data/lib/zip.rb
CHANGED
data/lib/zip/dos_time.rb
CHANGED
@@ -29,6 +29,11 @@ module Zip
|
|
29
29
|
to_i / 2 == other.to_i / 2
|
30
30
|
end
|
31
31
|
|
32
|
+
# Create a DOSTime instance from a vanilla Time instance.
|
33
|
+
def self.from_time(time)
|
34
|
+
local(time.year, time.month, time.day, time.hour, time.min, time.sec)
|
35
|
+
end
|
36
|
+
|
32
37
|
def self.parse_binary_dos_format(binaryDosDate, binaryDosTime)
|
33
38
|
second = 2 * (0b11111 & binaryDosTime)
|
34
39
|
minute = (0b11111100000 & binaryDosTime) >> 5
|
data/lib/zip/entry.rb
CHANGED
@@ -34,7 +34,7 @@ module Zip
|
|
34
34
|
end
|
35
35
|
@follow_symlinks = false
|
36
36
|
|
37
|
-
@restore_times =
|
37
|
+
@restore_times = false
|
38
38
|
@restore_permissions = false
|
39
39
|
@restore_ownership = false
|
40
40
|
# BUG: need an extra field to support uid/gid's
|
@@ -163,7 +163,7 @@ module Zip
|
|
163
163
|
# is passed.
|
164
164
|
def extract(dest_path = nil, &block)
|
165
165
|
if dest_path.nil? && !name_safe?
|
166
|
-
|
166
|
+
warn "WARNING: skipped '#{@name}' as unsafe."
|
167
167
|
return self
|
168
168
|
end
|
169
169
|
|
@@ -406,16 +406,20 @@ module Zip
|
|
406
406
|
@unix_uid = stat.uid
|
407
407
|
@unix_gid = stat.gid
|
408
408
|
@unix_perms = stat.mode & 0o7777
|
409
|
+
@time = ::Zip::DOSTime.from_time(stat.mtime)
|
409
410
|
end
|
410
411
|
|
411
|
-
def
|
412
|
-
# BUG: does not update timestamps into account
|
412
|
+
def set_unix_attributes_on_path(dest_path)
|
413
413
|
# ignore setuid/setgid bits by default. honor if @restore_ownership
|
414
414
|
unix_perms_mask = 0o1777
|
415
415
|
unix_perms_mask = 0o7777 if @restore_ownership
|
416
416
|
::FileUtils.chmod(@unix_perms & unix_perms_mask, dest_path) if @restore_permissions && @unix_perms
|
417
417
|
::FileUtils.chown(@unix_uid, @unix_gid, dest_path) if @restore_ownership && @unix_uid && @unix_gid && ::Process.egid == 0
|
418
|
-
|
418
|
+
|
419
|
+
# Restore the timestamp on a file. This will either have come from the
|
420
|
+
# original source file that was copied into the archive, or from the
|
421
|
+
# creation date of the archive if there was no original source file.
|
422
|
+
::FileUtils.touch(dest_path, mtime: time) if @restore_times
|
419
423
|
end
|
420
424
|
|
421
425
|
def set_extra_attributes_on_path(dest_path) # :nodoc:
|
@@ -423,7 +427,7 @@ module Zip
|
|
423
427
|
|
424
428
|
case @fstype
|
425
429
|
when ::Zip::FSTYPE_UNIX
|
426
|
-
|
430
|
+
set_unix_attributes_on_path(dest_path)
|
427
431
|
end
|
428
432
|
end
|
429
433
|
|
@@ -591,7 +595,7 @@ module Zip
|
|
591
595
|
def set_time(binary_dos_date, binary_dos_time)
|
592
596
|
@time = ::Zip::DOSTime.parse_binary_dos_format(binary_dos_date, binary_dos_time)
|
593
597
|
rescue ArgumentError
|
594
|
-
warn '
|
598
|
+
warn 'WARNING: invalid date/time in zip entry.' if ::Zip.warn_invalid_date
|
595
599
|
end
|
596
600
|
|
597
601
|
def create_file(dest_path, _continue_on_exists_proc = proc { Zip.continue_on_exists_proc })
|
@@ -601,8 +605,6 @@ module Zip
|
|
601
605
|
end
|
602
606
|
::File.open(dest_path, 'wb') do |os|
|
603
607
|
get_input_stream do |is|
|
604
|
-
set_extra_attributes_on_path(dest_path)
|
605
|
-
|
606
608
|
bytes_written = 0
|
607
609
|
warned = false
|
608
610
|
buf = ''.dup
|
@@ -610,17 +612,19 @@ module Zip
|
|
610
612
|
os << buf
|
611
613
|
bytes_written += buf.bytesize
|
612
614
|
if bytes_written > size && !warned
|
613
|
-
message = "
|
615
|
+
message = "entry '#{name}' should be #{size}B, but is larger when inflated."
|
614
616
|
if ::Zip.validate_entry_sizes
|
615
617
|
raise ::Zip::EntrySizeError, message
|
616
618
|
else
|
617
|
-
|
619
|
+
warn "WARNING: #{message}"
|
618
620
|
warned = true
|
619
621
|
end
|
620
622
|
end
|
621
623
|
end
|
622
624
|
end
|
623
625
|
end
|
626
|
+
|
627
|
+
set_extra_attributes_on_path(dest_path)
|
624
628
|
end
|
625
629
|
|
626
630
|
def create_directory(dest_path)
|
@@ -642,7 +646,7 @@ module Zip
|
|
642
646
|
def create_symlink(dest_path)
|
643
647
|
# TODO: Symlinks pose security challenges. Symlink support temporarily
|
644
648
|
# removed in view of https://github.com/rubyzip/rubyzip/issues/369 .
|
645
|
-
|
649
|
+
warn "WARNING: skipped symlink '#{dest_path}'."
|
646
650
|
end
|
647
651
|
|
648
652
|
# apply missing data from the zip64 extra information field, if present
|
@@ -16,7 +16,7 @@ module Zip
|
|
16
16
|
# If nil, start with empty.
|
17
17
|
return false
|
18
18
|
elsif binstr[0, 2] != self.class.const_get(:HEADER_ID)
|
19
|
-
|
19
|
+
warn 'WARNING: weird extra field header ID. Skip parsing it.'
|
20
20
|
return false
|
21
21
|
end
|
22
22
|
[binstr[2, 2].unpack('v')[0], binstr[4..-1]]
|
@@ -4,24 +4,51 @@ module Zip
|
|
4
4
|
HEADER_ID = 'UT'
|
5
5
|
register_map
|
6
6
|
|
7
|
+
ATIME_MASK = 0b010
|
8
|
+
CTIME_MASK = 0b100
|
9
|
+
MTIME_MASK = 0b001
|
10
|
+
|
7
11
|
def initialize(binstr = nil)
|
8
12
|
@ctime = nil
|
9
13
|
@mtime = nil
|
10
14
|
@atime = nil
|
11
|
-
@flag =
|
12
|
-
|
15
|
+
@flag = 0
|
16
|
+
|
17
|
+
merge(binstr) unless binstr.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :atime, :ctime, :mtime, :flag
|
21
|
+
|
22
|
+
def atime=(time)
|
23
|
+
@flag = time.nil? ? @flag & ~ATIME_MASK : @flag | ATIME_MASK
|
24
|
+
@atime = time
|
13
25
|
end
|
14
26
|
|
15
|
-
|
27
|
+
def ctime=(time)
|
28
|
+
@flag = time.nil? ? @flag & ~CTIME_MASK : @flag | CTIME_MASK
|
29
|
+
@ctime = time
|
30
|
+
end
|
31
|
+
|
32
|
+
def mtime=(time)
|
33
|
+
@flag = time.nil? ? @flag & ~MTIME_MASK : @flag | MTIME_MASK
|
34
|
+
@mtime = time
|
35
|
+
end
|
16
36
|
|
17
37
|
def merge(binstr)
|
18
38
|
return if binstr.empty?
|
39
|
+
|
19
40
|
size, content = initial_parse(binstr)
|
20
|
-
size ||
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
41
|
+
return if !size || size <= 0
|
42
|
+
|
43
|
+
@flag, *times = content.unpack('Cl<l<l<')
|
44
|
+
|
45
|
+
# Parse the timestamps, in order, based on which flags are set.
|
46
|
+
return if times[0].nil?
|
47
|
+
@mtime ||= ::Zip::DOSTime.at(times.shift) unless @flag & MTIME_MASK == 0
|
48
|
+
return if times[0].nil?
|
49
|
+
@atime ||= ::Zip::DOSTime.at(times.shift) unless @flag & ATIME_MASK == 0
|
50
|
+
return if times[0].nil?
|
51
|
+
@ctime ||= ::Zip::DOSTime.at(times.shift) unless @flag & CTIME_MASK == 0
|
25
52
|
end
|
26
53
|
|
27
54
|
def ==(other)
|
@@ -32,15 +59,15 @@ module Zip
|
|
32
59
|
|
33
60
|
def pack_for_local
|
34
61
|
s = [@flag].pack('C')
|
35
|
-
|
36
|
-
|
37
|
-
|
62
|
+
s << [@mtime.to_i].pack('l<') unless @flag & MTIME_MASK == 0
|
63
|
+
s << [@atime.to_i].pack('l<') unless @flag & ATIME_MASK == 0
|
64
|
+
s << [@ctime.to_i].pack('l<') unless @flag & CTIME_MASK == 0
|
38
65
|
s
|
39
66
|
end
|
40
67
|
|
41
68
|
def pack_for_c_dir
|
42
69
|
s = [@flag].pack('C')
|
43
|
-
|
70
|
+
s << [@mtime.to_i].pack('l<') unless @flag & MTIME_MASK == 0
|
44
71
|
s
|
45
72
|
end
|
46
73
|
end
|
data/lib/zip/file.rb
CHANGED
@@ -51,14 +51,23 @@ module Zip
|
|
51
51
|
DATA_BUFFER_SIZE = 8192
|
52
52
|
IO_METHODS = [:tell, :seek, :read, :close]
|
53
53
|
|
54
|
+
DEFAULT_OPTIONS = {
|
55
|
+
restore_ownership: false,
|
56
|
+
restore_permissions: false,
|
57
|
+
restore_times: false
|
58
|
+
}.freeze
|
59
|
+
|
54
60
|
attr_reader :name
|
55
61
|
|
56
|
-
# default -> false
|
62
|
+
# default -> false.
|
57
63
|
attr_accessor :restore_ownership
|
58
|
-
|
64
|
+
|
65
|
+
# default -> false, but will be set to true in a future version.
|
59
66
|
attr_accessor :restore_permissions
|
60
|
-
|
67
|
+
|
68
|
+
# default -> false, but will be set to true in a future version.
|
61
69
|
attr_accessor :restore_times
|
70
|
+
|
62
71
|
# Returns the zip files comment, if it has one
|
63
72
|
attr_accessor :comment
|
64
73
|
|
@@ -66,6 +75,7 @@ module Zip
|
|
66
75
|
# a new archive if it doesn't exist already.
|
67
76
|
def initialize(path_or_io, create = false, buffer = false, options = {})
|
68
77
|
super()
|
78
|
+
options = DEFAULT_OPTIONS.merge(options)
|
69
79
|
@name = path_or_io.respond_to?(:path) ? path_or_io.path : path_or_io
|
70
80
|
@comment = ''
|
71
81
|
@create = create ? true : false # allow any truthy value to mean true
|
@@ -98,17 +108,17 @@ module Zip
|
|
98
108
|
|
99
109
|
@stored_entries = @entry_set.dup
|
100
110
|
@stored_comment = @comment
|
101
|
-
@restore_ownership = options[:restore_ownership]
|
102
|
-
@restore_permissions = options[:restore_permissions]
|
103
|
-
@restore_times = options[:restore_times]
|
111
|
+
@restore_ownership = options[:restore_ownership]
|
112
|
+
@restore_permissions = options[:restore_permissions]
|
113
|
+
@restore_times = options[:restore_times]
|
104
114
|
end
|
105
115
|
|
106
116
|
class << self
|
107
|
-
#
|
108
|
-
# to the block and is automatically closed afterwards just as with
|
109
|
-
# ruby's builtin File
|
110
|
-
def open(file_name, create = false)
|
111
|
-
zf = ::Zip::File.new(file_name, create)
|
117
|
+
# Similar to ::new. If a block is passed the Zip::File object is passed
|
118
|
+
# to the block and is automatically closed afterwards, just as with
|
119
|
+
# ruby's builtin File::open method.
|
120
|
+
def open(file_name, create = false, options = {})
|
121
|
+
zf = ::Zip::File.new(file_name, create, false, options)
|
112
122
|
return zf unless block_given?
|
113
123
|
begin
|
114
124
|
yield zf
|
@@ -366,7 +376,13 @@ module Zip
|
|
366
376
|
# Searches for entry with the specified name. Returns nil if
|
367
377
|
# no entry is found. See also get_entry
|
368
378
|
def find_entry(entry_name)
|
369
|
-
@entry_set.find_entry(entry_name)
|
379
|
+
selected_entry = @entry_set.find_entry(entry_name)
|
380
|
+
return if selected_entry.nil?
|
381
|
+
|
382
|
+
selected_entry.restore_ownership = @restore_ownership
|
383
|
+
selected_entry.restore_permissions = @restore_permissions
|
384
|
+
selected_entry.restore_times = @restore_times
|
385
|
+
selected_entry
|
370
386
|
end
|
371
387
|
|
372
388
|
# Searches for entries given a glob
|
@@ -378,10 +394,8 @@ module Zip
|
|
378
394
|
# if no entry is found.
|
379
395
|
def get_entry(entry)
|
380
396
|
selected_entry = find_entry(entry)
|
381
|
-
raise Errno::ENOENT, entry
|
382
|
-
|
383
|
-
selected_entry.restore_permissions = @restore_permissions
|
384
|
-
selected_entry.restore_times = @restore_times
|
397
|
+
raise Errno::ENOENT, entry if selected_entry.nil?
|
398
|
+
|
385
399
|
selected_entry
|
386
400
|
end
|
387
401
|
|
data/lib/zip/input_stream.rb
CHANGED
@@ -2,12 +2,7 @@ module Zip
|
|
2
2
|
class StreamableStream < DelegateClass(Entry) # nodoc:all
|
3
3
|
def initialize(entry)
|
4
4
|
super(entry)
|
5
|
-
|
6
|
-
::File.dirname(zipfile)
|
7
|
-
else
|
8
|
-
nil
|
9
|
-
end
|
10
|
-
@temp_file = Tempfile.new(::File.basename(name), dirname)
|
5
|
+
@temp_file = Tempfile.new(::File.basename(name))
|
11
6
|
@temp_file.binmode
|
12
7
|
end
|
13
8
|
|
data/lib/zip/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubyzip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Simonov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -139,9 +139,9 @@ licenses:
|
|
139
139
|
- BSD 2-Clause
|
140
140
|
metadata:
|
141
141
|
bug_tracker_uri: https://github.com/rubyzip/rubyzip/issues
|
142
|
-
changelog_uri: https://github.com/rubyzip/rubyzip/blob/v2.
|
143
|
-
documentation_uri: https://www.rubydoc.info/gems/rubyzip/2.
|
144
|
-
source_code_uri: https://github.com/rubyzip/rubyzip/tree/v2.
|
142
|
+
changelog_uri: https://github.com/rubyzip/rubyzip/blob/v2.1.0/Changelog.md
|
143
|
+
documentation_uri: https://www.rubydoc.info/gems/rubyzip/2.1.0
|
144
|
+
source_code_uri: https://github.com/rubyzip/rubyzip/tree/v2.1.0
|
145
145
|
wiki_uri: https://github.com/rubyzip/rubyzip/wiki
|
146
146
|
post_install_message:
|
147
147
|
rdoc_options: []
|