rubyzip 1.0.0 → 1.2.0

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.

Files changed (107) hide show
  1. checksums.yaml +6 -14
  2. data/README.md +173 -42
  3. data/Rakefile +10 -5
  4. data/TODO +0 -1
  5. data/lib/zip/central_directory.rb +55 -24
  6. data/lib/zip/compressor.rb +0 -0
  7. data/lib/zip/constants.rb +4 -2
  8. data/lib/zip/crypto/encryption.rb +11 -0
  9. data/lib/zip/crypto/null_encryption.rb +45 -0
  10. data/lib/zip/crypto/traditional_encryption.rb +99 -0
  11. data/lib/zip/decompressor.rb +2 -2
  12. data/lib/zip/deflater.rb +11 -6
  13. data/lib/zip/dos_time.rb +4 -5
  14. data/lib/zip/entry.rb +159 -97
  15. data/lib/zip/entry_set.rb +18 -18
  16. data/lib/zip/errors.rb +15 -6
  17. data/lib/zip/extra_field/generic.rb +8 -8
  18. data/lib/zip/extra_field/ntfs.rb +90 -0
  19. data/lib/zip/extra_field/old_unix.rb +44 -0
  20. data/lib/zip/extra_field/universal_time.rb +14 -14
  21. data/lib/zip/extra_field/unix.rb +8 -9
  22. data/lib/zip/extra_field/zip64.rb +44 -6
  23. data/lib/zip/extra_field/zip64_placeholder.rb +16 -0
  24. data/lib/zip/extra_field.rb +20 -8
  25. data/lib/zip/file.rb +126 -114
  26. data/lib/zip/filesystem.rb +140 -139
  27. data/lib/zip/inflater.rb +10 -9
  28. data/lib/zip/input_stream.rb +105 -80
  29. data/lib/zip/ioextras/abstract_input_stream.rb +15 -12
  30. data/lib/zip/ioextras/abstract_output_stream.rb +0 -2
  31. data/lib/zip/ioextras.rb +1 -3
  32. data/lib/zip/null_compressor.rb +2 -2
  33. data/lib/zip/null_decompressor.rb +4 -4
  34. data/lib/zip/null_input_stream.rb +2 -1
  35. data/lib/zip/output_stream.rb +57 -43
  36. data/lib/zip/pass_thru_compressor.rb +4 -4
  37. data/lib/zip/pass_thru_decompressor.rb +4 -5
  38. data/lib/zip/streamable_directory.rb +2 -2
  39. data/lib/zip/streamable_stream.rb +22 -13
  40. data/lib/zip/version.rb +1 -1
  41. data/lib/zip.rb +11 -2
  42. data/samples/example.rb +30 -40
  43. data/samples/example_filesystem.rb +16 -18
  44. data/samples/example_recursive.rb +35 -27
  45. data/samples/{gtkRubyzip.rb → gtk_ruby_zip.rb} +25 -27
  46. data/samples/qtzip.rb +19 -28
  47. data/samples/write_simple.rb +12 -13
  48. data/samples/zipfind.rb +29 -37
  49. data/test/basic_zip_file_test.rb +60 -0
  50. data/test/case_sensitivity_test.rb +69 -0
  51. data/test/central_directory_entry_test.rb +69 -0
  52. data/test/central_directory_test.rb +100 -0
  53. data/test/crypto/null_encryption_test.rb +53 -0
  54. data/test/crypto/traditional_encryption_test.rb +80 -0
  55. data/test/data/WarnInvalidDate.zip +0 -0
  56. data/test/data/file1.txt +46 -0
  57. data/test/data/file1.txt.deflatedData +0 -0
  58. data/test/data/file2.txt +1504 -0
  59. data/test/data/globTest/foo/bar/baz/foo.txt +0 -0
  60. data/test/data/globTest/foo.txt +0 -0
  61. data/test/data/globTest/food.txt +0 -0
  62. data/test/data/globTest.zip +0 -0
  63. data/test/data/mimetype +1 -0
  64. data/test/data/notzippedruby.rb +7 -0
  65. data/test/data/ntfs.zip +0 -0
  66. data/test/data/oddExtraField.zip +0 -0
  67. data/test/data/rubycode.zip +0 -0
  68. data/test/data/rubycode2.zip +0 -0
  69. data/test/data/test.xls +0 -0
  70. data/test/data/testDirectory.bin +0 -0
  71. data/test/data/zip64-sample.zip +0 -0
  72. data/test/data/zipWithDirs.zip +0 -0
  73. data/test/data/zipWithEncryption.zip +0 -0
  74. data/test/deflater_test.rb +65 -0
  75. data/test/encryption_test.rb +42 -0
  76. data/test/entry_set_test.rb +152 -0
  77. data/test/entry_test.rb +163 -0
  78. data/test/errors_test.rb +34 -0
  79. data/test/extra_field_test.rb +76 -0
  80. data/test/file_extract_directory_test.rb +54 -0
  81. data/test/file_extract_test.rb +83 -0
  82. data/test/file_permissions_test.rb +69 -0
  83. data/test/file_split_test.rb +57 -0
  84. data/test/file_test.rb +563 -0
  85. data/test/filesystem/dir_iterator_test.rb +58 -0
  86. data/test/filesystem/directory_test.rb +121 -0
  87. data/test/filesystem/file_mutating_test.rb +88 -0
  88. data/test/filesystem/file_nonmutating_test.rb +508 -0
  89. data/test/filesystem/file_stat_test.rb +64 -0
  90. data/test/gentestfiles.rb +122 -0
  91. data/test/inflater_test.rb +14 -0
  92. data/test/input_stream_test.rb +182 -0
  93. data/test/ioextras/abstract_input_stream_test.rb +102 -0
  94. data/test/ioextras/abstract_output_stream_test.rb +106 -0
  95. data/test/ioextras/fake_io_test.rb +18 -0
  96. data/test/local_entry_test.rb +154 -0
  97. data/test/output_stream_test.rb +128 -0
  98. data/test/pass_thru_compressor_test.rb +30 -0
  99. data/test/pass_thru_decompressor_test.rb +14 -0
  100. data/test/samples/example_recursive_test.rb +37 -0
  101. data/test/settings_test.rb +95 -0
  102. data/test/test_helper.rb +221 -0
  103. data/test/unicode_file_names_and_comments_test.rb +50 -0
  104. data/test/zip64_full_test.rb +51 -0
  105. data/test/zip64_support_test.rb +14 -0
  106. metadata +198 -22
  107. data/NEWS +0 -182
