rubyzip 0.9.9 → 1.3.0
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 +7 -0
- data/README.md +284 -41
- data/Rakefile +11 -6
- data/TODO +0 -1
- data/lib/zip/central_directory.rb +208 -0
- data/lib/zip/compressor.rb +1 -2
- data/lib/zip/constants.rb +59 -7
- data/lib/zip/crypto/encryption.rb +11 -0
- data/lib/zip/crypto/null_encryption.rb +43 -0
- data/lib/zip/crypto/traditional_encryption.rb +99 -0
- data/lib/zip/decompressor.rb +4 -4
- data/lib/zip/deflater.rb +17 -13
- data/lib/zip/dos_time.rb +13 -14
- data/lib/zip/entry.rb +700 -0
- data/lib/zip/entry_set.rb +86 -0
- data/lib/zip/errors.rb +18 -0
- data/lib/zip/extra_field/generic.rb +43 -0
- 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 +47 -0
- data/lib/zip/extra_field/unix.rb +37 -0
- data/lib/zip/extra_field/zip64.rb +68 -0
- data/lib/zip/extra_field/zip64_placeholder.rb +15 -0
- data/lib/zip/extra_field.rb +101 -0
- data/lib/zip/file.rb +443 -0
- data/lib/zip/{zipfilesystem.rb → filesystem.rb} +162 -157
- data/lib/zip/inflater.rb +29 -28
- data/lib/zip/input_stream.rb +173 -0
- data/lib/zip/ioextras/abstract_input_stream.rb +111 -0
- data/lib/zip/ioextras/abstract_output_stream.rb +43 -0
- data/lib/zip/ioextras.rb +21 -149
- data/lib/zip/null_compressor.rb +2 -2
- data/lib/zip/null_decompressor.rb +8 -6
- data/lib/zip/null_input_stream.rb +3 -2
- data/lib/zip/output_stream.rb +189 -0
- data/lib/zip/pass_thru_compressor.rb +6 -6
- data/lib/zip/pass_thru_decompressor.rb +19 -19
- data/lib/zip/{zip_streamable_directory.rb → streamable_directory.rb} +3 -3
- data/lib/zip/streamable_stream.rb +56 -0
- data/lib/zip/version.rb +3 -0
- data/lib/zip.rb +71 -0
- data/samples/example.rb +44 -32
- data/samples/example_filesystem.rb +16 -18
- data/samples/example_recursive.rb +33 -28
- data/samples/{gtkRubyzip.rb → gtk_ruby_zip.rb} +26 -28
- data/samples/qtzip.rb +22 -31
- data/samples/write_simple.rb +12 -13
- data/samples/zipfind.rb +31 -39
- 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 +57 -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/gpbit3stored.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/path_traversal/Makefile +10 -0
- data/test/data/path_traversal/jwilk/README.md +5 -0
- 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 +3 -0
- 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 +65 -0
- data/test/encryption_test.rb +42 -0
- data/test/entry_set_test.rb +163 -0
- data/test/entry_test.rb +154 -0
- data/test/errors_test.rb +35 -0
- data/test/extra_field_test.rb +76 -0
- data/test/file_extract_directory_test.rb +54 -0
- data/test/file_extract_test.rb +145 -0
- data/test/file_permissions_test.rb +65 -0
- data/test/file_split_test.rb +57 -0
- data/test/file_test.rb +666 -0
- data/test/filesystem/dir_iterator_test.rb +58 -0
- data/test/filesystem/directory_test.rb +139 -0
- data/test/filesystem/file_mutating_test.rb +87 -0
- data/test/filesystem/file_nonmutating_test.rb +508 -0
- data/test/filesystem/file_stat_test.rb +64 -0
- data/test/gentestfiles.rb +126 -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/path_traversal_test.rb +141 -0
- data/test/samples/example_recursive_test.rb +37 -0
- data/test/settings_test.rb +95 -0
- data/test/test_helper.rb +234 -0
- data/test/unicode_file_names_and_comments_test.rb +62 -0
- data/test/zip64_full_test.rb +51 -0
- data/test/zip64_support_test.rb +14 -0
- metadata +274 -41
- data/NEWS +0 -172
- data/lib/zip/settings.rb +0 -10
- data/lib/zip/tempfile_bugfixed.rb +0 -195
- data/lib/zip/zip.rb +0 -56
- data/lib/zip/zip_central_directory.rb +0 -135
- data/lib/zip/zip_entry.rb +0 -638
- data/lib/zip/zip_entry_set.rb +0 -77
- data/lib/zip/zip_extra_field.rb +0 -213
- data/lib/zip/zip_file.rb +0 -340
- data/lib/zip/zip_input_stream.rb +0 -144
- data/lib/zip/zip_output_stream.rb +0 -173
- data/lib/zip/zip_streamable_stream.rb +0 -47
data/lib/zip/constants.rb
CHANGED
@@ -1,11 +1,63 @@
|
|
1
1
|
module Zip
|
2
|
-
VERSION = '0.9.7'
|
3
|
-
RUBY_MINOR_VERSION = RUBY_VERSION.split(".")[1].to_i
|
4
2
|
RUNNING_ON_WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/i
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
CENTRAL_DIRECTORY_ENTRY_SIGNATURE = 0x02014b50
|
5
|
+
CDIR_ENTRY_STATIC_HEADER_LENGTH = 46
|
6
|
+
|
7
|
+
LOCAL_ENTRY_SIGNATURE = 0x04034b50
|
8
|
+
LOCAL_ENTRY_STATIC_HEADER_LENGTH = 30
|
9
|
+
LOCAL_ENTRY_TRAILING_DESCRIPTOR_LENGTH = 4 + 4 + 4
|
10
|
+
VERSION_MADE_BY = 52 # this library's version
|
11
|
+
VERSION_NEEDED_TO_EXTRACT = 20
|
12
|
+
VERSION_NEEDED_TO_EXTRACT_ZIP64 = 45
|
13
|
+
|
14
|
+
FILE_TYPE_FILE = 0o10
|
15
|
+
FILE_TYPE_DIR = 0o04
|
16
|
+
FILE_TYPE_SYMLINK = 0o12
|
17
|
+
|
18
|
+
FSTYPE_FAT = 0
|
19
|
+
FSTYPE_AMIGA = 1
|
20
|
+
FSTYPE_VMS = 2
|
21
|
+
FSTYPE_UNIX = 3
|
22
|
+
FSTYPE_VM_CMS = 4
|
23
|
+
FSTYPE_ATARI = 5
|
24
|
+
FSTYPE_HPFS = 6
|
25
|
+
FSTYPE_MAC = 7
|
26
|
+
FSTYPE_Z_SYSTEM = 8
|
27
|
+
FSTYPE_CPM = 9
|
28
|
+
FSTYPE_TOPS20 = 10
|
29
|
+
FSTYPE_NTFS = 11
|
30
|
+
FSTYPE_QDOS = 12
|
31
|
+
FSTYPE_ACORN = 13
|
32
|
+
FSTYPE_VFAT = 14
|
33
|
+
FSTYPE_MVS = 15
|
34
|
+
FSTYPE_BEOS = 16
|
35
|
+
FSTYPE_TANDEM = 17
|
36
|
+
FSTYPE_THEOS = 18
|
37
|
+
FSTYPE_MAC_OSX = 19
|
38
|
+
FSTYPE_ATHEOS = 30
|
39
|
+
|
40
|
+
FSTYPES = {
|
41
|
+
FSTYPE_FAT => 'FAT'.freeze,
|
42
|
+
FSTYPE_AMIGA => 'Amiga'.freeze,
|
43
|
+
FSTYPE_VMS => 'VMS (Vax or Alpha AXP)'.freeze,
|
44
|
+
FSTYPE_UNIX => 'Unix'.freeze,
|
45
|
+
FSTYPE_VM_CMS => 'VM/CMS'.freeze,
|
46
|
+
FSTYPE_ATARI => 'Atari ST'.freeze,
|
47
|
+
FSTYPE_HPFS => 'OS/2 or NT HPFS'.freeze,
|
48
|
+
FSTYPE_MAC => 'Macintosh'.freeze,
|
49
|
+
FSTYPE_Z_SYSTEM => 'Z-System'.freeze,
|
50
|
+
FSTYPE_CPM => 'CP/M'.freeze,
|
51
|
+
FSTYPE_TOPS20 => 'TOPS-20'.freeze,
|
52
|
+
FSTYPE_NTFS => 'NTFS'.freeze,
|
53
|
+
FSTYPE_QDOS => 'SMS/QDOS'.freeze,
|
54
|
+
FSTYPE_ACORN => 'Acorn RISC OS'.freeze,
|
55
|
+
FSTYPE_VFAT => 'Win32 VFAT'.freeze,
|
56
|
+
FSTYPE_MVS => 'MVS'.freeze,
|
57
|
+
FSTYPE_BEOS => 'BeOS'.freeze,
|
58
|
+
FSTYPE_TANDEM => 'Tandem NSK'.freeze,
|
59
|
+
FSTYPE_THEOS => 'Theos'.freeze,
|
60
|
+
FSTYPE_MAC_OSX => 'Mac OS/X (Darwin)'.freeze,
|
61
|
+
FSTYPE_ATHEOS => 'AtheOS'.freeze
|
62
|
+
}.freeze
|
11
63
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Zip
|
2
|
+
module NullEncryption
|
3
|
+
def header_bytesize
|
4
|
+
0
|
5
|
+
end
|
6
|
+
|
7
|
+
def gp_flags
|
8
|
+
0
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class NullEncrypter < Encrypter
|
13
|
+
include NullEncryption
|
14
|
+
|
15
|
+
def header(_mtime)
|
16
|
+
''
|
17
|
+
end
|
18
|
+
|
19
|
+
def encrypt(data)
|
20
|
+
data
|
21
|
+
end
|
22
|
+
|
23
|
+
def data_descriptor(_crc32, _compressed_size, _uncomprssed_size)
|
24
|
+
''
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset!; end
|
28
|
+
end
|
29
|
+
|
30
|
+
class NullDecrypter < Decrypter
|
31
|
+
include NullEncryption
|
32
|
+
|
33
|
+
def decrypt(data)
|
34
|
+
data
|
35
|
+
end
|
36
|
+
|
37
|
+
def reset!(_header); end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
42
|
+
# rubyzip is free software; you can redistribute it and/or
|
43
|
+
# modify it under the terms of the ruby license.
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Zip
|
2
|
+
module TraditionalEncryption
|
3
|
+
def initialize(password)
|
4
|
+
@password = password
|
5
|
+
reset_keys!
|
6
|
+
end
|
7
|
+
|
8
|
+
def header_bytesize
|
9
|
+
12
|
10
|
+
end
|
11
|
+
|
12
|
+
def gp_flags
|
13
|
+
0x0001 | 0x0008
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def reset_keys!
|
19
|
+
@key0 = 0x12345678
|
20
|
+
@key1 = 0x23456789
|
21
|
+
@key2 = 0x34567890
|
22
|
+
@password.each_byte do |byte|
|
23
|
+
update_keys(byte.chr)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def update_keys(n)
|
28
|
+
@key0 = ~Zlib.crc32(n, ~@key0)
|
29
|
+
@key1 = ((@key1 + (@key0 & 0xff)) * 134_775_813 + 1) & 0xffffffff
|
30
|
+
@key2 = ~Zlib.crc32((@key1 >> 24).chr, ~@key2)
|
31
|
+
end
|
32
|
+
|
33
|
+
def decrypt_byte
|
34
|
+
temp = (@key2 & 0xffff) | 2
|
35
|
+
((temp * (temp ^ 1)) >> 8) & 0xff
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class TraditionalEncrypter < Encrypter
|
40
|
+
include TraditionalEncryption
|
41
|
+
|
42
|
+
def header(mtime)
|
43
|
+
[].tap do |header|
|
44
|
+
(header_bytesize - 2).times do
|
45
|
+
header << Random.rand(0..255)
|
46
|
+
end
|
47
|
+
header << (mtime.to_binary_dos_time & 0xff)
|
48
|
+
header << (mtime.to_binary_dos_time >> 8)
|
49
|
+
end.map { |x| encode x }.pack('C*')
|
50
|
+
end
|
51
|
+
|
52
|
+
def encrypt(data)
|
53
|
+
data.unpack('C*').map { |x| encode x }.pack('C*')
|
54
|
+
end
|
55
|
+
|
56
|
+
def data_descriptor(crc32, compressed_size, uncomprssed_size)
|
57
|
+
[0x08074b50, crc32, compressed_size, uncomprssed_size].pack('VVVV')
|
58
|
+
end
|
59
|
+
|
60
|
+
def reset!
|
61
|
+
reset_keys!
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def encode(n)
|
67
|
+
t = decrypt_byte
|
68
|
+
update_keys(n.chr)
|
69
|
+
t ^ n
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class TraditionalDecrypter < Decrypter
|
74
|
+
include TraditionalEncryption
|
75
|
+
|
76
|
+
def decrypt(data)
|
77
|
+
data.unpack('C*').map { |x| decode x }.pack('C*')
|
78
|
+
end
|
79
|
+
|
80
|
+
def reset!(header)
|
81
|
+
reset_keys!
|
82
|
+
header.each_byte do |x|
|
83
|
+
decode x
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def decode(n)
|
90
|
+
n ^= decrypt_byte
|
91
|
+
update_keys(n.chr)
|
92
|
+
n
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
98
|
+
# rubyzip is free software; you can redistribute it and/or
|
99
|
+
# modify it under the terms of the ruby license.
|
data/lib/zip/decompressor.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Zip
|
2
|
-
class Decompressor
|
3
|
-
CHUNK_SIZE=
|
4
|
-
def initialize(
|
2
|
+
class Decompressor #:nodoc:all
|
3
|
+
CHUNK_SIZE = 32_768
|
4
|
+
def initialize(input_stream)
|
5
5
|
super()
|
6
|
-
@
|
6
|
+
@input_stream = input_stream
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
data/lib/zip/deflater.rb
CHANGED
@@ -1,24 +1,28 @@
|
|
1
1
|
module Zip
|
2
2
|
class Deflater < Compressor #:nodoc:all
|
3
|
-
def initialize(
|
3
|
+
def initialize(output_stream, level = Zip.default_compression, encrypter = NullEncrypter.new)
|
4
4
|
super()
|
5
|
-
@
|
6
|
-
@
|
7
|
-
@size
|
8
|
-
@crc
|
5
|
+
@output_stream = output_stream
|
6
|
+
@zlib_deflater = ::Zlib::Deflate.new(level, -::Zlib::MAX_WBITS)
|
7
|
+
@size = 0
|
8
|
+
@crc = ::Zlib.crc32
|
9
|
+
@encrypter = encrypter
|
9
10
|
end
|
10
|
-
|
11
|
-
def <<
|
12
|
-
val
|
13
|
-
@crc
|
11
|
+
|
12
|
+
def <<(data)
|
13
|
+
val = data.to_s
|
14
|
+
@crc = Zlib.crc32(val, @crc)
|
14
15
|
@size += val.bytesize
|
15
|
-
|
16
|
+
buffer = @zlib_deflater.deflate(data)
|
17
|
+
if buffer.empty?
|
18
|
+
@output_stream
|
19
|
+
else
|
20
|
+
@output_stream << @encrypter.encrypt(buffer)
|
21
|
+
end
|
16
22
|
end
|
17
23
|
|
18
24
|
def finish
|
19
|
-
until @
|
20
|
-
@outputStream << @zlibDeflater.finish
|
21
|
-
end
|
25
|
+
@output_stream << @encrypter.encrypt(@zlib_deflater.finish) until @zlib_deflater.finished?
|
22
26
|
end
|
23
27
|
|
24
28
|
attr_reader :size, :crc
|
data/lib/zip/dos_time.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
module Zip
|
2
2
|
class DOSTime < Time #:nodoc:all
|
3
|
-
|
4
|
-
#MS-DOS File Date and Time format as used in Interrupt 21H Function 57H:
|
3
|
+
# MS-DOS File Date and Time format as used in Interrupt 21H Function 57H:
|
5
4
|
|
6
5
|
# Register CX, the Time:
|
7
6
|
# Bits 0-4 2 second increments (0-29)
|
@@ -14,31 +13,31 @@ module Zip
|
|
14
13
|
# bits 9-15 year (four digit year minus 1980)
|
15
14
|
|
16
15
|
def to_binary_dos_time
|
17
|
-
(sec/2) +
|
18
|
-
|
19
|
-
|
16
|
+
(sec / 2) +
|
17
|
+
(min << 5) +
|
18
|
+
(hour << 11)
|
20
19
|
end
|
21
20
|
|
22
21
|
def to_binary_dos_date
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
day +
|
23
|
+
(month << 5) +
|
24
|
+
((year - 1980) << 9)
|
26
25
|
end
|
27
26
|
|
28
27
|
# Dos time is only stored with two seconds accuracy
|
29
28
|
def dos_equals(other)
|
30
|
-
to_i/2 == other.to_i/2
|
29
|
+
to_i / 2 == other.to_i / 2
|
31
30
|
end
|
32
31
|
|
33
32
|
def self.parse_binary_dos_format(binaryDosDate, binaryDosTime)
|
34
|
-
second = 2 * (
|
35
|
-
minute = (
|
33
|
+
second = 2 * (0b11111 & binaryDosTime)
|
34
|
+
minute = (0b11111100000 & binaryDosTime) >> 5
|
36
35
|
hour = (0b1111100000000000 & binaryDosTime) >> 11
|
37
|
-
day = (
|
38
|
-
month = (
|
36
|
+
day = (0b11111 & binaryDosDate)
|
37
|
+
month = (0b111100000 & binaryDosDate) >> 5
|
39
38
|
year = ((0b1111111000000000 & binaryDosDate) >> 9) + 1980
|
40
39
|
begin
|
41
|
-
|
40
|
+
local(year, month, day, hour, minute, second)
|
42
41
|
end
|
43
42
|
end
|
44
43
|
end
|