rubyzip 1.2.2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +64 -23
  3. data/Rakefile +3 -0
  4. data/lib/zip.rb +6 -3
  5. data/lib/zip/central_directory.rb +9 -5
  6. data/lib/zip/constants.rb +52 -0
  7. data/lib/zip/crypto/decrypted_io.rb +40 -0
  8. data/lib/zip/crypto/traditional_encryption.rb +9 -9
  9. data/lib/zip/decompressor.rb +19 -1
  10. data/lib/zip/dos_time.rb +12 -7
  11. data/lib/zip/entry.rb +69 -37
  12. data/lib/zip/entry_set.rb +2 -0
  13. data/lib/zip/errors.rb +2 -0
  14. data/lib/zip/extra_field.rb +11 -9
  15. data/lib/zip/extra_field/generic.rb +10 -9
  16. data/lib/zip/extra_field/ntfs.rb +4 -0
  17. data/lib/zip/extra_field/old_unix.rb +3 -1
  18. data/lib/zip/extra_field/universal_time.rb +42 -12
  19. data/lib/zip/extra_field/unix.rb +3 -1
  20. data/lib/zip/extra_field/zip64.rb +4 -2
  21. data/lib/zip/file.rb +115 -70
  22. data/lib/zip/filesystem.rb +193 -177
  23. data/lib/zip/inflater.rb +24 -36
  24. data/lib/zip/input_stream.rb +33 -26
  25. data/lib/zip/ioextras.rb +1 -1
  26. data/lib/zip/ioextras/abstract_input_stream.rb +19 -8
  27. data/lib/zip/ioextras/abstract_output_stream.rb +1 -1
  28. data/lib/zip/null_decompressor.rb +1 -9
  29. data/lib/zip/output_stream.rb +14 -5
  30. data/lib/zip/pass_thru_compressor.rb +2 -2
  31. data/lib/zip/pass_thru_decompressor.rb +13 -22
  32. data/lib/zip/streamable_directory.rb +3 -3
  33. data/lib/zip/streamable_stream.rb +6 -10
  34. data/lib/zip/version.rb +1 -1
  35. data/samples/example.rb +2 -2
  36. data/samples/example_filesystem.rb +1 -1
  37. data/samples/gtk_ruby_zip.rb +19 -19
  38. data/samples/qtzip.rb +6 -6
  39. data/samples/write_simple.rb +2 -4
  40. data/samples/zipfind.rb +23 -22
  41. metadata +32 -167
  42. data/test/basic_zip_file_test.rb +0 -60
  43. data/test/case_sensitivity_test.rb +0 -69
  44. data/test/central_directory_entry_test.rb +0 -69
  45. data/test/central_directory_test.rb +0 -100
  46. data/test/crypto/null_encryption_test.rb +0 -57
  47. data/test/crypto/traditional_encryption_test.rb +0 -80
  48. data/test/data/WarnInvalidDate.zip +0 -0
  49. data/test/data/file1.txt +0 -46
  50. data/test/data/file1.txt.deflatedData +0 -0
  51. data/test/data/file2.txt +0 -1504
  52. data/test/data/globTest.zip +0 -0
  53. data/test/data/globTest/foo.txt +0 -0
  54. data/test/data/globTest/foo/bar/baz/foo.txt +0 -0
  55. data/test/data/globTest/food.txt +0 -0
  56. data/test/data/gpbit3stored.zip +0 -0
  57. data/test/data/mimetype +0 -1
  58. data/test/data/notzippedruby.rb +0 -7
  59. data/test/data/ntfs.zip +0 -0
  60. data/test/data/oddExtraField.zip +0 -0
  61. data/test/data/path_traversal/Makefile +0 -10
  62. data/test/data/path_traversal/jwilk/README.md +0 -5
  63. data/test/data/path_traversal/jwilk/absolute1.zip +0 -0
  64. data/test/data/path_traversal/jwilk/absolute2.zip +0 -0
  65. data/test/data/path_traversal/jwilk/dirsymlink.zip +0 -0
  66. data/test/data/path_traversal/jwilk/dirsymlink2a.zip +0 -0
  67. data/test/data/path_traversal/jwilk/dirsymlink2b.zip +0 -0
  68. data/test/data/path_traversal/jwilk/relative0.zip +0 -0
  69. data/test/data/path_traversal/jwilk/relative2.zip +0 -0
  70. data/test/data/path_traversal/jwilk/symlink.zip +0 -0
  71. data/test/data/path_traversal/relative1.zip +0 -0
  72. data/test/data/path_traversal/tuzovakaoff/README.md +0 -3
  73. data/test/data/path_traversal/tuzovakaoff/absolutepath.zip +0 -0
  74. data/test/data/path_traversal/tuzovakaoff/symlink.zip +0 -0
  75. data/test/data/rubycode.zip +0 -0
  76. data/test/data/rubycode2.zip +0 -0
  77. data/test/data/test.xls +0 -0
  78. data/test/data/testDirectory.bin +0 -0
  79. data/test/data/zip64-sample.zip +0 -0
  80. data/test/data/zipWithDirs.zip +0 -0
  81. data/test/data/zipWithEncryption.zip +0 -0
  82. data/test/deflater_test.rb +0 -65
  83. data/test/encryption_test.rb +0 -42
  84. data/test/entry_set_test.rb +0 -163
  85. data/test/entry_test.rb +0 -154
  86. data/test/errors_test.rb +0 -35
  87. data/test/extra_field_test.rb +0 -76
  88. data/test/file_extract_directory_test.rb +0 -54
  89. data/test/file_extract_test.rb +0 -83
  90. data/test/file_permissions_test.rb +0 -65
  91. data/test/file_split_test.rb +0 -57
  92. data/test/file_test.rb +0 -601
  93. data/test/filesystem/dir_iterator_test.rb +0 -58
  94. data/test/filesystem/directory_test.rb +0 -139
  95. data/test/filesystem/file_mutating_test.rb +0 -87
  96. data/test/filesystem/file_nonmutating_test.rb +0 -508
  97. data/test/filesystem/file_stat_test.rb +0 -64
  98. data/test/gentestfiles.rb +0 -126
  99. data/test/inflater_test.rb +0 -14
  100. data/test/input_stream_test.rb +0 -182
  101. data/test/ioextras/abstract_input_stream_test.rb +0 -102
  102. data/test/ioextras/abstract_output_stream_test.rb +0 -106
  103. data/test/ioextras/fake_io_test.rb +0 -18
  104. data/test/local_entry_test.rb +0 -154
  105. data/test/output_stream_test.rb +0 -128
  106. data/test/pass_thru_compressor_test.rb +0 -30
  107. data/test/pass_thru_decompressor_test.rb +0 -14
  108. data/test/path_traversal_test.rb +0 -134
  109. data/test/samples/example_recursive_test.rb +0 -37
  110. data/test/settings_test.rb +0 -95
  111. data/test/test_helper.rb +0 -234
  112. data/test/unicode_file_names_and_comments_test.rb +0 -62
  113. data/test/zip64_full_test.rb +0 -51
  114. data/test/zip64_support_test.rb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 898367588fc593bddd565ee8626c75cfbcddfce2
