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.
@@ -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