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/null_compressor.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
module Zip
|
2
|
-
class NullDecompressor
|
2
|
+
class NullDecompressor #:nodoc:all
|
3
3
|
include Singleton
|
4
|
+
|
4
5
|
def sysread(numberOfBytes = nil, buf = nil)
|
5
6
|
nil
|
6
7
|
end
|
7
|
-
|
8
|
+
|
8
9
|
def produce_input
|
9
10
|
nil
|
10
11
|
end
|
11
|
-
|
12
|
+
|
12
13
|
def input_finished?
|
13
14
|
true
|
14
15
|
end
|
@@ -16,6 +17,7 @@ module Zip
|
|
16
17
|
def eof
|
17
18
|
true
|
18
19
|
end
|
20
|
+
|
19
21
|
alias :eof? :eof
|
20
22
|
end
|
21
23
|
end
|
@@ -17,8 +17,8 @@ module Zip
|
|
17
17
|
# java.util.zip.ZipOutputStream is the original inspiration for this
|
18
18
|
# class.
|
19
19
|
|
20
|
-
class
|
21
|
-
include IOExtras::AbstractOutputStream
|
20
|
+
class OutputStream
|
21
|
+
include ::Zip::IOExtras::AbstractOutputStream
|
22
22
|
|
23
23
|
attr_accessor :comment
|
24
24
|
|
@@ -28,12 +28,12 @@ module Zip
|
|
28
28
|
super()
|
29
29
|
@fileName = fileName
|
30
30
|
if stream
|
31
|
-
@
|
31
|
+
@output_stream = ::StringIO.new
|
32
32
|
else
|
33
|
-
@
|
33
|
+
@output_stream = ::File.new(@fileName, "wb")
|
34
34
|
end
|
35
|
-
@
|
36
|
-
@compressor = NullCompressor.instance
|
35
|
+
@entry_set = ::Zip::EntrySet.new
|
36
|
+
@compressor = ::Zip::NullCompressor.instance
|
37
37
|
@closed = false
|
38
38
|
@currentEntry = nil
|
39
39
|
@comment = nil
|
@@ -42,19 +42,21 @@ module Zip
|
|
42
42
|
# Same as #initialize but if a block is passed the opened
|
43
43
|
# stream is passed to the block and closed when the block
|
44
44
|
# returns.
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
class << self
|
46
|
+
def open(fileName)
|
47
|
+
return new(fileName) unless block_given?
|
48
|
+
zos = new(fileName)
|
49
|
+
yield zos
|
50
|
+
ensure
|
51
|
+
zos.close if zos
|
52
|
+
end
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
# Same as #open but writes to a filestream instead
|
55
|
+
def write_buffer
|
56
|
+
zos = new('', true)
|
57
|
+
yield zos
|
58
|
+
return zos.close_buffer
|
59
|
+
end
|
58
60
|
end
|
59
61
|
|
60
62
|
# Closes the stream and writes the central directory to the zip file
|
@@ -63,32 +65,32 @@ module Zip
|
|
63
65
|
finalize_current_entry
|
64
66
|
update_local_headers
|
65
67
|
write_central_directory
|
66
|
-
@
|
68
|
+
@output_stream.close
|
67
69
|
@closed = true
|
68
70
|
end
|
69
71
|
|
70
72
|
# Closes the stream and writes the central directory to the zip file
|
71
73
|
def close_buffer
|
72
|
-
return @
|
74
|
+
return @output_stream if @closed
|
73
75
|
finalize_current_entry
|
74
76
|
update_local_headers
|
75
77
|
write_central_directory
|
76
78
|
@closed = true
|
77
|
-
@
|
79
|
+
@output_stream
|
78
80
|
end
|
79
81
|
|
80
82
|
# Closes the current entry and opens a new for writing.
|
81
83
|
# +entry+ can be a ZipEntry object or a string.
|
82
|
-
def put_next_entry(entryname, comment = nil, extra = nil, compression_method =
|
84
|
+
def put_next_entry(entryname, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zlib::DEFAULT_COMPRESSION)
|
83
85
|
raise ZipError, "zip stream is closed" if @closed
|
84
|
-
if entryname.kind_of?(
|
86
|
+
if entryname.kind_of?(Entry)
|
85
87
|
new_entry = entryname
|
86
88
|
else
|
87
|
-
new_entry =
|
89
|
+
new_entry = Entry.new(@fileName, entryname.to_s)
|
88
90
|
end
|
89
91
|
new_entry.comment = comment if !comment.nil?
|
90
92
|
if (!extra.nil?)
|
91
|
-
new_entry.extra =
|
93
|
+
new_entry.extra = ExtraField === extra ? extra : ExtraField.new(extra.to_s)
|
92
94
|
end
|
93
95
|
new_entry.compression_method = compression_method if !compression_method.nil?
|
94
96
|
init_next_entry(new_entry, level)
|
@@ -98,15 +100,15 @@ module Zip
|
|
98
100
|
def copy_raw_entry(entry)
|
99
101
|
entry = entry.dup
|
100
102
|
raise ZipError, "zip stream is closed" if @closed
|
101
|
-
raise ZipError, "entry is not a ZipEntry" if !entry.kind_of?(
|
103
|
+
raise ZipError, "entry is not a ZipEntry" if !entry.kind_of?(Entry)
|
102
104
|
finalize_current_entry
|
103
|
-
@
|
105
|
+
@entry_set << entry
|
104
106
|
src_pos = entry.local_entry_offset
|
105
|
-
entry.write_local_entry(@
|
107
|
+
entry.write_local_entry(@output_stream)
|
106
108
|
@compressor = NullCompressor.instance
|
107
109
|
entry.get_raw_input_stream do |is|
|
108
110
|
is.seek(src_pos, IO::SEEK_SET)
|
109
|
-
IOExtras.copy_stream_n(@
|
111
|
+
IOExtras.copy_stream_n(@output_stream, is, entry.compressed_size)
|
110
112
|
end
|
111
113
|
@compressor = NullCompressor.instance
|
112
114
|
@currentEntry = nil
|
@@ -117,7 +119,7 @@ module Zip
|
|
117
119
|
def finalize_current_entry
|
118
120
|
return unless @currentEntry
|
119
121
|
finish
|
120
|
-
@currentEntry.compressed_size = @
|
122
|
+
@currentEntry.compressed_size = @output_stream.tell - @currentEntry.local_header_offset - @currentEntry.calculate_local_header_size
|
121
123
|
@currentEntry.size = @compressor.size
|
122
124
|
@currentEntry.crc = @compressor.crc
|
123
125
|
@currentEntry = nil
|
@@ -126,32 +128,32 @@ module Zip
|
|
126
128
|
|
127
129
|
def init_next_entry(entry, level = Zlib::DEFAULT_COMPRESSION)
|
128
130
|
finalize_current_entry
|
129
|
-
@
|
130
|
-
entry.write_local_entry(@
|
131
|
+
@entry_set << entry
|
132
|
+
entry.write_local_entry(@output_stream)
|
131
133
|
@compressor = get_compressor(entry, level)
|
132
134
|
end
|
133
135
|
|
134
136
|
def get_compressor(entry, level)
|
135
137
|
case entry.compression_method
|
136
|
-
when
|
137
|
-
when
|
138
|
+
when Entry::DEFLATED then Deflater.new(@output_stream, level)
|
139
|
+
when Entry::STORED then PassThruCompressor.new(@output_stream)
|
138
140
|
else raise ZipCompressionMethodError,
|
139
141
|
"Invalid compression method: '#{entry.compression_method}'"
|
140
142
|
end
|
141
143
|
end
|
142
144
|
|
143
145
|
def update_local_headers
|
144
|
-
pos = @
|
145
|
-
@
|
146
|
-
@
|
147
|
-
entry.write_local_entry(@
|
146
|
+
pos = @output_stream.pos
|
147
|
+
@entry_set.each do |entry|
|
148
|
+
@output_stream.pos = entry.local_header_offset
|
149
|
+
entry.write_local_entry(@output_stream)
|
148
150
|
end
|
149
|
-
@
|
151
|
+
@output_stream.pos = pos
|
150
152
|
end
|
151
153
|
|
152
154
|
def write_central_directory
|
153
|
-
cdir =
|
154
|
-
cdir.write_to_stream(@
|
155
|
+
cdir = CentralDirectory.new(@entry_set, @comment)
|
156
|
+
cdir.write_to_stream(@output_stream)
|
155
157
|
end
|
156
158
|
|
157
159
|
protected
|
@@ -2,7 +2,7 @@ module Zip
|
|
2
2
|
class PassThruCompressor < Compressor #:nodoc:all
|
3
3
|
def initialize(outputStream)
|
4
4
|
super()
|
5
|
-
@
|
5
|
+
@output_stream = outputStream
|
6
6
|
@crc = Zlib::crc32
|
7
7
|
@size = 0
|
8
8
|
end
|
@@ -11,7 +11,7 @@ module Zip
|
|
11
11
|
val = data.to_s
|
12
12
|
@crc = Zlib::crc32(val, @crc)
|
13
13
|
@size += val.bytesize
|
14
|
-
@
|
14
|
+
@output_stream << val
|
15
15
|
end
|
16
16
|
|
17
17
|
attr_reader :size, :crc
|
@@ -1,35 +1,36 @@
|
|
1
1
|
module Zip
|
2
2
|
class PassThruDecompressor < Decompressor #:nodoc:all
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
@
|
7
|
-
@
|
3
|
+
|
4
|
+
def initialize(input_stream, chars_to_read)
|
5
|
+
super(input_stream)
|
6
|
+
@chars_to_read = chars_to_read
|
7
|
+
@read_so_far = 0
|
8
|
+
@has_returned_empty_string = false
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
def sysread(numberOfBytes = nil, buf = nil)
|
11
|
+
def sysread(number_of_bytes = nil, buf = nil)
|
12
12
|
if input_finished?
|
13
|
-
|
14
|
-
@
|
15
|
-
return
|
13
|
+
has_returned_empty_string_val = @has_returned_empty_string
|
14
|
+
@has_returned_empty_string = true
|
15
|
+
return '' unless has_returned_empty_string_val
|
16
16
|
return
|
17
17
|
end
|
18
18
|
|
19
|
-
if (
|
20
|
-
|
19
|
+
if (number_of_bytes == nil || @read_so_far + number_of_bytes > @chars_to_read)
|
20
|
+
number_of_bytes = @chars_to_read - @read_so_far
|
21
21
|
end
|
22
|
-
@
|
23
|
-
@
|
22
|
+
@read_so_far += number_of_bytes
|
23
|
+
@input_stream.read(number_of_bytes, buf)
|
24
24
|
end
|
25
25
|
|
26
26
|
def produce_input
|
27
|
-
sysread(Decompressor::CHUNK_SIZE)
|
27
|
+
sysread(::Zip::Decompressor::CHUNK_SIZE)
|
28
28
|
end
|
29
29
|
|
30
30
|
def input_finished?
|
31
|
-
|
31
|
+
@read_so_far >= @chars_to_read
|
32
32
|
end
|
33
|
+
|
33
34
|
alias :eof :input_finished?
|
34
35
|
alias :eof? :input_finished?
|
35
36
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Zip
|
2
|
-
class
|
2
|
+
class StreamableStream < DelegateClass(Entry) #nodoc:all
|
3
3
|
def initialize(entry)
|
4
4
|
super(entry)
|
5
5
|
@tempFile = Tempfile.new(::File.basename(name), ::File.dirname(zipfile))
|
@@ -37,7 +37,7 @@ module Zip
|
|
37
37
|
|
38
38
|
def write_to_zip_output_stream(aZipOutputStream)
|
39
39
|
aZipOutputStream.put_next_entry(self)
|
40
|
-
get_input_stream { |is| IOExtras.copy_stream(aZipOutputStream, is) }
|
40
|
+
get_input_stream { |is| ::Zip::IOExtras.copy_stream(aZipOutputStream, is) }
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
data/lib/zip/version.rb
ADDED
data/samples/example.rb
CHANGED
@@ -7,7 +7,7 @@ require 'zip/zip'
|
|
7
7
|
|
8
8
|
####### Using ZipInputStream alone: #######
|
9
9
|
|
10
|
-
Zip::
|
10
|
+
Zip::InputStream.open("example.zip") {
|
11
11
|
|zis|
|
12
12
|
entry = zis.get_next_entry
|
13
13
|
print "First line of '#{entry.name} (#{entry.size} bytes): "
|
@@ -20,7 +20,7 @@ Zip::ZipInputStream.open("example.zip") {
|
|
20
20
|
|
21
21
|
####### Using ZipFile to read the directory of a zip file: #######
|
22
22
|
|
23
|
-
zf = Zip::
|
23
|
+
zf = Zip::File.new("example.zip")
|
24
24
|
zf.each_with_index {
|
25
25
|
|entry, index|
|
26
26
|
|
@@ -33,7 +33,7 @@ zf.each_with_index {
|
|
33
33
|
|
34
34
|
####### Using ZipOutputStream to write a zip file: #######
|
35
35
|
|
36
|
-
Zip::
|
36
|
+
Zip::OutputStream.open("exampleout.zip") {
|
37
37
|
|zos|
|
38
38
|
zos.put_next_entry("the first little entry")
|
39
39
|
zos.puts "Hello hello hello hello hello hello hello hello hello"
|
@@ -47,7 +47,7 @@ Zip::ZipOutputStream.open("exampleout.zip") {
|
|
47
47
|
|
48
48
|
####### Using ZipFile to change a zip file: #######
|
49
49
|
|
50
|
-
Zip::
|
50
|
+
Zip::File.open("exampleout.zip") {
|
51
51
|
|zf|
|
52
52
|
zf.add("thisFile.rb", "example.rb")
|
53
53
|
zf.rename("thisFile.rb", "ILikeThisName.rb")
|
@@ -55,13 +55,35 @@ Zip::ZipFile.open("exampleout.zip") {
|
|
55
55
|
}
|
56
56
|
|
57
57
|
# Lets check
|
58
|
-
Zip::
|
58
|
+
Zip::File.open("exampleout.zip") {
|
59
59
|
|zf|
|
60
60
|
puts "Changed zip file contains: #{zf.entries.join(', ')}"
|
61
61
|
zf.remove("Again")
|
62
62
|
puts "Without 'Again': #{zf.entries.join(', ')}"
|
63
63
|
}
|
64
64
|
|
65
|
+
####### Using ZipFile to split a zip file: #######
|
66
|
+
|
67
|
+
# Creating large zip file for splitting
|
68
|
+
Zip::OutputStream.open("large_zip_file.zip") do |zos|
|
69
|
+
puts "Creating zip file..."
|
70
|
+
10.times do |i|
|
71
|
+
zos.put_next_entry("large_entry_#{i}.txt")
|
72
|
+
zos.puts "Hello" * 104857600
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Splitting created large zip file
|
77
|
+
part_zips_count = Zip::File.split("large_zip_file.zip", 2097152, false)
|
78
|
+
puts "Zip file splitted in #{part_zips_count} parts"
|
79
|
+
|
80
|
+
# Track splitting an archive
|
81
|
+
Zip::File.split("large_zip_file.zip", 1048576, true, 'part_zip_file') do
|
82
|
+
|part_count, part_index, chunk_bytes, segment_bytes|
|
83
|
+
puts "#{part_index} of #{part_count} part splitting: #{(chunk_bytes.to_f/segment_bytes.to_f * 100).to_i}%"
|
84
|
+
end
|
85
|
+
|
86
|
+
|
65
87
|
# For other examples, look at zip.rb and ziptest.rb
|
66
88
|
|
67
89
|
# Copyright (C) 2002 Thomas Sondergaard
|
@@ -8,7 +8,7 @@ EXAMPLE_ZIP = "filesystem.zip"
|
|
8
8
|
|
9
9
|
File.delete(EXAMPLE_ZIP) if File.exists?(EXAMPLE_ZIP)
|
10
10
|
|
11
|
-
Zip::
|
11
|
+
Zip::File.open(EXAMPLE_ZIP, Zip::File::CREATE) {
|
12
12
|
|zf|
|
13
13
|
zf.file.open("file1.txt", "w") { |os| os.write "first file1.txt" }
|
14
14
|
zf.dir.mkdir("dir1")
|
@@ -21,7 +21,7 @@ Zip::ZipFile.open(EXAMPLE_ZIP, Zip::ZipFile::CREATE) {
|
|
21
21
|
puts "Entries: #{zf.entries.join(', ')}"
|
22
22
|
}
|
23
23
|
|
24
|
-
Zip::
|
24
|
+
Zip::File.open(EXAMPLE_ZIP) {
|
25
25
|
|zf|
|
26
26
|
puts "Entries from reloaded zip: #{zf.entries.join(', ')}"
|
27
27
|
}
|
@@ -21,7 +21,7 @@ class ZipFileGenerator
|
|
21
21
|
# Zip the input directory.
|
22
22
|
def write()
|
23
23
|
entries = Dir.entries(@inputDir); entries.delete("."); entries.delete("..")
|
24
|
-
io = Zip::
|
24
|
+
io = Zip::File.open(@outputFile, Zip::File::CREATE);
|
25
25
|
|
26
26
|
writeEntries(entries, "", io)
|
27
27
|
io.close();
|
data/samples/gtkRubyzip.rb
CHANGED
data/samples/qtzip.rb
CHANGED
@@ -25,11 +25,11 @@ class ZipDialog < ZipDialogUI
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def zipfile(&proc)
|
28
|
-
Zip::
|
28
|
+
Zip::File.open(@zip_filename, &proc)
|
29
29
|
end
|
30
30
|
|
31
31
|
def each(&proc)
|
32
|
-
Zip::
|
32
|
+
Zip::File.foreach(@zip_filename, &proc)
|
33
33
|
end
|
34
34
|
|
35
35
|
def refresh()
|