rubyzip 2.0.0 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/zip/inflater.rb CHANGED
@@ -1,64 +1,52 @@
1
1
  module Zip
2
2
  class Inflater < Decompressor #:nodoc:all
3
- def initialize(input_stream, decrypter = NullDecrypter.new)
4
- super(input_stream)
5
- @zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
6
- @output_buffer = ''.dup
7
- @has_returned_empty_string = false
8
- @decrypter = decrypter
9
- end
3
+ def initialize(*args)
4
+ super
10
5
 
11
- def sysread(number_of_bytes = nil, buf = '')
12
- readEverything = number_of_bytes.nil?
13
- while readEverything || @output_buffer.bytesize < number_of_bytes
14
- break if internal_input_finished?
15
- @output_buffer << internal_produce_input(buf)
16
- end
17
- return value_when_finished if @output_buffer.bytesize == 0 && input_finished?
18
- end_index = number_of_bytes.nil? ? @output_buffer.bytesize : number_of_bytes
19
- @output_buffer.slice!(0...end_index)
6
+ @buffer = +''
7
+ @zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
20
8
  end
21
9
 
22
- def produce_input
23
- if @output_buffer.empty?
24
- internal_produce_input
25
- else
26
- @output_buffer.slice!(0...(@output_buffer.length))
10
+ def read(length = nil, outbuf = '')
11
+ return (length.nil? || length.zero? ? '' : nil) if eof
12
+
13
+ while length.nil? || (@buffer.bytesize < length)
14
+ break if input_finished?
15
+
16
+ @buffer << produce_input
27
17
  end
18
+
19
+ outbuf.replace(@buffer.slice!(0...(length || @buffer.bytesize)))
28
20
  end
29
21
 
30
- # to be used with produce_input, not read (as read may still have more data cached)
31
- # is data cached anywhere other than @outputBuffer? the comment above may be wrong
32
- def input_finished?
33
- @output_buffer.empty? && internal_input_finished?
22
+ def eof
23
+ @buffer.empty? && input_finished?
34
24
  end
35
25
 
36
- alias :eof input_finished?
37
- alias :eof? input_finished?
26
+ alias eof? eof
38
27
 
39
28
  private
40
29
 
41
- def internal_produce_input(buf = '')
30
+ def produce_input
42
31
  retried = 0
43
32
  begin
44
- @zlib_inflater.inflate(@decrypter.decrypt(@input_stream.read(Decompressor::CHUNK_SIZE, buf)))
33
+ @zlib_inflater.inflate(input_stream.read(Decompressor::CHUNK_SIZE))
45
34
  rescue Zlib::BufError
46
35
  raise if retried >= 5 # how many times should we retry?
36
+
47
37
  retried += 1
48
38
  retry
49
39
  end
40
+ rescue Zlib::Error
41
+ raise(::Zip::DecompressionError, 'zlib error while inflating')
50
42
  end
51
43
 
52
- def internal_input_finished?
44
+ def input_finished?
53
45
  @zlib_inflater.finished?
54
46
  end
55
-
56
- def value_when_finished # mimic behaviour of ruby File object.
57
- return if @has_returned_empty_string
58
- @has_returned_empty_string = true
59
- ''
60
- end
61
47
  end
48
+
49
+ ::Zip::Decompressor.register(::Zip::COMPRESSION_METHOD_DEFLATE, ::Zip::Inflater)
62
50
  end
63
51
 
64
52
  # Copyright (C) 2002, 2003 Thomas Sondergaard
@@ -39,6 +39,8 @@ module Zip
39
39
  # class.
40
40
 
41
41
  class InputStream
42
+ CHUNK_SIZE = 32_768
43
+
42
44
  include ::Zip::IOExtras::AbstractInputStream
43
45
 
44
46
  # Opens the indicated zip file. An exception is thrown
@@ -49,7 +51,7 @@ module Zip
49
51
  # @param offset [Integer] offset in the IO/StringIO
50
52
  def initialize(context, offset = 0, decrypter = nil)
51
53
  super()
