rubyzip 1.0.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +6 -14
  2. data/README.md +231 -46
  3. data/Rakefile +13 -5
  4. data/TODO +0 -1
  5. data/lib/zip/central_directory.rb +64 -29
  6. data/lib/zip/compressor.rb +1 -2
  7. data/lib/zip/constants.rb +59 -5
  8. data/lib/zip/crypto/decrypted_io.rb +40 -0
  9. data/lib/zip/crypto/encryption.rb +11 -0
  10. data/lib/zip/crypto/null_encryption.rb +43 -0
  11. data/lib/zip/crypto/traditional_encryption.rb +99 -0
  12. data/lib/zip/decompressor.rb +22 -4
  13. data/lib/zip/deflater.rb +11 -6
  14. data/lib/zip/dos_time.rb +27 -16
  15. data/lib/zip/entry.rb +299 -163
  16. data/lib/zip/entry_set.rb +22 -20
  17. data/lib/zip/errors.rb +17 -6
  18. data/lib/zip/extra_field/generic.rb +15 -14
  19. data/lib/zip/extra_field/ntfs.rb +94 -0
  20. data/lib/zip/extra_field/old_unix.rb +46 -0
  21. data/lib/zip/extra_field/universal_time.rb +46 -16
  22. data/lib/zip/extra_field/unix.rb +10 -9
  23. data/lib/zip/extra_field/zip64.rb +46 -6
  24. data/lib/zip/extra_field/zip64_placeholder.rb +15 -0
  25. data/lib/zip/extra_field.rb +32 -18
  26. data/lib/zip/file.rb +260 -160
  27. data/lib/zip/filesystem.rb +297 -276
  28. data/lib/zip/inflater.rb +23 -34
  29. data/lib/zip/input_stream.rb +130 -82
  30. data/lib/zip/ioextras/abstract_input_stream.rb +36 -22
  31. data/lib/zip/ioextras/abstract_output_stream.rb +4 -6
  32. data/lib/zip/ioextras.rb +4 -6
  33. data/lib/zip/null_compressor.rb +2 -2
  34. data/lib/zip/null_decompressor.rb +4 -12
  35. data/lib/zip/null_input_stream.rb +2 -1
  36. data/lib/zip/output_stream.rb +75 -45
  37. data/lib/zip/pass_thru_compressor.rb +6 -6
  38. data/lib/zip/pass_thru_decompressor.rb +14 -24
  39. data/lib/zip/streamable_directory.rb +3 -3
  40. data/lib/zip/streamable_stream.rb +21 -16
  41. data/lib/zip/version.rb +1 -1
  42. data/lib/zip.rb +42 -3
  43. data/samples/example.rb +30 -40
  44. data/samples/example_filesystem.rb +16 -18
  45. data/samples/example_recursive.rb +33 -28
  46. data/samples/gtk_ruby_zip.rb +84 -0
  47. data/samples/qtzip.rb +25 -34
  48. data/samples/write_simple.rb +10 -13
  49. data/samples/zipfind.rb +38 -45
  50. metadata +129 -28
  51. data/NEWS +0 -182
  52. data/samples/gtkRubyzip.rb +0 -86
data/lib/zip/inflater.rb CHANGED
@@ -1,63 +1,52 @@
1
1
  module Zip
2
2
  class Inflater < Decompressor #:nodoc:all
3
- def initialize(input_stream)
3
+ def initialize(*args)
4
4
  super
5
- @zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
6
- @output_buffer = ''
7
- @has_returned_empty_string = false
8
- end
9
5
 
10
- def sysread(number_of_bytes = nil, buf = nil)
11
- readEverything = number_of_bytes.nil?
12
- while (readEverything || @output_buffer.bytesize < number_of_bytes)
13
- break if internal_input_finished?
14
- @output_buffer << internal_produce_input(buf)
15
- end
16
- return value_when_finished if @output_buffer.bytesize == 0 && input_finished?
17
- end_index = number_of_bytes.nil? ? @output_buffer.bytesize : number_of_bytes
18
- @output_buffer.slice!(0...end_index)
6
+ @buffer = ''.b
7
+ @zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
19
8
  end
20
9
 
21
- def produce_input
22
- if (@output_buffer.empty?)
23
- internal_produce_input
24
- else
25
- @output_buffer.slice!(0...(@output_buffer.length))
10
+ def read(length = nil, outbuf = ''.b)
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
26
17
  end
