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
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
class InflaterTest < MiniTest::Test
|
3
|
+
include DecompressorTests
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@file = File.new('test/data/file1.txt.deflatedData', 'rb')
|
8
|
+
@decompressor = ::Zip::Inflater.new(@file)
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
@file.close
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ZipInputStreamTest < MiniTest::Test
|
4
|
+
include AssertEntry
|
5
|
+
|
6
|
+
class IOLike
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def initialize(path, mode)
|
10
|
+
@file = File.new(path, mode)
|
11
|
+
end
|
12
|
+
|
13
|
+
delegate ::Zip::File::IO_METHODS => :@file
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_new
|
17
|
+
zis = ::Zip::InputStream.new(TestZipFile::TEST_ZIP2.zip_name)
|
18
|
+
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
19
|
+
assert_equal(true, zis.eof?)
|
20
|
+
zis.close
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_open_with_block
|
24
|
+
::Zip::InputStream.open(TestZipFile::TEST_ZIP2.zip_name) do |zis|
|
25
|
+
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
26
|
+
assert_equal(true, zis.eof?)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_open_without_block
|
31
|
+
zis = ::Zip::InputStream.open(File.new(TestZipFile::TEST_ZIP2.zip_name, 'rb'))
|
32
|
+
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_open_buffer_with_block
|
36
|
+
::Zip::InputStream.open(File.new(TestZipFile::TEST_ZIP2.zip_name, 'rb')) do |zis|
|
37
|
+
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
38
|
+
assert_equal(true, zis.eof?)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_open_string_io_without_block
|
43
|
+
string_io = ::StringIO.new(::File.read(TestZipFile::TEST_ZIP2.zip_name))
|
44
|
+
zis = ::Zip::InputStream.open(string_io)
|
45
|
+
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_open_string_io_with_block
|
49
|
+
string_io = ::StringIO.new(::File.read(TestZipFile::TEST_ZIP2.zip_name))
|
50
|
+
::Zip::InputStream.open(string_io) do |zis|
|
51
|
+
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
52
|
+
assert_equal(true, zis.eof?)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_open_buffer_without_block
|
57
|
+
zis = ::Zip::InputStream.open(TestZipFile::TEST_ZIP2.zip_name)
|
58
|
+
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_open_io_like_with_block
|
62
|
+
::Zip::InputStream.open(IOLike.new(TestZipFile::TEST_ZIP2.zip_name, 'rb')) do |zis|
|
63
|
+
assert_stream_contents(zis, TestZipFile::TEST_ZIP2)
|
64
|
+
assert_equal(true, zis.eof?)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_incomplete_reads
|
69
|
+
::Zip::InputStream.open(TestZipFile::TEST_ZIP2.zip_name) do |zis|
|
70
|
+
entry = zis.get_next_entry # longAscii.txt
|
71
|
+
assert_equal(false, zis.eof?)
|
72
|
+
assert_equal(TestZipFile::TEST_ZIP2.entry_names[0], entry.name)
|
73
|
+
assert zis.gets.length > 0
|
74
|
+
assert_equal(false, zis.eof?)
|
75
|
+
entry = zis.get_next_entry # empty.txt
|
76
|
+
assert_equal(TestZipFile::TEST_ZIP2.entry_names[1], entry.name)
|
77
|
+
assert_equal(0, entry.size)
|
78
|
+
assert_equal(nil, zis.gets)
|
79
|
+
assert_equal(true, zis.eof?)
|
80
|
+
entry = zis.get_next_entry # empty_chmod640.txt
|
81
|
+
assert_equal(TestZipFile::TEST_ZIP2.entry_names[2], entry.name)
|
82
|
+
assert_equal(0, entry.size)
|
83
|
+
assert_equal(nil, zis.gets)
|
84
|
+
assert_equal(true, zis.eof?)
|
85
|
+
entry = zis.get_next_entry # short.txt
|
86
|
+
assert_equal(TestZipFile::TEST_ZIP2.entry_names[3], entry.name)
|
87
|
+
assert zis.gets.length > 0
|
88
|
+
entry = zis.get_next_entry # longBinary.bin
|
89
|
+
assert_equal(TestZipFile::TEST_ZIP2.entry_names[4], entry.name)
|
90
|
+
assert zis.gets.length > 0
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_incomplete_reads_from_string_io
|
95
|
+
string_io = ::StringIO.new(::File.read(TestZipFile::TEST_ZIP2.zip_name))
|
96
|
+
::Zip::InputStream.open(string_io) do |zis|
|
97
|
+
entry = zis.get_next_entry # longAscii.txt
|
98
|
+
assert_equal(false, zis.eof?)
|
99
|
+
assert_equal(TestZipFile::TEST_ZIP2.entry_names[0], entry.name)
|
100
|
+
assert zis.gets.length > 0
|
101
|
+
assert_equal(false, zis.eof?)
|
102
|
+
entry = zis.get_next_entry # empty.txt
|
103
|
+
assert_equal(TestZipFile::TEST_ZIP2.entry_names[1], entry.name)
|
104
|
+
assert_equal(0, entry.size)
|
105
|
+
assert_equal(nil, zis.gets)
|
106
|
+
assert_equal(true, zis.eof?)
|
107
|
+
entry = zis.get_next_entry # empty_chmod640.txt
|
108
|
+
assert_equal(TestZipFile::TEST_ZIP2.entry_names[2], entry.name)
|
109
|
+
assert_equal(0, entry.size)
|
110
|
+
assert_equal(nil, zis.gets)
|
111
|
+
assert_equal(true, zis.eof?)
|
112
|
+
entry = zis.get_next_entry # short.txt
|
113
|
+
assert_equal(TestZipFile::TEST_ZIP2.entry_names[3], entry.name)
|
114
|
+
assert zis.gets.length > 0
|
115
|
+
entry = zis.get_next_entry # longBinary.bin
|
116
|
+
assert_equal(TestZipFile::TEST_ZIP2.entry_names[4], entry.name)
|
117
|
+
assert zis.gets.length > 0
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_read_with_number_of_bytes_returns_nil_at_eof
|
122
|
+
::Zip::InputStream.open(TestZipFile::TEST_ZIP2.zip_name) do |zis|
|
123
|
+
entry = zis.get_next_entry # longAscii.txt
|
124
|
+
zis.read(entry.size)
|
125
|
+
assert_equal(true, zis.eof?)
|
126
|
+
assert_nil(zis.read(1))
|
127
|
+
assert_nil(zis.read(1))
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_rewind
|
132
|
+
::Zip::InputStream.open(TestZipFile::TEST_ZIP2.zip_name) do |zis|
|
133
|
+
e = zis.get_next_entry
|
134
|
+
assert_equal(TestZipFile::TEST_ZIP2.entry_names[0], e.name)
|
135
|
+
|
136
|
+
# Do a little reading
|
137
|
+
buf = ''
|
138
|
+
buf << zis.read(100)
|
139
|
+
assert_equal(100, zis.pos)
|
140
|
+
buf << (zis.gets || '')
|
141
|
+
buf << (zis.gets || '')
|
142
|
+
assert_equal(false, zis.eof?)
|
143
|
+
|
144
|
+
zis.rewind
|
145
|
+
|
146
|
+
buf2 = ''
|
147
|
+
buf2 << zis.read(100)
|
148
|
+
buf2 << (zis.gets || '')
|
149
|
+
buf2 << (zis.gets || '')
|
150
|
+
|
151
|
+
assert_equal(buf, buf2)
|
152
|
+
|
153
|
+
zis.rewind
|
154
|
+
assert_equal(false, zis.eof?)
|
155
|
+
assert_equal(0, zis.pos)
|
156
|
+
|
157
|
+
assert_entry(e.name, zis, e.name)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_mix_read_and_gets
|
162
|
+
::Zip::InputStream.open(TestZipFile::TEST_ZIP2.zip_name) do |zis|
|
163
|
+
zis.get_next_entry
|
164
|
+
assert_equal('#!/usr/bin/env ruby', zis.gets.chomp)
|
165
|
+
assert_equal(false, zis.eof?)
|
166
|
+
assert_equal('', zis.gets.chomp)
|
167
|
+
assert_equal(false, zis.eof?)
|
168
|
+
assert_equal('$VERBOSE =', zis.read(10))
|
169
|
+
assert_equal(false, zis.eof?)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_ungetc
|
174
|
+
::Zip::InputStream.open(TestZipFile::TEST_ZIP2.zip_name) do |zis|
|
175
|
+
zis.get_next_entry
|
176
|
+
first_line = zis.gets.chomp
|
177
|
+
first_line.reverse.bytes.each { |b| zis.ungetc(b) }
|
178
|
+
assert_equal('#!/usr/bin/env ruby', zis.gets.chomp)
|
179
|
+
assert_equal('$VERBOSE =', zis.read(10))
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'zip/ioextras'
|
3
|
+
|
4
|
+
class AbstractInputStreamTest < MiniTest::Test
|
5
|
+
# AbstractInputStream subclass that provides a read method
|
6
|
+
|
7
|
+
TEST_LINES = ["Hello world#{$/}",
|
8
|
+
"this is the second line#{$/}",
|
9
|
+
'this is the last line']
|
10
|
+
TEST_STRING = TEST_LINES.join
|
11
|
+
class TestAbstractInputStream
|
12
|
+
include ::Zip::IOExtras::AbstractInputStream
|
13
|
+
|
14
|
+
def initialize(aString)
|
15
|
+
super()
|
16
|
+
@contents = aString
|
17
|
+
@readPointer = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def sysread(charsToRead, _buf = nil)
|
21
|
+
retVal = @contents[@readPointer, charsToRead]
|
22
|
+
@readPointer += charsToRead
|
23
|
+
retVal
|
24
|
+
end
|
25
|
+
|
26
|
+
def produce_input
|
27
|
+
sysread(100)
|
28
|
+
end
|
29
|
+
|
30
|
+
def input_finished?
|
31
|
+
@contents[@readPointer].nil?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def setup
|
36
|
+
@io = TestAbstractInputStream.new(TEST_STRING)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_gets
|
40
|
+
assert_equal(TEST_LINES[0], @io.gets)
|
41
|
+
assert_equal(1, @io.lineno)
|
42
|
+
assert_equal(TEST_LINES[0].length, @io.pos)
|
43
|
+
assert_equal(TEST_LINES[1], @io.gets)
|
44
|
+
assert_equal(2, @io.lineno)
|
45
|
+
assert_equal(TEST_LINES[2], @io.gets)
|
46
|
+
assert_equal(3, @io.lineno)
|
47
|
+
assert_equal(nil, @io.gets)
|
48
|
+
assert_equal(4, @io.lineno)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_gets_multi_char_seperator
|
52
|
+
assert_equal('Hell', @io.gets('ll'))
|
53
|
+
assert_equal("o world#{$/}this is the second l", @io.gets('d l'))
|
54
|
+
end
|
55
|
+
|
56
|
+
LONG_LINES = [
|
57
|
+
'x' * 48 + "\r\n",
|
58
|
+
'y' * 49 + "\r\n",
|
59
|
+
'rest'
|
60
|
+
]
|
61
|
+
|
62
|
+
def test_gets_mulit_char_seperator_split
|
63
|
+
io = TestAbstractInputStream.new(LONG_LINES.join)
|
64
|
+
assert_equal(LONG_LINES[0], io.gets("\r\n"))
|
65
|
+
assert_equal(LONG_LINES[1], io.gets("\r\n"))
|
66
|
+
assert_equal(LONG_LINES[2], io.gets("\r\n"))
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_gets_with_sep_and_index
|
70
|
+
io = TestAbstractInputStream.new(LONG_LINES.join)
|
71
|
+
assert_equal('x', io.gets("\r\n", 1))
|
72
|
+
assert_equal('x' * 47 + "\r", io.gets("\r\n", 48))
|
73
|
+
assert_equal("\n", io.gets(nil, 1))
|
74
|
+
assert_equal('yy', io.gets(nil, 2))
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_gets_with_index
|
78
|
+
assert_equal(TEST_LINES[0], @io.gets(100))
|
79
|
+
assert_equal('this', @io.gets(4))
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_each_line
|
83
|
+
lineNumber = 0
|
84
|
+
@io.each_line do |line|
|
85
|
+
assert_equal(TEST_LINES[lineNumber], line)
|
86
|
+
lineNumber += 1
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_readlines
|
91
|
+
assert_equal(TEST_LINES, @io.readlines)
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_readline
|
95
|
+
test_gets
|
96
|
+
begin
|
97
|
+
@io.readline
|
98
|
+
fail 'EOFError expected'
|
99
|
+
rescue EOFError
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'zip/ioextras'
|
3
|
+
|
4
|
+
class AbstractOutputStreamTest < MiniTest::Test
|
5
|
+
class TestOutputStream
|
6
|
+
include ::Zip::IOExtras::AbstractOutputStream
|
7
|
+
|
8
|
+
attr_accessor :buffer
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@buffer = ''
|
12
|
+
end
|
13
|
+
|
14
|
+
def <<(data)
|
15
|
+
@buffer << data
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def setup
|
21
|
+
@output_stream = TestOutputStream.new
|
22
|
+
|
23
|
+
@origCommaSep = $,
|
24
|
+
@origOutputSep = $\
|
25
|
+
end
|
26
|
+
|
27
|
+
def teardown
|
28
|
+
$, = @origCommaSep
|
29
|
+
$\ = @origOutputSep
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_write
|
33
|
+
count = @output_stream.write('a little string')
|
34
|
+
assert_equal('a little string', @output_stream.buffer)
|
35
|
+
assert_equal('a little string'.length, count)
|
36
|
+
|
37
|
+
count = @output_stream.write('. a little more')
|
38
|
+
assert_equal('a little string. a little more', @output_stream.buffer)
|
39
|
+
assert_equal('. a little more'.length, count)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_print
|
43
|
+
$\ = nil # record separator set to nil
|
44
|
+
@output_stream.print('hello')
|
45
|
+
assert_equal('hello', @output_stream.buffer)
|
46
|
+
|
47
|
+
@output_stream.print(' world.')
|
48
|
+
assert_equal('hello world.', @output_stream.buffer)
|
49
|
+
|
50
|
+
@output_stream.print(' You ok ', 'out ', 'there?')
|
51
|
+
assert_equal('hello world. You ok out there?', @output_stream.buffer)
|
52
|
+
|
53
|
+
$\ = "\n"
|
54
|
+
@output_stream.print
|
55
|
+
assert_equal("hello world. You ok out there?\n", @output_stream.buffer)
|
56
|
+
|
57
|
+
@output_stream.print('I sure hope so!')
|
58
|
+
assert_equal("hello world. You ok out there?\nI sure hope so!\n", @output_stream.buffer)
|
59
|
+
|
60
|
+
$, = 'X'
|
61
|
+
@output_stream.buffer = ''
|
62
|
+
@output_stream.print('monkey', 'duck', 'zebra')
|
63
|
+
assert_equal("monkeyXduckXzebra\n", @output_stream.buffer)
|
64
|
+
|
65
|
+
$\ = nil
|
66
|
+
@output_stream.buffer = ''
|
67
|
+
@output_stream.print(20)
|
68
|
+
assert_equal('20', @output_stream.buffer)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_printf
|
72
|
+
@output_stream.printf('%d %04x', 123, 123)
|
73
|
+
assert_equal('123 007b', @output_stream.buffer)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_putc
|
77
|
+
@output_stream.putc('A')
|
78
|
+
assert_equal('A', @output_stream.buffer)
|
79
|
+
@output_stream.putc(65)
|
80
|
+
assert_equal('AA', @output_stream.buffer)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_puts
|
84
|
+
@output_stream.puts
|
85
|
+
assert_equal("\n", @output_stream.buffer)
|
86
|
+
|
87
|
+
@output_stream.puts('hello', 'world')
|
88
|
+
assert_equal("\nhello\nworld\n", @output_stream.buffer)
|
89
|
+
|
90
|
+
@output_stream.buffer = ''
|
91
|
+
@output_stream.puts("hello\n", "world\n")
|
92
|
+
assert_equal("hello\nworld\n", @output_stream.buffer)
|
93
|
+
|
94
|
+
@output_stream.buffer = ''
|
95
|
+
@output_stream.puts(["hello\n", "world\n"])
|
96
|
+
assert_equal("hello\nworld\n", @output_stream.buffer)
|
97
|
+
|
98
|
+
@output_stream.buffer = ''
|
99
|
+
@output_stream.puts(["hello\n", "world\n"], 'bingo')
|
100
|
+
assert_equal("hello\nworld\nbingo\n", @output_stream.buffer)
|
101
|
+
|
102
|
+
@output_stream.buffer = ''
|
103
|
+
@output_stream.puts(16, 20, 50, 'hello')
|
104
|
+
assert_equal("16\n20\n50\nhello\n", @output_stream.buffer)
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'zip/ioextras'
|
3
|
+
|
4
|
+
class FakeIOTest < MiniTest::Test
|
5
|
+
class FakeIOUsingClass
|
6
|
+
include ::Zip::IOExtras::FakeIO
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_kind_of?
|
10
|
+
obj = FakeIOUsingClass.new
|
11
|
+
|
12
|
+
assert(obj.kind_of?(Object))
|
13
|
+
assert(obj.kind_of?(FakeIOUsingClass))
|
14
|
+
assert(obj.kind_of?(IO))
|
15
|
+
assert(!obj.kind_of?(Fixnum))
|
16
|
+
assert(!obj.kind_of?(String))
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ZipLocalEntryTest < MiniTest::Test
|
4
|
+
CEH_FILE = 'test/data/generated/centralEntryHeader.bin'
|
5
|
+
LEH_FILE = 'test/data/generated/localEntryHeader.bin'
|
6
|
+
|
7
|
+
def teardown
|
8
|
+
::Zip.write_zip64_support = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_read_local_entry_header_of_first_test_zip_entry
|
12
|
+
::File.open(TestZipFile::TEST_ZIP3.zip_name, 'rb') do |file|
|
13
|
+
entry = ::Zip::Entry.read_local_entry(file)
|
14
|
+
|
15
|
+
assert_equal('', entry.comment)
|
16
|
+
# Differs from windows and unix because of CR LF
|
17
|
+
# assert_equal(480, entry.compressed_size)
|
18
|
+
# assert_equal(0x2a27930f, entry.crc)
|
19
|
+
# extra field is 21 bytes long
|
20
|
+
# probably contains some unix attrutes or something
|
21
|
+
# disabled: assert_equal(nil, entry.extra)
|
22
|
+
assert_equal(::Zip::Entry::DEFLATED, entry.compression_method)
|
23
|
+
assert_equal(TestZipFile::TEST_ZIP3.entry_names[0], entry.name)
|
24
|
+
assert_equal(::File.size(TestZipFile::TEST_ZIP3.entry_names[0]), entry.size)
|
25
|
+
assert(!entry.directory?)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_read_date_time
|
30
|
+
::File.open('test/data/rubycode.zip', 'rb') do |file|
|
31
|
+
entry = ::Zip::Entry.read_local_entry(file)
|
32
|
+
assert_equal('zippedruby1.rb', entry.name)
|
33
|
+
assert_equal(::Zip::DOSTime.at(1_019_261_638), entry.time)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_read_local_entry_from_non_zip_file
|
38
|
+
::File.open('test/data/file2.txt') do |file|
|
39
|
+
assert_equal(nil, ::Zip::Entry.read_local_entry(file))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_read_local_entry_from_truncated_zip_file
|
44
|
+
zipFragment = ''
|
45
|
+
::File.open(TestZipFile::TEST_ZIP2.zip_name) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes
|
46
|
+
zipFragment.extend(IOizeString).reset
|
47
|
+
entry = ::Zip::Entry.new
|
48
|
+
entry.read_local_entry(zipFragment)
|
49
|
+
fail 'ZipError expected'
|
50
|
+
rescue ::Zip::Error
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_write_entry
|
54
|
+
entry = ::Zip::Entry.new('file.zip', 'entryName', 'my little comment',
|
55
|
+
'thisIsSomeExtraInformation', 100, 987_654,
|
56
|
+
::Zip::Entry::DEFLATED, 400)
|
57
|
+
write_to_file(LEH_FILE, CEH_FILE, entry)
|
58
|
+
entryReadLocal, entryReadCentral = read_from_file(LEH_FILE, CEH_FILE)
|
59
|
+
assert(entryReadCentral.extra['Zip64Placeholder'].nil?, 'zip64 placeholder should not be used in central directory')
|
60
|
+
compare_local_entry_headers(entry, entryReadLocal)
|
61
|
+
compare_c_dir_entry_headers(entry, entryReadCentral)
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_write_entry_with_zip64
|
65
|
+
::Zip.write_zip64_support = true
|
66
|
+
entry = ::Zip::Entry.new('file.zip', 'entryName', 'my little comment',
|
67
|
+
'thisIsSomeExtraInformation', 100, 987_654,
|
68
|
+
::Zip::Entry::DEFLATED, 400)
|
69
|
+
write_to_file(LEH_FILE, CEH_FILE, entry)
|
70
|
+
entryReadLocal, entryReadCentral = read_from_file(LEH_FILE, CEH_FILE)
|
71
|
+
assert(entryReadLocal.extra['Zip64Placeholder'], 'zip64 placeholder should be used in local file header')
|
72
|
+
entryReadLocal.extra.delete('Zip64Placeholder') # it was removed when writing the c_dir_entry, so remove from compare
|
73
|
+
assert(entryReadCentral.extra['Zip64Placeholder'].nil?, 'zip64 placeholder should not be used in central directory')
|
74
|
+
compare_local_entry_headers(entry, entryReadLocal)
|
75
|
+
compare_c_dir_entry_headers(entry, entryReadCentral)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_write_64entry
|
79
|
+
::Zip.write_zip64_support = true
|
80
|
+
entry = ::Zip::Entry.new('bigfile.zip', 'entryName', 'my little equine',
|
81
|
+
'malformed extra field because why not',
|
82
|
+
0x7766554433221100, 0xDEADBEEF, ::Zip::Entry::DEFLATED,
|
83
|
+
0x9988776655443322)
|
84
|
+
write_to_file(LEH_FILE, CEH_FILE, entry)
|
85
|
+
entryReadLocal, entryReadCentral = read_from_file(LEH_FILE, CEH_FILE)
|
86
|
+
compare_local_entry_headers(entry, entryReadLocal)
|
87
|
+
compare_c_dir_entry_headers(entry, entryReadCentral)
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_rewrite_local_header64
|
91
|
+
::Zip.write_zip64_support = true
|
92
|
+
buf1 = StringIO.new
|
93
|
+
entry = ::Zip::Entry.new('file.zip', 'entryName')
|
94
|
+
entry.write_local_entry(buf1)
|
95
|
+
assert(entry.extra['Zip64'].nil?, 'zip64 extra is unnecessarily present')
|
96
|
+
|
97
|
+
buf2 = StringIO.new
|
98
|
+
entry.size = 0x123456789ABCDEF0
|
99
|
+
entry.compressed_size = 0x0123456789ABCDEF
|
100
|
+
entry.write_local_entry(buf2, true)
|
101
|
+
refute_nil(entry.extra['Zip64'])
|
102
|
+
refute_equal(buf1.size, 0)
|
103
|
+
assert_equal(buf1.size, buf2.size) # it can't grow, or we'd clobber file data
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_read_local_offset
|
107
|
+
entry = ::Zip::Entry.new('file.zip', 'entryName')
|
108
|
+
entry.local_header_offset = 12_345
|
109
|
+
::File.open(CEH_FILE, 'wb') { |f| entry.write_c_dir_entry(f) }
|
110
|
+
read_entry = nil
|
111
|
+
::File.open(CEH_FILE, 'rb') { |f| read_entry = ::Zip::Entry.read_c_dir_entry(f) }
|
112
|
+
compare_c_dir_entry_headers(entry, read_entry)
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_read64_local_offset
|
116
|
+
::Zip.write_zip64_support = true
|
117
|
+
entry = ::Zip::Entry.new('file.zip', 'entryName')
|
118
|
+
entry.local_header_offset = 0x0123456789ABCDEF
|
119
|
+
::File.open(CEH_FILE, 'wb') { |f| entry.write_c_dir_entry(f) }
|
120
|
+
read_entry = nil
|
121
|
+
::File.open(CEH_FILE, 'rb') { |f| read_entry = ::Zip::Entry.read_c_dir_entry(f) }
|
122
|
+
compare_c_dir_entry_headers(entry, read_entry)
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
def compare_local_entry_headers(entry1, entry2)
|
128
|
+
assert_equal(entry1.compressed_size, entry2.compressed_size)
|
129
|
+
assert_equal(entry1.crc, entry2.crc)
|
130
|
+
assert_equal(entry1.extra, entry2.extra)
|
131
|
+
assert_equal(entry1.compression_method, entry2.compression_method)
|
132
|
+
assert_equal(entry1.name, entry2.name)
|
133
|
+
assert_equal(entry1.size, entry2.size)
|
134
|
+
assert_equal(entry1.local_header_offset, entry2.local_header_offset)
|
135
|
+
end
|
136
|
+
|
137
|
+
def compare_c_dir_entry_headers(entry1, entry2)
|
138
|
+
compare_local_entry_headers(entry1, entry2)
|
139
|
+
assert_equal(entry1.comment, entry2.comment)
|
140
|
+
end
|
141
|
+
|
142
|
+
def write_to_file(localFileName, centralFileName, entry)
|
143
|
+
::File.open(localFileName, 'wb') { |f| entry.write_local_entry(f) }
|
144
|
+
::File.open(centralFileName, 'wb') { |f| entry.write_c_dir_entry(f) }
|
145
|
+
end
|
146
|
+
|
147
|
+
def read_from_file(localFileName, centralFileName)
|
148
|
+
localEntry = nil
|
149
|
+
cdirEntry = nil
|
150
|
+
::File.open(localFileName, 'rb') { |f| localEntry = ::Zip::Entry.read_local_entry(f) }
|
151
|
+
::File.open(centralFileName, 'rb') { |f| cdirEntry = ::Zip::Entry.read_c_dir_entry(f) }
|
152
|
+
[localEntry, cdirEntry]
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ZipOutputStreamTest < MiniTest::Test
|
4
|
+
include AssertEntry
|
5
|
+
|
6
|
+
TEST_ZIP = TestZipFile::TEST_ZIP2.clone
|
7
|
+
TEST_ZIP.zip_name = 'test/data/generated/output.zip'
|
8
|
+
|
9
|
+
def test_new
|
10
|
+
zos = ::Zip::OutputStream.new(TEST_ZIP.zip_name)
|
11
|
+
zos.comment = TEST_ZIP.comment
|
12
|
+
write_test_zip(zos)
|
13
|
+
zos.close
|
14
|
+
assert_test_zip_contents(TEST_ZIP)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_open
|
18
|
+
::Zip::OutputStream.open(TEST_ZIP.zip_name) do |zos|
|
19
|
+
zos.comment = TEST_ZIP.comment
|
20
|
+
write_test_zip(zos)
|
21
|
+
end
|
22
|
+
assert_test_zip_contents(TEST_ZIP)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_write_buffer
|
26
|
+
io = ::StringIO.new('')
|
27
|
+
buffer = ::Zip::OutputStream.write_buffer(io) do |zos|
|
28
|
+
zos.comment = TEST_ZIP.comment
|
29
|
+
write_test_zip(zos)
|
30
|
+
end
|
31
|
+
File.open(TEST_ZIP.zip_name, 'wb') { |f| f.write buffer.string }
|
32
|
+
assert_test_zip_contents(TEST_ZIP)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_write_buffer_with_temp_file
|
36
|
+
tmp_file = Tempfile.new('')
|
37
|
+
|
38
|
+
::Zip::OutputStream.write_buffer(tmp_file) do |zos|
|
39
|
+
zos.comment = TEST_ZIP.comment
|
40
|
+
write_test_zip(zos)
|
41
|
+
end
|
42
|
+
|
43
|
+
tmp_file.rewind
|
44
|
+
File.open(TEST_ZIP.zip_name, 'wb') { |f| f.write(tmp_file.read) }
|
45
|
+
tmp_file.unlink
|
46
|
+
|
47
|
+
assert_test_zip_contents(TEST_ZIP)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_writing_to_closed_stream
|
51
|
+
assert_i_o_error_in_closed_stream { |zos| zos << 'hello world' }
|
52
|
+
assert_i_o_error_in_closed_stream { |zos| zos.puts 'hello world' }
|
53
|
+
assert_i_o_error_in_closed_stream { |zos| zos.write 'hello world' }
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_cannot_open_file
|
57
|
+
name = TestFiles::EMPTY_TEST_DIR
|
58
|
+
begin
|
59
|
+
::Zip::OutputStream.open(name)
|
60
|
+
rescue Exception
|
61
|
+
assert($!.kind_of?(Errno::EISDIR) || # Linux
|
62
|
+
$!.kind_of?(Errno::EEXIST) || # Windows/cygwin
|
63
|
+
$!.kind_of?(Errno::EACCES), # Windows
|
64
|
+
"Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.class}")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_put_next_entry
|
69
|
+
stored_text = 'hello world in stored text'
|
70
|
+
entry_name = 'file1'
|
71
|
+
comment = 'my comment'
|
72
|
+
::Zip::OutputStream.open(TEST_ZIP.zip_name) do |zos|
|
73
|
+
zos.put_next_entry(entry_name, comment, nil, ::Zip::Entry::STORED)
|
74
|
+
zos << stored_text
|
75
|
+
end
|
76
|
+
|
77
|
+
assert(File.read(TEST_ZIP.zip_name)[stored_text])
|
78
|
+
::Zip::File.open(TEST_ZIP.zip_name) do |zf|
|
79
|
+
assert_equal(stored_text, zf.read(entry_name))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_put_next_entry_using_zip_entry_creates_entries_with_correct_timestamps
|
84
|
+
file = ::File.open('test/data/file2.txt', 'rb')
|
85
|
+
::Zip::OutputStream.open(TEST_ZIP.zip_name) do |zos|
|
86
|
+
zip_entry = ::Zip::Entry.new(zos, file.path, '', '', 0, 0, ::Zip::Entry::DEFLATED, 0, ::Zip::DOSTime.at(file.mtime))
|
87
|
+
zos.put_next_entry(zip_entry)
|
88
|
+
zos << file.read
|
89
|
+
end
|
90
|
+
|
91
|
+
::Zip::InputStream.open(TEST_ZIP.zip_name) do |io|
|
92
|
+
while (entry = io.get_next_entry)
|
93
|
+
assert(::Zip::DOSTime.at(file.mtime).dos_equals(::Zip::DOSTime.at(entry.mtime))) # Compare DOS Times, since they are stored with two seconds accuracy
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_chained_put_into_next_entry
|
99
|
+
stored_text = 'hello world in stored text'
|
100
|
+
stored_text2 = 'with chain'
|
101
|
+
entry_name = 'file1'
|
102
|
+
comment = 'my comment'
|
103
|
+
::Zip::OutputStream.open(TEST_ZIP.zip_name) do |zos|
|
104
|
+
zos.put_next_entry(entry_name, comment, nil, ::Zip::Entry::STORED)
|
105
|
+
zos << stored_text << stored_text2
|
106
|
+
end
|
107
|
+
|
108
|
+
assert(File.read(TEST_ZIP.zip_name)[stored_text])
|
109
|
+
::Zip::File.open(TEST_ZIP.zip_name) do |zf|
|
110
|
+
assert_equal(stored_text + stored_text2, zf.read(entry_name))
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def assert_i_o_error_in_closed_stream
|
115
|
+
assert_raises(IOError) do
|
116
|
+
zos = ::Zip::OutputStream.new('test/data/generated/test_putOnClosedStream.zip')
|
117
|
+
zos.close
|
118
|
+
yield zos
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def write_test_zip(zos)
|
123
|
+
TEST_ZIP.entry_names.each do |entryName|
|
124
|
+
zos.put_next_entry(entryName)
|
125
|
+
File.open(entryName, 'rb') { |f| zos.write(f.read) }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|