52
- @archive_io = get_io(context, offset)
54
+ @archive_io = get_io(context, offset)
53
55
  @decompressor = ::Zip::NullDecompressor
54
56
  @decrypter = decrypter || ::Zip::NullDecrypter.new
55
57
  @current_entry = nil
@@ -71,6 +73,7 @@ module Zip
71
73
  # Rewinds the stream to the beginning of the current entry
72
74
  def rewind
73
75
  return if @current_entry.nil?
76
+
74
77
  @lineno = 0
75
78
  @pos = 0
76
79
  @archive_io.seek(@current_entry.local_header_offset, IO::SEEK_SET)
@@ -78,16 +81,10 @@ module Zip
78
81
  end
79
82
 
80
83
  # Modeled after IO.sysread
81
- def sysread(number_of_bytes = nil, buf = nil)
82
- @decompressor.sysread(number_of_bytes, buf)
83
- end
84
-
85
- def eof
86
- @output_buffer.empty? && @decompressor.eof
84
+ def sysread(length = nil, outbuf = '')
85
+ @decompressor.read(length, outbuf)
87
86
  end
88
87
 
89
- alias :eof? eof
90
-
91
88
  class << self
92
89
  # Same as #initialize but if a block is passed the opened
93
90
  # stream is passed to the block and closed when the block
@@ -95,6 +92,7 @@ module Zip
95
92
  def open(filename_or_io, offset = 0, decrypter = nil)
96
93
  zio = new(filename_or_io, offset, decrypter)
97
94
  return zio unless block_given?
95
+
98
96
  begin
99
97
  yield zio
100
98
  ensure
@@ -103,8 +101,8 @@ module Zip
103
101
  end
104
102
 
105
103
  def open_buffer(filename_or_io, offset = 0)
106
- puts 'open_buffer is deprecated!!! Use open instead!'
107
- open(filename_or_io, offset)
104
+ warn 'open_buffer is deprecated!!! Use open instead!'
105
+ ::Zip::InputStream.open(filename_or_io, offset)
108
106
  end
109
107
  end
110
108
 
@@ -124,46 +122,55 @@ module Zip
124
122
 
125
123
  def open_entry
126
124
  @current_entry = ::Zip::Entry.read_local_entry(@archive_io)
127
- if @current_entry && @current_entry.gp_flags & 1 == 1 && @decrypter.is_a?(NullEncrypter)
125
+ if @current_entry && @current_entry.encrypted? && @decrypter.kind_of?(NullEncrypter)
128
126
  raise Error, 'password required to decode zip file'
129
127
  end
130
- if @current_entry && @current_entry.gp_flags & 8 == 8 && @current_entry.crc == 0 \
128
+
129
+ if @current_entry && @current_entry.incomplete? && @current_entry.crc == 0 \
131
130
  && @current_entry.compressed_size == 0 \
132
131
  && @current_entry.size == 0 && !@complete_entry
133
132
  raise GPFBit3Error,
134
133
  'General purpose flag Bit 3 is set so not possible to get proper info from local header.' \
135
134
  'Please use ::Zip::File instead of ::Zip::InputStream'
136
135
  end
136
+ @decrypted_io = get_decrypted_io
137
137
  @decompressor = get_decompressor
138
138
  flush
139
139
  @current_entry
140
140
  end
141
141
 
142
+ def get_decrypted_io
143
+ header = @archive_io.read(@decrypter.header_bytesize)
144
+ @decrypter.reset!(header)
145
+
146
+ ::Zip::DecryptedIo.new(@archive_io, @decrypter)
147
+ end
148
+
142
149
  def get_decompressor
143
- if @current_entry.nil?
144
- ::Zip::NullDecompressor
145
- elsif @current_entry.compression_method == ::Zip::Entry::STORED
146
- if @current_entry.gp_flags & 8 == 8 && @current_entry.crc == 0 && @current_entry.size == 0 && @complete_entry
147
- ::Zip::PassThruDecompressor.new(@archive_io, @complete_entry.size)
150
+ return ::Zip::NullDecompressor if @current_entry.nil?
151
+
152
+ decompressed_size =
153
+ if @current_entry.incomplete? && @current_entry.crc == 0 && @current_entry.size == 0 && @complete_entry
154
+ @complete_entry.size
148
155
  else
