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
@@ -1,193 +1,11 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'archive/support/io-like'
4
3
  require 'archive/zip/codec'
5
4
 
6
5
  module Archive; class Zip; module Codec
7
6
  # Archive::Zip::Codec::NullEncryption is a handle for an encryption codec
8
7
  # which passes data through itself unchanged.
9
8
  class NullEncryption
10
- # Archive::Zip::Codec::NullEncryption::Encrypt is a writable, IO-like object
11
- # which writes all data written to it directly to a delegate IO object. A
12
- # _close_ method is also provided which can optionally closed the delegate
13
- # object.
14
- class Encrypt
15
- include IO::Like
16
-
17
- # Creates a new instance of this class with the given argument using #new
18
- # and then passes the instance to the given block. The #close method is
19
- # guaranteed to be called after the block completes.
20
- #
21
- # Equivalent to #new if no block is given.
22
- def self.open(io)
23
- encrypt_io = new(io)
24
- return encrypt_io unless block_given?
25
-
26
- begin
27
- yield(encrypt_io)
28
- ensure
29
- encrypt_io.close unless encrypt_io.closed?
30
- end
31
- end
32
-
33
- # Creates a new instance of this class using _io_ as a data sink. _io_
34
- # must be writable and must provide a write method as IO does or errors
35
- # will be raised when performing write operations.
36
- #
37
- # The _flush_size_ attribute is set to <tt>0</tt> by default under the
38
- # assumption that _io_ is already buffered.
39
- def initialize(io)
40
- @io = io
41
-
42
- # Keep track of the total number of bytes written.
43
- @total_bytes_in = 0
44
-
45
- # Assume that the delegate IO object is already buffered.
46
- self.flush_size = 0
47
- end
48
-
49
- # Closes this object so that further write operations will fail. If
50
- # _close_delegate_ is +true+, the delegate object used as a data sink will
51
- # also be closed using its close method.
52
- def close(close_delegate = true)
53
- super()
54
- @io.close if close_delegate
55
- end
56
-
57
- private
58
-
59
- # Allows resetting this object and the delegate object back to the
60
- # beginning of the stream or reporting the current position in the stream.
61
- #
62
- # Raises Errno::EINVAL unless _offset_ is <tt>0</tt> and _whence_ is
63
- # either IO::SEEK_SET or IO::SEEK_CUR. Raises Errno::EINVAL if _whence_
64
- # is IO::SEEK_SEK and the delegate object does not respond to the _rewind_
65
- # method.
66
- def unbuffered_seek(offset, whence = IO::SEEK_SET)
67
- unless offset == 0 &&
68
- ((whence == IO::SEEK_SET && @io.respond_to?(:rewind)) ||
69
- whence == IO::SEEK_CUR) then
70
- raise Errno::EINVAL
71
- end
72
-
73
- case whence
74
- when IO::SEEK_SET
75
- @io.rewind
76
- @total_bytes_in = 0
77
- when IO::SEEK_CUR
78
- @total_bytes_in
79
- end
80
- end
81
-
82
- # Writes _string_ to the delegate IO object and returns the result.
83
- def unbuffered_write(string)
84
- bytes_written = @io.write(string)
85
- @total_bytes_in += bytes_written
86
- bytes_written
87
- end
88
- end
89
-
90
- # Archive::Zip::Codec::NullEncryption::Decrypt is a readable, IO-like object
91
- # which reads data directly from a delegate IO object, making no changes. A
92
- # _close_ method is also provided which can optionally closed the delegate
93
- # object.
94
- class Decrypt
95
- include IO::Like
96
-
97
- # Creates a new instance of this class with the given argument using #new
98
- # and then passes the instance to the given block. The #close method is
99
- # guaranteed to be called after the block completes.
100
- #
101
- # Equivalent to #new if no block is given.
102
- def self.open(io)
103
- decrypt_io = new(io)
104
- return decrypt_io unless block_given?
105
-
106
- begin
107
- yield(decrypt_io)
108
- ensure
109
- decrypt_io.close unless decrypt_io.closed?
110
- end
111
- end
112
-
113
- # Creates a new instance of this class using _io_ as a data source. _io_
114
- # must be readable and provide a _read_ method as an IO instance would or
115
- # errors will be raised when performing read operations.
116
- #
117
- # This class has extremely limited seek capabilities. It is possible to
118
- # seek with an offset of <tt>0</tt> and a whence of <tt>IO::SEEK_CUR</tt>.
119
- # As a result, the _pos_ and _tell_ methods also work as expected.
120
- #
121
- # Due to certain optimizations within IO::Like#seek and if there is data
122
- # in the read buffer, the _seek_ method can be used to seek forward from
123
- # the current stream position up to the end of the buffer. Unless it is
124
- # known definitively how much data is in the buffer, it is best to avoid
125
- # relying on this behavior.
126
- #
127
- # If _io_ also responds to _rewind_, then the _rewind_ method of this
128
- # class can be used to reset the whole stream back to the beginning. Using
129
- # _seek_ of this class to seek directly to offset <tt>0</tt> using
130
- # <tt>IO::SEEK_SET</tt> for whence will also work in this case.
131
- #
132
- # Any other seeking attempts, will raise Errno::EINVAL exceptions.
133
- #
134
- # The _fill_size_ attribute is set to <tt>0</tt> by default under the
135
- # assumption that _io_ is already buffered.
136
- def initialize(io)
137
- @io = io
138
-
139
- # Keep track of the total number of bytes read.
140
- @total_bytes_out = 0
141
-
142
- # Assume that the delegate IO object is already buffered.
143
- self.fill_size = 0
144
- end
145
-
146
- # Closes this object so that further write operations will fail. If
147
- # _close_delegate_ is +true+, the delegate object used as a data source
148
- # will also be closed using its close method.
149
- def close(close_delegate = true)
150
- super()
151
- @io.close if close_delegate
152
- end
153
-
154
- private
155
-
156
- # Reads and returns at most _length_ bytes from the delegate IO object.
157
- #
158
- # Raises EOFError if there is no data to read.
159
- def unbuffered_read(length)
160
- buffer = @io.read(length)
161
- raise EOFError, 'end of file reached' if buffer.nil?
162
- @total_bytes_out += buffer.length
163
-
164
- buffer
165
- end
166
-
167
- # Allows resetting this object and the delegate object back to the
168
- # beginning of the stream or reporting the current position in the stream.
169
- #
170
- # Raises Errno::EINVAL unless _offset_ is <tt>0</tt> and _whence_ is
171
- # either IO::SEEK_SET or IO::SEEK_CUR. Raises Errno::EINVAL if _whence_
172
- # is IO::SEEK_SEK and the delegate object does not respond to the _rewind_
173
- # method.
174
- def unbuffered_seek(offset, whence = IO::SEEK_SET)
175
- unless offset == 0 &&
176
- ((whence == IO::SEEK_SET && @io.respond_to?(:rewind)) ||
177
- whence == IO::SEEK_CUR) then
178
- raise Errno::EINVAL
179
- end
180
-
181
- case whence
182
- when IO::SEEK_SET
183
- @io.rewind
184
- @total_bytes_out = 0
185
- when IO::SEEK_CUR
186
- @total_bytes_out
187
- end
188
- end
189
- end
190
-
191
9
  # This method signature is part of the interface contract expected by