18
+
19
+ outbuf.replace(@buffer.slice!(0...(length || @buffer.bytesize)))
27
20
  end
28
21
 
29
- # to be used with produce_input, not read (as read may still have more data cached)
30
- # is data cached anywhere other than @outputBuffer? the comment above may be wrong
31
- def input_finished?
32
- @output_buffer.empty? && internal_input_finished?
22
+ def eof
23
+ @buffer.empty? && input_finished?
33
24
  end
34
25
 
35
- alias :eof :input_finished?
36
- alias :eof? :input_finished?
26
+ alias eof? eof
37
27
 
38
28
  private
39
29
 
40
- def internal_produce_input(buf = nil)
30
+ def produce_input
41
31
  retried = 0
42
32
  begin
43
- @zlib_inflater.inflate(@input_stream.read(Decompressor::CHUNK_SIZE, buf))
33
+ @zlib_inflater.inflate(input_stream.read(Decompressor::CHUNK_SIZE))
44
34
  rescue Zlib::BufError
45
35
  raise if retried >= 5 # how many times should we retry?
36
+
46
37
  retried += 1
47
38
  retry
48
39
  end
40
+ rescue Zlib::Error
41
+ raise(::Zip::DecompressionError, 'zlib error while inflating')
49
42
  end
50
43
 
51
- def internal_input_finished?
44
+ def input_finished?
52
45
  @zlib_inflater.finished?
53
46
  end
54
-
55
- def value_when_finished # mimic behaviour of ruby File object.
56
- return if @has_returned_empty_string
57
- @has_returned_empty_string = true
58
- ''
59
- end
60
47
  end
48
+
49
+ ::Zip::Decompressor.register(::Zip::COMPRESSION_METHOD_DEFLATE, ::Zip::Inflater)
61
50
  end
62
51
 
63
52
  # Copyright (C) 2002, 2003 Thomas Sondergaard
@@ -1,141 +1,189 @@
1
1
  module Zip
2
- # ZipInputStream is the basic class for reading zip entries in a
3
- # zip file. It is possible to create a ZipInputStream object directly,
4
- # passing the zip file name to the constructor, but more often than not
5
- # the ZipInputStream will be obtained from a ZipFile (perhaps using the
6
- # ZipFileSystem interface) object for a particular entry in the zip
2
+ # InputStream is the basic class for reading zip entries in a
3
+ # zip file. It is possible to create a InputStream object directly,
4
+ # passing the zip file name to the constructor, but more often than not
5
+ # the InputStream will be obtained from a File (perhaps using the
6
+ # ZipFileSystem interface) object for a particular entry in the zip
7
7
  # archive.
8
8
  #
9
- # A ZipInputStream inherits IOExtras::AbstractInputStream in order
10
- # to provide an IO-like interface for reading from a single zip
11
- # entry. Beyond methods for mimicking an IO-object it contains
12
- # the method get_next_entry for iterating through the entries of
13
- # an archive. get_next_entry returns a ZipEntry object that describes
14
- # the zip entry the ZipInputStream is currently reading from.
9
+ # A InputStream inherits IOExtras::AbstractInputStream in order
10
+ # to provide an IO-like interface for reading from a single zip
11
+ # entry. Beyond methods for mimicking an IO-object it contains
12
+ # the method get_next_entry for iterating through the entries of
13
+ # an archive. get_next_entry returns a Entry object that describes
14
+ # the zip entry the InputStream is currently reading from.
15
15
  #
16
- # Example that creates a zip archive with ZipOutputStream and reads it
17
- # back again with a ZipInputStream.
16
+ # Example that creates a zip archive with ZipOutputStream and reads it
17
+ # back again with a InputStream.
18
+ #
19
+ # require 'zip'
20
+ #
21
+ # Zip::OutputStream.open("my.zip") do |io|
18
22
  #
19
- # require 'zip/zip'
20
- #
21
- # Zip::ZipOutputStream::open("my.zip") {
22
- # |io|
23
- #
24
23
  # io.put_next_entry("first_entry.txt")
25
24
  # io.write "Hello world!"
26
- #
25
+ #
27
26
  # io.put_next_entry("adir/first_entry.txt")
28
27
  # io.write "Hello again!"