149
- ::Zip::PassThruDecompressor.new(@archive_io, @current_entry.size)
156
+ @current_entry.size
150
157
  end
151
- elsif @current_entry.compression_method == ::Zip::Entry::DEFLATED
152
- header = @archive_io.read(@decrypter.header_bytesize)
153
- @decrypter.reset!(header)
154
- ::Zip::Inflater.new(@archive_io, @decrypter)
155
- else
158
+
159
+ decompressor_class = ::Zip::Decompressor.find_by_compression_method(@current_entry.compression_method)
160
+ if decompressor_class.nil?
156
161
  raise ::Zip::CompressionMethodError,
157
162
  "Unsupported compression method #{@current_entry.compression_method}"
158
163
  end
164
+
165
+ decompressor_class.new(@decrypted_io, decompressed_size)
159
166
  end
160
167
 
161
168
  def produce_input
162
- @decompressor.produce_input
169
+ @decompressor.read(CHUNK_SIZE)
163
170
  end
164
171
 
165
172
  def input_finished?
166
- @decompressor.input_finished?
173
+ @decompressor.eof
167
174
  end
168
175
  end
169
176
  end
data/lib/zip/ioextras.rb CHANGED
@@ -25,7 +25,7 @@ module Zip
25
25
  object == IO || super
26
26
  end
27
27
  end
28
- end # IOExtras namespace module
28
+ end
29
29
  end
30
30
 
31
31
  require 'zip/ioextras/abstract_input_stream'
@@ -35,6 +35,7 @@ module Zip
35
35
 
36
36
  if tbuf.nil? || tbuf.empty?
37
37
  return nil if number_of_bytes
38
+
38
39
  return ''
39
40
  end
40
41
 
@@ -48,13 +49,13 @@ module Zip
48
49
  buf
49
50
  end
50
51
 
51
- def readlines(a_sep_string = $/)
52
+ def readlines(a_sep_string = $INPUT_RECORD_SEPARATOR)
52
53
  ret_val = []
53
54
  each_line(a_sep_string) { |line| ret_val << line }
54
55
  ret_val
55
56
  end
56
57
 
57
- def gets(a_sep_string = $/, number_of_bytes = nil)
58
+ def gets(a_sep_string = $INPUT_RECORD_SEPARATOR, number_of_bytes = nil)
58
59
  @lineno = @lineno.next
59
60
 
60
61
  if number_of_bytes.respond_to?(:to_int)
@@ -62,20 +63,22 @@ module Zip
62
63
  a_sep_string = a_sep_string.to_str if a_sep_string
63
64
  elsif a_sep_string.respond_to?(:to_int)
64
65
  number_of_bytes = a_sep_string.to_int
65
- a_sep_string = $/
66
+ a_sep_string = $INPUT_RECORD_SEPARATOR
66
67
  else
67
68
  number_of_bytes = nil
68
69
  a_sep_string = a_sep_string.to_str if a_sep_string
69
70
  end
70
71
 
71
72
  return read(number_of_bytes) if a_sep_string.nil?
72
- a_sep_string = "#{$/}#{$/}" if a_sep_string.empty?
73
+
74
+ a_sep_string = "#{$INPUT_RECORD_SEPARATOR}#{$INPUT_RECORD_SEPARATOR}" if a_sep_string.empty?
73
75
 
74
76
  buffer_index = 0
75
77
  over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
76
78
  while (match_index = @output_buffer.index(a_sep_string, buffer_index)).nil? && !over_limit
77
79
  buffer_index = [buffer_index, @output_buffer.bytesize - a_sep_string.bytesize].max
78
80
  return @output_buffer.empty? ? nil : flush if input_finished?
81
+
79
82
  @output_buffer << produce_input
80
83
  over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
81
84
  end
@@ -94,18 +97,26 @@ module Zip
94
97
  ret_val
95
98
  end
96
99
 
