archive-zip 0.12.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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/NEWS.md +5 -0
  4. data/README.md +1 -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/dos_time.rb +103 -0
  21. data/lib/archive/zip/entry.rb +86 -70
  22. data/lib/archive/zip.rb +2 -5
  23. metadata +35 -227
  24. data/.yardopts +0 -1
  25. data/Rakefile +0 -247
  26. data/lib/archive/support/binary_stringio.rb +0 -30
  27. data/lib/archive/support/integer.rb +0 -13
  28. data/lib/archive/support/io-like.rb +0 -14
  29. data/lib/archive/support/time.rb +0 -119
  30. data/lib/archive/zip/version.rb +0 -6
  31. data/spec/archive/dos_time_spec.rb +0 -113
  32. data/spec/archive/zip/archive_spec.rb +0 -54
  33. data/spec/archive/zip/codec/deflate/compress/checksum_spec.rb +0 -44
  34. data/spec/archive/zip/codec/deflate/compress/close_spec.rb +0 -45
  35. data/spec/archive/zip/codec/deflate/compress/crc32_spec.rb +0 -23
  36. data/spec/archive/zip/codec/deflate/compress/data_descriptor_spec.rb +0 -74
  37. data/spec/archive/zip/codec/deflate/compress/new_spec.rb +0 -39
  38. data/spec/archive/zip/codec/deflate/compress/open_spec.rb +0 -48
  39. data/spec/archive/zip/codec/deflate/compress/write_spec.rb +0 -111
  40. data/spec/archive/zip/codec/deflate/decompress/checksum_spec.rb +0 -20
  41. data/spec/archive/zip/codec/deflate/decompress/close_spec.rb +0 -34
  42. data/spec/archive/zip/codec/deflate/decompress/crc32_spec.rb +0 -20
  43. data/spec/archive/zip/codec/deflate/decompress/data_descriptor_spec.rb +0 -74
  44. data/spec/archive/zip/codec/deflate/decompress/new_spec.rb +0 -16
  45. data/spec/archive/zip/codec/deflate/decompress/open_spec.rb +0 -29
  46. data/spec/archive/zip/codec/deflate/fixtures/classes.rb +0 -25
  47. data/spec/archive/zip/codec/deflate/fixtures/compressed_file.bin +0 -1
  48. data/spec/archive/zip/codec/deflate/fixtures/compressed_file_nocomp.bin +0 -0
  49. data/spec/archive/zip/codec/deflate/fixtures/raw_file.txt +0 -10
  50. data/spec/archive/zip/codec/null_encryption/decrypt/close_spec.rb +0 -34
  51. data/spec/archive/zip/codec/null_encryption/decrypt/new_spec.rb +0 -16
  52. data/spec/archive/zip/codec/null_encryption/decrypt/open_spec.rb +0 -29
  53. data/spec/archive/zip/codec/null_encryption/decrypt/read_spec.rb +0 -26
  54. data/spec/archive/zip/codec/null_encryption/decrypt/rewind_spec.rb +0 -27
  55. data/spec/archive/zip/codec/null_encryption/decrypt/seek_spec.rb +0 -59
  56. data/spec/archive/zip/codec/null_encryption/decrypt/tell_spec.rb +0 -23
  57. data/spec/archive/zip/codec/null_encryption/encrypt/close_spec.rb +0 -34
  58. data/spec/archive/zip/codec/null_encryption/encrypt/new_spec.rb +0 -16
  59. data/spec/archive/zip/codec/null_encryption/encrypt/open_spec.rb +0 -31
  60. data/spec/archive/zip/codec/null_encryption/encrypt/rewind_spec.rb +0 -28
  61. data/spec/archive/zip/codec/null_encryption/encrypt/seek_spec.rb +0 -52
  62. data/spec/archive/zip/codec/null_encryption/encrypt/tell_spec.rb +0 -31
  63. data/spec/archive/zip/codec/null_encryption/encrypt/write_spec.rb +0 -31
  64. data/spec/archive/zip/codec/null_encryption/fixtures/classes.rb +0 -12
  65. data/spec/archive/zip/codec/null_encryption/fixtures/raw_file.txt +0 -10
  66. data/spec/archive/zip/codec/store/compress/close_spec.rb +0 -34
  67. data/spec/archive/zip/codec/store/compress/data_descriptor_spec.rb +0 -77
  68. data/spec/archive/zip/codec/store/compress/new_spec.rb +0 -16
  69. data/spec/archive/zip/codec/store/compress/open_spec.rb +0 -29
  70. data/spec/archive/zip/codec/store/compress/rewind_spec.rb +0 -28
  71. data/spec/archive/zip/codec/store/compress/seek_spec.rb +0 -52
  72. data/spec/archive/zip/codec/store/compress/tell_spec.rb +0 -31
  73. data/spec/archive/zip/codec/store/compress/write_spec.rb +0 -29
  74. data/spec/archive/zip/codec/store/decompress/close_spec.rb +0 -34
  75. data/spec/archive/zip/codec/store/decompress/data_descriptor_spec.rb +0 -75
  76. data/spec/archive/zip/codec/store/decompress/new_spec.rb +0 -16
  77. data/spec/archive/zip/codec/store/decompress/open_spec.rb +0 -29
  78. data/spec/archive/zip/codec/store/decompress/read_spec.rb +0 -26
  79. data/spec/archive/zip/codec/store/decompress/rewind_spec.rb +0 -27
  80. data/spec/archive/zip/codec/store/decompress/seek_spec.rb +0 -59
  81. data/spec/archive/zip/codec/store/decompress/tell_spec.rb +0 -23
  82. data/spec/archive/zip/codec/store/fixtures/classes.rb +0 -12
  83. data/spec/archive/zip/codec/store/fixtures/raw_file.txt +0 -10
  84. data/spec/archive/zip/codec/traditional_encryption/decrypt/close_spec.rb +0 -53
  85. data/spec/archive/zip/codec/traditional_encryption/decrypt/new_spec.rb +0 -20
  86. data/spec/archive/zip/codec/traditional_encryption/decrypt/open_spec.rb +0 -43
  87. data/spec/archive/zip/codec/traditional_encryption/decrypt/read_spec.rb +0 -127
  88. data/spec/archive/zip/codec/traditional_encryption/decrypt/rewind_spec.rb +0 -36
  89. data/spec/archive/zip/codec/traditional_encryption/decrypt/seek_spec.rb +0 -80
  90. data/spec/archive/zip/codec/traditional_encryption/decrypt/tell_spec.rb +0 -27
  91. data/spec/archive/zip/codec/traditional_encryption/encrypt/close_spec.rb +0 -53
  92. data/spec/archive/zip/codec/traditional_encryption/encrypt/new_spec.rb +0 -20
  93. data/spec/archive/zip/codec/traditional_encryption/encrypt/open_spec.rb +0 -41
  94. data/spec/archive/zip/codec/traditional_encryption/encrypt/rewind_spec.rb +0 -39
  95. data/spec/archive/zip/codec/traditional_encryption/encrypt/seek_spec.rb +0 -73
  96. data/spec/archive/zip/codec/traditional_encryption/encrypt/tell_spec.rb +0 -40
  97. data/spec/archive/zip/codec/traditional_encryption/encrypt/write_spec.rb +0 -114
  98. data/spec/archive/zip/codec/traditional_encryption/fixtures/classes.rb +0 -27
  99. data/spec/archive/zip/codec/traditional_encryption/fixtures/encrypted_file.bin +0 -0
  100. data/spec/archive/zip/codec/traditional_encryption/fixtures/raw_file.txt +0 -10
  101. data/spec/binary_stringio/new_spec.rb +0 -40
  102. data/spec/binary_stringio/set_encoding_spec.rb +0 -17
  103. data/spec/ioextensions/read_exactly_spec.rb +0 -52
  104. data/spec/zlib/fixtures/classes.rb +0 -65
  105. data/spec/zlib/fixtures/compressed_file.bin +0 -1
  106. data/spec/zlib/fixtures/compressed_file_gzip.bin +0 -0
  107. data/spec/zlib/fixtures/compressed_file_huffman.bin +0 -2
  108. data/spec/zlib/fixtures/compressed_file_minmem.bin +0 -0
  109. data/spec/zlib/fixtures/compressed_file_minwin.bin +0 -1
  110. data/spec/zlib/fixtures/compressed_file_nocomp.bin +0 -0
  111. data/spec/zlib/fixtures/compressed_file_raw.bin +0 -1
  112. data/spec/zlib/fixtures/raw_file.txt +0 -10
  113. data/spec/zlib/zreader/checksum_spec.rb +0 -42
  114. data/spec/zlib/zreader/close_spec.rb +0 -16
  115. data/spec/zlib/zreader/compressed_size_spec.rb +0 -20
  116. data/spec/zlib/zreader/new_spec.rb +0 -43
  117. data/spec/zlib/zreader/open_spec.rb +0 -51
  118. data/spec/zlib/zreader/read_spec.rb +0 -58
  119. data/spec/zlib/zreader/rewind_spec.rb +0 -25
  120. data/spec/zlib/zreader/seek_spec.rb +0 -57
  121. data/spec/zlib/zreader/tell_spec.rb +0 -23
  122. data/spec/zlib/zreader/uncompressed_size_spec.rb +0 -20
  123. data/spec/zlib/zwriter/checksum_spec.rb +0 -43
  124. data/spec/zlib/zwriter/close_spec.rb +0 -16
  125. data/spec/zlib/zwriter/compressed_size_spec.rb +0 -21
  126. data/spec/zlib/zwriter/new_spec.rb +0 -66
  127. data/spec/zlib/zwriter/open_spec.rb +0 -70
  128. data/spec/zlib/zwriter/rewind_spec.rb +0 -28
  129. data/spec/zlib/zwriter/seek_spec.rb +0 -52
  130. data/spec/zlib/zwriter/tell_spec.rb +0 -31
  131. data/spec/zlib/zwriter/uncompressed_size_spec.rb +0 -21
  132. data/spec/zlib/zwriter/write_spec.rb +0 -28