@@ -1,43 +1,41 @@
1
1
  module Zip
2
- # ZipInputStream is the basic class for reading zip entries in a
3
- # zip file. It is possible to create a ZipInputStream object directly,
4
- # passing the zip file name to the constructor, but more often than not
5
- # the ZipInputStream will be obtained from a ZipFile (perhaps using the
6
- # ZipFileSystem interface) object for a particular entry in the zip
2
+ # InputStream is the basic class for reading zip entries in a
3
+ # zip file. It is possible to create a InputStream object directly,
4
+ # passing the zip file name to the constructor, but more often than not
5
+ # the InputStream will be obtained from a File (perhaps using the
6
+ # ZipFileSystem interface) object for a particular entry in the zip
7
7
  # archive.
8
8
  #
9
- # A ZipInputStream inherits IOExtras::AbstractInputStream in order
10
- # to provide an IO-like interface for reading from a single zip
11
- # entry. Beyond methods for mimicking an IO-object it contains
12
- # the method get_next_entry for iterating through the entries of
13
- # an archive. get_next_entry returns a ZipEntry object that describes
14
- # the zip entry the ZipInputStream is currently reading from.
9
+ # A InputStream inherits IOExtras::AbstractInputStream in order
10
+ # to provide an IO-like interface for reading from a single zip
11
+ # entry. Beyond methods for mimicking an IO-object it contains
12
+ # the method get_next_entry for iterating through the entries of
13
+ # an archive. get_next_entry returns a Entry object that describes
14
+ # the zip entry the InputStream is currently reading from.
15
15
  #
16
- # Example that creates a zip archive with ZipOutputStream and reads it
17
- # back again with a ZipInputStream.
16
+ # Example that creates a zip archive with ZipOutputStream and reads it
17
+ # back again with a InputStream.
18
+ #
19
+ # require 'zip'
20
+ #
21
+ # Zip::OutputStream.open("my.zip") do |io|
18
22
  #
