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
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'zip
|
1
|
+
require 'zip'
|
2
2
|
|
3
3
|
module Zip
|
4
4
|
|
@@ -14,9 +14,9 @@ module Zip
|
|
14
14
|
# <code>first.txt</code>, a directory entry named <code>mydir</code>
|
15
15
|
# and finally another normal entry named <code>second.txt</code>
|
16
16
|
#
|
17
|
-
# require 'zip/
|
17
|
+
# require 'zip/filesystem'
|
18
18
|
#
|
19
|
-
# Zip::
|
19
|
+
# Zip::File.open("my.zip", Zip::ZipFile::CREATE) {
|
20
20
|
# |zipfile|
|
21
21
|
# zipfile.file.open("first.txt", "w") { |f| f.puts "Hello world" }
|
22
22
|
# zipfile.dir.mkdir("mydir")
|
@@ -27,14 +27,14 @@ module Zip
|
|
27
27
|
# example writes the contents of <code>first.txt</code> from zip archive
|
28
28
|
# <code>my.zip</code> to standard out.
|
29
29
|
#
|
30
|
-
# require 'zip/
|
30
|
+
# require 'zip/filesystem'
|
31
31
|
#
|
32
|
-
# Zip::
|
32
|
+
# Zip::File.open("my.zip") {
|
33
33
|
# |zipfile|
|
34
34
|
# puts zipfile.file.read("first.txt")
|
35
35
|
# }
|
36
36
|
|
37
|
-
module
|
37
|
+
module FileSystem
|
38
38
|
|
39
39
|
def initialize # :nodoc:
|
40
40
|
mappedZip = ZipFileNameMapper.new(self)
|
@@ -151,7 +151,7 @@ module Zip
|
|
151
151
|
def mode
|
152
152
|
e = get_entry
|
153
153
|
if e.fstype == 3
|
154
|
-
e.
|
154
|
+
e.external_file_attributes >> 16
|
155
155
|
else
|
156
156
|
33206 # 33206 is equivalent to -rw-rw-rw-
|
157
157
|
end
|
@@ -173,7 +173,7 @@ module Zip
|
|
173
173
|
def unix_mode_cmp(fileName, mode)
|
174
174
|
begin
|
175
175
|
e = get_entry(fileName)
|
176
|
-
e.fstype == 3 && ((e.
|
176
|
+
e.fstype == 3 && ((e.external_file_attributes >> 16) & mode ) != 0
|
177
177
|
rescue Errno::ENOENT
|
178
178
|
false
|
179
179
|
end
|
@@ -272,7 +272,7 @@ module Zip
|
|
272
272
|
e = get_entry(fileName)
|
273
273
|
e.fstype = 3 # force convertion filesystem type to unix
|
274
274
|
e.unix_perms = modeInt
|
275
|
-
e.
|
275
|
+
e.external_file_attributes = modeInt << 16
|
276
276
|
e.dirty = true
|
277
277
|
}
|
278
278
|
filenames.size
|
@@ -392,7 +392,7 @@ module Zip
|
|
392
392
|
end
|
393
393
|
|
394
394
|
def popen(*args, &aProc)
|
395
|
-
File.popen(*args, &aProc)
|
395
|
+
::File.popen(*args, &aProc)
|
396
396
|
end
|
397
397
|
|
398
398
|
def foreach(fileName, aSep = $/, &aProc)
|
@@ -612,8 +612,8 @@ module Zip
|
|
612
612
|
end
|
613
613
|
end
|
614
614
|
|
615
|
-
class
|
616
|
-
include
|
615
|
+
class File
|
616
|
+
include FileSystem
|
617
617
|
end
|
618
618
|
end
|
619
619
|
|
data/lib/zip/inflater.rb
CHANGED
@@ -1,36 +1,37 @@
|
|
1
1
|
module Zip
|
2
|
-
class Inflater < Decompressor
|
3
|
-
def initialize(
|
2
|
+
class Inflater < Decompressor #:nodoc:all
|
3
|
+
def initialize(input_stream)
|
4
4
|
super
|
5
|
-
@
|
6
|
-
@
|
7
|
-
@
|
5
|
+
@zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
6
|
+
@output_buffer = ''
|
7
|
+
@has_returned_empty_string = false
|
8
8
|
end
|
9
9
|
|
10
|
-
def sysread(
|
11
|
-
readEverything =
|
12
|
-
while (readEverything || @
|
10
|
+
def sysread(number_of_bytes = nil, buf = nil)
|
11
|
+
readEverything = number_of_bytes.nil?
|
12
|
+
while (readEverything || @output_buffer.bytesize < number_of_bytes)
|
13
13
|
break if internal_input_finished?
|
14
|
-
@
|
14
|
+
@output_buffer << internal_produce_input(buf)
|
15
15
|
end
|
16
|
-
return value_when_finished if @
|
17
|
-
|
18
|
-
|
16
|
+
return value_when_finished if @output_buffer.bytesize == 0 && input_finished?
|
17
|
+
end_index = number_of_bytes.nil? ? @output_buffer.bytesize : number_of_bytes
|
18
|
+
@output_buffer.slice!(0...end_index)
|
19
19
|
end
|
20
20
|
|
21
21
|
def produce_input
|
22
|
-
if (@
|
23
|
-
|
22
|
+
if (@output_buffer.empty?)
|
23
|
+
internal_produce_input
|
24
24
|
else
|
25
|
-
|
25
|
+
@output_buffer.slice!(0...(@output_buffer.length))
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
# to be used with produce_input, not read (as read may still have more data cached)
|
30
30
|
# is data cached anywhere other than @outputBuffer? the comment above may be wrong
|
31
31
|
def input_finished?
|
32
|
-
@
|
32
|
+
@output_buffer.empty? && internal_input_finished?
|
33
33
|
end
|
34
|
+
|
34
35
|
alias :eof :input_finished?
|
35
36
|
alias :eof? :input_finished?
|
36
37
|
|
@@ -39,23 +40,22 @@ module Zip
|
|
39
40
|
def internal_produce_input(buf = nil)
|
40
41
|
retried = 0
|
41
42
|
begin
|
42
|
-
@
|
43
|
+
@zlib_inflater.inflate(@input_stream.read(Decompressor::CHUNK_SIZE, buf))
|
43
44
|
rescue Zlib::BufError
|
44
|
-
raise if
|
45
|
+
raise if retried >= 5 # how many times should we retry?
|
45
46
|
retried += 1
|
46
47
|
retry
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
51
|
def internal_input_finished?
|
51
|
-
@
|
52
|
+
@zlib_inflater.finished?
|
52
53
|
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
return ""
|
55
|
+
def value_when_finished # mimic behaviour of ruby File object.
|
56
|
+
return if @has_returned_empty_string
|
57
|
+
@has_returned_empty_string = true
|
58
|
+
''
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
@@ -40,8 +40,8 @@ module Zip
|
|
40
40
|
# java.util.zip.ZipInputStream is the original inspiration for this
|
41
41
|
# class.
|
42
42
|
|
43
|
-
class
|
44
|
-
include IOExtras::AbstractInputStream
|
43
|
+
class InputStream
|
44
|
+
include ::Zip::IOExtras::AbstractInputStream
|
45
45
|
|
46
46
|
# Opens the indicated zip file. An exception is thrown
|
47
47
|
# if the specified offset in the specified filename is
|
@@ -65,7 +65,7 @@ module Zip
|
|
65
65
|
# Same as #initialize but if a block is passed the opened
|
66
66
|
# stream is passed to the block and closed when the block
|
67
67
|
# returns.
|
68
|
-
def
|
68
|
+
def InputStream.open(filename)
|
69
69
|
return new(filename) unless block_given?
|
70
70
|
|
71
71
|
zio = new(filename)
|
@@ -74,7 +74,7 @@ module Zip
|
|
74
74
|
zio.close if zio
|
75
75
|
end
|
76
76
|
|
77
|
-
def
|
77
|
+
def InputStream.open_buffer(io)
|
78
78
|
return new('',0,io) unless block_given?
|
79
79
|
zio = new('',0,io)
|
80
80
|
yield zio
|
@@ -96,7 +96,8 @@ module Zip
|
|
96
96
|
def rewind
|
97
97
|
return if @currentEntry.nil?
|
98
98
|
@lineno = 0
|
99
|
-
@
|
99
|
+
@pos = 0
|
100
|
+
@archiveIO.seek(@currentEntry.local_header_offset,
|
100
101
|
IO::SEEK_SET)
|
101
102
|
open_entry
|
102
103
|
end
|
@@ -107,19 +108,19 @@ module Zip
|
|
107
108
|
end
|
108
109
|
|
109
110
|
def eof
|
110
|
-
@
|
111
|
+
@output_buffer.empty? && @decompressor.eof
|
111
112
|
end
|
112
113
|
alias :eof? :eof
|
113
114
|
|
114
115
|
protected
|
115
116
|
|
116
117
|
def open_entry
|
117
|
-
@currentEntry =
|
118
|
+
@currentEntry = Entry.read_local_entry(@archiveIO)
|
118
119
|
if @currentEntry.nil?
|
119
120
|
@decompressor = NullDecompressor.instance
|
120
|
-
elsif @currentEntry.compression_method ==
|
121
|
+
elsif @currentEntry.compression_method == Entry::STORED
|
121
122
|
@decompressor = PassThruDecompressor.new(@archiveIO, @currentEntry.size)
|
122
|
-
elsif @currentEntry.compression_method ==
|
123
|
+
elsif @currentEntry.compression_method == Entry::DEFLATED
|
123
124
|
@decompressor = Inflater.new(@archiveIO)
|
124
125
|
else
|
125
126
|
raise ZipCompressionMethodError,
|
@@ -141,4 +142,4 @@ end
|
|
141
142
|
|
142
143
|
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
143
144
|
# rubyzip is free software; you can redistribute it and/or
|
144
|
-
# modify it under the terms of the ruby license.
|
145
|
+
# modify it under the terms of the ruby license.
|
data/lib/zip/ioextras.rb
CHANGED
@@ -1,163 +1,185 @@
|
|
1
|
-
module
|
1
|
+
module Zip
|
2
|
+
module IOExtras #:nodoc:
|
2
3
|
|
3
|
-
|
4
|
+
CHUNK_SIZE = 131072
|
4
5
|
|
5
|
-
|
6
|
+
RANGE_ALL = 0..-1
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
def self.copy_stream(ostream, istream)
|
9
|
+
s = ''
|
10
|
+
ostream.write(istream.read(CHUNK_SIZE, s)) until istream.eof?
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
def self.copy_stream_n(ostream, istream, nbytes)
|
14
|
+
s = ''
|
15
|
+
toread = nbytes
|
16
|
+
while (toread > 0 && !istream.eof?)
|
17
|
+
tr = toread > CHUNK_SIZE ? CHUNK_SIZE : toread
|
18
|
+
ostream.write(istream.read(tr, s))
|
19
|
+
toread -= tr
|
20
|
+
end
|
21
|
+
end
|
21
22
|
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
# Implements many of the convenience methods of IO
|
31
|
-
# such as gets, getc, readline and readlines
|
32
|
-
# depends on: input_finished?, produce_input and read
|
33
|
-
module AbstractInputStream
|
34
|
-
include Enumerable
|
35
|
-
include FakeIO
|
36
|
-
|
37
|
-
def initialize
|
38
|
-
super
|
39
|
-
@lineno = 0
|
40
|
-
@outputBuffer = ""
|
24
|
+
# Implements kind_of? in order to pretend to be an IO object
|
25
|
+
module FakeIO
|
26
|
+
def kind_of?(object)
|
27
|
+
object == IO || super
|
28
|
+
end
|
41
29
|
end
|
42
30
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
31
|
+
# Implements many of the convenience methods of IO
|
32
|
+
# such as gets, getc, readline and readlines
|
33
|
+
# depends on: input_finished?, produce_input and read
|
34
|
+
module AbstractInputStream
|
35
|
+
include Enumerable
|
36
|
+
include FakeIO
|
37
|
+
|
38
|
+
def initialize
|
39
|
+
super
|
40
|
+
@lineno = 0
|
41
|
+
@pos = 0
|
42
|
+
@output_buffer = ""
|
43
|
+
end
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
attr_accessor :lineno
|
46
|
+
attr_reader :pos
|
47
|
+
|
48
|
+
def read(numberOfBytes = nil, buf = nil)
|
49
|
+
tbuf = nil
|
50
|
+
|
51
|
+
if @output_buffer.bytesize > 0
|
52
|
+
if numberOfBytes <= @output_buffer.bytesize
|
53
|
+
tbuf = @output_buffer.slice!(0, numberOfBytes)
|
54
|
+
else
|
55
|
+
numberOfBytes -= @output_buffer.bytesize if (numberOfBytes)
|
56
|
+
rbuf = sysread(numberOfBytes, buf)
|
57
|
+
tbuf = @output_buffer
|
58
|
+
tbuf << rbuf if (rbuf)
|
59
|
+
@output_buffer = ""
|
60
|
+
end
|
51
61
|
else
|
52
|
-
|
53
|
-
rbuf = sysread(numberOfBytes, buf)
|
54
|
-
tbuf = @outputBuffer
|
55
|
-
tbuf << rbuf if (rbuf)
|
56
|
-
@outputBuffer = ""
|
62
|
+
tbuf = sysread(numberOfBytes, buf)
|
57
63
|
end
|
58
|
-
else
|
59
|
-
tbuf = sysread(numberOfBytes, buf)
|
60
|
-
end
|
61
64
|
|
62
|
-
|
65
|
+
@pos += tbuf.length
|
63
66
|
|
64
|
-
|
65
|
-
buf.replace(tbuf)
|
66
|
-
else
|
67
|
-
buf = tbuf
|
68
|
-
end
|
67
|
+
return nil unless (tbuf)
|
69
68
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
each_line(aSepString) { |line| retVal << line }
|
76
|
-
retVal
|
77
|
-
end
|
69
|
+
if buf
|
70
|
+
buf.replace(tbuf)
|
71
|
+
else
|
72
|
+
buf = tbuf
|
73
|
+
end
|
78
74
|
|
79
|
-
|
80
|
-
|
81
|
-
return read if aSepString.nil?
|
82
|
-
aSepString = "#{$/}#{$/}" if aSepString.empty?
|
75
|
+
buf
|
76
|
+
end
|
83
77
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
return @outputBuffer.empty? ? nil : flush
|
89
|
-
end
|
90
|
-
@outputBuffer << produce_input
|
78
|
+
def readlines(aSepString = $/)
|
79
|
+
retVal = []
|
80
|
+
each_line(aSepString) { |line| retVal << line }
|
81
|
+
retVal
|
91
82
|
end
|
92
|
-
sepIndex = matchIndex + aSepString.bytesize
|
93
|
-
return @outputBuffer.slice!(0...sepIndex)
|
94
|
-
end
|
95
83
|
|
96
|
-
|
97
|
-
|
98
|
-
@outputBuffer=""
|
99
|
-
return retVal
|
100
|
-
end
|
84
|
+
def gets(aSepString = $/, numberOfBytes = nil)
|
85
|
+
@lineno = @lineno.next
|
101
86
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
87
|
+
if numberOfBytes.respond_to?(:to_int)
|
88
|
+
numberOfBytes = numberOfBytes.to_int
|
89
|
+
aSepString = aSepString.to_str if aSepString
|
90
|
+
elsif aSepString.respond_to?(:to_int)
|
91
|
+
numberOfBytes = aSepString.to_int
|
92
|
+
aSepString = $/
|
93
|
+
else
|
94
|
+
numberOfBytes = nil
|
95
|
+
aSepString = aSepString.to_str if aSepString
|
96
|
+
end
|
107
97
|
|
108
|
-
|
109
|
-
|
110
|
-
|
98
|
+
return read(numberOfBytes) if aSepString.nil?
|
99
|
+
aSepString = "#{$/}#{$/}" if aSepString.empty?
|
100
|
+
|
101
|
+
bufferIndex = 0
|
102
|
+
overLimit = (numberOfBytes && @output_buffer.bytesize >= numberOfBytes)
|
103
|
+
while ((matchIndex = @output_buffer.index(aSepString, bufferIndex)) == nil && !overLimit)
|
104
|
+
bufferIndex = [bufferIndex, @output_buffer.bytesize - aSepString.bytesize].max
|
105
|
+
if input_finished?
|
106
|
+
return @output_buffer.empty? ? nil : flush
|
107
|
+
end
|
108
|
+
@output_buffer << produce_input
|
109
|
+
overLimit = (numberOfBytes && @output_buffer.bytesize >= numberOfBytes)
|
110
|
+
end
|
111
|
+
sepIndex = [matchIndex + aSepString.bytesize, numberOfBytes || @output_buffer.bytesize].min
|
112
|
+
@pos += sepIndex
|
113
|
+
return @output_buffer.slice!(0...sepIndex)
|
111
114
|
end
|
112
|
-
rescue EOFError
|
113
|
-
end
|
114
115
|
|
115
|
-
|
116
|
-
|
116
|
+
def flush
|
117
|
+
retVal = @output_buffer
|
118
|
+
@output_buffer=""
|
119
|
+
return retVal
|
120
|
+
end
|
117
121
|
|
122
|
+
def readline(aSepString = $/)
|
123
|
+
retVal = gets(aSepString)
|
124
|
+
raise EOFError if retVal == nil
|
125
|
+
retVal
|
126
|
+
end
|
118
127
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
128
|
+
def each_line(aSepString = $/)
|
129
|
+
while true
|
130
|
+
yield readline(aSepString)
|
131
|
+
end
|
132
|
+
rescue EOFError
|
133
|
+
end
|
123
134
|
|
124
|
-
|
125
|
-
self << data
|
126
|
-
data.to_s.bytesize
|
135
|
+
alias_method :each, :each_line
|
127
136
|
end
|
128
137
|
|
129
138
|
|
130
|
-
|
131
|
-
|
132
|
-
|
139
|
+
# Implements many of the output convenience methods of IO.
|
140
|
+
# relies on <<
|
141
|
+
module AbstractOutputStream
|
142
|
+
include FakeIO
|
143
|
+
|
144
|
+
def write(data)
|
145
|
+
self << data
|
146
|
+
data.to_s.bytesize
|
147
|
+
end
|
133
148
|
|
134
|
-
def printf(aFormatString, *params)
|
135
|
-
self << sprintf(aFormatString, *params)
|
136
|
-
end
|
137
149
|
|
138
|
-
|
139
|
-
|
140
|
-
when Fixnum then anObject.chr
|
141
|
-
when String then anObject
|
142
|
-
else raise TypeError, "putc: Only Fixnum and String supported"
|
150
|
+
def print(*params)
|
151
|
+
self << params.join($,) << $\.to_s
|
143
152
|
end
|
144
|
-
anObject
|
145
|
-
end
|
146
153
|
|
147
|
-
|
148
|
-
|
149
|
-
params.flatten.each do |element|
|
150
|
-
val = element.to_s
|
151
|
-
self << val
|
152
|
-
self << "\n" unless val[-1,1] == "\n"
|
154
|
+
def printf(aFormatString, *params)
|
155
|
+
self << sprintf(aFormatString, *params)
|
153
156
|
end
|
154
|
-
end
|
155
157
|
|
156
|
-
|
158
|
+
def putc(anObject)
|
159
|
+
self << case anObject
|
160
|
+
when Fixnum then
|
161
|
+
anObject.chr
|
162
|
+
when String then
|
163
|
+
anObject
|
164
|
+
else
|
165
|
+
raise TypeError, "putc: Only Fixnum and String supported"
|
166
|
+
end
|
167
|
+
anObject
|
168
|
+
end
|
157
169
|
|
158
|
-
|
170
|
+
def puts(*params)
|
171
|
+
params << "\n" if params.empty?
|
172
|
+
params.flatten.each do |element|
|
173
|
+
val = element.to_s
|
174
|
+
self << val
|
175
|
+
self << "\n" unless val[-1, 1] == "\n"
|
176
|
+
end
|
177
|
+
end
|
159
178
|
|
179
|
+
end
|
160
180
|
|
181
|
+
end # IOExtras namespace module
|
182
|
+
end
|
161
183
|
|
162
184
|
# Copyright (C) 2002-2004 Thomas Sondergaard
|
163
185
|
# rubyzip is free software; you can redistribute it and/or
|