@@ -0,0 +1,103 @@
1
+ # encoding: UTF-8
2
+
3
+ module Archive; class Zip
4
+ # A representation of the DOS time structure which can be converted into
5
+ # instances of Time.
6
+ class DOSTime
7
+ include Comparable
8
+
9
+ # Creates a new instance of DOSTime. _dos_time_ is a 4 byte String or
10
+ # unsigned number (Integer) representing an MS-DOS time structure where:
11
+ # Bits 0-4:: 2 second increments (0-29)
12
+ # Bits 5-10:: minutes (0-59)
13
+ # Bits 11-15:: hours (0-24)
14
+ # Bits 16-20:: day (1-31)
15
+ # Bits 21-24:: month (1-12)
16
+ # Bits 25-31:: four digit year minus 1980 (0-119)
17
+ #
18
+ # If _dos_time_ is ommitted or +nil+, a new instance is created based on the
19
+ # current time.
20
+ def initialize(time = nil)
21
+ @dos_time = case time
22
+ when nil
23
+ from_time(Time.now)
24
+ when Time
25
+ from_time(time)
26
+ else
27
+ time
28
+ end
29
+
30
+ validate
31
+ end
32
+
33
+ # Returns 1 if _other_ is a time earlier than this one, 0 if _other_ is the
34
+ # same time, and -1 if _other_ is a later time.
35
+ def cmp(other)
36
+ raise ArgumentError, 'other must be a DOSTime' unless DOSTime === other
37
+ to_i <=> other.to_i
38
+ end
39
+ alias_method :<=>, :cmp
40
+
41
+ # Returns the time value of this object as an integer representing the DOS
42
+ # time structure.
43
+ def to_i
44
+ @dos_time
45
+ end
46
+
47
+ # Returns a Time instance which is equivalent to the time represented by
48
+ # this object.
49
+ def to_time
50
+ second = ((0b11111 & @dos_time) ) * 2
51
+ minute = ((0b111111 << 5 & @dos_time) >> 5)
52
+ hour = ((0b11111 << 11 & @dos_time) >> 11)
53
+ day = ((0b11111 << 16 & @dos_time) >> 16)
54
+ month = ((0b1111 << 21 & @dos_time) >> 21)
55
+ year = ((0b1111111 << 25 & @dos_time) >> 25) + 1980
56
+ return Time.local(year, month, day, hour, minute, second)
57
+ end
58
+
59
+ private
60
+
61
+ # Converts an instance of Time into a DOS date-time structure. Times are
62
+ # bracketed by the limits of the ability of the DOS date-time structure to
63
+ # represent them. Accuracy is 2 seconds and years range from 1980 to 2099.
64
+ def from_time(time)
65
+ dos_sec = time.sec/2
66
+ dos_year = time.year - 1980
67
+ dos_year = 0 if dos_year < 0
68
+ dos_year = 119 if dos_year > 119
69
+
70
+ (dos_sec ) |
71
+ (time.min << 5) |
72
+ (time.hour << 11) |
73
+ (time.day << 16) |
74
+ (time.month << 21) |
75
+ (dos_year << 25)
76
+ end
77
+
78
+ def validate
79
+ second = (0b11111 & @dos_time)
80
+ minute = (0b111111 << 5 & @dos_time) >> 5
81
+ hour = (0b11111 << 11 & @dos_time) >> 11
82
+ day = (0b11111 << 16 & @dos_time) >> 16
83
+ month = (0b1111 << 21 & @dos_time) >> 21
84
+ year = (0b1111111 << 25 & @dos_time) >> 25
85
+
86
+ if second > 29
87
+ raise ArgumentError, 'second must not be greater than 29'
88
+ elsif minute > 59
89
+ raise ArgumentError, 'minute must not be greater than 59'
90
+ elsif hour > 23
91
+ raise ArgumentError, 'hour must not be greater than 23'
92
+ elsif day < 1
93
+ raise ArgumentError, 'day must not be less than 1'
94
+ elsif month < 1
95
+ raise ArgumentError, 'month must not be less than 1'
96
+ elsif month > 12
97
+ raise ArgumentError, 'month must not be greater than 12'
98
+ elsif year > 119
99
+ raise ArgumentError, 'year must not be greater than 119'
100
+ end
101
+ end
102
+ end
103
+ end; end
@@ -1,12 +1,15 @@
1
1
  # encoding: UTF-8