192
10
  # Archive::Zip::Entry for encryption codec objects.
193
11
  #
@@ -195,7 +13,8 @@ module Archive; class Zip; module Codec
195
13
  # Archive::Zip::Codec::NullEncryption::Encrypt object using that class' open
196
14
  # method.
197
15
  def encryptor(io, password, &b)
198
- Encrypt.open(io, &b)
16
+ return io unless block_given?
17
+ b[io]
199
18
  end
200
19
 
201
20
  # This method signature is part of the interface contract expected by
@@ -205,7 +24,8 @@ module Archive; class Zip; module Codec
205
24
  # Archive::Zip::Codec::NullEncryption::Decrypt object using that class' open
206
25
  # method.
207
26
  def decryptor(io, password, &b)
208
- Decrypt.open(io, &b)
27
+ return io unless block_given?
28
+ b[io]
209
29
  end
210
30
 
211
31
  # This method signature is part of the interface contract expected by
@@ -0,0 +1,97 @@
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 Store
9
+ # Archive::Zip::Codec::Store::Reader is a readable, IO-like wrapper
10
+ # around a readable, IO-like object which provides a CRC32 checksum of the
11
+ # data read through it as well as the count of the total amount of data. A
12
+ # _close_ method is also provided which can optionally close the delegate
13
+ # object. In addition a convenience method is provided for generating
14
+ # DataDescriptor objects based on the data which is passed through this
15
+ # object.
16
+ #
17
+ # Instances of this class should only be accessed via the
18
+ # Archive::Zip::Codec::Store#decompressor method.
19
+ class Reader < IO::LikeHelpers::DelegatedIO
20
+ # Creates a new instance of this class using _io_ as a data source. _io_
21
+ # must be readable and provide a _read_ method as an IO instance would or
22
+ # errors will be raised when performing read operations.
23
+ #
24
+ # This class has extremely limited seek capabilities. It is possible to
25
+ # seek with an offset of <tt>0</tt> and a whence of <tt>IO::SEEK_CUR</tt>.
26
+ # As a result, the _pos_ and _tell_ methods also work as expected.
27
+ #
28
+ # Due to certain optimizations within IO::Like#seek and if there is data
29
+ # in the read buffer, the _seek_ method can be used to seek forward from
30
+ # the current stream position up to the end of the buffer. Unless it is
31
+ # known definitively how much data is in the buffer, it is best to avoid
32
+ # relying on this behavior.
33
+ #
34
+ # If _io_ also responds to _rewind_, then the _rewind_ method of this
35
+ # class can be used to reset the whole stream back to the beginning. Using
36
+ # _seek_ of this class to seek directly to offset <tt>0</tt> using
37
+ # <tt>IO::SEEK_SET</tt> for whence will also work in this case.
38
+ #
39
+ # Any other seeking attempts, will raise Errno::EINVAL exceptions.
40
+ def initialize(delegate, autoclose: true)
41
+ super
42
+ @crc32 = 0
43
+ @uncompressed_size = 0
44
+ end
45
+
46
+ # Returns an instance of Archive::Zip::DataDescriptor with information
47
+ # regarding the data which has passed through this object from the
48
+ # delegate object. It is recommended to call the close method before
49
+ # calling this in order to ensure that no further read operations change
50
+ # the state of this object.
51
+ def data_descriptor
52
+ DataDescriptor.new(
53
+ @crc32,
54
+ @uncompressed_size,
55
+ @uncompressed_size
56
+ )
57
+ end
58
+
59
+ # Returns at most _length_ bytes from the delegate object. Updates the
60
+ # uncompressed_size and crc32 attributes as a side effect.
61
+ def read(length, buffer: nil, buffer_offset: 0)
62
+ result = super
63
+ return result if Symbol === result
64
+
65
+ buffer = result if buffer.nil?
66
+ @uncompressed_size += buffer.bytesize
67
+ @crc32 = Zlib.crc32(buffer, @crc32)
68
+
69
+ result
70
+ end
71
+
72
+ # Allows resetting this object and the delegate object back to the
73
+ # beginning of the stream or reporting the current position in the stream.
74
+ #
75
+ # Raises Errno::EINVAL unless _offset_ is <tt>0</tt> and _whence_ is
76
+ # either IO::SEEK_SET or IO::SEEK_CUR. Raises Errno::EINVAL if _whence_
77
+ # is IO::SEEK_SEK and the delegate object does not respond to the _rewind_
78
+ # method.
79
+ def seek(amount, whence = IO::SEEK_SET)
80
+ assert_open
81
+ raise Errno::ESPIPE if amount != 0 || whence == IO::SEEK_END
82
+
83
+ case whence
84
+ when IO::SEEK_SET
85
+ result = super
86
+ return result if Symbol === result
87
+ @crc32 = 0
88
+ @uncompressed_size = 0
89
+ result
90
+ when IO::SEEK_CUR
91
+ @uncompressed_size
92
+ else
93
+ raise Errno::EINVAL
94
+ end
95
+ end
96
+ end
97
+ end; end; end; end
@@ -0,0 +1,78 @@
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 Store
9
+ # Archive::Zip::Codec::Store::Writer is simply a writable, IO-like wrapper
10
+ # around a writable, IO-like object which provides a CRC32 checksum of the
11
+ # data written through it as well as the count of the total amount of data.
12
+ # A _close_ method is also provided which can optionally close the delegate
13
+ # object. In addition a convenience method is provided for generating
14
+ # DataDescriptor objects based on the data which is passed through this
15
+ # object.
16
+ #
17
+ # Instances of this class should only be accessed via the
18
+ # Archive::Zip::Codec::Store#compressor method.
19
+ class Writer < IO::LikeHelpers::DelegatedIO
20
+ # Creates a new instance of this class using _io_ as a data sink. _io_
21
+ # must be writable and must provide a write method as IO does or errors
22
+ # will be raised when performing write operations.
23
+ def initialize(delegate, autoclose: true)
24
+ super
25
+ @crc32 = 0
26
+ @uncompressed_size = 0
27
+ end
28
+
29
+ # Returns an instance of Archive::Zip::DataDescriptor with information
30
+ # regarding the data which has passed through this object to the delegate
31
+ # object. The close or flush methods should be called before using this
32
+ # method in order to ensure that any possibly buffered data is flushed to
33
+ # the delegate object; otherwise, the contents of the data descriptor may
34
+ # be inaccurate.
35
+ def data_descriptor
36
+ DataDescriptor.new(@crc32, @uncompressed_size, @uncompressed_size)
37
+ end
38
+
39
+ # Allows resetting this object and the delegate object back to the
40
+ # beginning of the stream or reporting the current position in the stream.
41
+ #
42
+ # Raises Errno::EINVAL unless _offset_ is <tt>0</tt> and _whence_ is
43
+ # either IO::SEEK_SET or IO::SEEK_CUR. Raises Errno::EINVAL if _whence_
44
+ # is IO::SEEK_SEK and the delegate object does not respond to the _rewind_
45
+ # method.
46
+ def seek(amount, whence = IO::SEEK_SET)
47
+ assert_open
48
+ raise Errno::ESPIPE if amount != 0 || whence == IO::SEEK_END
49
+
50
+ case whence
51
+ when IO::SEEK_SET
52
+ result = super
53
+ return result if Symbol === result
54
+ @crc32 = 0
55
+ @uncompressed_size = 0
56
+ result
57
+ when IO::SEEK_CUR
58
+ @uncompressed_size
59
+ else
60
+ raise Errno::EINVAL
61
+ end
62
+ end
63
+
64
+ # Writes _string_ to the delegate object and returns the number of bytes
65
+ # actually written. Updates the uncompressed_size and crc32 attributes as
66
+ # a side effect.
67
+ def write(buffer, length: buffer.bytesize)
68
+ result = super
69
+ return result if Symbol === result
70
+
71
+ @uncompressed_size += result
72
+ buffer = buffer[0, result] if result < buffer.bytesize
73
+ @crc32 = Zlib.crc32(buffer, @crc32)
74
+
75
+ result
76
+ end
77
+ end
78
+ end; end; end; end
@@ -1,237 +1,12 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'archive/support/io-like'
4
- require 'archive/support/zlib'
5
- require 'archive/zip/codec'
6
- require 'archive/zip/data_descriptor'
3
+ require 'archive/zip/codec/store/reader'
4
+ require 'archive/zip/codec/store/writer'
7
5
 
