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/null_input_stream'
|
||||||
require 'zip/pass_thru_compressor'
|
require 'zip/pass_thru_compressor'
|
||||||
require 'zip/pass_thru_decompressor'
|
require 'zip/pass_thru_decompressor'
|
||||||
|
require 'zip/crypto/decrypted_io'
|
||||||
require 'zip/crypto/encryption'
|
require 'zip/crypto/encryption'
|
||||||
require 'zip/crypto/null_encryption'
|
require 'zip/crypto/null_encryption'
|
||||||
require 'zip/crypto/traditional_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
|
MAX_SEGMENT_SIZE = 3_221_225_472
|
||||||
MIN_SEGMENT_SIZE = 65_536
|
MIN_SEGMENT_SIZE = 65_536
|
||||||
DATA_BUFFER_SIZE = 8192
|
DATA_BUFFER_SIZE = 8192
|
||||||
IO_METHODS = [:tell, :seek, :read, :close]
|
IO_METHODS = [:tell, :seek, :read, :eof, :close]
|
||||||
|
|
||||||
DEFAULT_OPTIONS = {
|
DEFAULT_OPTIONS = {
|
||||||
restore_ownership: false,
|
restore_ownership: false,
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
module Zip
|
module Zip
|
||||||
class Inflater < Decompressor #:nodoc:all
|
class Inflater < Decompressor #:nodoc:all
|
||||||
def initialize(input_stream, decrypter = NullDecrypter.new)
|
def initialize(input_stream)
|
||||||
super(input_stream)
|
super(input_stream)
|
||||||
@zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
@zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
||||||
@output_buffer = ''.dup
|
@output_buffer = ''.dup
|
||||||
@has_returned_empty_string = false
|
@has_returned_empty_string = false
|
||||||
@decrypter = decrypter
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def sysread(number_of_bytes = nil, buf = '')
|
def sysread(number_of_bytes = nil, buf = '')
|
||||||
|
@ -30,7 +29,7 @@ module Zip
|
||||||
def internal_produce_input(buf = '')
|
def internal_produce_input(buf = '')
|
||||||
retried = 0
|
retried = 0
|
||||||
begin
|
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
|
rescue Zlib::BufError
|
||||||
raise if retried >= 5 # how many times should we retry?
|
raise if retried >= 5 # how many times should we retry?
|
||||||
retried += 1
|
retried += 1
|
||||||
|
|
|
@ -147,7 +147,8 @@ module Zip
|
||||||
elsif @current_entry.compression_method == ::Zip::Entry::DEFLATED
|
elsif @current_entry.compression_method == ::Zip::Entry::DEFLATED
|
||||||
header = @archive_io.read(@decrypter.header_bytesize)
|
header = @archive_io.read(@decrypter.header_bytesize)
|
||||||
@decrypter.reset!(header)
|
@decrypter.reset!(header)
|
||||||
::Zip::Inflater.new(@archive_io, @decrypter)
|
decrypted_io = ::Zip::DecryptedIo.new(@archive_io, @decrypter)
|
||||||
|
::Zip::Inflater.new(decrypted_io)
|
||||||
else
|
else
|
||||||
raise ::Zip::CompressionMethodError,
|
raise ::Zip::CompressionMethodError,
|
||||||
"Unsupported compression method #{@current_entry.compression_method}"
|
"Unsupported compression method #{@current_entry.compression_method}"
|
||||||
|
|
Loading…
Reference in New Issue