zip_tricks 5.2.0 → 5.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +96 -0
- data/.gitignore +2 -1
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +37 -1
- data/CONTRIBUTING.md +4 -4
- data/README.md +28 -17
- data/lib/zip_tricks/block_write.rb +26 -21
- data/lib/zip_tricks/file_reader.rb +8 -6
- data/lib/zip_tricks/null_writer.rb +1 -1
- data/lib/zip_tricks/output_enumerator.rb +48 -27
- data/lib/zip_tricks/path_set.rb +4 -0
- data/lib/zip_tricks/rails_streaming.rb +7 -9
- data/lib/zip_tricks/stream_crc32.rb +2 -2
- data/lib/zip_tricks/streamer.rb +69 -25
- data/lib/zip_tricks/streamer/deflated_writer.rb +9 -28
- data/lib/zip_tricks/streamer/entry.rb +5 -1
- data/lib/zip_tricks/streamer/stored_writer.rb +4 -3
- data/lib/zip_tricks/version.rb +1 -1
- data/lib/zip_tricks/write_and_tell.rb +2 -12
- data/lib/zip_tricks/write_buffer.rb +37 -17
- data/lib/zip_tricks/zip_writer.rb +24 -24
- data/zip_tricks.gemspec +3 -5
- metadata +8 -44
- data/.travis.yml +0 -11
- data/qa/README_QA.md +0 -16
- data/qa/generate_test_files.rb +0 -126
- data/qa/in/VTYL8830.jpg +0 -0
- data/qa/in/war-and-peace.txt +0 -10810
- data/qa/support.rb +0 -88
- data/qa/test-report-2016-07-28.txt +0 -156
- data/qa/test-report-2016-12-12.txt +0 -156
- data/qa/test-report-2017-04-2.txt +0 -168
- data/qa/test-report.txt +0 -28
@@ -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, :unix_permissions)
|
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
|
@@ -12,7 +12,8 @@ class ZipTricks::Streamer::StoredWriter
|
|
12
12
|
|
13
13
|
def initialize(io)
|
14
14
|
@io = ZipTricks::WriteAndTell.new(io)
|
15
|
-
@
|
15
|
+
@crc_compute = ZipTricks::StreamCRC32.new
|
16
|
+
@crc = ZipTricks::WriteBuffer.new(@crc_compute, CRC32_BUFFER_SIZE)
|
16
17
|
end
|
17
18
|
|
18
19
|
# Writes the given data to the contained IO object.
|
@@ -28,9 +29,9 @@ class ZipTricks::Streamer::StoredWriter
|
|
28
29
|
# Returns the amount of data written and the CRC32 checksum. The return value
|
29
30
|
# can be directly used as the argument to {Streamer#update_last_entry_and_write_data_descriptor}
|
30
31
|
#
|
31
|
-
# @param data[String] data to be written
|
32
32
|
# @return [Hash] a hash of `{crc32, compressed_size, uncompressed_size}`
|
33
33
|
def finish
|
34
|
-
|
34
|
+
@crc.flush
|
35
|
+
{crc32: @crc_compute.to_i, compressed_size: @io.tell, uncompressed_size: @io.tell}
|
35
36
|
end
|
36
37
|
end
|
data/lib/zip_tricks/version.rb
CHANGED
@@ -10,9 +10,8 @@ class ZipTricks::WriteAndTell
|
|
10
10
|
|
11
11
|
def <<(bytes)
|
12
12
|
return self if bytes.nil?
|
13
|
-
|
14
|
-
@
|
15
|
-
@pos += binary_bytes.bytesize
|
13
|
+
@io << bytes.b
|
14
|
+
@pos += bytes.bytesize
|
16
15
|
self
|
17
16
|
end
|
18
17
|
|
@@ -23,13 +22,4 @@ class ZipTricks::WriteAndTell
|
|
23
22
|
def tell
|
24
23
|
@pos
|
25
24
|
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def binary(str)
|
30
|
-
return str if str.encoding == Encoding::BINARY
|
31
|
-
str.force_encoding(Encoding::BINARY)
|
32
|
-
rescue RuntimeError # the string is frozen
|
33
|
-
str.dup.force_encoding(Encoding::BINARY)
|
34
|
-
end
|
35
25
|
end
|
@@ -7,13 +7,34 @@
|
|
7
7
|
# CRC32 combine operations - and this adds up. Since the CRC32 value
|
8
8
|
# is usually not needed until the complete output has completed
|
9
9
|
# we can buffer at least some amount of data before computing CRC32 over it.
|
10
|
+
# We also use this buffer for output via Rack, where some amount of buffering
|
11
|
+
# helps reduce the number of syscalls made by the webserver. ZipTricks performs
|
12
|
+
# lots of very small writes, and some degree of speedup (about 20%) can be achieved
|
13
|
+
# with a buffer of a few KB.
|
14
|
+
#
|
15
|
+
# Note that there is no guarantee that the write buffer is going to flush at or above
|
16
|
+
# the given `buffer_size`, because for writes which exceed the buffer size it will
|
17
|
+
# first `flush` and then write through the oversized chunk, without buffering it. This
|
18
|
+
# helps conserve memory. Also note that the buffer will *not* duplicate strings for you
|
19
|
+
# and *will* yield the same buffer String over and over, so if you are storing it in an
|
20
|
+
# Array you might need to duplicate it.
|
21
|
+
#
|
22
|
+
# Note also that the WriteBuffer assumes that the object it `<<`-writes into is going
|
23
|
+
# to **consume** in some way the string that it passes in. After the `<<` method returns,
|
24
|
+
# the WriteBuffer will be cleared, and it passes the same String reference on every call
|
25
|
+
# to `<<`. Therefore, if you need to retain the output of the WriteBuffer in, say, an Array,
|
26
|
+
# you might need to `.dup` the `String` it gives you.
|
10
27
|
class ZipTricks::WriteBuffer
|
11
28
|
# Creates a new WriteBuffer bypassing into a given writable object
|
12
29
|
#
|
13
|
-
# @param writable[#<<] An object that responds to `#<<` with
|
30
|
+
# @param writable[#<<] An object that responds to `#<<` with a String as argument
|
14
31
|
# @param buffer_size[Integer] How many bytes to buffer
|
15
32
|
def initialize(writable, buffer_size)
|
16
|
-
|
33
|
+
# Allocating the buffer using a zero-padded String as a variation
|
34
|
+
# on using capacity:, which JRuby apparently does not like very much. The
|
35
|
+
# desire here is that the buffer doesn't have to be resized during the lifetime
|
36
|
+
# of the object.
|
37
|
+
@buf = ("\0".b * (buffer_size * 2)).clear
|
17
38
|
@buffer_size = buffer_size
|
18
39
|
@writable = writable
|
19
40
|
end
|
@@ -24,28 +45,27 @@ class ZipTricks::WriteBuffer
|
|
24
45
|
# @param data[String] data to be written
|
25
46
|
# @return self
|
26
47
|
def <<(data)
|
27
|
-
|
28
|
-
|
48
|
+
if data.bytesize >= @buffer_size
|
49
|
+
flush unless @buf.empty? # <- this is were we can output less than @buffer_size
|
50
|
+
@writable << data
|
51
|
+
else
|
52
|
+
@buf << data
|
53
|
+
flush if @buf.bytesize >= @buffer_size
|
54
|
+
end
|
29
55
|
self
|
30
56
|
end
|
31
57
|
|
32
58
|
# Explicitly flushes the buffer if it contains anything
|
33
59
|
#
|
34
60
|
# @return self
|
35
|
-
def flush
|
36
|
-
|
37
|
-
|
38
|
-
|
61
|
+
def flush
|
62
|
+
unless @buf.empty?
|
63
|
+
@writable << @buf
|
64
|
+
@buf.clear
|
65
|
+
end
|
39
66
|
self
|
40
67
|
end
|
41
68
|
|
42
|
-
#
|
43
|
-
|
44
|
-
# computation by retrieving the CRC as an integer
|
45
|
-
#
|
46
|
-
# @return [Integer] the return value of `writable#to_i`
|
47
|
-
def to_i
|
48
|
-
flush!
|
49
|
-
@writable.to_i
|
50
|
-
end
|
69
|
+
# `flush!` was renamed to `flush` but we preserve this method for backwards compatibility
|
70
|
+
alias_method :flush!, :flush
|
51
71
|
end
|
@@ -31,22 +31,10 @@ class ZipTricks::ZipWriter
|
|
31
31
|
VERSION_MADE_BY = 52
|
32
32
|
VERSION_NEEDED_TO_EXTRACT = 20
|
33
33
|
VERSION_NEEDED_TO_EXTRACT_ZIP64 = 45
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# zipinfo.external_attr = 0644 << 16L # permissions -r-wr--r--.
|
39
|
-
# We snatch the incantations from Rubyzip for this.
|
40
|
-
unix_perms = 0o644
|
41
|
-
file_type_file = 0o10
|
42
|
-
(file_type_file << 12 | (unix_perms & 0o7777)) << 16
|
43
|
-
end
|
44
|
-
EMPTY_DIRECTORY_EXTERNAL_ATTRS = begin
|
45
|
-
# Applies permissions to an empty directory.
|
46
|
-
unix_perms = 0o755
|
47
|
-
file_type_dir = 0o04
|
48
|
-
(file_type_dir << 12 | (unix_perms & 0o7777)) << 16
|
49
|
-
end
|
34
|
+
DEFAULT_FILE_UNIX_PERMISSIONS = 0o644
|
35
|
+
DEFAULT_DIRECTORY_UNIX_PERMISSIONS = 0o755
|
36
|
+
FILE_TYPE_FILE = 0o10
|
37
|
+
FILE_TYPE_DIRECTORY = 0o04
|
50
38
|
MADE_BY_SIGNATURE = begin
|
51
39
|
# A combination of the VERSION_MADE_BY low byte and the OS type high byte
|
52
40
|
os_type = 3 # UNIX
|
@@ -57,14 +45,15 @@ class ZipTricks::ZipWriter
|
|
57
45
|
C_UINT2 = 'v' # Encode a 2-byte unsigned little-endian uint
|
58
46
|
C_UINT8 = 'Q<' # Encode an 8-byte unsigned little-endian uint
|
59
47
|
C_CHAR = 'C' # For bit-encoded strings
|
60
|
-
C_INT4 = '
|
48
|
+
C_INT4 = 'l<' # Encode a 4-byte signed little-endian int
|
61
49
|
|
62
50
|
private_constant :FOUR_BYTE_MAX_UINT,
|
63
51
|
:TWO_BYTE_MAX_UINT,
|
64
52
|
:VERSION_MADE_BY,
|
65
53
|
:VERSION_NEEDED_TO_EXTRACT,
|
66
54
|
:VERSION_NEEDED_TO_EXTRACT_ZIP64,
|
67
|
-
:
|
55
|
+
:FILE_TYPE_FILE,
|
56
|
+
:FILE_TYPE_DIRECTORY,
|
68
57
|
:MADE_BY_SIGNATURE,
|
69
58
|
:C_UINT4,
|
70
59
|
:C_UINT2,
|
@@ -136,6 +125,7 @@ class ZipTricks::ZipWriter
|
|
136
125
|
# @param crc32[Fixnum] The CRC32 checksum of the file
|
137
126
|
# @param mtime[Time] the modification time to be recorded in the ZIP
|
138
127
|
# @param gp_flags[Fixnum] bit-packed general purpose flags
|
128
|
+
# @param unix_permissions[Fixnum?] the permissions for the file, or nil for the default to be used
|
139
129
|
# @return [void]
|
140
130
|
def write_central_directory_file_header(io:,
|
141
131
|
local_file_header_location:,
|
@@ -145,7 +135,9 @@ class ZipTricks::ZipWriter
|
|
145
135
|
uncompressed_size:,
|
146
136
|
mtime:,
|
147
137
|
crc32:,
|
148
|
-
filename
|
138
|
+
filename:,
|
139
|
+
unix_permissions: nil
|
140
|
+
)
|
149
141
|
# At this point if the header begins somewhere beyound 0xFFFFFFFF we _have_ to record the offset
|
150
142
|
# of the local file header as a zip64 extra field, so we give up, give in, you loose, love will always win...
|
151
143
|
add_zip64 = (local_file_header_location > FOUR_BYTE_MAX_UINT) ||
|
@@ -195,16 +187,20 @@ class ZipTricks::ZipWriter
|
|
195
187
|
[TWO_BYTE_MAX_UINT].pack(C_UINT2)
|
196
188
|
else
|
197
189
|
[0].pack(C_UINT2)
|
198
|
-
|
190
|
+
end
|
199
191
|
io << [0].pack(C_UINT2) # internal file attributes 2 bytes
|
200
192
|
|
201
193
|
# Because the add_empty_directory method will create a directory with a trailing "/",
|
202
194
|
# this check can be used to assign proper permissions to the created directory.
|
203
|
-
|
204
|
-
|
195
|
+
# external file attributes 4 bytes
|
196
|
+
external_attrs = if filename.end_with?('/')
|
197
|
+
unix_permissions ||= DEFAULT_DIRECTORY_UNIX_PERMISSIONS
|
198
|
+
generate_external_attrs(unix_permissions, FILE_TYPE_DIRECTORY)
|
205
199
|
else
|
206
|
-
|
200
|
+
unix_permissions ||= DEFAULT_FILE_UNIX_PERMISSIONS
|
201
|
+
generate_external_attrs(unix_permissions, FILE_TYPE_FILE)
|
207
202
|
end
|
203
|
+
io << [external_attrs].pack(C_UINT4)
|
208
204
|
|
209
205
|
io << if add_zip64 # relative offset of local header 4 bytes
|
210
206
|
[FOUR_BYTE_MAX_UINT].pack(C_UINT4)
|
@@ -385,7 +381,7 @@ class ZipTricks::ZipWriter
|
|
385
381
|
0x5455, C_UINT2, # tag for this extra block type ("UT")
|
386
382
|
(1 + 4), C_UINT2, # the size of this block (1 byte used for the Flag + 3 longs used for the timestamp)
|
387
383
|
flags, C_CHAR, # encode a single byte
|
388
|
-
mtime.utc.to_i, C_INT4, # Use a signed
|
384
|
+
mtime.utc.to_i, C_INT4, # Use a signed int, not the unsigned one used by the rest of the ZIP spec.
|
389
385
|
]
|
390
386
|
# The atime and ctime can be omitted if not present
|
391
387
|
pack_array(data_and_packspecs)
|
@@ -434,4 +430,8 @@ class ZipTricks::ZipWriter
|
|
434
430
|
values, packspecs = values_to_packspecs.partition.each_with_index { |_, i| i.even? }
|
435
431
|
values.pack(packspecs.join)
|
436
432
|
end
|
433
|
+
|
434
|
+
def generate_external_attrs(unix_permissions_int, file_type_int)
|
435
|
+
(file_type_int << 12 | (unix_permissions_int & 0o7777)) << 16
|
436
|
+
end
|
437
437
|
end
|
data/zip_tricks.gemspec
CHANGED
@@ -5,13 +5,13 @@ require 'zip_tricks/version'
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'zip_tricks'
|
7
7
|
spec.version = ZipTricks::VERSION
|
8
|
-
spec.authors = ['Julik Tarkhanov', 'Noah Berman', 'Dmitry Tymchuk', 'David Bosveld']
|
8
|
+
spec.authors = ['Julik Tarkhanov', 'Noah Berman', 'Dmitry Tymchuk', 'David Bosveld', 'Felix Bünemann']
|
9
9
|
spec.email = ['me@julik.nl']
|
10
10
|
|
11
11
|
spec.licenses = ['MIT (Hippocratic)']
|
12
12
|
spec.summary = 'Stream out ZIP files from Ruby'
|
13
13
|
spec.description = 'Stream out ZIP files from Ruby'
|
14
|
-
spec.homepage = '
|
14
|
+
spec.homepage = 'https://github.com/wetransfer/zip_tricks'
|
15
15
|
|
16
16
|
# Prevent pushing this gem to RubyGems.org.
|
17
17
|
# To allow pushes either set the 'allowed_push_host'
|
@@ -32,10 +32,8 @@ Gem::Specification.new do |spec|
|
|
32
32
|
|
33
33
|
spec.add_development_dependency 'bundler'
|
34
34
|
spec.add_development_dependency 'rubyzip', '~> 1'
|
35
|
-
spec.add_development_dependency 'terminal-table'
|
36
|
-
spec.add_development_dependency 'range_utils'
|
37
35
|
|
38
|
-
spec.add_development_dependency 'rack', '~> 1.6' # For
|
36
|
+
spec.add_development_dependency 'rack', '~> 1.6' # For tests, where we spin up a server
|
39
37
|
spec.add_development_dependency 'rake', '~> 12.2'
|
40
38
|
spec.add_development_dependency 'rspec', '~> 3'
|
41
39
|
spec.add_development_dependency 'complexity_assert'
|
metadata
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zip_tricks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
8
8
|
- Noah Berman
|
9
9
|
- Dmitry Tymchuk
|
10
10
|
- David Bosveld
|
11
|
-
|
11
|
+
- Felix Bünemann
|
12
|
+
autorequire:
|
12
13
|
bindir: exe
|
13
14
|
cert_chain: []
|
14
|
-
date:
|
15
|
+
date: 2021-06-05 00:00:00.000000000 Z
|
15
16
|
dependencies:
|
16
17
|
- !ruby/object:Gem::Dependency
|
17
18
|
name: bundler
|
@@ -41,34 +42,6 @@ dependencies:
|
|
41
42
|
- - "~>"
|
42
43
|
- !ruby/object:Gem::Version
|
43
44
|
version: '1'
|
44
|
-
- !ruby/object:Gem::Dependency
|
45
|
-
name: terminal-table
|
46
|
-
requirement: !ruby/object:Gem::Requirement
|
47
|
-
requirements:
|
48
|
-
- - ">="
|
49
|
-
- !ruby/object:Gem::Version
|
50
|
-
version: '0'
|
51
|
-
type: :development
|
52
|
-
prerelease: false
|
53
|
-
version_requirements: !ruby/object:Gem::Requirement
|
54
|
-
requirements:
|
55
|
-
- - ">="
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
version: '0'
|
58
|
-
- !ruby/object:Gem::Dependency
|
59
|
-
name: range_utils
|
60
|
-
requirement: !ruby/object:Gem::Requirement
|
61
|
-
requirements:
|
62
|
-
- - ">="
|
63
|
-
- !ruby/object:Gem::Version
|
64
|
-
version: '0'
|
65
|
-
type: :development
|
66
|
-
prerelease: false
|
67
|
-
version_requirements: !ruby/object:Gem::Requirement
|
68
|
-
requirements:
|
69
|
-
- - ">="
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
version: '0'
|
72
45
|
- !ruby/object:Gem::Dependency
|
73
46
|
name: rack
|
74
47
|
requirement: !ruby/object:Gem::Requirement
|
@@ -218,10 +191,10 @@ extra_rdoc_files: []
|
|
218
191
|
files:
|
219
192
|
- ".codeclimate.yml"
|
220
193
|
- ".document"
|
194
|
+
- ".github/workflows/ci.yml"
|
221
195
|
- ".gitignore"
|
222
196
|
- ".rspec"
|
223
197
|
- ".rubocop.yml"
|
224
|
-
- ".travis.yml"
|
225
198
|
- ".yardopts"
|
226
199
|
- CHANGELOG.md
|
227
200
|
- CODE_OF_CONDUCT.md
|
@@ -262,22 +235,13 @@ files:
|
|
262
235
|
- lib/zip_tricks/write_and_tell.rb
|
263
236
|
- lib/zip_tricks/write_buffer.rb
|
264
237
|
- lib/zip_tricks/zip_writer.rb
|
265
|
-
- qa/README_QA.md
|
266
|
-
- qa/generate_test_files.rb
|
267
|
-
- qa/in/VTYL8830.jpg
|
268
|
-
- qa/in/war-and-peace.txt
|
269
|
-
- qa/support.rb
|
270
|
-
- qa/test-report-2016-07-28.txt
|
271
|
-
- qa/test-report-2016-12-12.txt
|
272
|
-
- qa/test-report-2017-04-2.txt
|
273
|
-
- qa/test-report.txt
|
274
238
|
- zip_tricks.gemspec
|
275
|
-
homepage:
|
239
|
+
homepage: https://github.com/wetransfer/zip_tricks
|
276
240
|
licenses:
|
277
241
|
- MIT (Hippocratic)
|
278
242
|
metadata:
|
279
243
|
allowed_push_host: https://rubygems.org
|
280
|
-
post_install_message:
|
244
|
+
post_install_message:
|
281
245
|
rdoc_options: []
|
282
246
|
require_paths:
|
283
247
|
- lib
|
@@ -293,7 +257,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
293
257
|
version: '0'
|
294
258
|
requirements: []
|
295
259
|
rubygems_version: 3.0.3
|
296
|
-
signing_key:
|
260
|
+
signing_key:
|
297
261
|
specification_version: 4
|
298
262
|
summary: Stream out ZIP files from Ruby
|
299
263
|
test_files: []
|
data/.travis.yml
DELETED
data/qa/README_QA.md
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
## Manual testing harness for ZipTricks
|
2
|
-
|
3
|
-
These tests will generate **very large** files that test various edge cases of ZIP generation. The idea is to generate
|
4
|
-
these files and to then try to open them with the unarchiver applications we support. The workflow is as follows:
|
5
|
-
|
6
|
-
|
7
|
-
1. Configure your storage to have `zip_tricks` directory linked into your virtual machines and to be on a fast volume (SSD RAID0 is recommended)
|
8
|
-
2. Run `generate_test_files.rb`. This will take some time and produce a number of large ZIP files.
|
9
|
-
3. Open them with the following ZIP unarchivers:
|
10
|
-
* A recent version of `zipinfo` with the `-tlhvz` flags - to see the information about the file
|
11
|
-
* ArchiveUtility on OSX
|
12
|
-
* The Unarchiver on OSX
|
13
|
-
* Built-in Explorer on Windows 7
|
14
|
-
* 7Zip 9.20 on Windows 7
|
15
|
-
* Any other unarchivers you consider necessary
|
16
|
-
* Write down your observations in `test-report.txt` and, when cutting a release, timestamp a copy of that file.
|
data/qa/generate_test_files.rb
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'support'
|
4
|
-
|
5
|
-
build_test 'Two small stored files' do |zip|
|
6
|
-
zip.add_stored_entry(filename: 'text.txt',
|
7
|
-
size: $war_and_peace.bytesize,
|
8
|
-
crc32: $war_and_peace_crc)
|
9
|
-
zip << $war_and_peace
|
10
|
-
|
11
|
-
zip.add_stored_entry(filename: 'image.jpg',
|
12
|
-
size: $image_file.bytesize,
|
13
|
-
crc32: $image_file_crc)
|
14
|
-
zip << $image_file
|
15
|
-
end
|
16
|
-
|
17
|
-
build_test 'Two small stored files and an empty directory' do |zip|
|
18
|
-
zip.add_stored_entry(filename: 'text.txt',
|
19
|
-
size: $war_and_peace.bytesize,
|
20
|
-
crc32: $war_and_peace_crc)
|
21
|
-
zip << $war_and_peace
|
22
|
-
|
23
|
-
zip.add_stored_entry(filename: 'image.jpg',
|
24
|
-
size: $image_file.bytesize,
|
25
|
-
crc32: $image_file_crc)
|
26
|
-
zip << $image_file
|
27
|
-
|
28
|
-
zip.add_empty_directory(dirname: 'Chekov')
|
29
|
-
end
|
30
|
-
|
31
|
-
build_test 'Filename with diacritics' do |zip|
|
32
|
-
zip.add_stored_entry(filename: 'Kungälv.txt',
|
33
|
-
size: $war_and_peace.bytesize,
|
34
|
-
crc32: $war_and_peace_crc)
|
35
|
-
zip << $war_and_peace
|
36
|
-
end
|
37
|
-
|
38
|
-
build_test 'Purely UTF-8 filename' do |zip|
|
39
|
-
zip.add_stored_entry(filename: 'Война и мир.txt',
|
40
|
-
size: $war_and_peace.bytesize,
|
41
|
-
crc32: $war_and_peace_crc)
|
42
|
-
zip << $war_and_peace
|
43
|
-
end
|
44
|
-
|
45
|
-
# The trick of this test is that each file of the 2, on it's own, does _not_ exceed the
|
46
|
-
# size threshold for Zip64. Together, however, they do.
|
47
|
-
build_test 'Two entries larger than the overall Zip64 offset' do |zip|
|
48
|
-
big = generate_big_entry((0xFFFFFFFF / 2) + 1_024)
|
49
|
-
zip.add_stored_entry(filename: 'repeated-A.txt',
|
50
|
-
size: big.size,
|
51
|
-
crc32: big.crc32)
|
52
|
-
big.write_to(zip)
|
53
|
-
|
54
|
-
zip.add_stored_entry(filename: 'repeated-B.txt',
|
55
|
-
size: big.size,
|
56
|
-
crc32: big.crc32)
|
57
|
-
big.write_to(zip)
|
58
|
-
end
|
59
|
-
|
60
|
-
build_test 'One entry that requires Zip64 and a tiny entry following it' do |zip|
|
61
|
-
big = generate_big_entry(0xFFFFFFFF + 2_048)
|
62
|
-
zip.add_stored_entry(filename: 'large-requires-zip64.bin',
|
63
|
-
size: big.size,
|
64
|
-
crc32: big.crc32)
|
65
|
-
big.write_to(zip)
|
66
|
-
|
67
|
-
zip.add_stored_entry(filename: 'tiny-after.txt',
|
68
|
-
size: $war_and_peace.bytesize,
|
69
|
-
crc32: $war_and_peace_crc)
|
70
|
-
zip << $war_and_peace
|
71
|
-
end
|
72
|
-
|
73
|
-
build_test 'One tiny entry followed by second that requires Zip64' do |zip|
|
74
|
-
zip.add_stored_entry(filename: 'tiny-at-start.txt',
|
75
|
-
size: $war_and_peace.bytesize,
|
76
|
-
crc32: $war_and_peace_crc)
|
77
|
-
zip << $war_and_peace
|
78
|
-
|
79
|
-
big = generate_big_entry(0xFFFFFFFF + 2_048)
|
80
|
-
zip.add_stored_entry(filename: 'large-requires-zip64.bin',
|
81
|
-
size: big.size,
|
82
|
-
crc32: big.crc32)
|
83
|
-
big.write_to(zip)
|
84
|
-
end
|
85
|
-
|
86
|
-
build_test 'Two entries both requiring Zip64' do |zip|
|
87
|
-
big = generate_big_entry(0xFFFFFFFF + 2_048)
|
88
|
-
zip.add_stored_entry(filename: 'huge-file-1.bin',
|
89
|
-
size: big.size,
|
90
|
-
crc32: big.crc32)
|
91
|
-
big.write_to(zip)
|
92
|
-
|
93
|
-
zip.add_stored_entry(filename: 'huge-file-2.bin',
|
94
|
-
size: big.size,
|
95
|
-
crc32: big.crc32)
|
96
|
-
big.write_to(zip)
|
97
|
-
end
|
98
|
-
|
99
|
-
build_test 'Two stored entries using data descriptors' do |zip|
|
100
|
-
zip.write_stored_file('stored.1.bin') do |sink|
|
101
|
-
sink << Random.new.bytes(1_024 * 1_024 * 4)
|
102
|
-
end
|
103
|
-
zip.write_stored_file('stored.2.bin') do |sink|
|
104
|
-
sink << Random.new.bytes(1_024 * 1_024 * 3)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
build_test 'One entry deflated using data descriptors' do |zip|
|
109
|
-
big = generate_big_entry(0xFFFFFFFF / 64)
|
110
|
-
zip.write_deflated_file('war-and-peace-repeated-compressed.txt') do |sink|
|
111
|
-
big.write_to(sink)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
build_test 'Two entries larger than the overall Zip64 offset using data descriptors' do |zip|
|
116
|
-
big = generate_big_entry((0xFFFFFFFF / 2) + 1_024)
|
117
|
-
|
118
|
-
zip.write_stored_file('repeated-A.txt') { |sink| big.write_to(sink) }
|
119
|
-
zip.write_stored_file('repeated-B.txt') { |sink| big.write_to(sink) }
|
120
|
-
end
|
121
|
-
|
122
|
-
build_test 'One stored entry larger than Zip64 threshold using data descriptors' do |zip|
|
123
|
-
big = generate_big_entry(0xFFFFFFFF + 64_000)
|
124
|
-
|
125
|
-
zip.write_stored_file('repeated-A.txt') { |sink| big.write_to(sink) }
|
126
|
-
end
|