19
- # require 'zip/zip'
20
- #
21
- # Zip::ZipOutputStream::open("my.zip") {
22
- # |io|
23
- #
24
23
  # io.put_next_entry("first_entry.txt")
25
24
  # io.write "Hello world!"
26
- #
25
+ #
27
26
  # io.put_next_entry("adir/first_entry.txt")
28
27
  # io.write "Hello again!"
29
- # }
28
+ # end
29
+ #
30
+ #
31
+ # Zip::InputStream.open("my.zip") do |io|
30
32
  #
31
- #
32
- # Zip::ZipInputStream::open("my.zip") {
33
- # |io|
34
- #
35
33
  # while (entry = io.get_next_entry)
36
34
  # puts "Contents of #{entry.name}: '#{io.read}'"
37
35
  # end
38
- # }
36
+ # end
39
37
  #
40
- # java.util.zip.ZipInputStream is the original inspiration for this
38
+ # java.util.zip.ZipInputStream is the original inspiration for this
41
39
  # class.
42
40
 
43
41
  class InputStream
@@ -46,88 +44,115 @@ module Zip
46
44
  # Opens the indicated zip file. An exception is thrown
47
45
  # if the specified offset in the specified filename is
48
46
  # not a local zip entry header.
49
- def initialize(filename, offset = 0, io = nil)
47
+ #
48
+ # @param context [String||IO||StringIO] file path or IO/StringIO object
49
+ # @param offset [Integer] offset in the IO/StringIO
50
+ def initialize(context, offset = 0, decrypter = nil)
50
51
  super()
51
- if (io.nil?)
52
- @archiveIO = ::File.open(filename, "rb")
53
- @archiveIO.seek(offset, IO::SEEK_SET)
54
- else
55
- @archiveIO = io
56
- end
57
- @decompressor = NullDecompressor.instance
58
- @currentEntry = nil
59
- end
60
-
61
- def close
62
- @archiveIO.close
63
- end
64
-
65
- # Same as #initialize but if a block is passed the opened
66
- # stream is passed to the block and closed when the block
67
- # returns.
68
- def InputStream.open(filename)
69
- return new(filename) unless block_given?
70
-
71
- zio = new(filename)
72
- yield zio
73
- ensure
74
- zio.close if zio
52
+ @archive_io = get_io(context, offset)
53
+ @decompressor = ::Zip::NullDecompressor
54
+ @decrypter = decrypter || ::Zip::NullDecrypter.new
55
+ @current_entry = nil
75
56
  end
76
57
 
77
- def InputStream.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
58
+ def close
59
+ @archive_io.close
83
60
  end
84
61
 
85
- # Returns a ZipEntry object. It is necessary to call this
86
- # method on a newly created ZipInputStream before reading from
87
- # the first entry in the archive. Returns nil when there are
62
+ # Returns a Entry object. It is necessary to call this
63
+ # method on a newly created InputStream before reading from
64
+ # the first entry in the archive. Returns nil when there are
88
65
  # no more entries.
89
-
90
66
  def get_next_entry
91
- @archiveIO.seek(@currentEntry.next_header_offset, IO::SEEK_SET) if @currentEntry
67
+ @archive_io.seek(@current_entry.next_header_offset, IO::SEEK_SET) if @current_entry
92
68
  open_entry
93
69
  end
94
70
 
95
71
  # Rewinds the stream to the beginning of the current entry
96
72
  def rewind
97
- return if @currentEntry.nil?
73
+ return if @current_entry.nil?
98
74
  @lineno = 0
99
- @pos = 0
100
- @archiveIO.seek(@currentEntry.local_header_offset,
101
- IO::SEEK_SET)
75
+ @pos = 0
76
+ @archive_io.seek(@current_entry.local_header_offset, IO::SEEK_SET)
102
77
  open_entry
103
78
  end
104
79
 
105
80
  # Modeled after IO.sysread
106
- def sysread(numberOfBytes = nil, buf = nil)
107
- @decompressor.sysread(numberOfBytes, buf)
81
+ def sysread(number_of_bytes = nil, buf = nil)
82
+ @decompressor.sysread(number_of_bytes, buf)
108
83
  end
109
84
 
