zip_tricks 4.2.3 → 4.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,43 +0,0 @@
1
- require_relative '../spec_helper'
2
-
3
- describe ZipTricks::WriteAndTell do
4
- it 'maintains the count of bytes written' do
5
- adapter = described_class.new('')
6
- expect(adapter.tell).to be_zero
7
-
8
- adapter << 'hello'
9
- adapter << ''
10
- adapter << '!'
11
- expect(adapter.tell).to eq(6)
12
- end
13
-
14
- it 'is able to write frozen String objects in different encodings, converting them to binary' do
15
- strs = [
16
- [12, 123, 0, 3].pack("C*"),
17
- "текста кусок",
18
- "текста замороженный кусок".freeze,
19
- [12, 123, 0, 3].pack("C*"),
20
- ]
21
-
22
- buf = 'превед'.force_encoding(Encoding::BINARY)
23
- writer = described_class.new(buf)
24
- strs.each {|s| writer << s }
25
- expect(writer.tell).to eq(79)
26
- expect(buf.bytesize).to eq(91) # It already contained some bytes
27
- end
28
-
29
- it 'advances the internal pointer using advance_position_by' do
30
- str = ''
31
-
32
- adapter = described_class.new(str)
33
- expect(adapter.tell).to be_zero
34
-
35
- adapter << 'hello'
36
- adapter << ''
37
- adapter << '!'
38
- expect(adapter.tell).to eq(6)
39
- adapter.advance_position_by(128981)
40
- expect(adapter.tell).to eq(6 + 128981)
41
- expect(str).to eq('hello!')
42
- end
43
- end
@@ -1,419 +0,0 @@
1
- require_relative '../spec_helper'
2
- require_relative '../../testing/support'
3
-
4
- describe ZipTricks::ZipWriter do
5
- class ByteReader < Struct.new(:io)
6
- def initialize(io)
7
- super(io).tap { io.rewind }
8
- end
9
-
10
- def read_2b
11
- read_n(2).unpack('v').first
12
- end
13
-
14
- def read_2c
15
- read_n(2).unpack('CC').first
16
- end
17
-
18
- def read_4b
19
- read_n(4).unpack('V').first
20
- end
21
-
22
- def read_8b
23
- read_n(8).unpack('Q<').first
24
- end
25
-
26
- def read_n(n)
27
- io.read(n).tap {|r|
28
- raise "Expected to read #{n} bytes, but read() returned nil" if r.nil?
29
- raise "Expected to read #{n} bytes, but read #{r.bytesize} instead" if r.bytesize != n
30
- }
31
- end
32
-
33
- # For conveniently going to a specific signature
34
- def seek_to_start_of_signature(signature)
35
- io.rewind
36
- signature_encoded = [signature].pack('V')
37
- idx = io.read.index(signature_encoded)
38
- raise "Could not find the signature #{signature} in the buffer" unless idx
39
- io.seek(idx, IO::SEEK_SET)
40
- end
41
- end
42
-
43
- describe '#write_local_file_header' do
44
- it 'writes the local file header for an entry that does not require Zip64' do
45
- buf = StringIO.new
46
- mtime = Time.utc(2016, 7, 17, 13, 48)
47
-
48
- subject = ZipTricks::ZipWriter.new
49
- subject.write_local_file_header(io: buf, gp_flags: 12, crc32: 456, compressed_size: 768, uncompressed_size: 901, mtime: mtime, filename: 'foo.bin', storage_mode: 8)
50
-
51
- br = ByteReader.new(buf)
52
- expect(br.read_4b).to eq(0x04034b50) # Signature
53
- expect(br.read_2b).to eq(20) # Version needed to extract
54
- expect(br.read_2b).to eq(12) # gp flags
55
- expect(br.read_2b).to eq(8) # storage mode
56
- expect(br.read_2b).to eq(28160) # DOS time
57
- expect(br.read_2b).to eq(18673) # DOS date
58
- expect(br.read_4b).to eq(456) # CRC32
59
- expect(br.read_4b).to eq(768) # compressed size
60
- expect(br.read_4b).to eq(901) # uncompressed size
61
- expect(br.read_2b).to eq(7) # filename size
62
- expect(br.read_2b).to eq(0) # extra fields size
63
- expect(br.read_n(7)).to eq('foo.bin') # extra fields size
64
- expect(buf).to be_eof
65
- end
66
-
67
- it 'writes the local file header for an entry that does require Zip64 based on uncompressed size (with the Zip64 extra)' do
68
- buf = StringIO.new
69
- mtime = Time.utc(2016, 7, 17, 13, 48)
70
-
71
- subject = ZipTricks::ZipWriter.new
72
- subject.write_local_file_header(io: buf, gp_flags: 12, crc32: 456, compressed_size: 768, uncompressed_size: 0xFFFFFFFF+1, mtime: mtime, filename: 'foo.bin', storage_mode: 8)
73
-
74
- br = ByteReader.new(buf)
75
- expect(br.read_4b).to eq(0x04034b50) # Signature
76
- expect(br.read_2b).to eq(45) # Version needed to extract
77
- expect(br.read_2b).to eq(12) # gp flags
78
- expect(br.read_2b).to eq(8) # storage mode
79
- expect(br.read_2b).to eq(28160) # DOS time
80
- expect(br.read_2b).to eq(18673) # DOS date
81
- expect(br.read_4b).to eq(456) # CRC32
82
- expect(br.read_4b).to eq(0xFFFFFFFF) # compressed size
83
- expect(br.read_4b).to eq(0xFFFFFFFF) # uncompressed size
84
- expect(br.read_2b).to eq(7) # filename size
85
- expect(br.read_2b).to eq(20) # extra fields size
86
- expect(br.read_n(7)).to eq('foo.bin') # extra fields size
87
-
88
- expect(buf).not_to be_eof
89
-
90
- expect(br.read_2b).to eq(1) # Zip64 extra tag
91
- expect(br.read_2b).to eq(16) # Size of the Zip64 extra payload
92
- expect(br.read_8b).to eq(0xFFFFFFFF+1) # uncompressed size
93
- expect(br.read_8b).to eq(768) # compressed size
94
- end
95
-
96
- it 'writes the local file header for an entry that does require Zip64 based on compressed size (with the Zip64 extra)' do
97
- buf = StringIO.new
98
- mtime = Time.utc(2016, 7, 17, 13, 48)
99
-
100
- subject = ZipTricks::ZipWriter.new
101
- subject.write_local_file_header(io: buf, gp_flags: 12, crc32: 456, compressed_size: 0xFFFFFFFF+1, uncompressed_size: 768, mtime: mtime, filename: 'foo.bin', storage_mode: 8)
102
-
103
- br = ByteReader.new(buf)
104
- expect(br.read_4b).to eq(0x04034b50) # Signature
105
- expect(br.read_2b).to eq(45) # Version needed to extract
106
- expect(br.read_2b).to eq(12) # gp flags
107
- expect(br.read_2b).to eq(8) # storage mode
108
- expect(br.read_2b).to eq(28160) # DOS time
109
- expect(br.read_2b).to eq(18673) # DOS date
110
- expect(br.read_4b).to eq(456) # CRC32
111
- expect(br.read_4b).to eq(0xFFFFFFFF) # compressed size
112
- expect(br.read_4b).to eq(0xFFFFFFFF) # uncompressed size
113
- expect(br.read_2b).to eq(7) # filename size
114
- expect(br.read_2b).to eq(20) # extra fields size
115
- expect(br.read_n(7)).to eq('foo.bin') # extra fields size
116
-
117
- expect(buf).not_to be_eof
118
-
119
- expect(br.read_2b).to eq(1) # Zip64 extra tag
120
- expect(br.read_2b).to eq(16) # Size of the Zip64 extra payload
121
- expect(br.read_8b).to eq(768) # uncompressed size
122
- expect(br.read_8b).to eq(0xFFFFFFFF+1) # compressed size
123
- end
124
- end
125
-
126
- describe '#write_data_descriptor' do
127
- it 'writes 4-byte sizes into the data descriptor for standard file sizes' do
128
- buf = StringIO.new
129
-
130
- subject.write_data_descriptor(io: buf, crc32: 123, compressed_size: 89821, uncompressed_size: 990912)
131
-
132
- br = ByteReader.new(buf)
133
- expect(br.read_4b).to eq(0x08074b50) # Signature
134
- expect(br.read_4b).to eq(123) # CRC32
135
- expect(br.read_4b).to eq(89821) # compressed size
136
- expect(br.read_4b).to eq(990912) # uncompressed size
137
- expect(buf).to be_eof
138
- end
139
-
140
- it 'writes 8-byte sizes into the data descriptor for Zip64 compressed file size' do
141
- buf = StringIO.new
142
-
143
- subject.write_data_descriptor(io: buf, crc32: 123, compressed_size: 0xFFFFFFFF + 1, uncompressed_size: 990912)
144
-
145
- br = ByteReader.new(buf)
146
- expect(br.read_4b).to eq(0x08074b50) # Signature
147
- expect(br.read_4b).to eq(123) # CRC32
148
- expect(br.read_8b).to eq(0xFFFFFFFF + 1) # compressed size
149
- expect(br.read_8b).to eq(990912) # uncompressed size
150
- expect(buf).to be_eof
151
- end
152
-
153
- it 'writes 8-byte sizes into the data descriptor for Zip64 uncompressed file size' do
154
- buf = StringIO.new
155
-
156
- subject.write_data_descriptor(io: buf, crc32: 123, compressed_size: 123, uncompressed_size: 0xFFFFFFFF + 1)
157
-
158
- br = ByteReader.new(buf)
159
- expect(br.read_4b).to eq(0x08074b50) # Signature
160
- expect(br.read_4b).to eq(123) # CRC32
161
- expect(br.read_8b).to eq(123) # compressed size
162
- expect(br.read_8b).to eq(0xFFFFFFFF + 1) # uncompressed size
163
- expect(buf).to be_eof
164
- end
165
- end
166
-
167
- describe '#write_central_directory_file_header' do
168
- it 'writes the file header for a small-ish entry' do
169
- buf = StringIO.new
170
-
171
- subject.write_central_directory_file_header(io: buf, local_file_header_location: 898921,
172
- gp_flags: 555, storage_mode: 23,
173
- compressed_size: 901, uncompressed_size: 909102,
174
- mtime: Time.utc(2016, 2, 2, 14, 00), crc32: 89765,
175
- filename: 'a-file.txt', external_attrs: 123)
176
-
177
- br = ByteReader.new(buf)
178
- expect(br.read_4b).to eq(0x02014b50) # Central directory entry sig
179
- expect(br.read_2b).to eq(820) # version made by
180
- expect(br.read_2b).to eq(20) # version need to extract
181
- expect(br.read_2b).to eq(555) # general purpose bit flag (explicitly set to bogus value to ensure we pass it through)
182
- expect(br.read_2b).to eq(23) # compression method (explicitly set to bogus value)
183
- expect(br.read_2b).to eq(28672) # last mod file time
184
- expect(br.read_2b).to eq(18498) # last mod file date
185
- expect(br.read_4b).to eq(89765) # crc32
186
- expect(br.read_4b).to eq(901) # compressed size
187
- expect(br.read_4b).to eq(909102) # uncompressed size
188
- expect(br.read_2b).to eq(10) # filename length
189
- expect(br.read_2b).to eq(0) # extra field length
190
- expect(br.read_2b).to eq(0) # file comment
191
- expect(br.read_2b).to eq(0) # disk number, must be blanked to the maximum value because of The Unarchiver bug
192
- expect(br.read_2b).to eq(0) # internal file attributes
193
- expect(br.read_4b).to eq(2175008768) # external file attributes
194
- expect(br.read_4b).to eq(898921) # relative offset of local header
195
- expect(br.read_n(10)).to eq('a-file.txt') # the filename
196
- end
197
-
198
- it 'writes the file header for an entry that requires Zip64 extra because of the uncompressed size' do
199
- buf = StringIO.new
200
-
201
- subject.write_central_directory_file_header(io: buf, local_file_header_location: 898921,
202
- gp_flags: 555, storage_mode: 23,
203
- compressed_size: 901, uncompressed_size: 0xFFFFFFFFF + 3,
204
- mtime: Time.utc(2016, 2, 2, 14, 00), crc32: 89765,
205
- filename: 'a-file.txt', external_attrs: 123)
206
-
207
- br = ByteReader.new(buf)
208
- expect(br.read_4b).to eq(0x02014b50) # Central directory entry sig
209
- expect(br.read_2b).to eq(820) # version made by
210
- expect(br.read_2b).to eq(45) # version need to extract
211
- expect(br.read_2b).to eq(555) # general purpose bit flag (explicitly set to bogus value to ensure we pass it through)
212
- expect(br.read_2b).to eq(23) # compression method (explicitly set to bogus value)
213
- expect(br.read_2b).to eq(28672) # last mod file time
214
- expect(br.read_2b).to eq(18498) # last mod file date
215
- expect(br.read_4b).to eq(89765) # crc32
216
- expect(br.read_4b).to eq(0xFFFFFFFF) # compressed size
217
- expect(br.read_4b).to eq(0xFFFFFFFF) # uncompressed size
218
- expect(br.read_2b).to eq(10) # filename length
219
- expect(br.read_2b).to eq(32) # extra field length
220
- expect(br.read_2b).to eq(0) # file comment
221
- expect(br.read_2b).to eq(0xFFFF) # disk number, must be blanked to the maximum value because of The Unarchiver bug
222
- expect(br.read_2b).to eq(0) # internal file attributes
223
- expect(br.read_4b).to eq(2175008768) # external file attributes
224
- expect(br.read_4b).to eq(0xFFFFFFFF) # relative offset of local header
225
- expect(br.read_n(10)).to eq('a-file.txt') # the filename
226
-
227
- expect(buf).not_to be_eof
228
- expect(br.read_2b).to eq(1) # Zip64 extra tag
229
- expect(br.read_2b).to eq(28) # Size of the Zip64 extra payload
230
- expect(br.read_8b).to eq(0xFFFFFFFFF + 3) # uncompressed size
231
- expect(br.read_8b).to eq(901) # compressed size
232
- expect(br.read_8b).to eq(898921) # local file header location
233
- end
234
-
235
- it 'writes the file header for an entry that requires Zip64 extra because of the compressed size' do
236
- buf = StringIO.new
237
-
238
- subject.write_central_directory_file_header(io: buf, local_file_header_location: 898921,
239
- gp_flags: 555, storage_mode: 23,
240
- compressed_size: 0xFFFFFFFFF + 3, uncompressed_size: 901, # the worst compression scheme in the universe
241
- mtime: Time.utc(2016, 2, 2, 14, 00), crc32: 89765,
242
- filename: 'a-file.txt', external_attrs: 123)
243
-
244
- br = ByteReader.new(buf)
245
- expect(br.read_4b).to eq(0x02014b50) # Central directory entry sig
246
- expect(br.read_2b).to eq(820) # version made by
247
- expect(br.read_2b).to eq(45) # version need to extract
248
- expect(br.read_2b).to eq(555) # general purpose bit flag (explicitly set to bogus value to ensure we pass it through)
249
- expect(br.read_2b).to eq(23) # compression method (explicitly set to bogus value)
250
- expect(br.read_2b).to eq(28672) # last mod file time
251
- expect(br.read_2b).to eq(18498) # last mod file date
252
- expect(br.read_4b).to eq(89765) # crc32
253
- expect(br.read_4b).to eq(0xFFFFFFFF) # compressed size
254
- expect(br.read_4b).to eq(0xFFFFFFFF) # uncompressed size
255
- expect(br.read_2b).to eq(10) # filename length
256
- expect(br.read_2b).to eq(32) # extra field length
257
- expect(br.read_2b).to eq(0) # file comment
258
- expect(br.read_2b).to eq(0xFFFF) # disk number, must be blanked to the maximum value because of The Unarchiver bug
259
- expect(br.read_2b).to eq(0) # internal file attributes
260
- expect(br.read_4b).to eq(2175008768) # external file attributes
261
- expect(br.read_4b).to eq(0xFFFFFFFF) # relative offset of local header
262
- expect(br.read_n(10)).to eq('a-file.txt') # the filename
263
-
264
- expect(buf).not_to be_eof
265
- expect(br.read_2b).to eq(1) # Zip64 extra tag
266
- expect(br.read_2b).to eq(28) # Size of the Zip64 extra payload
267
- expect(br.read_8b).to eq(901) # uncompressed size
268
- expect(br.read_8b).to eq(0xFFFFFFFFF + 3) # compressed size
269
- expect(br.read_8b).to eq(898921) # local file header location
270
- end
271
-
272
- it 'writes the file header for an entry that requires Zip64 extra because of the local file header offset being beyound 4GB' do
273
- buf = StringIO.new
274
-
275
- subject.write_central_directory_file_header(io: buf, local_file_header_location: 0xFFFFFFFFF + 1,
276
- gp_flags: 555, storage_mode: 23,
277
- compressed_size: 8981, uncompressed_size: 819891, # the worst compression scheme in the universe
278
- mtime: Time.utc(2016, 2, 2, 14, 00), crc32: 89765,
279
- filename: 'a-file.txt', external_attrs: 123)
280
-
281
- br = ByteReader.new(buf)
282
- expect(br.read_4b).to eq(0x02014b50) # Central directory entry sig
283
- expect(br.read_2b).to eq(820) # version made by
284
- expect(br.read_2b).to eq(45) # version need to extract
285
- expect(br.read_2b).to eq(555) # general purpose bit flag (explicitly set to bogus value to ensure we pass it through)
286
- expect(br.read_2b).to eq(23) # compression method (explicitly set to bogus value)
287
- expect(br.read_2b).to eq(28672) # last mod file time
288
- expect(br.read_2b).to eq(18498) # last mod file date
289
- expect(br.read_4b).to eq(89765) # crc32
290
- expect(br.read_4b).to eq(0xFFFFFFFF) # compressed size
291
- expect(br.read_4b).to eq(0xFFFFFFFF) # uncompressed size
292
- expect(br.read_2b).to eq(10) # filename length
293
- expect(br.read_2b).to eq(32) # extra field length
294
- expect(br.read_2b).to eq(0) # file comment
295
- expect(br.read_2b).to eq(0xFFFF) # disk number, must be blanked to the maximum value because of The Unarchiver bug
296
- expect(br.read_2b).to eq(0) # internal file attributes
297
- expect(br.read_4b).to eq(2175008768) # external file attributes
298
- expect(br.read_4b).to eq(0xFFFFFFFF) # relative offset of local header
299
- expect(br.read_n(10)).to eq('a-file.txt') # the filename
300
-
301
- expect(buf).not_to be_eof
302
- expect(br.read_2b).to eq(1) # Zip64 extra tag
303
- expect(br.read_2b).to eq(28) # Size of the Zip64 extra payload
304
- expect(br.read_8b).to eq(819891) # uncompressed size
305
- expect(br.read_8b).to eq(8981) # compressed size
306
- expect(br.read_8b).to eq(0xFFFFFFFFF + 1) # local file header location
307
- end
308
- end
309
-
310
- describe '#write_end_of_central_directory' do
311
- it 'writes out the EOCD with all markers for a small ZIP file with just a few entries' do
312
- buf = StringIO.new
313
-
314
- num_files = rand(8..190)
315
- subject.write_end_of_central_directory(io: buf, start_of_central_directory_location: 9091211,
316
- central_directory_size: 9091, num_files_in_archive: num_files)
317
-
318
- br = ByteReader.new(buf)
319
- expect(br.read_4b).to eq(0x06054b50) # EOCD signature
320
- expect(br.read_2b).to eq(0) # number of this disk
321
- expect(br.read_2b).to eq(0) # number of the disk with the EOCD record
322
- expect(br.read_2b).to eq(num_files) # number of files on this disk
323
- expect(br.read_2b).to eq(num_files) # number of files in central directory total (for all disks)
324
- expect(br.read_4b).to eq(9091) # size of the central directory (cdir records for all files)
325
- expect(br.read_4b).to eq(9091211) # start of central directory offset from the beginning of file/disk
326
-
327
- comment_length = br.read_2b
328
- expect(comment_length).not_to be_zero
329
-
330
- expect(br.read_n(comment_length)).to match(/ZipTricks/)
331
- end
332
-
333
- it 'writes out the custom comment' do
334
- buf = ''
335
- comment = 'Ohai mate'
336
- subject.write_end_of_central_directory(io: buf, start_of_central_directory_location: 9091211,
337
- central_directory_size: 9091, num_files_in_archive: 4, comment: comment)
338
-
339
- size_and_comment = buf[((comment.bytesize + 2) * -1)..-1]
340
- comment_size = size_and_comment.unpack('v')[0]
341
- expect(comment_size).to eq(comment.bytesize)
342
- end
343
-
344
- it 'writes out the Zip64 EOCD as well if the central directory is located beyound 4GB in the archive' do
345
- buf = StringIO.new
346
-
347
- num_files = rand(8..190)
348
- subject.write_end_of_central_directory(io: buf, start_of_central_directory_location: 0xFFFFFFFF + 3,
349
- central_directory_size: 9091, num_files_in_archive: num_files)
350
-
351
- br = ByteReader.new(buf)
352
-
353
- expect(br.read_4b).to eq(0x06064b50) # Zip64 EOCD signature
354
- expect(br.read_8b).to eq(44) # Zip64 EOCD record size
355
- expect(br.read_2b).to eq(820) # Version made by
356
- expect(br.read_2b).to eq(45) # Version needed to extract
357
- expect(br.read_4b).to eq(0) # Number of this disk
358
- expect(br.read_4b).to eq(0) # Number of the disk with the Zip64 EOCD record
359
- expect(br.read_8b).to eq(num_files) # Number of entries in the central directory of this disk
360
- expect(br.read_8b).to eq(num_files) # Number of entries in the central directories of all disks
361
- expect(br.read_8b).to eq(9091) # Central directory size
362
- expect(br.read_8b).to eq(0xFFFFFFFF + 3) # Start of central directory location
363
-
364
- expect(br.read_4b).to eq(0x07064b50) # Zip64 EOCD locator signature
365
- expect(br.read_4b).to eq(0) # Number of the disk with the EOCD locator signature
366
- expect(br.read_8b).to eq((0xFFFFFFFF + 3) + 9091) # Where the Zip64 EOCD record starts
367
- expect(br.read_4b).to eq(1) # Total number of disks
368
-
369
- # Then the usual EOCD record
370
- expect(br.read_4b).to eq(0x06054b50) # EOCD signature
371
- expect(br.read_2b).to eq(0) # number of this disk
372
- expect(br.read_2b).to eq(0) # number of the disk with the EOCD record
373
- expect(br.read_2b).to eq(0xFFFF) # number of files on this disk
374
- expect(br.read_2b).to eq(0xFFFF) # number of files in central directory total (for all disks)
375
- expect(br.read_4b).to eq(0xFFFFFFFF) # size of the central directory (cdir records for all files)
376
- expect(br.read_4b).to eq(0xFFFFFFFF) # start of central directory offset from the beginning of file/disk
377
-
378
- comment_length = br.read_2b
379
- expect(comment_length).not_to be_zero
380
- expect(br.read_n(comment_length)).to match(/ZipTricks/)
381
- end
382
-
383
- it 'writes out the Zip64 EOCD if the archive has more than 0xFFFF files' do
384
- buf = StringIO.new
385
-
386
- subject.write_end_of_central_directory(io: buf, start_of_central_directory_location: 123,
387
- central_directory_size: 9091, num_files_in_archive: 0xFFFF + 1)
388
-
389
- br = ByteReader.new(buf)
390
-
391
- expect(br.read_4b).to eq(0x06064b50) # Zip64 EOCD signature
392
- br.read_8b
393
- br.read_2b
394
- br.read_2b
395
- br.read_4b
396
- br.read_4b
397
- expect(br.read_8b).to eq(0xFFFF + 1) # Number of entries in the central directory of this disk
398
- expect(br.read_8b).to eq(0xFFFF + 1) # Number of entries in the central directories of all disks
399
- end
400
-
401
- it 'writes out the Zip64 EOCD if the central directory size exceeds 0xFFFFFFFF' do
402
- buf = StringIO.new
403
-
404
- subject.write_end_of_central_directory(io: buf, start_of_central_directory_location: 123,
405
- central_directory_size: 0xFFFFFFFF + 2, num_files_in_archive: 5)
406
-
407
- br = ByteReader.new(buf)
408
-
409
- expect(br.read_4b).to eq(0x06064b50) # Zip64 EOCD signature
410
- br.read_8b
411
- br.read_2b
412
- br.read_2b
413
- br.read_4b
414
- br.read_4b
415
- expect(br.read_8b).to eq(5) # Number of entries in the central directory of this disk
416
- expect(br.read_8b).to eq(5) # Number of entries in the central directories of all disks
417
- end
418
- end
419
- end