2
2
 
3
+ require 'io/like_helpers/io_wrapper'
4
+
3
5
  require 'archive/support/ioextensions'
4
- require 'archive/support/binary_stringio'
6
+ require 'archive/support/stringio'
5
7
  require 'archive/zip/codec/deflate'
6
8
  require 'archive/zip/codec/null_encryption'
7
9
  require 'archive/zip/codec/store'
8
10
  require 'archive/zip/codec/traditional_encryption'
9
11
  require 'archive/zip/data_descriptor'
12
+ require 'archive/zip/dos_time'
10
13
  require 'archive/zip/error'
11
14
  require 'archive/zip/extra_field'
12
15
 
@@ -220,6 +223,8 @@ module Archive; class Zip
220
223
  cfr = parse_central_file_record(io)
221
224
  next_record_position = io.pos
222
225
  io.seek(cfr.local_header_position)
226
+ IOExtensions.read_exactly(io, 4)
227
+ io.pos -= 4
223
228
  unless IOExtensions.read_exactly(io, 4) == LFH_SIGNATURE then
224
229
  raise Zip::EntryError, 'bad local file header signature'
225
230
  end
@@ -258,7 +263,9 @@ module Archive; class Zip
258
263
 
259
264
  # Create the entry.
260
265
  expanded_path = expand_path(cfr.zip_path)
