rubyzip 0.9.5 → 0.9.6.1
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.
- data/TODO +1 -1
- data/lib/zip/constants.rb +3 -2
- data/lib/zip/{stdrubyext.rb → dos_time.rb} +4 -34
- data/lib/zip/tempfile_bugfixed.rb +147 -147
- data/lib/zip/zip.rb +2 -2
- data/lib/zip/zip_entry.rb +15 -16
- data/lib/zip/zip_entry_set.rb +8 -8
- data/lib/zip/zip_extra_field.rb +3 -3
- data/lib/zip/zip_file.rb +17 -16
- data/lib/zip/zip_input_stream.rb +23 -13
- data/lib/zip/zip_output_stream.rb +3 -4
- data/lib/zip/zip_streamable_stream.rb +1 -1
- data/lib/zip/zipfilesystem.rb +23 -17
- data/samples/example_recursive.rb +1 -1
- metadata +4 -3
data/TODO
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
* Suggestion: Add ZipFile/ZipInputStream example that demonstrates extracting all entries.
|
5
5
|
* Suggestion: ZipFile#extract destination should default to "."
|
6
6
|
* Suggestion: ZipEntry should have extract(), get_input_stream() methods etc
|
7
|
-
*
|
7
|
+
* Suggestion: ZipInputStream/ZipOutputStream should accept an IO object in addition to a filename.
|
8
8
|
* (is buffering used anywhere with write?)
|
9
9
|
* Inflater.sysread should pass the buffer to produce_input.
|
10
10
|
* Implement ZipFsDir.glob
|
data/lib/zip/constants.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module Zip
|
2
|
-
VERSION = '0.9.
|
2
|
+
VERSION = '0.9.5'
|
3
3
|
RUBY_MINOR_VERSION = RUBY_VERSION.split(".")[1].to_i
|
4
|
-
RUNNING_ON_WINDOWS = RbConfig::CONFIG['host_os'] =~
|
4
|
+
RUNNING_ON_WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/i
|
5
|
+
|
5
6
|
# Ruby 1.7.x compatibility
|
6
7
|
# In ruby 1.6.x and 1.8.0 reading from an empty stream returns
|
7
8
|
# an empty string the first time and then nil.
|
@@ -1,37 +1,17 @@
|
|
1
|
-
|
2
|
-
# returns a new array of all the return values not equal to nil
|
3
|
-
# This implementation could be faster
|
4
|
-
def select_map(&aProc)
|
5
|
-
map(&aProc).reject { |e| e.nil? }
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
class String #:nodoc:all
|
10
|
-
|
11
|
-
def ensure_end(aString)
|
12
|
-
end_with?(aString) ? self : self + aString
|
13
|
-
end
|
14
|
-
|
15
|
-
def lchop
|
16
|
-
slice(1, length)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class Time #:nodoc:all
|
1
|
+
class DOSTime < Time #:nodoc:all
|
21
2
|
|
22
3
|
#MS-DOS File Date and Time format as used in Interrupt 21H Function 57H:
|
23
|
-
|
4
|
+
|
24
5
|
# Register CX, the Time:
|
25
6
|
# Bits 0-4 2 second increments (0-29)
|
26
7
|
# Bits 5-10 minutes (0-59)
|
27
8
|
# bits 11-15 hours (0-24)
|
28
|
-
|
9
|
+
|
29
10
|
# Register DX, the Date:
|
30
11
|
# Bits 0-4 day (1-31)
|
31
12
|
# bits 5-8 month (1-12)
|
32
13
|
# bits 9-15 year (four digit year minus 1980)
|
33
14
|
|
34
|
-
|
35
15
|
def to_binary_dos_time
|
36
16
|
(sec/2) +
|
37
17
|
(min << 5) +
|
@@ -57,21 +37,11 @@ class Time #:nodoc:all
|
|
57
37
|
month = ( 0b111100000 & binaryDosDate) >> 5
|
58
38
|
year = ((0b1111111000000000 & binaryDosDate) >> 9) + 1980
|
59
39
|
begin
|
60
|
-
return
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
class Module #:nodoc:all
|
66
|
-
def forward_message(forwarder, *messagesToForward)
|
67
|
-
methodDefs = messagesToForward.map do |msg|
|
68
|
-
"def #{msg}; #{forwarder}(:#{msg}); end"
|
40
|
+
return self.local(year, month, day, hour, minute, second)
|
69
41
|
end
|
70
|
-
module_eval(methodDefs.join("\n"))
|
71
42
|
end
|
72
43
|
end
|
73
44
|
|
74
|
-
|
75
45
|
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
76
46
|
# rubyzip is free software; you can redistribute it and/or
|
77
47
|
# modify it under the terms of the ruby license.
|
@@ -9,183 +9,183 @@ require 'tmpdir'
|
|
9
9
|
|
10
10
|
module BugFix #:nodoc:all
|
11
11
|
|
12
|
-
# A class for managing temporary files. This library is written to be
|
13
|
-
# thread safe.
|
14
|
-
class Tempfile < DelegateClass(File)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
12
|
+
# A class for managing temporary files. This library is written to be
|
13
|
+
# thread safe.
|
14
|
+
class Tempfile < DelegateClass(File)
|
15
|
+
MAX_TRY = 10
|
16
|
+
@@cleanlist = []
|
17
|
+
|
18
|
+
# Creates a temporary file of mode 0600 in the temporary directory
|
19
|
+
# whose name is basename.pid.n and opens with mode "w+". A Tempfile
|
20
|
+
# object works just like a File object.
|
21
|
+
#
|
22
|
+
# If tmpdir is omitted, the temporary directory is determined by
|
23
|
+
# Dir::tmpdir provided by 'tmpdir.rb'.
|
24
|
+
# When $SAFE > 0 and the given tmpdir is tainted, it uses
|
25
|
+
# /tmp. (Note that ENV values are tainted by default)
|
26
|
+
def initialize(basename, tmpdir=Dir::tmpdir)
|
27
|
+
if $SAFE > 0 and tmpdir.tainted?
|
28
|
+
tmpdir = '/tmp'
|
29
|
+
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
begin
|
35
|
-
Thread.critical = true
|
31
|
+
lock = nil
|
32
|
+
n = failure = 0
|
36
33
|
|
37
34
|
begin
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
ObjectSpace.define_finalizer(self, @clean_proc)
|
35
|
+
Thread.critical = true
|
36
|
+
|
37
|
+
begin
|
38
|
+
tmpname = sprintf('%s/%s%d.%d', tmpdir, basename, $$, n)
|
39
|
+
lock = tmpname + '.lock'
|
40
|
+
n += 1
|
41
|
+
end while @@cleanlist.include?(tmpname) ||
|
42
|
+
::File.exist?(lock) || ::File.exist?(tmpname)
|
43
|
+
|
44
|
+
Dir.mkdir(lock)
|
45
|
+
rescue
|
46
|
+
failure += 1
|
47
|
+
retry if failure < MAX_TRY
|
48
|
+
raise "cannot generate tempfile `%s'" % tmpname
|
49
|
+
ensure
|
50
|
+
Thread.critical = false
|
51
|
+
end
|
56
52
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
@data[1] = @tmpfile
|
61
|
-
@data[2] = @@cleanlist
|
53
|
+
@data = [tmpname]
|
54
|
+
@clean_proc = Tempfile.callback(@data)
|
55
|
+
ObjectSpace.define_finalizer(self, @clean_proc)
|
62
56
|
|
63
|
-
|
57
|
+
@tmpfile = ::File.open(tmpname, ::File::RDWR|::File::CREAT|::File::EXCL, 0600)
|
58
|
+
@tmpname = tmpname
|
59
|
+
@@cleanlist << @tmpname
|
60
|
+
@data[1] = @tmpfile
|
61
|
+
@data[2] = @@cleanlist
|
64
62
|
|
65
|
-
|
66
|
-
# carelessly put bare puts(), etc. after this.
|
63
|
+
super(@tmpfile)
|
67
64
|
|
68
|
-
|
69
|
-
|
65
|
+
# Now we have all the File/IO methods defined, you must not
|
66
|
+
# carelessly put bare puts(), etc. after this.
|
70
67
|
|
71
|
-
|
72
|
-
def open
|
73
|
-
@tmpfile.close if @tmpfile
|
74
|
-
@tmpfile = File.open(@tmpname, 'r+')
|
75
|
-
@data[1] = @tmpfile
|
76
|
-
__setobj__(@tmpfile)
|
77
|
-
end
|
78
|
-
|
79
|
-
def _close # :nodoc:
|
80
|
-
@tmpfile.close if @tmpfile
|
81
|
-
@data[1] = @tmpfile = nil
|
82
|
-
end
|
83
|
-
protected :_close
|
84
|
-
|
85
|
-
# Closes the file. If the optional flag is true, unlinks the file
|
86
|
-
# after closing.
|
87
|
-
#
|
88
|
-
# If you don't explicitly unlink the temporary file, the removal
|
89
|
-
# will be delayed until the object is finalized.
|
90
|
-
def close(unlink_now=false)
|
91
|
-
if unlink_now
|
92
|
-
close!
|
93
|
-
else
|
94
|
-
_close
|
68
|
+
Dir.rmdir(lock)
|
95
69
|
end
|
96
|
-
end
|
97
70
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
71
|
+
# Opens or reopens the file with mode "r+".
|
72
|
+
def open
|
73
|
+
@tmpfile.close if @tmpfile
|
74
|
+
@tmpfile = ::File.open(@tmpname, 'r+')
|
75
|
+
@data[1] = @tmpfile
|
76
|
+
__setobj__(@tmpfile)
|
77
|
+
end
|
104
78
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
# keep this order for thread safeness
|
111
|
-
File.unlink(@tmpname) if File.exist?(@tmpname)
|
112
|
-
@@cleanlist.delete(@tmpname) if @@cleanlist
|
113
|
-
end
|
114
|
-
alias delete unlink
|
79
|
+
def _close # :nodoc:
|
80
|
+
@tmpfile.close if @tmpfile
|
81
|
+
@data[1] = @tmpfile = nil
|
82
|
+
end
|
83
|
+
protected :_close
|
115
84
|
|
116
|
-
|
117
|
-
|
118
|
-
|
85
|
+
# Closes the file. If the optional flag is true, unlinks the file
|
86
|
+
# after closing.
|
87
|
+
#
|
88
|
+
# If you don't explicitly unlink the temporary file, the removal
|
89
|
+
# will be delayed until the object is finalized.
|
90
|
+
def close(unlink_now=false)
|
91
|
+
if unlink_now
|
92
|
+
close!
|
93
|
+
else
|
94
|
+
_close
|
95
|
+
end
|
119
96
|
end
|
120
|
-
|
121
|
-
|
122
|
-
|
97
|
+
|
98
|
+
# Closes and unlinks the file.
|
99
|
+
def close!
|
100
|
+
_close
|
101
|
+
@clean_proc.call
|
102
|
+
ObjectSpace.undefine_finalizer(self)
|
123
103
|
end
|
124
|
-
end
|
125
104
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
105
|
+
# Unlinks the file. On UNIX-like systems, it is often a good idea
|
106
|
+
# to unlink a temporary file immediately after creating and opening
|
107
|
+
# it, because it leaves other programs zero chance to access the
|
108
|
+
# file.
|
109
|
+
def unlink
|
110
|
+
# keep this order for thread safeness
|
111
|
+
::File.unlink(@tmpname) if ::File.exist?(@tmpname)
|
112
|
+
@@cleanlist.delete(@tmpname) if @@cleanlist
|
113
|
+
end
|
114
|
+
alias :delete :unlink
|
130
115
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
@tmpfile.flush
|
136
|
-
@tmpfile.stat.size
|
116
|
+
if RUBY_VERSION > '1.8.0'
|
117
|
+
def __setobj__(obj)
|
118
|
+
@_dc_obj = obj
|
119
|
+
end
|
137
120
|
else
|
138
|
-
|
121
|
+
def __setobj__(obj)
|
122
|
+
@obj = obj
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Returns the full path name of the temporary file.
|
127
|
+
def path
|
128
|
+
@tmpname
|
139
129
|
end
|
140
|
-
end
|
141
|
-
alias length size
|
142
130
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
131
|
+
# Returns the size of the temporary file. As a side effect, the IO
|
132
|
+
# buffer is flushed before determining the size.
|
133
|
+
def size
|
134
|
+
if @tmpfile
|
135
|
+
@tmpfile.flush
|
136
|
+
@tmpfile.stat.size
|
137
|
+
else
|
138
|
+
0
|
139
|
+
end
|
140
|
+
end
|
141
|
+
alias length size
|
149
142
|
|
150
|
-
|
143
|
+
class << self
|
144
|
+
def callback(data) # :nodoc:
|
145
|
+
pid = $$
|
146
|
+
lambda{
|
147
|
+
if pid == $$
|
148
|
+
path, tmpfile, cleanlist = *data
|
151
149
|
|
152
|
-
|
150
|
+
print "removing ", path, "..." if $DEBUG
|
153
151
|
|
154
|
-
|
155
|
-
File.unlink(path) if File.exist?(path)
|
156
|
-
cleanlist.delete(path) if cleanlist
|
152
|
+
tmpfile.close if tmpfile
|
157
153
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
end
|
154
|
+
# keep this order for thread safeness
|
155
|
+
::File.unlink(path) if ::File.exist?(path)
|
156
|
+
cleanlist.delete(path) if cleanlist
|
162
157
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
158
|
+
print "done\n" if $DEBUG
|
159
|
+
end
|
160
|
+
}
|
161
|
+
end
|
162
|
+
|
163
|
+
# If no block is given, this is a synonym for new().
|
164
|
+
#
|
165
|
+
# If a block is given, it will be passed tempfile as an argument,
|
166
|
+
# and the tempfile will automatically be closed when the block
|
167
|
+
# terminates. In this case, open() returns nil.
|
168
|
+
def open(*args)
|
169
|
+
tempfile = new(*args)
|
170
|
+
|
171
|
+
if block_given?
|
172
|
+
begin
|
173
|
+
yield(tempfile)
|
174
|
+
ensure
|
175
|
+
tempfile.close
|
176
|
+
end
|
177
|
+
|
178
|
+
nil
|
179
|
+
else
|
180
|
+
tempfile
|
181
|
+
end
|
181
182
|
end
|
182
183
|
end
|
183
184
|
end
|
184
|
-
end
|
185
185
|
|
186
186
|
end # module BugFix
|
187
187
|
if __FILE__ == $0
|
188
|
-
# $DEBUG = true
|
188
|
+
# $DEBUG = true
|
189
189
|
f = Tempfile.new("foo")
|
190
190
|
f.print("foo\n")
|
191
191
|
f.close
|
data/lib/zip/zip.rb
CHANGED
@@ -5,7 +5,7 @@ require 'tempfile'
|
|
5
5
|
require 'fileutils'
|
6
6
|
require 'stringio'
|
7
7
|
require 'zlib'
|
8
|
-
require 'zip/
|
8
|
+
require 'zip/dos_time'
|
9
9
|
require 'zip/ioextras'
|
10
10
|
require 'rbconfig'
|
11
11
|
|
@@ -34,7 +34,7 @@ if Tempfile.superclass == SimpleDelegator
|
|
34
34
|
end
|
35
35
|
|
36
36
|
module Zlib #:nodoc:all
|
37
|
-
if !
|
37
|
+
if !const_defined?(:MAX_WBITS)
|
38
38
|
MAX_WBITS = Zlib::Deflate.MAX_WBITS
|
39
39
|
end
|
40
40
|
end
|
data/lib/zip/zip_entry.rb
CHANGED
@@ -62,7 +62,7 @@ module Zip
|
|
62
62
|
|
63
63
|
# Returns the character encoding used for name and comment
|
64
64
|
def name_encoding
|
65
|
-
(@gp_flags & 0b100000000000) != 0 ? "
|
65
|
+
(@gp_flags & 0b100000000000) != 0 ? "UTF-8" : "CP437//"
|
66
66
|
end
|
67
67
|
|
68
68
|
# Returns the name in the encoding specified by enc
|
@@ -82,7 +82,7 @@ module Zip
|
|
82
82
|
def initialize(zipfile = "", name = "", comment = "", extra = "",
|
83
83
|
compressed_size = 0, crc = 0,
|
84
84
|
compression_method = ZipEntry::DEFLATED, size = 0,
|
85
|
-
time =
|
85
|
+
time = DOSTime.now)
|
86
86
|
super()
|
87
87
|
if name.start_with?("/")
|
88
88
|
raise ZipEntryNameError, "Illegal ZipEntry name '#{name}', name must not start with /"
|
@@ -140,7 +140,7 @@ module Zip
|
|
140
140
|
if @extra["UniversalTime"]
|
141
141
|
@extra["UniversalTime"].mtime
|
142
142
|
else
|
143
|
-
#
|
143
|
+
# Standard time field in central directory has local time
|
144
144
|
# under archive creator. Then, we can't get timezone.
|
145
145
|
@time
|
146
146
|
end
|
@@ -485,10 +485,9 @@ module Zip
|
|
485
485
|
elsif @filepath
|
486
486
|
case @ftype
|
487
487
|
when :file
|
488
|
-
return File.open(@filepath, "rb", &aProc)
|
489
|
-
|
488
|
+
return ::File.open(@filepath, "rb", &aProc)
|
490
489
|
when :symlink
|
491
|
-
linkpath = File::readlink(@filepath)
|
490
|
+
linkpath = ::File::readlink(@filepath)
|
492
491
|
stringio = StringIO.new(linkpath)
|
493
492
|
return yield(stringio) if block_given?
|
494
493
|
return stringio
|
@@ -558,23 +557,23 @@ module Zip
|
|
558
557
|
end
|
559
558
|
|
560
559
|
def get_raw_input_stream(&aProc)
|
561
|
-
File.open(@zipfile, "rb", &aProc)
|
560
|
+
::File.open(@zipfile, "rb", &aProc)
|
562
561
|
end
|
563
562
|
|
564
563
|
private
|
565
564
|
|
566
565
|
def set_time(binaryDosDate, binaryDosTime)
|
567
|
-
@time =
|
566
|
+
@time = DOSTime.parse_binary_dos_format(binaryDosDate, binaryDosTime)
|
568
567
|
rescue ArgumentError
|
569
568
|
puts "Invalid date/time in zip entry"
|
570
569
|
end
|
571
570
|
|
572
571
|
def write_file(destPath, continueOnExistsProc = proc { false })
|
573
|
-
if File.exists?(destPath) && ! yield(self, destPath)
|
572
|
+
if ::File.exists?(destPath) && ! yield(self, destPath)
|
574
573
|
raise ZipDestinationFileExistsError,
|
575
574
|
"Destination '#{destPath}' already exists"
|
576
575
|
end
|
577
|
-
File.open(destPath, "wb") do |os|
|
576
|
+
::File.open(destPath, "wb") do |os|
|
578
577
|
get_input_stream do |is|
|
579
578
|
set_extra_attributes_on_path(destPath)
|
580
579
|
|
@@ -587,9 +586,9 @@ module Zip
|
|
587
586
|
end
|
588
587
|
|
589
588
|
def create_directory(destPath)
|
590
|
-
if File.directory?
|
589
|
+
if ::File.directory?(destPath)
|
591
590
|
return
|
592
|
-
elsif File.exists?
|
591
|
+
elsif ::File.exists?(destPath)
|
593
592
|
if block_given? && yield(self, destPath)
|
594
593
|
FileUtils::rm_f destPath
|
595
594
|
else
|
@@ -606,7 +605,7 @@ module Zip
|
|
606
605
|
def create_symlink(destPath)
|
607
606
|
stat = nil
|
608
607
|
begin
|
609
|
-
stat = File::lstat(destPath)
|
608
|
+
stat = ::File::lstat(destPath)
|
610
609
|
rescue Errno::ENOENT
|
611
610
|
end
|
612
611
|
|
@@ -615,7 +614,7 @@ module Zip
|
|
615
614
|
|
616
615
|
if stat
|
617
616
|
if stat.symlink?
|
618
|
-
if File::readlink(destPath) == linkto
|
617
|
+
if ::File::readlink(destPath) == linkto
|
619
618
|
return
|
620
619
|
else
|
621
620
|
raise ZipDestinationFileExistsError,
|
@@ -629,11 +628,11 @@ module Zip
|
|
629
628
|
end
|
630
629
|
end
|
631
630
|
|
632
|
-
File::symlink(linkto, destPath)
|
631
|
+
::File::symlink(linkto, destPath)
|
633
632
|
end
|
634
633
|
end
|
635
634
|
end
|
636
635
|
|
637
636
|
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
638
637
|
# rubyzip is free software; you can redistribute it and/or
|
639
|
-
# modify it under the terms of the ruby license.
|
638
|
+
# modify it under the terms of the ruby license.
|
data/lib/zip/zip_entry_set.rb
CHANGED
@@ -20,6 +20,7 @@ module Zip
|
|
20
20
|
def size
|
21
21
|
@entrySet.size
|
22
22
|
end
|
23
|
+
|
23
24
|
alias :length :size
|
24
25
|
|
25
26
|
def delete(entry)
|
@@ -36,23 +37,22 @@ module Zip
|
|
36
37
|
|
37
38
|
# deep clone
|
38
39
|
def dup
|
39
|
-
|
40
|
+
ZipEntrySet.new(@entrySet.values.map { |e| e.dup })
|
40
41
|
end
|
41
42
|
|
42
|
-
def ==
|
43
|
+
def ==(other)
|
43
44
|
return false unless other.kind_of?(ZipEntrySet)
|
44
|
-
|
45
|
+
@entrySet == other.entrySet
|
45
46
|
end
|
46
47
|
|
47
48
|
def parent(entry)
|
48
49
|
@entrySet[entry.parent_as_string]
|
49
50
|
end
|
50
51
|
|
51
|
-
def glob(pattern, flags = File::FNM_PATHNAME
|
52
|
-
entries.select
|
53
|
-
|
54
|
-
|
55
|
-
}
|
52
|
+
def glob(pattern, flags = ::File::FNM_PATHNAME|::File::FNM_DOTMATCH)
|
53
|
+
entries.select do |entry|
|
54
|
+
::File.fnmatch(pattern, entry.name.chomp('/'), flags)
|
55
|
+
end
|
56
56
|
end
|
57
57
|
|
58
58
|
#TODO attr_accessor :auto_create_directories
|
data/lib/zip/zip_extra_field.rb
CHANGED
@@ -64,9 +64,9 @@ module Zip
|
|
64
64
|
size, content = initial_parse(binstr)
|
65
65
|
size or return
|
66
66
|
@flag, mtime, atime, ctime = content.unpack("CVVV")
|
67
|
-
mtime and @mtime ||=
|
68
|
-
atime and @atime ||=
|
69
|
-
ctime and @ctime ||=
|
67
|
+
mtime and @mtime ||= DOSTime.at(mtime)
|
68
|
+
atime and @atime ||= DOSTime.at(atime)
|
69
|
+
ctime and @ctime ||= DOSTime.at(ctime)
|
70
70
|
end
|
71
71
|
|
72
72
|
def ==(other)
|
data/lib/zip/zip_file.rb
CHANGED
@@ -61,8 +61,8 @@ module Zip
|
|
61
61
|
super()
|
62
62
|
@name = fileName
|
63
63
|
@comment = ""
|
64
|
-
if (File.exists?(fileName)) and !buffer
|
65
|
-
File.open(name, "rb") { |f| read_from_stream(f) }
|
64
|
+
if (::File.exists?(fileName)) and !buffer
|
65
|
+
::File.open(name, "rb") { |f| read_from_stream(f) }
|
66
66
|
elsif (create)
|
67
67
|
@entrySet = ZipEntrySet.new
|
68
68
|
else
|
@@ -113,10 +113,9 @@ module Zip
|
|
113
113
|
# local entry headers (which contain the same information as the
|
114
114
|
# central directory).
|
115
115
|
def ZipFile.foreach(aZipFileName, &block)
|
116
|
-
ZipFile.open(aZipFileName)
|
117
|
-
|zipFile|
|
116
|
+
ZipFile.open(aZipFileName) do |zipFile|
|
118
117
|
zipFile.each(&block)
|
119
|
-
|
118
|
+
end
|
120
119
|
end
|
121
120
|
|
122
121
|
# Returns an input stream to the specified entry. If a block is passed
|
@@ -178,7 +177,8 @@ module Zip
|
|
178
177
|
# the file system).
|
179
178
|
def replace(entry, srcPath)
|
180
179
|
check_file(srcPath)
|
181
|
-
|
180
|
+
remove(entry)
|
181
|
+
add(entry, srcPath)
|
182
182
|
end
|
183
183
|
|
184
184
|
# Extracts entry to file destPath.
|
@@ -251,8 +251,7 @@ module Zip
|
|
251
251
|
selectedEntry.restore_ownership = @restore_ownership
|
252
252
|
selectedEntry.restore_permissions = @restore_permissions
|
253
253
|
selectedEntry.restore_times = @restore_times
|
254
|
-
|
255
|
-
return selectedEntry
|
254
|
+
selectedEntry
|
256
255
|
end
|
257
256
|
|
258
257
|
# Creates a directory
|
@@ -260,21 +259,23 @@ module Zip
|
|
260
259
|
if find_entry(entryName)
|
261
260
|
raise Errno::EEXIST, "File exists - #{entryName}"
|
262
261
|
end
|
263
|
-
|
262
|
+
entryName = entryName.to_s
|
263
|
+
entryName << '/' unless entryName.end_with?('/')
|
264
|
+
@entrySet << ZipStreamableDirectory.new(@name, entryName, nil, permissionInt)
|
264
265
|
end
|
265
266
|
|
266
267
|
private
|
267
268
|
|
268
269
|
def is_directory(newEntry, srcPath)
|
269
|
-
srcPathIsDirectory = File.directory?(srcPath)
|
270
|
+
srcPathIsDirectory = ::File.directory?(srcPath)
|
270
271
|
if newEntry.is_directory && ! srcPathIsDirectory
|
271
272
|
raise ArgumentError,
|
272
273
|
"entry name '#{newEntry}' indicates directory entry, but "+
|
273
274
|
"'#{srcPath}' is not a directory"
|
274
|
-
|
275
|
+
elsif !newEntry.is_directory && srcPathIsDirectory
|
275
276
|
newEntry.name += "/"
|
276
277
|
end
|
277
|
-
|
278
|
+
newEntry.is_directory && srcPathIsDirectory
|
278
279
|
end
|
279
280
|
|
280
281
|
def check_entry_exists(entryName, continueOnExistsProc, procedureName)
|
@@ -284,13 +285,13 @@ module Zip
|
|
284
285
|
remove get_entry(entryName)
|
285
286
|
else
|
286
287
|
raise ZipEntryExistsError,
|
287
|
-
procedureName+" failed. Entry #{entryName} already exists"
|
288
|
+
procedureName + " failed. Entry #{entryName} already exists"
|
288
289
|
end
|
289
290
|
end
|
290
291
|
end
|
291
292
|
|
292
293
|
def check_file(path)
|
293
|
-
unless File.readable?
|
294
|
+
unless ::File.readable?(path)
|
294
295
|
raise Errno::ENOENT, path
|
295
296
|
end
|
296
297
|
end
|
@@ -300,12 +301,12 @@ module Zip
|
|
300
301
|
tmpFilename = tmpfile.path
|
301
302
|
tmpfile.close
|
302
303
|
if yield tmpFilename
|
303
|
-
File.rename(tmpFilename, name)
|
304
|
+
::File.rename(tmpFilename, name)
|
304
305
|
end
|
305
306
|
end
|
306
307
|
|
307
308
|
def get_tempfile
|
308
|
-
tempFile = Tempfile.new(File.basename(name), File.dirname(name))
|
309
|
+
tempFile = Tempfile.new(::File.basename(name), ::File.dirname(name))
|
309
310
|
tempFile.binmode
|
310
311
|
tempFile
|
311
312
|
end
|
data/lib/zip/zip_input_stream.rb
CHANGED
@@ -46,10 +46,14 @@ module Zip
|
|
46
46
|
# Opens the indicated zip file. An exception is thrown
|
47
47
|
# if the specified offset in the specified filename is
|
48
48
|
# not a local zip entry header.
|
49
|
-
def initialize(filename, offset = 0)
|
49
|
+
def initialize(filename, offset = 0, io = nil)
|
50
50
|
super()
|
51
|
-
|
52
|
-
|
51
|
+
if (io.nil?)
|
52
|
+
@archiveIO = ::File.open(filename, "rb")
|
53
|
+
@archiveIO.seek(offset, IO::SEEK_SET)
|
54
|
+
else
|
55
|
+
@archiveIO = io
|
56
|
+
end
|
53
57
|
@decompressor = NullDecompressor.instance
|
54
58
|
@currentEntry = nil
|
55
59
|
end
|
@@ -70,14 +74,21 @@ module Zip
|
|
70
74
|
zio.close if zio
|
71
75
|
end
|
72
76
|
|
77
|
+
def ZipInputStream.open_buffer(io)
|
78
|
+
return new('',0,io) unless block_given?
|
79
|
+
zio = new('',0,io)
|
80
|
+
yield zio
|
81
|
+
ensure
|
82
|
+
zio.close if zio
|
83
|
+
end
|
84
|
+
|
73
85
|
# Returns a ZipEntry object. It is necessary to call this
|
74
86
|
# method on a newly created ZipInputStream before reading from
|
75
87
|
# the first entry in the archive. Returns nil when there are
|
76
88
|
# no more entries.
|
77
89
|
|
78
90
|
def get_next_entry
|
79
|
-
@archiveIO.seek(@currentEntry.next_header_offset,
|
80
|
-
IO::SEEK_SET) if @currentEntry
|
91
|
+
@archiveIO.seek(@currentEntry.next_header_offset, IO::SEEK_SET) if @currentEntry
|
81
92
|
open_entry
|
82
93
|
end
|
83
94
|
|
@@ -104,16 +115,15 @@ module Zip
|
|
104
115
|
|
105
116
|
def open_entry
|
106
117
|
@currentEntry = ZipEntry.read_local_entry(@archiveIO)
|
107
|
-
if
|
108
|
-
|
118
|
+
if @currentEntry.nil?
|
119
|
+
@decompressor = NullDecompressor.instance
|
109
120
|
elsif @currentEntry.compression_method == ZipEntry::STORED
|
110
|
-
|
111
|
-
@currentEntry.size)
|
121
|
+
@decompressor = PassThruDecompressor.new(@archiveIO, @currentEntry.size)
|
112
122
|
elsif @currentEntry.compression_method == ZipEntry::DEFLATED
|
113
|
-
|
123
|
+
@decompressor = Inflater.new(@archiveIO)
|
114
124
|
else
|
115
|
-
|
116
|
-
|
125
|
+
raise ZipCompressionMethodError,
|
126
|
+
"Unsupported compression method #{@currentEntry.compression_method}"
|
117
127
|
end
|
118
128
|
flush
|
119
129
|
return @currentEntry
|
@@ -131,4 +141,4 @@ end
|
|
131
141
|
|
132
142
|
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
133
143
|
# rubyzip is free software; you can redistribute it and/or
|
134
|
-
# modify it under the terms of the ruby license.
|
144
|
+
# modify it under the terms of the ruby license.
|
@@ -30,7 +30,7 @@ module Zip
|
|
30
30
|
if stream
|
31
31
|
@outputStream = StringIO.new
|
32
32
|
else
|
33
|
-
@outputStream = File.new(@fileName, "wb")
|
33
|
+
@outputStream = ::File.new(@fileName, "wb")
|
34
34
|
end
|
35
35
|
@entrySet = ZipEntrySet.new
|
36
36
|
@compressor = NullCompressor.instance
|
@@ -101,11 +101,10 @@ module Zip
|
|
101
101
|
src_pos = entry.local_entry_offset
|
102
102
|
entry.write_local_entry(@outputStream)
|
103
103
|
@compressor = NullCompressor.instance
|
104
|
-
entry.get_raw_input_stream
|
105
|
-
|is|
|
104
|
+
entry.get_raw_input_stream do |is|
|
106
105
|
is.seek(src_pos, IO::SEEK_SET)
|
107
106
|
IOExtras.copy_stream_n(@outputStream, is, entry.compressed_size)
|
108
|
-
|
107
|
+
end
|
109
108
|
@compressor = NullCompressor.instance
|
110
109
|
@currentEntry = nil
|
111
110
|
end
|
@@ -2,7 +2,7 @@ module Zip
|
|
2
2
|
class ZipStreamableStream < DelegateClass(ZipEntry) #nodoc:all
|
3
3
|
def initialize(entry)
|
4
4
|
super(entry)
|
5
|
-
@tempFile = Tempfile.new(File.basename(name), File.dirname(zipfile))
|
5
|
+
@tempFile = Tempfile.new(::File.basename(name), ::File.dirname(zipfile))
|
6
6
|
@tempFile.binmode
|
7
7
|
end
|
8
8
|
|
data/lib/zip/zipfilesystem.rb
CHANGED
@@ -70,29 +70,34 @@ module Zip
|
|
70
70
|
# protected :dir
|
71
71
|
|
72
72
|
class ZipFsStat
|
73
|
+
|
74
|
+
class << self
|
75
|
+
|
76
|
+
def delegate_to_fs_file(*methods)
|
77
|
+
methods.each do |method|
|
78
|
+
self.class_eval <<-end_eval, __FILE__, __LINE__ + 1
|
79
|
+
def #{method} # def file?
|
80
|
+
@zipFsFile.#{method}(@entryName) # @zipFsFile.file?(@entryName)
|
81
|
+
end # end
|
82
|
+
end_eval
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
73
88
|
def initialize(zipFsFile, entryName)
|
74
89
|
@zipFsFile = zipFsFile
|
75
90
|
@entryName = entryName
|
76
91
|
end
|
77
92
|
|
78
|
-
def forward_invoke(msg)
|
79
|
-
@zipFsFile.send(msg, @entryName)
|
80
|
-
end
|
81
|
-
|
82
93
|
def kind_of?(t)
|
83
94
|
super || t == ::File::Stat
|
84
95
|
end
|
85
96
|
|
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
|
97
|
+
delegate_to_fs_file :file?, :directory?, :pipe?, :chardev?, :symlink?,
|
98
|
+
:socket?, :blockdev?, :readable?, :readable_real?, :writable?, :ctime,
|
99
|
+
:writable_real?, :executable?, :executable_real?, :sticky?, :owned?,
|
100
|
+
:grpowned?, :setuid?, :setgid?, :zero?, :size, :size?, :mtime, :atime
|
96
101
|
|
97
102
|
def blocks; nil; end
|
98
103
|
|
@@ -466,7 +471,8 @@ module Zip
|
|
466
471
|
unless @file.stat(aDirectoryName).directory?
|
467
472
|
raise Errno::ENOTDIR, aDirectoryName
|
468
473
|
end
|
469
|
-
path = @file.expand_path(aDirectoryName)
|
474
|
+
path = @file.expand_path(aDirectoryName)
|
475
|
+
path << '/' unless path.end_with?('/')
|
470
476
|
path = Regexp.escape(path)
|
471
477
|
subDirEntriesRegex = Regexp.new("^#{path}([^/]+)$")
|
472
478
|
@mappedZip.each {
|
@@ -588,7 +594,7 @@ module Zip
|
|
588
594
|
end
|
589
595
|
|
590
596
|
def expand_path(aPath)
|
591
|
-
expanded = aPath.start_with?("/") ? aPath : @pwd
|
597
|
+
expanded = aPath.start_with?("/") ? aPath : ::File.join(@pwd, aPath)
|
592
598
|
expanded.gsub!(/\/\.(\/|$)/, "")
|
593
599
|
expanded.gsub!(/[^\/]+\/\.\.(\/|$)/, "")
|
594
600
|
expanded.empty? ? "/" : expanded
|
@@ -597,7 +603,7 @@ module Zip
|
|
597
603
|
private
|
598
604
|
|
599
605
|
def expand_to_entry(aPath)
|
600
|
-
expand_path(aPath)
|
606
|
+
expand_path(aPath)[1..-1]
|
601
607
|
end
|
602
608
|
end
|
603
609
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubyzip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.6.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-02-08 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description:
|
15
15
|
email: alan@aussiegeek.net
|
@@ -28,6 +28,7 @@ files:
|
|
28
28
|
- lib/zip/constants.rb
|
29
29
|
- lib/zip/decompressor.rb
|
30
30
|
- lib/zip/deflater.rb
|
31
|
+
- lib/zip/dos_time.rb
|
31
32
|
- lib/zip/inflater.rb
|
32
33
|
- lib/zip/ioextras.rb
|
33
34
|
- lib/zip/null_compressor.rb
|
@@ -35,7 +36,6 @@ files:
|
|
35
36
|
- lib/zip/null_input_stream.rb
|
36
37
|
- lib/zip/pass_thru_compressor.rb
|
37
38
|
- lib/zip/pass_thru_decompressor.rb
|
38
|
-
- lib/zip/stdrubyext.rb
|
39
39
|
- lib/zip/tempfile_bugfixed.rb
|
40
40
|
- lib/zip/zip.rb
|
41
41
|
- lib/zip/zip_central_directory.rb
|
@@ -77,3 +77,4 @@ signing_key:
|
|
77
77
|
specification_version: 3
|
78
78
|
summary: rubyzip is a ruby module for reading and writing zip files
|
79
79
|
test_files: []
|
80
|
+
has_rdoc:
|