archive-zip 0.11.0 → 0.13.0.pre1

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.
Files changed (133) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/NEWS.md +12 -0
  4. data/README.md +2 -1
  5. data/lib/archive/support/ioextensions.rb +5 -7
  6. data/lib/archive/support/iowindow.rb +34 -87
  7. data/lib/archive/support/stringio.rb +27 -0
  8. data/lib/archive/support/zlib.rb +0 -435
  9. data/lib/archive/zip/codec/deflate/reader.rb +187 -0
  10. data/lib/archive/zip/codec/deflate/writer.rb +209 -0
  11. data/lib/archive/zip/codec/deflate.rb +92 -244
  12. data/lib/archive/zip/codec/null_encryption.rb +4 -184
  13. data/lib/archive/zip/codec/store/reader.rb +97 -0
  14. data/lib/archive/zip/codec/store/writer.rb +78 -0
  15. data/lib/archive/zip/codec/store.rb +6 -231
  16. data/lib/archive/zip/codec/traditional_encryption/base.rb +85 -0
  17. data/lib/archive/zip/codec/traditional_encryption/reader.rb +65 -0
  18. data/lib/archive/zip/codec/traditional_encryption/writer.rb +71 -0
  19. data/lib/archive/zip/codec/traditional_encryption.rb +6 -360
  20. data/lib/archive/zip/codec.rb +2 -2
  21. data/lib/archive/zip/dos_time.rb +103 -0
  22. data/lib/archive/zip/entry.rb +86 -70
  23. data/lib/archive/zip.rb +2 -5
  24. metadata +37 -227
  25. data/.yardopts +0 -1
  26. data/Rakefile +0 -247
  27. data/lib/archive/support/binary_stringio.rb +0 -30
  28. data/lib/archive/support/integer.rb +0 -13
  29. data/lib/archive/support/io-like.rb +0 -14
  30. data/lib/archive/support/time.rb +0 -119
  31. data/lib/archive/zip/version.rb +0 -6
  32. data/spec/archive/dos_time_spec.rb +0 -113
  33. data/spec/archive/zip/archive_spec.rb +0 -54
  34. data/spec/archive/zip/codec/deflate/compress/checksum_spec.rb +0 -44
  35. data/spec/archive/zip/codec/deflate/compress/close_spec.rb +0 -45
  36. data/spec/archive/zip/codec/deflate/compress/crc32_spec.rb +0 -23
  37. data/spec/archive/zip/codec/deflate/compress/data_descriptor_spec.rb +0 -74
  38. data/spec/archive/zip/codec/deflate/compress/new_spec.rb +0 -39
  39. data/spec/archive/zip/codec/deflate/compress/open_spec.rb +0 -48
  40. data/spec/archive/zip/codec/deflate/compress/write_spec.rb +0 -111
  41. data/spec/archive/zip/codec/deflate/decompress/checksum_spec.rb +0 -20
  42. data/spec/archive/zip/codec/deflate/decompress/close_spec.rb +0 -34
  43. data/spec/archive/zip/codec/deflate/decompress/crc32_spec.rb +0 -20
  44. data/spec/archive/zip/codec/deflate/decompress/data_descriptor_spec.rb +0 -74
  45. data/spec/archive/zip/codec/deflate/decompress/new_spec.rb +0 -16
  46. data/spec/archive/zip/codec/deflate/decompress/open_spec.rb +0 -29
  47. data/spec/archive/zip/codec/deflate/fixtures/classes.rb +0 -25
  48. data/spec/archive/zip/codec/deflate/fixtures/compressed_file.bin +0 -1
  49. data/spec/archive/zip/codec/deflate/fixtures/compressed_file_nocomp.bin +0 -0
  50. data/spec/archive/zip/codec/deflate/fixtures/raw_file.txt +0 -10
  51. data/spec/archive/zip/codec/null_encryption/decrypt/close_spec.rb +0 -34
  52. data/spec/archive/zip/codec/null_encryption/decrypt/new_spec.rb +0 -16
  53. data/spec/archive/zip/codec/null_encryption/decrypt/open_spec.rb +0 -29
  54. data/spec/archive/zip/codec/null_encryption/decrypt/read_spec.rb +0 -26
  55. data/spec/archive/zip/codec/null_encryption/decrypt/rewind_spec.rb +0 -27
  56. data/spec/archive/zip/codec/null_encryption/decrypt/seek_spec.rb +0 -59
  57. data/spec/archive/zip/codec/null_encryption/decrypt/tell_spec.rb +0 -23
  58. data/spec/archive/zip/codec/null_encryption/encrypt/close_spec.rb +0 -34
  59. data/spec/archive/zip/codec/null_encryption/encrypt/new_spec.rb +0 -16
  60. data/spec/archive/zip/codec/null_encryption/encrypt/open_spec.rb +0 -31
  61. data/spec/archive/zip/codec/null_encryption/encrypt/rewind_spec.rb +0 -28
  62. data/spec/archive/zip/codec/null_encryption/encrypt/seek_spec.rb +0 -52
  63. data/spec/archive/zip/codec/null_encryption/encrypt/tell_spec.rb +0 -31
  64. data/spec/archive/zip/codec/null_encryption/encrypt/write_spec.rb +0 -31
  65. data/spec/archive/zip/codec/null_encryption/fixtures/classes.rb +0 -12
  66. data/spec/archive/zip/codec/null_encryption/fixtures/raw_file.txt +0 -10
  67. data/spec/archive/zip/codec/store/compress/close_spec.rb +0 -34
  68. data/spec/archive/zip/codec/store/compress/data_descriptor_spec.rb +0 -77
  69. data/spec/archive/zip/codec/store/compress/new_spec.rb +0 -16
  70. data/spec/archive/zip/codec/store/compress/open_spec.rb +0 -29
  71. data/spec/archive/zip/codec/store/compress/rewind_spec.rb +0 -28
  72. data/spec/archive/zip/codec/store/compress/seek_spec.rb +0 -52
  73. data/spec/archive/zip/codec/store/compress/tell_spec.rb +0 -31
  74. data/spec/archive/zip/codec/store/compress/write_spec.rb +0 -29
  75. data/spec/archive/zip/codec/store/decompress/close_spec.rb +0 -34
  76. data/spec/archive/zip/codec/store/decompress/data_descriptor_spec.rb +0 -75
  77. data/spec/archive/zip/codec/store/decompress/new_spec.rb +0 -16
  78. data/spec/archive/zip/codec/store/decompress/open_spec.rb +0 -29
  79. data/spec/archive/zip/codec/store/decompress/read_spec.rb +0 -26
  80. data/spec/archive/zip/codec/store/decompress/rewind_spec.rb +0 -27
  81. data/spec/archive/zip/codec/store/decompress/seek_spec.rb +0 -59
  82. data/spec/archive/zip/codec/store/decompress/tell_spec.rb +0 -23
  83. data/spec/archive/zip/codec/store/fixtures/classes.rb +0 -12
  84. data/spec/archive/zip/codec/store/fixtures/raw_file.txt +0 -10
  85. data/spec/archive/zip/codec/traditional_encryption/decrypt/close_spec.rb +0 -53
  86. data/spec/archive/zip/codec/traditional_encryption/decrypt/new_spec.rb +0 -20
  87. data/spec/archive/zip/codec/traditional_encryption/decrypt/open_spec.rb +0 -43
  88. data/spec/archive/zip/codec/traditional_encryption/decrypt/read_spec.rb +0 -127
  89. data/spec/archive/zip/codec/traditional_encryption/decrypt/rewind_spec.rb +0 -36
  90. data/spec/archive/zip/codec/traditional_encryption/decrypt/seek_spec.rb +0 -80
  91. data/spec/archive/zip/codec/traditional_encryption/decrypt/tell_spec.rb +0 -27
  92. data/spec/archive/zip/codec/traditional_encryption/encrypt/close_spec.rb +0 -53
  93. data/spec/archive/zip/codec/traditional_encryption/encrypt/new_spec.rb +0 -20
  94. data/spec/archive/zip/codec/traditional_encryption/encrypt/open_spec.rb +0 -41
  95. data/spec/archive/zip/codec/traditional_encryption/encrypt/rewind_spec.rb +0 -39
  96. data/spec/archive/zip/codec/traditional_encryption/encrypt/seek_spec.rb +0 -73
  97. data/spec/archive/zip/codec/traditional_encryption/encrypt/tell_spec.rb +0 -40
  98. data/spec/archive/zip/codec/traditional_encryption/encrypt/write_spec.rb +0 -114
  99. data/spec/archive/zip/codec/traditional_encryption/fixtures/classes.rb +0 -27
  100. data/spec/archive/zip/codec/traditional_encryption/fixtures/encrypted_file.bin +0 -0
  101. data/spec/archive/zip/codec/traditional_encryption/fixtures/raw_file.txt +0 -10
  102. data/spec/binary_stringio/new_spec.rb +0 -40
  103. data/spec/binary_stringio/set_encoding_spec.rb +0 -17
  104. data/spec/ioextensions/read_exactly_spec.rb +0 -52
  105. data/spec/zlib/fixtures/classes.rb +0 -65
  106. data/spec/zlib/fixtures/compressed_file.bin +0 -1
  107. data/spec/zlib/fixtures/compressed_file_gzip.bin +0 -0
  108. data/spec/zlib/fixtures/compressed_file_huffman.bin +0 -2
  109. data/spec/zlib/fixtures/compressed_file_minmem.bin +0 -0
  110. data/spec/zlib/fixtures/compressed_file_minwin.bin +0 -1
  111. data/spec/zlib/fixtures/compressed_file_nocomp.bin +0 -0
  112. data/spec/zlib/fixtures/compressed_file_raw.bin +0 -1
  113. data/spec/zlib/fixtures/raw_file.txt +0 -10
  114. data/spec/zlib/zreader/checksum_spec.rb +0 -42
  115. data/spec/zlib/zreader/close_spec.rb +0 -16
  116. data/spec/zlib/zreader/compressed_size_spec.rb +0 -20
  117. data/spec/zlib/zreader/new_spec.rb +0 -43
  118. data/spec/zlib/zreader/open_spec.rb +0 -51
  119. data/spec/zlib/zreader/read_spec.rb +0 -58
  120. data/spec/zlib/zreader/rewind_spec.rb +0 -25
  121. data/spec/zlib/zreader/seek_spec.rb +0 -57
  122. data/spec/zlib/zreader/tell_spec.rb +0 -23
  123. data/spec/zlib/zreader/uncompressed_size_spec.rb +0 -20
  124. data/spec/zlib/zwriter/checksum_spec.rb +0 -43
  125. data/spec/zlib/zwriter/close_spec.rb +0 -16
  126. data/spec/zlib/zwriter/compressed_size_spec.rb +0 -21
  127. data/spec/zlib/zwriter/new_spec.rb +0 -66
  128. data/spec/zlib/zwriter/open_spec.rb +0 -70
  129. data/spec/zlib/zwriter/rewind_spec.rb +0 -28
  130. data/spec/zlib/zwriter/seek_spec.rb +0 -52
  131. data/spec/zlib/zwriter/tell_spec.rb +0 -31
  132. data/spec/zlib/zwriter/uncompressed_size_spec.rb +0 -21
  133. data/spec/zlib/zwriter/write_spec.rb +0 -28
