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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e2be8aa3dea85f1e99fa26b5b2530ede874228f35379181d5219eb3864a0e33
4
- data.tar.gz: '0985b8cd0b421a0bdf83953ba907ddad52d236948a81a242f322f0f5fa2145a6'
3
+ metadata.gz: 7befb1c4855935534788418759d90641e37bd31c53428b5ba04c6c8c4bc4a544
4
+ data.tar.gz: 9b5669fc4b3c8a03cc39c73c7ae0e26ece01a2e51a401274f737a43798592b5b
5
5
  SHA512:
6
- metadata.gz: c870bef8352ddb4e706a847f66da596fe556938d1b1422c3541f8ab24aa10bbdb6be577cd031853459101e24a4290aa816436834d1cae66dd26238b451f41d15
7
- data.tar.gz: bb5c8ca7d286346bfad64a6e1bd637cb8a40a99974bc62fbd76ea1a5ee139d16dcf52a8480cc219e48e311d84046feafab2c497cfbeb0721940a06a5c7a163a2
6
+ metadata.gz: a537f87d0051073f2a31ced8f732d0b3b5c7376e792d02d3c1a52b597133f0f4be16b6c2c2564624104b179e501b7016ec6fecdde3681709d9730b5fb124dc72
7
+ data.tar.gz: 37ed030e2ffbb243bc639e969d050d21836448f746c1d47a49b8f77417b286438bee60dd80a6ba1e333642db218a56d32908ccbce4b3b6873082c42a709c6c77
data/lib/zip.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'delegate'
2
2
  require 'singleton'
3
3
  require 'tempfile'
4
- require 'tmpdir'
5
4
  require 'fileutils'
6
5
  require 'stringio'
7
6
  require 'zlib'
@@ -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
@@ -34,7 +34,7 @@ module Zip
34
34
  end
35
35
  @follow_symlinks = false
36
36
 
37
- @restore_times = true
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
- puts "WARNING: skipped #{@name} as unsafe"
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 set_unix_permissions_on_path(dest_path)
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
- # File::utimes()
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
- set_unix_permissions_on_path(dest_path)
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 'Invalid date/time in zip entry' if ::Zip.warn_invalid_date
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 = "Entry #{name} should be #{size}B but is larger when inflated"
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
- puts "WARNING: #{message}"
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
- puts "WARNING: skipped symlink #{dest_path}"
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
- $stderr.puts 'Warning: weired extra feild header ID. skip parsing'
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 = nil
12
- binstr && merge(binstr)
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
- attr_accessor :atime, :ctime, :mtime, :flag
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 || return
21
- @flag, mtime, atime, ctime = content.unpack('CVVV')
22
- mtime && @mtime ||= ::Zip::DOSTime.at(mtime)
23
- atime && @atime ||= ::Zip::DOSTime.at(atime)
24
- ctime && @ctime ||= ::Zip::DOSTime.at(ctime)
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
- @flag & 1 != 0 && s << [@mtime.to_i].pack('V')
36
- @flag & 2 != 0 && s << [@atime.to_i].pack('V')
37
- @flag & 4 != 0 && s << [@ctime.to_i].pack('V')
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
- @flag & 1 == 1 && s << [@mtime.to_i].pack('V')
70
+ s << [@mtime.to_i].pack('l<') unless @flag & MTIME_MASK == 0
44
71
  s
45
72
  end
46
73
  end
@@ -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
- # default -> false
64
+
65
+ # default -> false, but will be set to true in a future version.
59
66
  attr_accessor :restore_permissions
60
- # default -> true
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] || false
102
- @restore_permissions = options[:restore_permissions] || true
103
- @restore_times = options[:restore_times] || true
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
- # Same as #new. If a block is passed the ZipFile object is passed
108
- # to the block and is automatically closed afterwards just as with
109
- # ruby's builtin File.open method.
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 unless selected_entry
382
- selected_entry.restore_ownership = @restore_ownership
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
 
@@ -103,7 +103,7 @@ module Zip
103
103
  end
104
104
 
105
105
  def open_buffer(filename_or_io, offset = 0)
106
- puts 'open_buffer is deprecated!!! Use open instead!'
106
+ warn 'open_buffer is deprecated!!! Use open instead!'
107
107
  open(filename_or_io, offset)
108
108
  end
109
109
  end
@@ -2,12 +2,7 @@ module Zip
2
2
  class StreamableStream < DelegateClass(Entry) # nodoc:all
3
3
  def initialize(entry)
4
4
  super(entry)
5
- dirname = if zipfile.is_a?(::String)
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
 
@@ -1,3 +1,3 @@
1
1
  module Zip
2
- VERSION = '2.0.0'
2
+ VERSION = '2.1.0'
3
3
  end
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.0.0
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: 2019-09-25 00:00:00.000000000 Z
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.0.0/Changelog.md
143
- documentation_uri: https://www.rubydoc.info/gems/rubyzip/2.0.0
144
- source_code_uri: https://github.com/rubyzip/rubyzip/tree/v2.0.0
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: []