Untangle encryption and decompression
This commit is contained in:
parent
8f7c5caf29
commit
4e28f7286c
|
@ -21,6 +21,7 @@ require 'zip/null_compressor'
|
|||
require 'zip/null_input_stream'
|
||||
require 'zip/pass_thru_compressor'
|
||||
require 'zip/pass_thru_decompressor'
|
||||
require 'zip/crypto/decrypted_io'
|
||||
require 'zip/crypto/encryption'
|
||||
require 'zip/crypto/null_encryption'
|
||||
require 'zip/crypto/traditional_encryption'
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
module Zip
|
||||
class DecryptedIo #:nodoc:all
|
||||
CHUNK_SIZE = 32_768
|
||||
|
||||
def initialize(io, decrypter)
|
||||
@io = io
|
||||
@decrypter = decrypter
|
||||
end
|
||||
|
||||
def read(length = nil, outbuf = '')
|
||||
return ((length.nil? || length.zero?) ? "" : nil) if eof
|
||||
|
||||
while length.nil? || (buffer.bytesize < length)
|
||||
break if input_finished?
|
||||
buffer << produce_input
|
||||
end
|
||||
|
||||
outbuf.replace(buffer.slice!(0...(length || output_buffer.bytesize)))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def eof
|
||||
buffer.empty? && input_finished?
|
||||
end
|
||||
|
||||
def buffer
|
||||
@buffer ||= ''.dup
|
||||
end
|
||||
|
||||
def input_finished?
|
||||
@io.eof
|
||||
end
|
||||
|
||||
def produce_input
|
||||
@decrypter.decrypt(@io.read(CHUNK_SIZE))
|
||||
end
|
||||
end
|
||||
end
|
|
@ -49,7 +49,7 @@ module Zip
|
|||
MAX_SEGMENT_SIZE = 3_221_225_472
|
||||
MIN_SEGMENT_SIZE = 65_536
|
||||
DATA_BUFFER_SIZE = 8192
|
||||
IO_METHODS = [:tell, :seek, :read, :close]
|
||||
IO_METHODS = [:tell, :seek, :read, :eof, :close]
|
||||
|
||||
DEFAULT_OPTIONS = {
|
||||
restore_ownership: false,
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
module Zip
|
||||
class Inflater < Decompressor #:nodoc:all
|
||||
def initialize(input_stream, decrypter = NullDecrypter.new)
|
||||
def initialize(input_stream)
|
||||
super(input_stream)
|
||||
@zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
||||
@output_buffer = ''.dup
|
||||
@has_returned_empty_string = false
|
||||
@decrypter = decrypter
|
||||
end
|
||||
|
||||
def sysread(number_of_bytes = nil, buf = '')
|
||||
|
@ -30,7 +29,7 @@ module Zip
|
|||
def internal_produce_input(buf = '')
|
||||
retried = 0
|
||||
begin
|
||||
@zlib_inflater.inflate(@decrypter.decrypt(@input_stream.read(Decompressor::CHUNK_SIZE, buf)))
|
||||
@zlib_inflater.inflate(@input_stream.read(Decompressor::CHUNK_SIZE, buf))
|
||||
rescue Zlib::BufError
|
||||
raise if retried >= 5 # how many times should we retry?
|
||||
retried += 1
|
||||
|
|
|
@ -147,7 +147,8 @@ module Zip
|
|||
elsif @current_entry.compression_method == ::Zip::Entry::DEFLATED
|
||||
header = @archive_io.read(@decrypter.header_bytesize)
|
||||
@decrypter.reset!(header)
|
||||
::Zip::Inflater.new(@archive_io, @decrypter)
|
||||
decrypted_io = ::Zip::DecryptedIo.new(@archive_io, @decrypter)
|
||||
::Zip::Inflater.new(decrypted_io)
|
||||
else
|
||||
raise ::Zip::CompressionMethodError,
|
||||
"Unsupported compression method #{@current_entry.compression_method}"
|
||||
|
|
Loading…
Reference in New Issue