zip_tricks 5.2.0 → 5.6.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.
@@ -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
- @crc = ZipTricks::WriteBuffer.new(ZipTricks::StreamCRC32.new, CRC32_BUFFER_SIZE)
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
- {crc32: @crc.to_i, compressed_size: @io.tell, uncompressed_size: @io.tell}
34
+ @crc.flush
35
+ {crc32: @crc_compute.to_i, compressed_size: @io.tell, uncompressed_size: @io.tell}
35
36
  end
36
37
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ZipTricks
4
- VERSION = '5.2.0'
4
+ VERSION = '5.6.0'
5
5
  end
@@ -10,9 +10,8 @@ class ZipTricks::WriteAndTell
10
10
 
11
11
  def <<(bytes)
12
12
  return self if bytes.nil?
13
- binary_bytes = binary(bytes)
14
- @io << binary_bytes
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 string as argument
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
- @buf = StringIO.new
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
- @buf << data
28
- flush! if @buf.size > @buffer_size
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
- @writable << @buf.string if @buf.size > 0
37
- @buf.truncate(0)
38
- @buf.rewind
61
+ def flush
62
+ unless @buf.empty?
63
+ @writable << @buf
64
+ @buf.clear
65
+ end
39
66
  self
40
67
  end
41
68
 
42
- # Flushes the buffer and returns the result of `#to_i` of the contained `writable`.
43
- # Primarily facilitates working with StreamCRC32 objects where you finish the
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
- DEFAULT_EXTERNAL_ATTRS = begin
35
- # These need to be set so that the unarchived files do not become executable on UNIX, for
36
- # security purposes. Strictly speaking we would want to make this user-customizable,
37
- # but for now just putting in sane defaults will do. For example, Trac with zipinfo does this:
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 = 'N' # Encode a 4-byte signed little-endian int
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
- :DEFAULT_EXTERNAL_ATTRS,
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
- end
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
- io << if filename.end_with?('/')
204
- [EMPTY_DIRECTORY_EXTERNAL_ATTRS].pack(C_UINT4)
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
- [DEFAULT_EXTERNAL_ATTRS].pack(C_UINT4) # external file attributes 4 bytes
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 long, not the unsigned one used by the rest of the ZIP spec.
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 = 'http://github.com/wetransfer/zip_tricks'
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 Jeweler
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.2.0
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
- autorequire:
11
+ - Felix Bünemann
12
+ autorequire:
12
13
  bindir: exe
13
14
  cert_chain: []
14
- date: 2020-05-19 00:00:00.000000000 Z
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: http://github.com/wetransfer/zip_tricks
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
@@ -1,11 +0,0 @@
1
- rvm:
2
- - 2.1.0
3
- - 2.6.5
4
- - jruby-9.0
5
- sudo: false
6
- cache: bundler
7
- matrix:
8
- allow_failures:
9
- - rvm: jruby-9.0
10
- script:
11
- - bundle exec rake
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.
@@ -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