rubyzip 2.2.0 → 2.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 +4 -4
- data/Rakefile +3 -0
- data/lib/zip.rb +1 -0
- data/lib/zip/central_directory.rb +9 -5
- data/lib/zip/constants.rb +18 -18
- data/lib/zip/crypto/decrypted_io.rb +4 -3
- data/lib/zip/crypto/traditional_encryption.rb +9 -9
- data/lib/zip/dos_time.rb +7 -7
- data/lib/zip/entry.rb +35 -28
- data/lib/zip/entry_set.rb +2 -0
- data/lib/zip/extra_field.rb +11 -9
- data/lib/zip/extra_field/generic.rb +9 -8
- data/lib/zip/extra_field/ntfs.rb +4 -0
- data/lib/zip/extra_field/old_unix.rb +3 -1
- data/lib/zip/extra_field/universal_time.rb +3 -0
- data/lib/zip/extra_field/unix.rb +3 -1
- data/lib/zip/extra_field/zip64.rb +4 -2
- data/lib/zip/file.rb +49 -38
- data/lib/zip/filesystem.rb +193 -177
- data/lib/zip/inflater.rb +5 -3
- data/lib/zip/input_stream.rb +6 -3
- data/lib/zip/ioextras.rb +1 -1
- data/lib/zip/ioextras/abstract_input_stream.rb +14 -9
- data/lib/zip/ioextras/abstract_output_stream.rb +1 -1
- data/lib/zip/output_stream.rb +14 -5
- data/lib/zip/pass_thru_compressor.rb +2 -2
- data/lib/zip/pass_thru_decompressor.rb +2 -2
- data/lib/zip/streamable_directory.rb +3 -3
- data/lib/zip/streamable_stream.rb +5 -4
- data/lib/zip/version.rb +1 -1
- data/samples/example.rb +2 -2
- data/samples/example_filesystem.rb +1 -1
- data/samples/gtk_ruby_zip.rb +19 -19
- data/samples/qtzip.rb +6 -6
- data/samples/write_simple.rb +2 -4
- data/samples/zipfind.rb +23 -22
- metadata +25 -19
data/lib/zip/inflater.rb
CHANGED
@@ -3,15 +3,16 @@ module Zip
|
|
3
3
|
def initialize(*args)
|
4
4
|
super
|
5
5
|
|
6
|
-
@buffer = ''
|
6
|
+
@buffer = +''
|
7
7
|
@zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
8
8
|
end
|
9
9
|
|
10
10
|
def read(length = nil, outbuf = '')
|
11
|
-
return (
|
11
|
+
return (length.nil? || length.zero? ? '' : nil) if eof
|
12
12
|
|
13
13
|
while length.nil? || (@buffer.bytesize < length)
|
14
14
|
break if input_finished?
|
15
|
+
|
15
16
|
@buffer << produce_input
|
16
17
|
end
|
17
18
|
|
@@ -22,7 +23,7 @@ module Zip
|
|
22
23
|
@buffer.empty? && input_finished?
|
23
24
|
end
|
24
25
|
|
25
|
-
|
26
|
+
alias eof? eof
|
26
27
|
|
27
28
|
private
|
28
29
|
|
@@ -32,6 +33,7 @@ module Zip
|
|
32
33
|
@zlib_inflater.inflate(input_stream.read(Decompressor::CHUNK_SIZE))
|
33
34
|
rescue Zlib::BufError
|
34
35
|
raise if retried >= 5 # how many times should we retry?
|
36
|
+
|
35
37
|
retried += 1
|
36
38
|
retry
|
37
39
|
end
|
data/lib/zip/input_stream.rb
CHANGED
@@ -51,7 +51,7 @@ module Zip
|
|
51
51
|
# @param offset [Integer] offset in the IO/StringIO
|
52
52
|
def initialize(context, offset = 0, decrypter = nil)
|
53
53
|
super()
|
54
|
-
@archive_io
|
54
|
+
@archive_io = get_io(context, offset)
|
55
55
|
@decompressor = ::Zip::NullDecompressor
|
56
56
|
@decrypter = decrypter || ::Zip::NullDecrypter.new
|
57
57
|
@current_entry = nil
|
@@ -73,6 +73,7 @@ module Zip
|
|
73
73
|
# Rewinds the stream to the beginning of the current entry
|
74
74
|
def rewind
|
75
75
|
return if @current_entry.nil?
|
76
|
+
|
76
77
|
@lineno = 0
|
77
78
|
@pos = 0
|
78
79
|
@archive_io.seek(@current_entry.local_header_offset, IO::SEEK_SET)
|
@@ -91,6 +92,7 @@ module Zip
|
|
91
92
|
def open(filename_or_io, offset = 0, decrypter = nil)
|
92
93
|
zio = new(filename_or_io, offset, decrypter)
|
93
94
|
return zio unless block_given?
|
95
|
+
|
94
96
|
begin
|
95
97
|
yield zio
|
96
98
|
ensure
|
@@ -100,7 +102,7 @@ module Zip
|
|
100
102
|
|
101
103
|
def open_buffer(filename_or_io, offset = 0)
|
102
104
|
warn 'open_buffer is deprecated!!! Use open instead!'
|
103
|
-
open(filename_or_io, offset)
|
105
|
+
::Zip::InputStream.open(filename_or_io, offset)
|
104
106
|
end
|
105
107
|
end
|
106
108
|
|
@@ -120,9 +122,10 @@ module Zip
|
|
120
122
|
|
121
123
|
def open_entry
|
122
124
|
@current_entry = ::Zip::Entry.read_local_entry(@archive_io)
|
123
|
-
if @current_entry && @current_entry.encrypted? && @decrypter.
|
125
|
+
if @current_entry && @current_entry.encrypted? && @decrypter.kind_of?(NullEncrypter)
|
124
126
|
raise Error, 'password required to decode zip file'
|
125
127
|
end
|
128
|
+
|
126
129
|
if @current_entry && @current_entry.incomplete? && @current_entry.crc == 0 \
|
127
130
|
&& @current_entry.compressed_size == 0 \
|
128
131
|
&& @current_entry.size == 0 && !@complete_entry
|
data/lib/zip/ioextras.rb
CHANGED
@@ -35,6 +35,7 @@ module Zip
|
|
35
35
|
|
36
36
|
if tbuf.nil? || tbuf.empty?
|
37
37
|
return nil if number_of_bytes
|
38
|
+
|
38
39
|
return ''
|
39
40
|
end
|
40
41
|
|
@@ -48,13 +49,13 @@ module Zip
|
|
48
49
|
buf
|
49
50
|
end
|
50
51
|
|
51
|
-
def readlines(a_sep_string =
|
52
|
+
def readlines(a_sep_string = $INPUT_RECORD_SEPARATOR)
|
52
53
|
ret_val = []
|
53
54
|
each_line(a_sep_string) { |line| ret_val << line }
|
54
55
|
ret_val
|
55
56
|
end
|
56
57
|
|
57
|
-
def gets(a_sep_string =
|
58
|
+
def gets(a_sep_string = $INPUT_RECORD_SEPARATOR, number_of_bytes = nil)
|
58
59
|
@lineno = @lineno.next
|
59
60
|
|
60
61
|
if number_of_bytes.respond_to?(:to_int)
|
@@ -62,20 +63,22 @@ module Zip
|
|
62
63
|
a_sep_string = a_sep_string.to_str if a_sep_string
|
63
64
|
elsif a_sep_string.respond_to?(:to_int)
|
64
65
|
number_of_bytes = a_sep_string.to_int
|
65
|
-
a_sep_string =
|
66
|
+
a_sep_string = $INPUT_RECORD_SEPARATOR
|
66
67
|
else
|
67
68
|
number_of_bytes = nil
|
68
69
|
a_sep_string = a_sep_string.to_str if a_sep_string
|
69
70
|
end
|
70
71
|
|
71
72
|
return read(number_of_bytes) if a_sep_string.nil?
|
72
|
-
|
73
|
+
|
74
|
+
a_sep_string = "#{$INPUT_RECORD_SEPARATOR}#{$INPUT_RECORD_SEPARATOR}" if a_sep_string.empty?
|
73
75
|
|
74
76
|
buffer_index = 0
|
75
77
|
over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
|
76
78
|
while (match_index = @output_buffer.index(a_sep_string, buffer_index)).nil? && !over_limit
|
77
79
|
buffer_index = [buffer_index, @output_buffer.bytesize - a_sep_string.bytesize].max
|
78
80
|
return @output_buffer.empty? ? nil : flush if input_finished?
|
81
|
+
|
79
82
|
@output_buffer << produce_input
|
80
83
|
over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
|
81
84
|
end
|
@@ -94,24 +97,26 @@ module Zip
|
|
94
97
|
ret_val
|
95
98
|
end
|
96
99
|
|
97
|
-
def readline(a_sep_string =
|
100
|
+
def readline(a_sep_string = $INPUT_RECORD_SEPARATOR)
|
98
101
|
ret_val = gets(a_sep_string)
|
99
102
|
raise EOFError unless ret_val
|
103
|
+
|
100
104
|
ret_val
|
101
105
|
end
|
102
106
|
|
103
|
-
def each_line(a_sep_string =
|
104
|
-
yield readline(a_sep_string)
|
107
|
+
def each_line(a_sep_string = $INPUT_RECORD_SEPARATOR)
|
108
|
+
loop { yield readline(a_sep_string) }
|
105
109
|
rescue EOFError
|
110
|
+
# We just need to catch this; we don't need to handle it.
|
106
111
|
end
|
107
112
|
|
108
|
-
|
113
|
+
alias each each_line
|
109
114
|
|
110
115
|
def eof
|
111
116
|
@output_buffer.empty? && input_finished?
|
112
117
|
end
|
113
118
|
|
114
|
-
|
119
|
+
alias eof? eof
|
115
120
|
end
|
116
121
|
end
|
117
122
|
end
|
data/lib/zip/output_stream.rb
CHANGED
@@ -49,6 +49,7 @@ module Zip
|
|
49
49
|
class << self
|
50
50
|
def open(file_name, encrypter = nil)
|
51
51
|
return new(file_name) unless block_given?
|
52
|
+
|
52
53
|
zos = new(file_name, false, encrypter)
|
53
54
|
yield zos
|
54
55
|
ensure
|
@@ -57,6 +58,7 @@ module Zip
|
|
57
58
|
|
58
59
|
# Same as #open but writes to a filestream instead
|
59
60
|
def write_buffer(io = ::StringIO.new(''), encrypter = nil)
|
61
|
+
io.binmode if io.respond_to?(:binmode)
|
60
62
|
zos = new(io, true, encrypter)
|
61
63
|
yield zos
|
62
64
|
zos.close_buffer
|
@@ -66,6 +68,7 @@ module Zip
|
|
66
68
|
# Closes the stream and writes the central directory to the zip file
|
67
69
|
def close
|
68
70
|
return if @closed
|
71
|
+
|
69
72
|
finalize_current_entry
|
70
73
|
update_local_headers
|
71
74
|
write_central_directory
|
@@ -76,6 +79,7 @@ module Zip
|
|
76
79
|
# Closes the stream and writes the central directory to the zip file
|
77
80
|
def close_buffer
|
78
81
|
return @output_stream if @closed
|
82
|
+
|
79
83
|
finalize_current_entry
|
80
84
|
update_local_headers
|
81
85
|
write_central_directory
|
@@ -87,6 +91,7 @@ module Zip
|
|
87
91
|
# +entry+ can be a ZipEntry object or a string.
|
88
92
|
def put_next_entry(entry_name, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zip.default_compression)
|
89
93
|
raise Error, 'zip stream is closed' if @closed
|
94
|
+
|
90
95
|
new_entry = if entry_name.kind_of?(Entry)
|
91
96
|
entry_name
|
92
97
|
else
|
@@ -94,7 +99,7 @@ module Zip
|
|
94
99
|
end
|
95
100
|
new_entry.comment = comment unless comment.nil?
|
96
101
|
unless extra.nil?
|
97
|
-
new_entry.extra = extra.
|
102
|
+
new_entry.extra = extra.kind_of?(ExtraField) ? extra : ExtraField.new(extra.to_s)
|
98
103
|
end
|
99
104
|
new_entry.compression_method = compression_method unless compression_method.nil?
|
100
105
|
init_next_entry(new_entry, level)
|
@@ -104,7 +109,8 @@ module Zip
|
|
104
109
|
def copy_raw_entry(entry)
|
105
110
|
entry = entry.dup
|
106
111
|
raise Error, 'zip stream is closed' if @closed
|
107
|
-
raise Error, 'entry is not a ZipEntry' unless entry.
|
112
|
+
raise Error, 'entry is not a ZipEntry' unless entry.kind_of?(Entry)
|
113
|
+
|
108
114
|
finalize_current_entry
|
109
115
|
@entry_set << entry
|
110
116
|
src_pos = entry.local_header_offset
|
@@ -123,8 +129,11 @@ module Zip
|
|
123
129
|
|
124
130
|
def finalize_current_entry
|
125
131
|
return unless @current_entry
|
132
|
+
|
126
133
|
finish
|
127
|
-
@current_entry.compressed_size = @output_stream.tell -
|
134
|
+
@current_entry.compressed_size = @output_stream.tell - \
|
135
|
+
@current_entry.local_header_offset - \
|
136
|
+
@current_entry.calculate_local_header_size
|
128
137
|
@current_entry.size = @compressor.size
|
129
138
|
@current_entry.crc = @compressor.crc
|
130
139
|
@output_stream << @encrypter.data_descriptor(@current_entry.crc, @current_entry.compressed_size, @current_entry.size)
|
@@ -144,9 +153,9 @@ module Zip
|
|
144
153
|
|
145
154
|
def get_compressor(entry, level)
|
146
155
|
case entry.compression_method
|
147
|
-
when Entry::DEFLATED
|
156
|
+
when Entry::DEFLATED
|
148
157
|
::Zip::Deflater.new(@output_stream, level, @encrypter)
|
149
|
-
when Entry::STORED
|
158
|
+
when Entry::STORED
|
150
159
|
::Zip::PassThruCompressor.new(@output_stream)
|
151
160
|
else
|
152
161
|
raise ::Zip::CompressionMethodError,
|
@@ -6,7 +6,7 @@ module Zip
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def read(length = nil, outbuf = '')
|
9
|
-
return (
|
9
|
+
return (length.nil? || length.zero? ? '' : nil) if eof
|
10
10
|
|
11
11
|
if length.nil? || (@read_so_far + length) > decompressed_size
|
12
12
|
length = decompressed_size - @read_so_far
|
@@ -20,7 +20,7 @@ module Zip
|
|
20
20
|
@read_so_far >= decompressed_size
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
alias eof? eof
|
24
24
|
end
|
25
25
|
|
26
26
|
::Zip::Decompressor.register(::Zip::COMPRESSION_METHOD_STORE, ::Zip::PassThruDecompressor)
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Zip
|
2
2
|
class StreamableDirectory < Entry
|
3
|
-
def initialize(zipfile, entry,
|
3
|
+
def initialize(zipfile, entry, src_path = nil, permission = nil)
|
4
4
|
super(zipfile, entry)
|
5
5
|
|
6
6
|
@ftype = :directory
|
7
|
-
entry.get_extra_attributes_from_path(
|
8
|
-
@unix_perms =
|
7
|
+
entry.get_extra_attributes_from_path(src_path) if src_path
|
8
|
+
@unix_perms = permission if permission
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Zip
|
2
|
-
class StreamableStream < DelegateClass(Entry) # nodoc:all
|
2
|
+
class StreamableStream < DelegateClass(Entry) # :nodoc:all
|
3
3
|
def initialize(entry)
|
4
4
|
super(entry)
|
5
5
|
@temp_file = Tempfile.new(::File.basename(name))
|
@@ -22,6 +22,7 @@ module Zip
|
|
22
22
|
unless @temp_file.closed?
|
23
23
|
raise StandardError, "cannot open entry for reading while its open for writing - #{name}"
|
24
24
|
end
|
25
|
+
|
25
26
|
@temp_file.open # reopens tempfile from top
|
26
27
|
@temp_file.binmode
|
27
28
|
if block_given?
|
@@ -35,9 +36,9 @@ module Zip
|
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
|
-
def write_to_zip_output_stream(
|
39
|
-
|
40
|
-
get_input_stream { |is| ::Zip::IOExtras.copy_stream(
|
39
|
+
def write_to_zip_output_stream(output_stream)
|
40
|
+
output_stream.put_next_entry(self)
|
41
|
+
get_input_stream { |is| ::Zip::IOExtras.copy_stream(output_stream, is) }
|
41
42
|
end
|
42
43
|
|
43
44
|
def clean_up
|
data/lib/zip/version.rb
CHANGED
data/samples/example.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
$LOAD_PATH << '../lib'
|
4
4
|
system('zip example.zip example.rb gtk_ruby_zip.rb')
|
5
5
|
|
6
6
|
require 'zip'
|
@@ -71,7 +71,7 @@ puts "Zip file splitted in #{part_zips_count} parts"
|
|
71
71
|
|
72
72
|
# Track splitting an archive
|
73
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
|
74
|
+
puts "#{part_index} of #{part_count} part splitting: #{(chunk_bytes.to_f / segment_bytes * 100).to_i}%"
|
75
75
|
end
|
76
76
|
|
77
77
|
# For other examples, look at zip.rb and ziptest.rb
|
data/samples/gtk_ruby_zip.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
$LOAD_PATH << '../lib'
|
4
4
|
|
5
5
|
$VERBOSE = true
|
6
6
|
|
@@ -18,14 +18,14 @@ class MainApp < Gtk::Window
|
|
18
18
|
add(box)
|
19
19
|
|
20
20
|
@zipfile = nil
|
21
|
-
@
|
22
|
-
@
|
21
|
+
@button_panel = ButtonPanel.new
|
22
|
+
@button_panel.open_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) do
|
23
23
|
show_file_selector
|
24
24
|
end
|
25
|
-
@
|
25
|
+
@button_panel.extract_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) do
|
26
26
|
puts 'Not implemented!'
|
27
27
|
end
|
28
|
-
box.pack_start(@
|
28
|
+
box.pack_start(@button_panel, false, false, 0)
|
29
29
|
|
30
30
|
sw = Gtk::ScrolledWindow.new
|
31
31
|
sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
|
@@ -42,27 +42,27 @@ class MainApp < Gtk::Window
|
|
42
42
|
end
|
43
43
|
|
44
44
|
class ButtonPanel < Gtk::HButtonBox
|
45
|
-
attr_reader :
|
45
|
+
attr_reader :open_button, :extract_button
|
46
46
|
def initialize
|
47
47
|
super
|
48
48
|
set_layout(Gtk::BUTTONBOX_START)
|
49
49
|
set_spacing(0)
|
50
|
-
@
|
51
|
-
@
|
52
|
-
pack_start(@
|
53
|
-
pack_start(@
|
50
|
+
@open_button = Gtk::Button.new('Open archive')
|
51
|
+
@extract_button = Gtk::Button.new('Extract entry')
|
52
|
+
pack_start(@open_button)
|
53
|
+
pack_start(@extract_button)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
57
|
def show_file_selector
|
58
|
-
@
|
59
|
-
@
|
60
|
-
@
|
61
|
-
open_zip(@
|
62
|
-
@
|
58
|
+
@file_selector = Gtk::FileSelection.new('Open zip file')
|
59
|
+
@file_selector.show
|
60
|
+
@file_selector.ok_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) do
|
61
|
+
open_zip(@file_selector.filename)
|
62
|
+
@file_selector.destroy
|
63
63
|
end
|
64
|
-
@
|
65
|
-
@
|
64
|
+
@file_selector.cancel_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) do
|
65
|
+
@file_selector.destroy
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
@@ -77,8 +77,8 @@ class MainApp < Gtk::Window
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
|
80
|
+
main_app = MainApp.new
|
81
81
|
|
82
|
-
|
82
|
+
main_app.show_all
|
83
83
|
|
84
84
|
Gtk.main
|
data/samples/qtzip.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
$VERBOSE = true
|
4
4
|
|
5
|
-
|
5
|
+
$LOAD_PATH << '../lib'
|
6
6
|
|
7
7
|
require 'Qt'
|
8
8
|
system('rbuic -o zipdialogui.rb zipdialogui.ui')
|
@@ -20,12 +20,12 @@ class ZipDialog < ZipDialogUI
|
|
20
20
|
self, SLOT('extract_files()'))
|
21
21
|
end
|
22
22
|
|
23
|
-
def zipfile(&
|
24
|
-
Zip::File.open(@zip_filename, &
|
23
|
+
def zipfile(&a_proc)
|
24
|
+
Zip::File.open(@zip_filename, &a_proc)
|
25
25
|
end
|
26
26
|
|
27
|
-
def each(&
|
28
|
-
Zip::File.foreach(@zip_filename, &
|
27
|
+
def each(&a_proc)
|
28
|
+
Zip::File.foreach(@zip_filename, &a_proc)
|
29
29
|
end
|
30
30
|
|
31
31
|
def refresh
|
@@ -80,7 +80,7 @@ class ZipDialog < ZipDialogUI
|
|
80
80
|
end
|
81
81
|
|
82
82
|
unless ARGV[0]
|
83
|
-
puts "usage: #{$
|
83
|
+
puts "usage: #{$PROGRAM_NAME} zipname"
|
84
84
|
exit
|
85
85
|
end
|
86
86
|
|