29
- # }
28
+ # end
29
+ #
30
+ #
31
+ # Zip::InputStream.open("my.zip") do |io|
30
32
  #
31
- #
32
- # Zip::ZipInputStream::open("my.zip") {
33
- # |io|
34
- #
35
33
  # while (entry = io.get_next_entry)
36
34
  # puts "Contents of #{entry.name}: '#{io.read}'"
37
35
  # end
38
- # }
36
+ # end
39
37
  #
40
- # java.util.zip.ZipInputStream is the original inspiration for this
38
+ # java.util.zip.ZipInputStream is the original inspiration for this
41
39
  # class.
42
40
 
43
41
  class InputStream
42
+ CHUNK_SIZE = 32_768
43
+
44
44
  include ::Zip::IOExtras::AbstractInputStream
45
45
 
46
46
  # Opens the indicated zip file. An exception is thrown
47
47
  # if the specified offset in the specified filename is
48
48
  # not a local zip entry header.
49
- def initialize(filename, offset = 0, io = nil)
49
+ #
50
+ # @param context [String||IO||StringIO] file path or IO/StringIO object
51
+ # @param offset [Integer] offset in the IO/StringIO
52
+ def initialize(context, dep_offset = 0, dep_decrypter = nil, offset: 0, decrypter: nil)
50
53
  super()
51
- if (io.nil?)
52
- @archiveIO = ::File.open(filename, "rb")
53
- @archiveIO.seek(offset, IO::SEEK_SET)
54
- else
55
- @archiveIO = io
54
+
55
+ if !dep_offset.zero? || !dep_decrypter.nil?
56
+ Zip.warn_about_v3_api('Zip::InputStream.new')
56
57
  end
57
- @decompressor = NullDecompressor.instance
58
- @currentEntry = nil
59
- end
60
-
61
- def close
62
- @archiveIO.close
63
- end
64
58
 
65
- # Same as #initialize but if a block is passed the opened
66
- # stream is passed to the block and closed when the block
67
- # returns.
68
- def InputStream.open(filename)
69
- return new(filename) unless block_given?
70
-
71
- zio = new(filename)
72
- yield zio
73
- ensure
74
- zio.close if zio
59
+ offset = dep_offset if offset.zero?
60
+ @archive_io = get_io(context, offset)
61
+ @decompressor = ::Zip::NullDecompressor
62
+ @decrypter = decrypter || dep_decrypter || ::Zip::NullDecrypter.new
63
+ @current_entry = nil
75
64
  end
76
65
 
77
- def InputStream.open_buffer(io)
78
- return new('',0,io) unless block_given?
79
- zio = new('',0,io)
80
- yield zio
81
- ensure
82
- zio.close if zio
66
+ def close
67
+ @archive_io.close
83
68
  end
84
69
 
85
- # Returns a ZipEntry object. It is necessary to call this
86
- # method on a newly created ZipInputStream before reading from
87
- # the first entry in the archive. Returns nil when there are
70
+ # Returns a Entry object. It is necessary to call this
71
+ # method on a newly created InputStream before reading from
72
+ # the first entry in the archive. Returns nil when there are
88
73
  # no more entries.
89
-
90
74
  def get_next_entry
91
- @archiveIO.seek(@currentEntry.next_header_offset, IO::SEEK_SET) if @currentEntry
75
+ @archive_io.seek(@current_entry.next_header_offset, IO::SEEK_SET) if @current_entry
92
76
  open_entry
93
77
  end
94
78
 
95
79
  # Rewinds the stream to the beginning of the current entry
96
80
  def rewind
97
- return if @currentEntry.nil?
81
+ return if @current_entry.nil?
82
+
98
83
  @lineno = 0
99
- @pos = 0
100
- @archiveIO.seek(@currentEntry.local_header_offset,
101
- IO::SEEK_SET)
84
+ @pos = 0
85
+ @archive_io.seek(@current_entry.local_header_offset, IO::SEEK_SET)
102
86
  open_entry
103
87
  end
104
88
 
105
89
  # Modeled after IO.sysread
106
- def sysread(numberOfBytes = nil, buf = nil)
107
- @decompressor.sysread(numberOfBytes, buf)
90
+ def sysread(length = nil, outbuf = '')
91
+ @decompressor.read(length, outbuf)
108
92
  end
109
93
 