@@ -2,8 +2,6 @@
2
2
 
3
3
  require 'zlib'
4
4
 
5
- require 'archive/support/io-like'
6
-
7
5
  module Zlib # :nodoc:
8
6
  # The maximum size of the zlib history buffer. Note that zlib allows larger
9
7
  # values to enable different inflate modes. See Zlib::Inflate.new for details.
@@ -19,437 +17,4 @@ module Zlib # :nodoc:
19
17
  # simpler decoder to be used to inflate. Provided here only for Ruby versions
20
18
  # that do not provide it.
21
19
  FIXED = 4 unless const_defined?(:FIXED)
22
-
23
- # Zlib::ZWriter is a writable, IO-like object (includes IO::Like) which wraps
24
- # other writable, IO-like objects in order to facilitate writing data to those
25
- # objects using the deflate method of compression.
26
- class ZWriter
27
- include IO::Like
28
-
29
- # Creates a new instance of this class with the given arguments using #new
30
- # and then passes the instance to the given block. The #close method is
31
- # guaranteed to be called after the block completes.
32
- #
33
- # Equivalent to #new if no block is given.
34
- def self.open(delegate, level = nil, window_bits = nil, mem_level = nil, strategy = nil)
35
- zw = new(delegate, level, window_bits, mem_level, strategy)
36
- return zw unless block_given?
37
-
38
- begin
39
- yield(zw)
40
- ensure
41
- zw.close unless zw.closed?
42
- end
43
- end
44
-
45
- # Creates a new instance of this class. _delegate_ must respond to the
46
- # _write_ method as an instance of IO would. _level_, _window_bits_,
47
- # _mem_level_, and _strategy_ are all passed directly to
48
- # Zlib::Deflate.new().
49
- #
50
- # <b>
51
- # The following descriptions of _level_, _window_bits_, _mem_level_, and
52
- # _strategy_ are based upon or pulled largely verbatim from descriptions
53
- # found in zlib.h version 1.2.3 with changes made to account for different
54
- # parameter names and to improve readability. Some of the statements
55
- # concerning default settings or value ranges may not be accurate depending
56
- # on the version of the zlib library used by a given Ruby interpreter.
57
- # </b>
58
- #
59
- # The _level_ parameter must be +nil+, Zlib::DEFAULT_COMPRESSION, or between
60
- # <tt>0</tt> and <tt>9</tt>: <tt>1</tt> gives best speed, <tt>9</tt> gives
61
- # best compression, <tt>0</tt> gives no compression at all (the input data
62
- # is simply copied a block at a time). Zlib::DEFAULT_COMPRESSION requests a
63
- # default compromise between speed and compression (currently equivalent to
64
- # level <tt>6</tt>). If unspecified or +nil+, _level_ defaults to
65
- # Zlib::DEFAULT_COMPRESSION.
66
- #
67
- # The _window_bits_ parameter specifies the size of the history buffer, the
68
- # format of the compressed stream, and the kind of checksum returned by the
69
- # checksum method. The size of the history buffer is specified by setting
70
- # the value of _window_bits_ in the range of <tt>8</tt>..<tt>15</tt>,
71
- # inclusive. A value of <tt>8</tt> indicates a small window which reduces
72
- # memory usage but lowers the compression ratio while a value of <tt>15</tt>
73
- # indicates a larger window which increases memory usage but raises the
74
- # compression ratio. Modification of this base value for _window_bits_ as
75
- # noted below dictates what kind of compressed stream and checksum will be
76
- # produced <b>while preserving the setting for the history buffer</b>.
77
- #
78
- # If nothing else is done to the base value of _window_bits_, a zlib stream
79
- # is to be produced with an appropriate header and trailer. In this case
80
- # the checksum method of this object will be an adler32.
81
- #
82
- # Adding <tt>16</tt> to the base value of _window_bits_ indicates that a
83
- # gzip stream is to be produced with an appropriate header and trailer. The
84
- # gzip header will have no file name, no extra data, no comment, no
85
- # modification time (set to zero), no header crc, and the operating system
86
- # will be set to <tt>255</tt> (unknown). In this case the checksum
87
- # attribute of this object will be a crc32.
88
- #
89
- # Finally, negating the base value of _window_bits_ indicates that a raw
90
- # zlib stream is to be produced without any header or trailer. In this case
91
- # the checksum method of this object will always return <tt>nil</tt>. This is
92
- # for use with other formats that use the deflate compressed data format
93
- # such as zip. Such formats should provide their own check values.
94
- #
95
- # If unspecified or +nil+, _window_bits_ defaults to <tt>15</tt>.
96
- #
97
- # The _mem_level_ parameter specifies how much memory should be allocated
98
- # for the internal compression state. A value of <tt>1</tt> uses minimum
99
- # memory but is slow and reduces compression ratio; a value of <tt>9</tt>
100
- # uses maximum memory for optimal speed. The default value is <tt>8</tt> if
101
- # unspecified or +nil+.
102
- #
103
- # The _strategy_ parameter is used to tune the compression algorithm. It
104
- # only affects the compression ratio but not the correctness of the
105
- # compressed output even if it is not set appropriately. The default value
106
- # is Zlib::DEFAULT_STRATEGY if unspecified or +nil+.
107
- #
108
- # Use the value Zlib::DEFAULT_STRATEGY for normal data, Zlib::FILTERED for
109
- # data produced by a filter (or predictor), Zlib::HUFFMAN_ONLY to force
110
- # Huffman encoding only (no string match), Zlib::RLE to limit match
111
- # distances to 1 (run-length encoding), or Zlib::FIXED to simplify decoder
112
- # requirements.
113
- #
114
- # The effect of Zlib::FILTERED is to force more Huffman coding and less
115
- # string matching; it is somewhat intermediate between
116
- # Zlib::DEFAULT_STRATEGY and Zlib::HUFFMAN_ONLY. Filtered data consists
117
- # mostly of small values with a somewhat random distribution. In this case,
118
- # the compression algorithm is tuned to compress them better.
119
- #
120
- # Zlib::RLE is designed to be almost as fast as Zlib::HUFFMAN_ONLY, but give
121
- # better compression for PNG image data.
122
- #
123
- # Zlib::FIXED prevents the use of dynamic Huffman codes, allowing for a
124
- # simpler decoder for special applications.
125
- #
126
- # This class has extremely limited seek capabilities. It is possible to
127
- # seek with an offset of <tt>0</tt> and a whence of <tt>IO::SEEK_CUR</tt>.
128
- # As a result, the _pos_ and _tell_ methods also work as expected.
129
- #
130
- # If _delegate_ also responds to _rewind_, then the _rewind_ method of this
131
- # class can be used to reset the whole stream back to the beginning. Using
132
- # _seek_ of this class to seek directly to offset <tt>0</tt> using
133
- # <tt>IO::SEEK_SET</tt> for whence will also work in this case.
134
- #
135
- # <b>NOTE:</b> Due to limitations in Ruby's finalization capabilities, the
136
- # #close method is _not_ automatically called when this object is garbage
137
- # collected. Make sure to call #close when finished with this object.
138
- def initialize(delegate, level = nil, window_bits = nil, mem_level = nil, strategy = nil)
139
- @delegate = delegate
140
- @level = level
141
- @window_bits = window_bits
142
- @mem_level = mem_level
143
- @strategy = strategy
144
- @deflater = Zlib::Deflate.new(@level, @window_bits, @mem_level, @strategy)
145
- @deflate_buffer = ''
146
- @checksum = nil
147
- @compressed_size = nil
148
- @uncompressed_size = nil
149
- end
150
-
151
- protected
152
-
153
- # The delegate object to which compressed data is written.
154
- attr_reader :delegate
155
-
156
- public
157
-
158
- # Returns the checksum computed over the data written to this stream so far.
159
- #
160
- # <b>NOTE:</b> Refer to the documentation of #new concerning _window_bits_
161
- # to learn what kind of checksum will be returned.
162
- #
163
- # <b>NOTE:</b> Anything still in the internal write buffer has not been
164
- # processed, so calling #flush prior to calling this method may be necessary
165
- # for an accurate checksum.
166
- def checksum
167
- return nil if @window_bits < 0
168
- @deflater.closed? ? @checksum : @deflater.adler
169
- end
170
-
171
- # Closes the writer by finishing the compressed data and flushing it to the
172
- # delegate.
173
- #
174
- # Raises IOError if called more than once.
175
- def close
176
- flush()
177
- @deflate_buffer << @deflater.finish unless @deflater.finished?
178
- begin
179
- until @deflate_buffer.empty? do
180
- @deflate_buffer.slice!(0, delegate.write(@deflate_buffer))
181
- end
182
- rescue Errno::EAGAIN, Errno::EINTR
183
- retry if write_ready?
184
- end
185
- @checksum = @deflater.adler
186
- @compressed_size = @deflater.total_out
187
- @uncompressed_size = @deflater.total_in
188
- @deflater.close
189
- super()
190
- nil
191
- end
192
-
193
- # Returns the number of bytes of compressed data produced so far.
194
- #
195
- # <b>NOTE:</b> This value is only updated when both the internal write
196
- # buffer is flushed and there is enough data to produce a compressed block.
197
- # It does not necessarily reflect the amount of data written to the
198
- # delegate until this stream is closed however. Until then the only
199
- # guarantee is that the value will be greater than or equal to <tt>0</tt>.
200
- def compressed_size
201
- @deflater.closed? ? @compressed_size : @deflater.total_out
202
- end
203
-
204
- # Returns the number of bytes sent to be compressed so far.
205
- #
206
- # <b>NOTE:</b> This value is only updated when the internal write buffer is
207
- # flushed.
208
- def uncompressed_size
209
- @deflater.closed? ? @uncompressed_size : @deflater.total_in
210
- end
211
-
212
- private
213
-
214
- # Allows resetting this object and the delegate object back to the beginning
215
- # of the stream or reporting the current position in the stream.
216
- #
217
- # Raises Errno::EINVAL unless _offset_ is <tt>0</tt> and _whence_ is either
218
- # IO::SEEK_SET or IO::SEEK_CUR. Raises Errno::EINVAL if _whence_ is
219
- # IO::SEEK_SEK and the delegate object does not respond to the _rewind_
220
- # method.
221
- def unbuffered_seek(offset, whence = IO::SEEK_SET)
222
- unless offset == 0 &&
223
- ((whence == IO::SEEK_SET && delegate.respond_to?(:rewind)) ||
224
- whence == IO::SEEK_CUR) then
225
- raise Errno::EINVAL
226
- end
227
-
228
- case whence
229
- when IO::SEEK_SET
230
- delegate.rewind
231
- @deflater.finish
232
- @deflater.close
233
- @deflater = Zlib::Deflate.new(
234
- @level, @window_bits, @mem_level, @strategy
235
- )
236
- @deflate_buffer = ''
237
- 0
238
- when IO::SEEK_CUR
239
- @deflater.total_in
240
- end
241
- end
242
-
243
- def unbuffered_write(string)
244
- # First try to write out the contents of the deflate buffer because if
245
- # that raises a failure we can let that pass up the call stack without
246
- # having polluted the deflater instance.
247
- until @deflate_buffer.empty? do
248
- @deflate_buffer.slice!(0, delegate.write(@deflate_buffer))
249
- end
250
- # At this point we can deflate the given string into a new buffer and
251
- # behave as if it was written.
252
- @deflate_buffer = @deflater.deflate(string)
253
- string.length
254
- end
255
- end
256
-
257
- # Zlib::ZReader is a readable, IO-like object (includes IO::Like) which wraps
258
- # other readable, IO-like objects in order to facilitate reading data from
259
- # those objects using the inflate method of decompression.
260
- class ZReader
261
- include IO::Like
262
-
263
- # The number of bytes to read from the delegate object each time the
264
- # internal read buffer is filled.
265
- DEFAULT_DELEGATE_READ_SIZE = 4096
266
-
267
- # Creates a new instance of this class with the given arguments using #new
268
- # and then passes the instance to the given block. The #close method is
269
- # guaranteed to be called after the block completes.
270
- #
271
- # Equivalent to #new if no block is given.
272
- def self.open(delegate, window_bits = nil)
273
- zr = new(delegate, window_bits)
274
- return zr unless block_given?
275
-
276
- begin
277
- yield(zr)
278
- ensure
279
- zr.close unless zr.closed?
280
- end
281
- end
282
-
283
- # Creates a new instance of this class. _delegate_ must respond to the
284
- # _read_ method as an IO instance would. _window_bits_ is passed directly
285
- # to Zlib::Inflate.new().
286
- #
287
- # <b>
288
- # The following description of _window_bits_ is based on the description
289
- # found in zlib.h version 1.2.3. Some of the statements concerning default
290
- # settings or value ranges may not be accurate depending on the version of
291
- # the zlib library used by a given Ruby interpreter.
292
- # </b>
293
- #
294
- # The _window_bits_ parameter specifies the size of the history buffer, the
295
- # format of the compressed stream, and the kind of checksum returned by the
296
- # checksum method. The size of the history buffer is specified by setting
297
- # the value of _window_bits_ in the range of <tt>8</tt>..<tt>15</tt>,
298
- # inclusive. It must be at least as large as the setting used to create the
299
- # stream or a Zlib::DataError will be raised. Modification of this base
300
- # value for _window_bits_ as noted below dictates what kind of compressed
301
- # stream is expected and what kind of checksum will be produced <b>while
302
- # preserving the setting for the history buffer</b>.
303
- #
304
- # If nothing else is done to the base value of _window_bits_, a zlib stream
305
- # is expected with an appropriate header and trailer. In this case the
306
- # checksum method of this object will be an adler32.
307
- #
308
- # Adding <tt>16</tt> to the base value of _window_bits_ indicates that a
309
- # gzip stream is expected with an appropriate header and trailer. In this
310
- # case the checksum method of this object will be a crc32.
311
- #
312
- # Adding <tt>32</tt> to the base value of _window_bits_ indicates that an
313
- # automatic detection of the stream format should be made based on the
314
- # header in the stream. In this case the checksum method of this object
315
- # will depend on whether a zlib or a gzip stream is detected.
316
- #
317
- # Finally, negating the base value of _window_bits_ indicates that a raw
318
- # zlib stream is expected without any header or trailer. In this case the
319
- # checksum method of this object will always return <tt>nil</tt>. This is for
320
- # use with other formats that use the deflate compressed data format such as
321
- # zip. Such formats should provide their own check values.
322
- #
323
- # If unspecified or +nil+, _window_bits_ defaults to <tt>15</tt>.
324
- #
325
- # In all cases, Zlib::DataError is raised if the wrong stream format is
326
- # found <b>when reading</b>.
327
- #
328
- # This class has extremely limited seek capabilities. It is possible to
329
- # seek with an offset of <tt>0</tt> and a whence of <tt>IO::SEEK_CUR</tt>.
330
- # As a result, the _pos_ and _tell_ methods also work as expected.
331
- #
332
- # Due to certain optimizations within IO::Like#seek and if there is data in
333
- # the read buffer, the _seek_ method can be used to seek forward from the
334
- # current stream position up to the end of the buffer. Unless it is known
335
- # definitively how much data is in the buffer, it is best to avoid relying
336
- # on this behavior.
337
- #
338
- # If _delegate_ also responds to _rewind_, then the _rewind_ method of this
339
- # class can be used to reset the whole stream back to the beginning. Using
340
- # _seek_ of this class to seek directly to offset <tt>0</tt> using
341
- # <tt>IO::SEEK_SET</tt> for whence will also work in this case.
342
- #
343
- # Any other seeking attempts, will raise Errno::EINVAL exceptions.
344
- #
345
- # <b>NOTE:</b> Due to limitations in Ruby's finalization capabilities, the
346
- # #close method is _not_ automatically called when this object is garbage
347
- # collected. Make sure to call #close when finished with this object.
348
- def initialize(delegate, window_bits = nil)
349
- @delegate = delegate
350
- @delegate_read_size = DEFAULT_DELEGATE_READ_SIZE
351
- @window_bits = window_bits
352
- @inflater = Zlib::Inflate.new(@window_bits)
353
- @inflate_buffer = ''
354
- @checksum = nil
355
- @compressed_size = nil
356
- @uncompressed_size = nil
357
- end
358
-
359
- # The number of bytes to read from the delegate object each time the
360
- # internal read buffer is filled.
361
- attr_accessor :delegate_read_size
362
-
363
- protected
364
-
365
- # The delegate object from which compressed data is read.
366
- attr_reader :delegate
367
-
368
- public
369
-
370
- # Returns the checksum computed over the data read from this stream.
371
- #
372
- # <b>NOTE:</b> Refer to the documentation of #new concerning _window_bits_
373
- # to learn what kind of checksum will be returned.
374
- #
375
- # <b>NOTE:</b> The contents of the internal read buffer are immediately
376
- # processed any time the internal buffer is filled, so this checksum is only
377
- # accurate if all data has been read out of this object.
378
- def checksum
379
- return nil if @window_bits < 0
380
- @inflater.closed? ? @checksum : @inflater.adler
381
- end
382
-
383
- # Closes the reader.
384
- #
385
- # Raises IOError if called more than once.
386
- def close
387
- super()
388
- @checksum = @inflater.adler
389
- @compressed_size = @inflater.total_in
390
- @uncompressed_size = @inflater.total_out
391
- @inflater.close
392
- nil
393
- end
394
-
395
- # Returns the number of bytes sent to be compressed so far.
396
- #
397
- # <b>NOTE:</b> This value is updated whenever the internal read buffer needs
398
- # to be filled, not when data is read out of this stream.
399
- def compressed_size
400
- @inflater.closed? ? @compressed_size : @inflater.total_in
401
- end
402
-
403
- # Returns the number of bytes of decompressed data produced so far.
404
- #
405
- # <b>NOTE:</b> This value is updated whenever the internal read buffer needs
406
- # to be filled, not when data is read out of this stream.
407
- def uncompressed_size
408
- @inflater.closed? ? @uncompressed_size : @inflater.total_out
409
- end
410
-
411
- private
412
-
413
- def unbuffered_read(length)
414
- if @inflate_buffer.empty? && @inflater.finished? then
415
- raise EOFError, 'end of file reached'
416
- end
417
-
418
- begin
419
- while @inflate_buffer.length < length && ! @inflater.finished? do
420
- @inflate_buffer <<
421
- @inflater.inflate(delegate.read(@delegate_read_size))
422
- end
423
- rescue Errno::EINTR, Errno::EAGAIN
424
- raise if @inflate_buffer.empty?
425
- end
426
- @inflate_buffer.slice!(0, length)
427
- end
428
-
429
- # Allows resetting this object and the delegate object back to the beginning
430
- # of the stream or reporting the current position in the stream.
431
- #
432
- # Raises Errno::EINVAL unless _offset_ is <tt>0</tt> and _whence_ is either
433
- # IO::SEEK_SET or IO::SEEK_CUR. Raises Errno::EINVAL if _whence_ is
434
- # IO::SEEK_SEK and the delegate object does not respond to the _rewind_
435
- # method.
436
- def unbuffered_seek(offset, whence = IO::SEEK_SET)
437
- unless offset == 0 &&
438
- ((whence == IO::SEEK_SET && delegate.respond_to?(:rewind)) ||
439
- whence == IO::SEEK_CUR) then
440
- raise Errno::EINVAL
441
- end
442
-
443
- case whence
444
- when IO::SEEK_SET
445
- delegate.rewind
446
- @inflater.close
447
- @inflater = Zlib::Inflate.new(@window_bits)
448
- @inflate_buffer = ''
449
- 0
450
- when IO::SEEK_CUR
451
- @inflater.total_out - @inflate_buffer.length
452
- end
453
- end
454
- end
455
20
  end
