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.
- checksums.yaml +6 -14
- data/README.md +231 -46
- data/Rakefile +13 -5
- data/TODO +0 -1
- data/lib/zip/central_directory.rb +64 -29
- data/lib/zip/compressor.rb +1 -2
- data/lib/zip/constants.rb +59 -5
- data/lib/zip/crypto/decrypted_io.rb +40 -0
- data/lib/zip/crypto/encryption.rb +11 -0
- data/lib/zip/crypto/null_encryption.rb +43 -0
- data/lib/zip/crypto/traditional_encryption.rb +99 -0
- data/lib/zip/decompressor.rb +22 -4
- data/lib/zip/deflater.rb +11 -6
- data/lib/zip/dos_time.rb +27 -16
- data/lib/zip/entry.rb +299 -163
- data/lib/zip/entry_set.rb +22 -20
- data/lib/zip/errors.rb +17 -6
- data/lib/zip/extra_field/generic.rb +15 -14
- data/lib/zip/extra_field/ntfs.rb +94 -0
- data/lib/zip/extra_field/old_unix.rb +46 -0
- data/lib/zip/extra_field/universal_time.rb +46 -16
- data/lib/zip/extra_field/unix.rb +10 -9
- data/lib/zip/extra_field/zip64.rb +46 -6
- data/lib/zip/extra_field/zip64_placeholder.rb +15 -0
- data/lib/zip/extra_field.rb +32 -18
- data/lib/zip/file.rb +260 -160
- data/lib/zip/filesystem.rb +297 -276
- data/lib/zip/inflater.rb +23 -34
- data/lib/zip/input_stream.rb +130 -82
- data/lib/zip/ioextras/abstract_input_stream.rb +36 -22
- data/lib/zip/ioextras/abstract_output_stream.rb +4 -6
- data/lib/zip/ioextras.rb +4 -6
- data/lib/zip/null_compressor.rb +2 -2
- data/lib/zip/null_decompressor.rb +4 -12
- data/lib/zip/null_input_stream.rb +2 -1
- data/lib/zip/output_stream.rb +75 -45
- data/lib/zip/pass_thru_compressor.rb +6 -6
- data/lib/zip/pass_thru_decompressor.rb +14 -24
- data/lib/zip/streamable_directory.rb +3 -3
- data/lib/zip/streamable_stream.rb +21 -16
- data/lib/zip/version.rb +1 -1
- data/lib/zip.rb +42 -3
- data/samples/example.rb +30 -40
- data/samples/example_filesystem.rb +16 -18
- data/samples/example_recursive.rb +33 -28
- data/samples/gtk_ruby_zip.rb +84 -0
- data/samples/qtzip.rb +25 -34
- data/samples/write_simple.rb +10 -13
- data/samples/zipfind.rb +38 -45
- metadata +129 -28
- data/NEWS +0 -182
- 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(
|
|
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
|
-
|
|
11
|
-
|
|
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
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
30
|
-
|
|
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
|
|
36
|
-
alias :eof? :input_finished?
|
|
26
|
+
alias eof? eof
|
|
37
27
|
|
|
38
28
|
private
|
|
39
29
|
|
|
40
|
-
def
|
|
30
|
+
def produce_input
|
|
41
31
|
retried = 0
|
|
42
32
|
begin
|
|
43
|
-
@zlib_inflater.inflate(
|
|
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
|
|
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
|
data/lib/zip/input_stream.rb
CHANGED
|
@@ -1,141 +1,189 @@
|
|
|
1
1
|
module Zip
|
|
2
|
-
#
|
|
3
|
-
# zip file. It is possible to create a
|
|
4
|
-
# passing the zip file name to the constructor, but more often than not
|
|
5
|
-
# 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
|
|
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
|
|
14
|
-
# the zip entry the
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
|
78
|
-
|
|
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
|
|
86
|
-
# method on a newly created
|
|
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
|
-
@
|
|
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 @
|
|
81
|
+
return if @current_entry.nil?
|
|
82
|
+
|
|
98
83
|
@lineno = 0
|
|
99
|
-
@pos
|
|
100
|
-
@
|
|
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(
|
|
107
|
-
@decompressor.
|
|
90
|
+
def sysread(length = nil, outbuf = '')
|
|
91
|
+
@decompressor.read(length, outbuf)
|
|
108
92
|
end
|
|
109
93
|
|
|
110
|
-
|
|
111
|
-
|
|
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
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
|
|
127
|
-
|
|
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
|
-
|
|
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.
|
|
182
|
+
@decompressor.read(CHUNK_SIZE)
|
|
135
183
|
end
|
|
136
184
|
|
|
137
185
|
def input_finished?
|
|
138
|
-
@decompressor.
|
|
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 =
|
|
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
|
-
|
|
36
|
+
if tbuf.nil? || tbuf.empty?
|
|
37
|
+
return nil if number_of_bytes
|
|
38
|
+
|
|
39
|
+
return ''
|
|
40
|
+
end
|
|
37
41
|
|
|
38
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
83
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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 <<
|
|
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
|
|
23
|
+
when Integer
|
|
25
24
|
an_object.chr
|
|
26
25
|
when String
|
|
27
26
|
an_object
|
|
28
27
|
else
|
|
29
|
-
raise TypeError, 'putc: Only
|
|
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'
|
data/lib/zip/null_compressor.rb
CHANGED
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
module Zip
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
module NullDecompressor #:nodoc:all
|
|
3
|
+
module_function
|
|
4
4
|
|
|
5
|
-
def
|
|
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
|
|
13
|
+
alias eof? eof
|
|
22
14
|
end
|
|
23
15
|
end
|
|
24
16
|
|