110
- def eof
111
- @output_buffer.empty? && @decompressor.eof
94
+ class << self
95
+ # Same as #initialize but if a block is passed the opened
96
+ # stream is passed to the block and closed when the block
97
+ # returns.
98
+ def open(filename_or_io, dep_offset = 0, dep_decrypter = nil, offset: 0, decrypter: nil)
99
+ if !dep_offset.zero? || !dep_decrypter.nil?
100
+ Zip.warn_about_v3_api('Zip::InputStream.new')
101
+ end
102
+
103
+ offset = dep_offset if offset.zero?
104
+
105
+ zio = new(filename_or_io, offset: offset, decrypter: decrypter || dep_decrypter)
106
+ return zio unless block_given?
107
+
108
+ begin
109
+ yield zio
110
+ ensure
111
+ zio.close if zio
112
+ end
113
+ end
114
+
115
+ def open_buffer(filename_or_io, offset = 0)
116
+ Zip.warn_about_v3_api('Zip::InputStream.open_buffer')
117
+
118
+ ::Zip::InputStream.open(filename_or_io, offset)
119
+ end
112
120
  end
113
- alias :eof? :eof
114
121
 
115
122
  protected
116
123
 
117
- def open_entry
118
- @currentEntry = Entry.read_local_entry(@archiveIO)
119
- if @currentEntry.nil?
120
- @decompressor = NullDecompressor.instance
121
- elsif @currentEntry.compression_method == Entry::STORED
122
- @decompressor = PassThruDecompressor.new(@archiveIO, @currentEntry.size)
123
- elsif @currentEntry.compression_method == Entry::DEFLATED
124
- @decompressor = Inflater.new(@archiveIO)
124
+ def get_io(io_or_file, offset = 0)
125
+ if io_or_file.respond_to?(:seek)
126
+ io = io_or_file.dup
127
+ io.seek(offset, ::IO::SEEK_SET)
128
+ io
125
129
  else
126
- raise ZipCompressionMethodError,
127
- "Unsupported compression method #{@currentEntry.compression_method}"
130
+ file = ::File.open(io_or_file, 'rb')
131
+ file.seek(offset, ::IO::SEEK_SET)
132
+ file
133
+ end
134
+ end
135
+
136
+ def open_entry
137
+ @current_entry = ::Zip::Entry.read_local_entry(@archive_io)
138
+ if @current_entry && @current_entry.encrypted? && @decrypter.kind_of?(NullEncrypter)
139
+ raise Error, 'password required to decode zip file'
140
+ end
141
+
142
+ if @current_entry && @current_entry.incomplete? && @current_entry.crc == 0 \
143
+ && @current_entry.compressed_size == 0 \
144
+ && @current_entry.size == 0 && !@complete_entry
145
+ raise GPFBit3Error,
146
+ 'General purpose flag Bit 3 is set so not possible to get proper info from local header.' \
147
+ 'Please use ::Zip::File instead of ::Zip::InputStream'
128
148
  end
149
+ @decrypted_io = get_decrypted_io
150
+ @decompressor = get_decompressor
129
151
  flush
130
- return @currentEntry
152
+ @current_entry
153
+ end
154
+
155
+ def get_decrypted_io
156
+ header = @archive_io.read(@decrypter.header_bytesize)
157
+ @decrypter.reset!(header)
158
+
159
+ ::Zip::DecryptedIo.new(@archive_io, @decrypter)
160
+ end
161
+
162
+ def get_decompressor
163
+ return ::Zip::NullDecompressor if @current_entry.nil?
164
+
165
+ decompressed_size =
166
+ if @current_entry.incomplete? && @current_entry.crc == 0 && @current_entry.size == 0 && @complete_entry
167
+ @complete_entry.size
168
+ else
169
+ @current_entry.size
170
+ end
171
+
172
+ decompressor_class = ::Zip::Decompressor.find_by_compression_method(@current_entry.compression_method)
173
+ if decompressor_class.nil?
174
+ raise ::Zip::CompressionMethodError,
175
+ "Unsupported compression method #{@current_entry.compression_method}"
176
+ end
177
+
178
+ decompressor_class.new(@decrypted_io, decompressed_size)
131
179
  end
132
180
 
133
181
  def produce_input
134
- @decompressor.produce_input
182
+ @decompressor.read(CHUNK_SIZE)
135
183
  end
136
184
 