261
- io_window = IOWindow.new(io, io.pos, cfr.compressed_size)
266
+ io_window = IOWindow.new(
267
+ IO::LikeHelpers::IOWrapper.new(io), io.pos, cfr.compressed_size
268
+ )
262
269
  if cfr.zip_path[-1..-1] == '/' then
263
270
  # This is a directory entry.
264
271
  entry = Entry::Directory.new(expanded_path, io_window)
@@ -391,23 +398,31 @@ module Archive; class Zip
391
398
  raise Zip::EntryError, 'unexpected end of file'
392
399
  end
393
400
 
401
+ def self.parse_extra_fields(bytes)
402
+ extra_fields = []
403
+ idx = 0
404
+ while idx < bytes.size do
405
+ raise EntryError, 'insufficient data available' if bytes.size < idx + 4
406
+ header_id, data_size = bytes[idx, 4].unpack('vv')
407
+ idx += 4
408
+
409
+ if bytes.size < idx + data_size
410
+ raise EntryError, 'insufficient data available'
411
+ end
412
+ data = bytes[idx, data_size]
413
+ idx += data_size
414
+
415
+ extra_fields << yield(header_id, data)
416
+ end
417
+ extra_fields
418
+ end
419
+
394
420
  # Parses the extra fields for central file records and returns an array of
