rubyzip 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubyzip might be problematic. Click here for more details.
- checksums.yaml +6 -14
- data/README.md +173 -42
- data/Rakefile +10 -5
- data/TODO +0 -1
- data/lib/zip/central_directory.rb +55 -24
- data/lib/zip/compressor.rb +0 -0
- data/lib/zip/constants.rb +4 -2
- data/lib/zip/crypto/encryption.rb +11 -0
- data/lib/zip/crypto/null_encryption.rb +45 -0
- data/lib/zip/crypto/traditional_encryption.rb +99 -0
- data/lib/zip/decompressor.rb +2 -2
- data/lib/zip/deflater.rb +11 -6
- data/lib/zip/dos_time.rb +4 -5
- data/lib/zip/entry.rb +159 -97
- data/lib/zip/entry_set.rb +18 -18
- data/lib/zip/errors.rb +15 -6
- data/lib/zip/extra_field/generic.rb +8 -8
- 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 +14 -14
- data/lib/zip/extra_field/unix.rb +8 -9
- data/lib/zip/extra_field/zip64.rb +44 -6
- data/lib/zip/extra_field/zip64_placeholder.rb +16 -0
- data/lib/zip/extra_field.rb +20 -8
- data/lib/zip/file.rb +126 -114
- data/lib/zip/filesystem.rb +140 -139
- data/lib/zip/inflater.rb +10 -9
- data/lib/zip/input_stream.rb +105 -80
- data/lib/zip/ioextras/abstract_input_stream.rb +15 -12
- data/lib/zip/ioextras/abstract_output_stream.rb +0 -2
- data/lib/zip/ioextras.rb +1 -3
- data/lib/zip/null_compressor.rb +2 -2
- data/lib/zip/null_decompressor.rb +4 -4
- data/lib/zip/null_input_stream.rb +2 -1
- data/lib/zip/output_stream.rb +57 -43
- data/lib/zip/pass_thru_compressor.rb +4 -4
- data/lib/zip/pass_thru_decompressor.rb +4 -5
- data/lib/zip/streamable_directory.rb +2 -2
- data/lib/zip/streamable_stream.rb +22 -13
- data/lib/zip/version.rb +1 -1
- data/lib/zip.rb +11 -2
- data/samples/example.rb +30 -40
- data/samples/example_filesystem.rb +16 -18
- data/samples/example_recursive.rb +35 -27
- data/samples/{gtkRubyzip.rb → gtk_ruby_zip.rb} +25 -27
- data/samples/qtzip.rb +19 -28
- data/samples/write_simple.rb +12 -13
- data/samples/zipfind.rb +29 -37
- 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 +53 -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/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/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 +152 -0
- data/test/entry_test.rb +163 -0
- data/test/errors_test.rb +34 -0
- data/test/extra_field_test.rb +76 -0
- data/test/file_extract_directory_test.rb +54 -0
- data/test/file_extract_test.rb +83 -0
- data/test/file_permissions_test.rb +69 -0
- data/test/file_split_test.rb +57 -0
- data/test/file_test.rb +563 -0
- data/test/filesystem/dir_iterator_test.rb +58 -0
- data/test/filesystem/directory_test.rb +121 -0
- data/test/filesystem/file_mutating_test.rb +88 -0
- data/test/filesystem/file_nonmutating_test.rb +508 -0
- data/test/filesystem/file_stat_test.rb +64 -0
- data/test/gentestfiles.rb +122 -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/samples/example_recursive_test.rb +37 -0
- data/test/settings_test.rb +95 -0
- data/test/test_helper.rb +221 -0
- data/test/unicode_file_names_and_comments_test.rb +50 -0
- data/test/zip64_full_test.rb +51 -0
- data/test/zip64_support_test.rb +14 -0
- metadata +198 -22
- data/NEWS +0 -182
data/lib/zip/input_stream.rb
CHANGED
@@ -1,43 +1,41 @@
|
|
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
|
@@ -46,88 +44,115 @@ module Zip
|
|
46
44
|
# Opens the indicated zip file. An exception is thrown
|
47
45
|
# if the specified offset in the specified filename is
|
48
46
|
# not a local zip entry header.
|
49
|
-
|
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)
|
50
51
|
super()
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
@archiveIO = io
|
56
|
-
end
|
57
|
-
@decompressor = NullDecompressor.instance
|
58
|
-
@currentEntry = nil
|
59
|
-
end
|
60
|
-
|
61
|
-
def close
|
62
|
-
@archiveIO.close
|
63
|
-
end
|
64
|
-
|
65
|
-
# Same as #initialize but if a block is passed the opened
|
66
|
-
# stream is passed to the block and closed when the block
|
67
|
-
# returns.
|
68
|
-
def InputStream.open(filename)
|
69
|
-
return new(filename) unless block_given?
|
70
|
-
|
71
|
-
zio = new(filename)
|
72
|
-
yield zio
|
73
|
-
ensure
|
74
|
-
zio.close if zio
|
52
|
+
@archive_io = get_io(context, offset)
|
53
|
+
@decompressor = ::Zip::NullDecompressor
|
54
|
+
@decrypter = decrypter || ::Zip::NullDecrypter.new
|
55
|
+
@current_entry = nil
|
75
56
|
end
|
76
57
|
|
77
|
-
def
|
78
|
-
|
79
|
-
zio = new('',0,io)
|
80
|
-
yield zio
|
81
|
-
ensure
|
82
|
-
zio.close if zio
|
58
|
+
def close
|
59
|
+
@archive_io.close
|
83
60
|
end
|
84
61
|
|
85
|
-
# Returns a
|
86
|
-
# method on a newly created
|
87
|
-
# the first entry in the archive. Returns nil when there are
|
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
|
88
65
|
# no more entries.
|
89
|
-
|
90
66
|
def get_next_entry
|
91
|
-
@
|
67
|
+
@archive_io.seek(@current_entry.next_header_offset, IO::SEEK_SET) if @current_entry
|
92
68
|
open_entry
|
93
69
|
end
|
94
70
|
|
95
71
|
# Rewinds the stream to the beginning of the current entry
|
96
72
|
def rewind
|
97
|
-
return if @
|
73
|
+
return if @current_entry.nil?
|
98
74
|
@lineno = 0
|
99
|
-
@pos
|
100
|
-
@
|
101
|
-
IO::SEEK_SET)
|
75
|
+
@pos = 0
|
76
|
+
@archive_io.seek(@current_entry.local_header_offset, IO::SEEK_SET)
|
102
77
|
open_entry
|
103
78
|
end
|
104
79
|
|
105
80
|
# Modeled after IO.sysread
|
106
|
-
def sysread(
|
107
|
-
@decompressor.sysread(
|
81
|
+
def sysread(number_of_bytes = nil, buf = nil)
|
82
|
+
@decompressor.sysread(number_of_bytes, buf)
|
108
83
|
end
|
109
84
|
|
110
85
|
def eof
|
111
86
|
@output_buffer.empty? && @decompressor.eof
|
112
87
|
end
|
113
|
-
|
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
|
114
110
|
|
115
111
|
protected
|
116
112
|
|
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)
|
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
|
125
118
|
else
|
126
|
-
|
127
|
-
|
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'
|
128
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 && !@internal
|
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
|
129
138
|
flush
|
130
|
-
|
139
|
+
@current_entry
|
140
|
+
end
|
141
|
+
|
142
|
+
def get_decompressor
|
143
|
+
case
|
144
|
+
when @current_entry.nil?
|
145
|
+
::Zip::NullDecompressor
|
146
|
+
when @current_entry.compression_method == ::Zip::Entry::STORED
|
147
|
+
::Zip::PassThruDecompressor.new(@archive_io, @current_entry.size)
|
148
|
+
when @current_entry.compression_method == ::Zip::Entry::DEFLATED
|
149
|
+
header = @archive_io.read(@decrypter.header_bytesize)
|
150
|
+
@decrypter.reset!(header)
|
151
|
+
::Zip::Inflater.new(@archive_io, @decrypter)
|
152
|
+
else
|
153
|
+
raise ::Zip::CompressionMethodError,
|
154
|
+
"Unsupported compression method #{@current_entry.compression_method}"
|
155
|
+
end
|
131
156
|
end
|
132
157
|
|
133
158
|
def produce_input
|
@@ -17,7 +17,7 @@ module Zip
|
|
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 = '')
|
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)
|
@@ -33,9 +33,12 @@ module Zip
|
|
33
33
|
sysread(number_of_bytes, buf)
|
34
34
|
end
|
35
35
|
|
36
|
-
|
36
|
+
if tbuf.nil? || tbuf.length == 0
|
37
|
+
return nil if number_of_bytes
|
38
|
+
return ''
|
39
|
+
end
|
37
40
|
|
38
|
-
|
41
|
+
@pos += tbuf.length
|
39
42
|
|
40
43
|
if buf
|
41
44
|
buf.replace(tbuf)
|
@@ -72,15 +75,17 @@ module Zip
|
|
72
75
|
over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
|
73
76
|
while (match_index = @output_buffer.index(a_sep_string, buffer_index)).nil? && !over_limit
|
74
77
|
buffer_index = [buffer_index, @output_buffer.bytesize - a_sep_string.bytesize].max
|
75
|
-
if input_finished?
|
76
|
-
return @output_buffer.empty? ? nil : flush
|
77
|
-
end
|
78
|
+
return @output_buffer.empty? ? nil : flush if input_finished?
|
78
79
|
@output_buffer << produce_input
|
79
80
|
over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
|
80
81
|
end
|
81
82
|
sep_index = [match_index + a_sep_string.bytesize, number_of_bytes || @output_buffer.bytesize].min
|
82
|
-
@pos
|
83
|
-
|
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
|
84
89
|
end
|
85
90
|
|
86
91
|
def flush
|
@@ -96,13 +101,11 @@ module Zip
|
|
96
101
|
end
|
97
102
|
|
98
103
|
def each_line(a_sep_string = $/)
|
99
|
-
while true
|
100
|
-
yield readline(a_sep_string)
|
101
|
-
end
|
104
|
+
yield readline(a_sep_string) while true
|
102
105
|
rescue EOFError
|
103
106
|
end
|
104
107
|
|
105
108
|
alias_method :each, :each_line
|
106
109
|
end
|
107
110
|
end
|
108
|
-
end
|
111
|
+
end
|
data/lib/zip/ioextras.rb
CHANGED
data/lib/zip/null_compressor.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Zip
|
2
|
-
|
3
|
-
|
2
|
+
module NullDecompressor #:nodoc:all
|
3
|
+
module_function
|
4
4
|
|
5
|
-
def sysread(
|
5
|
+
def sysread(_numberOfBytes = nil, _buf = nil)
|
6
6
|
nil
|
7
7
|
end
|
8
8
|
|
@@ -18,7 +18,7 @@ module Zip
|
|
18
18
|
true
|
19
19
|
end
|
20
20
|
|
21
|
-
alias
|
21
|
+
alias eof? eof
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
data/lib/zip/output_stream.rb
CHANGED
@@ -24,18 +24,22 @@ 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(
|
27
|
+
def initialize(file_name, stream = false, encrypter = nil)
|
28
28
|
super()
|
29
|
-
@
|
30
|
-
if stream
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
@file_name = file_name
|
30
|
+
@output_stream = if stream
|
31
|
+
iostream = @file_name.dup
|
32
|
+
iostream.reopen(@file_name)
|
33
|
+
iostream.rewind
|
34
|
+
iostream
|
35
|
+
else
|
36
|
+
::File.new(@file_name, 'wb')
|
37
|
+
end
|
35
38
|
@entry_set = ::Zip::EntrySet.new
|
36
39
|
@compressor = ::Zip::NullCompressor.instance
|
40
|
+
@encrypter = encrypter || ::Zip::NullEncrypter.new
|
37
41
|
@closed = false
|
38
|
-
@
|
42
|
+
@current_entry = nil
|
39
43
|
@comment = nil
|
40
44
|
end
|
41
45
|
|
@@ -43,19 +47,19 @@ module Zip
|
|
43
47
|
# stream is passed to the block and closed when the block
|
44
48
|
# returns.
|
45
49
|
class << self
|
46
|
-
def open(
|
47
|
-
return new(
|
48
|
-
zos = new(
|
50
|
+
def open(file_name, encrypter = nil)
|
51
|
+
return new(file_name) unless block_given?
|
52
|
+
zos = new(file_name, false, encrypter)
|
49
53
|
yield zos
|
50
54
|
ensure
|
51
55
|
zos.close if zos
|
52
56
|
end
|
53
57
|
|
54
|
-
|
55
|
-
def write_buffer
|
56
|
-
zos = new(
|
58
|
+
# Same as #open but writes to a filestream instead
|
59
|
+
def write_buffer(io = ::StringIO.new(''), encrypter = nil)
|
60
|
+
zos = new(io, true, encrypter)
|
57
61
|
yield zos
|
58
|
-
|
62
|
+
zos.close_buffer
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
@@ -79,66 +83,74 @@ module Zip
|
|
79
83
|
@output_stream
|
80
84
|
end
|
81
85
|
|
82
|
-
|
86
|
+
# Closes the current entry and opens a new for writing.
|
83
87
|
# +entry+ can be a ZipEntry object or a string.
|
84
|
-
def put_next_entry(
|
85
|
-
raise
|
86
|
-
if
|
87
|
-
new_entry =
|
88
|
+
def put_next_entry(entry_name, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zip.default_compression)
|
89
|
+
raise Error, 'zip stream is closed' if @closed
|
90
|
+
if entry_name.kind_of?(Entry)
|
91
|
+
new_entry = entry_name
|
88
92
|
else
|
89
|
-
new_entry = Entry.new(@
|
93
|
+
new_entry = Entry.new(@file_name, entry_name.to_s)
|
90
94
|
end
|
91
|
-
new_entry.comment = comment
|
92
|
-
|
93
|
-
new_entry.extra = ExtraField
|
95
|
+
new_entry.comment = comment unless comment.nil?
|
96
|
+
unless extra.nil?
|
97
|
+
new_entry.extra = extra.is_a?(ExtraField) ? extra : ExtraField.new(extra.to_s)
|
94
98
|
end
|
95
|
-
new_entry.compression_method = compression_method
|
99
|
+
new_entry.compression_method = compression_method unless compression_method.nil?
|
96
100
|
init_next_entry(new_entry, level)
|
97
|
-
@
|
101
|
+
@current_entry = new_entry
|
98
102
|
end
|
99
103
|
|
100
104
|
def copy_raw_entry(entry)
|
101
105
|
entry = entry.dup
|
102
|
-
raise
|
103
|
-
raise
|
106
|
+
raise Error, 'zip stream is closed' if @closed
|
107
|
+
raise Error, 'entry is not a ZipEntry' unless entry.is_a?(Entry)
|
104
108
|
finalize_current_entry
|
105
109
|
@entry_set << entry
|
106
|
-
src_pos = entry.
|
110
|
+
src_pos = entry.local_header_offset
|
107
111
|
entry.write_local_entry(@output_stream)
|
108
112
|
@compressor = NullCompressor.instance
|
109
113
|
entry.get_raw_input_stream do |is|
|
110
114
|
is.seek(src_pos, IO::SEEK_SET)
|
115
|
+
::Zip::Entry.read_local_entry(is)
|
111
116
|
IOExtras.copy_stream_n(@output_stream, is, entry.compressed_size)
|
112
117
|
end
|
113
118
|
@compressor = NullCompressor.instance
|
114
|
-
@
|
119
|
+
@current_entry = nil
|
115
120
|
end
|
116
121
|
|
117
122
|
private
|
118
123
|
|
119
124
|
def finalize_current_entry
|
120
|
-
return unless @
|
125
|
+
return unless @current_entry
|
121
126
|
finish
|
122
|
-
@
|
123
|
-
@
|
124
|
-
@
|
125
|
-
@
|
126
|
-
@
|
127
|
+
@current_entry.compressed_size = @output_stream.tell - @current_entry.local_header_offset - @current_entry.calculate_local_header_size
|
128
|
+
@current_entry.size = @compressor.size
|
129
|
+
@current_entry.crc = @compressor.crc
|
130
|
+
@output_stream << @encrypter.data_descriptor(@current_entry.crc, @current_entry.compressed_size, @current_entry.size)
|
131
|
+
@current_entry.gp_flags |= @encrypter.gp_flags
|
132
|
+
@current_entry = nil
|
133
|
+
@compressor = ::Zip::NullCompressor.instance
|
127
134
|
end
|
128
135
|
|
129
|
-
def init_next_entry(entry, level =
|
136
|
+
def init_next_entry(entry, level = Zip.default_compression)
|
130
137
|
finalize_current_entry
|
131
138
|
@entry_set << entry
|
132
139
|
entry.write_local_entry(@output_stream)
|
140
|
+
@encrypter.reset!
|
141
|
+
@output_stream << @encrypter.header(entry.mtime)
|
133
142
|
@compressor = get_compressor(entry, level)
|
134
143
|
end
|
135
144
|
|
136
145
|
def get_compressor(entry, level)
|
137
146
|
case entry.compression_method
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
147
|
+
when Entry::DEFLATED then
|
148
|
+
::Zip::Deflater.new(@output_stream, level, @encrypter)
|
149
|
+
when Entry::STORED then
|
150
|
+
::Zip::PassThruCompressor.new(@output_stream)
|
151
|
+
else
|
152
|
+
raise ::Zip::CompressionMethodError,
|
153
|
+
"Invalid compression method: '#{entry.compression_method}'"
|
142
154
|
end
|
143
155
|
end
|
144
156
|
|
@@ -146,7 +158,7 @@ module Zip
|
|
146
158
|
pos = @output_stream.pos
|
147
159
|
@entry_set.each do |entry|
|
148
160
|
@output_stream.pos = entry.local_header_offset
|
149
|
-
entry.write_local_entry(@output_stream)
|
161
|
+
entry.write_local_entry(@output_stream, true)
|
150
162
|
end
|
151
163
|
@output_stream.pos = pos
|
152
164
|
end
|
@@ -163,9 +175,11 @@ module Zip
|
|
163
175
|
end
|
164
176
|
|
165
177
|
public
|
178
|
+
|
166
179
|
# Modeled after IO.<<
|
167
|
-
def <<
|
180
|
+
def <<(data)
|
168
181
|
@compressor << data
|
182
|
+
self
|
169
183
|
end
|
170
184
|
end
|
171
185
|
end
|
@@ -3,13 +3,13 @@ module Zip
|
|
3
3
|
def initialize(outputStream)
|
4
4
|
super()
|
5
5
|
@output_stream = outputStream
|
6
|
-
@crc = Zlib
|
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,6 +1,5 @@
|
|
1
1
|
module Zip
|
2
2
|
class PassThruDecompressor < Decompressor #:nodoc:all
|
3
|
-
|
4
3
|
def initialize(input_stream, chars_to_read)
|
5
4
|
super(input_stream)
|
6
5
|
@chars_to_read = chars_to_read
|
@@ -8,7 +7,7 @@ module Zip
|
|
8
7
|
@has_returned_empty_string = false
|
9
8
|
end
|
10
9
|
|
11
|
-
def sysread(number_of_bytes = nil, buf =
|
10
|
+
def sysread(number_of_bytes = nil, buf = '')
|
12
11
|
if input_finished?
|
13
12
|
has_returned_empty_string_val = @has_returned_empty_string
|
14
13
|
@has_returned_empty_string = true
|
@@ -16,7 +15,7 @@ module Zip
|
|
16
15
|
return
|
17
16
|
end
|
18
17
|
|
19
|
-
if
|
18
|
+
if number_of_bytes.nil? || @read_so_far + number_of_bytes > @chars_to_read
|
20
19
|
number_of_bytes = @chars_to_read - @read_so_far
|
21
20
|
end
|
22
21
|
@read_so_far += number_of_bytes
|
@@ -31,8 +30,8 @@ module Zip
|
|
31
30
|
@read_so_far >= @chars_to_read
|
32
31
|
end
|
33
32
|
|
34
|
-
alias
|
35
|
-
alias
|
33
|
+
alias eof input_finished?
|
34
|
+
alias eof? input_finished?
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
@@ -4,8 +4,8 @@ module Zip
|
|
4
4
|
super(zipfile, entry)
|
5
5
|
|
6
6
|
@ftype = :directory
|
7
|
-
entry.get_extra_attributes_from_path(srcPath) if
|
8
|
-
@unix_perms = permissionInt if
|
7
|
+
entry.get_extra_attributes_from_path(srcPath) if srcPath
|
8
|
+
@unix_perms = permissionInt if permissionInt
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|