110
85
  def eof
111
86
  @output_buffer.empty? && @decompressor.eof
112
87
  end
113
- alias :eof? :eof
88
+
89
+ alias :eof? eof
90
+
91
+ class << self
92
+ # Same as #initialize but if a block is passed the opened
93
+ # stream is passed to the block and closed when the block
94
+ # returns.
95
+ def open(filename_or_io, offset = 0, decrypter = nil)
96
+ zio = new(filename_or_io, offset, decrypter)
97
+ return zio unless block_given?
98
+ begin
99
+ yield zio
100
+ ensure
101
+ zio.close if zio
102
+ end
103
+ end
104
+
105
+ def open_buffer(filename_or_io, offset = 0)
106
+ puts 'open_buffer is deprecated!!! Use open instead!'
107
+ open(filename_or_io, offset)
108
+ end
109
+ end
114
110
 
115
111
  protected
116
112
 
117
- def open_entry
118
- @currentEntry = Entry.read_local_entry(@archiveIO)
119
- if @currentEntry.nil?
120
- @decompressor = NullDecompressor.instance
121
- elsif @currentEntry.compression_method == Entry::STORED
122
- @decompressor = PassThruDecompressor.new(@archiveIO, @currentEntry.size)
123
- elsif @currentEntry.compression_method == Entry::DEFLATED
124
- @decompressor = Inflater.new(@archiveIO)
113
+ def get_io(io_or_file, offset = 0)
114
+ if io_or_file.respond_to?(:seek)
115
+ io = io_or_file.dup
116
+ io.seek(offset, ::IO::SEEK_SET)
117
+ io
125
118
  else
126
- raise ZipCompressionMethodError,
127
- "Unsupported compression method #{@currentEntry.compression_method}"
119
+ file = ::File.open(io_or_file, 'rb')
120
+ file.seek(offset, ::IO::SEEK_SET)
121
+ file
122
+ end
123
+ end
124
+
125
+ def open_entry
126
+ @current_entry = ::Zip::Entry.read_local_entry(@archive_io)
127
+ if @current_entry && @current_entry.gp_flags & 1 == 1 && @decrypter.is_a?(NullEncrypter)
128
+ raise Error, 'password required to decode zip file'
128
129
  end
130
+ if @current_entry && @current_entry.gp_flags & 8 == 8 && @current_entry.crc == 0 \
131
+ && @current_entry.compressed_size == 0 \
132
+ && @current_entry.size == 0 && !@internal
133
+ raise GPFBit3Error,
134
+ 'General purpose flag Bit 3 is set so not possible to get proper info from local header.' \
135
+ 'Please use ::Zip::File instead of ::Zip::InputStream'
136
+ end
137
+ @decompressor = get_decompressor
129
138
  flush
130
- return @currentEntry
139
+ @current_entry
140
+ end
141
+
142
+ def get_decompressor
143
+ case
144
+ when @current_entry.nil?
145
+ ::Zip::NullDecompressor
146
+ when @current_entry.compression_method == ::Zip::Entry::STORED
147
+ ::Zip::PassThruDecompressor.new(@archive_io, @current_entry.size)
148
+ when @current_entry.compression_method == ::Zip::Entry::DEFLATED
149
+ header = @archive_io.read(@decrypter.header_bytesize)
150
+ @decrypter.reset!(header)
151
+ ::Zip::Inflater.new(@archive_io, @decrypter)
152
+ else
153
+ raise ::Zip::CompressionMethodError,
154
+ "Unsupported compression method #{@current_entry.compression_method}"
155
+ end
131
156
  end
132
157
 
133
158
  def produce_input
@@ -17,7 +17,7 @@ module Zip
17
17
  attr_accessor :lineno
18
18
  attr_reader :pos
19
19
 
20
- def read(number_of_bytes = nil, buf = nil)
20
+ def read(number_of_bytes = nil, buf = '')
21
21
  tbuf = if @output_buffer.bytesize > 0
22
22
  if number_of_bytes <= @output_buffer.bytesize
23
23
  @output_buffer.slice!(0, number_of_bytes)
@@ -33,9 +33,12 @@ module Zip
33
33
  sysread(number_of_bytes, buf)
34
34
  end
35
35
 
