rubyzip 0.9.5 → 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 +334 -45
- 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 +61 -8
- 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 +18 -14
- data/lib/zip/dos_time.rb +48 -0
- 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} +179 -164
- 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 +7 -7
- 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 +275 -41
- data/NEWS +0 -162
- data/lib/zip/stdrubyext.rb +0 -77
- data/lib/zip/tempfile_bugfixed.rb +0 -195
- data/lib/zip/zip.rb +0 -54
- data/lib/zip/zip_central_directory.rb +0 -139
- data/lib/zip/zip_entry.rb +0 -639
- data/lib/zip/zip_entry_set.rb +0 -66
- data/lib/zip/zip_extra_field.rb +0 -213
- data/lib/zip/zip_file.rb +0 -318
- data/lib/zip/zip_input_stream.rb +0 -134
- data/lib/zip/zip_output_stream.rb +0 -172
- data/lib/zip/zip_streamable_stream.rb +0 -47
@@ -1,41 +1,39 @@
|
|
1
|
-
require 'zip
|
1
|
+
require 'zip'
|
2
2
|
|
3
3
|
module Zip
|
4
|
-
|
5
|
-
#
|
6
|
-
# a zip archive that is similar to ruby's builtin File and Dir
|
4
|
+
# The ZipFileSystem API provides an API for accessing entries in
|
5
|
+
# a zip archive that is similar to ruby's builtin File and Dir
|
7
6
|
# classes.
|
8
7
|
#
|
9
|
-
# Requiring 'zip/
|
10
|
-
# making the methods in this module available on
|
8
|
+
# Requiring 'zip/filesystem' includes this module in Zip::File
|
9
|
+
# making the methods in this module available on Zip::File objects.
|
11
10
|
#
|
12
|
-
# Using this API the following example creates a new zip file
|
11
|
+
# Using this API the following example creates a new zip file
|
13
12
|
# <code>my.zip</code> containing a normal entry with the name
|
14
13
|
# <code>first.txt</code>, a directory entry named <code>mydir</code>
|
15
14
|
# and finally another normal entry named <code>second.txt</code>
|
16
15
|
#
|
17
|
-
# require 'zip/
|
18
|
-
#
|
19
|
-
# Zip::
|
16
|
+
# require 'zip/filesystem'
|
17
|
+
#
|
18
|
+
# Zip::File.open("my.zip", Zip::File::CREATE) {
|
20
19
|
# |zipfile|
|
21
20
|
# zipfile.file.open("first.txt", "w") { |f| f.puts "Hello world" }
|
22
21
|
# zipfile.dir.mkdir("mydir")
|
23
22
|
# zipfile.file.open("mydir/second.txt", "w") { |f| f.puts "Hello again" }
|
24
23
|
# }
|
25
24
|
#
|
26
|
-
# Reading is as easy as writing, as the following example shows. The
|
25
|
+
# Reading is as easy as writing, as the following example shows. The
|
27
26
|
# example writes the contents of <code>first.txt</code> from zip archive
|
28
27
|
# <code>my.zip</code> to standard out.
|
29
28
|
#
|
30
|
-
# require 'zip/
|
31
|
-
#
|
32
|
-
# Zip::
|
29
|
+
# require 'zip/filesystem'
|
30
|
+
#
|
31
|
+
# Zip::File.open("my.zip") {
|
33
32
|
# |zipfile|
|
34
33
|
# puts zipfile.file.read("first.txt")
|
35
34
|
# }
|
36
35
|
|
37
|
-
module
|
38
|
-
|
36
|
+
module FileSystem
|
39
37
|
def initialize # :nodoc:
|
40
38
|
mappedZip = ZipFileNameMapper.new(self)
|
41
39
|
@zipFsDir = ZipFsDir.new(mappedZip)
|
@@ -45,56 +43,59 @@ module Zip
|
|
45
43
|
end
|
46
44
|
|
47
45
|
# Returns a ZipFsDir which is much like ruby's builtin Dir (class)
|
48
|
-
# object, except it works on the
|
46
|
+
# object, except it works on the Zip::File on which this method is
|
49
47
|
# invoked
|
50
48
|
def dir
|
51
49
|
@zipFsDir
|
52
50
|
end
|
53
51
|
|
54
52
|
# Returns a ZipFsFile which is much like ruby's builtin File (class)
|
55
|
-
# object, except it works on the
|
53
|
+
# object, except it works on the Zip::File on which this method is
|
56
54
|
# invoked
|
57
55
|
def file
|
58
56
|
@zipFsFile
|
59
57
|
end
|
60
58
|
|
61
59
|
# Instances of this class are normally accessed via the accessor
|
62
|
-
#
|
63
|
-
# builtin File (class) object, except it works on
|
60
|
+
# Zip::File::file. An instance of ZipFsFile behaves like ruby's
|
61
|
+
# builtin File (class) object, except it works on Zip::File entries.
|
64
62
|
#
|
65
63
|
# The individual methods are not documented due to their
|
66
64
|
# similarity with the methods in File
|
67
65
|
class ZipFsFile
|
68
|
-
|
69
66
|
attr_writer :dir
|
70
|
-
#
|
67
|
+
# protected :dir
|
71
68
|
|
72
69
|
class ZipFsStat
|
70
|
+
class << self
|
71
|
+
def delegate_to_fs_file(*methods)
|
72
|
+
methods.each do |method|
|
73
|
+
class_eval <<-end_eval, __FILE__, __LINE__ + 1
|
74
|
+
def #{method} # def file?
|
75
|
+
@zipFsFile.#{method}(@entryName) # @zipFsFile.file?(@entryName)
|
76
|
+
end # end
|
77
|
+
end_eval
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
73
82
|
def initialize(zipFsFile, entryName)
|
74
83
|
@zipFsFile = zipFsFile
|
75
84
|
@entryName = entryName
|
76
85
|
end
|
77
86
|
|
78
|
-
def forward_invoke(msg)
|
79
|
-
@zipFsFile.send(msg, @entryName)
|
80
|
-
end
|
81
|
-
|
82
87
|
def kind_of?(t)
|
83
|
-
super || t == ::File::Stat
|
88
|
+
super || t == ::File::Stat
|
84
89
|
end
|
85
90
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
forward_message :forward_invoke, :executable?, :executable_real?
|
91
|
-
forward_message :forward_invoke, :sticky?, :owned?, :grpowned?
|
92
|
-
forward_message :forward_invoke, :setuid?, :setgid?
|
93
|
-
forward_message :forward_invoke, :zero?
|
94
|
-
forward_message :forward_invoke, :size, :size?
|
95
|
-
forward_message :forward_invoke, :mtime, :atime, :ctime
|
91
|
+
delegate_to_fs_file :file?, :directory?, :pipe?, :chardev?, :symlink?,
|
92
|
+
:socket?, :blockdev?, :readable?, :readable_real?, :writable?, :ctime,
|
93
|
+
:writable_real?, :executable?, :executable_real?, :sticky?, :owned?,
|
94
|
+
:grpowned?, :setuid?, :setgid?, :zero?, :size, :size?, :mtime, :atime
|
96
95
|
|
97
|
-
def blocks
|
96
|
+
def blocks
|
97
|
+
nil
|
98
|
+
end
|
98
99
|
|
99
100
|
def get_entry
|
100
101
|
@zipFsFile.__send__(:get_entry, @entryName)
|
@@ -103,8 +104,8 @@ module Zip
|
|
103
104
|
|
104
105
|
def gid
|
105
106
|
e = get_entry
|
106
|
-
if e.extra.member?
|
107
|
-
e.extra[
|
107
|
+
if e.extra.member? 'IUnix'
|
108
|
+
e.extra['IUnix'].gid || 0
|
108
109
|
else
|
109
110
|
0
|
110
111
|
end
|
@@ -112,43 +113,57 @@ module Zip
|
|
112
113
|
|
113
114
|
def uid
|
114
115
|
e = get_entry
|
115
|
-
if e.extra.member?
|
116
|
-
e.extra[
|
116
|
+
if e.extra.member? 'IUnix'
|
117
|
+
e.extra['IUnix'].uid || 0
|
117
118
|
else
|
118
119
|
0
|
119
120
|
end
|
120
121
|
end
|
121
122
|
|
122
|
-
def ino
|
123
|
+
def ino
|
124
|
+
0
|
125
|
+
end
|
123
126
|
|
124
|
-
def dev
|
127
|
+
def dev
|
128
|
+
0
|
129
|
+
end
|
125
130
|
|
126
|
-
def rdev
|
131
|
+
def rdev
|
132
|
+
0
|
133
|
+
end
|
127
134
|
|
128
|
-
def rdev_major
|
135
|
+
def rdev_major
|
136
|
+
0
|
137
|
+
end
|
129
138
|
|
130
|
-
def rdev_minor
|
139
|
+
def rdev_minor
|
140
|
+
0
|
141
|
+
end
|
131
142
|
|
132
143
|
def ftype
|
133
144
|
if file?
|
134
|
-
|
145
|
+
'file'
|
135
146
|
elsif directory?
|
136
|
-
|
147
|
+
'directory'
|
137
148
|
else
|
138
|
-
raise StandardError,
|
149
|
+
raise StandardError, 'Unknown file type'
|
139
150
|
end
|
140
151
|
end
|
141
152
|
|
142
|
-
def nlink
|
153
|
+
def nlink
|
154
|
+
1
|
155
|
+
end
|
143
156
|
|
144
|
-
def blksize
|
157
|
+
def blksize
|
158
|
+
nil
|
159
|
+
end
|
145
160
|
|
146
161
|
def mode
|
147
162
|
e = get_entry
|
148
163
|
if e.fstype == 3
|
149
|
-
e.
|
164
|
+
e.external_file_attributes >> 16
|
150
165
|
else
|
151
|
-
|
166
|
+
33_206 # 33206 is equivalent to -rw-rw-rw-
|
152
167
|
end
|
153
168
|
end
|
154
169
|
end
|
@@ -158,7 +173,7 @@ module Zip
|
|
158
173
|
end
|
159
174
|
|
160
175
|
def get_entry(fileName)
|
161
|
-
|
176
|
+
unless exists?(fileName)
|
162
177
|
raise Errno::ENOENT, "No such file or directory - #{fileName}"
|
163
178
|
end
|
164
179
|
@mappedZip.find_entry(fileName)
|
@@ -166,77 +181,75 @@ module Zip
|
|
166
181
|
private :get_entry
|
167
182
|
|
168
183
|
def unix_mode_cmp(fileName, mode)
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
false
|
174
|
-
end
|
184
|
+
e = get_entry(fileName)
|
185
|
+
e.fstype == 3 && ((e.external_file_attributes >> 16) & mode) != 0
|
186
|
+
rescue Errno::ENOENT
|
187
|
+
false
|
175
188
|
end
|
176
189
|
private :unix_mode_cmp
|
177
190
|
|
178
191
|
def exists?(fileName)
|
179
|
-
expand_path(fileName) ==
|
192
|
+
expand_path(fileName) == '/' || !@mappedZip.find_entry(fileName).nil?
|
180
193
|
end
|
181
|
-
alias
|
194
|
+
alias exist? exists?
|
182
195
|
|
183
196
|
# Permissions not implemented, so if the file exists it is accessible
|
184
|
-
alias owned?
|
185
|
-
alias grpowned?
|
197
|
+
alias owned? exists?
|
198
|
+
alias grpowned? exists?
|
186
199
|
|
187
200
|
def readable?(fileName)
|
188
|
-
unix_mode_cmp(fileName,
|
201
|
+
unix_mode_cmp(fileName, 0o444)
|
189
202
|
end
|
190
|
-
alias readable_real?
|
203
|
+
alias readable_real? readable?
|
191
204
|
|
192
205
|
def writable?(fileName)
|
193
|
-
unix_mode_cmp(fileName,
|
206
|
+
unix_mode_cmp(fileName, 0o222)
|
194
207
|
end
|
195
|
-
alias writable_real?
|
208
|
+
alias writable_real? writable?
|
196
209
|
|
197
210
|
def executable?(fileName)
|
198
|
-
unix_mode_cmp(fileName,
|
211
|
+
unix_mode_cmp(fileName, 0o111)
|
199
212
|
end
|
200
213
|
alias executable_real? executable?
|
201
214
|
|
202
215
|
def setuid?(fileName)
|
203
|
-
unix_mode_cmp(fileName,
|
216
|
+
unix_mode_cmp(fileName, 0o4000)
|
204
217
|
end
|
205
218
|
|
206
219
|
def setgid?(fileName)
|
207
|
-
unix_mode_cmp(fileName,
|
220
|
+
unix_mode_cmp(fileName, 0o2000)
|
208
221
|
end
|
209
222
|
|
210
223
|
def sticky?(fileName)
|
211
|
-
unix_mode_cmp(fileName,
|
224
|
+
unix_mode_cmp(fileName, 0o1000)
|
212
225
|
end
|
213
226
|
|
214
227
|
def umask(*args)
|
215
228
|
::File.umask(*args)
|
216
229
|
end
|
217
230
|
|
218
|
-
def truncate(
|
219
|
-
raise StandardError,
|
231
|
+
def truncate(_fileName, _len)
|
232
|
+
raise StandardError, 'truncate not supported'
|
220
233
|
end
|
221
234
|
|
222
235
|
def directory?(fileName)
|
223
236
|
entry = @mappedZip.find_entry(fileName)
|
224
|
-
expand_path(fileName) ==
|
237
|
+
expand_path(fileName) == '/' || (!entry.nil? && entry.directory?)
|
225
238
|
end
|
226
239
|
|
227
|
-
def open(fileName, openMode =
|
228
|
-
openMode.
|
240
|
+
def open(fileName, openMode = 'r', permissionInt = 0o644, &block)
|
241
|
+
openMode.delete!('b') # ignore b option
|
229
242
|
case openMode
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
243
|
+
when 'r'
|
244
|
+
@mappedZip.get_input_stream(fileName, &block)
|
245
|
+
when 'w'
|
246
|
+
@mappedZip.get_output_stream(fileName, permissionInt, &block)
|
247
|
+
else
|
248
|
+
raise StandardError, "openmode '#{openMode} not supported" unless openMode == 'r'
|
236
249
|
end
|
237
250
|
end
|
238
251
|
|
239
|
-
def new(fileName, openMode =
|
252
|
+
def new(fileName, openMode = 'r')
|
240
253
|
open(fileName, openMode)
|
241
254
|
end
|
242
255
|
|
@@ -247,43 +260,41 @@ module Zip
|
|
247
260
|
# Returns nil for not found and nil for directories
|
248
261
|
def size?(fileName)
|
249
262
|
entry = @mappedZip.find_entry(fileName)
|
250
|
-
|
263
|
+
entry.nil? || entry.directory? ? nil : entry.size
|
251
264
|
end
|
252
265
|
|
253
266
|
def chown(ownerInt, groupInt, *filenames)
|
254
|
-
filenames.each
|
267
|
+
filenames.each do |fileName|
|
255
268
|
e = get_entry(fileName)
|
256
|
-
unless e.extra.member?(
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
e.extra["IUnix"].gid = groupInt
|
261
|
-
}
|
269
|
+
e.extra.create('IUnix') unless e.extra.member?('IUnix')
|
270
|
+
e.extra['IUnix'].uid = ownerInt
|
271
|
+
e.extra['IUnix'].gid = groupInt
|
272
|
+
end
|
262
273
|
filenames.size
|
263
274
|
end
|
264
275
|
|
265
|
-
def chmod
|
266
|
-
filenames.each
|
276
|
+
def chmod(modeInt, *filenames)
|
277
|
+
filenames.each do |fileName|
|
267
278
|
e = get_entry(fileName)
|
268
279
|
e.fstype = 3 # force convertion filesystem type to unix
|
269
280
|
e.unix_perms = modeInt
|
270
|
-
e.
|
281
|
+
e.external_file_attributes = modeInt << 16
|
271
282
|
e.dirty = true
|
272
|
-
|
283
|
+
end
|
273
284
|
filenames.size
|
274
285
|
end
|
275
286
|
|
276
287
|
def zero?(fileName)
|
277
288
|
sz = size(fileName)
|
278
|
-
sz
|
289
|
+
sz.nil? || sz == 0
|
279
290
|
rescue Errno::ENOENT
|
280
291
|
false
|
281
292
|
end
|
282
293
|
|
283
294
|
def file?(fileName)
|
284
295
|
entry = @mappedZip.find_entry(fileName)
|
285
|
-
entry
|
286
|
-
end
|
296
|
+
!entry.nil? && entry.file?
|
297
|
+
end
|
287
298
|
|
288
299
|
def dirname(fileName)
|
289
300
|
::File.dirname(fileName)
|
@@ -302,9 +313,9 @@ module Zip
|
|
302
313
|
end
|
303
314
|
|
304
315
|
def utime(modifiedTime, *fileNames)
|
305
|
-
fileNames.each
|
316
|
+
fileNames.each do |fileName|
|
306
317
|
get_entry(fileName).time = modifiedTime
|
307
|
-
|
318
|
+
end
|
308
319
|
end
|
309
320
|
|
310
321
|
def mtime(fileName)
|
@@ -313,66 +324,64 @@ module Zip
|
|
313
324
|
|
314
325
|
def atime(fileName)
|
315
326
|
e = get_entry(fileName)
|
316
|
-
if e.extra.member?
|
317
|
-
e.extra[
|
318
|
-
|
319
|
-
|
327
|
+
if e.extra.member? 'UniversalTime'
|
328
|
+
e.extra['UniversalTime'].atime
|
329
|
+
elsif e.extra.member? 'NTFS'
|
330
|
+
e.extra['NTFS'].atime
|
320
331
|
end
|
321
332
|
end
|
322
333
|
|
323
334
|
def ctime(fileName)
|
324
335
|
e = get_entry(fileName)
|
325
|
-
if e.extra.member?
|
326
|
-
e.extra[
|
327
|
-
|
328
|
-
|
336
|
+
if e.extra.member? 'UniversalTime'
|
337
|
+
e.extra['UniversalTime'].ctime
|
338
|
+
elsif e.extra.member? 'NTFS'
|
339
|
+
e.extra['NTFS'].ctime
|
329
340
|
end
|
330
341
|
end
|
331
342
|
|
332
|
-
def pipe?(
|
343
|
+
def pipe?(_filename)
|
333
344
|
false
|
334
345
|
end
|
335
346
|
|
336
|
-
def blockdev?(
|
347
|
+
def blockdev?(_filename)
|
337
348
|
false
|
338
349
|
end
|
339
350
|
|
340
|
-
def chardev?(
|
351
|
+
def chardev?(_filename)
|
341
352
|
false
|
342
353
|
end
|
343
354
|
|
344
|
-
def symlink?(
|
355
|
+
def symlink?(_fileName)
|
345
356
|
false
|
346
357
|
end
|
347
358
|
|
348
|
-
def socket?(
|
359
|
+
def socket?(_fileName)
|
349
360
|
false
|
350
361
|
end
|
351
362
|
|
352
363
|
def ftype(fileName)
|
353
|
-
@mappedZip.get_entry(fileName).directory? ?
|
364
|
+
@mappedZip.get_entry(fileName).directory? ? 'directory' : 'file'
|
354
365
|
end
|
355
366
|
|
356
|
-
def readlink(
|
357
|
-
raise NotImplementedError,
|
367
|
+
def readlink(_fileName)
|
368
|
+
raise NotImplementedError, 'The readlink() function is not implemented'
|
358
369
|
end
|
359
370
|
|
360
|
-
def symlink(
|
361
|
-
raise NotImplementedError,
|
371
|
+
def symlink(_fileName, _symlinkName)
|
372
|
+
raise NotImplementedError, 'The symlink() function is not implemented'
|
362
373
|
end
|
363
374
|
|
364
|
-
def link(
|
365
|
-
raise NotImplementedError,
|
375
|
+
def link(_fileName, _symlinkName)
|
376
|
+
raise NotImplementedError, 'The link() function is not implemented'
|
366
377
|
end
|
367
378
|
|
368
379
|
def pipe
|
369
|
-
raise NotImplementedError,
|
380
|
+
raise NotImplementedError, 'The pipe() function is not implemented'
|
370
381
|
end
|
371
382
|
|
372
383
|
def stat(fileName)
|
373
|
-
|
374
|
-
raise Errno::ENOENT, fileName
|
375
|
-
end
|
384
|
+
raise Errno::ENOENT, fileName unless exists?(fileName)
|
376
385
|
ZipFsStat.new(self, fileName)
|
377
386
|
end
|
378
387
|
|
@@ -387,7 +396,7 @@ module Zip
|
|
387
396
|
end
|
388
397
|
|
389
398
|
def popen(*args, &aProc)
|
390
|
-
File.popen(*args, &aProc)
|
399
|
+
::File.popen(*args, &aProc)
|
391
400
|
end
|
392
401
|
|
393
402
|
def foreach(fileName, aSep = $/, &aProc)
|
@@ -395,20 +404,19 @@ module Zip
|
|
395
404
|
end
|
396
405
|
|
397
406
|
def delete(*args)
|
398
|
-
args.each
|
399
|
-
|fileName|
|
407
|
+
args.each do |fileName|
|
400
408
|
if directory?(fileName)
|
401
409
|
raise Errno::EISDIR, "Is a directory - \"#{fileName}\""
|
402
410
|
end
|
403
411
|
@mappedZip.remove(fileName)
|
404
|
-
|
412
|
+
end
|
405
413
|
end
|
406
414
|
|
407
415
|
def rename(fileToRename, newName)
|
408
416
|
@mappedZip.rename(fileToRename, newName) { true }
|
409
417
|
end
|
410
418
|
|
411
|
-
alias
|
419
|
+
alias unlink delete
|
412
420
|
|
413
421
|
def expand_path(aPath)
|
414
422
|
@mappedZip.expand_path(aPath)
|
@@ -422,7 +430,6 @@ module Zip
|
|
422
430
|
# The individual methods are not documented due to their
|
423
431
|
# similarity with the methods in Dir
|
424
432
|
class ZipFsDir
|
425
|
-
|
426
433
|
def initialize(mappedZip)
|
427
434
|
@mappedZip = mappedZip
|
428
435
|
end
|
@@ -446,7 +453,9 @@ module Zip
|
|
446
453
|
dirIt
|
447
454
|
end
|
448
455
|
|
449
|
-
def pwd
|
456
|
+
def pwd
|
457
|
+
@mappedZip.pwd
|
458
|
+
end
|
450
459
|
alias getwd pwd
|
451
460
|
|
452
461
|
def chdir(aDirectoryName)
|
@@ -462,18 +471,22 @@ module Zip
|
|
462
471
|
entries
|
463
472
|
end
|
464
473
|
|
474
|
+
def glob(*args, &block)
|
475
|
+
@mappedZip.glob(*args, &block)
|
476
|
+
end
|
477
|
+
|
465
478
|
def foreach(aDirectoryName)
|
466
479
|
unless @file.stat(aDirectoryName).directory?
|
467
480
|
raise Errno::ENOTDIR, aDirectoryName
|
468
481
|
end
|
469
|
-
path = @file.expand_path(aDirectoryName)
|
482
|
+
path = @file.expand_path(aDirectoryName)
|
483
|
+
path << '/' unless path.end_with?('/')
|
470
484
|
path = Regexp.escape(path)
|
471
485
|
subDirEntriesRegex = Regexp.new("^#{path}([^/]+)$")
|
472
|
-
@mappedZip.each
|
473
|
-
|fileName|
|
486
|
+
@mappedZip.each do |fileName|
|
474
487
|
match = subDirEntriesRegex.match(fileName)
|
475
|
-
yield(match[1]) unless match
|
476
|
-
|
488
|
+
yield(match[1]) unless match.nil?
|
489
|
+
end
|
477
490
|
end
|
478
491
|
|
479
492
|
def delete(entryName)
|
@@ -482,17 +495,16 @@ module Zip
|
|
482
495
|
end
|
483
496
|
@mappedZip.remove(entryName)
|
484
497
|
end
|
485
|
-
alias rmdir
|
498
|
+
alias rmdir delete
|
486
499
|
alias unlink delete
|
487
500
|
|
488
|
-
def mkdir(entryName, permissionInt =
|
501
|
+
def mkdir(entryName, permissionInt = 0o755)
|
489
502
|
@mappedZip.mkdir(entryName, permissionInt)
|
490
503
|
end
|
491
504
|
|
492
|
-
def chroot(*
|
493
|
-
raise NotImplementedError,
|
505
|
+
def chroot(*_args)
|
506
|
+
raise NotImplementedError, 'The chroot() function is not implemented'
|
494
507
|
end
|
495
|
-
|
496
508
|
end
|
497
509
|
|
498
510
|
class ZipFsDirIterator # :nodoc:all
|
@@ -508,39 +520,39 @@ module Zip
|
|
508
520
|
end
|
509
521
|
|
510
522
|
def each(&aProc)
|
511
|
-
raise IOError,
|
523
|
+
raise IOError, 'closed directory' if @fileNames.nil?
|
512
524
|
@fileNames.each(&aProc)
|
513
525
|
end
|
514
526
|
|
515
527
|
def read
|
516
|
-
raise IOError,
|
517
|
-
@fileNames[(@index+=1)-1]
|
528
|
+
raise IOError, 'closed directory' if @fileNames.nil?
|
529
|
+
@fileNames[(@index += 1) - 1]
|
518
530
|
end
|
519
531
|
|
520
532
|
def rewind
|
521
|
-
raise IOError,
|
533
|
+
raise IOError, 'closed directory' if @fileNames.nil?
|
522
534
|
@index = 0
|
523
535
|
end
|
524
536
|
|
525
537
|
def seek(anIntegerPosition)
|
526
|
-
raise IOError,
|
538
|
+
raise IOError, 'closed directory' if @fileNames.nil?
|
527
539
|
@index = anIntegerPosition
|
528
540
|
end
|
529
541
|
|
530
542
|
def tell
|
531
|
-
raise IOError,
|
543
|
+
raise IOError, 'closed directory' if @fileNames.nil?
|
532
544
|
@index
|
533
545
|
end
|
534
546
|
end
|
535
547
|
|
536
|
-
# All access to
|
548
|
+
# All access to Zip::File from ZipFsFile and ZipFsDir goes through a
|
537
549
|
# ZipFileNameMapper, which has one responsibility: ensure
|
538
550
|
class ZipFileNameMapper # :nodoc:all
|
539
551
|
include Enumerable
|
540
552
|
|
541
553
|
def initialize(zipFile)
|
542
554
|
@zipFile = zipFile
|
543
|
-
@pwd =
|
555
|
+
@pwd = '/'
|
544
556
|
end
|
545
557
|
|
546
558
|
attr_accessor :pwd
|
@@ -561,6 +573,10 @@ module Zip
|
|
561
573
|
@zipFile.get_output_stream(expand_to_entry(fileName), permissionInt, &aProc)
|
562
574
|
end
|
563
575
|
|
576
|
+
def glob(pattern, *flags, &block)
|
577
|
+
@zipFile.glob(expand_to_entry(pattern), *flags, &block)
|
578
|
+
end
|
579
|
+
|
564
580
|
def read(fileName)
|
565
581
|
@zipFile.read(expand_to_entry(fileName))
|
566
582
|
end
|
@@ -570,40 +586,39 @@ module Zip
|
|
570
586
|
end
|
571
587
|
|
572
588
|
def rename(fileName, newName, &continueOnExistsProc)
|
573
|
-
@zipFile.rename(expand_to_entry(fileName), expand_to_entry(newName),
|
589
|
+
@zipFile.rename(expand_to_entry(fileName), expand_to_entry(newName),
|
574
590
|
&continueOnExistsProc)
|
575
591
|
end
|
576
592
|
|
577
|
-
def mkdir(fileName, permissionInt =
|
593
|
+
def mkdir(fileName, permissionInt = 0o755)
|
578
594
|
@zipFile.mkdir(expand_to_entry(fileName), permissionInt)
|
579
595
|
end
|
580
596
|
|
581
597
|
# Turns entries into strings and adds leading /
|
582
598
|
# and removes trailing slash on directories
|
583
599
|
def each
|
584
|
-
@zipFile.each
|
585
|
-
|
586
|
-
|
587
|
-
}
|
600
|
+
@zipFile.each do |e|
|
601
|
+
yield('/' + e.to_s.chomp('/'))
|
602
|
+
end
|
588
603
|
end
|
589
604
|
|
590
605
|
def expand_path(aPath)
|
591
|
-
expanded = aPath.start_with?(
|
592
|
-
expanded.gsub!(/\/\.(\/|$)/,
|
593
|
-
expanded.gsub!(/[^\/]+\/\.\.(\/|$)/,
|
594
|
-
expanded.empty? ?
|
606
|
+
expanded = aPath.start_with?('/') ? aPath : ::File.join(@pwd, aPath)
|
607
|
+
expanded.gsub!(/\/\.(\/|$)/, '')
|
608
|
+
expanded.gsub!(/[^\/]+\/\.\.(\/|$)/, '')
|
609
|
+
expanded.empty? ? '/' : expanded
|
595
610
|
end
|
596
611
|
|
597
612
|
private
|
598
613
|
|
599
614
|
def expand_to_entry(aPath)
|
600
|
-
expand_path(aPath)
|
615
|
+
expand_path(aPath)[1..-1]
|
601
616
|
end
|
602
617
|
end
|
603
618
|
end
|
604
619
|
|
605
|
-
class
|
606
|
-
include
|
620
|
+
class File
|
621
|
+
include FileSystem
|
607
622
|
end
|
608
623
|
end
|
609
624
|
|