97
- def readline(a_sep_string = $/)
100
+ def readline(a_sep_string = $INPUT_RECORD_SEPARATOR)
98
101
  ret_val = gets(a_sep_string)
99
102
  raise EOFError unless ret_val
103
+
100
104
  ret_val
101
105
  end
102
106
 
103
- def each_line(a_sep_string = $/)
104
- yield readline(a_sep_string) while true
107
+ def each_line(a_sep_string = $INPUT_RECORD_SEPARATOR)
108
+ loop { yield readline(a_sep_string) }
105
109
  rescue EOFError
110
+ # We just need to catch this; we don't need to handle it.
111
+ end
112
+
113
+ alias each each_line
114
+
115
+ def eof
116
+ @output_buffer.empty? && input_finished?
106
117
  end
107
118
 
108
- alias_method :each, :each_line
119
+ alias eof? eof
109
120
  end
110
121
  end
111
122
  end
@@ -11,7 +11,7 @@ module Zip
11
11
  end
12
12
 
13
13
  def print(*params)
14
- self << params.join($,) << $\.to_s
14
+ self << params.join($OUTPUT_FIELD_SEPARATOR) << $OUTPUT_RECORD_SEPARATOR.to_s
15
15
  end
16
16
 
17
17
  def printf(a_format_string, *params)
@@ -2,18 +2,10 @@ module Zip
2
2
  module NullDecompressor #:nodoc:all
3
3
  module_function
4
4
 
5
- def sysread(_numberOfBytes = nil, _buf = nil)
5
+ def read(_length = nil, _outbuf = nil)
6
6
  nil
7
7
  end
8
8
 
9
- def produce_input
10
- nil
11
- end
12
-
13
- def input_finished?
14
- true
15
- end
16
-
17
9
  def eof
18
10
  true
19
11
  end
@@ -49,6 +49,7 @@ module Zip
49
49
  class << self
50
50
  def open(file_name, encrypter = nil)
51
51
  return new(file_name) unless block_given?
52
+
52
53
  zos = new(file_name, false, encrypter)
53
54
  yield zos
54
55
  ensure
@@ -57,6 +58,7 @@ module Zip
57
58
 
58
59
  # Same as #open but writes to a filestream instead
59
60
  def write_buffer(io = ::StringIO.new(''), encrypter = nil)
61
+ io.binmode if io.respond_to?(:binmode)
60
62
  zos = new(io, true, encrypter)
61
63
  yield zos
62
64
  zos.close_buffer
@@ -66,6 +68,7 @@ module Zip
66
68
  # Closes the stream and writes the central directory to the zip file
67
69
  def close
68
70
  return if @closed
71
+
69
72
  finalize_current_entry
70
73
  update_local_headers
71
74
  write_central_directory
@@ -76,6 +79,7 @@ module Zip
76
79
  # Closes the stream and writes the central directory to the zip file
77
80
  def close_buffer
78
81
  return @output_stream if @closed
82
+
79
83
  finalize_current_entry
80
84
  update_local_headers
81
85
  write_central_directory
@@ -87,6 +91,7 @@ module Zip
87
91
  # +entry+ can be a ZipEntry object or a string.
88
92
  def put_next_entry(entry_name, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zip.default_compression)
89
93
  raise Error, 'zip stream is closed' if @closed
94
+
90
95
  new_entry = if entry_name.kind_of?(Entry)
91
96
  entry_name
92
97
  else
@@ -94,7 +99,7 @@ module Zip
94
99
  end
95
100
  new_entry.comment = comment unless comment.nil?
96
101
  unless extra.nil?
97
- new_entry.extra = extra.is_a?(ExtraField) ? extra : ExtraField.new(extra.to_s)
102
+ new_entry.extra = extra.kind_of?(ExtraField) ? extra : ExtraField.new(extra.to_s)
98
103
  end
99
104
  new_entry.compression_method = compression_method unless compression_method.nil?
100
105
  init_next_entry(new_entry, level)
@@ -104,7 +109,8 @@ module Zip
104
109
  def copy_raw_entry(entry)
105
110
  entry = entry.dup