@@ -0,0 +1,187 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'io/like_helpers/delegated_io'
4
+
5
+ require 'archive/support/zlib'
6
+ require 'archive/zip/data_descriptor'
7
+
8
+ module Archive; class Zip; module Codec; class Deflate
9
+ # Archive::Zip::Codec::Deflate::Reader extends Zlib::ZReader in order to
10
+ # specify the standard Zlib options required by ZIP archives and to provide
11
+ # a close method which can optionally close the delegate IO-like object.
12
+ # In addition a convenience method is provided for generating DataDescriptor
13
+ # objects based on the data which is passed through this object.
14
+ #
15
+ # Instances of this class should only be accessed via the
16
+ # Archive::Zip::Codec::Deflate#decompressor method.
17
+ class Reader < IO::LikeHelpers::DelegatedIO
18
+ # The number of bytes to read from the delegate object each time the
19
+ # internal read buffer is filled.
20
+ DEFAULT_DELEGATE_READ_SIZE = 8192
21
+
22
+ # Creates a new instance of this class. _delegate_ must respond to the
23
+ # _read_ method as an IO instance would.
24
+ #
25
+ # In all cases, Zlib::DataError is raised if the wrong stream format is
26
+ # found <b>when reading</b>.
27
+ #
28
+ # This class has extremely limited seek capabilities. It is possible to
29
+ # seek with an offset of <tt>0</tt> and a whence of <tt>IO::SEEK_CUR</tt>.
30
+ # As a result, the _pos_ and _tell_ methods also work as expected.
31
+ #
32
+ # Due to certain optimizations within IO::Like#seek and if there is data in
33
+ # the read buffer, the _seek_ method can be used to seek forward from the
34
+ # current stream position up to the end of the buffer. Unless it is known
35
+ # definitively how much data is in the buffer, it is best to avoid relying
36
+ # on this behavior.
37
+ #
38
+ # If _delegate_ also responds to _rewind_, then the _rewind_ method of this
39
+ # class can be used to reset the whole stream back to the beginning. Using
40
+ # _seek_ of this class to seek directly to offset <tt>0</tt> using
41
+ # <tt>IO::SEEK_SET</tt> for whence will also work in this case.
42
+ #
43
+ # Any other seeking attempts, will raise Errno::EINVAL exceptions.
44
+ #
45
+ # <b>NOTE:</b> Due to limitations in Ruby's finalization capabilities, the
46
+ # #close method is _not_ automatically called when this object is garbage
47
+ # collected. Make sure to call #close when finished with this object.
48
+ def initialize(
49
+ delegate,
50
+ autoclose: true,
51
+ delegate_read_size: DEFAULT_DELEGATE_READ_SIZE
52
+ )
53
+ super(delegate, autoclose: autoclose)
54
+
55
+ @delegate_read_size = delegate_read_size
56
+ @read_buffer = "\0".b * @delegate_read_size
57
+ @inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
58
+ @inflate_buffer = ''
59
+ @inflate_buffer_idx = 0
60
+ @compressed_size = nil
61
+ @uncompressed_size = nil
62
+ @crc32 = 0
63
+ end
64
+
65
+ # The number of bytes to read from the delegate object each time the
66
+ # internal read buffer is filled.
67
+ attr_accessor :delegate_read_size
68
+
69
+ # Closes the reader.
70
+ #
71
+ # Raises IOError if called more than once.
72
+ def close
73
+ return nil if closed?
74
+
75
+ result = super
76
+ return result if Symbol === result
77
+
78
+ @compressed_size = @inflater.total_in
79
+ @uncompressed_size = @inflater.total_out
80
+ @inflate_buffer = nil
81
+ @inflate_buffer_idx = 0
82
+
83
+ # Avoid warnings by only attempting to close the inflater if it was
84
+ # correctly finished.
85
+ @inflater.close if @inflater.finished?
86
+
87
+ nil
88
+ end
89
+
90
+ # The CRC32 checksum of the uncompressed data read using this object.
91
+ #
92
+ # <b>NOTE:</b> The contents of the internal read buffer are immediately
93
+ # processed any time the internal buffer is filled, so this checksum is
94
+ # only accurate if all data has been read out of this object.
95
+ attr_reader :crc32
96
+
97
+ # Returns the number of bytes sent to be compressed so far.
98
+ #
99
+ # <b>NOTE:</b> This value is updated whenever the internal read buffer needs
100
+ # to be filled, not when data is read out of this stream.
101
+ def compressed_size
102
+ @inflater.closed? ? @compressed_size : @inflater.total_in
103
+ end
104
+
105
+ # Returns the number of bytes of decompressed data produced so far.
106
+ #
107
+ # <b>NOTE:</b> This value is updated whenever the internal read buffer needs
108
+ # to be filled, not when data is read out of this stream.
109
+ def uncompressed_size
110
+ @inflater.closed? ? @uncompressed_size : @inflater.total_out
111
+ end
112
+
113
+ # Returns an instance of Archive::Zip::DataDescriptor with information
114
+ # regarding the data which has passed through this object from the
115
+ # delegate object. It is recommended to call the close method before
116
+ # calling this in order to ensure that no further read operations change
117
+ # the state of this object.
118
+ def data_descriptor
119
+ DataDescriptor.new(crc32, compressed_size, uncompressed_size)
120
+ end
121
+
122
+ def read(length, buffer: nil, buffer_offset: 0)
123
+ length = Integer(length)
124
+ raise ArgumentError, 'length must be at least 0' if length < 0
125
+ if ! buffer.nil?
126
+ if buffer_offset < 0 || buffer_offset >= buffer.bytesize
127
+ raise ArgumentError, 'buffer_offset is not a valid buffer index'
128
+ end
129
+ if buffer.bytesize - buffer_offset < length
130
+ raise ArgumentError, 'length is greater than available buffer space'
131
+ end
132
+ end
133
+
134
+ assert_readable
135
+
136
+ if @inflate_buffer_idx >= @inflate_buffer.size
137
+ raise EOFError, 'end of file reached' if @inflater.finished?
138
+
139
+ @inflate_buffer =
140
+ begin
141
+ result = super(@delegate_read_size, buffer: @read_buffer)
142
+ return result if Symbol === result
143
+ @inflater.inflate(@read_buffer[0, result])
144
+ rescue EOFError
145
+ @inflater.inflate(nil)
146
+ end
147
+ @inflate_buffer_idx = 0
148
+ end
149
+
150
+ available = @inflate_buffer.size - @inflate_buffer_idx
151
+ length = available if available < length
152
+ content = @inflate_buffer[@inflate_buffer_idx, length]
153
+ @inflate_buffer_idx += length
154
+ @crc32 = Zlib.crc32(content, @crc32)
155
+ return content if buffer.nil?
156
+
157
+ buffer[buffer_offset, length] = content
158
+ return length
159
+ end
160
+
161
+ # Allows resetting this object and the delegate object back to the beginning
162
+ # of the stream or reporting the current position in the stream.
163
+ #
164
+ # Raises Errno::EINVAL unless _offset_ is <tt>0</tt> and _whence_ is either
165
+ # IO::SEEK_SET or IO::SEEK_CUR. Raises Errno::EINVAL if _whence_ is
166
+ # IO::SEEK_SEK and the delegate object does not respond to the _rewind_
167
+ # method.
168
+ def seek(amount, whence = IO::SEEK_SET)
169
+ assert_open
170
+ raise Errno::ESPIPE if amount != 0 || whence == IO::SEEK_END
171
+
172
+ case whence
173
+ when IO::SEEK_SET
174
+ result = super
175
+ return result if Symbol === result
176
+ @inflater.reset
177
+ @inflate_buffer_idx = @inflate_buffer.size
178
+ @crc32 = 0
179
+ result
180
+ when IO::SEEK_CUR
181
+ @inflater.total_out - (@inflate_buffer.size - @inflate_buffer_idx)
182
+ else
183
+ raise Errno::EINVAL
184
+ end
185
+ end
186
+ end
187
+ end; end; end; end