137
185
  def input_finished?
138
- @decompressor.input_finished?
186
+ @decompressor.eof
139
187
  end
140
188
  end
141
189
  end
@@ -11,13 +11,13 @@ module Zip
11
11
  super
12
12
  @lineno = 0
13
13
  @pos = 0
14
- @output_buffer = ''
14
+ @output_buffer = ''.b
15
15
  end
16
16
 
17
17
  attr_accessor :lineno
18
18
  attr_reader :pos
19
19
 
20
- def read(number_of_bytes = nil, buf = nil)
20
+ def read(number_of_bytes = nil, buf = ''.b)
21
21
  tbuf = if @output_buffer.bytesize > 0
22
22
  if number_of_bytes <= @output_buffer.bytesize
23
23
  @output_buffer.slice!(0, number_of_bytes)
@@ -26,16 +26,20 @@ module Zip
26
26
  rbuf = sysread(number_of_bytes, buf)
27
27
  out = @output_buffer
28
28
  out << rbuf if rbuf
29
- @output_buffer = ''
29
+ @output_buffer = ''.b
30
30
  out
31
31
  end
32
32
  else
33
33
  sysread(number_of_bytes, buf)
34
34
  end
35
35
 
36
- @pos += tbuf.length
36
+ if tbuf.nil? || tbuf.empty?
37
+ return nil if number_of_bytes
38
+
39
+ return ''
40
+ end
37
41
 
38
- return nil unless tbuf
42
+ @pos += tbuf.length
39
43
 
40
44
  if buf
41
45
  buf.replace(tbuf)
@@ -45,13 +49,13 @@ module Zip
45
49
  buf
46
50
  end
47
51
 
48
- def readlines(a_sep_string = $/)
52
+ def readlines(a_sep_string = $INPUT_RECORD_SEPARATOR)
49
53
  ret_val = []
50
54
  each_line(a_sep_string) { |line| ret_val << line }
51
55
  ret_val
52
56
  end
53
57
 
54
- def gets(a_sep_string = $/, number_of_bytes = nil)
58
+ def gets(a_sep_string = $INPUT_RECORD_SEPARATOR, number_of_bytes = nil)
55
59
  @lineno = @lineno.next
56
60
 
57
61
  if number_of_bytes.respond_to?(:to_int)
@@ -59,50 +63,60 @@ module Zip
59
63
  a_sep_string = a_sep_string.to_str if a_sep_string
60
64
  elsif a_sep_string.respond_to?(:to_int)
61
65
  number_of_bytes = a_sep_string.to_int
62
- a_sep_string = $/
66
+ a_sep_string = $INPUT_RECORD_SEPARATOR
63
67
  else
64
68
  number_of_bytes = nil
65
69
  a_sep_string = a_sep_string.to_str if a_sep_string
66
70
  end
67
71
 
68
72
  return read(number_of_bytes) if a_sep_string.nil?
69
- a_sep_string = "#{$/}#{$/}" if a_sep_string.empty?
73
+
74
+ a_sep_string = "#{$INPUT_RECORD_SEPARATOR}#{$INPUT_RECORD_SEPARATOR}" if a_sep_string.empty?
70
75
 
71
76
  buffer_index = 0
72
77
  over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
73
78
  while (match_index = @output_buffer.index(a_sep_string, buffer_index)).nil? && !over_limit
74
79
  buffer_index = [buffer_index, @output_buffer.bytesize - a_sep_string.bytesize].max
75
- if input_finished?
76
- return @output_buffer.empty? ? nil : flush
77
- end
80
+ return @output_buffer.empty? ? nil : flush if input_finished?
81
+
78
82
  @output_buffer << produce_input
79
83
  over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
80
84
  end
81
85
  sep_index = [match_index + a_sep_string.bytesize, number_of_bytes || @output_buffer.bytesize].min
82
- @pos += sep_index
83
- return @output_buffer.slice!(0...sep_index)
86
+ @pos += sep_index
87
+ @output_buffer.slice!(0...sep_index)
88
+ end
89
+
90
+ def ungetc(byte)
91
+ @output_buffer = byte.chr + @output_buffer
84
92
  end
85
93
 
86
94
  def flush
87
95
  ret_val = @output_buffer
88
- @output_buffer = ''
96
+ @output_buffer = ''.b
89
97
  ret_val
90
98
  end
