rubyzip 1.3.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 +4 -4
- data/README.md +18 -16
- data/Rakefile +3 -0
- data/lib/zip/central_directory.rb +9 -5
- data/lib/zip/constants.rb +52 -0
- data/lib/zip/crypto/decrypted_io.rb +40 -0
- data/lib/zip/crypto/traditional_encryption.rb +9 -9
- data/lib/zip/decompressor.rb +19 -1
- data/lib/zip/dos_time.rb +24 -12
- data/lib/zip/entry.rb +107 -49
- data/lib/zip/entry_set.rb +2 -0
- data/lib/zip/errors.rb +1 -0
- data/lib/zip/extra_field/generic.rb +10 -9
- data/lib/zip/extra_field/ntfs.rb +5 -1
- data/lib/zip/extra_field/old_unix.rb +3 -1
- data/lib/zip/extra_field/universal_time.rb +42 -12
- data/lib/zip/extra_field/unix.rb +3 -1
- data/lib/zip/extra_field/zip64.rb +5 -3
- data/lib/zip/extra_field.rb +11 -9
- data/lib/zip/file.rb +142 -65
- data/lib/zip/filesystem.rb +193 -177
- data/lib/zip/inflater.rb +24 -36
- data/lib/zip/input_stream.rb +50 -30
- data/lib/zip/ioextras/abstract_input_stream.rb +23 -12
- data/lib/zip/ioextras/abstract_output_stream.rb +1 -1
- data/lib/zip/ioextras.rb +3 -3
- data/lib/zip/null_decompressor.rb +1 -9
- data/lib/zip/output_stream.rb +28 -12
- data/lib/zip/pass_thru_compressor.rb +2 -2
- data/lib/zip/pass_thru_decompressor.rb +13 -22
- data/lib/zip/streamable_directory.rb +3 -3
- data/lib/zip/streamable_stream.rb +6 -10
- data/lib/zip/version.rb +1 -1
- data/lib/zip.rb +23 -3
- data/samples/example.rb +2 -2
- data/samples/example_filesystem.rb +1 -1
- data/samples/gtk_ruby_zip.rb +19 -19
- data/samples/qtzip.rb +6 -6
- data/samples/write_simple.rb +2 -4
- data/samples/zipfind.rb +23 -22
- metadata +54 -181
- data/test/basic_zip_file_test.rb +0 -60
- data/test/case_sensitivity_test.rb +0 -69
- data/test/central_directory_entry_test.rb +0 -69
- data/test/central_directory_test.rb +0 -100
- data/test/crypto/null_encryption_test.rb +0 -57
- data/test/crypto/traditional_encryption_test.rb +0 -80
- data/test/data/WarnInvalidDate.zip +0 -0
- data/test/data/file1.txt +0 -46
- data/test/data/file1.txt.deflatedData +0 -0
- data/test/data/file2.txt +0 -1504
- 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 +0 -1
- data/test/data/notzippedruby.rb +0 -7
- data/test/data/ntfs.zip +0 -0
- data/test/data/oddExtraField.zip +0 -0
- data/test/data/path_traversal/Makefile +0 -10
- data/test/data/path_traversal/jwilk/README.md +0 -5
- 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 +0 -3
- 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 +0 -65
- data/test/encryption_test.rb +0 -42
- data/test/entry_set_test.rb +0 -163
- data/test/entry_test.rb +0 -154
- data/test/errors_test.rb +0 -35
- data/test/extra_field_test.rb +0 -76
- data/test/file_extract_directory_test.rb +0 -54
- data/test/file_extract_test.rb +0 -145
- data/test/file_permissions_test.rb +0 -65
- data/test/file_split_test.rb +0 -57
- data/test/file_test.rb +0 -666
- data/test/filesystem/dir_iterator_test.rb +0 -58
- data/test/filesystem/directory_test.rb +0 -139
- data/test/filesystem/file_mutating_test.rb +0 -87
- data/test/filesystem/file_nonmutating_test.rb +0 -508
- data/test/filesystem/file_stat_test.rb +0 -64
- data/test/gentestfiles.rb +0 -126
- data/test/inflater_test.rb +0 -14
- data/test/input_stream_test.rb +0 -182
- data/test/ioextras/abstract_input_stream_test.rb +0 -102
- data/test/ioextras/abstract_output_stream_test.rb +0 -106
- data/test/ioextras/fake_io_test.rb +0 -18
- data/test/local_entry_test.rb +0 -154
- data/test/output_stream_test.rb +0 -128
- data/test/pass_thru_compressor_test.rb +0 -30
- data/test/pass_thru_decompressor_test.rb +0 -14
- data/test/path_traversal_test.rb +0 -141
- data/test/samples/example_recursive_test.rb +0 -37
- data/test/settings_test.rb +0 -95
- data/test/test_helper.rb +0 -234
- data/test/unicode_file_names_and_comments_test.rb +0 -62
- data/test/zip64_full_test.rb +0 -51
- data/test/zip64_support_test.rb +0 -14
data/lib/zip/inflater.rb
CHANGED
@@ -1,64 +1,52 @@
|
|
1
1
|
module Zip
|
2
2
|
class Inflater < Decompressor #:nodoc:all
|
3
|
-
def initialize(
|
4
|
-
super
|
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
|
-
|
12
|
-
|
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 = ''.b
|
7
|
+
@zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
20
8
|
end
|
21
9
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
27
17
|
end
|
18
|
+
|
19
|
+
outbuf.replace(@buffer.slice!(0...(length || @buffer.bytesize)))
|
28
20
|
end
|
29
21
|
|
30
|
-
|
31
|
-
|
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
|
37
|
-
alias :eof? input_finished?
|
26
|
+
alias eof? eof
|
38
27
|
|
39
28
|
private
|
40
29
|
|
41
|
-
def
|
30
|
+
def produce_input
|
42
31
|
retried = 0
|
43
32
|
begin
|
44
|
-
@zlib_inflater.inflate(
|
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
|
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
|
data/lib/zip/input_stream.rb
CHANGED
@@ -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
|
@@ -47,11 +49,17 @@ module Zip
|
|
47
49
|
#
|
48
50
|
# @param context [String||IO||StringIO] file path or IO/StringIO object
|
49
51
|
# @param offset [Integer] offset in the IO/StringIO
|
50
|
-
def initialize(context,
|
52
|
+
def initialize(context, dep_offset = 0, dep_decrypter = nil, offset: 0, decrypter: nil)
|
51
53
|
super()
|
52
|
-
|
54
|
+
|
55
|
+
if !dep_offset.zero? || !dep_decrypter.nil?
|
56
|
+
Zip.warn_about_v3_api('Zip::InputStream.new')
|
57
|
+
end
|
58
|
+
|
59
|
+
offset = dep_offset if offset.zero?
|
60
|
+
@archive_io = get_io(context, offset)
|
53
61
|
@decompressor = ::Zip::NullDecompressor
|
54
|
-
@decrypter = decrypter || ::Zip::NullDecrypter.new
|
62
|
+
@decrypter = decrypter || dep_decrypter || ::Zip::NullDecrypter.new
|
55
63
|
@current_entry = nil
|
56
64
|
end
|
57
65
|
|
@@ -71,6 +79,7 @@ module Zip
|
|
71
79
|
# Rewinds the stream to the beginning of the current entry
|
72
80
|
def rewind
|
73
81
|
return if @current_entry.nil?
|
82
|
+
|
74
83
|
@lineno = 0
|
75
84
|
@pos = 0
|
76
85
|
@archive_io.seek(@current_entry.local_header_offset, IO::SEEK_SET)
|
@@ -78,23 +87,24 @@ module Zip
|
|
78
87
|
end
|
79
88
|
|
80
89
|
# Modeled after IO.sysread
|
81
|
-
def sysread(
|
82
|
-
@decompressor.
|
90
|
+
def sysread(length = nil, outbuf = '')
|
91
|
+
@decompressor.read(length, outbuf)
|
83
92
|
end
|
84
93
|
|
85
|
-
def eof
|
86
|
-
@output_buffer.empty? && @decompressor.eof
|
87
|
-
end
|
88
|
-
|
89
|
-
alias :eof? eof
|
90
|
-
|
91
94
|
class << self
|
92
95
|
# Same as #initialize but if a block is passed the opened
|
93
96
|
# stream is passed to the block and closed when the block
|
94
97
|
# returns.
|
95
|
-
def open(filename_or_io,
|
96
|
-
|
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)
|
97
106
|
return zio unless block_given?
|
107
|
+
|
98
108
|
begin
|
99
109
|
yield zio
|
100
110
|
ensure
|
@@ -103,8 +113,9 @@ module Zip
|
|
103
113
|
end
|
104
114
|
|
105
115
|
def open_buffer(filename_or_io, offset = 0)
|
106
|
-
|
107
|
-
|
116
|
+
Zip.warn_about_v3_api('Zip::InputStream.open_buffer')
|
117
|
+
|
118
|
+
::Zip::InputStream.open(filename_or_io, offset)
|
108
119
|
end
|
109
120
|
end
|
110
121
|
|
@@ -124,46 +135,55 @@ module Zip
|
|
124
135
|
|
125
136
|
def open_entry
|
126
137
|
@current_entry = ::Zip::Entry.read_local_entry(@archive_io)
|
127
|
-
if @current_entry && @current_entry.
|
138
|
+
if @current_entry && @current_entry.encrypted? && @decrypter.kind_of?(NullEncrypter)
|
128
139
|
raise Error, 'password required to decode zip file'
|
129
140
|
end
|
130
|
-
|
141
|
+
|
142
|
+
if @current_entry && @current_entry.incomplete? && @current_entry.crc == 0 \
|
131
143
|
&& @current_entry.compressed_size == 0 \
|
132
144
|
&& @current_entry.size == 0 && !@complete_entry
|
133
145
|
raise GPFBit3Error,
|
134
146
|
'General purpose flag Bit 3 is set so not possible to get proper info from local header.' \
|
135
147
|
'Please use ::Zip::File instead of ::Zip::InputStream'
|
136
148
|
end
|
149
|
+
@decrypted_io = get_decrypted_io
|
137
150
|
@decompressor = get_decompressor
|
138
151
|
flush
|
139
152
|
@current_entry
|
140
153
|
end
|
141
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
|
+
|
142
162
|
def get_decompressor
|
143
|
-
if @current_entry.nil?
|
144
|
-
|
145
|
-
|
146
|
-
if @current_entry.
|
147
|
-
|
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
|
148
168
|
else
|
149
|
-
|
169
|
+
@current_entry.size
|
150
170
|
end
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
::Zip::Inflater.new(@archive_io, @decrypter)
|
155
|
-
else
|
171
|
+
|
172
|
+
decompressor_class = ::Zip::Decompressor.find_by_compression_method(@current_entry.compression_method)
|
173
|
+
if decompressor_class.nil?
|
156
174
|
raise ::Zip::CompressionMethodError,
|
157
175
|
"Unsupported compression method #{@current_entry.compression_method}"
|
158
176
|
end
|
177
|
+
|
178
|
+
decompressor_class.new(@decrypted_io, decompressed_size)
|
159
179
|
end
|
160
180
|
|
161
181
|
def produce_input
|
162
|
-
@decompressor.
|
182
|
+
@decompressor.read(CHUNK_SIZE)
|
163
183
|
end
|
164
184
|
|
165
185
|
def input_finished?
|
166
|
-
@decompressor.
|
186
|
+
@decompressor.eof
|
167
187
|
end
|
168
188
|
end
|
169
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,7 +26,7 @@ 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
|
@@ -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 =
|
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
|
-
|
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
|
@@ -90,22 +93,30 @@ module Zip
|
|
90
93
|
|
91
94
|
def flush
|
92
95
|
ret_val = @output_buffer
|
93
|
-
@output_buffer = ''
|
96
|
+
@output_buffer = ''.b
|
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)
|
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
|
-
|
119
|
+
alias eof? eof
|
109
120
|
end
|
110
121
|
end
|
111
122
|
end
|
data/lib/zip/ioextras.rb
CHANGED
@@ -6,14 +6,14 @@ module Zip
|
|
6
6
|
|
7
7
|
class << self
|
8
8
|
def copy_stream(ostream, istream)
|
9
|
-
ostream.write(istream.read(CHUNK_SIZE, '')) until istream.eof?
|
9
|
+
ostream.write(istream.read(CHUNK_SIZE, ''.b)) until istream.eof?
|
10
10
|
end
|
11
11
|
|
12
12
|
def copy_stream_n(ostream, istream, nbytes)
|
13
13
|
toread = nbytes
|
14
14
|
while toread > 0 && !istream.eof?
|
15
15
|
tr = toread > CHUNK_SIZE ? CHUNK_SIZE : toread
|
16
|
-
ostream.write(istream.read(tr, ''))
|
16
|
+
ostream.write(istream.read(tr, ''.b))
|
17
17
|
toread -= tr
|
18
18
|
end
|
19
19
|
end
|
@@ -25,7 +25,7 @@ module Zip
|
|
25
25
|
object == IO || super
|
26
26
|
end
|
27
27
|
end
|
28
|
-
end
|
28
|
+
end
|
29
29
|
end
|
30
30
|
|
31
31
|
require 'zip/ioextras/abstract_input_stream'
|
@@ -2,18 +2,10 @@ module Zip
|
|
2
2
|
module NullDecompressor #:nodoc:all
|
3
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
|
data/lib/zip/output_stream.rb
CHANGED
@@ -24,10 +24,13 @@ module Zip
|
|
24
24
|
|
25
25
|
# Opens the indicated zip file. If a file with that name already
|
26
26
|
# exists it will be overwritten.
|
27
|
-
def initialize(file_name,
|
27
|
+
def initialize(file_name, dep_stream = false, dep_encrypter = nil, stream: false, encrypter: nil)
|
28
28
|
super()
|
29
|
+
|
30
|
+
Zip.warn_about_v3_api('Zip::OutputStream.new') if dep_stream || !dep_encrypter.nil?
|
31
|
+
|
29
32
|
@file_name = file_name
|
30
|
-
@output_stream = if stream
|
33
|
+
@output_stream = if stream || dep_stream
|
31
34
|
iostream = @file_name.dup
|
32
35
|
iostream.reopen(@file_name)
|
33
36
|
iostream.rewind
|
@@ -37,7 +40,7 @@ module Zip
|
|
37
40
|
end
|
38
41
|
@entry_set = ::Zip::EntrySet.new
|
39
42
|
@compressor = ::Zip::NullCompressor.instance
|
40
|
-
@encrypter = encrypter || ::Zip::NullEncrypter.new
|
43
|
+
@encrypter = encrypter || dep_encrypter || ::Zip::NullEncrypter.new
|
41
44
|
@closed = false
|
42
45
|
@current_entry = nil
|
43
46
|
@comment = nil
|
@@ -47,17 +50,23 @@ module Zip
|
|
47
50
|
# stream is passed to the block and closed when the block
|
48
51
|
# returns.
|
49
52
|
class << self
|
50
|
-
def open(file_name,
|
53
|
+
def open(file_name, dep_encrypter = nil, encrypter: nil)
|
51
54
|
return new(file_name) unless block_given?
|
52
|
-
|
55
|
+
|
56
|
+
Zip.warn_about_v3_api('Zip::OutputStream.open') unless dep_encrypter.nil?
|
57
|
+
|
58
|
+
zos = new(file_name, stream: false, encrypter: (encrypter || dep_encrypter))
|
53
59
|
yield zos
|
54
60
|
ensure
|
55
61
|
zos.close if zos
|
56
62
|
end
|
57
63
|
|
58
64
|
# Same as #open but writes to a filestream instead
|
59
|
-
def write_buffer(io = ::StringIO.new
|
60
|
-
|
65
|
+
def write_buffer(io = ::StringIO.new, dep_encrypter = nil, encrypter: nil)
|
66
|
+
Zip.warn_about_v3_api('Zip::OutputStream.write_buffer') unless dep_encrypter.nil?
|
67
|
+
|
68
|
+
io.binmode if io.respond_to?(:binmode)
|
69
|
+
zos = new(io, stream: true, encrypter: (encrypter || dep_encrypter))
|
61
70
|
yield zos
|
62
71
|
zos.close_buffer
|
63
72
|
end
|
@@ -66,6 +75,7 @@ module Zip
|
|
66
75
|
# Closes the stream and writes the central directory to the zip file
|
67
76
|
def close
|
68
77
|
return if @closed
|
78
|
+
|
69
79
|
finalize_current_entry
|
70
80
|
update_local_headers
|
71
81
|
write_central_directory
|
@@ -76,6 +86,7 @@ module Zip
|
|
76
86
|
# Closes the stream and writes the central directory to the zip file
|
77
87
|
def close_buffer
|
78
88
|
return @output_stream if @closed
|
89
|
+
|
79
90
|
finalize_current_entry
|
80
91
|
update_local_headers
|
81
92
|
write_central_directory
|
@@ -87,6 +98,7 @@ module Zip
|
|
87
98
|
# +entry+ can be a ZipEntry object or a string.
|
88
99
|
def put_next_entry(entry_name, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zip.default_compression)
|
89
100
|
raise Error, 'zip stream is closed' if @closed
|
101
|
+
|
90
102
|
new_entry = if entry_name.kind_of?(Entry)
|
91
103
|
entry_name
|
92
104
|
else
|
@@ -94,7 +106,7 @@ module Zip
|
|
94
106
|
end
|
95
107
|
new_entry.comment = comment unless comment.nil?
|
96
108
|
unless extra.nil?
|
97
|
-
new_entry.extra = extra.
|
109
|
+
new_entry.extra = extra.kind_of?(ExtraField) ? extra : ExtraField.new(extra.to_s)
|
98
110
|
end
|
99
111
|
new_entry.compression_method = compression_method unless compression_method.nil?
|
100
112
|
init_next_entry(new_entry, level)
|
@@ -104,7 +116,8 @@ module Zip
|
|
104
116
|
def copy_raw_entry(entry)
|
105
117
|
entry = entry.dup
|
106
118
|
raise Error, 'zip stream is closed' if @closed
|
107
|
-
raise Error, 'entry is not a ZipEntry' unless entry.
|
119
|
+
raise Error, 'entry is not a ZipEntry' unless entry.kind_of?(Entry)
|
120
|
+
|
108
121
|
finalize_current_entry
|
109
122
|
@entry_set << entry
|
110
123
|
src_pos = entry.local_header_offset
|
@@ -123,8 +136,11 @@ module Zip
|
|
123
136
|
|
124
137
|
def finalize_current_entry
|
125
138
|
return unless @current_entry
|
139
|
+
|
126
140
|
finish
|
127
|
-
@current_entry.compressed_size = @output_stream.tell -
|
141
|
+
@current_entry.compressed_size = @output_stream.tell - \
|
142
|
+
@current_entry.local_header_offset - \
|
143
|
+
@current_entry.calculate_local_header_size
|
128
144
|
@current_entry.size = @compressor.size
|
129
145
|
@current_entry.crc = @compressor.crc
|
130
146
|
@output_stream << @encrypter.data_descriptor(@current_entry.crc, @current_entry.compressed_size, @current_entry.size)
|
@@ -144,9 +160,9 @@ module Zip
|
|
144
160
|
|
145
161
|
def get_compressor(entry, level)
|
146
162
|
case entry.compression_method
|
147
|
-
when Entry::DEFLATED
|
163
|
+
when Entry::DEFLATED
|
148
164
|
::Zip::Deflater.new(@output_stream, level, @encrypter)
|
149
|
-
when Entry::STORED
|
165
|
+
when Entry::STORED
|
150
166
|
::Zip::PassThruCompressor.new(@output_stream)
|
151
167
|
else
|
152
168
|
raise ::Zip::CompressionMethodError,
|
@@ -1,38 +1,29 @@
|
|
1
1
|
module Zip
|
2
2
|
class PassThruDecompressor < Decompressor #:nodoc:all
|
3
|
-
def initialize(
|
4
|
-
super
|
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
|
11
|
-
if
|
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 = ''.b)
|
9
|
+
return (length.nil? || length.zero? ? '' : nil) if eof
|
17
10
|
|
18
|
-
if
|
19
|
-
|
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
|
-
|
26
|
-
|
15
|
+
@read_so_far += length
|
16
|
+
input_stream.read(length, outbuf)
|
27
17
|
end
|
28
18
|
|
29
|
-
def
|
30
|
-
@read_so_far >=
|
19
|
+
def eof
|
20
|
+
@read_so_far >= decompressed_size
|
31
21
|
end
|
32
22
|
|
33
|
-
alias eof
|
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
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Zip
|
2
2
|
class StreamableDirectory < Entry
|
3
|
-
def initialize(zipfile, entry,
|
3
|
+
def initialize(zipfile, entry, src_path = nil, permission = nil)
|
4
4
|
super(zipfile, entry)
|
5
5
|
|
6
6
|
@ftype = :directory
|
7
|
-
entry.get_extra_attributes_from_path(
|
8
|
-
@unix_perms =
|
7
|
+
entry.get_extra_attributes_from_path(src_path) if src_path
|
8
|
+
@unix_perms = permission if permission
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -1,13 +1,8 @@
|
|
1
1
|
module Zip
|
2
|
-
class StreamableStream < DelegateClass(Entry) # nodoc:all
|
2
|
+
class StreamableStream < DelegateClass(Entry) # :nodoc:all
|
3
3
|
def initialize(entry)
|
4
4
|
super(entry)
|
5
|
-
|
6
|
-
::File.dirname(zipfile)
|
7
|
-
else
|
8
|
-
nil
|
9
|
-
end
|
10
|
-
@temp_file = Tempfile.new(::File.basename(name), dirname)
|
5
|
+
@temp_file = Tempfile.new(::File.basename(name))
|
11
6
|
@temp_file.binmode
|
12
7
|
end
|
13
8
|
|
@@ -27,6 +22,7 @@ module Zip
|
|
27
22
|
unless @temp_file.closed?
|
28
23
|
raise StandardError, "cannot open entry for reading while its open for writing - #{name}"
|
29
24
|
end
|
25
|
+
|
30
26
|
@temp_file.open # reopens tempfile from top
|
31
27
|
@temp_file.binmode
|
32
28
|
if block_given?
|
@@ -40,9 +36,9 @@ module Zip
|
|
40
36
|
end
|
41
37
|
end
|
42
38
|
|
43
|
-
def write_to_zip_output_stream(
|
44
|
-
|
45
|
-
get_input_stream { |is| ::Zip::IOExtras.copy_stream(
|
39
|
+
def write_to_zip_output_stream(output_stream)
|
40
|
+
output_stream.put_next_entry(self)
|
41
|
+
get_input_stream { |is| ::Zip::IOExtras.copy_stream(output_stream, is) }
|
46
42
|
end
|
47
43
|
|
48
44
|
def clean_up
|
data/lib/zip/version.rb
CHANGED