4
- data.tar.gz: 24d90fd344a11d8cf3b8098c459eb2c765e933e7
2
+ SHA256:
3
+ metadata.gz: 8ffab0e42187d7bbd5b732ff0b9395a6215587a18ce5dd9d64da46d1c628a69c
4
+ data.tar.gz: 3032ae5d4f62644c1a19d5de25d515844ecb8da0f59c774fcaa6b16904f496b7
5
5
  SHA512:
6
- metadata.gz: 4f00c8c74720ba3bf103596601400f57e89d03cdd90b4423debd4c96ed6150a3db0fa8f7407201657cf6a7ee0b2e6586c7a284e1398dd1cf44c523799e1b25be
7
- data.tar.gz: 3a434114b84d7b109e26aec4821b395ad100efda591ad004656c6b5fd8cdba3740e50c171409c726a9770996e0815ef0324c87063d975024642c6f89ba56377e
6
+ metadata.gz: 218f77b0c4ae423f2baed702bf56bb598e2c3d22a01fc9af8c2fa33432580e2706a820474fa1222480370517a9f28bda692a2f296d89620459d9c6239fcfff37
7
+ data.tar.gz: a4ffa820bb2272b07bd918827d03751261f87d694966ef6c88f74f4ec569c94b0420c9288a92e5370653d00790478bdd85d3e89a9ef42ccd94834facb622c336
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # rubyzip
2
+
2
3
  [![Gem Version](https://badge.fury.io/rb/rubyzip.svg)](http://badge.fury.io/rb/rubyzip)
3
4
  [![Build Status](https://secure.travis-ci.org/rubyzip/rubyzip.svg)](http://travis-ci.org/rubyzip/rubyzip)
4
5
  [![Code Climate](https://codeclimate.com/github/rubyzip/rubyzip.svg)](https://codeclimate.com/github/rubyzip/rubyzip)
@@ -19,9 +20,10 @@ gem 'zip-zip' # will load compatibility for old rubyzip API.
19
20
 
20
21
  ## Requirements
21
22
 
22
- * Ruby 1.9.2 or greater
23
+ - Ruby 2.4 or greater (for rubyzip 2.0; use 1.x for older rubies)
23
24
 
24
25
  ## Installation
26
+
25
27
  Rubyzip is available on RubyGems:
26
28
 
27
29
  ```
@@ -59,7 +61,8 @@ end
59
61
  ```
60
62
 
61
63
  ### Zipping a directory recursively
62
- Copy from [here](https://github.com/rubyzip/rubyzip/blob/05916bf89181e1955118fd3ea059f18acac28cc8/samples/example_recursive.rb )
64
+
65
+ Copy from [here](https://github.com/rubyzip/rubyzip/blob/9d891f7353e66052283562d3e252fe380bb4b199/samples/example_recursive.rb)
63
66
 
64
67
  ```ruby
65
68
  require 'zip'
@@ -83,7 +86,7 @@ class ZipFileGenerator
83
86
 
84
87
  # Zip the input directory.
85
88
  def write
86
- entries = Dir.entries(@input_dir) - %w(. ..)
89
+ entries = Dir.entries(@input_dir) - %w[. ..]
87
90
 
88
91
  ::Zip::File.open(@output_file, ::Zip::File::CREATE) do |zipfile|
89
92
  write_entries entries, '', zipfile
@@ -97,7 +100,6 @@ class ZipFileGenerator
97
100
  entries.each do |e|
98
101
  zipfile_path = path == '' ? e : File.join(path, e)
99
102
  disk_file_path = File.join(@input_dir, zipfile_path)
100
- puts "Deflating #{disk_file_path}"
101
103
 
102
104
  if File.directory? disk_file_path
103
105
  recursively_deflate_directory(disk_file_path, zipfile, zipfile_path)
@@ -109,14 +111,12 @@ class ZipFileGenerator
109
111
 
110
112
  def recursively_deflate_directory(disk_file_path, zipfile, zipfile_path)
111
113
  zipfile.mkdir zipfile_path
112
- subdir = Dir.entries(disk_file_path) - %w(. ..)
114
+ subdir = Dir.entries(disk_file_path) - %w[. ..]
113
115
  write_entries subdir, zipfile_path, zipfile
114
116
  end
115
117
 
116
118
  def put_into_archive(disk_file_path, zipfile, zipfile_path)
117
- zipfile.get_output_stream(zipfile_path) do |f|
118
- f.write(File.open(disk_file_path, 'rb').read)
119
- end
119
+ zipfile.add(zipfile_path, disk_file_path)
120
120
  end
121
121
  end
122
122
  ```
@@ -152,12 +152,15 @@ When modifying a zip archive the file permissions of the archive are preserved.
152
152
  ### Reading a Zip file
153
153
 
154
154
  ```ruby
155
+ MAX_SIZE = 1024**2 # 1MiB (but of course you can increase this)
155
156
  Zip::File.open('foo.zip') do |zip_file|
156
157
  # Handle entries one by one
157
158
  zip_file.each do |entry|
158
- # Extract to file/directory/symlink
159
159
  puts "Extracting #{entry.name}"
160
- entry.extract(dest_file)
160
+ raise 'File too large when extracted' if entry.size > MAX_SIZE
161
+
162
+ # Extract to file or directory based on name in the archive
163
+ entry.extract
161
164
 
162
165
  # Read into memory
163
166
  content = entry.get_input_stream.read
@@ -165,6 +168,7 @@ Zip::File.open('foo.zip') do |zip_file|
165
168
 
166
169
  # Find specific entry
167
170
  entry = zip_file.glob('*.csv').first
171
+ raise 'File too large when extracted' if entry.size > MAX_SIZE
168
172
  puts entry.get_input_stream.read
169
173
  end
170
174
  ```
@@ -177,7 +181,6 @@ But there is one exception when it is not working - General Purpose Flag Bit 3.
177
181
 
178
182
  > If bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is written. The fields in the local header are filled with zero, and the CRC-32 and size are appended in a 12-byte structure (optionally preceded by a 4-byte signature) immediately after the compressed data
179
183
 
180
-
181
184
  If `::Zip::InputStream` finds such entry in the zip archive it will raise an exception.
182
185
 
183
186
  ### Password Protection (Experimental)
@@ -220,7 +223,9 @@ File.open(new_path, "wb") {|f| f.write(buffer.string) }
220
223
 
221
224
  ## Configuration
222
225
 
223
- By default, rubyzip will not overwrite files if they already exist inside of the extracted path. To change this behavior, you may specify a configuration option like so:
226
+ ### Existing Files
227
+
228
+ By default, rubyzip will not overwrite files if they already exist inside of the extracted path. To change this behavior, you may specify a configuration option like so:
224
229
 
225
230
  ```ruby
226
231
  Zip.on_exists_proc = true
@@ -234,32 +239,76 @@ Additionally, if you want to configure rubyzip to overwrite existing files while
234
239
  Zip.continue_on_exists_proc = true
235
240
  ```
236
241
 
242
+ ### Non-ASCII Names
243
+
237
244
  If you want to store non-english names and want to open them on Windows(pre 7) you need to set this option:
238
245
 
239
246
  ```ruby
240
247
  Zip.unicode_names = true
241
248
  ```
242
249
 
250
+ Sometimes file names inside zip contain non-ASCII characters. If you can assume which encoding was used for such names and want to be able to find such entries using `find_entry` then you can force assumed encoding like so:
251
+
252
+ ```ruby
253
+ Zip.force_entry_names_encoding = 'UTF-8'
254
+ ```
255
+
256
+ Allowed encoding names are the same as accepted by `String#force_encoding`
257
+
258
+ ### Date Validation
259
+
243
260
  Some zip files might have an invalid date format, which will raise a warning. You can hide this warning with the following setting:
244
261
 
245
262
  ```ruby
246
263
  Zip.warn_invalid_date = false
247
264
  ```
248
265
 
266
+ ### Size Validation
267
+
268
+ By default (in rubyzip >= 2.0), rubyzip's `extract` method checks that an entry's reported uncompressed size is not (significantly) smaller than its actual size. This is to help you protect your application against [zip bombs](https://en.wikipedia.org/wiki/Zip_bomb). Before `extract`ing an entry, you should check that its size is in the range you expect. For example, if your application supports processing up to 100 files at once, each up to 10MiB, your zip extraction code might look like:
269
+
270
+ ```ruby
271
+ MAX_FILE_SIZE = 10 * 1024**2 # 10MiB
272
+ MAX_FILES = 100
273
+ Zip::File.open('foo.zip') do |zip_file|
274
+ num_files = 0
275
+ zip_file.each do |entry|
276
+ num_files += 1 if entry.file?
277
+ raise 'Too many extracted files' if num_files > MAX_FILES
278
+ raise 'File too large when extracted' if entry.size > MAX_FILE_SIZE
279
+ entry.extract
280
+ end
281
+ end
282
+ ```
283
+
284
+ If you need to extract zip files that report incorrect uncompressed sizes and you really trust them not too be too large, you can disable this setting with
285
+ ```ruby
286
+ Zip.validate_entry_sizes = false
287
+ ```
288
+
289
+ Note that if you use the lower level `Zip::InputStream` interface, `rubyzip` does *not* check the entry `size`s. In this case, the caller is responsible for making sure it does not read more data than expected from the input stream.
290
+
291
+ ### Default Compression
292
+
249
293
  You can set the default compression level like so:
250
294
 
251
295
  ```ruby
252
296
  Zip.default_compression = Zlib::DEFAULT_COMPRESSION
253
297
  ```
298
+
254
299
  It defaults to `Zlib::DEFAULT_COMPRESSION`. Possible values are `Zlib::BEST_COMPRESSION`, `Zlib::DEFAULT_COMPRESSION` and `Zlib::NO_COMPRESSION`
255
300
 
256
- Sometimes file names inside zip contain non-ASCII characters. If you can assume which encoding was used for such names and want to be able to find such entries using `find_entry` then you can force assumed encoding like so:
301
+ ### Zip64 Support
302
+
303
+ By default, Zip64 support is disabled for writing. To enable it do this:
257
304
 
258
305
  ```ruby
259
- Zip.force_entry_names_encoding = 'UTF-8'
306
+ Zip.write_zip64_support = true
260
307
  ```
261
308
 
262
- Allowed encoding names are the same as accepted by `String#force_encoding`
309
+ _NOTE_: If you will enable Zip64 writing then you will need zip extractor with Zip64 support to extract archive.
310
+
311
+ ### Block Form
263
312
 
264
313
  You can set multiple settings at the same time by using a block:
265
314
 
@@ -272,14 +321,6 @@ You can set multiple settings at the same time by using a block:
272
321
  end
273
322
  ```
274
323
 
275
- By default, Zip64 support is disabled for writing. To enable it do this:
276
-
277
- ```ruby
278
- Zip.write_zip64_support = true
279
- ```
280
-
281
- _NOTE_: If you will enable Zip64 writing then you will need zip extractor with Zip64 support to extract archive.
282
-
283
324
  ## Developing
284
325
 
285
326
  To run the test you need to do this:
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rake/testtask'
3
+ require 'rubocop/rake_task'
3
4
 
4
5
  task default: :test
5
6
 
@@ -10,6 +11,8 @@ Rake::TestTask.new(:test) do |test|
10
11
  test.verbose = true
11
12
  end
12
13
 
14
+ RuboCop::RakeTask.new
15
+
13
16
  # Rake::TestTask.new(:zip64_full_test) do |test|
14
17
  # test.libs << File.join(File.dirname(__FILE__), 'lib')
15
18
  # test.libs << File.join(File.dirname(__FILE__), 'test')
data/lib/zip.rb CHANGED
@@ -1,10 +1,11 @@
1
+ require 'English'
1
2
  require 'delegate'
2
3
  require 'singleton'
3
4
  require 'tempfile'
4
- require 'tmpdir'
5
5
  require 'fileutils'
6
6
  require 'stringio'
7
7
  require 'zlib'
8
+ require 'zip/constants'
8
9
  require 'zip/dos_time'
9
10
  require 'zip/ioextras'
10
11
  require 'rbconfig'
@@ -22,6 +23,7 @@ require 'zip/null_compressor'
22
23
  require 'zip/null_input_stream'
23
24
  require 'zip/pass_thru_compressor'
24
25
  require 'zip/pass_thru_decompressor'
26
+ require 'zip/crypto/decrypted_io'
25
27
  require 'zip/crypto/encryption'
26
28
  require 'zip/crypto/null_encryption'
27
29
  require 'zip/crypto/traditional_encryption'
@@ -29,7 +31,6 @@ require 'zip/inflater'
29
31
  require 'zip/deflater'
30
32
  require 'zip/streamable_stream'
31
33
  require 'zip/streamable_directory'
32
- require 'zip/constants'
33
34
  require 'zip/errors'
34
35
 
35
36
  module Zip
@@ -42,7 +43,8 @@ module Zip
42
43
  :write_zip64_support,
43
44
  :warn_invalid_date,
44
45
  :case_insensitive_match,
45
- :force_entry_names_encoding
46
+ :force_entry_names_encoding,
47
+ :validate_entry_sizes
46
48
 
47
49
  def reset!
48
50
  @_ran_once = false
@@ -54,6 +56,7 @@ module Zip
54
56
  @write_zip64_support = false
55
57
  @warn_invalid_date = true
56
58
  @case_insensitive_match = false
59
+ @validate_entry_sizes = true
57
60
  end
58
61
 
59
62
  def setup
@@ -65,7 +65,7 @@ module Zip
65
65
  @entry_set ? @entry_set.size : 0, # number of entries on this disk
66
66
  @entry_set ? @entry_set.size : 0, # number of entries total
67
67
  cdir_size, # size of central directory
68
- offset, # offset of start of central directory in its disk
68
+ offset # offset of start of central directory in its disk
69
69
  ]
70
70
  io << tmp.pack('VQ<vvVVQ<Q<Q<Q<')
71
71
  end
@@ -141,6 +141,7 @@ module Zip
141
141
  def get_e_o_c_d(buf) #:nodoc:
142
142
  sig_index = buf.rindex([END_OF_CDS].pack('V'))
143
143
  raise Error, 'Zip end of central directory signature not found' unless sig_index
144
+
144
145
  buf = buf.slice!((sig_index + 4)..(buf.bytesize))
145
146
 
146
147
  def buf.read(count)
@@ -166,8 +167,10 @@ module Zip
166
167
  def get_64_e_o_c_d(buf) #:nodoc:
167
168
  zip_64_start = buf.rindex([ZIP64_END_OF_CDS].pack('V'))
168
169
  raise Error, 'Zip64 end of central directory signature not found' unless zip_64_start
170
+
169
171
  zip_64_locator = buf.rindex([ZIP64_EOCD_LOCATOR].pack('V'))
170
172
  raise Error, 'Zip64 end of central directory signature locator not found' unless zip_64_locator
173
+
171
174
  buf = buf.slice!((zip_64_start + 4)..zip_64_locator)
172
175
 
173
176
  def buf.read(count)
@@ -178,8 +181,8 @@ module Zip
178
181
  end
179
182
 
180
183
  # For iterating over the entries.
181
- def each(&proc)
182
- @entry_set.each(&proc)
184
+ def each(&a_proc)
185
+ @entry_set.each(&a_proc)
183
186
  end
184
187
 
185
188
  # Returns the number of entries in the central directory (and
@@ -191,13 +194,14 @@ module Zip
191
194
  def self.read_from_stream(io) #:nodoc:
192
195
  cdir = new
193
196
  cdir.read_from_stream(io)
194
- return cdir
197
+ cdir
195
198
  rescue Error
196
- return nil
199
+ nil
197
200
  end
198
201
 
199
202
  def ==(other) #:nodoc:
200
203
  return false unless other.kind_of?(CentralDirectory)
204
+
201
205
  @entry_set.entries.sort == other.entries.sort && comment == other.comment
202
206
  end
203
207
  end
@@ -60,4 +60,56 @@ module Zip
60
60
  FSTYPE_MAC_OSX => 'Mac OS/X (Darwin)'.freeze,
61
61
  FSTYPE_ATHEOS => 'AtheOS'.freeze
62
62
  }.freeze
63
+
64
+ COMPRESSION_METHOD_STORE = 0
65
+ COMPRESSION_METHOD_SHRINK = 1
66
+ COMPRESSION_METHOD_REDUCE_1 = 2
67
+ COMPRESSION_METHOD_REDUCE_2 = 3
68
+ COMPRESSION_METHOD_REDUCE_3 = 4
69
+ COMPRESSION_METHOD_REDUCE_4 = 5
70
+ COMPRESSION_METHOD_IMPLODE = 6
71
+ # RESERVED = 7
72
+ COMPRESSION_METHOD_DEFLATE = 8
73
+ COMPRESSION_METHOD_DEFLATE_64 = 9
74
+ COMPRESSION_METHOD_PKWARE_DCLI = 10
75
+ # RESERVED = 11
76
+ COMPRESSION_METHOD_BZIP2 = 12
77
+ # RESERVED = 13
78
+ COMPRESSION_METHOD_LZMA = 14
79
+ # RESERVED = 15
80
+ COMPRESSION_METHOD_IBM_CMPSC = 16
81
+ # RESERVED = 17
82
+ COMPRESSION_METHOD_IBM_TERSE = 18
83
+ COMPRESSION_METHOD_IBM_LZ77 = 19
84
+ COMPRESSION_METHOD_JPEG = 96
85
+ COMPRESSION_METHOD_WAVPACK = 97
86
+ COMPRESSION_METHOD_PPMD = 98
87
+ COMPRESSION_METHOD_AES = 99
88
+
89
+ COMPRESSION_METHODS = {
90
+ COMPRESSION_METHOD_STORE => 'Store (no compression)',
91
+ COMPRESSION_METHOD_SHRINK => 'Shrink',
92
+ COMPRESSION_METHOD_REDUCE_1 => 'Reduce with compression factor 1',
93
+ COMPRESSION_METHOD_REDUCE_2 => 'Reduce with compression factor 2',
94
+ COMPRESSION_METHOD_REDUCE_3 => 'Reduce with compression factor 3',
95
+ COMPRESSION_METHOD_REDUCE_4 => 'Reduce with compression factor 4',
96
+ COMPRESSION_METHOD_IMPLODE => 'Implode',
97
+ # RESERVED = 7
98
+ COMPRESSION_METHOD_DEFLATE => 'Deflate',
99
+ COMPRESSION_METHOD_DEFLATE_64 => 'Deflate64(tm)',
100
+ COMPRESSION_METHOD_PKWARE_DCLI => 'PKWARE Data Compression Library Imploding (old IBM TERSE)',
101
+ # RESERVED = 11
102
+ COMPRESSION_METHOD_BZIP2 => 'BZIP2',
103
+ # RESERVED = 13
104
+ COMPRESSION_METHOD_LZMA => 'LZMA',
105
+ # RESERVED = 15
106
+ COMPRESSION_METHOD_IBM_CMPSC => 'IBM z/OS CMPSC Compression',
107
+ # RESERVED = 17
108
+ COMPRESSION_METHOD_IBM_TERSE => 'IBM TERSE (new)',
109
+ COMPRESSION_METHOD_IBM_LZ77 => 'IBM LZ77 z Architecture (PFS)',
110
+ COMPRESSION_METHOD_JPEG => 'JPEG variant',
111
+ COMPRESSION_METHOD_WAVPACK => 'WavPack compressed data',
112
+ COMPRESSION_METHOD_PPMD => 'PPMd version I, Rev 1',
113
+ COMPRESSION_METHOD_AES => 'AES encryption'
114
+ }.freeze
63
115
  end
@@ -0,0 +1,40 @@
1
+ module Zip
2
+ class DecryptedIo #:nodoc:all
3
+ CHUNK_SIZE = 32_768
4
+
5
+ def initialize(io, decrypter)
6
+ @io = io
7
+ @decrypter = decrypter
8
+ end
9
+
10
+ def read(length = nil, outbuf = +'')
11
+ return (length.nil? || length.zero? ? '' : nil) if eof
12
+
13
+ while length.nil? || (buffer.bytesize < length)
14
+ break if input_finished?
15
+
16
+ buffer << produce_input
17
+ end
18
+
19
+ outbuf.replace(buffer.slice!(0...(length || output_buffer.bytesize)))
20
+ end
21
+
22
+ private
23
+
24
+ def eof
25
+ buffer.empty? && input_finished?
26
+ end
27
+
28
+ def buffer
29
+ @buffer ||= +''
30
+ end
31
+
32
+ def input_finished?
33
+ @io.eof
34
+ end
35
+
36
+ def produce_input
37
+ @decrypter.decrypt(@io.read(CHUNK_SIZE))
38
+ end
39
+ end
40
+ end
@@ -24,8 +24,8 @@ module Zip
24
24
  end
25
25
  end
26
26
 
27
- def update_keys(n)
28
- @key0 = ~Zlib.crc32(n, ~@key0)
27
+ def update_keys(num)
28
+ @key0 = ~Zlib.crc32(num, ~@key0)
29
29
  @key1 = ((@key1 + (@key0 & 0xff)) * 134_775_813 + 1) & 0xffffffff
30
30
  @key2 = ~Zlib.crc32((@key1 >> 24).chr, ~@key2)
31
31
  end
@@ -63,10 +63,10 @@ module Zip
63
63
 
64
64
  private
65
65
 
66
- def encode(n)
66
+ def encode(num)
67
67
  t = decrypt_byte
68
- update_keys(n.chr)
69
- t ^ n
68
+ update_keys(num.chr)
69
+ t ^ num
70
70
  end
71
71
  end
72
72
 
@@ -86,10 +86,10 @@ module Zip
86
86
 
87
87
  private
88
88
 
89
- def decode(n)
90
- n ^= decrypt_byte
91
- update_keys(n.chr)
92
- n
89
+ def decode(num)
90
+ num ^= decrypt_byte
91
+ update_keys(num.chr)
92
+ num
93
93
  end
94
94
  end
95
95
  end