rubyzip 1.1.7 → 2.3.2
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 +5 -5
- data/README.md +137 -54
- data/Rakefile +6 -4
- data/lib/zip/central_directory.rb +17 -13
- data/lib/zip/compressor.rb +1 -2
- data/lib/zip/constants.rb +57 -5
- data/lib/zip/crypto/decrypted_io.rb +40 -0
- data/lib/zip/crypto/null_encryption.rb +4 -6
- data/lib/zip/crypto/traditional_encryption.rb +14 -14
- data/lib/zip/decompressor.rb +22 -4
- data/lib/zip/deflater.rb +8 -6
- data/lib/zip/dos_time.rb +17 -13
- data/lib/zip/entry.rb +171 -148
- data/lib/zip/entry_set.rb +16 -14
- data/lib/zip/errors.rb +3 -0
- data/lib/zip/extra_field/generic.rb +14 -13
- data/lib/zip/extra_field/ntfs.rb +18 -16
- data/lib/zip/extra_field/old_unix.rb +12 -11
- 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 +15 -12
- data/lib/zip/extra_field/zip64_placeholder.rb +1 -2
- data/lib/zip/extra_field.rb +18 -16
- data/lib/zip/file.rb +147 -115
- data/lib/zip/filesystem.rb +289 -272
- data/lib/zip/inflater.rb +24 -36
- data/lib/zip/input_stream.rb +44 -28
- data/lib/zip/ioextras/abstract_input_stream.rb +24 -17
- data/lib/zip/ioextras/abstract_output_stream.rb +4 -6
- data/lib/zip/ioextras.rb +2 -4
- data/lib/zip/null_compressor.rb +2 -2
- data/lib/zip/null_decompressor.rb +3 -11
- data/lib/zip/null_input_stream.rb +0 -0
- data/lib/zip/output_stream.rb +25 -17
- 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 +7 -11
- data/lib/zip/version.rb +1 -1
- data/lib/zip.rb +15 -6
- data/samples/example.rb +29 -39
- data/samples/example_filesystem.rb +16 -18
- data/samples/example_recursive.rb +31 -25
- data/samples/gtk_ruby_zip.rb +84 -0
- data/samples/qtzip.rb +23 -32
- data/samples/write_simple.rb +10 -13
- data/samples/zipfind.rb +33 -40
- metadata +50 -141
- data/samples/gtkRubyzip.rb +0 -86
- data/test/basic_zip_file_test.rb +0 -64
- data/test/central_directory_entry_test.rb +0 -73
- data/test/central_directory_test.rb +0 -104
- data/test/crypto/null_encryption_test.rb +0 -53
- 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/mimetype +0 -1
- data/test/data/notzippedruby.rb +0 -7
- data/test/data/ntfs.zip +0 -0
- data/test/data/rubycode.zip +0 -0
- data/test/data/rubycode2.zip +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 -67
- data/test/encryption_test.rb +0 -42
- data/test/entry_set_test.rb +0 -138
- data/test/entry_test.rb +0 -165
- data/test/errors_test.rb +0 -36
- data/test/extra_field_test.rb +0 -78
- data/test/file_extract_directory_test.rb +0 -56
- data/test/file_extract_test.rb +0 -90
- data/test/file_split_test.rb +0 -60
- data/test/file_test.rb +0 -559
- data/test/filesystem/dir_iterator_test.rb +0 -62
- data/test/filesystem/directory_test.rb +0 -131
- data/test/filesystem/file_mutating_test.rb +0 -100
- data/test/filesystem/file_nonmutating_test.rb +0 -514
- data/test/filesystem/file_stat_test.rb +0 -66
- data/test/gentestfiles.rb +0 -134
- data/test/inflater_test.rb +0 -14
- data/test/input_stream_test.rb +0 -170
- data/test/ioextras/abstract_input_stream_test.rb +0 -103
- 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 -156
- data/test/output_stream_test.rb +0 -129
- data/test/pass_thru_compressor_test.rb +0 -31
- data/test/pass_thru_decompressor_test.rb +0 -15
- data/test/settings_test.rb +0 -92
- data/test/test_helper.rb +0 -228
- data/test/unicode_file_names_and_comments_test.rb +0 -52
- data/test/zip64_full_test.rb +0 -53
- data/test/zip64_support_test.rb +0 -15
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 = ''
|
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 = +''
|
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 = '')
|
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
|
@@ -49,7 +51,7 @@ module Zip
|
|
49
51
|
# @param offset [Integer] offset in the IO/StringIO
|
50
52
|
def initialize(context, offset = 0, decrypter = nil)
|
51
53
|
super()
|
52
|
-
@archive_io
|
54
|
+
@archive_io = get_io(context, offset)
|
53
55
|
@decompressor = ::Zip::NullDecompressor
|
54
56
|
@decrypter = decrypter || ::Zip::NullDecrypter.new
|
55
57
|
@current_entry = nil
|
@@ -71,6 +73,7 @@ module Zip
|
|
71
73
|
# Rewinds the stream to the beginning of the current entry
|
72
74
|
def rewind
|
73
75
|
return if @current_entry.nil?
|
76
|
+
|
74
77
|
@lineno = 0
|
75
78
|
@pos = 0
|
76
79
|
@archive_io.seek(@current_entry.local_header_offset, IO::SEEK_SET)
|
@@ -78,23 +81,18 @@ module Zip
|
|
78
81
|
end
|
79
82
|
|
80
83
|
# Modeled after IO.sysread
|
81
|
-
def sysread(
|
82
|
-
@decompressor.
|
83
|
-
end
|
84
|
-
|
85
|
-
def eof
|
86
|
-
@output_buffer.empty? && @decompressor.eof
|
84
|
+
def sysread(length = nil, outbuf = '')
|
85
|
+
@decompressor.read(length, outbuf)
|
87
86
|
end
|
88
87
|
|
89
|
-
alias :eof? :eof
|
90
|
-
|
91
88
|
class << self
|
92
89
|
# Same as #initialize but if a block is passed the opened
|
93
90
|
# stream is passed to the block and closed when the block
|
94
91
|
# returns.
|
95
92
|
def open(filename_or_io, offset = 0, decrypter = nil)
|
96
|
-
zio =
|
93
|
+
zio = new(filename_or_io, offset, decrypter)
|
97
94
|
return zio unless block_given?
|
95
|
+
|
98
96
|
begin
|
99
97
|
yield zio
|
100
98
|
ensure
|
@@ -103,16 +101,15 @@ module Zip
|
|
103
101
|
end
|
104
102
|
|
105
103
|
def open_buffer(filename_or_io, offset = 0)
|
106
|
-
|
107
|
-
|
104
|
+
warn 'open_buffer is deprecated!!! Use open instead!'
|
105
|
+
::Zip::InputStream.open(filename_or_io, offset)
|
108
106
|
end
|
109
107
|
end
|
110
108
|
|
111
109
|
protected
|
112
110
|
|
113
111
|
def get_io(io_or_file, offset = 0)
|
114
|
-
|
115
|
-
when IO, StringIO
|
112
|
+
if io_or_file.respond_to?(:seek)
|
116
113
|
io = io_or_file.dup
|
117
114
|
io.seek(offset, ::IO::SEEK_SET)
|
118
115
|
io
|
@@ -125,36 +122,55 @@ module Zip
|
|
125
122
|
|
126
123
|
def open_entry
|
127
124
|
@current_entry = ::Zip::Entry.read_local_entry(@archive_io)
|
128
|
-
if @current_entry
|
125
|
+
if @current_entry && @current_entry.encrypted? && @decrypter.kind_of?(NullEncrypter)
|
129
126
|
raise Error, 'password required to decode zip file'
|
130
127
|
end
|
131
|
-
|
128
|
+
|
129
|
+
if @current_entry && @current_entry.incomplete? && @current_entry.crc == 0 \
|
130
|
+
&& @current_entry.compressed_size == 0 \
|
131
|
+
&& @current_entry.size == 0 && !@complete_entry
|
132
|
+
raise GPFBit3Error,
|
133
|
+
'General purpose flag Bit 3 is set so not possible to get proper info from local header.' \
|
134
|
+
'Please use ::Zip::File instead of ::Zip::InputStream'
|
135
|
+
end
|
136
|
+
@decrypted_io = get_decrypted_io
|
137
|
+
@decompressor = get_decompressor
|
132
138
|
flush
|
133
139
|
@current_entry
|
134
140
|
end
|
135
141
|
|
142
|
+
def get_decrypted_io
|
143
|
+
header = @archive_io.read(@decrypter.header_bytesize)
|
144
|
+
@decrypter.reset!(header)
|
145
|
+
|
146
|
+
::Zip::DecryptedIo.new(@archive_io, @decrypter)
|
147
|
+
end
|
148
|
+
|
136
149
|
def get_decompressor
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
150
|
+
return ::Zip::NullDecompressor if @current_entry.nil?
|
151
|
+
|
152
|
+
decompressed_size =
|
153
|
+
if @current_entry.incomplete? && @current_entry.crc == 0 && @current_entry.size == 0 && @complete_entry
|
154
|
+
@complete_entry.size
|
155
|
+
else
|
156
|
+
@current_entry.size
|
157
|
+
end
|
158
|
+
|
159
|
+
decompressor_class = ::Zip::Decompressor.find_by_compression_method(@current_entry.compression_method)
|
160
|
+
if decompressor_class.nil?
|
147
161
|
raise ::Zip::CompressionMethodError,
|
148
162
|
"Unsupported compression method #{@current_entry.compression_method}"
|
149
163
|
end
|
164
|
+
|
165
|
+
decompressor_class.new(@decrypted_io, decompressed_size)
|
150
166
|
end
|
151
167
|
|
152
168
|
def produce_input
|
153
|
-
@decompressor.
|
169
|
+
@decompressor.read(CHUNK_SIZE)
|
154
170
|
end
|
155
171
|
|
156
172
|
def input_finished?
|
157
|
-
@decompressor.
|
173
|
+
@decompressor.eof
|
158
174
|
end
|
159
175
|
end
|
160
176
|
end
|
@@ -33,9 +33,10 @@ module Zip
|
|
33
33
|
sysread(number_of_bytes, buf)
|
34
34
|
end
|
35
35
|
|
36
|
-
if tbuf.nil? || tbuf.
|
36
|
+
if tbuf.nil? || tbuf.empty?
|
37
37
|
return nil if number_of_bytes
|
38
|
-
|
38
|
+
|
39
|
+
return ''
|
39
40
|
end
|
40
41
|
|
41
42
|
@pos += tbuf.length
|
@@ -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,28 +63,28 @@ 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
|
-
if input_finished?
|
79
|
-
|
80
|
-
end
|
80
|
+
return @output_buffer.empty? ? nil : flush if input_finished?
|
81
|
+
|
81
82
|
@output_buffer << produce_input
|
82
83
|
over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
|
83
84
|
end
|
84
85
|
sep_index = [match_index + a_sep_string.bytesize, number_of_bytes || @output_buffer.bytesize].min
|
85
|
-
@pos
|
86
|
-
|
86
|
+
@pos += sep_index
|
87
|
+
@output_buffer.slice!(0...sep_index)
|
87
88
|
end
|
88
89
|
|
89
90
|
def ungetc(byte)
|
@@ -96,20 +97,26 @@ module Zip
|
|
96
97
|
ret_val
|
97
98
|
end
|
98
99
|
|
99
|
-
def readline(a_sep_string =
|
100
|
+
def readline(a_sep_string = $INPUT_RECORD_SEPARATOR)
|
100
101
|
ret_val = gets(a_sep_string)
|
101
102
|
raise EOFError unless ret_val
|
103
|
+
|
102
104
|
ret_val
|
103
105
|
end
|
104
106
|
|
105
|
-
def each_line(a_sep_string =
|
106
|
-
|
107
|
-
yield readline(a_sep_string)
|
108
|
-
end
|
107
|
+
def each_line(a_sep_string = $INPUT_RECORD_SEPARATOR)
|
108
|
+
loop { yield readline(a_sep_string) }
|
109
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?
|
110
117
|
end
|
111
118
|
|
112
|
-
|
119
|
+
alias eof? eof
|
113
120
|
end
|
114
121
|
end
|
115
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,7 +1,6 @@
|
|
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
|
|
@@ -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
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
|
20
12
|
|
21
|
-
alias
|
13
|
+
alias eof? eof
|
22
14
|
end
|
23
15
|
end
|
24
16
|
|
File without changes
|
data/lib/zip/output_stream.rb
CHANGED
@@ -24,7 +24,7 @@ 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, stream=false, encrypter=nil)
|
27
|
+
def initialize(file_name, stream = false, encrypter = nil)
|
28
28
|
super()
|
29
29
|
@file_name = file_name
|
30
30
|
@output_stream = if stream
|
@@ -33,7 +33,7 @@ module Zip
|
|
33
33
|
iostream.rewind
|
34
34
|
iostream
|
35
35
|
else
|
36
|
-
::File.new(@file_name,
|
36
|
+
::File.new(@file_name, 'wb')
|
37
37
|
end
|
38
38
|
@entry_set = ::Zip::EntrySet.new
|
39
39
|
@compressor = ::Zip::NullCompressor.instance
|
@@ -49,6 +49,7 @@ module Zip
|
|
49
49
|
class << self
|
50
50
|
def open(file_name, encrypter = nil)
|
51
51
|
return new(file_name) unless block_given?
|
52
|
+
|
52
53
|
zos = new(file_name, false, encrypter)
|
53
54
|
yield zos
|
54
55
|
ensure
|
@@ -57,6 +58,7 @@ module Zip
|
|
57
58
|
|
58
59
|
# Same as #open but writes to a filestream instead
|
59
60
|
def write_buffer(io = ::StringIO.new(''), encrypter = nil)
|
61
|
+
io.binmode if io.respond_to?(:binmode)
|
60
62
|
zos = new(io, true, encrypter)
|
61
63
|
yield zos
|
62
64
|
zos.close_buffer
|
@@ -66,6 +68,7 @@ module Zip
|
|
66
68
|
# Closes the stream and writes the central directory to the zip file
|
67
69
|
def close
|
68
70
|
return if @closed
|
71
|
+
|
69
72
|
finalize_current_entry
|
70
73
|
update_local_headers
|
71
74
|
write_central_directory
|
@@ -76,6 +79,7 @@ module Zip
|
|
76
79
|
# Closes the stream and writes the central directory to the zip file
|
77
80
|
def close_buffer
|
78
81
|
return @output_stream if @closed
|
82
|
+
|
79
83
|
finalize_current_entry
|
80
84
|
update_local_headers
|
81
85
|
write_central_directory
|
@@ -86,15 +90,16 @@ module Zip
|
|
86
90
|
# Closes the current entry and opens a new for writing.
|
87
91
|
# +entry+ can be a ZipEntry object or a string.
|
88
92
|
def put_next_entry(entry_name, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zip.default_compression)
|
89
|
-
raise Error,
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
93
|
+
raise Error, 'zip stream is closed' if @closed
|
94
|
+
|
95
|
+
new_entry = if entry_name.kind_of?(Entry)
|
96
|
+
entry_name
|
97
|
+
else
|
98
|
+
Entry.new(@file_name, entry_name.to_s)
|
99
|
+
end
|
95
100
|
new_entry.comment = comment unless comment.nil?
|
96
101
|
unless extra.nil?
|
97
|
-
new_entry.extra = ExtraField
|
102
|
+
new_entry.extra = extra.kind_of?(ExtraField) ? extra : ExtraField.new(extra.to_s)
|
98
103
|
end
|
99
104
|
new_entry.compression_method = compression_method unless compression_method.nil?
|
100
105
|
init_next_entry(new_entry, level)
|
@@ -103,8 +108,9 @@ module Zip
|
|
103
108
|
|
104
109
|
def copy_raw_entry(entry)
|
105
110
|
entry = entry.dup
|
106
|
-
raise Error,
|
107
|
-
raise Error,
|
111
|
+
raise Error, 'zip stream is closed' if @closed
|
112
|
+
raise Error, 'entry is not a ZipEntry' unless entry.kind_of?(Entry)
|
113
|
+
|
108
114
|
finalize_current_entry
|
109
115
|
@entry_set << entry
|
110
116
|
src_pos = entry.local_header_offset
|
@@ -123,9 +129,11 @@ module Zip
|
|
123
129
|
|
124
130
|
def finalize_current_entry
|
125
131
|
return unless @current_entry
|
126
|
-
|
132
|
+
|
127
133
|
finish
|
128
|
-
@current_entry.compressed_size = @output_stream.tell -
|
134
|
+
@current_entry.compressed_size = @output_stream.tell - \
|
135
|
+
@current_entry.local_header_offset - \
|
136
|
+
@current_entry.calculate_local_header_size
|
129
137
|
@current_entry.size = @compressor.size
|
130
138
|
@current_entry.crc = @compressor.crc
|
131
139
|
@output_stream << @encrypter.data_descriptor(@current_entry.crc, @current_entry.compressed_size, @current_entry.size)
|
@@ -139,14 +147,15 @@ module Zip
|
|
139
147
|
@entry_set << entry
|
140
148
|
entry.write_local_entry(@output_stream)
|
141
149
|
@encrypter.reset!
|
150
|
+
@output_stream << @encrypter.header(entry.mtime)
|
142
151
|
@compressor = get_compressor(entry, level)
|
143
152
|
end
|
144
153
|
|
145
154
|
def get_compressor(entry, level)
|
146
155
|
case entry.compression_method
|
147
|
-
when Entry::DEFLATED
|
156
|
+
when Entry::DEFLATED
|
148
157
|
::Zip::Deflater.new(@output_stream, level, @encrypter)
|
149
|
-
when Entry::STORED
|
158
|
+
when Entry::STORED
|
150
159
|
::Zip::PassThruCompressor.new(@output_stream)
|
151
160
|
else
|
152
161
|
raise ::Zip::CompressionMethodError,
|
@@ -177,11 +186,10 @@ module Zip
|
|
177
186
|
public
|
178
187
|
|
179
188
|
# Modeled after IO.<<
|
180
|
-
def <<
|
189
|
+
def <<(data)
|
181
190
|
@compressor << data
|
182
191
|
self
|
183
192
|
end
|
184
|
-
|
185
193
|
end
|
186
194
|
end
|
187
195
|
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module Zip
|
2
2
|
class PassThruCompressor < Compressor #:nodoc:all
|
3
|
-
def initialize(
|
3
|
+
def initialize(output_stream)
|
4
4
|
super()
|
5
|
-
@output_stream =
|
6
|
-
@crc = Zlib
|
5
|
+
@output_stream = output_stream
|
6
|
+
@crc = Zlib.crc32
|
7
7
|
@size = 0
|
8
8
|
end
|
9
|
-
|
10
|
-
def <<
|
9
|
+
|
10
|
+
def <<(data)
|
11
11
|
val = data.to_s
|
12
|
-
@crc = Zlib
|
12
|
+
@crc = Zlib.crc32(val, @crc)
|
13
13
|
@size += val.bytesize
|
14
14
|
@output_stream << val
|
15
15
|
end
|
@@ -1,39 +1,29 @@
|
|
1
1
|
module Zip
|
2
|
-
class PassThruDecompressor < Decompressor
|
3
|
-
|
4
|
-
|
5
|
-
super(input_stream)
|
6
|
-
@chars_to_read = chars_to_read
|
2
|
+
class PassThruDecompressor < Decompressor #:nodoc:all
|
3
|
+
def initialize(*args)
|
4
|
+
super
|
7
5
|
@read_so_far = 0
|
8
|
-
@has_returned_empty_string = false
|
9
6
|
end
|
10
7
|
|
11
|
-
def
|
12
|
-
if
|
13
|
-
has_returned_empty_string_val = @has_returned_empty_string
|
14
|
-
@has_returned_empty_string = true
|
15
|
-
return '' unless has_returned_empty_string_val
|
16
|
-
return
|
17
|
-
end
|
8
|
+
def read(length = nil, outbuf = '')
|
9
|
+
return (length.nil? || length.zero? ? '' : nil) if eof
|
18
10
|
|
19
|
-
if
|
20
|
-
|
11
|
+
if length.nil? || (@read_so_far + length) > decompressed_size
|
12
|
+
length = decompressed_size - @read_so_far
|
21
13
|
end
|
22
|
-
@read_so_far += number_of_bytes
|
23
|
-
@input_stream.read(number_of_bytes, buf)
|
24
|
-
end
|
25
14
|
|
26
|
-
|
27
|
-
|
15
|
+
@read_so_far += length
|
16
|
+
input_stream.read(length, outbuf)
|
28
17
|
end
|
29
18
|
|
30
|
-
def
|
31
|
-
@read_so_far >=
|
19
|
+
def eof
|
20
|
+
@read_so_far >= decompressed_size
|
32
21
|
end
|
33
22
|
|
34
|
-
alias
|
35
|
-
alias :eof? :input_finished?
|
23
|
+
alias eof? eof
|
36
24
|
end
|
25
|
+
|
26
|
+
::Zip::Decompressor.register(::Zip::COMPRESSION_METHOD_STORE, ::Zip::PassThruDecompressor)
|
37
27
|
end
|
38
28
|
|
39
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
|