diff --git a/README.md b/README.md index 12d1872..2dca73c 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,7 @@ There is one exception where it can not work however, and this is if the file do > 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. -If `Zip::InputStream` finds such an entry in the zip archive it will raise an exception (`Zip::GPFBit3Error`). +If `Zip::InputStream` finds such an entry in the zip archive it will raise an exception (`Zip::StreamingError`). `Zip::InputStream` is not designed to be used for random access in a zip file. When performing any operations on an entry that you are accessing via `Zip::InputStream.get_next_entry` then you should complete any such operations before the next call to `get_next_entry`. diff --git a/lib/zip/errors.rb b/lib/zip/errors.rb index 3e1895a..fd10022 100644 --- a/lib/zip/errors.rb +++ b/lib/zip/errors.rb @@ -7,7 +7,6 @@ module Zip class EntryNameError < Error; end class EntrySizeError < Error; end class InternalError < Error; end - class GPFBit3Error < Error; end class DecompressionError < Error; end class SplitArchiveError < Error; end @@ -23,4 +22,19 @@ module Zip "Unsupported compression method: #{COMPRESSION_METHODS[@compression_method]}." end end + + class StreamingError < Error + attr_reader :entry + + def initialize(entry) + super() + @entry = entry + end + + def message + "The local header of this entry ('#{@entry.name}') does not contain " \ + 'the correct metadata for `Zip::InputStream` to be able to ' \ + 'uncompress it. Please use `Zip::File` instead of `Zip::InputStream`.' + end + end end diff --git a/lib/zip/input_stream.rb b/lib/zip/input_stream.rb index a1f2929..f48466c 100644 --- a/lib/zip/input_stream.rb +++ b/lib/zip/input_stream.rb @@ -70,12 +70,7 @@ module Zip # Returns nil when there are no more entries. def get_next_entry unless @current_entry.nil? - if @current_entry.incomplete? - raise GPFBit3Error, - 'It is not possible to get complete info from the local ' \ - 'header to extract this entry (GP flags bit 3 is set). ' \ - 'Please use `Zip::File` instead of `Zip::InputStream`.' - end + raise StreamingError, @current_entry if @current_entry.incomplete? @archive_io.seek(@current_entry.next_header_offset, IO::SEEK_SET) end @@ -151,10 +146,7 @@ module Zip if @current_entry.incomplete? && @current_entry.compressed_size == 0 \ && !@complete_entry - raise GPFBit3Error, - 'It is not possible to get complete info from the local ' \ - 'header to extract this entry (GP flags bit 3 is set). ' \ - 'Please use `Zip::File` instead of `Zip::InputStream`.' + raise StreamingError, @current_entry end @decrypted_io = get_decrypted_io diff --git a/test/file_test.rb b/test/file_test.rb index 106e69a..dfc48c8 100644 --- a/test/file_test.rb +++ b/test/file_test.rb @@ -46,9 +46,13 @@ class ZipFileTest < MiniTest::Test def test_get_input_stream_stored_with_gpflag_bit3 ::Zip::File.open('test/data/gpbit3stored.zip') do |zf| zis = zf.get_input_stream('file1.txt') - assert_raises(::Zip::GPFBit3Error) do + + error = assert_raises(::Zip::StreamingError) do zis.get_next_entry end + assert_match(/file1\.txt/, error.message) + assert_equal('file1.txt', error.entry.name) + zf.get_input_stream('file2.txt') end end diff --git a/test/input_stream_test.rb b/test/input_stream_test.rb index 6500e5e..becb933 100644 --- a/test/input_stream_test.rb +++ b/test/input_stream_test.rb @@ -69,17 +69,21 @@ class ZipInputStreamTest < MiniTest::Test def test_open_file_with_gp3bit_set ::Zip::InputStream.open('test/data/gpbit3stored.zip') do |zis| - assert_raises(::Zip::GPFBit3Error) do + error = assert_raises(::Zip::StreamingError) do zis.get_next_entry end + assert_match(/file1\.txt/, error.message) + assert_equal('file1.txt', error.entry.name) end end def test_open_file_with_gp3bit_set_created_by_osx_archive ::Zip::InputStream.open('test/data/osx-archive.zip') do |zis| - assert_raises(::Zip::GPFBit3Error) do + error = assert_raises(::Zip::StreamingError) do zis.get_next_entry end + assert_match(/1\.txt/, error.message) + assert_equal('1.txt', error.entry.name) end end