36
- @pos += tbuf.length
36
+ if tbuf.nil? || tbuf.length == 0
37
+ return nil if number_of_bytes
38
+ return ''
39
+ end
37
40
 
38
- return nil unless tbuf
41
+ @pos += tbuf.length
39
42
 
40
43
  if buf
41
44
  buf.replace(tbuf)
@@ -72,15 +75,17 @@ module Zip
72
75
  over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
73
76
  while (match_index = @output_buffer.index(a_sep_string, buffer_index)).nil? && !over_limit
74
77
  buffer_index = [buffer_index, @output_buffer.bytesize - a_sep_string.bytesize].max
75
- if input_finished?
76
- return @output_buffer.empty? ? nil : flush
77
- end
78
+ return @output_buffer.empty? ? nil : flush if input_finished?
78
79
  @output_buffer << produce_input
79
80
  over_limit = (number_of_bytes && @output_buffer.bytesize >= number_of_bytes)
80
81
  end
81
82
  sep_index = [match_index + a_sep_string.bytesize, number_of_bytes || @output_buffer.bytesize].min
82
- @pos += sep_index
83
- return @output_buffer.slice!(0...sep_index)
83
+ @pos += sep_index
84
+ @output_buffer.slice!(0...sep_index)
85
+ end
86
+
87
+ def ungetc(byte)
88
+ @output_buffer = byte.chr + @output_buffer
84
89
  end
85
90
 
86
91
  def flush
@@ -96,13 +101,11 @@ module Zip
96
101
  end
97
102
 
98
103
  def each_line(a_sep_string = $/)
99
- while true
100
- yield readline(a_sep_string)
101
- end
104
+ yield readline(a_sep_string) while true
102
105
  rescue EOFError
103
106
  end
104
107
 
105
108
  alias_method :each, :each_line
106
109
  end
107
110
  end
108
- end
111
+ end
@@ -10,7 +10,6 @@ module Zip
10
10
  data.to_s.bytesize
11
11
  end
12
12
 
13
-
14
13
  def print(*params)
15
14
  self << params.join($,) << $\.to_s
16
15
  end
@@ -39,7 +38,6 @@ module Zip
39
38
  self << "\n" unless val[-1, 1] == "\n"
40
39
  end
41
40
  end
42
-
43
41
  end
44
42
  end
45
43
  end
data/lib/zip/ioextras.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  module Zip
2
2
  module IOExtras #:nodoc:
3
-
4
- CHUNK_SIZE = 131072
3
+ CHUNK_SIZE = 131_072
5
4
 
6
5
  RANGE_ALL = 0..-1
7
6
 
@@ -26,7 +25,6 @@ module Zip
26
25
  object == IO || super
27
26
  end
28
27
  end
29
-
30
28
  end # IOExtras namespace module
31
29
  end
32
30
 
@@ -2,8 +2,8 @@ module Zip
2
2
  class NullCompressor < Compressor #:nodoc:all
3
3
  include Singleton
4
4
 
5
- def <<(data)
6
- raise IOError, "closed stream"
5
+ def <<(_data)
6
+ raise IOError, 'closed stream'
7
7
  end
8
8
 
9
9
  attr_reader :size, :compressed_size
@@ -1,8 +1,8 @@
1
1
  module Zip
2
- class NullDecompressor #:nodoc:all
3
- include Singleton
2
+ module NullDecompressor #:nodoc:all
3
+ module_function
4
4
 
5
- def sysread(numberOfBytes = nil, buf = nil)
5
+ def sysread(_numberOfBytes = nil, _buf = nil)
6
6
  nil
7
7
  end
8
8
 
@@ -18,7 +18,7 @@ module Zip
18
18
  true
19
19
  end
20
20
 
21
- alias :eof? :eof
21
+ alias eof? eof
22
22
  end
23
23
  end
24
24
 
@@ -1,5 +1,6 @@
1
1
  module Zip
2
- class NullInputStream < NullDecompressor #:nodoc:all
2
+ module NullInputStream #:nodoc:all
3
+ include ::Zip::NullDecompressor
3
4
  include ::Zip::IOExtras::AbstractInputStream
4
5
  end
5
6
  end
@@ -24,18 +24,22 @@ module Zip
24
24
 