395
421
  # extra field objects. _bytes_ must be a String containing all of the extra
396
422
  # field data to be parsed.
397
423
  def self.parse_central_extra_fields(bytes)
398
- BinaryStringIO.open(bytes) do |io|
399
- extra_fields = []
400
- while ! io.eof? do
401
- begin
402
- header_id, data_size = IOExtensions.read_exactly(io, 4).unpack('vv')
403
- data = IOExtensions.read_exactly(io, data_size)
404
- rescue ::EOFError
405
- raise EntryError, 'insufficient data available'
406
- end
407
-
408
- extra_fields << ExtraField.parse_central(header_id, data)
409
- end
410
- extra_fields
424
+ parse_extra_fields(bytes) do |header_id, data|
425
+ ExtraField.parse_central(header_id, data)
411
426
  end
412
427
  end
413
428
 
@@ -415,19 +430,8 @@ module Archive; class Zip
415
430
  # extra field objects. _bytes_ must be a String containing all of the extra
416
431
  # field data to be parsed.
417
432
  def self.parse_local_extra_fields(bytes)
418
- BinaryStringIO.open(bytes) do |io|
419
- extra_fields = []
420
- while ! io.eof? do
421
- begin
422
- header_id, data_size = IOExtensions.read_exactly(io, 4).unpack('vv')
423
- data = IOExtensions.read_exactly(io, data_size)
424
- rescue ::EOFError
425
- raise EntryError, 'insufficient data available'
426
- end
427
-
428
- extra_fields << ExtraField.parse_local(header_id, data)
429
- end
430
- extra_fields
433
+ parse_extra_fields(bytes) do |header_id, data|
434
+ ExtraField.parse_local(header_id, data)
431
435
  end
432
436
  end
433
437
 
@@ -604,11 +608,11 @@ module Archive; class Zip
604
608
  if encryption_codec.class == Codec::TraditionalEncryption then
605
609
  # HACK:
606
610
  # According to the ZIP specification, a trailing data descriptor should
607
- # only be required when writing to non-seekable IO , but InfoZIP
608
- # *always* does this when using traditional encryption even though it
609
- # will also write the data descriptor in the usual place if possible.
610
- # Failure to emulate InfoZIP in this behavior will prevent InfoZIP
611
- # compatibility with traditionally encrypted entries.
611
+ # only be required when writing to non-seekable IO, but InfoZIP *always*
612
+ # does this when using traditional encryption even though it will also
613
+ # write the data descriptor in the usual place if possible. Failure to
614
+ # emulate InfoZIP in this behavior will prevent InfoZIP compatibility
615
+ # with traditionally encrypted entries.
612
616
  need_trailing_data_descriptor = true
613
617
  # HACK:
614
618
  # The InfoZIP implementation of traditional encryption requires that the
