rubyzip 0.9.9 → 1.0.0.beta1
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 +7 -0
- data/NEWS +9 -5
- data/README.md +79 -21
- data/Rakefile +1 -1
- data/lib/zip.rb +52 -0
- data/lib/zip/central_directory.rb +135 -0
- data/lib/zip/constants.rb +57 -7
- data/lib/zip/decompressor.rb +2 -2
- data/lib/zip/deflater.rb +11 -12
- data/lib/zip/dos_time.rb +9 -9
- data/lib/zip/entry.rb +609 -0
- data/lib/zip/entry_set.rb +86 -0
- data/lib/zip/errors.rb +8 -0
- data/lib/zip/extra_field.rb +90 -0
- data/lib/zip/extra_field/generic.rb +43 -0
- data/lib/zip/extra_field/universal_time.rb +47 -0
- data/lib/zip/extra_field/unix.rb +39 -0
- data/lib/zip/{zip_file.rb → file.rb} +140 -61
- data/lib/zip/{zipfilesystem.rb → filesystem.rb} +12 -12
- data/lib/zip/inflater.rb +24 -24
- data/lib/zip/{zip_input_stream.rb → input_stream.rb} +11 -10
- data/lib/zip/ioextras.rb +145 -123
- data/lib/zip/null_compressor.rb +1 -1
- data/lib/zip/null_decompressor.rb +5 -3
- data/lib/zip/null_input_stream.rb +2 -2
- data/lib/zip/{zip_output_stream.rb → output_stream.rb} +43 -41
- data/lib/zip/pass_thru_compressor.rb +2 -2
- data/lib/zip/pass_thru_decompressor.rb +17 -16
- data/lib/zip/{zip_streamable_directory.rb → streamable_directory.rb} +1 -1
- data/lib/zip/{zip_streamable_stream.rb → streamable_stream.rb} +2 -2
- data/lib/zip/version.rb +3 -0
- data/samples/example.rb +27 -5
- data/samples/example_filesystem.rb +2 -2
- data/samples/example_recursive.rb +1 -1
- data/samples/gtkRubyzip.rb +1 -1
- data/samples/qtzip.rb +2 -2
- data/samples/write_simple.rb +1 -1
- data/samples/zipfind.rb +1 -1
- metadata +29 -27
- 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_entry.rb
DELETED
@@ -1,638 +0,0 @@
|
|
1
|
-
module Zip
|
2
|
-
class ZipEntry
|
3
|
-
STORED = 0
|
4
|
-
DEFLATED = 8
|
5
|
-
|
6
|
-
FSTYPE_FAT = 0
|
7
|
-
FSTYPE_AMIGA = 1
|
8
|
-
FSTYPE_VMS = 2
|
9
|
-
FSTYPE_UNIX = 3
|
10
|
-
FSTYPE_VM_CMS = 4
|
11
|
-
FSTYPE_ATARI = 5
|
12
|
-
FSTYPE_HPFS = 6
|
13
|
-
FSTYPE_MAC = 7
|
14
|
-
FSTYPE_Z_SYSTEM = 8
|
15
|
-
FSTYPE_CPM = 9
|
16
|
-
FSTYPE_TOPS20 = 10
|
17
|
-
FSTYPE_NTFS = 11
|
18
|
-
FSTYPE_QDOS = 12
|
19
|
-
FSTYPE_ACORN = 13
|
20
|
-
FSTYPE_VFAT = 14
|
21
|
-
FSTYPE_MVS = 15
|
22
|
-
FSTYPE_BEOS = 16
|
23
|
-
FSTYPE_TANDEM = 17
|
24
|
-
FSTYPE_THEOS = 18
|
25
|
-
FSTYPE_MAC_OSX = 19
|
26
|
-
FSTYPE_ATHEOS = 30
|
27
|
-
|
28
|
-
FSTYPES = {
|
29
|
-
FSTYPE_FAT => 'FAT'.freeze,
|
30
|
-
FSTYPE_AMIGA => 'Amiga'.freeze,
|
31
|
-
FSTYPE_VMS => 'VMS (Vax or Alpha AXP)'.freeze,
|
32
|
-
FSTYPE_UNIX => 'Unix'.freeze,
|
33
|
-
FSTYPE_VM_CMS => 'VM/CMS'.freeze,
|
34
|
-
FSTYPE_ATARI => 'Atari ST'.freeze,
|
35
|
-
FSTYPE_HPFS => 'OS/2 or NT HPFS'.freeze,
|
36
|
-
FSTYPE_MAC => 'Macintosh'.freeze,
|
37
|
-
FSTYPE_Z_SYSTEM => 'Z-System'.freeze,
|
38
|
-
FSTYPE_CPM => 'CP/M'.freeze,
|
39
|
-
FSTYPE_TOPS20 => 'TOPS-20'.freeze,
|
40
|
-
FSTYPE_NTFS => 'NTFS'.freeze,
|
41
|
-
FSTYPE_QDOS => 'SMS/QDOS'.freeze,
|
42
|
-
FSTYPE_ACORN => 'Acorn RISC OS'.freeze,
|
43
|
-
FSTYPE_VFAT => 'Win32 VFAT'.freeze,
|
44
|
-
FSTYPE_MVS => 'MVS'.freeze,
|
45
|
-
FSTYPE_BEOS => 'BeOS'.freeze,
|
46
|
-
FSTYPE_TANDEM => 'Tandem NSK'.freeze,
|
47
|
-
FSTYPE_THEOS => 'Theos'.freeze,
|
48
|
-
FSTYPE_MAC_OSX => 'Mac OS/X (Darwin)'.freeze,
|
49
|
-
FSTYPE_ATHEOS => 'AtheOS'.freeze,
|
50
|
-
}.freeze
|
51
|
-
|
52
|
-
attr_accessor :comment, :compressed_size, :crc, :extra, :compression_method,
|
53
|
-
:name, :size, :localHeaderOffset, :zipfile, :fstype, :externalFileAttributes, :gp_flags, :header_signature
|
54
|
-
|
55
|
-
attr_accessor :follow_symlinks
|
56
|
-
attr_accessor :restore_times, :restore_permissions, :restore_ownership
|
57
|
-
attr_accessor :unix_uid, :unix_gid, :unix_perms
|
58
|
-
attr_accessor :dirty
|
59
|
-
attr_reader :ftype, :filepath # :nodoc:
|
60
|
-
|
61
|
-
def initialize(zipfile = "", name = "", comment = "", extra = "",
|
62
|
-
compressed_size = 0, crc = 0,
|
63
|
-
compression_method = ZipEntry::DEFLATED, size = 0,
|
64
|
-
time = DOSTime.now)
|
65
|
-
super()
|
66
|
-
if name.start_with?("/")
|
67
|
-
raise ZipEntryNameError, "Illegal ZipEntry name '#{name}', name must not start with /"
|
68
|
-
end
|
69
|
-
@localHeaderOffset = 0
|
70
|
-
@local_header_size = 0
|
71
|
-
@internalFileAttributes = 1
|
72
|
-
@externalFileAttributes = 0
|
73
|
-
@header_signature = CENTRAL_DIRECTORY_ENTRY_SIGNATURE
|
74
|
-
@versionNeededToExtract = VERSION_NEEDED_TO_EXTRACT
|
75
|
-
@version = 52 # this library's version
|
76
|
-
@ftype = nil # unspecified or unknown
|
77
|
-
@filepath = nil
|
78
|
-
if Zip::RUNNING_ON_WINDOWS
|
79
|
-
@fstype = FSTYPE_FAT
|
80
|
-
else
|
81
|
-
@fstype = FSTYPE_UNIX
|
82
|
-
end
|
83
|
-
@zipfile = zipfile
|
84
|
-
@comment = comment
|
85
|
-
@compressed_size = compressed_size
|
86
|
-
@crc = crc
|
87
|
-
@extra = extra
|
88
|
-
@compression_method = compression_method
|
89
|
-
@name = name
|
90
|
-
@size = size
|
91
|
-
@time = time
|
92
|
-
@gp_flags = 0
|
93
|
-
|
94
|
-
@follow_symlinks = false
|
95
|
-
|
96
|
-
@restore_times = true
|
97
|
-
@restore_permissions = false
|
98
|
-
@restore_ownership = false
|
99
|
-
|
100
|
-
# BUG: need an extra field to support uid/gid's
|
101
|
-
@unix_uid = nil
|
102
|
-
@unix_gid = nil
|
103
|
-
@unix_perms = nil
|
104
|
-
# @posix_acl = nil
|
105
|
-
# @ntfs_acl = nil
|
106
|
-
|
107
|
-
if name_is_directory?
|
108
|
-
@ftype = :directory
|
109
|
-
else
|
110
|
-
@ftype = :file
|
111
|
-
end
|
112
|
-
|
113
|
-
unless ZipExtraField === @extra
|
114
|
-
@extra = ZipExtraField.new(@extra.to_s)
|
115
|
-
end
|
116
|
-
|
117
|
-
@dirty = false
|
118
|
-
end
|
119
|
-
|
120
|
-
def time
|
121
|
-
if @extra["UniversalTime"]
|
122
|
-
@extra["UniversalTime"].mtime
|
123
|
-
else
|
124
|
-
# Standard time field in central directory has local time
|
125
|
-
# under archive creator. Then, we can't get timezone.
|
126
|
-
@time
|
127
|
-
end
|
128
|
-
end
|
129
|
-
alias :mtime :time
|
130
|
-
|
131
|
-
def time=(aTime)
|
132
|
-
unless @extra.member?("UniversalTime")
|
133
|
-
@extra.create("UniversalTime")
|
134
|
-
end
|
135
|
-
@extra["UniversalTime"].mtime = aTime
|
136
|
-
@time = aTime
|
137
|
-
end
|
138
|
-
|
139
|
-
# Returns +true+ if the entry is a directory.
|
140
|
-
def directory?
|
141
|
-
raise ZipInternalError, "current filetype is unknown: #{self.inspect}" unless @ftype
|
142
|
-
@ftype == :directory
|
143
|
-
end
|
144
|
-
alias :is_directory :directory?
|
145
|
-
|
146
|
-
# Returns +true+ if the entry is a file.
|
147
|
-
def file?
|
148
|
-
raise ZipInternalError, "current filetype is unknown: #{self.inspect}" unless @ftype
|
149
|
-
@ftype == :file
|
150
|
-
end
|
151
|
-
|
152
|
-
# Returns +true+ if the entry is a symlink.
|
153
|
-
def symlink?
|
154
|
-
raise ZipInternalError, "current filetype is unknown: #{self.inspect}" unless @ftype
|
155
|
-
@ftype == :symlink
|
156
|
-
end
|
157
|
-
|
158
|
-
def name_is_directory? #:nodoc:all
|
159
|
-
(%r{\/$} =~ @name) != nil
|
160
|
-
end
|
161
|
-
|
162
|
-
def local_entry_offset #:nodoc:all
|
163
|
-
localHeaderOffset + @local_header_size
|
164
|
-
end
|
165
|
-
|
166
|
-
def calculate_local_header_size #:nodoc:all
|
167
|
-
LOCAL_ENTRY_STATIC_HEADER_LENGTH + (@name ? @name.bytesize : 0) + (@extra ? @extra.local_size : 0)
|
168
|
-
end
|
169
|
-
|
170
|
-
def cdir_header_size #:nodoc:all
|
171
|
-
CDIR_ENTRY_STATIC_HEADER_LENGTH + (@name ? @name.bytesize : 0) +
|
172
|
-
(@extra ? @extra.c_dir_size : 0) + (@comment ? @comment.bytesize : 0)
|
173
|
-
end
|
174
|
-
|
175
|
-
def next_header_offset #:nodoc:all
|
176
|
-
local_entry_offset + self.compressed_size
|
177
|
-
end
|
178
|
-
|
179
|
-
# Extracts entry to file destPath (defaults to @name).
|
180
|
-
def extract(destPath = @name, &onExistsProc)
|
181
|
-
onExistsProc ||= proc { Zip.options[:on_exists_proc] }
|
182
|
-
|
183
|
-
if directory?
|
184
|
-
create_directory(destPath, &onExistsProc)
|
185
|
-
elsif file?
|
186
|
-
write_file(destPath, &onExistsProc)
|
187
|
-
elsif symlink?
|
188
|
-
create_symlink(destPath, &onExistsProc)
|
189
|
-
else
|
190
|
-
raise RuntimeError, "unknown file type #{self.inspect}"
|
191
|
-
end
|
192
|
-
|
193
|
-
self
|
194
|
-
end
|
195
|
-
|
196
|
-
def to_s
|
197
|
-
@name
|
198
|
-
end
|
199
|
-
|
200
|
-
protected
|
201
|
-
|
202
|
-
class << self
|
203
|
-
def read_zip_short(io) # :nodoc:
|
204
|
-
io.read(2).unpack('v')[0]
|
205
|
-
end
|
206
|
-
|
207
|
-
def read_zip_long(io) # :nodoc:
|
208
|
-
io.read(4).unpack('V')[0]
|
209
|
-
end
|
210
|
-
|
211
|
-
def read_c_dir_entry(io) #:nodoc:all
|
212
|
-
entry = new(io.path)
|
213
|
-
entry.read_c_dir_entry(io)
|
214
|
-
entry
|
215
|
-
rescue ZipError
|
216
|
-
nil
|
217
|
-
end
|
218
|
-
|
219
|
-
def read_local_entry(io)
|
220
|
-
entry = new(io.path)
|
221
|
-
entry.read_local_entry(io)
|
222
|
-
entry
|
223
|
-
rescue ZipError
|
224
|
-
nil
|
225
|
-
end
|
226
|
-
|
227
|
-
end
|
228
|
-
|
229
|
-
public
|
230
|
-
|
231
|
-
LOCAL_ENTRY_SIGNATURE = 0x04034b50
|
232
|
-
LOCAL_ENTRY_STATIC_HEADER_LENGTH = 30
|
233
|
-
LOCAL_ENTRY_TRAILING_DESCRIPTOR_LENGTH = 4+4+4
|
234
|
-
VERSION_NEEDED_TO_EXTRACT = 20
|
235
|
-
|
236
|
-
def read_local_entry(io) #:nodoc:all
|
237
|
-
@localHeaderOffset = io.tell
|
238
|
-
staticSizedFieldsBuf = io.read(LOCAL_ENTRY_STATIC_HEADER_LENGTH)
|
239
|
-
unless (staticSizedFieldsBuf.size == LOCAL_ENTRY_STATIC_HEADER_LENGTH)
|
240
|
-
raise ZipError, "Premature end of file. Not enough data for zip entry local header"
|
241
|
-
end
|
242
|
-
|
243
|
-
@header_signature ,
|
244
|
-
@version ,
|
245
|
-
@fstype ,
|
246
|
-
@gp_flags ,
|
247
|
-
@compression_method,
|
248
|
-
lastModTime ,
|
249
|
-
lastModDate ,
|
250
|
-
@crc ,
|
251
|
-
@compressed_size ,
|
252
|
-
@size ,
|
253
|
-
nameLength ,
|
254
|
-
extraLength = staticSizedFieldsBuf.unpack('VCCvvvvVVVvv')
|
255
|
-
|
256
|
-
unless (@header_signature == LOCAL_ENTRY_SIGNATURE)
|
257
|
-
raise ZipError, "Zip local header magic not found at location '#{localHeaderOffset}'"
|
258
|
-
end
|
259
|
-
set_time(lastModDate, lastModTime)
|
260
|
-
|
261
|
-
@name = io.read(nameLength)
|
262
|
-
extra = io.read(extraLength)
|
263
|
-
until @name.sub!('\\', '/') == nil do end # some zip files use backslashes instead of slashes as path separators
|
264
|
-
if (extra && extra.bytesize != extraLength)
|
265
|
-
raise ZipError, "Truncated local zip entry header"
|
266
|
-
else
|
267
|
-
if ZipExtraField === @extra
|
268
|
-
@extra.merge(extra)
|
269
|
-
else
|
270
|
-
@extra = ZipExtraField.new(extra)
|
271
|
-
end
|
272
|
-
end
|
273
|
-
@local_header_size = calculate_local_header_size
|
274
|
-
end
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
def write_local_entry(io) #:nodoc:all
|
279
|
-
@localHeaderOffset = io.tell
|
280
|
-
|
281
|
-
io <<
|
282
|
-
[LOCAL_ENTRY_SIGNATURE ,
|
283
|
-
@versionNeededToExtract , # version needed to extract
|
284
|
-
@gp_flags , # @gp_flags ,
|
285
|
-
@compression_method ,
|
286
|
-
@time.to_binary_dos_time , # @lastModTime ,
|
287
|
-
@time.to_binary_dos_date , # @lastModDate ,
|
288
|
-
@crc ,
|
289
|
-
@compressed_size ,
|
290
|
-
@size ,
|
291
|
-
@name ? @name.bytesize : 0,
|
292
|
-
@extra? @extra.local_length : 0 ].pack('VvvvvvVVVvv')
|
293
|
-
io << @name
|
294
|
-
io << (@extra ? @extra.to_local_bin : "")
|
295
|
-
end
|
296
|
-
|
297
|
-
CENTRAL_DIRECTORY_ENTRY_SIGNATURE = 0x02014b50
|
298
|
-
CDIR_ENTRY_STATIC_HEADER_LENGTH = 46
|
299
|
-
|
300
|
-
def read_c_dir_entry(io) #:nodoc:all
|
301
|
-
staticSizedFieldsBuf = io.read(CDIR_ENTRY_STATIC_HEADER_LENGTH)
|
302
|
-
unless (staticSizedFieldsBuf.bytesize == CDIR_ENTRY_STATIC_HEADER_LENGTH)
|
303
|
-
raise ZipError, "Premature end of file. Not enough data for zip cdir entry header"
|
304
|
-
end
|
305
|
-
|
306
|
-
|
307
|
-
@header_signature ,
|
308
|
-
@version , # version of encoding software
|
309
|
-
@fstype , # filesystem type
|
310
|
-
@versionNeededToExtract ,
|
311
|
-
@gp_flags ,
|
312
|
-
@compression_method ,
|
313
|
-
lastModTime ,
|
314
|
-
lastModDate ,
|
315
|
-
@crc ,
|
316
|
-
@compressed_size ,
|
317
|
-
@size ,
|
318
|
-
nameLength ,
|
319
|
-
extraLength ,
|
320
|
-
commentLength ,
|
321
|
-
diskNumberStart ,
|
322
|
-
@internalFileAttributes ,
|
323
|
-
@externalFileAttributes ,
|
324
|
-
@localHeaderOffset ,
|
325
|
-
@name ,
|
326
|
-
@extra ,
|
327
|
-
@comment = staticSizedFieldsBuf.unpack('VCCvvvvvVVVvvvvvVV')
|
328
|
-
|
329
|
-
unless (@header_signature == CENTRAL_DIRECTORY_ENTRY_SIGNATURE)
|
330
|
-
raise ZipError, "Zip local header magic not found at location '#{localHeaderOffset}'"
|
331
|
-
end
|
332
|
-
set_time(lastModDate, lastModTime)
|
333
|
-
|
334
|
-
@name = io.read(nameLength)
|
335
|
-
until @name.sub!('\\', '/') == nil do end # some zip files use backslashes instead of slashes as path separators
|
336
|
-
if ZipExtraField === @extra
|
337
|
-
@extra.merge(io.read(extraLength))
|
338
|
-
else
|
339
|
-
@extra = ZipExtraField.new(io.read(extraLength))
|
340
|
-
end
|
341
|
-
@comment = io.read(commentLength)
|
342
|
-
unless (@comment && @comment.bytesize == commentLength)
|
343
|
-
raise ZipError, "Truncated cdir zip entry header"
|
344
|
-
end
|
345
|
-
|
346
|
-
case @fstype
|
347
|
-
when FSTYPE_UNIX
|
348
|
-
@unix_perms = (@externalFileAttributes >> 16) & 07777
|
349
|
-
|
350
|
-
case (@externalFileAttributes >> 28)
|
351
|
-
when 04
|
352
|
-
@ftype = :directory
|
353
|
-
when 010
|
354
|
-
@ftype = :file
|
355
|
-
when 012
|
356
|
-
@ftype = :symlink
|
357
|
-
else
|
358
|
-
#best case guess for whether it is a file or not
|
359
|
-
#Otherwise this would be set to unknown and that entry would never be able to extracted
|
360
|
-
if name_is_directory?
|
361
|
-
@ftype = :directory
|
362
|
-
else
|
363
|
-
@ftype = :file
|
364
|
-
end
|
365
|
-
end
|
366
|
-
else
|
367
|
-
if name_is_directory?
|
368
|
-
@ftype = :directory
|
369
|
-
else
|
370
|
-
@ftype = :file
|
371
|
-
end
|
372
|
-
end
|
373
|
-
@local_header_size = calculate_local_header_size
|
374
|
-
end
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
def file_stat(path) # :nodoc:
|
379
|
-
if @follow_symlinks
|
380
|
-
return File::stat(path)
|
381
|
-
else
|
382
|
-
return File::lstat(path)
|
383
|
-
end
|
384
|
-
end
|
385
|
-
|
386
|
-
def get_extra_attributes_from_path(path) # :nodoc:
|
387
|
-
unless Zip::RUNNING_ON_WINDOWS
|
388
|
-
stat = file_stat(path)
|
389
|
-
@unix_uid = stat.uid
|
390
|
-
@unix_gid = stat.gid
|
391
|
-
@unix_perms = stat.mode & 07777
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
|
-
def set_extra_attributes_on_path(destPath) # :nodoc:
|
396
|
-
return unless (file? or directory?)
|
397
|
-
|
398
|
-
case @fstype
|
399
|
-
when FSTYPE_UNIX
|
400
|
-
# BUG: does not update timestamps into account
|
401
|
-
# ignore setuid/setgid bits by default. honor if @restore_ownership
|
402
|
-
unix_perms_mask = 01777
|
403
|
-
unix_perms_mask = 07777 if (@restore_ownership)
|
404
|
-
FileUtils::chmod(@unix_perms & unix_perms_mask, destPath) if (@restore_permissions && @unix_perms)
|
405
|
-
FileUtils::chown(@unix_uid, @unix_gid, destPath) if (@restore_ownership && @unix_uid && @unix_gid && Process::egid == 0)
|
406
|
-
# File::utimes()
|
407
|
-
end
|
408
|
-
end
|
409
|
-
|
410
|
-
def write_c_dir_entry(io) #:nodoc:all
|
411
|
-
case @fstype
|
412
|
-
when FSTYPE_UNIX
|
413
|
-
ft = nil
|
414
|
-
case @ftype
|
415
|
-
when :file
|
416
|
-
ft = 010
|
417
|
-
@unix_perms ||= 0644
|
418
|
-
when :directory
|
419
|
-
ft = 004
|
420
|
-
@unix_perms ||= 0755
|
421
|
-
when :symlink
|
422
|
-
ft = 012
|
423
|
-
@unix_perms ||= 0755
|
424
|
-
end
|
425
|
-
|
426
|
-
if (!ft.nil?)
|
427
|
-
@externalFileAttributes = (ft << 12 | (@unix_perms & 07777)) << 16
|
428
|
-
end
|
429
|
-
end
|
430
|
-
|
431
|
-
tmp = [
|
432
|
-
@header_signature,
|
433
|
-
@version , # version of encoding software
|
434
|
-
@fstype , # filesystem type
|
435
|
-
@versionNeededToExtract , # @versionNeededToExtract ,
|
436
|
-
@gp_flags , # @gp_flags ,
|
437
|
-
@compression_method ,
|
438
|
-
@time.to_binary_dos_time , # @lastModTime ,
|
439
|
-
@time.to_binary_dos_date , # @lastModDate ,
|
440
|
-
@crc ,
|
441
|
-
@compressed_size ,
|
442
|
-
@size ,
|
443
|
-
@name ? @name.bytesize : 0 ,
|
444
|
-
@extra ? @extra.c_dir_length : 0 ,
|
445
|
-
@comment ? @comment.bytesize : 0 ,
|
446
|
-
0 , # disk number start
|
447
|
-
@internalFileAttributes , # file type (binary=0, text=1)
|
448
|
-
@externalFileAttributes , # native filesystem attributes
|
449
|
-
@localHeaderOffset ,
|
450
|
-
@name ,
|
451
|
-
@extra ,
|
452
|
-
@comment
|
453
|
-
]
|
454
|
-
|
455
|
-
io << tmp.pack('VCCvvvvvVVVvvvvvVV')
|
456
|
-
|
457
|
-
io << @name
|
458
|
-
io << (@extra ? @extra.to_c_dir_bin : "")
|
459
|
-
io << @comment
|
460
|
-
end
|
461
|
-
|
462
|
-
def == (other)
|
463
|
-
return false unless other.class == self.class
|
464
|
-
# Compares contents of local entry and exposed fields
|
465
|
-
(@compression_method == other.compression_method &&
|
466
|
-
@crc == other.crc &&
|
467
|
-
@compressed_size == other.compressed_size &&
|
468
|
-
@size == other.size &&
|
469
|
-
@name == other.name &&
|
470
|
-
@extra == other.extra &&
|
471
|
-
@filepath == other.filepath &&
|
472
|
-
self.time.dos_equals(other.time))
|
473
|
-
end
|
474
|
-
|
475
|
-
def <=> (other)
|
476
|
-
return to_s <=> other.to_s
|
477
|
-
end
|
478
|
-
|
479
|
-
# Returns an IO like object for the given ZipEntry.
|
480
|
-
# Warning: may behave weird with symlinks.
|
481
|
-
def get_input_stream(&aProc)
|
482
|
-
if @ftype == :directory
|
483
|
-
return yield(NullInputStream.instance) if block_given?
|
484
|
-
return NullInputStream.instance
|
485
|
-
elsif @filepath
|
486
|
-
case @ftype
|
487
|
-
when :file
|
488
|
-
return ::File.open(@filepath, "rb", &aProc)
|
489
|
-
when :symlink
|
490
|
-
linkpath = ::File::readlink(@filepath)
|
491
|
-
stringio = StringIO.new(linkpath)
|
492
|
-
return yield(stringio) if block_given?
|
493
|
-
return stringio
|
494
|
-
else
|
495
|
-
raise "unknown @ftype #{@ftype}"
|
496
|
-
end
|
497
|
-
else
|
498
|
-
zis = ZipInputStream.new(@zipfile, localHeaderOffset)
|
499
|
-
zis.get_next_entry
|
500
|
-
if block_given?
|
501
|
-
begin
|
502
|
-
return yield(zis)
|
503
|
-
ensure
|
504
|
-
zis.close
|
505
|
-
end
|
506
|
-
else
|
507
|
-
return zis
|
508
|
-
end
|
509
|
-
end
|
510
|
-
end
|
511
|
-
|
512
|
-
def gather_fileinfo_from_srcpath(srcPath) # :nodoc:
|
513
|
-
stat = file_stat(srcPath)
|
514
|
-
case stat.ftype
|
515
|
-
when 'file'
|
516
|
-
if name_is_directory?
|
517
|
-
raise ArgumentError,
|
518
|
-
"entry name '#{newEntry}' indicates directory entry, but "+
|
519
|
-
"'#{srcPath}' is not a directory"
|
520
|
-
end
|
521
|
-
@ftype = :file
|
522
|
-
when 'directory'
|
523
|
-
if ! name_is_directory?
|
524
|
-
@name += "/"
|
525
|
-
end
|
526
|
-
@ftype = :directory
|
527
|
-
when 'link'
|
528
|
-
if name_is_directory?
|
529
|
-
raise ArgumentError,
|
530
|
-
"entry name '#{newEntry}' indicates directory entry, but "+
|
531
|
-
"'#{srcPath}' is not a directory"
|
532
|
-
end
|
533
|
-
@ftype = :symlink
|
534
|
-
else
|
535
|
-
raise RuntimeError, "unknown file type: #{srcPath.inspect} #{stat.inspect}"
|
536
|
-
end
|
537
|
-
|
538
|
-
@filepath = srcPath
|
539
|
-
get_extra_attributes_from_path(@filepath)
|
540
|
-
end
|
541
|
-
|
542
|
-
def write_to_zip_output_stream(aZipOutputStream) #:nodoc:all
|
543
|
-
if @ftype == :directory
|
544
|
-
aZipOutputStream.put_next_entry(self)
|
545
|
-
elsif @filepath
|
546
|
-
aZipOutputStream.put_next_entry(self)
|
547
|
-
get_input_stream { |is| IOExtras.copy_stream(aZipOutputStream, is) }
|
548
|
-
else
|
549
|
-
aZipOutputStream.copy_raw_entry(self)
|
550
|
-
end
|
551
|
-
end
|
552
|
-
|
553
|
-
def parent_as_string
|
554
|
-
entry_name = name.chomp("/")
|
555
|
-
slash_index = entry_name.rindex("/")
|
556
|
-
slash_index ? entry_name.slice(0, slash_index+1) : nil
|
557
|
-
end
|
558
|
-
|
559
|
-
def get_raw_input_stream(&aProc)
|
560
|
-
::File.open(@zipfile, "rb", &aProc)
|
561
|
-
end
|
562
|
-
|
563
|
-
private
|
564
|
-
|
565
|
-
def set_time(binaryDosDate, binaryDosTime)
|
566
|
-
@time = DOSTime.parse_binary_dos_format(binaryDosDate, binaryDosTime)
|
567
|
-
rescue ArgumentError
|
568
|
-
puts "Invalid date/time in zip entry"
|
569
|
-
end
|
570
|
-
|
571
|
-
def write_file(destPath, continueOnExistsProc = proc { Zip.options[:continue_on_exists_proc] })
|
572
|
-
if ::File.exists?(destPath) && ! yield(self, destPath)
|
573
|
-
raise ZipDestinationFileExistsError,
|
574
|
-
"Destination '#{destPath}' already exists"
|
575
|
-
end
|
576
|
-
::File.open(destPath, "wb") do |os|
|
577
|
-
get_input_stream do |is|
|
578
|
-
set_extra_attributes_on_path(destPath)
|
579
|
-
|
580
|
-
buf = ''
|
581
|
-
while buf = is.sysread(Decompressor::CHUNK_SIZE, buf)
|
582
|
-
os << buf
|
583
|
-
end
|
584
|
-
end
|
585
|
-
end
|
586
|
-
end
|
587
|
-
|
588
|
-
def create_directory(destPath)
|
589
|
-
if ::File.directory?(destPath)
|
590
|
-
return
|
591
|
-
elsif ::File.exists?(destPath)
|
592
|
-
if block_given? && yield(self, destPath)
|
593
|
-
FileUtils::rm_f destPath
|
594
|
-
else
|
595
|
-
raise ZipDestinationFileExistsError,
|
596
|
-
"Cannot create directory '#{destPath}'. "+
|
597
|
-
"A file already exists with that name"
|
598
|
-
end
|
599
|
-
end
|
600
|
-
Dir.mkdir destPath
|
601
|
-
set_extra_attributes_on_path(destPath)
|
602
|
-
end
|
603
|
-
|
604
|
-
# BUG: create_symlink() does not use &onExistsProc
|
605
|
-
def create_symlink(destPath)
|
606
|
-
stat = nil
|
607
|
-
begin
|
608
|
-
stat = ::File::lstat(destPath)
|
609
|
-
rescue Errno::ENOENT
|
610
|
-
end
|
611
|
-
|
612
|
-
io = get_input_stream
|
613
|
-
linkto = io.read
|
614
|
-
|
615
|
-
if stat
|
616
|
-
if stat.symlink?
|
617
|
-
if ::File::readlink(destPath) == linkto
|
618
|
-
return
|
619
|
-
else
|
620
|
-
raise ZipDestinationFileExistsError,
|
621
|
-
"Cannot create symlink '#{destPath}'. "+
|
622
|
-
"A symlink already exists with that name"
|
623
|
-
end
|
624
|
-
else
|
625
|
-
raise ZipDestinationFileExistsError,
|
626
|
-
"Cannot create symlink '#{destPath}'. "+
|
627
|
-
"A file already exists with that name"
|
628
|
-
end
|
629
|
-
end
|
630
|
-
|
631
|
-
::File::symlink(linkto, destPath)
|
632
|
-
end
|
633
|
-
end
|
634
|
-
end
|
635
|
-
|
636
|
-
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
637
|
-
# rubyzip is free software; you can redistribute it and/or
|
638
|
-
# modify it under the terms of the ruby license.
|