8
6
  module Archive; class Zip; module Codec
9
7
  # Archive::Zip::Codec::Store is a handle for the store-unstore (no
10
8
  # compression) codec.
11
9
  class Store
12
- # Archive::Zip::Codec::Store::Compress is simply a writable, IO-like wrapper
13
- # around a writable, IO-like object which provides a CRC32 checksum of the
14
- # data written through it as well as the count of the total amount of data.
15
- # A _close_ method is also provided which can optionally close the delegate
16
- # object. In addition a convenience method is provided for generating
17
- # DataDescriptor objects based on the data which is passed through this
18
- # object.
19
- #
20
- # Instances of this class should only be accessed via the
21
- # Archive::Zip::Codec::Store#compressor method.
22
- class Compress
23
- include IO::Like
24
-
25
- # Creates a new instance of this class with the given argument using #new
26
- # and then passes the instance to the given block. The #close method is
27
- # guaranteed to be called after the block completes.
28
- #
29
- # Equivalent to #new if no block is given.
30
- def self.open(io)
31
- store_io = new(io)
32
- return store_io unless block_given?
33
-
34
- begin
35
- yield(store_io)
36
- ensure
37
- store_io.close unless store_io.closed?
38
- end
39
- end
40
-
41
- # Creates a new instance of this class using _io_ as a data sink. _io_
42
- # must be writable and must provide a write method as IO does or errors
43
- # will be raised when performing write operations.
44
- #
45
- # The _flush_size_ attribute is set to <tt>0</tt> by default under the
46
- # assumption that _io_ is already buffered.
47
- def initialize(io)
48
- @io = io
49
- @crc32 = 0
50
- @uncompressed_size = 0
51
- # Assume that the delegate IO object is already buffered.
52
- self.flush_size = 0
53
- end
54
-
55
- # Closes this object so that further write operations will fail. If
56
- # _close_delegate_ is +true+, the delegate object used as a data sink will
57
- # also be closed using its close method.
58
- def close(close_delegate = true)
59
- super()
60
- @io.close if close_delegate
61
- nil
62
- end
63
-
64
- # Returns an instance of Archive::Zip::DataDescriptor with information
65
- # regarding the data which has passed through this object to the delegate
66
- # object. The close or flush methods should be called before using this
67
- # method in order to ensure that any possibly buffered data is flushed to
68
- # the delegate object; otherwise, the contents of the data descriptor may
69
- # be inaccurate.
70
- def data_descriptor
71
- DataDescriptor.new(
72
- @crc32,
73
- @uncompressed_size,
74
- @uncompressed_size
75
- )
76
- end
77
-
78
- private
79
-
80
- # Allows resetting this object and the delegate object back to the
81
- # beginning of the stream or reporting the current position in the stream.
82
- #
83
- # Raises Errno::EINVAL unless _offset_ is <tt>0</tt> and _whence_ is
84
- # either IO::SEEK_SET or IO::SEEK_CUR. Raises Errno::EINVAL if _whence_
85
- # is IO::SEEK_SEK and the delegate object does not respond to the _rewind_
86
- # method.
87
- def unbuffered_seek(offset, whence = IO::SEEK_SET)
88
- unless offset == 0 &&
89
- ((whence == IO::SEEK_SET && @io.respond_to?(:rewind)) ||
90
- whence == IO::SEEK_CUR) then
91
- raise Errno::EINVAL
92
- end
93
-
94
- case whence
95
- when IO::SEEK_SET
96
- @io.rewind
97
- @crc32 = 0
98
- @uncompressed_size = 0
99
- when IO::SEEK_CUR
100
- @uncompressed_size
101
- end
102
- end
103
-
104
- # Writes _string_ to the delegate object and returns the number of bytes
105
- # actually written. Updates the uncompressed_size and crc32 attributes as
106
- # a side effect.
107
- def unbuffered_write(string)
108
- bytes_written = @io.write(string)
109
- @uncompressed_size += bytes_written
110
- @crc32 = Zlib.crc32(string.slice(0, bytes_written), @crc32)
111
- bytes_written
112
- end
113
- end
114
-
115
- # Archive::Zip::Codec::Store::Decompress is a readable, IO-like wrapper
116
- # around a readable, IO-like object which provides a CRC32 checksum of the
117
- # data read through it as well as the count of the total amount of data. A
118
- # _close_ method is also provided which can optionally close the delegate
119
- # object. In addition a convenience method is provided for generating
120
- # DataDescriptor objects based on the data which is passed through this
121
- # object.
122
- #
123
- # Instances of this class should only be accessed via the
124
- # Archive::Zip::Codec::Store#decompressor method.
125
- class Decompress
126
- include IO::Like
127
-
128
- # Creates a new instance of this class with the given arguments using #new
129
- # and then passes the instance to the given block. The #close method is
130
- # guaranteed to be called after the block completes.
131
- #
132
- # Equivalent to #new if no block is given.
133
- def self.open(io)
134
- unstore_io = new(io)
135
- return unstore_io unless block_given?
136
-
137
- begin
138
- yield(unstore_io)
139
- ensure
140
- unstore_io.close unless unstore_io.closed?
141
- end
142
- end
143
-
144
- # Creates a new instance of this class using _io_ as a data source. _io_
145
- # must be readable and provide a _read_ method as an IO instance would or
146
- # errors will be raised when performing read operations.
147
- #
148
- # This class has extremely limited seek capabilities. It is possible to
149
- # seek with an offset of <tt>0</tt> and a whence of <tt>IO::SEEK_CUR</tt>.
150
- # As a result, the _pos_ and _tell_ methods also work as expected.
151
- #
152
- # Due to certain optimizations within IO::Like#seek and if there is data
153
- # in the read buffer, the _seek_ method can be used to seek forward from
154
- # the current stream position up to the end of the buffer. Unless it is
155
- # known definitively how much data is in the buffer, it is best to avoid
156
- # relying on this behavior.
157
- #
158
- # If _io_ also responds to _rewind_, then the _rewind_ method of this
159
- # class can be used to reset the whole stream back to the beginning. Using
160
- # _seek_ of this class to seek directly to offset <tt>0</tt> using
161
- # <tt>IO::SEEK_SET</tt> for whence will also work in this case.
162
- #
163
- # Any other seeking attempts, will raise Errno::EINVAL exceptions.
164
- #
165
- # The _fill_size_ attribute is set to <tt>0</tt> by default under the
166
- # assumption that _io_ is already buffered.
167
- def initialize(io)
168
- @io = io
169
- @crc32 = 0
170
- @uncompressed_size = 0
171
- # Assume that the delegate IO object is already buffered.
172
- self.fill_size = 0
173
- end
174
-
175
- # Closes this object so that further read operations will fail. If
176
- # _close_delegate_ is +true+, the delegate object used as a data source
177
- # will also be closed using its close method.
178
- def close(close_delegate = true)
179
- super()
180
- @io.close if close_delegate
181
- nil
182
- end
183
-
184
- # Returns an instance of Archive::Zip::DataDescriptor with information
185
- # regarding the data which has passed through this object from the
186
- # delegate object. It is recommended to call the close method before
187
- # calling this in order to ensure that no further read operations change
188
- # the state of this object.
189
- def data_descriptor
190
- DataDescriptor.new(
191
- @crc32,
192
- @uncompressed_size,
193
- @uncompressed_size
194
- )
195
- end
196
-
197
- private
198
-
199
- # Returns at most _length_ bytes from the delegate object. Updates the
200
- # uncompressed_size and crc32 attributes as a side effect.
201
- def unbuffered_read(length)
202
- buffer = @io.read(length)
203
- raise EOFError, 'end of file reached' if buffer.nil?
204
-
205
- @uncompressed_size += buffer.length
206
- @crc32 = Zlib.crc32(buffer, @crc32)
207
- buffer
208
- end
209
-
210
- # Allows resetting this object and the delegate object back to the
211
- # beginning of the stream or reporting the current position in the stream.
212
- #
213
- # Raises Errno::EINVAL unless _offset_ is <tt>0</tt> and _whence_ is
214
- # either IO::SEEK_SET or IO::SEEK_CUR. Raises Errno::EINVAL if _whence_
215
- # is IO::SEEK_SEK and the delegate object does not respond to the _rewind_
216
- # method.
217
- def unbuffered_seek(offset, whence = IO::SEEK_SET)
218
- unless offset == 0 &&
219
- ((whence == IO::SEEK_SET && @io.respond_to?(:rewind)) ||
220
- whence == IO::SEEK_CUR) then
221
- raise Errno::EINVAL
222
- end
223
-
224
- case whence
225
- when IO::SEEK_SET
226
- @io.rewind
227
- @crc32 = 0
228
- @uncompressed_size = 0
229
- when IO::SEEK_CUR
230
- @uncompressed_size
231
- end
232
- end
233
- end
234
-
235
10
  # The numeric identifier assigned to this compresion codec by the ZIP
236
11
  # specification.
237
12
  ID = 0
@@ -250,20 +25,20 @@ module Archive; class Zip; module Codec
250
25
  # This method signature is part of the interface contract expected by
251
26
  # Archive::Zip::Entry for compression codec objects.
252
27
  #
253
- # A convenience method for creating an Archive::Zip::Codec::Store::Compress
28
+ # A convenience method for creating an Archive::Zip::Codec::Store::Writer
254
29
  # object using that class' open method.
255
30
  def compressor(io, &b)
256
- Compress.open(io, &b)
31
+ Writer.open(io, &b)
257
32
  end
258
33
 
259
34
  # This method signature is part of the interface contract expected by
260
35
  # Archive::Zip::Entry for compression codec objects.
261
36
  #
262
37
  # A convenience method for creating an
263
- # Archive::Zip::Codec::Store::Decompress object using that class' open
38
+ # Archive::Zip::Codec::Store::Reader object using that class' open
264
39
  # method.
265
40
  def decompressor(io, &b)
266
- Decompress.open(io, &b)
41
+ Reader.open(io, &b)
267
42
  end
268
43
 
269
44
  # This method signature is part of the interface contract expected by