91
99
 
92
- def readline(a_sep_string = $/)
100
+ def readline(a_sep_string = $INPUT_RECORD_SEPARATOR)
93
101
  ret_val = gets(a_sep_string)
94
102
  raise EOFError unless ret_val
103
+
95
104
  ret_val
96
105
  end
97
106
 
98
- def each_line(a_sep_string = $/)
99
- while true
100
- yield readline(a_sep_string)
101
- end
107
+ def each_line(a_sep_string = $INPUT_RECORD_SEPARATOR)
108
+ loop { yield readline(a_sep_string) }
102
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?
103
117
  end
104
118
 
105
- alias_method :each, :each_line
119
+ alias eof? eof
106
120
  end
107
121
  end
108
- end
122
+ end
@@ -10,23 +10,22 @@ module Zip
10
10
  data.to_s.bytesize
11
11
  end
12
12
 
13
-
14
13
  def print(*params)
15
- self << params.join($,) << $\.to_s
14
+ self << params.join($OUTPUT_FIELD_SEPARATOR) << $OUTPUT_RECORD_SEPARATOR.to_s
16
15
  end
17
16
 
18
17
  def printf(a_format_string, *params)
19
- self << sprintf(a_format_string, *params)
18
+ self << format(a_format_string, *params)
20
19
  end
21
20
 
22
21
  def putc(an_object)
23
22
  self << case an_object
24
- when Fixnum
23
+ when Integer
25
24
  an_object.chr
26
25
  when String
27
26
  an_object
28
27
  else
29
- raise TypeError, 'putc: Only Fixnum and String supported'
28
+ raise TypeError, 'putc: Only Integer and String supported'
30
29
  end
31
30
  an_object
32
31
  end
@@ -39,7 +38,6 @@ module Zip
39
38
  self << "\n" unless val[-1, 1] == "\n"
40
39
  end
41
40
  end
42
-
43
41
  end
44
42
  end
45
43
  end
data/lib/zip/ioextras.rb CHANGED
@@ -1,20 +1,19 @@
1
1
  module Zip
2
2
  module IOExtras #:nodoc:
3
-
4
- CHUNK_SIZE = 131072
3
+ CHUNK_SIZE = 131_072
5
4
 
6
5
  RANGE_ALL = 0..-1
7
6
 
8
7
  class << self
9
8
  def copy_stream(ostream, istream)
10
- ostream.write(istream.read(CHUNK_SIZE, '')) until istream.eof?
9
+ ostream.write(istream.read(CHUNK_SIZE, ''.b)) until istream.eof?
11
10
  end
12
11
 
13
12
  def copy_stream_n(ostream, istream, nbytes)
14
13
  toread = nbytes
15
14
  while toread > 0 && !istream.eof?
16
15
  tr = toread > CHUNK_SIZE ? CHUNK_SIZE : toread
17
- ostream.write(istream.read(tr, ''))
16
+ ostream.write(istream.read(tr, ''.b))
18
17
  toread -= tr
19
18
  end
20
19
  end
@@ -26,8 +25,7 @@ module Zip
26
25
  object == IO || super
27
26
  end
28
27
  end
29
-
30
- end # IOExtras namespace module
28
+ end
31
29
  end
32
30
 
33
31
  require 'zip/ioextras/abstract_input_stream'
@@ -2,8 +2,8 @@ module Zip
2
2
  class NullCompressor < Compressor #:nodoc:all
3
3
  include Singleton
4
4
 
5
- def <<(data)
6
- raise IOError, "closed stream"
5
+ def <<(_data)
6
+ raise IOError, 'closed stream'
7
7
  end
8
8
 
9
9
  attr_reader :size, :compressed_size
@@ -1,24 +1,16 @@
1
1
  module Zip
2
- class NullDecompressor #:nodoc:all
3
- include Singleton
2
+ module NullDecompressor #:nodoc:all
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
20
12
 
21
- alias :eof? :eof
13
+ alias eof? eof
22
14
  end
23
15
  end
24
16
 
@@ -1,5 +1,6 @@
1
1
  module Zip
2
- class NullInputStream < NullDecompressor #:nodoc:all
2
+ module NullInputStream #:nodoc:all
3
+ include ::Zip::NullDecompressor
3
4
  include ::Zip::IOExtras::AbstractInputStream
4
5
  end
5
6
  end