rubyzip 0.9.9 → 1.3.0
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 +7 -0
- data/README.md +284 -41
- data/Rakefile +11 -6
- data/TODO +0 -1
- data/lib/zip/central_directory.rb +208 -0
- data/lib/zip/compressor.rb +1 -2
- data/lib/zip/constants.rb +59 -7
- 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 +4 -4
- data/lib/zip/deflater.rb +17 -13
- data/lib/zip/dos_time.rb +13 -14
- data/lib/zip/entry.rb +700 -0
- data/lib/zip/entry_set.rb +86 -0
- data/lib/zip/errors.rb +18 -0
- data/lib/zip/extra_field/generic.rb +43 -0
- data/lib/zip/extra_field/ntfs.rb +90 -0
- data/lib/zip/extra_field/old_unix.rb +44 -0
- data/lib/zip/extra_field/universal_time.rb +47 -0
- data/lib/zip/extra_field/unix.rb +37 -0
- data/lib/zip/extra_field/zip64.rb +68 -0
- data/lib/zip/extra_field/zip64_placeholder.rb +15 -0
- data/lib/zip/extra_field.rb +101 -0
- data/lib/zip/file.rb +443 -0
- data/lib/zip/{zipfilesystem.rb → filesystem.rb} +162 -157
- data/lib/zip/inflater.rb +29 -28
- data/lib/zip/input_stream.rb +173 -0
- data/lib/zip/ioextras/abstract_input_stream.rb +111 -0
- data/lib/zip/ioextras/abstract_output_stream.rb +43 -0
- data/lib/zip/ioextras.rb +21 -149
- data/lib/zip/null_compressor.rb +2 -2
- data/lib/zip/null_decompressor.rb +8 -6
- data/lib/zip/null_input_stream.rb +3 -2
- data/lib/zip/output_stream.rb +189 -0
- data/lib/zip/pass_thru_compressor.rb +6 -6
- data/lib/zip/pass_thru_decompressor.rb +19 -19
- data/lib/zip/{zip_streamable_directory.rb → streamable_directory.rb} +3 -3
- data/lib/zip/streamable_stream.rb +56 -0
- data/lib/zip/version.rb +3 -0
- data/lib/zip.rb +71 -0
- data/samples/example.rb +44 -32
- data/samples/example_filesystem.rb +16 -18
- data/samples/example_recursive.rb +33 -28
- data/samples/{gtkRubyzip.rb → gtk_ruby_zip.rb} +26 -28
- data/samples/qtzip.rb +22 -31
- data/samples/write_simple.rb +12 -13
- data/samples/zipfind.rb +31 -39
- data/test/basic_zip_file_test.rb +60 -0
- data/test/case_sensitivity_test.rb +69 -0
- data/test/central_directory_entry_test.rb +69 -0
- data/test/central_directory_test.rb +100 -0
- data/test/crypto/null_encryption_test.rb +57 -0
- data/test/crypto/traditional_encryption_test.rb +80 -0
- data/test/data/WarnInvalidDate.zip +0 -0
- data/test/data/file1.txt +46 -0
- data/test/data/file1.txt.deflatedData +0 -0
- data/test/data/file2.txt +1504 -0
- data/test/data/globTest/foo/bar/baz/foo.txt +0 -0
- data/test/data/globTest/foo.txt +0 -0
- data/test/data/globTest/food.txt +0 -0
- data/test/data/globTest.zip +0 -0
- data/test/data/gpbit3stored.zip +0 -0
- data/test/data/mimetype +1 -0
- data/test/data/notzippedruby.rb +7 -0
- data/test/data/ntfs.zip +0 -0
- data/test/data/oddExtraField.zip +0 -0
- data/test/data/path_traversal/Makefile +10 -0
- data/test/data/path_traversal/jwilk/README.md +5 -0
- data/test/data/path_traversal/jwilk/absolute1.zip +0 -0
- data/test/data/path_traversal/jwilk/absolute2.zip +0 -0
- data/test/data/path_traversal/jwilk/dirsymlink.zip +0 -0
- data/test/data/path_traversal/jwilk/dirsymlink2a.zip +0 -0
- data/test/data/path_traversal/jwilk/dirsymlink2b.zip +0 -0
- data/test/data/path_traversal/jwilk/relative0.zip +0 -0
- data/test/data/path_traversal/jwilk/relative2.zip +0 -0
- data/test/data/path_traversal/jwilk/symlink.zip +0 -0
- data/test/data/path_traversal/relative1.zip +0 -0
- data/test/data/path_traversal/tilde.zip +0 -0
- data/test/data/path_traversal/tuzovakaoff/README.md +3 -0
- data/test/data/path_traversal/tuzovakaoff/absolutepath.zip +0 -0
- data/test/data/path_traversal/tuzovakaoff/symlink.zip +0 -0
- data/test/data/rubycode.zip +0 -0
- data/test/data/rubycode2.zip +0 -0
- data/test/data/test.xls +0 -0
- data/test/data/testDirectory.bin +0 -0
- data/test/data/zip64-sample.zip +0 -0
- data/test/data/zipWithDirs.zip +0 -0
- data/test/data/zipWithEncryption.zip +0 -0
- data/test/deflater_test.rb +65 -0
- data/test/encryption_test.rb +42 -0
- data/test/entry_set_test.rb +163 -0
- data/test/entry_test.rb +154 -0
- data/test/errors_test.rb +35 -0
- data/test/extra_field_test.rb +76 -0
- data/test/file_extract_directory_test.rb +54 -0
- data/test/file_extract_test.rb +145 -0
- data/test/file_permissions_test.rb +65 -0
- data/test/file_split_test.rb +57 -0
- data/test/file_test.rb +666 -0
- data/test/filesystem/dir_iterator_test.rb +58 -0
- data/test/filesystem/directory_test.rb +139 -0
- data/test/filesystem/file_mutating_test.rb +87 -0
- data/test/filesystem/file_nonmutating_test.rb +508 -0
- data/test/filesystem/file_stat_test.rb +64 -0
- data/test/gentestfiles.rb +126 -0
- data/test/inflater_test.rb +14 -0
- data/test/input_stream_test.rb +182 -0
- data/test/ioextras/abstract_input_stream_test.rb +102 -0
- data/test/ioextras/abstract_output_stream_test.rb +106 -0
- data/test/ioextras/fake_io_test.rb +18 -0
- data/test/local_entry_test.rb +154 -0
- data/test/output_stream_test.rb +128 -0
- data/test/pass_thru_compressor_test.rb +30 -0
- data/test/pass_thru_decompressor_test.rb +14 -0
- data/test/path_traversal_test.rb +141 -0
- data/test/samples/example_recursive_test.rb +37 -0
- data/test/settings_test.rb +95 -0
- data/test/test_helper.rb +234 -0
- data/test/unicode_file_names_and_comments_test.rb +62 -0
- data/test/zip64_full_test.rb +51 -0
- data/test/zip64_support_test.rb +14 -0
- metadata +274 -41
- data/NEWS +0 -172
- data/lib/zip/settings.rb +0 -10
- data/lib/zip/tempfile_bugfixed.rb +0 -195
- data/lib/zip/zip.rb +0 -56
- data/lib/zip/zip_central_directory.rb +0 -135
- data/lib/zip/zip_entry.rb +0 -638
- data/lib/zip/zip_entry_set.rb +0 -77
- data/lib/zip/zip_extra_field.rb +0 -213
- data/lib/zip/zip_file.rb +0 -340
- data/lib/zip/zip_input_stream.rb +0 -144
- data/lib/zip/zip_output_stream.rb +0 -173
- data/lib/zip/zip_streamable_stream.rb +0 -47
data/lib/zip/inflater.rb
CHANGED
@@ -1,61 +1,62 @@
|
|
1
1
|
module Zip
|
2
|
-
class Inflater < Decompressor
|
3
|
-
def initialize(
|
4
|
-
super
|
5
|
-
@
|
6
|
-
@
|
7
|
-
@
|
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
|
8
9
|
end
|
9
10
|
|
10
|
-
def sysread(
|
11
|
-
readEverything =
|
12
|
-
while
|
11
|
+
def sysread(number_of_bytes = nil, buf = '')
|
12
|
+
readEverything = number_of_bytes.nil?
|
13
|
+
while readEverything || @output_buffer.bytesize < number_of_bytes
|
13
14
|
break if internal_input_finished?
|
14
|
-
@
|
15
|
+
@output_buffer << internal_produce_input(buf)
|
15
16
|
end
|
16
|
-
return value_when_finished if @
|
17
|
-
|
18
|
-
|
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)
|
19
20
|
end
|
20
21
|
|
21
22
|
def produce_input
|
22
|
-
if
|
23
|
-
|
23
|
+
if @output_buffer.empty?
|
24
|
+
internal_produce_input
|
24
25
|
else
|
25
|
-
|
26
|
+
@output_buffer.slice!(0...(@output_buffer.length))
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
30
|
# to be used with produce_input, not read (as read may still have more data cached)
|
30
31
|
# is data cached anywhere other than @outputBuffer? the comment above may be wrong
|
31
32
|
def input_finished?
|
32
|
-
@
|
33
|
+
@output_buffer.empty? && internal_input_finished?
|
33
34
|
end
|
34
|
-
|
35
|
-
alias :eof
|
35
|
+
|
36
|
+
alias :eof input_finished?
|
37
|
+
alias :eof? input_finished?
|
36
38
|
|
37
39
|
private
|
38
40
|
|
39
|
-
def internal_produce_input(buf =
|
41
|
+
def internal_produce_input(buf = '')
|
40
42
|
retried = 0
|
41
43
|
begin
|
42
|
-
@
|
44
|
+
@zlib_inflater.inflate(@decrypter.decrypt(@input_stream.read(Decompressor::CHUNK_SIZE, buf)))
|
43
45
|
rescue Zlib::BufError
|
44
|
-
raise if
|
46
|
+
raise if retried >= 5 # how many times should we retry?
|
45
47
|
retried += 1
|
46
48
|
retry
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
50
52
|
def internal_input_finished?
|
51
|
-
@
|
53
|
+
@zlib_inflater.finished?
|
52
54
|
end
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
return ""
|
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
|
+
''
|
59
60
|
end
|
60
61
|
end
|
61
62
|
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
module 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
|
+
# archive.
|
8
|
+
#
|
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
|
+
#
|
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|
|
22
|
+
#
|
23
|
+
# io.put_next_entry("first_entry.txt")
|
24
|
+
# io.write "Hello world!"
|
25
|
+
#
|
26
|
+
# io.put_next_entry("adir/first_entry.txt")
|
27
|
+
# io.write "Hello again!"
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
#
|
31
|
+
# Zip::InputStream.open("my.zip") do |io|
|
32
|
+
#
|
33
|
+
# while (entry = io.get_next_entry)
|
34
|
+
# puts "Contents of #{entry.name}: '#{io.read}'"
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# java.util.zip.ZipInputStream is the original inspiration for this
|
39
|
+
# class.
|
40
|
+
|
41
|
+
class InputStream
|
42
|
+
include ::Zip::IOExtras::AbstractInputStream
|
43
|
+
|
44
|
+
# Opens the indicated zip file. An exception is thrown
|
45
|
+
# if the specified offset in the specified filename is
|
46
|
+
# not a local zip entry header.
|
47
|
+
#
|
48
|
+
# @param context [String||IO||StringIO] file path or IO/StringIO object
|
49
|
+
# @param offset [Integer] offset in the IO/StringIO
|
50
|
+
def initialize(context, offset = 0, decrypter = nil)
|
51
|
+
super()
|
52
|
+
@archive_io = get_io(context, offset)
|
53
|
+
@decompressor = ::Zip::NullDecompressor
|
54
|
+
@decrypter = decrypter || ::Zip::NullDecrypter.new
|
55
|
+
@current_entry = nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def close
|
59
|
+
@archive_io.close
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns a Entry object. It is necessary to call this
|
63
|
+
# method on a newly created InputStream before reading from
|
64
|
+
# the first entry in the archive. Returns nil when there are
|
65
|
+
# no more entries.
|
66
|
+
def get_next_entry
|
67
|
+
@archive_io.seek(@current_entry.next_header_offset, IO::SEEK_SET) if @current_entry
|
68
|
+
open_entry
|
69
|
+
end
|
70
|
+
|
71
|
+
# Rewinds the stream to the beginning of the current entry
|
72
|
+
def rewind
|
73
|
+
return if @current_entry.nil?
|
74
|
+
@lineno = 0
|
75
|
+
@pos = 0
|
76
|
+
@archive_io.seek(@current_entry.local_header_offset, IO::SEEK_SET)
|
77
|
+
open_entry
|
78
|
+
end
|
79
|
+
|
80
|
+
# 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
|
87
|
+
end
|
88
|
+
|
89
|
+
alias :eof? eof
|
90
|
+
|
91
|
+
class << self
|
92
|
+
# Same as #initialize but if a block is passed the opened
|
93
|
+
# stream is passed to the block and closed when the block
|
94
|
+
# returns.
|
95
|
+
def open(filename_or_io, offset = 0, decrypter = nil)
|
96
|
+
zio = new(filename_or_io, offset, decrypter)
|
97
|
+
return zio unless block_given?
|
98
|
+
begin
|
99
|
+
yield zio
|
100
|
+
ensure
|
101
|
+
zio.close if zio
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def open_buffer(filename_or_io, offset = 0)
|
106
|
+
puts 'open_buffer is deprecated!!! Use open instead!'
|
107
|
+
open(filename_or_io, offset)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
protected
|
112
|
+
|
113
|
+
def get_io(io_or_file, offset = 0)
|
114
|
+
if io_or_file.respond_to?(:seek)
|
115
|
+
io = io_or_file.dup
|
116
|
+
io.seek(offset, ::IO::SEEK_SET)
|
117
|
+
io
|
118
|
+
else
|
119
|
+
file = ::File.open(io_or_file, 'rb')
|
120
|
+
file.seek(offset, ::IO::SEEK_SET)
|
121
|
+
file
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def open_entry
|
126
|
+
@current_entry = ::Zip::Entry.read_local_entry(@archive_io)
|
127
|
+
if @current_entry && @current_entry.gp_flags & 1 == 1 && @decrypter.is_a?(NullEncrypter)
|
128
|
+
raise Error, 'password required to decode zip file'
|
129
|
+
end
|
130
|
+
if @current_entry && @current_entry.gp_flags & 8 == 8 && @current_entry.crc == 0 \
|
131
|
+
&& @current_entry.compressed_size == 0 \
|
132
|
+
&& @current_entry.size == 0 && !@complete_entry
|
133
|
+
raise GPFBit3Error,
|
134
|
+
'General purpose flag Bit 3 is set so not possible to get proper info from local header.' \
|
135
|
+
'Please use ::Zip::File instead of ::Zip::InputStream'
|
136
|
+
end
|
137
|
+
@decompressor = get_decompressor
|
138
|
+
flush
|
139
|
+
@current_entry
|
140
|
+
end
|
141
|
+
|
142
|
+
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)
|
148
|
+
else
|
149
|
+
::Zip::PassThruDecompressor.new(@archive_io, @current_entry.size)
|
150
|
+
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
|
156
|
+
raise ::Zip::CompressionMethodError,
|
157
|
+
"Unsupported compression method #{@current_entry.compression_method}"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def produce_input
|
162
|
+
@decompressor.produce_input
|
163
|
+
end
|
164
|
+
|
165
|
+
def input_finished?
|
166
|
+
@decompressor.input_finished?
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
172
|
+
# rubyzip is free software; you can redistribute it and/or
|
173
|
+
# modify it under the terms of the ruby license.
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Zip
|
2
|
+
module IOExtras
|
3
|
+
# Implements many of the convenience methods of IO
|
4
|
+
# such as gets, getc, readline and readlines
|
5
|
+
# depends on: input_finished?, produce_input and read
|
6
|
+
module AbstractInputStream
|
7
|
+
include Enumerable
|
8
|
+
include FakeIO
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
super
|
12
|
+
@lineno = 0
|
13
|
+
@pos = 0
|
14
|
+
@output_buffer = ''
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_accessor :lineno
|
18
|
+
attr_reader :pos
|
19
|
+
|
20
|
+
def read(number_of_bytes = nil, buf = '')
|
21
|
+
tbuf = if @output_buffer.bytesize > 0
|
22
|
+
if number_of_bytes <= @output_buffer.bytesize
|
23
|
+
@output_buffer.slice!(0, number_of_bytes)
|
24
|
+
else
|
25
|
+
number_of_bytes -= @output_buffer.bytesize if number_of_bytes
|
26
|
+
rbuf = sysread(number_of_bytes, buf)
|
27
|
+
out = @output_buffer
|
28
|
+
out << rbuf if rbuf
|
29
|
+
@output_buffer = ''
|
30
|
+
out
|
31
|
+
end
|
32
|
+
else
|
33
|
+
sysread(number_of_bytes, buf)
|
34
|
+
end
|
35
|
+
|
36
|
+
if tbuf.nil? || tbuf.empty?
|
37
|
+
return nil if number_of_bytes
|
38
|
+
return ''
|
39
|
+
end
|
40
|
+
|
41
|
+
@pos += tbuf.length
|
42
|
+
|
43
|
+
if buf
|
44
|
+
buf.replace(tbuf)
|
45
|
+
else
|
46
|
+
buf = tbuf
|
47
|
+
end
|
48
|
+
buf
|
49
|
+
end
|
50
|
+
|
51
|
+
def readlines(a_sep_string = $/)
|
52
|
+
ret_val = []
|
53
|
+
each_line(a_sep_string) { |line| ret_val << line }
|
54
|
+
ret_val
|
55
|
+
end
|
56
|
+
|
57
|
+
def gets(a_sep_string = $/, number_of_bytes = nil)
|
58
|
+
@lineno = @lineno.next
|
59
|
+
|
60
|
+
if number_of_bytes.respond_to?(:to_int)
|
61
|
+
number_of_bytes = number_of_bytes.to_int
|
62
|
+
a_sep_string = a_sep_string.to_str if a_sep_string
|
63
|
+
elsif a_sep_string.respond_to?(:to_int)
|
64
|
+
number_of_bytes = a_sep_string.to_int
|
65
|
+
a_sep_string = $/
|
66
|
+
else
|
67
|
+
number_of_bytes = nil
|
68
|
+
a_sep_string = a_sep_string.to_str if a_sep_string
|
69
|
+
end
|
70
|
+
|
71
|
+
return read(number_of_bytes) if a_sep_string.nil?
|
72
|
+
a_sep_string = "#{$/}#{$/}" if a_sep_string.empty?
|
73
|
+
|
74
|
+
buffer_index = 0
|
75
|
+
over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
|
76
|
+
while (match_index = @output_buffer.index(a_sep_string, buffer_index)).nil? && !over_limit
|
77
|
+
buffer_index = [buffer_index, @output_buffer.bytesize - a_sep_string.bytesize].max
|
78
|
+
return @output_buffer.empty? ? nil : flush if input_finished?
|
79
|
+
@output_buffer << produce_input
|
80
|
+
over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
|
81
|
+
end
|
82
|
+
sep_index = [match_index + a_sep_string.bytesize, number_of_bytes || @output_buffer.bytesize].min
|
83
|
+
@pos += sep_index
|
84
|
+
@output_buffer.slice!(0...sep_index)
|
85
|
+
end
|
86
|
+
|
87
|
+
def ungetc(byte)
|
88
|
+
@output_buffer = byte.chr + @output_buffer
|
89
|
+
end
|
90
|
+
|
91
|
+
def flush
|
92
|
+
ret_val = @output_buffer
|
93
|
+
@output_buffer = ''
|
94
|
+
ret_val
|
95
|
+
end
|
96
|
+
|
97
|
+
def readline(a_sep_string = $/)
|
98
|
+
ret_val = gets(a_sep_string)
|
99
|
+
raise EOFError unless ret_val
|
100
|
+
ret_val
|
101
|
+
end
|
102
|
+
|
103
|
+
def each_line(a_sep_string = $/)
|
104
|
+
yield readline(a_sep_string) while true
|
105
|
+
rescue EOFError
|
106
|
+
end
|
107
|
+
|
108
|
+
alias_method :each, :each_line
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Zip
|
2
|
+
module IOExtras
|
3
|
+
# Implements many of the output convenience methods of IO.
|
4
|
+
# relies on <<
|
5
|
+
module AbstractOutputStream
|
6
|
+
include FakeIO
|
7
|
+
|
8
|
+
def write(data)
|
9
|
+
self << data
|
10
|
+
data.to_s.bytesize
|
11
|
+
end
|
12
|
+
|
13
|
+
def print(*params)
|
14
|
+
self << params.join($,) << $\.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def printf(a_format_string, *params)
|
18
|
+
self << format(a_format_string, *params)
|
19
|
+
end
|
20
|
+
|
21
|
+
def putc(an_object)
|
22
|
+
self << case an_object
|
23
|
+
when Integer
|
24
|
+
an_object.chr
|
25
|
+
when String
|
26
|
+
an_object
|
27
|
+
else
|
28
|
+
raise TypeError, 'putc: Only Integer and String supported'
|
29
|
+
end
|
30
|
+
an_object
|
31
|
+
end
|
32
|
+
|
33
|
+
def puts(*params)
|
34
|
+
params << "\n" if params.empty?
|
35
|
+
params.flatten.each do |element|
|
36
|
+
val = element.to_s
|
37
|
+
self << val
|
38
|
+
self << "\n" unless val[-1, 1] == "\n"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/zip/ioextras.rb
CHANGED
@@ -1,163 +1,35 @@
|
|
1
|
-
module
|
1
|
+
module Zip
|
2
|
+
module IOExtras #:nodoc:
|
3
|
+
CHUNK_SIZE = 131_072
|
2
4
|
|
3
|
-
|
5
|
+
RANGE_ALL = 0..-1
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
s = ''
|
9
|
-
ostream.write(istream.read(CHUNK_SIZE, s)) until istream.eof?
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.copy_stream_n(ostream, istream, nbytes)
|
13
|
-
s = ''
|
14
|
-
toread = nbytes
|
15
|
-
while (toread > 0 && ! istream.eof?)
|
16
|
-
tr = toread > CHUNK_SIZE ? CHUNK_SIZE : toread
|
17
|
-
ostream.write(istream.read(tr, s))
|
18
|
-
toread -= tr
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
|
23
|
-
# Implements kind_of? in order to pretend to be an IO object
|
24
|
-
module FakeIO
|
25
|
-
def kind_of?(object)
|
26
|
-
object == IO || super
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Implements many of the convenience methods of IO
|
31
|
-
# such as gets, getc, readline and readlines
|
32
|
-
# depends on: input_finished?, produce_input and read
|
33
|
-
module AbstractInputStream
|
34
|
-
include Enumerable
|
35
|
-
include FakeIO
|
36
|
-
|
37
|
-
def initialize
|
38
|
-
super
|
39
|
-
@lineno = 0
|
40
|
-
@outputBuffer = ""
|
41
|
-
end
|
42
|
-
|
43
|
-
attr_accessor :lineno
|
44
|
-
|
45
|
-
def read(numberOfBytes = nil, buf = nil)
|
46
|
-
tbuf = nil
|
47
|
-
|
48
|
-
if @outputBuffer.bytesize > 0
|
49
|
-
if numberOfBytes <= @outputBuffer.bytesize
|
50
|
-
tbuf = @outputBuffer.slice!(0, numberOfBytes)
|
51
|
-
else
|
52
|
-
numberOfBytes -= @outputBuffer.bytesize if (numberOfBytes)
|
53
|
-
rbuf = sysread(numberOfBytes, buf)
|
54
|
-
tbuf = @outputBuffer
|
55
|
-
tbuf << rbuf if (rbuf)
|
56
|
-
@outputBuffer = ""
|
57
|
-
end
|
58
|
-
else
|
59
|
-
tbuf = sysread(numberOfBytes, buf)
|
60
|
-
end
|
61
|
-
|
62
|
-
return nil unless (tbuf)
|
63
|
-
|
64
|
-
if buf
|
65
|
-
buf.replace(tbuf)
|
66
|
-
else
|
67
|
-
buf = tbuf
|
7
|
+
class << self
|
8
|
+
def copy_stream(ostream, istream)
|
9
|
+
ostream.write(istream.read(CHUNK_SIZE, '')) until istream.eof?
|
68
10
|
end
|
69
11
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
retVal
|
77
|
-
end
|
78
|
-
|
79
|
-
def gets(aSepString = $/)
|
80
|
-
@lineno = @lineno.next
|
81
|
-
return read if aSepString.nil?
|
82
|
-
aSepString = "#{$/}#{$/}" if aSepString.empty?
|
83
|
-
|
84
|
-
bufferIndex = 0
|
85
|
-
while ((matchIndex = @outputBuffer.index(aSepString, bufferIndex)) == nil)
|
86
|
-
bufferIndex = @outputBuffer.bytesize
|
87
|
-
if input_finished?
|
88
|
-
return @outputBuffer.empty? ? nil : flush
|
12
|
+
def copy_stream_n(ostream, istream, nbytes)
|
13
|
+
toread = nbytes
|
14
|
+
while toread > 0 && !istream.eof?
|
15
|
+
tr = toread > CHUNK_SIZE ? CHUNK_SIZE : toread
|
16
|
+
ostream.write(istream.read(tr, ''))
|
17
|
+
toread -= tr
|
89
18
|
end
|
90
|
-
@outputBuffer << produce_input
|
91
19
|
end
|
92
|
-
sepIndex = matchIndex + aSepString.bytesize
|
93
|
-
return @outputBuffer.slice!(0...sepIndex)
|
94
|
-
end
|
95
|
-
|
96
|
-
def flush
|
97
|
-
retVal = @outputBuffer
|
98
|
-
@outputBuffer=""
|
99
|
-
return retVal
|
100
20
|
end
|
101
21
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
end
|
107
|
-
|
108
|
-
def each_line(aSepString = $/)
|
109
|
-
while true
|
110
|
-
yield readline(aSepString)
|
22
|
+
# Implements kind_of? in order to pretend to be an IO object
|
23
|
+
module FakeIO
|
24
|
+
def kind_of?(object)
|
25
|
+
object == IO || super
|
111
26
|
end
|
112
|
-
rescue EOFError
|
113
27
|
end
|
28
|
+
end # IOExtras namespace module
|
29
|
+
end
|
114
30
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
# Implements many of the output convenience methods of IO.
|
120
|
-
# relies on <<
|
121
|
-
module AbstractOutputStream
|
122
|
-
include FakeIO
|
123
|
-
|
124
|
-
def write(data)
|
125
|
-
self << data
|
126
|
-
data.to_s.bytesize
|
127
|
-
end
|
128
|
-
|
129
|
-
|
130
|
-
def print(*params)
|
131
|
-
self << params.join($,) << $\.to_s
|
132
|
-
end
|
133
|
-
|
134
|
-
def printf(aFormatString, *params)
|
135
|
-
self << sprintf(aFormatString, *params)
|
136
|
-
end
|
137
|
-
|
138
|
-
def putc(anObject)
|
139
|
-
self << case anObject
|
140
|
-
when Fixnum then anObject.chr
|
141
|
-
when String then anObject
|
142
|
-
else raise TypeError, "putc: Only Fixnum and String supported"
|
143
|
-
end
|
144
|
-
anObject
|
145
|
-
end
|
146
|
-
|
147
|
-
def puts(*params)
|
148
|
-
params << "\n" if params.empty?
|
149
|
-
params.flatten.each do |element|
|
150
|
-
val = element.to_s
|
151
|
-
self << val
|
152
|
-
self << "\n" unless val[-1,1] == "\n"
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
end
|
157
|
-
|
158
|
-
end # IOExtras namespace module
|
159
|
-
|
160
|
-
|
31
|
+
require 'zip/ioextras/abstract_input_stream'
|
32
|
+
require 'zip/ioextras/abstract_output_stream'
|
161
33
|
|
162
34
|
# Copyright (C) 2002-2004 Thomas Sondergaard
|
163
35
|
# rubyzip is free software; you can redistribute it and/or
|
data/lib/zip/null_compressor.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
module Zip
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
module NullDecompressor #:nodoc:all
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def sysread(_numberOfBytes = nil, _buf = nil)
|
5
6
|
nil
|
6
7
|
end
|
7
|
-
|
8
|
+
|
8
9
|
def produce_input
|
9
10
|
nil
|
10
11
|
end
|
11
|
-
|
12
|
+
|
12
13
|
def input_finished?
|
13
14
|
true
|
14
15
|
end
|
@@ -16,7 +17,8 @@ module Zip
|
|
16
17
|
def eof
|
17
18
|
true
|
18
19
|
end
|
19
|
-
|
20
|
+
|
21
|
+
alias eof? eof
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|