rubyzip 2.3.1 → 3.0.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog.md +368 -0
- data/README.md +122 -39
- data/Rakefile +11 -7
- data/lib/zip/central_directory.rb +164 -118
- data/lib/zip/compressor.rb +3 -1
- data/lib/zip/constants.rb +25 -21
- data/lib/zip/crypto/decrypted_io.rb +3 -1
- data/lib/zip/crypto/encryption.rb +4 -2
- data/lib/zip/crypto/null_encryption.rb +5 -3
- data/lib/zip/crypto/traditional_encryption.rb +5 -3
- data/lib/zip/decompressor.rb +4 -3
- data/lib/zip/deflater.rb +10 -8
- data/lib/zip/dirtyable.rb +32 -0
- data/lib/zip/dos_time.rb +41 -5
- data/lib/zip/entry.rb +273 -170
- data/lib/zip/entry_set.rb +9 -7
- data/lib/zip/errors.rb +115 -16
- data/lib/zip/extra_field/generic.rb +3 -10
- data/lib/zip/extra_field/ntfs.rb +4 -2
- data/lib/zip/extra_field/old_unix.rb +3 -1
- data/lib/zip/extra_field/universal_time.rb +3 -1
- data/lib/zip/extra_field/unix.rb +5 -3
- data/lib/zip/extra_field/unknown.rb +33 -0
- data/lib/zip/extra_field/zip64.rb +12 -5
- data/lib/zip/extra_field.rb +15 -21
- data/lib/zip/file.rb +152 -221
- 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 +26 -595
- data/lib/zip/inflater.rb +6 -4
- data/lib/zip/input_stream.rb +43 -25
- data/lib/zip/ioextras/abstract_input_stream.rb +13 -8
- data/lib/zip/ioextras/abstract_output_stream.rb +5 -3
- data/lib/zip/ioextras.rb +6 -6
- data/lib/zip/null_compressor.rb +3 -1
- data/lib/zip/null_decompressor.rb +3 -1
- data/lib/zip/null_input_stream.rb +3 -1
- data/lib/zip/output_stream.rb +45 -39
- data/lib/zip/pass_thru_compressor.rb +3 -1
- data/lib/zip/pass_thru_decompressor.rb +4 -2
- data/lib/zip/streamable_directory.rb +3 -1
- data/lib/zip/streamable_stream.rb +3 -0
- data/lib/zip/version.rb +3 -1
- data/lib/zip.rb +15 -22
- data/rubyzip.gemspec +38 -0
- data/samples/example.rb +8 -3
- data/samples/example_filesystem.rb +2 -1
- data/samples/example_recursive.rb +3 -1
- data/samples/gtk_ruby_zip.rb +4 -2
- data/samples/qtzip.rb +6 -5
- data/samples/write_simple.rb +1 -0
- data/samples/zipfind.rb +1 -0
- metadata +83 -35
- data/TODO +0 -15
- data/lib/zip/extra_field/zip64_placeholder.rb +0 -15
data/Rakefile
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bundler/gem_tasks'
|
2
4
|
require 'rake/testtask'
|
5
|
+
require 'rdoc/task'
|
3
6
|
require 'rubocop/rake_task'
|
4
7
|
|
5
8
|
task default: :test
|
@@ -11,11 +14,12 @@ Rake::TestTask.new(:test) do |test|
|
|
11
14
|
test.verbose = true
|
12
15
|
end
|
13
16
|
|
14
|
-
|
17
|
+
RDoc::Task.new do |rdoc|
|
18
|
+
rdoc.main = 'README.md'
|
19
|
+
rdoc.rdoc_files.include('README.md', 'lib/**/*.rb')
|
20
|
+
rdoc.options << '--markup=markdown'
|
21
|
+
rdoc.options << '--tab-width=2'
|
22
|
+
rdoc.options << "-t Rubyzip version #{::Zip::VERSION}"
|
23
|
+
end
|
15
24
|
|
16
|
-
|
17
|
-
# test.libs << File.join(File.dirname(__FILE__), 'lib')
|
18
|
-
# test.libs << File.join(File.dirname(__FILE__), 'test')
|
19
|
-
# test.pattern = File.join(File.dirname(__FILE__), 'test/zip64_full_test.rb')
|
20
|
-
# test.verbose = true
|
21
|
-
# end
|
25
|
+
RuboCop::RakeTask.new
|
@@ -1,45 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
require_relative 'dirtyable'
|
6
|
+
|
1
7
|
module Zip
|
2
|
-
class CentralDirectory
|
3
|
-
|
8
|
+
class CentralDirectory # :nodoc:
|
9
|
+
extend Forwardable
|
10
|
+
include Dirtyable
|
11
|
+
|
12
|
+
END_OF_CD_SIG = 0x06054b50
|
13
|
+
ZIP64_END_OF_CD_SIG = 0x06064b50
|
14
|
+
ZIP64_EOCD_LOCATOR_SIG = 0x07064b50
|
4
15
|
|
5
|
-
END_OF_CDS = 0x06054b50
|
6
|
-
ZIP64_END_OF_CDS = 0x06064b50
|
7
|
-
ZIP64_EOCD_LOCATOR = 0x07064b50
|
8
|
-
MAX_END_OF_CDS_SIZE = 65_536 + 18
|
9
16
|
STATIC_EOCD_SIZE = 22
|
17
|
+
ZIP64_STATIC_EOCD_SIZE = 56
|
18
|
+
ZIP64_EOCD_LOC_SIZE = 20
|
19
|
+
MAX_FILE_COMMENT_SIZE = (1 << 16) - 1
|
20
|
+
MAX_END_OF_CD_SIZE =
|
21
|
+
MAX_FILE_COMMENT_SIZE + STATIC_EOCD_SIZE + ZIP64_EOCD_LOC_SIZE
|
10
22
|
|
11
|
-
|
23
|
+
attr_accessor :comment
|
12
24
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
25
|
+
def_delegators :@entry_set,
|
26
|
+
:<<, :delete, :each, :entries, :find_entry, :glob,
|
27
|
+
:include?, :size
|
28
|
+
|
29
|
+
mark_dirty :<<, :comment=, :delete
|
17
30
|
|
18
31
|
def initialize(entries = EntrySet.new, comment = '') #:nodoc:
|
19
|
-
super()
|
32
|
+
super(dirty_on_create: false)
|
20
33
|
@entry_set = entries.kind_of?(EntrySet) ? entries : EntrySet.new(entries)
|
21
34
|
@comment = comment
|
22
35
|
end
|
23
36
|
|
37
|
+
def read_from_stream(io)
|
38
|
+
read_eocds(io)
|
39
|
+
read_central_directory_entries(io)
|
40
|
+
end
|
41
|
+
|
24
42
|
def write_to_stream(io) #:nodoc:
|
25
43
|
cdir_offset = io.tell
|
26
44
|
@entry_set.each { |entry| entry.write_c_dir_entry(io) }
|
27
45
|
eocd_offset = io.tell
|
28
46
|
cdir_size = eocd_offset - cdir_offset
|
29
|
-
if
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
write_64_e_o_c_d(io, cdir_offset, cdir_size)
|
34
|
-
write_64_eocd_locator(io, eocd_offset)
|
35
|
-
end
|
47
|
+
if Zip.write_zip64_support &&
|
48
|
+
(cdir_offset > 0xFFFFFFFF || cdir_size > 0xFFFFFFFF || @entry_set.size > 0xFFFF)
|
49
|
+
write_64_e_o_c_d(io, cdir_offset, cdir_size)
|
50
|
+
write_64_eocd_locator(io, eocd_offset)
|
36
51
|
end
|
37
52
|
write_e_o_c_d(io, cdir_offset, cdir_size)
|
38
53
|
end
|
39
54
|
|
55
|
+
# Reads the End of Central Directory Record (and the Zip64 equivalent if
|
56
|
+
# needs be) and returns the number of entries in the archive. This is a
|
57
|
+
# convenience method that avoids reading in all of the entry data to get a
|
58
|
+
# very quick entry count.
|
59
|
+
def count_entries(io)
|
60
|
+
read_eocds(io)
|
61
|
+
@size
|
62
|
+
end
|
63
|
+
|
64
|
+
def ==(other) #:nodoc:
|
65
|
+
return false unless other.kind_of?(CentralDirectory)
|
66
|
+
|
67
|
+
@entry_set.entries.sort == other.entries.sort && comment == other.comment
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
40
72
|
def write_e_o_c_d(io, offset, cdir_size) #:nodoc:
|
41
73
|
tmp = [
|
42
|
-
|
74
|
+
END_OF_CD_SIG,
|
43
75
|
0, # @numberOfThisDisk
|
44
76
|
0, # @numberOfDiskWithStartOfCDir
|
45
77
|
@entry_set ? [@entry_set.size, 0xFFFF].min : 0,
|
@@ -52,11 +84,9 @@ module Zip
|
|
52
84
|
io << @comment
|
53
85
|
end
|
54
86
|
|
55
|
-
private :write_e_o_c_d
|
56
|
-
|
57
87
|
def write_64_e_o_c_d(io, offset, cdir_size) #:nodoc:
|
58
88
|
tmp = [
|
59
|
-
|
89
|
+
ZIP64_END_OF_CD_SIG,
|
60
90
|
44, # size of zip64 end of central directory record (excludes signature and field itself)
|
61
91
|
VERSION_MADE_BY,
|
62
92
|
VERSION_NEEDED_TO_EXTRACT_ZIP64,
|
@@ -70,11 +100,9 @@ module Zip
|
|
70
100
|
io << tmp.pack('VQ<vvVVQ<Q<Q<Q<')
|
71
101
|
end
|
72
102
|
|
73
|
-
private :write_64_e_o_c_d
|
74
|
-
|
75
103
|
def write_64_eocd_locator(io, zip64_eocd_offset)
|
76
104
|
tmp = [
|
77
|
-
|
105
|
+
ZIP64_EOCD_LOCATOR_SIG,
|
78
106
|
0, # number of disk containing the start of zip64 eocd record
|
79
107
|
zip64_eocd_offset, # offset of the start of zip64 eocd record in its disk
|
80
108
|
1 # total number of disks
|
@@ -82,127 +110,145 @@ module Zip
|
|
82
110
|
io << tmp.pack('VVQ<V')
|
83
111
|
end
|
84
112
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
@
|
90
|
-
@
|
91
|
-
@
|
92
|
-
@
|
93
|
-
@
|
94
|
-
@
|
95
|
-
@
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
113
|
+
def unpack_64_e_o_c_d(buffer) #:nodoc:
|
114
|
+
_, # ZIP64_END_OF_CD_SIG. We know we have this at this point.
|
115
|
+
@size_of_zip64_e_o_c_d,
|
116
|
+
@version_made_by,
|
117
|
+
@version_needed_for_extract,
|
118
|
+
@number_of_this_disk,
|
119
|
+
@number_of_disk_with_start_of_cdir,
|
120
|
+
@total_number_of_entries_in_cdir_on_this_disk,
|
121
|
+
@size,
|
122
|
+
@size_in_bytes,
|
123
|
+
@cdir_offset = buffer.unpack('VQ<vvVVQ<Q<Q<Q<')
|
124
|
+
|
125
|
+
zip64_extensible_data_size =
|
126
|
+
@size_of_zip64_e_o_c_d - ZIP64_STATIC_EOCD_SIZE + 12
|
127
|
+
@zip64_extensible_data = if zip64_extensible_data_size.zero?
|
128
|
+
''
|
129
|
+
else
|
130
|
+
buffer.slice(
|
131
|
+
ZIP64_STATIC_EOCD_SIZE,
|
132
|
+
zip64_extensible_data_size
|
133
|
+
)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def unpack_64_eocd_locator(buffer) #:nodoc:
|
138
|
+
_, # ZIP64_EOCD_LOCATOR_SIG. We know we have this at this point.
|
139
|
+
_, zip64_eocd_offset, = buffer.unpack('VVQ<V')
|
140
|
+
|
141
|
+
zip64_eocd_offset
|
100
142
|
end
|
101
143
|
|
102
|
-
def
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
comment_length
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
144
|
+
def unpack_e_o_c_d(buffer) #:nodoc:
|
145
|
+
_, # END_OF_CD_SIG. We know we have this at this point.
|
146
|
+
num_disk,
|
147
|
+
num_disk_cdir,
|
148
|
+
num_cdir_disk,
|
149
|
+
num_entries,
|
150
|
+
size_in_bytes,
|
151
|
+
cdir_offset,
|
152
|
+
comment_length = buffer.unpack('VvvvvVVv')
|
153
|
+
|
154
|
+
@number_of_this_disk = num_disk unless num_disk == 0xFFFF
|
155
|
+
@number_of_disk_with_start_of_cdir = num_disk_cdir unless num_disk_cdir == 0xFFFF
|
156
|
+
@total_number_of_entries_in_cdir_on_this_disk = num_cdir_disk unless num_cdir_disk == 0xFFFF
|
157
|
+
@size = num_entries unless num_entries == 0xFFFF
|
158
|
+
@size_in_bytes = size_in_bytes unless size_in_bytes == 0xFFFFFFFF
|
159
|
+
@cdir_offset = cdir_offset unless cdir_offset == 0xFFFFFFFF
|
160
|
+
|
161
|
+
@comment = if comment_length.positive?
|
162
|
+
buffer.slice(STATIC_EOCD_SIZE, comment_length)
|
163
|
+
else
|
164
|
+
''
|
165
|
+
end
|
117
166
|
end
|
118
167
|
|
119
168
|
def read_central_directory_entries(io) #:nodoc:
|
169
|
+
# `StringIO` doesn't raise `EINVAL` if you seek beyond the current end,
|
170
|
+
# so we need to catch that *and* query `io#eof?` here.
|
171
|
+
eof = false
|
120
172
|
begin
|
121
173
|
io.seek(@cdir_offset, IO::SEEK_SET)
|
122
174
|
rescue Errno::EINVAL
|
123
|
-
|
175
|
+
eof = true
|
124
176
|
end
|
177
|
+
raise Error, 'Zip consistency problem while reading central directory entry' if eof || io.eof?
|
178
|
+
|
125
179
|
@entry_set = EntrySet.new
|
126
180
|
@size.times do
|
127
|
-
|
128
|
-
|
129
|
-
|
181
|
+
entry = Entry.read_c_dir_entry(io)
|
182
|
+
next unless entry
|
183
|
+
|
184
|
+
offset = if entry.zip64?
|
185
|
+
entry.extra['Zip64'].relative_header_offset
|
186
|
+
else
|
187
|
+
entry.local_header_offset
|
188
|
+
end
|
189
|
+
|
190
|
+
unless offset.nil?
|
191
|
+
io_save = io.tell
|
192
|
+
io.seek(offset, IO::SEEK_SET)
|
193
|
+
entry.read_extra_field(read_local_extra_field(io), local: true)
|
194
|
+
io.seek(io_save, IO::SEEK_SET)
|
195
|
+
end
|
130
196
|
|
131
|
-
|
132
|
-
buf = start_buf(io)
|
133
|
-
if zip64_file?(buf)
|
134
|
-
read_64_e_o_c_d(buf)
|
135
|
-
else
|
136
|
-
read_e_o_c_d(buf)
|
197
|
+
@entry_set << entry
|
137
198
|
end
|
138
|
-
read_central_directory_entries(io)
|
139
199
|
end
|
140
200
|
|
141
|
-
def
|
142
|
-
|
143
|
-
|
201
|
+
def read_local_extra_field(io)
|
202
|
+
buf = io.read(::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH) || ''
|
203
|
+
return '' unless buf.bytesize == ::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH
|
144
204
|
|
145
|
-
|
205
|
+
head, _, _, _, _, _, _, _, _, _, n_len, e_len = buf.unpack('VCCvvvvVVVvv')
|
206
|
+
return '' unless head == ::Zip::LOCAL_ENTRY_SIGNATURE
|
146
207
|
|
147
|
-
|
148
|
-
|
149
|
-
end
|
150
|
-
|
151
|
-
buf
|
208
|
+
io.seek(n_len, IO::SEEK_CUR) # Skip over the entry name.
|
209
|
+
io.read(e_len)
|
152
210
|
end
|
153
211
|
|
154
|
-
def
|
155
|
-
|
156
|
-
end
|
212
|
+
def read_eocds(io) #:nodoc:
|
213
|
+
base_location, data = eocd_data(io)
|
157
214
|
|
158
|
-
|
159
|
-
|
160
|
-
io.seek(-MAX_END_OF_CDS_SIZE, IO::SEEK_END)
|
161
|
-
rescue Errno::EINVAL
|
162
|
-
io.seek(0, IO::SEEK_SET)
|
163
|
-
end
|
164
|
-
io.read
|
165
|
-
end
|
215
|
+
eocd_location = data.rindex([END_OF_CD_SIG].pack('V'))
|
216
|
+
raise Error, 'Zip end of central directory signature not found' unless eocd_location
|
166
217
|
|
167
|
-
|
168
|
-
zip_64_start = buf.rindex([ZIP64_END_OF_CDS].pack('V'))
|
169
|
-
raise Error, 'Zip64 end of central directory signature not found' unless zip_64_start
|
218
|
+
zip64_eocd_locator = data.rindex([ZIP64_EOCD_LOCATOR_SIG].pack('V'))
|
170
219
|
|
171
|
-
|
172
|
-
|
220
|
+
if zip64_eocd_locator
|
221
|
+
zip64_eocd_location = data.rindex([ZIP64_END_OF_CD_SIG].pack('V'))
|
173
222
|
|
174
|
-
|
223
|
+
zip64_eocd_data =
|
224
|
+
if zip64_eocd_location
|
225
|
+
data.slice(zip64_eocd_location..zip64_eocd_locator)
|
226
|
+
else
|
227
|
+
zip64_eocd_location = unpack_64_eocd_locator(
|
228
|
+
data.slice(zip64_eocd_locator..eocd_location)
|
229
|
+
)
|
230
|
+
unless zip64_eocd_location
|
231
|
+
raise Error, 'Zip64 end of central directory signature not found'
|
232
|
+
end
|
175
233
|
|
176
|
-
|
177
|
-
|
178
|
-
|
234
|
+
io.seek(zip64_eocd_location, IO::SEEK_SET)
|
235
|
+
io.read(base_location + zip64_eocd_locator - zip64_eocd_location)
|
236
|
+
end
|
179
237
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
# For iterating over the entries.
|
184
|
-
def each(&a_proc)
|
185
|
-
@entry_set.each(&a_proc)
|
186
|
-
end
|
187
|
-
|
188
|
-
# Returns the number of entries in the central directory (and
|
189
|
-
# consequently in the zip archive).
|
190
|
-
def size
|
191
|
-
@entry_set.size
|
192
|
-
end
|
238
|
+
unpack_64_e_o_c_d(zip64_eocd_data)
|
239
|
+
end
|
193
240
|
|
194
|
-
|
195
|
-
cdir = new
|
196
|
-
cdir.read_from_stream(io)
|
197
|
-
cdir
|
198
|
-
rescue Error
|
199
|
-
nil
|
241
|
+
unpack_e_o_c_d(data.slice(eocd_location..-1))
|
200
242
|
end
|
201
243
|
|
202
|
-
def
|
203
|
-
|
244
|
+
def eocd_data(io)
|
245
|
+
begin
|
246
|
+
io.seek(-MAX_END_OF_CD_SIZE, IO::SEEK_END)
|
247
|
+
rescue Errno::EINVAL
|
248
|
+
io.seek(0, IO::SEEK_SET)
|
249
|
+
end
|
204
250
|
|
205
|
-
|
251
|
+
[io.tell, io.read]
|
206
252
|
end
|
207
253
|
end
|
208
254
|
end
|
data/lib/zip/compressor.rb
CHANGED
data/lib/zip/constants.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Zip
|
2
4
|
RUNNING_ON_WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/i
|
3
5
|
|
@@ -11,6 +13,8 @@ module Zip
|
|
11
13
|
VERSION_NEEDED_TO_EXTRACT = 20
|
12
14
|
VERSION_NEEDED_TO_EXTRACT_ZIP64 = 45
|
13
15
|
|
16
|
+
SPLIT_FILE_SIGNATURE = 0x08074b50
|
17
|
+
|
14
18
|
FILE_TYPE_FILE = 0o10
|
15
19
|
FILE_TYPE_DIR = 0o04
|
16
20
|
FILE_TYPE_SYMLINK = 0o12
|
@@ -38,27 +42,27 @@ module Zip
|
|
38
42
|
FSTYPE_ATHEOS = 30
|
39
43
|
|
40
44
|
FSTYPES = {
|
41
|
-
FSTYPE_FAT => 'FAT'
|
42
|
-
FSTYPE_AMIGA => 'Amiga'
|
43
|
-
FSTYPE_VMS => 'VMS (Vax or Alpha AXP)'
|
44
|
-
FSTYPE_UNIX => 'Unix'
|
45
|
-
FSTYPE_VM_CMS => 'VM/CMS'
|
46
|
-
FSTYPE_ATARI => 'Atari ST'
|
47
|
-
FSTYPE_HPFS => 'OS/2 or NT HPFS'
|
48
|
-
FSTYPE_MAC => 'Macintosh'
|
49
|
-
FSTYPE_Z_SYSTEM => 'Z-System'
|
50
|
-
FSTYPE_CPM => 'CP/M'
|
51
|
-
FSTYPE_TOPS20 => 'TOPS-20'
|
52
|
-
FSTYPE_NTFS => 'NTFS'
|
53
|
-
FSTYPE_QDOS => 'SMS/QDOS'
|
54
|
-
FSTYPE_ACORN => 'Acorn RISC OS'
|
55
|
-
FSTYPE_VFAT => 'Win32 VFAT'
|
56
|
-
FSTYPE_MVS => 'MVS'
|
57
|
-
FSTYPE_BEOS => 'BeOS'
|
58
|
-
FSTYPE_TANDEM => 'Tandem NSK'
|
59
|
-
FSTYPE_THEOS => 'Theos'
|
60
|
-
FSTYPE_MAC_OSX => 'Mac OS/X (Darwin)'
|
61
|
-
FSTYPE_ATHEOS => 'AtheOS'
|
45
|
+
FSTYPE_FAT => 'FAT',
|
46
|
+
FSTYPE_AMIGA => 'Amiga',
|
47
|
+
FSTYPE_VMS => 'VMS (Vax or Alpha AXP)',
|
48
|
+
FSTYPE_UNIX => 'Unix',
|
49
|
+
FSTYPE_VM_CMS => 'VM/CMS',
|
50
|
+
FSTYPE_ATARI => 'Atari ST',
|
51
|
+
FSTYPE_HPFS => 'OS/2 or NT HPFS',
|
52
|
+
FSTYPE_MAC => 'Macintosh',
|
53
|
+
FSTYPE_Z_SYSTEM => 'Z-System',
|
54
|
+
FSTYPE_CPM => 'CP/M',
|
55
|
+
FSTYPE_TOPS20 => 'TOPS-20',
|
56
|
+
FSTYPE_NTFS => 'NTFS',
|
57
|
+
FSTYPE_QDOS => 'SMS/QDOS',
|
58
|
+
FSTYPE_ACORN => 'Acorn RISC OS',
|
59
|
+
FSTYPE_VFAT => 'Win32 VFAT',
|
60
|
+
FSTYPE_MVS => 'MVS',
|
61
|
+
FSTYPE_BEOS => 'BeOS',
|
62
|
+
FSTYPE_TANDEM => 'Tandem NSK',
|
63
|
+
FSTYPE_THEOS => 'Theos',
|
64
|
+
FSTYPE_MAC_OSX => 'Mac OS/X (Darwin)',
|
65
|
+
FSTYPE_ATHEOS => 'AtheOS'
|
62
66
|
}.freeze
|
63
67
|
|
64
68
|
COMPRESSION_METHOD_STORE = 0
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Zip
|
2
|
-
module NullEncryption
|
4
|
+
module NullEncryption # :nodoc:
|
3
5
|
def header_bytesize
|
4
6
|
0
|
5
7
|
end
|
@@ -9,7 +11,7 @@ module Zip
|
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
12
|
-
class NullEncrypter < Encrypter
|
14
|
+
class NullEncrypter < Encrypter # :nodoc:
|
13
15
|
include NullEncryption
|
14
16
|
|
15
17
|
def header(_mtime)
|
@@ -27,7 +29,7 @@ module Zip
|
|
27
29
|
def reset!; end
|
28
30
|
end
|
29
31
|
|
30
|
-
class NullDecrypter < Decrypter
|
32
|
+
class NullDecrypter < Decrypter # :nodoc:
|
31
33
|
include NullEncryption
|
32
34
|
|
33
35
|
def decrypt(data)
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Zip
|
2
|
-
module TraditionalEncryption
|
4
|
+
module TraditionalEncryption # :nodoc:
|
3
5
|
def initialize(password)
|
4
6
|
@password = password
|
5
7
|
reset_keys!
|
@@ -36,7 +38,7 @@ module Zip
|
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
39
|
-
class TraditionalEncrypter < Encrypter
|
41
|
+
class TraditionalEncrypter < Encrypter # :nodoc:
|
40
42
|
include TraditionalEncryption
|
41
43
|
|
42
44
|
def header(mtime)
|
@@ -70,7 +72,7 @@ module Zip
|
|
70
72
|
end
|
71
73
|
end
|
72
74
|
|
73
|
-
class TraditionalDecrypter < Decrypter
|
75
|
+
class TraditionalDecrypter < Decrypter # :nodoc:
|
74
76
|
include TraditionalEncryption
|
75
77
|
|
76
78
|
def decrypt(data)
|
data/lib/zip/decompressor.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Zip
|
2
|
-
class Decompressor
|
4
|
+
class Decompressor # :nodoc:all
|
3
5
|
CHUNK_SIZE = 32_768
|
4
6
|
|
5
7
|
def self.decompressor_classes
|
@@ -14,8 +16,7 @@ module Zip
|
|
14
16
|
decompressor_classes[compression_method]
|
15
17
|
end
|
16
18
|
|
17
|
-
attr_reader :input_stream
|
18
|
-
attr_reader :decompressed_size
|
19
|
+
attr_reader :decompressed_size, :input_stream
|
19
20
|
|
20
21
|
def initialize(input_stream, decompressed_size = nil)
|
21
22
|
super()
|
data/lib/zip/deflater.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Zip
|
2
|
-
class Deflater < Compressor
|
4
|
+
class Deflater < Compressor # :nodoc:all
|
3
5
|
def initialize(output_stream, level = Zip.default_compression, encrypter = NullEncrypter.new)
|
4
6
|
super()
|
5
7
|
@output_stream = output_stream
|
@@ -13,16 +15,16 @@ module Zip
|
|
13
15
|
val = data.to_s
|
14
16
|
@crc = Zlib.crc32(val, @crc)
|
15
17
|
@size += val.bytesize
|
16
|
-
buffer = @zlib_deflater.deflate(data)
|
17
|
-
if buffer.empty?
|
18
|
-
|
19
|
-
|
20
|
-
@output_stream << @encrypter.encrypt(buffer)
|
21
|
-
end
|
18
|
+
buffer = @zlib_deflater.deflate(data, Zlib::SYNC_FLUSH)
|
19
|
+
return @output_stream if buffer.empty?
|
20
|
+
|
21
|
+
@output_stream << @encrypter.encrypt(buffer)
|
22
22
|
end
|
23
23
|
|
24
24
|
def finish
|
25
|
-
|
25
|
+
buffer = @zlib_deflater.finish
|
26
|
+
@output_stream << @encrypter.encrypt(buffer) unless buffer.empty?
|
27
|
+
@zlib_deflater.close
|
26
28
|
end
|
27
29
|
|
28
30
|
attr_reader :size, :crc
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zip
|
4
|
+
module Dirtyable # :nodoc:all
|
5
|
+
def initialize(dirty_on_create: true)
|
6
|
+
@dirty = dirty_on_create
|
7
|
+
end
|
8
|
+
|
9
|
+
def dirty?
|
10
|
+
@dirty
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods # :nodoc:
|
14
|
+
def mark_dirty(*symbols) # :nodoc:
|
15
|
+
# Move the original method and call it after we've set the dirty flag.
|
16
|
+
symbols.each do |symbol|
|
17
|
+
orig_name = "orig_#{symbol}"
|
18
|
+
alias_method orig_name, symbol
|
19
|
+
|
20
|
+
define_method(symbol) do |param|
|
21
|
+
@dirty = true
|
22
|
+
send(orig_name, param)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.included(base)
|
29
|
+
base.extend(ClassMethods)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|