@@ -639,7 +643,7 @@ module Archive; class Zip
639
643
  version_needed_to_extract,
640
644
  general_purpose_flags,
641
645
  compression_codec.compression_method,
642
- mtime.to_dos_time.to_i,
646
+ DOSTime.new(mtime).to_i,
643
647
  0,
644
648
  0,
645
649
  0,
@@ -649,20 +653,24 @@ module Archive; class Zip
649
653
  )
650
654
  bytes_written += io.write(zip_path)
651
655
  bytes_written += io.write(extra_field_data)
656
+ # Flush buffered data here because writing to the compression pipeline
657
+ # next bypasses the buffer.
658
+ io.flush
652
659
 
653
660
  # Pipeline a compressor into an encryptor, write all the file data to the
654
661
  # compressor, and get a data descriptor from it.
655
- encryption_codec.encryptor(io, password) do |e|
656
- compression_codec.compressor(e) do |c|
657
- dump_file_data(c)
658
- c.close(false)
659
- @data_descriptor = DataDescriptor.new(
660
- c.data_descriptor.crc32,
661
- c.data_descriptor.compressed_size + encryption_codec.header_size,
662
- c.data_descriptor.uncompressed_size
663
- )
664
- end
665
- e.close(false)
662
+ compression_codec.compressor(
663
+ encryption_codec.encryptor(
664
+ IO::LikeHelpers::IOWrapper.open(io, autoclose: false), password
665
+ )
666
+ ) do |c|
667
+ dump_file_data(c)
668
+ c.close
669
+ @data_descriptor = DataDescriptor.new(
670
+ c.data_descriptor.crc32,
671
+ c.data_descriptor.compressed_size + encryption_codec.header_size,
672
+ c.data_descriptor.uncompressed_size
673
+ )
666
674
  end
667
675
  bytes_written += @data_descriptor.compressed_size
668
676
 
@@ -735,7 +743,7 @@ module Archive; class Zip
735
743
  version_needed_to_extract,
736
744
  general_purpose_flags,
737
745
  compression_codec.compression_method,
738
- mtime.to_dos_time.to_i
746
+ DOSTime.new(mtime).to_i
739
747
  ].pack('vvvvV')
740
748
  )
741
749
  bytes_written += @data_descriptor.dump(io)
@@ -912,18 +920,18 @@ module Archive; class Zip; module Entry
912
920
  def link_target
913
921
  return @link_target unless @link_target.nil?
914
922
 
915
- raw_data.rewind
916
- encryption_codec.decryptor(raw_data, password) do |decryptor|
917
- compression_codec.decompressor(decryptor) do |decompressor|
918
- @link_target = decompressor.read
919
- # Verify that the extracted data is good.
920
- begin
921
- unless expected_data_descriptor.nil? then
922
- expected_data_descriptor.verify(decompressor.data_descriptor)
923
- end
924
- rescue => e
925
- raise Zip::EntryError, "`#{zip_path}': #{e.message}"
923
+ raw_data.seek(0)
924
+ compression_codec.decompressor(
925
+ encryption_codec.decryptor(raw_data, password)
926
+ ) do |decompressor|
927
+ @link_target = decompressor.read
928
+ # Verify that the extracted data is good.
929
+ begin
930
+ unless expected_data_descriptor.nil? then
931
+ expected_data_descriptor.verify(decompressor.data_descriptor)
926
932
  end
933
+ rescue => e
934
+ raise Zip::EntryError, "`#{zip_path}': #{e.message}"
927
935
  end
928
936
  end
929
937
  @link_target
@@ -1064,20 +1072,22 @@ module Archive; class Zip; module Entry
1064
1072
  def file_data
1065
1073
  return @file_data unless @file_data.nil? || @file_data.closed?
1066
1074
 
1067
- unless raw_data.nil? then
1068
- raw_data.rewind
1069
- @file_data = compression_codec.decompressor(
1070
- encryption_codec.decryptor(raw_data, password)
1071
- )
1072
- else
1075
+ if raw_data.nil? then
1073
1076
  if @file_path.nil? then
