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
@@ -0,0 +1,189 @@
|
|
1
|
+
module Zip
|
2
|
+
# ZipOutputStream is the basic class for writing zip files. It is
|
3
|
+
# possible to create a ZipOutputStream object directly, passing
|
4
|
+
# the zip file name to the constructor, but more often than not
|
5
|
+
# the ZipOutputStream will be obtained from a ZipFile (perhaps using the
|
6
|
+
# ZipFileSystem interface) object for a particular entry in the zip
|
7
|
+
# archive.
|
8
|
+
#
|
9
|
+
# A ZipOutputStream inherits IOExtras::AbstractOutputStream in order
|
10
|
+
# to provide an IO-like interface for writing to a single zip
|
11
|
+
# entry. Beyond methods for mimicking an IO-object it contains
|
12
|
+
# the method put_next_entry that closes the current entry
|
13
|
+
# and creates a new.
|
14
|
+
#
|
15
|
+
# Please refer to ZipInputStream for example code.
|
16
|
+
#
|
17
|
+
# java.util.zip.ZipOutputStream is the original inspiration for this
|
18
|
+
# class.
|
19
|
+
|
20
|
+
class OutputStream
|
21
|
+
include ::Zip::IOExtras::AbstractOutputStream
|
22
|
+
|
23
|
+
attr_accessor :comment
|
24
|
+
|
25
|
+
# Opens the indicated zip file. If a file with that name already
|
26
|
+
# exists it will be overwritten.
|
27
|
+
def initialize(file_name, stream = false, encrypter = nil)
|
28
|
+
super()
|
29
|
+
@file_name = file_name
|
30
|
+
@output_stream = if stream
|
31
|
+
iostream = @file_name.dup
|
32
|
+
iostream.reopen(@file_name)
|
33
|
+
iostream.rewind
|
34
|
+
iostream
|
35
|
+
else
|
36
|
+
::File.new(@file_name, 'wb')
|
37
|
+
end
|
38
|
+
@entry_set = ::Zip::EntrySet.new
|
39
|
+
@compressor = ::Zip::NullCompressor.instance
|
40
|
+
@encrypter = encrypter || ::Zip::NullEncrypter.new
|
41
|
+
@closed = false
|
42
|
+
@current_entry = nil
|
43
|
+
@comment = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
# Same as #initialize but if a block is passed the opened
|
47
|
+
# stream is passed to the block and closed when the block
|
48
|
+
# returns.
|
49
|
+
class << self
|
50
|
+
def open(file_name, encrypter = nil)
|
51
|
+
return new(file_name) unless block_given?
|
52
|
+
zos = new(file_name, false, encrypter)
|
53
|
+
yield zos
|
54
|
+
ensure
|
55
|
+
zos.close if zos
|
56
|
+
end
|
57
|
+
|
58
|
+
# Same as #open but writes to a filestream instead
|
59
|
+
def write_buffer(io = ::StringIO.new(''), encrypter = nil)
|
60
|
+
zos = new(io, true, encrypter)
|
61
|
+
yield zos
|
62
|
+
zos.close_buffer
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Closes the stream and writes the central directory to the zip file
|
67
|
+
def close
|
68
|
+
return if @closed
|
69
|
+
finalize_current_entry
|
70
|
+
update_local_headers
|
71
|
+
write_central_directory
|
72
|
+
@output_stream.close
|
73
|
+
@closed = true
|
74
|
+
end
|
75
|
+
|
76
|
+
# Closes the stream and writes the central directory to the zip file
|
77
|
+
def close_buffer
|
78
|
+
return @output_stream if @closed
|
79
|
+
finalize_current_entry
|
80
|
+
update_local_headers
|
81
|
+
write_central_directory
|
82
|
+
@closed = true
|
83
|
+
@output_stream
|
84
|
+
end
|
85
|
+
|
86
|
+
# Closes the current entry and opens a new for writing.
|
87
|
+
# +entry+ can be a ZipEntry object or a string.
|
88
|
+
def put_next_entry(entry_name, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zip.default_compression)
|
89
|
+
raise Error, 'zip stream is closed' if @closed
|
90
|
+
new_entry = if entry_name.kind_of?(Entry)
|
91
|
+
entry_name
|
92
|
+
else
|
93
|
+
Entry.new(@file_name, entry_name.to_s)
|
94
|
+
end
|
95
|
+
new_entry.comment = comment unless comment.nil?
|
96
|
+
unless extra.nil?
|
97
|
+
new_entry.extra = extra.is_a?(ExtraField) ? extra : ExtraField.new(extra.to_s)
|
98
|
+
end
|
99
|
+
new_entry.compression_method = compression_method unless compression_method.nil?
|
100
|
+
init_next_entry(new_entry, level)
|
101
|
+
@current_entry = new_entry
|
102
|
+
end
|
103
|
+
|
104
|
+
def copy_raw_entry(entry)
|
105
|
+
entry = entry.dup
|
106
|
+
raise Error, 'zip stream is closed' if @closed
|
107
|
+
raise Error, 'entry is not a ZipEntry' unless entry.is_a?(Entry)
|
108
|
+
finalize_current_entry
|
109
|
+
@entry_set << entry
|
110
|
+
src_pos = entry.local_header_offset
|
111
|
+
entry.write_local_entry(@output_stream)
|
112
|
+
@compressor = NullCompressor.instance
|
113
|
+
entry.get_raw_input_stream do |is|
|
114
|
+
is.seek(src_pos, IO::SEEK_SET)
|
115
|
+
::Zip::Entry.read_local_entry(is)
|
116
|
+
IOExtras.copy_stream_n(@output_stream, is, entry.compressed_size)
|
117
|
+
end
|
118
|
+
@compressor = NullCompressor.instance
|
119
|
+
@current_entry = nil
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def finalize_current_entry
|
125
|
+
return unless @current_entry
|
126
|
+
finish
|
127
|
+
@current_entry.compressed_size = @output_stream.tell - @current_entry.local_header_offset - @current_entry.calculate_local_header_size
|
128
|
+
@current_entry.size = @compressor.size
|
129
|
+
@current_entry.crc = @compressor.crc
|
130
|
+
@output_stream << @encrypter.data_descriptor(@current_entry.crc, @current_entry.compressed_size, @current_entry.size)
|
131
|
+
@current_entry.gp_flags |= @encrypter.gp_flags
|
132
|
+
@current_entry = nil
|
133
|
+
@compressor = ::Zip::NullCompressor.instance
|
134
|
+
end
|
135
|
+
|
136
|
+
def init_next_entry(entry, level = Zip.default_compression)
|
137
|
+
finalize_current_entry
|
138
|
+
@entry_set << entry
|
139
|
+
entry.write_local_entry(@output_stream)
|
140
|
+
@encrypter.reset!
|
141
|
+
@output_stream << @encrypter.header(entry.mtime)
|
142
|
+
@compressor = get_compressor(entry, level)
|
143
|
+
end
|
144
|
+
|
145
|
+
def get_compressor(entry, level)
|
146
|
+
case entry.compression_method
|
147
|
+
when Entry::DEFLATED then
|
148
|
+
::Zip::Deflater.new(@output_stream, level, @encrypter)
|
149
|
+
when Entry::STORED then
|
150
|
+
::Zip::PassThruCompressor.new(@output_stream)
|
151
|
+
else
|
152
|
+
raise ::Zip::CompressionMethodError,
|
153
|
+
"Invalid compression method: '#{entry.compression_method}'"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def update_local_headers
|
158
|
+
pos = @output_stream.pos
|
159
|
+
@entry_set.each do |entry|
|
160
|
+
@output_stream.pos = entry.local_header_offset
|
161
|
+
entry.write_local_entry(@output_stream, true)
|
162
|
+
end
|
163
|
+
@output_stream.pos = pos
|
164
|
+
end
|
165
|
+
|
166
|
+
def write_central_directory
|
167
|
+
cdir = CentralDirectory.new(@entry_set, @comment)
|
168
|
+
cdir.write_to_stream(@output_stream)
|
169
|
+
end
|
170
|
+
|
171
|
+
protected
|
172
|
+
|
173
|
+
def finish
|
174
|
+
@compressor.finish
|
175
|
+
end
|
176
|
+
|
177
|
+
public
|
178
|
+
|
179
|
+
# Modeled after IO.<<
|
180
|
+
def <<(data)
|
181
|
+
@compressor << data
|
182
|
+
self
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
188
|
+
# rubyzip is free software; you can redistribute it and/or
|
189
|
+
# modify it under the terms of the ruby license.
|
@@ -2,16 +2,16 @@ module Zip
|
|
2
2
|
class PassThruCompressor < Compressor #:nodoc:all
|
3
3
|
def initialize(outputStream)
|
4
4
|
super()
|
5
|
-
@
|
6
|
-
@crc = Zlib
|
5
|
+
@output_stream = outputStream
|
6
|
+
@crc = Zlib.crc32
|
7
7
|
@size = 0
|
8
8
|
end
|
9
|
-
|
10
|
-
def <<
|
9
|
+
|
10
|
+
def <<(data)
|
11
11
|
val = data.to_s
|
12
|
-
@crc = Zlib
|
13
|
-
@size += val.
|
14
|
-
@
|
12
|
+
@crc = Zlib.crc32(val, @crc)
|
13
|
+
@size += val.bytesize
|
14
|
+
@output_stream << val
|
15
15
|
end
|
16
16
|
|
17
17
|
attr_reader :size, :crc
|
@@ -1,37 +1,37 @@
|
|
1
1
|
module Zip
|
2
|
-
class PassThruDecompressor < Decompressor
|
3
|
-
def initialize(
|
4
|
-
super
|
5
|
-
@
|
6
|
-
@
|
7
|
-
@
|
2
|
+
class PassThruDecompressor < Decompressor #:nodoc:all
|
3
|
+
def initialize(input_stream, chars_to_read)
|
4
|
+
super(input_stream)
|
5
|
+
@chars_to_read = chars_to_read
|
6
|
+
@read_so_far = 0
|
7
|
+
@has_returned_empty_string = false
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
def sysread(numberOfBytes = nil, buf = nil)
|
10
|
+
def sysread(number_of_bytes = nil, buf = '')
|
12
11
|
if input_finished?
|
13
|
-
|
14
|
-
@
|
15
|
-
return
|
12
|
+
has_returned_empty_string_val = @has_returned_empty_string
|
13
|
+
@has_returned_empty_string = true
|
14
|
+
return '' unless has_returned_empty_string_val
|
16
15
|
return
|
17
16
|
end
|
18
17
|
|
19
|
-
if
|
20
|
-
|
18
|
+
if number_of_bytes.nil? || @read_so_far + number_of_bytes > @chars_to_read
|
19
|
+
number_of_bytes = @chars_to_read - @read_so_far
|
21
20
|
end
|
22
|
-
@
|
23
|
-
@
|
21
|
+
@read_so_far += number_of_bytes
|
22
|
+
@input_stream.read(number_of_bytes, buf)
|
24
23
|
end
|
25
24
|
|
26
25
|
def produce_input
|
27
|
-
sysread(Decompressor::CHUNK_SIZE)
|
26
|
+
sysread(::Zip::Decompressor::CHUNK_SIZE)
|
28
27
|
end
|
29
28
|
|
30
29
|
def input_finished?
|
31
|
-
|
30
|
+
@read_so_far >= @chars_to_read
|
32
31
|
end
|
33
|
-
|
34
|
-
alias
|
32
|
+
|
33
|
+
alias eof input_finished?
|
34
|
+
alias eof? input_finished?
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Zip
|
2
|
-
class
|
2
|
+
class StreamableDirectory < Entry
|
3
3
|
def initialize(zipfile, entry, srcPath = nil, permissionInt = nil)
|
4
4
|
super(zipfile, entry)
|
5
5
|
|
6
6
|
@ftype = :directory
|
7
|
-
entry.get_extra_attributes_from_path(srcPath) if
|
8
|
-
@unix_perms = permissionInt if
|
7
|
+
entry.get_extra_attributes_from_path(srcPath) if srcPath
|
8
|
+
@unix_perms = permissionInt if permissionInt
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Zip
|
2
|
+
class StreamableStream < DelegateClass(Entry) # nodoc:all
|
3
|
+
def initialize(entry)
|
4
|
+
super(entry)
|
5
|
+
dirname = if zipfile.is_a?(::String)
|
6
|
+
::File.dirname(zipfile)
|
7
|
+
else
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
@temp_file = Tempfile.new(::File.basename(name), dirname)
|
11
|
+
@temp_file.binmode
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_output_stream
|
15
|
+
if block_given?
|
16
|
+
begin
|
17
|
+
yield(@temp_file)
|
18
|
+
ensure
|
19
|
+
@temp_file.close
|
20
|
+
end
|
21
|
+
else
|
22
|
+
@temp_file
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_input_stream
|
27
|
+
unless @temp_file.closed?
|
28
|
+
raise StandardError, "cannot open entry for reading while its open for writing - #{name}"
|
29
|
+
end
|
30
|
+
@temp_file.open # reopens tempfile from top
|
31
|
+
@temp_file.binmode
|
32
|
+
if block_given?
|
33
|
+
begin
|
34
|
+
yield(@temp_file)
|
35
|
+
ensure
|
36
|
+
@temp_file.close
|
37
|
+
end
|
38
|
+
else
|
39
|
+
@temp_file
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def write_to_zip_output_stream(aZipOutputStream)
|
44
|
+
aZipOutputStream.put_next_entry(self)
|
45
|
+
get_input_stream { |is| ::Zip::IOExtras.copy_stream(aZipOutputStream, is) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def clean_up
|
49
|
+
@temp_file.unlink
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
55
|
+
# rubyzip is free software; you can redistribute it and/or
|
56
|
+
# modify it under the terms of the ruby license.
|
data/lib/zip/version.rb
ADDED
data/lib/zip.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'singleton'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'tmpdir'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'stringio'
|
7
|
+
require 'zlib'
|
8
|
+
require 'zip/dos_time'
|
9
|
+
require 'zip/ioextras'
|
10
|
+
require 'rbconfig'
|
11
|
+
require 'zip/entry'
|
12
|
+
require 'zip/extra_field'
|
13
|
+
require 'zip/entry_set'
|
14
|
+
require 'zip/central_directory'
|
15
|
+
require 'zip/file'
|
16
|
+
require 'zip/input_stream'
|
17
|
+
require 'zip/output_stream'
|
18
|
+
require 'zip/decompressor'
|
19
|
+
require 'zip/compressor'
|
20
|
+
require 'zip/null_decompressor'
|
21
|
+
require 'zip/null_compressor'
|
22
|
+
require 'zip/null_input_stream'
|
23
|
+
require 'zip/pass_thru_compressor'
|
24
|
+
require 'zip/pass_thru_decompressor'
|
25
|
+
require 'zip/crypto/encryption'
|
26
|
+
require 'zip/crypto/null_encryption'
|
27
|
+
require 'zip/crypto/traditional_encryption'
|
28
|
+
require 'zip/inflater'
|
29
|
+
require 'zip/deflater'
|
30
|
+
require 'zip/streamable_stream'
|
31
|
+
require 'zip/streamable_directory'
|
32
|
+
require 'zip/constants'
|
33
|
+
require 'zip/errors'
|
34
|
+
|
35
|
+
module Zip
|
36
|
+
extend self
|
37
|
+
attr_accessor :unicode_names,
|
38
|
+
:on_exists_proc,
|
39
|
+
:continue_on_exists_proc,
|
40
|
+
:sort_entries,
|
41
|
+
:default_compression,
|
42
|
+
:write_zip64_support,
|
43
|
+
:warn_invalid_date,
|
44
|
+
:case_insensitive_match,
|
45
|
+
:force_entry_names_encoding,
|
46
|
+
:validate_entry_sizes
|
47
|
+
|
48
|
+
def reset!
|
49
|
+
@_ran_once = false
|
50
|
+
@unicode_names = false
|
51
|
+
@on_exists_proc = false
|
52
|
+
@continue_on_exists_proc = false
|
53
|
+
@sort_entries = false
|
54
|
+
@default_compression = ::Zlib::DEFAULT_COMPRESSION
|
55
|
+
@write_zip64_support = false
|
56
|
+
@warn_invalid_date = true
|
57
|
+
@case_insensitive_match = false
|
58
|
+
@validate_entry_sizes = false
|
59
|
+
end
|
60
|
+
|
61
|
+
def setup
|
62
|
+
yield self unless @_ran_once
|
63
|
+
@_ran_once = true
|
64
|
+
end
|
65
|
+
|
66
|
+
reset!
|
67
|
+
end
|
68
|
+
|
69
|
+
# Copyright (C) 2002, 2003 Thomas Sondergaard
|
70
|
+
# rubyzip is free software; you can redistribute it and/or
|
71
|
+
# modify it under the terms of the ruby license.
|
data/samples/example.rb
CHANGED
@@ -1,66 +1,78 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
$: <<
|
4
|
-
system(
|
3
|
+
$: << '../lib'
|
4
|
+
system('zip example.zip example.rb gtk_ruby_zip.rb')
|
5
5
|
|
6
|
-
require 'zip
|
6
|
+
require 'zip'
|
7
7
|
|
8
8
|
####### Using ZipInputStream alone: #######
|
9
9
|
|
10
|
-
Zip::
|
11
|
-
|zis|
|
10
|
+
Zip::InputStream.open('example.zip') do |zis|
|
12
11
|
entry = zis.get_next_entry
|
13
12
|
print "First line of '#{entry.name} (#{entry.size} bytes): "
|
14
13
|
puts "'#{zis.gets.chomp}'"
|
15
14
|
entry = zis.get_next_entry
|
16
15
|
print "First line of '#{entry.name} (#{entry.size} bytes): "
|
17
16
|
puts "'#{zis.gets.chomp}'"
|
18
|
-
|
19
|
-
|
17
|
+
end
|
20
18
|
|
21
19
|
####### Using ZipFile to read the directory of a zip file: #######
|
22
20
|
|
23
|
-
zf = Zip::
|
24
|
-
zf.each_with_index
|
25
|
-
|entry, index|
|
26
|
-
|
21
|
+
zf = Zip::File.new('example.zip')
|
22
|
+
zf.each_with_index do |entry, index|
|
27
23
|
puts "entry #{index} is #{entry.name}, size = #{entry.size}, compressed size = #{entry.compressed_size}"
|
28
24
|
# use zf.get_input_stream(entry) to get a ZipInputStream for the entry
|
29
25
|
# entry can be the ZipEntry object or any object which has a to_s method that
|
30
26
|
# returns the name of the entry.
|
31
|
-
|
32
|
-
|
27
|
+
end
|
33
28
|
|
34
29
|
####### Using ZipOutputStream to write a zip file: #######
|
35
30
|
|
36
|
-
Zip::
|
37
|
-
|
38
|
-
zos.
|
39
|
-
zos.puts "Hello hello hello hello hello hello hello hello hello"
|
31
|
+
Zip::OutputStream.open('exampleout.zip') do |zos|
|
32
|
+
zos.put_next_entry('the first little entry')
|
33
|
+
zos.puts 'Hello hello hello hello hello hello hello hello hello'
|
40
34
|
|
41
|
-
zos.put_next_entry(
|
42
|
-
zos.puts
|
35
|
+
zos.put_next_entry('the second little entry')
|
36
|
+
zos.puts 'Hello again'
|
43
37
|
|
44
38
|
# Use rubyzip or your zip client of choice to verify
|
45
39
|
# the contents of exampleout.zip
|
46
|
-
|
40
|
+
end
|
47
41
|
|
48
42
|
####### Using ZipFile to change a zip file: #######
|
49
43
|
|
50
|
-
Zip::
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
}
|
44
|
+
Zip::File.open('exampleout.zip') do |zip_file|
|
45
|
+
zip_file.add('thisFile.rb', 'example.rb')
|
46
|
+
zip_file.rename('thisFile.rb', 'ILikeThisName.rb')
|
47
|
+
zip_file.add('Again', 'example.rb')
|
48
|
+
end
|
56
49
|
|
57
50
|
# Lets check
|
58
|
-
Zip::
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
51
|
+
Zip::File.open('exampleout.zip') do |zip_file|
|
52
|
+
puts "Changed zip file contains: #{zip_file.entries.join(', ')}"
|
53
|
+
zip_file.remove('Again')
|
54
|
+
puts "Without 'Again': #{zip_file.entries.join(', ')}"
|
55
|
+
end
|
56
|
+
|
57
|
+
####### Using ZipFile to split a zip file: #######
|
58
|
+
|
59
|
+
# Creating large zip file for splitting
|
60
|
+
Zip::OutputStream.open('large_zip_file.zip') do |zos|
|
61
|
+
puts 'Creating zip file...'
|
62
|
+
10.times do |i|
|
63
|
+
zos.put_next_entry("large_entry_#{i}.txt")
|
64
|
+
zos.puts 'Hello' * 104_857_600
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Splitting created large zip file
|
69
|
+
part_zips_count = Zip::File.split('large_zip_file.zip', 2_097_152, false)
|
70
|
+
puts "Zip file splitted in #{part_zips_count} parts"
|
71
|
+
|
72
|
+
# Track splitting an archive
|
73
|
+
Zip::File.split('large_zip_file.zip', 1_048_576, true, 'part_zip_file') do |part_count, part_index, chunk_bytes, segment_bytes|
|
74
|
+
puts "#{part_index} of #{part_count} part splitting: #{(chunk_bytes.to_f / segment_bytes.to_f * 100).to_i}%"
|
75
|
+
end
|
64
76
|
|
65
77
|
# For other examples, look at zip.rb and ziptest.rb
|
66
78
|
|
@@ -1,30 +1,28 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
$: <<
|
3
|
+
$: << '../lib'
|
4
4
|
|
5
|
-
require 'zip/
|
5
|
+
require 'zip/filesystem'
|
6
6
|
|
7
|
-
EXAMPLE_ZIP =
|
7
|
+
EXAMPLE_ZIP = 'filesystem.zip'
|
8
8
|
|
9
|
-
File.delete(EXAMPLE_ZIP) if File.
|
9
|
+
File.delete(EXAMPLE_ZIP) if File.exist?(EXAMPLE_ZIP)
|
10
10
|
|
11
|
-
Zip::
|
12
|
-
|
13
|
-
zf.
|
14
|
-
zf.dir.
|
15
|
-
zf.
|
16
|
-
zf.file.
|
17
|
-
puts zf.file.read(
|
18
|
-
|
19
|
-
zf.
|
20
|
-
zf.file.open("file2.txt", "w") { |os| os.write "first file2.txt" }
|
11
|
+
Zip::File.open(EXAMPLE_ZIP, Zip::File::CREATE) do |zf|
|
12
|
+
zf.file.open('file1.txt', 'w') { |os| os.write 'first file1.txt' }
|
13
|
+
zf.dir.mkdir('dir1')
|
14
|
+
zf.dir.chdir('dir1')
|
15
|
+
zf.file.open('file1.txt', 'w') { |os| os.write 'second file1.txt' }
|
16
|
+
puts zf.file.read('file1.txt')
|
17
|
+
puts zf.file.read('../file1.txt')
|
18
|
+
zf.dir.chdir('..')
|
19
|
+
zf.file.open('file2.txt', 'w') { |os| os.write 'first file2.txt' }
|
21
20
|
puts "Entries: #{zf.entries.join(', ')}"
|
22
|
-
|
21
|
+
end
|
23
22
|
|
24
|
-
Zip::
|
25
|
-
|zf|
|
23
|
+
Zip::File.open(EXAMPLE_ZIP) do |zf|
|
26
24
|
puts "Entries from reloaded zip: #{zf.entries.join(', ')}"
|
27
|
-
|
25
|
+
end
|
28
26
|
|
29
27
|
# For other examples, look at zip.rb and ziptest.rb
|
30
28
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'zip
|
1
|
+
require 'zip'
|
2
2
|
|
3
3
|
# This is a simple example which uses rubyzip to
|
4
4
|
# recursively generate a zip file from the contents of
|
@@ -6,44 +6,49 @@ require 'zip/zip'
|
|
6
6
|
# included in the archive, rather just its contents.
|
7
7
|
#
|
8
8
|
# Usage:
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# zf = ZipFileGenerator(
|
9
|
+
# directory_to_zip = "/tmp/input"
|
10
|
+
# output_file = "/tmp/out.zip"
|
11
|
+
# zf = ZipFileGenerator.new(directory_to_zip, output_file)
|
12
12
|
# zf.write()
|
13
13
|
class ZipFileGenerator
|
14
|
-
|
15
14
|
# Initialize with the directory to zip and the location of the output archive.
|
16
|
-
def initialize(
|
17
|
-
@
|
18
|
-
@
|
15
|
+
def initialize(input_dir, output_file)
|
16
|
+
@input_dir = input_dir
|
17
|
+
@output_file = output_file
|
19
18
|
end
|
20
19
|
|
21
20
|
# Zip the input directory.
|
22
|
-
def write
|
23
|
-
entries = Dir.entries(@
|
24
|
-
io = Zip::ZipFile.open(@outputFile, Zip::ZipFile::CREATE);
|
21
|
+
def write
|
22
|
+
entries = Dir.entries(@input_dir) - %w[. ..]
|
25
23
|
|
26
|
-
|
27
|
-
|
24
|
+
::Zip::File.open(@output_file, ::Zip::File::CREATE) do |zipfile|
|
25
|
+
write_entries entries, '', zipfile
|
26
|
+
end
|
28
27
|
end
|
29
28
|
|
30
|
-
# A helper method to make the recursion work.
|
31
29
|
private
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
writeEntries(subdir, zipFilePath, io)
|
30
|
+
|
31
|
+
# A helper method to make the recursion work.
|
32
|
+
def write_entries(entries, path, zipfile)
|
33
|
+
entries.each do |e|
|
34
|
+
zipfile_path = path == '' ? e : File.join(path, e)
|
35
|
+
disk_file_path = File.join(@input_dir, zipfile_path)
|
36
|
+
|
37
|
+
if File.directory? disk_file_path
|
38
|
+
recursively_deflate_directory(disk_file_path, zipfile, zipfile_path)
|
42
39
|
else
|
43
|
-
|
40
|
+
put_into_archive(disk_file_path, zipfile, zipfile_path)
|
44
41
|
end
|
45
|
-
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def recursively_deflate_directory(disk_file_path, zipfile, zipfile_path)
|
46
|
+
zipfile.mkdir zipfile_path
|
47
|
+
subdir = Dir.entries(disk_file_path) - %w[. ..]
|
48
|
+
write_entries subdir, zipfile_path, zipfile
|
46
49
|
end
|
47
|
-
|
48
|
-
end
|
49
50
|
|
51
|
+
def put_into_archive(disk_file_path, zipfile, zipfile_path)
|
52
|
+
zipfile.add(zipfile_path, disk_file_path)
|
53
|
+
end
|
54
|
+
end
|