25
25
  # Opens the indicated zip file. If a file with that name already
26
26
  # exists it will be overwritten.
27
- def initialize(fileName, stream=false)
27
+ def initialize(file_name, stream = false, encrypter = nil)
28
28
  super()
29
- @fileName = fileName
30
- if stream
31
- @output_stream = ::StringIO.new
32
- else
33
- @output_stream = ::File.new(@fileName, "wb")
34
- end
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
35
38
  @entry_set = ::Zip::EntrySet.new
36
39
  @compressor = ::Zip::NullCompressor.instance
40
+ @encrypter = encrypter || ::Zip::NullEncrypter.new
37
41
  @closed = false
38
- @currentEntry = nil
42
+ @current_entry = nil
39
43
  @comment = nil
40
44
  end
41
45
 
@@ -43,19 +47,19 @@ module Zip
43
47
  # stream is passed to the block and closed when the block
44
48
  # returns.
45
49
  class << self
46
- def open(fileName)
47
- return new(fileName) unless block_given?
48
- zos = new(fileName)
50
+ def open(file_name, encrypter = nil)
51
+ return new(file_name) unless block_given?
52
+ zos = new(file_name, false, encrypter)
49
53
  yield zos
50
54
  ensure
51
55
  zos.close if zos
52
56
  end
53
57
 
54
- # Same as #open but writes to a filestream instead
55
- def write_buffer
56
- zos = new('', true)
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)
57
61
  yield zos
58
- return zos.close_buffer
62
+ zos.close_buffer
59
63
  end
60
64
  end
61
65
 
@@ -79,66 +83,74 @@ module Zip
79
83
  @output_stream
80
84
  end
81
85
 
82
- # Closes the current entry and opens a new for writing.
86
+ # Closes the current entry and opens a new for writing.
83
87
  # +entry+ can be a ZipEntry object or a string.
84
- def put_next_entry(entryname, comment = nil, extra = nil, compression_method = Entry::DEFLATED, level = Zlib::DEFAULT_COMPRESSION)
85
- raise ZipError, "zip stream is closed" if @closed
86
- if entryname.kind_of?(Entry)
87
- new_entry = entryname
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
+ if entry_name.kind_of?(Entry)
91
+ new_entry = entry_name
88
92
  else
89
- new_entry = Entry.new(@fileName, entryname.to_s)
93
+ new_entry = Entry.new(@file_name, entry_name.to_s)
90
94
  end
91
- new_entry.comment = comment if !comment.nil?
92
- if (!extra.nil?)
93
- new_entry.extra = ExtraField === extra ? extra : ExtraField.new(extra.to_s)
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)
94
98
  end
95
- new_entry.compression_method = compression_method if !compression_method.nil?
99
+ new_entry.compression_method = compression_method unless compression_method.nil?
96
100
  init_next_entry(new_entry, level)
97
- @currentEntry = new_entry
101
+ @current_entry = new_entry
98
102
  end
99
103
 
100
104
  def copy_raw_entry(entry)
101
105
  entry = entry.dup
102
- raise ZipError, "zip stream is closed" if @closed
103
- raise ZipError, "entry is not a ZipEntry" if !entry.kind_of?(Entry)
106
+ raise Error, 'zip stream is closed' if @closed
107
+ raise Error, 'entry is not a ZipEntry' unless entry.is_a?(Entry)
104
108
  finalize_current_entry
105
109
  @entry_set << entry
106
- src_pos = entry.local_entry_offset
110
+ src_pos = entry.local_header_offset
107
111
  entry.write_local_entry(@output_stream)
108
112
  @compressor = NullCompressor.instance
109
113
  entry.get_raw_input_stream do |is|
110
114
  is.seek(src_pos, IO::SEEK_SET)
115
+ ::Zip::Entry.read_local_entry(is)
111
116
  IOExtras.copy_stream_n(@output_stream, is, entry.compressed_size)
112
117
  end
113
118
  @compressor = NullCompressor.instance
114
- @currentEntry = nil
119
+ @current_entry = nil
115
120
  end
116
121
 
117
122
  private
118
123
 
119
124
  def finalize_current_entry
120
- return unless @currentEntry
125
+ return unless @current_entry
121
126
  finish
