Make decryption generic for all compression methods

Now, STORED files can be decrypted, just like DEFLATED files.
This commit is contained in:
Jan-Joost Spanjers 2019-12-21 15:04:43 +01:00
parent 4e28f7286c
commit b80ce3cc57
4 changed files with 48 additions and 9 deletions

View File

@ -130,25 +130,30 @@ module Zip
'General purpose flag Bit 3 is set so not possible to get proper info from local header.' \
'Please use ::Zip::File instead of ::Zip::InputStream'
end
@decrypted_io = get_decrypted_io
@decompressor = get_decompressor
flush
@current_entry
end
def get_decrypted_io
header = @archive_io.read(@decrypter.header_bytesize)
@decrypter.reset!(header)
::Zip::DecryptedIo.new(@archive_io, @decrypter)
end
def get_decompressor
if @current_entry.nil?
::Zip::NullDecompressor
elsif @current_entry.compression_method == ::Zip::Entry::STORED
return ::Zip::NullDecompressor if @current_entry.nil?
if @current_entry.compression_method == ::Zip::Entry::STORED
if @current_entry.incomplete? && @current_entry.crc == 0 && @current_entry.size == 0 && @complete_entry
::Zip::PassThruDecompressor.new(@archive_io, @complete_entry.size)
::Zip::PassThruDecompressor.new(@decrypted_io, @complete_entry.size)
else
::Zip::PassThruDecompressor.new(@archive_io, @current_entry.size)
::Zip::PassThruDecompressor.new(@decrypted_io, @current_entry.size)
end
elsif @current_entry.compression_method == ::Zip::Entry::DEFLATED
header = @archive_io.read(@decrypter.header_bytesize)
@decrypter.reset!(header)
decrypted_io = ::Zip::DecryptedIo.new(@archive_io, @decrypter)
::Zip::Inflater.new(decrypted_io)
::Zip::Inflater.new(@decrypted_io)
else
raise ::Zip::CompressionMethodError,
"Unsupported compression method #{@current_entry.compression_method}"

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,34 @@
require 'test_helper'
class StoredSupportTest < MiniTest::Test
STORED_ZIP_TEST_FILE = 'test/data/zipWithStoredCompression.zip'
ENCRYPTED_STORED_ZIP_TEST_FILE = 'test/data/zipWithStoredCompressionAndEncryption.zip'
INPUT_FILE1 = 'test/data/file1.txt'
INPUT_FILE2 = 'test/data/file2.txt'
def test_read
Zip::InputStream.open(STORED_ZIP_TEST_FILE) do |zis|
entry = zis.get_next_entry
assert_equal 'file1.txt', entry.name
assert_equal 1327, entry.size
assert_equal open(INPUT_FILE1, 'r').read, zis.read
entry = zis.get_next_entry
assert_equal 'file2.txt', entry.name
assert_equal 41234, entry.size
assert_equal open(INPUT_FILE2, 'r').read, zis.read
end
end
def test_encrypted_read
Zip::InputStream.open(ENCRYPTED_STORED_ZIP_TEST_FILE, 0, Zip::TraditionalDecrypter.new('password')) do |zis|
entry = zis.get_next_entry
assert_equal 'file1.txt', entry.name
assert_equal 1327, entry.size
assert_equal open(INPUT_FILE1, 'r').read, zis.read
entry = zis.get_next_entry
assert_equal 'file2.txt', entry.name
assert_equal 41234, entry.size
assert_equal open(INPUT_FILE2, 'r').read, zis.read
end
end
end