106
111
  raise Error, 'zip stream is closed' if @closed
107
- raise Error, 'entry is not a ZipEntry' unless entry.is_a?(Entry)
112
+ raise Error, 'entry is not a ZipEntry' unless entry.kind_of?(Entry)
113
+
108
114
  finalize_current_entry
109
115
  @entry_set << entry
110
116
  src_pos = entry.local_header_offset
@@ -123,8 +129,11 @@ module Zip
123
129
 
124
130
  def finalize_current_entry
125
131
  return unless @current_entry
132
+
126
133
  finish
127
- @current_entry.compressed_size = @output_stream.tell - @current_entry.local_header_offset - @current_entry.calculate_local_header_size
134
+ @current_entry.compressed_size = @output_stream.tell - \
135
+ @current_entry.local_header_offset - \
136
+ @current_entry.calculate_local_header_size
128
137
  @current_entry.size = @compressor.size
129
138
  @current_entry.crc = @compressor.crc
130
139
  @output_stream << @encrypter.data_descriptor(@current_entry.crc, @current_entry.compressed_size, @current_entry.size)
@@ -144,9 +153,9 @@ module Zip
144
153
 
145
154
  def get_compressor(entry, level)
146
155
  case entry.compression_method
147
- when Entry::DEFLATED then
156
+ when Entry::DEFLATED
148
157
  ::Zip::Deflater.new(@output_stream, level, @encrypter)
149
- when Entry::STORED then
158
+ when Entry::STORED
150
159
  ::Zip::PassThruCompressor.new(@output_stream)
151
160
  else
152
161
  raise ::Zip::CompressionMethodError,
@@ -1,8 +1,8 @@
1
1
  module Zip
2
2
  class PassThruCompressor < Compressor #:nodoc:all
3
- def initialize(outputStream)
3
+ def initialize(output_stream)
4
4
  super()
5
- @output_stream = outputStream
5
+ @output_stream = output_stream
6
6
  @crc = Zlib.crc32
7
7
  @size = 0
8
8
  end
@@ -1,38 +1,29 @@
1
1
  module Zip
2
2
  class PassThruDecompressor < Decompressor #:nodoc:all
3
- def initialize(input_stream, chars_to_read)
4
- super(input_stream)
5
- @chars_to_read = chars_to_read
3
+ def initialize(*args)
4
+ super
6
5
  @read_so_far = 0
7
- @has_returned_empty_string = false
8
6
  end
9
7
 
10
- def sysread(number_of_bytes = nil, buf = '')
11
- if input_finished?
12
- has_returned_empty_string_val = @has_returned_empty_string
13
- @has_returned_empty_string = true
14
- return '' unless has_returned_empty_string_val
15
- return
16
- end
8
+ def read(length = nil, outbuf = '')
9
+ return (length.nil? || length.zero? ? '' : nil) if eof
17
10
 
18
- if number_of_bytes.nil? || @read_so_far + number_of_bytes > @chars_to_read
19
- number_of_bytes = @chars_to_read - @read_so_far
11
+ if length.nil? || (@read_so_far + length) > decompressed_size
12
+ length = decompressed_size - @read_so_far
20
13
  end
21
- @read_so_far += number_of_bytes
22
- @input_stream.read(number_of_bytes, buf)
23
- end
24
14
 
25
- def produce_input
26
- sysread(::Zip::Decompressor::CHUNK_SIZE)
15
+ @read_so_far += length
16
+ input_stream.read(length, outbuf)
27
17
  end
28
18
 
29
- def input_finished?
30
- @read_so_far >= @chars_to_read
19
+ def eof
20
+ @read_so_far >= decompressed_size
31
21
  end
32
22
 
33
- alias eof input_finished?
34
- alias eof? input_finished?
23
+ alias eof? eof
35
24
  end
25
+
26
+ ::Zip::Decompressor.register(::Zip::COMPRESSION_METHOD_STORE, ::Zip::PassThruDecompressor)
36
27
  end
37
28
 
38
29
  # Copyright (C) 2002, 2003 Thomas Sondergaard