1074
- simulated_raw_data = BinaryStringIO.new
1077
+ simulated_raw_data = StringIO.new('', 'rb')
1075
1078
  else
1076
1079
  simulated_raw_data = ::File.new(@file_path, 'rb')
1077
1080
  end
1078
1081
  # Ensure that the IO-like object can return a data descriptor so that
1079
1082
  # it's possible to verify extraction later if desired.
1080
- @file_data = Zip::Codec::Store.new.decompressor(simulated_raw_data)
1083
+ @file_data = Zip::Codec::Store.new.decompressor(
1084
+ IO::LikeHelpers::IOWrapper.new(simulated_raw_data)
1085
+ )
1086
+ else
1087
+ raw_data.seek(0)
1088
+ @file_data = compression_codec.decompressor(
1089
+ encryption_codec.decryptor(raw_data, password)
1090
+ )
1081
1091
  end
1082
1092
  @file_data
1083
1093
  end
@@ -1140,8 +1150,10 @@ module Archive; class Zip; module Entry
1140
1150
 
1141
1151
  # Dump the file contents.
1142
1152
  ::File.open(file_path, 'wb') do |f|
1143
- while buffer = file_data.read(4096) do
1144
- f.write(buffer)
1153
+ begin
1154
+ loop do f.write(file_data.read(8192)) end
1155
+ rescue EOFError
1156
+ # Ignore
1145
1157
  end
1146
1158
  end
1147
1159
 
@@ -1162,7 +1174,7 @@ module Archive; class Zip; module Entry
1162
1174
  # Attempt to rewind the file data back to the beginning, but ignore
1163
1175
  # errors.
1164
1176
  begin
1165
- file_data.rewind
1177
+ file_data.seek(0)
1166
1178
  rescue
1167
1179
  # Ignore.
1168
1180
  end
@@ -1174,7 +1186,11 @@ module Archive; class Zip; module Entry
1174
1186
 
1175
1187
  # Write the file data to _io_.
1176
1188
  def dump_file_data(io)
1177
- while buffer = file_data.read(4096) do io.write(buffer) end
1189
+ begin
1190
+ loop do io.write(file_data.read(8192)) end
1191
+ rescue EOFError
1192
+ # Ignore
1193
+ end
1178
1194
 
1179
1195
  # Attempt to ensure that the file data will still be in a readable state
1180
1196
  # at the beginning of the data for the next user, but close it if possible
@@ -1184,7 +1200,7 @@ module Archive; class Zip; module Entry
1184
1200
  # reinitialize the IO object it returns, so attempt to rewind the file
1185
1201
  # data back to the beginning, but ignore errors.
1186
1202
  begin
1187
- file_data.rewind
1203
+ file_data.seek(0)
1188
1204
  rescue
1189
1205
  # Ignore.
1190
1206
  end
data/lib/archive/zip.rb CHANGED
@@ -6,7 +6,6 @@ require 'tempfile'
6
6
 
7
7
  require 'archive/support/ioextensions'
8
8
  require 'archive/support/iowindow'
9
- require 'archive/support/time'
10
9
  require 'archive/support/zlib'
11
10
  require 'archive/zip/codec'
12
11
  require 'archive/zip/entry'
@@ -112,7 +111,7 @@ module Archive # :nodoc:
112
111
  begin
113
112
  yield(zf)
114
113
  ensure
115
- zf.close unless zf.closed?
114
+ zf.close
116
115
  end
117
116
  end
118
117
 
@@ -164,10 +163,8 @@ module Archive # :nodoc:
164
163
  #
165
164
  # <b>NOTE:</b> The underlying stream is only closed if the archive was
166
165
  # opened with a String for the _archive_ parameter.
167
- #
168
- # Raises Archive::Zip::IOError if called more than once.
169
166
  def close
170
- raise IOError, 'closed archive' if closed?
167
+ return nil if closed?
171
168
 
172
169
  if writable? then
173
170
  # Write the new archive contents.