122
- @currentEntry.compressed_size = @output_stream.tell - @currentEntry.local_header_offset - @currentEntry.calculate_local_header_size
123
- @currentEntry.size = @compressor.size
124
- @currentEntry.crc = @compressor.crc
125
- @currentEntry = nil
126
- @compressor = NullCompressor.instance
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
127
134
  end
128
135
 
129
- def init_next_entry(entry, level = Zlib::DEFAULT_COMPRESSION)
136
+ def init_next_entry(entry, level = Zip.default_compression)
130
137
  finalize_current_entry
131
138
  @entry_set << entry
132
139
  entry.write_local_entry(@output_stream)
140
+ @encrypter.reset!
141
+ @output_stream << @encrypter.header(entry.mtime)
133
142
  @compressor = get_compressor(entry, level)
134
143
  end
135
144
 
136
145
  def get_compressor(entry, level)
137
146
  case entry.compression_method
138
- when Entry::DEFLATED then Deflater.new(@output_stream, level)
139
- when Entry::STORED then PassThruCompressor.new(@output_stream)
140
- else raise ZipCompressionMethodError,
141
- "Invalid compression method: '#{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}'"
142
154
  end
143
155
  end
144
156
 
@@ -146,7 +158,7 @@ module Zip
146
158
  pos = @output_stream.pos
147
159
  @entry_set.each do |entry|
148
160
  @output_stream.pos = entry.local_header_offset
149
- entry.write_local_entry(@output_stream)
161
+ entry.write_local_entry(@output_stream, true)
150
162
  end
151
163
  @output_stream.pos = pos
152
164
  end
@@ -163,9 +175,11 @@ module Zip
163
175
  end
164
176
 
165
177
  public
178
+
166
179
  # Modeled after IO.<<
167
- def << (data)
180
+ def <<(data)
168
181
  @compressor << data
182
+ self
169
183
  end
170
184
  end
171
185
  end
@@ -3,13 +3,13 @@ module Zip
3
3
  def initialize(outputStream)
4
4
  super()
5
5
  @output_stream = outputStream
6
- @crc = Zlib::crc32
6
+ @crc = Zlib.crc32
7
7
  @size = 0
8
8
  end
9
-
10
- def << (data)
9
+
10
+ def <<(data)
11
11
  val = data.to_s
12
- @crc = Zlib::crc32(val, @crc)
12
+ @crc = Zlib.crc32(val, @crc)
13
13
  @size += val.bytesize
14
14
  @output_stream << val
15
15
  end
@@ -1,6 +1,5 @@
1
1
  module Zip
2
2
  class PassThruDecompressor < Decompressor #:nodoc:all
3
-
4
3
  def initialize(input_stream, chars_to_read)
5
4
  super(input_stream)
6
5
  @chars_to_read = chars_to_read
@@ -8,7 +7,7 @@ module Zip
8
7
  @has_returned_empty_string = false
9
8
  end
10
9
 
11
- def sysread(number_of_bytes = nil, buf = nil)
10
+ def sysread(number_of_bytes = nil, buf = '')
12
11
  if input_finished?
13
12
  has_returned_empty_string_val = @has_returned_empty_string
14
13
  @has_returned_empty_string = true
@@ -16,7 +15,7 @@ module Zip
16
15
  return
17
16
  end
18
17
 
19
- if (number_of_bytes == nil || @read_so_far + number_of_bytes > @chars_to_read)
18
+ if number_of_bytes.nil? || @read_so_far + number_of_bytes > @chars_to_read
20
19
  number_of_bytes = @chars_to_read - @read_so_far
21
20
  end
22
21
  @read_so_far += number_of_bytes
@@ -31,8 +30,8 @@ module Zip
31
30
  @read_so_far >= @chars_to_read
32
31
  end
33
32
 
34
- alias :eof :input_finished?
35
- alias :eof? :input_finished?
33
+ alias eof input_finished?
34
+ alias eof? input_finished?
36
35
  end
37
36
  end
38
37
 
@@ -4,8 +4,8 @@ module Zip
4
4
  super(zipfile, entry)
5
5
 
6
6
  @ftype = :directory
7
- entry.get_extra_attributes_from_path(srcPath) if (srcPath)
8
- @unix_perms = permissionInt if (permissionInt)
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