zip_tricks 5.0.0 → 5.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/.travis.yml +2 -6
- data/CHANGELOG.md +32 -3
- data/lib/zip_tricks/file_reader.rb +3 -1
- data/lib/zip_tricks/remote_io.rb +43 -24
- data/lib/zip_tricks/remote_uncap.rb +3 -29
- data/lib/zip_tricks/size_estimator.rb +0 -3
- data/lib/zip_tricks/streamer.rb +40 -11
- data/lib/zip_tricks/streamer/entry.rb +5 -1
- data/lib/zip_tricks/version.rb +1 -1
- data/lib/zip_tricks/zip_writer.rb +15 -8
- data/zip_tricks.gemspec +2 -1
- metadata +21 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9e1ad9dd7452add6a2f9187edecdd366699d81fba9260692ce2a96003401eca
|
4
|
+
data.tar.gz: 1f2665b7c3a5c99ce190b5dab76fa9334ac4c6a3307928bab94758acd98bcb56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8864d6d56796e49e2024e46aee7cd1ac1c8ea575d757a6fbe6fd62a6e77db94eef6dc5b80bdbeae5bb932536e889fbdab224642862452f5b1acc0020e8a8c906
|
7
|
+
data.tar.gz: 67bc05db334c9a54804ac460f14f5919b9049913ee75532da090405f9a5b1f7e792ff4678aec0683a8b2a3136a9799ea3dd88aa3c9995491b28e4e6d88c4ac3a
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,32 @@
|
|
1
|
+
## 5.3.1
|
2
|
+
|
3
|
+
* Fix extended timestamp timestamp value encoding. Previously we would use an incorrect encoding for the timestamp value, which would output correct but nonsensical timestamps. The pack specifier is now changed to output the correct value.
|
4
|
+
|
5
|
+
## 5.3.0
|
6
|
+
|
7
|
+
* Raise in `Streamer#close` when the IO offset of the Streamer does not match the size of the written entries. This is a situation which
|
8
|
+
can occur if one adds the local headers, writes the bodies of the files to the socket/output directly, and forgets to adjust the internal
|
9
|
+
Streamer offset. The unadjusted offset would then produce incorrect values in both the local headers which come after the missing
|
10
|
+
offset adjustment _and_ in the central directory headers. Some ZIP unarchivers are able to recover from this (ones that read
|
11
|
+
files "straight-ahead" but others aren't - if the ZIP unarchiver uses central directory entries it would be using incorrect offsets.
|
12
|
+
Instead of producing an invalid ZIP, raise an exception which explains what happened and how it can be resolved.
|
13
|
+
|
14
|
+
## 5.2.0
|
15
|
+
|
16
|
+
* Remove `Streamer#add_compressed_entry` and `SizeEstimator#add_compressed_entry`
|
17
|
+
|
18
|
+
## 5.1.1
|
19
|
+
|
20
|
+
* Fix extended timestamp extra field output. The first bit of the flag would be set instead of the last bit of
|
21
|
+
the flag, which made it impossible for Rubyzip to read the timestamp of the entry - and it would also make
|
22
|
+
the extra field useless for most reading applications.
|
23
|
+
|
24
|
+
## 5.1.0
|
25
|
+
|
26
|
+
* Slightly rework `RemoteIO` and `RemoteUncap` and make sure they work correctly by spinning up a test webserver
|
27
|
+
to verify their operation. The changes to the documented API are fairly small so this is still marked as a minor
|
28
|
+
release.
|
29
|
+
|
1
30
|
## 5.0.0
|
2
31
|
|
3
32
|
* Disable automatic filename deduplication by default, because it does not play nice with file/directory
|
@@ -19,16 +48,16 @@
|
|
19
48
|
|
20
49
|
## 4.7.4
|
21
50
|
|
22
|
-
* Use a single fixed capacity string in StreamCRC32.from_io to avoid unnecessary allocations
|
51
|
+
* Use a single fixed capacity string in `StreamCRC32.from_io` to avoid unnecessary allocations
|
23
52
|
* Fix a few tests that were calling out to external binaries
|
24
53
|
|
25
54
|
## 4.7.3
|
26
55
|
|
27
|
-
* Fix RemoteUncap#request_object_size to function correctly
|
56
|
+
* Fix `RemoteUncap#request_object_size` to function correctly
|
28
57
|
|
29
58
|
## 4.7.2
|
30
59
|
|
31
|
-
* Relax bundler dependency so that both 1.x and 2.x are supported cleanly
|
60
|
+
* Relax bundler dependency so that both bundler 1.x and 2.x are supported cleanly
|
32
61
|
|
33
62
|
## 4.7.1
|
34
63
|
|
@@ -82,7 +82,9 @@ class ZipTricks::FileReader
|
|
82
82
|
|
83
83
|
private_constant :StoredReader, :InflatingReader
|
84
84
|
|
85
|
-
# Represents a file within the ZIP archive being read
|
85
|
+
# Represents a file within the ZIP archive being read. This is different from
|
86
|
+
# the Entry object used in Streamer for ZIP writing, since during writing more
|
87
|
+
# data can be kept in memory for immediate use.
|
86
88
|
class ZipEntry
|
87
89
|
# @return [Fixnum] bit-packed version signature of the program that made the archive
|
88
90
|
attr_accessor :made_by
|
data/lib/zip_tricks/remote_io.rb
CHANGED
@@ -8,14 +8,16 @@
|
|
8
8
|
# actual fetches over HTTP and an object that expects a handful of IO methods to be
|
9
9
|
# available.
|
10
10
|
class ZipTricks::RemoteIO
|
11
|
-
# @param
|
12
|
-
def initialize(
|
11
|
+
# @param url[String, URI] the HTTP/HTTPS URL of the object to be retrieved
|
12
|
+
def initialize(url)
|
13
13
|
@pos = 0
|
14
|
-
@
|
15
|
-
@remote_size =
|
14
|
+
@uri = URI(url)
|
15
|
+
@remote_size = nil
|
16
16
|
end
|
17
17
|
|
18
18
|
# Emulates IO#seek
|
19
|
+
# @param offset[Integer] absolute offset in the remote resource to seek to
|
20
|
+
# @param mode[Integer] The seek mode (only SEEK_SET is supported)
|
19
21
|
def seek(offset, mode = IO::SEEK_SET)
|
20
22
|
raise "Unsupported read mode #{mode}" unless mode == IO::SEEK_SET
|
21
23
|
@remote_size ||= request_object_size
|
@@ -25,7 +27,7 @@ class ZipTricks::RemoteIO
|
|
25
27
|
|
26
28
|
# Emulates IO#size.
|
27
29
|
#
|
28
|
-
# @return [
|
30
|
+
# @return [Integer] the size of the remote resource
|
29
31
|
def size
|
30
32
|
@remote_size ||= request_object_size
|
31
33
|
end
|
@@ -39,21 +41,20 @@ class ZipTricks::RemoteIO
|
|
39
41
|
# @param n_bytes[Fixnum, nil] how many bytes to read, or `nil` to read all the way to the end
|
40
42
|
# @return [String] the read bytes
|
41
43
|
def read(n_bytes = nil)
|
42
|
-
@remote_size ||= request_object_size
|
43
|
-
|
44
44
|
# If the resource is empty there is nothing to read
|
45
|
-
return if
|
45
|
+
return if size.zero?
|
46
46
|
|
47
|
-
maximum_avaialable =
|
47
|
+
maximum_avaialable = size - @pos
|
48
48
|
n_bytes ||= maximum_avaialable # nil == read to the end of file
|
49
49
|
return '' if n_bytes.zero?
|
50
50
|
raise ArgumentError, "No negative reads(#{n_bytes})" if n_bytes < 0
|
51
51
|
|
52
52
|
n_bytes = clamp(0, n_bytes, maximum_avaialable)
|
53
53
|
|
54
|
-
|
54
|
+
http_range = (@pos..(@pos + n_bytes - 1))
|
55
|
+
request_range(http_range).tap do |data|
|
55
56
|
raise "Remote read returned #{data.bytesize} bytes instead of #{n_bytes} as requested" if data.bytesize != n_bytes
|
56
|
-
@pos = clamp(0, @pos + data.bytesize,
|
57
|
+
@pos = clamp(0, @pos + data.bytesize, size)
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
@@ -66,23 +67,41 @@ class ZipTricks::RemoteIO
|
|
66
67
|
|
67
68
|
protected
|
68
69
|
|
70
|
+
# Only used internally when reading the remote ZIP.
|
71
|
+
#
|
72
|
+
# @param range[Range] the HTTP range of data to fetch from remote
|
73
|
+
# @return [String] the response body of the ranged request
|
69
74
|
def request_range(range)
|
70
|
-
@
|
75
|
+
http = Net::HTTP.start(@uri.hostname, @uri.port)
|
76
|
+
request = Net::HTTP::Get.new(@uri)
|
77
|
+
request.range = range
|
78
|
+
response = http.request(request)
|
79
|
+
case response.code
|
80
|
+
when "206", "200"
|
81
|
+
response.body
|
82
|
+
else
|
83
|
+
raise "Remote at #{@uri} replied with code #{response.code}"
|
84
|
+
end
|
71
85
|
end
|
72
86
|
|
87
|
+
# For working with S3 it is a better idea to perform a GET request for one byte, since doing a HEAD
|
88
|
+
# request needs a different permission - and standard GET presigned URLs are not allowed to perform it
|
89
|
+
#
|
90
|
+
# @return [Integer] the size of the remote resource, parsed either from Content-Length or Content-Range header
|
73
91
|
def request_object_size
|
74
|
-
@
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
92
|
+
http = Net::HTTP.start(@uri.hostname, @uri.port)
|
93
|
+
request = Net::HTTP::Get.new(@uri)
|
94
|
+
request.range = 0..0
|
95
|
+
response = http.request(request)
|
96
|
+
case response.code
|
97
|
+
when "206"
|
98
|
+
content_range_header_value = response['Content-Range']
|
99
|
+
content_range_header_value.split('/').last.to_i
|
100
|
+
when "200"
|
101
|
+
response['Content-Length'].to_i
|
102
|
+
else
|
103
|
+
raise "Remote at #{@uri} replied with code #{response.code}"
|
104
|
+
end
|
86
105
|
end
|
87
106
|
|
88
107
|
private
|
@@ -7,42 +7,16 @@
|
|
7
7
|
#
|
8
8
|
# Please read the security warning in `FileReader` _VERY CAREFULLY_
|
9
9
|
# before you use this module.
|
10
|
-
|
10
|
+
module ZipTricks::RemoteUncap
|
11
11
|
# @param uri[String] the HTTP(S) URL to read the ZIP footer from
|
12
12
|
# @param reader_class[Class] which class to use for reading
|
13
13
|
# @param options_for_zip_reader[Hash] any additional options to give to
|
14
14
|
# {ZipTricks::FileReader} when reading
|
15
15
|
# @return [Array<ZipTricks::FileReader::ZipEntry>] metadata about the
|
16
16
|
# files within the remote archive
|
17
|
-
def self.files_within_zip_at(uri,
|
18
|
-
|
19
|
-
**options_for_zip_reader)
|
20
|
-
fetcher = new(uri)
|
21
|
-
fake_io = ZipTricks::RemoteIO.new(fetcher)
|
17
|
+
def self.files_within_zip_at(uri, reader_class: ZipTricks::FileReader, **options_for_zip_reader)
|
18
|
+
fake_io = ZipTricks::RemoteIO.new(uri)
|
22
19
|
reader = reader_class.new
|
23
20
|
reader.read_zip_structure(io: fake_io, **options_for_zip_reader)
|
24
21
|
end
|
25
|
-
|
26
|
-
def initialize(uri)
|
27
|
-
@uri = URI(uri)
|
28
|
-
end
|
29
|
-
|
30
|
-
# Only used internally when reading the remote ZIP.
|
31
|
-
#
|
32
|
-
# @param range[Range] the HTTP range of data to fetch from remote
|
33
|
-
# @return [String] the response body of the ranged request
|
34
|
-
def request_range(range)
|
35
|
-
request = Net::HTTP::Get.new(@uri)
|
36
|
-
request.range = range
|
37
|
-
http = Net::HTTP.start(@uri.hostname, @uri.port)
|
38
|
-
http.request(request).body
|
39
|
-
end
|
40
|
-
|
41
|
-
# Only used internally when reading the remote ZIP.
|
42
|
-
#
|
43
|
-
# @return [Fixnum] the byte size of the ranged request
|
44
|
-
def request_object_size
|
45
|
-
http = Net::HTTP.start(@uri.hostname, @uri.port)
|
46
|
-
http.request_head(@uri)['Content-Length'].to_i
|
47
|
-
end
|
48
22
|
end
|
data/lib/zip_tricks/streamer.rb
CHANGED
@@ -91,6 +91,7 @@ class ZipTricks::Streamer
|
|
91
91
|
InvalidOutput = Class.new(ArgumentError)
|
92
92
|
Overflow = Class.new(StandardError)
|
93
93
|
UnknownMode = Class.new(StandardError)
|
94
|
+
OffsetOutOfSync = Class.new(StandardError)
|
94
95
|
|
95
96
|
private_constant :DeflatedWriter, :StoredWriter, :STORED, :DEFLATED
|
96
97
|
|
@@ -149,7 +150,6 @@ class ZipTricks::Streamer
|
|
149
150
|
@dedupe_filenames = auto_rename_duplicate_filenames
|
150
151
|
@out = ZipTricks::WriteAndTell.new(stream)
|
151
152
|
@files = []
|
152
|
-
@local_header_offsets = []
|
153
153
|
@path_set = ZipTricks::PathSet.new
|
154
154
|
@writer = writer
|
155
155
|
end
|
@@ -213,9 +213,6 @@ class ZipTricks::Streamer
|
|
213
213
|
@out.tell
|
214
214
|
end
|
215
215
|
|
216
|
-
# Will be phased out in ZipTricks 5.x
|
217
|
-
alias_method :add_compressed_entry, :add_deflated_entry
|
218
|
-
|
219
216
|
# Writes out the local header for an entry (file in the ZIP) that is using
|
220
217
|
# the stored storage model (is stored as-is).
|
221
218
|
# Once this method is called, the `<<` method has to be called one or more
|
@@ -363,14 +360,16 @@ class ZipTricks::Streamer
|
|
363
360
|
#
|
364
361
|
# @return [Integer] the offset the output IO is at after closing the archive
|
365
362
|
def close
|
363
|
+
# Make sure offsets are in order
|
364
|
+
verify_offsets!
|
365
|
+
|
366
366
|
# Record the central directory offset, so that it can be written into the EOCD record
|
367
367
|
cdir_starts_at = @out.tell
|
368
368
|
|
369
369
|
# Write out the central directory entries, one for each file
|
370
|
-
@files.
|
371
|
-
header_loc = @local_header_offsets.fetch(i)
|
370
|
+
@files.each do |entry|
|
372
371
|
@writer.write_central_directory_file_header(io: @out,
|
373
|
-
local_file_header_location:
|
372
|
+
local_file_header_location: entry.local_header_offset,
|
374
373
|
gp_flags: entry.gp_flags,
|
375
374
|
storage_mode: entry.storage_mode,
|
376
375
|
compressed_size: entry.compressed_size,
|
@@ -423,15 +422,40 @@ class ZipTricks::Streamer
|
|
423
422
|
last_entry.compressed_size = compressed_size
|
424
423
|
last_entry.uncompressed_size = uncompressed_size
|
425
424
|
|
425
|
+
offset_before_data_descriptor = @out.tell
|
426
426
|
@writer.write_data_descriptor(io: @out,
|
427
427
|
crc32: last_entry.crc32,
|
428
428
|
compressed_size: last_entry.compressed_size,
|
429
429
|
uncompressed_size: last_entry.uncompressed_size)
|
430
|
+
last_entry.bytes_used_for_data_descriptor = @out.tell - offset_before_data_descriptor
|
431
|
+
|
430
432
|
@out.tell
|
431
433
|
end
|
432
434
|
|
433
435
|
private
|
434
436
|
|
437
|
+
def verify_offsets!
|
438
|
+
# We need to check whether the offsets noted for the entries actually make sense
|
439
|
+
computed_offset = @files.map(&:total_bytes_used).inject(0, &:+)
|
440
|
+
actual_offset = @out.tell
|
441
|
+
if computed_offset != actual_offset
|
442
|
+
message = <<-EMS
|
443
|
+
The offset of the Streamer output IO is out of sync with the expected value. All entries written so far,
|
444
|
+
including their compressed bodies, local headers and data descriptors, add up to a certain offset,
|
445
|
+
but this offset does not match the actual offset of the IO.
|
446
|
+
|
447
|
+
Entries add up to #{computed_offset} bytes and the IO is at #{actual_offset} bytes.
|
448
|
+
|
449
|
+
This can happen if you write local headers for an entry, write the "body" of the entry directly to the IO
|
450
|
+
object which is your destination, but do not adjust the offset known to the Streamer object. To adjust
|
451
|
+
the offfset you need to call `Streamer#simulate_write(body_size)` after outputting the entry. Otherwise
|
452
|
+
the local header offsets of the entries you write are going to be incorrect and some ZIP applications
|
453
|
+
are going to have problems opening your archive.
|
454
|
+
EMS
|
455
|
+
raise OffsetOutOfSync, message
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
435
459
|
def add_file_and_write_local_header(
|
436
460
|
filename:,
|
437
461
|
modification_time:,
|
@@ -464,16 +488,18 @@ class ZipTricks::Streamer
|
|
464
488
|
uncompressed_size = 0
|
465
489
|
end
|
466
490
|
|
491
|
+
local_header_starts_at = @out.tell
|
492
|
+
|
467
493
|
e = Entry.new(filename,
|
468
494
|
crc32,
|
469
495
|
compressed_size,
|
470
496
|
uncompressed_size,
|
471
497
|
storage_mode,
|
472
498
|
modification_time,
|
473
|
-
use_data_descriptor
|
474
|
-
|
475
|
-
|
476
|
-
|
499
|
+
use_data_descriptor,
|
500
|
+
_local_file_header_offset = local_header_starts_at,
|
501
|
+
_bytes_used_for_local_header = 0,
|
502
|
+
_bytes_used_for_data_descriptor = 0)
|
477
503
|
|
478
504
|
@writer.write_local_file_header(io: @out,
|
479
505
|
gp_flags: e.gp_flags,
|
@@ -483,6 +509,9 @@ class ZipTricks::Streamer
|
|
483
509
|
mtime: e.mtime,
|
484
510
|
filename: e.filename,
|
485
511
|
storage_mode: e.storage_mode)
|
512
|
+
e.bytes_used_for_local_header = @out.tell - e.local_header_offset
|
513
|
+
|
514
|
+
@files << e
|
486
515
|
end
|
487
516
|
|
488
517
|
def remove_backslash(filename)
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# Normally you will not have to use this class directly
|
5
5
|
class ZipTricks::Streamer::Entry < Struct.new(:filename, :crc32, :compressed_size,
|
6
6
|
:uncompressed_size, :storage_mode, :mtime,
|
7
|
-
:use_data_descriptor)
|
7
|
+
:use_data_descriptor, :local_header_offset, :bytes_used_for_local_header, :bytes_used_for_data_descriptor)
|
8
8
|
def initialize(*)
|
9
9
|
super
|
10
10
|
filename.force_encoding(Encoding::UTF_8)
|
@@ -15,6 +15,10 @@ class ZipTricks::Streamer::Entry < Struct.new(:filename, :crc32, :compressed_siz
|
|
15
15
|
end)
|
16
16
|
end
|
17
17
|
|
18
|
+
def total_bytes_used
|
19
|
+
bytes_used_for_local_header + compressed_size + bytes_used_for_data_descriptor
|
20
|
+
end
|
21
|
+
|
18
22
|
# Set the general purpose flags for the entry. We care about is the EFS
|
19
23
|
# bit (bit 11) which should be set if the filename is UTF8. If it is, we need to set the
|
20
24
|
# bit so that the unarchiving application knows that the filename in the archive is UTF-8
|
data/lib/zip_tricks/version.rb
CHANGED
@@ -57,7 +57,7 @@ class ZipTricks::ZipWriter
|
|
57
57
|
C_UINT2 = 'v' # Encode a 2-byte unsigned little-endian uint
|
58
58
|
C_UINT8 = 'Q<' # Encode an 8-byte unsigned little-endian uint
|
59
59
|
C_CHAR = 'C' # For bit-encoded strings
|
60
|
-
C_INT4 = '
|
60
|
+
C_INT4 = 'l<' # Encode a 4-byte signed little-endian int
|
61
61
|
|
62
62
|
private_constant :FOUR_BYTE_MAX_UINT,
|
63
63
|
:TWO_BYTE_MAX_UINT,
|
@@ -118,7 +118,7 @@ class ZipTricks::ZipWriter
|
|
118
118
|
if requires_zip64
|
119
119
|
extra_fields << zip_64_extra_for_local_file_header(compressed_size: compressed_size, uncompressed_size: uncompressed_size)
|
120
120
|
end
|
121
|
-
extra_fields <<
|
121
|
+
extra_fields << timestamp_extra_for_local_file_header(mtime)
|
122
122
|
|
123
123
|
io << [extra_fields.size].pack(C_UINT2) # extra field length 2 bytes
|
124
124
|
|
@@ -182,7 +182,7 @@ class ZipTricks::ZipWriter
|
|
182
182
|
compressed_size: compressed_size,
|
183
183
|
uncompressed_size: uncompressed_size)
|
184
184
|
end
|
185
|
-
extra_fields <<
|
185
|
+
extra_fields << timestamp_extra_for_central_directory_entry(mtime)
|
186
186
|
|
187
187
|
io << [extra_fields.size].pack(C_UINT2) # extra field length 2 bytes
|
188
188
|
|
@@ -345,12 +345,14 @@ class ZipTricks::ZipWriter
|
|
345
345
|
pack_array(data_and_packspecs)
|
346
346
|
end
|
347
347
|
|
348
|
-
# Writes the extended timestamp information field
|
348
|
+
# Writes the extended timestamp information field for local headers.
|
349
|
+
#
|
350
|
+
# The spec defines 2
|
349
351
|
# different formats - the one for the local file header can also accomodate the
|
350
352
|
# atime and ctime, whereas the one for the central directory can only take
|
351
353
|
# the mtime - and refers the reader to the local header extra to obtain the
|
352
354
|
# remaining times
|
353
|
-
def
|
355
|
+
def timestamp_extra_for_local_file_header(mtime)
|
354
356
|
# Local-header version:
|
355
357
|
#
|
356
358
|
# Value Size Description
|
@@ -378,16 +380,21 @@ class ZipTricks::ZipWriter
|
|
378
380
|
# bit 1 if set, access time is present
|
379
381
|
# bit 2 if set, creation time is present
|
380
382
|
# bits 3-7 reserved for additional timestamps; not set
|
381
|
-
flags =
|
383
|
+
flags = 0b00000001 # Set the lowest bit only, to indicate that only mtime is present
|
382
384
|
data_and_packspecs = [
|
383
385
|
0x5455, C_UINT2, # tag for this extra block type ("UT")
|
384
|
-
(1 + 4), C_UINT2, # the size of this block (1 byte used for the Flag +
|
386
|
+
(1 + 4), C_UINT2, # the size of this block (1 byte used for the Flag + 3 longs used for the timestamp)
|
385
387
|
flags, C_CHAR, # encode a single byte
|
386
|
-
mtime.utc.to_i, C_INT4, # Use a signed
|
388
|
+
mtime.utc.to_i, C_INT4, # Use a signed int, not the unsigned one used by the rest of the ZIP spec.
|
387
389
|
]
|
390
|
+
# The atime and ctime can be omitted if not present
|
388
391
|
pack_array(data_and_packspecs)
|
389
392
|
end
|
390
393
|
|
394
|
+
# Since we do not supply atime or ctime, the contents of the two extra fields (central dir and local header)
|
395
|
+
# is exactly the same, so we can use a method alias.
|
396
|
+
alias_method :timestamp_extra_for_central_directory_entry, :timestamp_extra_for_local_file_header
|
397
|
+
|
391
398
|
# Writes the Zip64 extra field for the central directory header.It differs from the extra used in the local file header because it
|
392
399
|
# also contains the location of the local file header in the ZIP as an 8-byte int.
|
393
400
|
#
|
data/zip_tricks.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.require_paths = ['lib']
|
32
32
|
|
33
33
|
spec.add_development_dependency 'bundler'
|
34
|
-
spec.add_development_dependency 'rubyzip', '
|
34
|
+
spec.add_development_dependency 'rubyzip', '~> 1'
|
35
35
|
spec.add_development_dependency 'terminal-table'
|
36
36
|
spec.add_development_dependency 'range_utils'
|
37
37
|
|
@@ -44,4 +44,5 @@ Gem::Specification.new do |spec|
|
|
44
44
|
spec.add_development_dependency 'allocation_stats', '~> 0.1.5'
|
45
45
|
spec.add_development_dependency 'yard', '~> 0.9'
|
46
46
|
spec.add_development_dependency 'wetransfer_style', '0.6.0'
|
47
|
+
spec.add_development_dependency 'puma'
|
47
48
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zip_tricks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2020-06-16 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -31,16 +31,16 @@ dependencies:
|
|
31
31
|
name: rubyzip
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
requirements:
|
34
|
-
- - "
|
34
|
+
- - "~>"
|
35
35
|
- !ruby/object:Gem::Version
|
36
|
-
version: 1
|
36
|
+
version: '1'
|
37
37
|
type: :development
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
|
-
- - "
|
41
|
+
- - "~>"
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 1
|
43
|
+
version: '1'
|
44
44
|
- !ruby/object:Gem::Dependency
|
45
45
|
name: terminal-table
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
@@ -195,6 +195,20 @@ dependencies:
|
|
195
195
|
- - '='
|
196
196
|
- !ruby/object:Gem::Version
|
197
197
|
version: 0.6.0
|
198
|
+
- !ruby/object:Gem::Dependency
|
199
|
+
name: puma
|
200
|
+
requirement: !ruby/object:Gem::Requirement
|
201
|
+
requirements:
|
202
|
+
- - ">="
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
version: '0'
|
205
|
+
type: :development
|
206
|
+
prerelease: false
|
207
|
+
version_requirements: !ruby/object:Gem::Requirement
|
208
|
+
requirements:
|
209
|
+
- - ">="
|
210
|
+
- !ruby/object:Gem::Version
|
211
|
+
version: '0'
|
198
212
|
description: Stream out ZIP files from Ruby
|
199
213
|
email:
|
200
214
|
- me@julik.nl
|
@@ -278,7 +292,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
278
292
|
- !ruby/object:Gem::Version
|
279
293
|
version: '0'
|
280
294
|
requirements: []
|
281
|
-
rubygems_version: 3.0.
|
295
|
+
rubygems_version: 3.0.3
|
282
296
|
signing_key:
|
283
297
|
specification_version: 4
|
284
298
|
summary: Stream out ZIP files from Ruby
|