diff --git a/lib/zip/decompressor.rb b/lib/zip/decompressor.rb index 9dfaa353..2f89545c 100644 --- a/lib/zip/decompressor.rb +++ b/lib/zip/decompressor.rb @@ -2,6 +2,18 @@ module Zip class Decompressor #:nodoc:all CHUNK_SIZE = 32_768 + def self.decompressor_classes + @decompressor_classes ||= {} + end + + def self.register(compression_method, decompressor_class) + decompressor_classes[compression_method] = decompressor_class + end + + def self.find_by_compression_method(compression_method) + decompressor_classes[compression_method] + end + attr_reader :input_stream attr_reader :decompressed_size diff --git a/lib/zip/inflater.rb b/lib/zip/inflater.rb index de3e7fc4..4e217f6f 100644 --- a/lib/zip/inflater.rb +++ b/lib/zip/inflater.rb @@ -43,6 +43,8 @@ def input_finished? @zlib_inflater.finished? end end + + ::Zip::Decompressor.register(::Zip::COMPRESSION_METHOD_DEFLATE, ::Zip::Inflater) end # Copyright (C) 2002, 2003 Thomas Sondergaard diff --git a/lib/zip/input_stream.rb b/lib/zip/input_stream.rb index 748e18c0..b4c502f5 100644 --- a/lib/zip/input_stream.rb +++ b/lib/zip/input_stream.rb @@ -146,18 +146,20 @@ def get_decrypted_io def get_decompressor return ::Zip::NullDecompressor if @current_entry.nil? - if @current_entry.compression_method == ::Zip::Entry::STORED + decompressed_size = if @current_entry.incomplete? && @current_entry.crc == 0 && @current_entry.size == 0 && @complete_entry - ::Zip::PassThruDecompressor.new(@decrypted_io, @complete_entry.size) + @complete_entry.size else - ::Zip::PassThruDecompressor.new(@decrypted_io, @current_entry.size) + @current_entry.size end - elsif @current_entry.compression_method == ::Zip::Entry::DEFLATED - ::Zip::Inflater.new(@decrypted_io) - else + + decompressor_class = ::Zip::Decompressor.find_by_compression_method(@current_entry.compression_method) + if decompressor_class.nil? raise ::Zip::CompressionMethodError, "Unsupported compression method #{@current_entry.compression_method}" end + + decompressor_class.new(@decrypted_io, decompressed_size) end def produce_input diff --git a/lib/zip/pass_thru_decompressor.rb b/lib/zip/pass_thru_decompressor.rb index 9b9a419b..ac21b61e 100644 --- a/lib/zip/pass_thru_decompressor.rb +++ b/lib/zip/pass_thru_decompressor.rb @@ -22,6 +22,8 @@ def eof alias_method :eof?, :eof end + + ::Zip::Decompressor.register(::Zip::COMPRESSION_METHOD_STORE, ::Zip::PassThruDecompressor) end # Copyright (C) 2002, 2003 Thomas Sondergaard diff --git a/test/decompressor_test.rb b/test/decompressor_test.rb new file mode 100644 index 00000000..d7ff2e73 --- /dev/null +++ b/test/decompressor_test.rb @@ -0,0 +1,15 @@ +require 'test_helper' +class DecompressorTest < MiniTest::Test + TEST_COMPRESSION_METHOD = 255 + + class TestCompressionClass + end + + def test_decompressor_registration + assert_nil(::Zip::Decompressor.find_by_compression_method(TEST_COMPRESSION_METHOD)) + + ::Zip::Decompressor.register(TEST_COMPRESSION_METHOD, TestCompressionClass) + + assert_equal(TestCompressionClass, ::Zip::Decompressor.find_by_compression_method(TEST_COMPRESSION_METHOD)) + end +end