rubyzip 2.0.0 → 2.1.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 +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: []
|