rubyzip 1.3.0 → 3.0.0.alpha
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/Changelog.md +368 -0
- data/README.md +123 -46
- data/Rakefile +13 -6
- data/lib/zip/central_directory.rb +166 -116
- data/lib/zip/compressor.rb +3 -1
- data/lib/zip/constants.rb +77 -21
- data/lib/zip/crypto/decrypted_io.rb +42 -0
- data/lib/zip/crypto/encryption.rb +4 -2
- data/lib/zip/crypto/null_encryption.rb +5 -3
- data/lib/zip/crypto/traditional_encryption.rb +14 -12
- data/lib/zip/decompressor.rb +21 -2
- data/lib/zip/deflater.rb +10 -8
- data/lib/zip/dirtyable.rb +32 -0
- data/lib/zip/dos_time.rb +53 -12
- data/lib/zip/entry.rb +306 -184
- data/lib/zip/entry_set.rb +11 -7
- data/lib/zip/errors.rb +115 -15
- data/lib/zip/extra_field/generic.rb +11 -17
- data/lib/zip/extra_field/ntfs.rb +8 -2
- data/lib/zip/extra_field/old_unix.rb +6 -2
- data/lib/zip/extra_field/universal_time.rb +45 -13
- data/lib/zip/extra_field/unix.rb +7 -3
- data/lib/zip/extra_field/unknown.rb +33 -0
- data/lib/zip/extra_field/zip64.rb +16 -7
- data/lib/zip/extra_field.rb +22 -26
- data/lib/zip/file.rb +196 -240
- data/lib/zip/file_split.rb +97 -0
- data/lib/zip/filesystem/dir.rb +86 -0
- data/lib/zip/filesystem/directory_iterator.rb +48 -0
- data/lib/zip/filesystem/file.rb +262 -0
- data/lib/zip/filesystem/file_stat.rb +110 -0
- data/lib/zip/filesystem/zip_file_name_mapper.rb +81 -0
- data/lib/zip/filesystem.rb +31 -584
- data/lib/zip/inflater.rb +27 -37
- data/lib/zip/input_stream.rb +67 -42
- data/lib/zip/ioextras/abstract_input_stream.rb +32 -16
- data/lib/zip/ioextras/abstract_output_stream.rb +5 -3
- data/lib/zip/ioextras.rb +7 -7
- data/lib/zip/null_compressor.rb +3 -1
- data/lib/zip/null_decompressor.rb +4 -10
- data/lib/zip/null_input_stream.rb +3 -1
- data/lib/zip/output_stream.rb +58 -43
- data/lib/zip/pass_thru_compressor.rb +5 -3
- data/lib/zip/pass_thru_decompressor.rb +16 -23
- data/lib/zip/streamable_directory.rb +6 -4
- data/lib/zip/streamable_stream.rb +9 -10
- data/lib/zip/version.rb +3 -1
- data/lib/zip.rb +19 -4
- data/rubyzip.gemspec +38 -0
- data/samples/example.rb +9 -4
- data/samples/example_filesystem.rb +3 -2
- data/samples/example_recursive.rb +3 -1
- data/samples/gtk_ruby_zip.rb +22 -20
- data/samples/qtzip.rb +12 -11
- data/samples/write_simple.rb +3 -4
- data/samples/zipfind.rb +24 -22
- metadata +86 -179
- data/TODO +0 -15
- data/lib/zip/extra_field/zip64_placeholder.rb +0 -15
- 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
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class ZipFileExtractDirectoryTest < MiniTest::Test
|
4
|
-
include CommonZipFileFixture
|
5
|
-
|
6
|
-
TEST_OUT_NAME = 'test/data/generated/emptyOutDir'
|
7
|
-
|
8
|
-
def open_zip(&aProc)
|
9
|
-
assert(!aProc.nil?)
|
10
|
-
::Zip::File.open(TestZipFile::TEST_ZIP4.zip_name, &aProc)
|
11
|
-
end
|
12
|
-
|
13
|
-
def extract_test_dir(&aProc)
|
14
|
-
open_zip do |zf|
|
15
|
-
zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def setup
|
20
|
-
super
|
21
|
-
|
22
|
-
Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME
|
23
|
-
File.delete(TEST_OUT_NAME) if File.exist? TEST_OUT_NAME
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_extract_directory
|
27
|
-
extract_test_dir
|
28
|
-
assert(File.directory?(TEST_OUT_NAME))
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_extract_directory_exists_as_dir
|
32
|
-
Dir.mkdir TEST_OUT_NAME
|
33
|
-
extract_test_dir
|
34
|
-
assert(File.directory?(TEST_OUT_NAME))
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_extract_directory_exists_as_file
|
38
|
-
File.open(TEST_OUT_NAME, 'w') { |f| f.puts 'something' }
|
39
|
-
assert_raises(::Zip::DestinationFileExistsError) { extract_test_dir }
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_extract_directory_exists_as_file_overwrite
|
43
|
-
File.open(TEST_OUT_NAME, 'w') { |f| f.puts 'something' }
|
44
|
-
gotCalled = false
|
45
|
-
extract_test_dir do |entry, destPath|
|
46
|
-
gotCalled = true
|
47
|
-
assert_equal(TEST_OUT_NAME, destPath)
|
48
|
-
assert(entry.directory?)
|
49
|
-
true
|
50
|
-
end
|
51
|
-
assert(gotCalled)
|
52
|
-
assert(File.directory?(TEST_OUT_NAME))
|
53
|
-
end
|
54
|
-
end
|
data/test/file_extract_test.rb
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class ZipFileExtractTest < MiniTest::Test
|
4
|
-
include CommonZipFileFixture
|
5
|
-
EXTRACTED_FILENAME = 'test/data/generated/extEntry'
|
6
|
-
ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entry_names.reverse
|
7
|
-
|
8
|
-
def setup
|
9
|
-
super
|
10
|
-
::File.delete(EXTRACTED_FILENAME) if ::File.exist?(EXTRACTED_FILENAME)
|
11
|
-
end
|
12
|
-
|
13
|
-
def teardown
|
14
|
-
::Zip.reset!
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_extract
|
18
|
-
::Zip::File.open(TEST_ZIP.zip_name) do |zf|
|
19
|
-
zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME)
|
20
|
-
|
21
|
-
assert(File.exist?(EXTRACTED_FILENAME))
|
22
|
-
AssertEntry.assert_contents(EXTRACTED_FILENAME,
|
23
|
-
zf.get_input_stream(ENTRY_TO_EXTRACT) { |is| is.read })
|
24
|
-
|
25
|
-
::File.unlink(EXTRACTED_FILENAME)
|
26
|
-
|
27
|
-
entry = zf.get_entry(ENTRY_TO_EXTRACT)
|
28
|
-
entry.extract(EXTRACTED_FILENAME)
|
29
|
-
|
30
|
-
assert(File.exist?(EXTRACTED_FILENAME))
|
31
|
-
AssertEntry.assert_contents(EXTRACTED_FILENAME,
|
32
|
-
entry.get_input_stream { |is| is.read })
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def test_extract_exists
|
37
|
-
writtenText = 'written text'
|
38
|
-
::File.open(EXTRACTED_FILENAME, 'w') { |f| f.write(writtenText) }
|
39
|
-
|
40
|
-
assert_raises(::Zip::DestinationFileExistsError) do
|
41
|
-
::Zip::File.open(TEST_ZIP.zip_name) do |zf|
|
42
|
-
zf.extract(zf.entries.first, EXTRACTED_FILENAME)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
File.open(EXTRACTED_FILENAME, 'r') do |f|
|
46
|
-
assert_equal(writtenText, f.read)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def test_extract_exists_overwrite
|
51
|
-
writtenText = 'written text'
|
52
|
-
::File.open(EXTRACTED_FILENAME, 'w') { |f| f.write(writtenText) }
|
53
|
-
|
54
|
-
gotCalledCorrectly = false
|
55
|
-
::Zip::File.open(TEST_ZIP.zip_name) do |zf|
|
56
|
-
zf.extract(zf.entries.first, EXTRACTED_FILENAME) do |entry, extractLoc|
|
57
|
-
gotCalledCorrectly = zf.entries.first == entry &&
|
58
|
-
extractLoc == EXTRACTED_FILENAME
|
59
|
-
true
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
assert(gotCalledCorrectly)
|
64
|
-
::File.open(EXTRACTED_FILENAME, 'r') do |f|
|
65
|
-
assert(writtenText != f.read)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def test_extract_non_entry
|
70
|
-
zf = ::Zip::File.new(TEST_ZIP.zip_name)
|
71
|
-
assert_raises(Errno::ENOENT) { zf.extract('nonExistingEntry', 'nonExistingEntry') }
|
72
|
-
ensure
|
73
|
-
zf.close if zf
|
74
|
-
end
|
75
|
-
|
76
|
-
def test_extract_non_entry_2
|
77
|
-
outFile = 'outfile'
|
78
|
-
assert_raises(Errno::ENOENT) do
|
79
|
-
zf = ::Zip::File.new(TEST_ZIP.zip_name)
|
80
|
-
nonEntry = 'hotdog-diddelidoo'
|
81
|
-
assert(!zf.entries.include?(nonEntry))
|
82
|
-
zf.extract(nonEntry, outFile)
|
83
|
-
zf.close
|
84
|
-
end
|
85
|
-
assert(!File.exist?(outFile))
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_extract_incorrect_size
|
89
|
-
# The uncompressed size fields in the zip file cannot be trusted. This makes
|
90
|
-
# it harder for callers to validate the sizes of the files they are
|
91
|
-
# extracting, which can lead to denial of service. See also
|
92
|
-
# https://en.wikipedia.org/wiki/Zip_bomb
|
93
|
-
Dir.mktmpdir do |tmp|
|
94
|
-
real_zip = File.join(tmp, 'real.zip')
|
95
|
-
fake_zip = File.join(tmp, 'fake.zip')
|
96
|
-
file_name = 'a'
|
97
|
-
true_size = 500_000
|
98
|
-
fake_size = 1
|
99
|
-
|
100
|
-
::Zip::File.open(real_zip, ::Zip::File::CREATE) do |zf|
|
101
|
-
zf.get_output_stream(file_name) do |os|
|
102
|
-
os.write 'a' * true_size
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
compressed_size = nil
|
107
|
-
::Zip::File.open(real_zip) do |zf|
|
108
|
-
a_entry = zf.find_entry(file_name)
|
109
|
-
compressed_size = a_entry.compressed_size
|
110
|
-
assert_equal true_size, a_entry.size
|
111
|
-
end
|
112
|
-
|
113
|
-
true_size_bytes = [compressed_size, true_size, file_name.size].pack('LLS')
|
114
|
-
fake_size_bytes = [compressed_size, fake_size, file_name.size].pack('LLS')
|
115
|
-
|
116
|
-
data = File.binread(real_zip)
|
117
|
-
assert data.include?(true_size_bytes)
|
118
|
-
data.gsub! true_size_bytes, fake_size_bytes
|
119
|
-
|
120
|
-
File.open(fake_zip, 'wb') do |file|
|
121
|
-
file.write data
|
122
|
-
end
|
123
|
-
|
124
|
-
Dir.chdir tmp do
|
125
|
-
::Zip::File.open(fake_zip) do |zf|
|
126
|
-
a_entry = zf.find_entry(file_name)
|
127
|
-
assert_equal fake_size, a_entry.size
|
128
|
-
|
129
|
-
::Zip.validate_entry_sizes = false
|
130
|
-
a_entry.extract
|
131
|
-
assert_equal true_size, File.size(file_name)
|
132
|
-
FileUtils.rm file_name
|
133
|
-
|
134
|
-
::Zip.validate_entry_sizes = true
|
135
|
-
error = assert_raises ::Zip::EntrySizeError do
|
136
|
-
a_entry.extract
|
137
|
-
end
|
138
|
-
assert_equal \
|
139
|
-
'Entry a should be 1B but is larger when inflated',
|
140
|
-
error.message
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class FilePermissionsTest < MiniTest::Test
|
4
|
-
ZIPNAME = File.join(File.dirname(__FILE__), 'umask.zip')
|
5
|
-
FILENAME = File.join(File.dirname(__FILE__), 'umask.txt')
|
6
|
-
|
7
|
-
def teardown
|
8
|
-
::File.unlink(ZIPNAME)
|
9
|
-
::File.unlink(FILENAME)
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_current_umask
|
13
|
-
create_files
|
14
|
-
assert_matching_permissions FILENAME, ZIPNAME
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_umask_000
|
18
|
-
set_umask(0o000) do
|
19
|
-
create_files
|
20
|
-
end
|
21
|
-
|
22
|
-
assert_matching_permissions FILENAME, ZIPNAME
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_umask_066
|
26
|
-
set_umask(0o066) do
|
27
|
-
create_files
|
28
|
-
end
|
29
|
-
|
30
|
-
assert_matching_permissions FILENAME, ZIPNAME
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_umask_027
|
34
|
-
set_umask(0o027) do
|
35
|
-
create_files
|
36
|
-
end
|
37
|
-
|
38
|
-
assert_matching_permissions FILENAME, ZIPNAME
|
39
|
-
end
|
40
|
-
|
41
|
-
def assert_matching_permissions(expected_file, actual_file)
|
42
|
-
assert_equal(
|
43
|
-
::File.stat(expected_file).mode.to_s(8).rjust(4, '0'),
|
44
|
-
::File.stat(actual_file).mode.to_s(8).rjust(4, '0')
|
45
|
-
)
|
46
|
-
end
|
47
|
-
|
48
|
-
def create_files
|
49
|
-
::Zip::File.open(ZIPNAME, ::Zip::File::CREATE) do |zip|
|
50
|
-
zip.comment = 'test'
|
51
|
-
end
|
52
|
-
|
53
|
-
::File.open(FILENAME, 'w') do |file|
|
54
|
-
file << 'test'
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# If anything goes wrong, make sure the umask is restored.
|
59
|
-
def set_umask(umask)
|
60
|
-
saved_umask = ::File.umask(umask)
|
61
|
-
yield
|
62
|
-
ensure
|
63
|
-
::File.umask(saved_umask)
|
64
|
-
end
|
65
|
-
end
|
data/test/file_split_test.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class ZipFileSplitTest < MiniTest::Test
|
4
|
-
TEST_ZIP = TestZipFile::TEST_ZIP2.clone
|
5
|
-
TEST_ZIP.zip_name = 'large_zip_file.zip'
|
6
|
-
EXTRACTED_FILENAME = 'test/data/generated/extEntrySplit'
|
7
|
-
UNSPLITTED_FILENAME = 'test/data/generated/unsplitted.zip'
|
8
|
-
ENTRY_TO_EXTRACT = TEST_ZIP.entry_names.first
|
9
|
-
|
10
|
-
def setup
|
11
|
-
FileUtils.cp(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name)
|
12
|
-
end
|
13
|
-
|
14
|
-
def teardown
|
15
|
-
File.delete(TEST_ZIP.zip_name)
|
16
|
-
File.delete(UNSPLITTED_FILENAME) if File.exist?(UNSPLITTED_FILENAME)
|
17
|
-
|
18
|
-
Dir["#{TEST_ZIP.zip_name}.*"].each do |zip_file_name|
|
19
|
-
File.delete(zip_file_name) if File.exist?(zip_file_name)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_split_method_respond
|
24
|
-
assert_respond_to ::Zip::File, :split, 'Does not have split class method'
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_split
|
28
|
-
result = ::Zip::File.split(TEST_ZIP.zip_name, 65_536, false)
|
29
|
-
|
30
|
-
return if result.nil?
|
31
|
-
Dir["#{TEST_ZIP.zip_name}.*"].sort.each_with_index do |zip_file_name, index|
|
32
|
-
File.open(zip_file_name, 'rb') do |zip_file|
|
33
|
-
zip_file.read([::Zip::File::SPLIT_SIGNATURE].pack('V').size) if index == 0
|
34
|
-
File.open(UNSPLITTED_FILENAME, 'ab') do |file|
|
35
|
-
file << zip_file.read
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
::Zip::File.open(UNSPLITTED_FILENAME) do |zf|
|
41
|
-
zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME)
|
42
|
-
|
43
|
-
assert(File.exist?(EXTRACTED_FILENAME))
|
44
|
-
AssertEntry.assert_contents(EXTRACTED_FILENAME,
|
45
|
-
zf.get_input_stream(ENTRY_TO_EXTRACT) { |is| is.read })
|
46
|
-
|
47
|
-
File.unlink(EXTRACTED_FILENAME)
|
48
|
-
|
49
|
-
entry = zf.get_entry(ENTRY_TO_EXTRACT)
|
50
|
-
entry.extract(EXTRACTED_FILENAME)
|
51
|
-
|
52
|
-
assert(File.exist?(EXTRACTED_FILENAME))
|
53
|
-
AssertEntry.assert_contents(EXTRACTED_FILENAME,
|
54
|
-
entry.get_input_stream { |is| is.read })
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|