rubyzip 1.1.7 → 2.3.2

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 (101) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +137 -54
  3. data/Rakefile +6 -4
  4. data/lib/zip/central_directory.rb +17 -13
  5. data/lib/zip/compressor.rb +1 -2
  6. data/lib/zip/constants.rb +57 -5
  7. data/lib/zip/crypto/decrypted_io.rb +40 -0
  8. data/lib/zip/crypto/null_encryption.rb +4 -6
  9. data/lib/zip/crypto/traditional_encryption.rb +14 -14
  10. data/lib/zip/decompressor.rb +22 -4
  11. data/lib/zip/deflater.rb +8 -6
  12. data/lib/zip/dos_time.rb +17 -13
  13. data/lib/zip/entry.rb +171 -148
  14. data/lib/zip/entry_set.rb +16 -14
  15. data/lib/zip/errors.rb +3 -0
  16. data/lib/zip/extra_field/generic.rb +14 -13
  17. data/lib/zip/extra_field/ntfs.rb +18 -16
  18. data/lib/zip/extra_field/old_unix.rb +12 -11
  19. data/lib/zip/extra_field/universal_time.rb +46 -16
  20. data/lib/zip/extra_field/unix.rb +10 -9
  21. data/lib/zip/extra_field/zip64.rb +15 -12
  22. data/lib/zip/extra_field/zip64_placeholder.rb +1 -2
  23. data/lib/zip/extra_field.rb +18 -16
  24. data/lib/zip/file.rb +147 -115
  25. data/lib/zip/filesystem.rb +289 -272
  26. data/lib/zip/inflater.rb +24 -36
  27. data/lib/zip/input_stream.rb +44 -28
  28. data/lib/zip/ioextras/abstract_input_stream.rb +24 -17
  29. data/lib/zip/ioextras/abstract_output_stream.rb +4 -6
  30. data/lib/zip/ioextras.rb +2 -4
  31. data/lib/zip/null_compressor.rb +2 -2
  32. data/lib/zip/null_decompressor.rb +3 -11
  33. data/lib/zip/null_input_stream.rb +0 -0
  34. data/lib/zip/output_stream.rb +25 -17
  35. data/lib/zip/pass_thru_compressor.rb +6 -6
  36. data/lib/zip/pass_thru_decompressor.rb +14 -24
  37. data/lib/zip/streamable_directory.rb +3 -3
  38. data/lib/zip/streamable_stream.rb +7 -11
  39. data/lib/zip/version.rb +1 -1
  40. data/lib/zip.rb +15 -6
  41. data/samples/example.rb +29 -39
  42. data/samples/example_filesystem.rb +16 -18
  43. data/samples/example_recursive.rb +31 -25
  44. data/samples/gtk_ruby_zip.rb +84 -0
  45. data/samples/qtzip.rb +23 -32
  46. data/samples/write_simple.rb +10 -13
  47. data/samples/zipfind.rb +33 -40
  48. metadata +50 -141
  49. data/samples/gtkRubyzip.rb +0 -86
  50. data/test/basic_zip_file_test.rb +0 -64
  51. data/test/central_directory_entry_test.rb +0 -73
  52. data/test/central_directory_test.rb +0 -104
  53. data/test/crypto/null_encryption_test.rb +0 -53
  54. data/test/crypto/traditional_encryption_test.rb +0 -80
  55. data/test/data/WarnInvalidDate.zip +0 -0
  56. data/test/data/file1.txt +0 -46
  57. data/test/data/file1.txt.deflatedData +0 -0
  58. data/test/data/file2.txt +0 -1504
  59. data/test/data/globTest/foo/bar/baz/foo.txt +0 -0
  60. data/test/data/globTest/foo.txt +0 -0
  61. data/test/data/globTest/food.txt +0 -0
  62. data/test/data/globTest.zip +0 -0
  63. data/test/data/mimetype +0 -1
  64. data/test/data/notzippedruby.rb +0 -7
  65. data/test/data/ntfs.zip +0 -0
  66. data/test/data/rubycode.zip +0 -0
  67. data/test/data/rubycode2.zip +0 -0
  68. data/test/data/testDirectory.bin +0 -0
  69. data/test/data/zip64-sample.zip +0 -0
  70. data/test/data/zipWithDirs.zip +0 -0
  71. data/test/data/zipWithEncryption.zip +0 -0
  72. data/test/deflater_test.rb +0 -67
  73. data/test/encryption_test.rb +0 -42
  74. data/test/entry_set_test.rb +0 -138
  75. data/test/entry_test.rb +0 -165
  76. data/test/errors_test.rb +0 -36
  77. data/test/extra_field_test.rb +0 -78
  78. data/test/file_extract_directory_test.rb +0 -56
  79. data/test/file_extract_test.rb +0 -90
  80. data/test/file_split_test.rb +0 -60
  81. data/test/file_test.rb +0 -559
  82. data/test/filesystem/dir_iterator_test.rb +0 -62
  83. data/test/filesystem/directory_test.rb +0 -131
  84. data/test/filesystem/file_mutating_test.rb +0 -100
  85. data/test/filesystem/file_nonmutating_test.rb +0 -514
  86. data/test/filesystem/file_stat_test.rb +0 -66
  87. data/test/gentestfiles.rb +0 -134
  88. data/test/inflater_test.rb +0 -14
  89. data/test/input_stream_test.rb +0 -170
  90. data/test/ioextras/abstract_input_stream_test.rb +0 -103
  91. data/test/ioextras/abstract_output_stream_test.rb +0 -106
  92. data/test/ioextras/fake_io_test.rb +0 -18
  93. data/test/local_entry_test.rb +0 -156
  94. data/test/output_stream_test.rb +0 -129
  95. data/test/pass_thru_compressor_test.rb +0 -31
  96. data/test/pass_thru_decompressor_test.rb +0 -15
  97. data/test/settings_test.rb +0 -92
  98. data/test/test_helper.rb +0 -228
  99. data/test/unicode_file_names_and_comments_test.rb +0 -52
  100. data/test/zip64_full_test.rb +0 -53
  101. data/test/zip64_support_test.rb +0 -15
data/lib/zip/entry_set.rb CHANGED
@@ -5,7 +5,7 @@ module Zip
5
5
 
6
6
  def initialize(an_enumerable = [])
7
7
  super()
8
- @entry_set = {}
8
+ @entry_set = {}
9
9
  an_enumerable.each { |o| push(o) }
10
10
  end
11
11
 
@@ -18,28 +18,24 @@ module Zip
18
18
  end
19
19
 
20
20
  def <<(entry)
21
- @entry_set[to_key(entry)] = entry
21
+ @entry_set[to_key(entry)] = entry if entry
22
22
  end
23
23
 
24
- alias :push :<<
24
+ alias push <<
25
25
 
26
26
  def size
27
27
  @entry_set.size
28
28
  end
29
29
 
30
- alias :length :size
30
+ alias length size
31
31
 
32
32
  def delete(entry)
33
- if @entry_set.delete(to_key(entry))
34
- entry
35
- else
36
- nil
37
- end
33
+ entry if @entry_set.delete(to_key(entry))
38
34
  end
39
35
 
40
- def each(&block)
36
+ def each
41
37
  @entry_set = sorted_entries.dup.each do |_, value|
42
- block.call(value)
38
+ yield(value)
43
39
  end
44
40
  end
45
41
 
@@ -49,11 +45,12 @@ module Zip
49
45
 
50
46
  # deep clone
51
47
  def dup
52
- EntrySet.new(@entry_set.map { |key, value| value.dup })
48
+ EntrySet.new(@entry_set.values.map(&:dup))
53
49
  end
54
50
 
55
51
  def ==(other)
56
52
  return false unless other.kind_of?(EntrySet)
53
+
57
54
  @entry_set.values == other.entry_set.values
58
55
  end
59
56
 
@@ -61,22 +58,27 @@ module Zip
61
58
  @entry_set[to_key(entry.parent_as_string)]
62
59
  end
63
60
 
64
- def glob(pattern, flags = ::File::FNM_PATHNAME|::File::FNM_DOTMATCH)
61
+ def glob(pattern, flags = ::File::FNM_PATHNAME | ::File::FNM_DOTMATCH | ::File::FNM_EXTGLOB)
65
62
  entries.map do |entry|
66
63
  next nil unless ::File.fnmatch(pattern, entry.name.chomp('/'), flags)
64
+
67
65
  yield(entry) if block_given?
68
66
  entry
69
67
  end.compact
70
68
  end
71
69
 
72
70
  protected
71
+
73
72
  def sorted_entries
74
73
  ::Zip.sort_entries ? Hash[@entry_set.sort] : @entry_set
75
74
  end
76
75
 
77
76
  private
77
+
78
78
  def to_key(entry)
79
- entry.to_s.chomp('/')
79
+ k = entry.to_s.chomp('/')
80
+ k.downcase! if ::Zip.case_insensitive_match
81
+ k
80
82
  end
81
83
  end
82
84
  end
data/lib/zip/errors.rb CHANGED
@@ -4,7 +4,10 @@ module Zip
4
4
  class DestinationFileExistsError < Error; end
5
5
  class CompressionMethodError < Error; end
6
6
  class EntryNameError < Error; end
7
+ class EntrySizeError < Error; end
7
8
  class InternalError < Error; end
9
+ class GPFBit3Error < Error; end
10
+ class DecompressionError < Error; end
8
11
 
9
12
  # Backwards compatibility with v1 (delete in v2)
10
13
  ZipError = Error
@@ -1,43 +1,44 @@
1
1
  module Zip
2
2
  class ExtraField::Generic
3
3
  def self.register_map
4
- if self.const_defined?(:HEADER_ID)
5
- ::Zip::ExtraField::ID_MAP[self.const_get(:HEADER_ID)] = self
6
- end
4
+ return unless const_defined?(:HEADER_ID)
5
+
6
+ ::Zip::ExtraField::ID_MAP[const_get(:HEADER_ID)] = self
7
7
  end
8
8
 
9
9
  def self.name
10
- @name ||= self.to_s.split("::")[-1]
10
+ @name ||= to_s.split('::')[-1]
11
11
  end
12
12
 
13
13
  # return field [size, content] or false
14
14
  def initial_parse(binstr)
15
- if !binstr
16
- # If nil, start with empty.
17
- return false
18
- elsif binstr[0, 2] != self.class.const_get(:HEADER_ID)
19
- $stderr.puts "Warning: weired extra feild header ID. skip parsing"
15
+ return false unless binstr
16
+
17
+ if binstr[0, 2] != self.class.const_get(:HEADER_ID)
18
+ warn 'WARNING: weird extra field header ID. Skip parsing it.'
20
19
  return false
21
20
  end
22
- [binstr[2, 2].unpack("v")[0], binstr[4..-1]]
21
+
22
+ [binstr[2, 2].unpack1('v'), binstr[4..-1]]
23
23
  end
24
24
 
25
25
  def ==(other)
26
26
  return false if self.class != other.class
27
+
27
28
  each do |k, v|
28
- v != other[k] and return false
29
+ return false if v != other[k]
29
30
  end
30
31
  true
31
32
  end
32
33
 
33
34
  def to_local_bin
34
35
  s = pack_for_local
35
- self.class.const_get(:HEADER_ID) + [s.bytesize].pack("v") << s
36
+ self.class.const_get(:HEADER_ID) + [s.bytesize].pack('v') << s
36
37
  end
37
38
 
38
39
  def to_c_dir_bin
39
40
  s = pack_for_c_dir
40
- self.class.const_get(:HEADER_ID) + [s.bytesize].pack("v") << s
41
+ self.class.const_get(:HEADER_ID) + [s.bytesize].pack('v') << s
41
42
  end
42
43
  end
43
44
  end
@@ -5,33 +5,34 @@ module Zip
5
5
  HEADER_ID = [0x000A].pack('v')
6
6
  register_map
7
7
 
8
- WINDOWS_TICK = 10000000.0
9
- SEC_TO_UNIX_EPOCH = 11644473600
8
+ WINDOWS_TICK = 10_000_000.0
9
+ SEC_TO_UNIX_EPOCH = 11_644_473_600
10
10
 
11
11
  def initialize(binstr = nil)
12
12
  @ctime = nil
13
13
  @mtime = nil
14
14
  @atime = nil
15
- binstr and merge(binstr)
15
+ binstr && merge(binstr)
16
16
  end
17
17
 
18
18
  attr_accessor :atime, :ctime, :mtime
19
19
 
20
20
  def merge(binstr)
21
21
  return if binstr.empty?
22
+
22
23
  size, content = initial_parse(binstr)
23
- (size && content) or return
24
+ (size && content) || return
24
25
 
25
26
  content = content[4..-1]
26
27
  tags = parse_tags(content)
27
28
 
28
29
  tag1 = tags[1]
29
- if tag1
30
- ntfs_mtime, ntfs_atime, ntfs_ctime = tag1.unpack("Q<Q<Q<")
31
- ntfs_mtime and @mtime ||= from_ntfs_time(ntfs_mtime)
32
- ntfs_atime and @atime ||= from_ntfs_time(ntfs_atime)
33
- ntfs_ctime and @ctime ||= from_ntfs_time(ntfs_ctime)
34
- end
30
+ return unless tag1
31
+
32
+ ntfs_mtime, ntfs_atime, ntfs_ctime = tag1.unpack('Q<Q<Q<')
33
+ ntfs_mtime && @mtime ||= from_ntfs_time(ntfs_mtime)
34
+ ntfs_atime && @atime ||= from_ntfs_time(ntfs_atime)
35
+ ntfs_ctime && @ctime ||= from_ntfs_time(ntfs_ctime)
35
36
  end
36
37
 
37
38
  def ==(other)
@@ -48,16 +49,14 @@ module Zip
48
49
  # But 7-zip for Windows only stores at central dir
49
50
  def pack_for_c_dir
50
51
  # reserved 0 and tag 1
51
- s = [0, 1].pack("Vv")
52
+ s = [0, 1].pack('Vv')
52
53
 
53
54
  tag1 = ''.force_encoding(Encoding::BINARY)
54
55
  if @mtime
55
56
  tag1 << [to_ntfs_time(@mtime)].pack('Q<')
56
57
  if @atime
57
58
  tag1 << [to_ntfs_time(@atime)].pack('Q<')
58
- if @ctime
59
- tag1 << [to_ntfs_time(@ctime)].pack('Q<')
60
- end
59
+ tag1 << [to_ntfs_time(@ctime)].pack('Q<') if @ctime
61
60
  end
62
61
  end
63
62
  s << [tag1.bytesize].pack('v') << tag1
@@ -65,14 +64,17 @@ module Zip
65
64
  end
66
65
 
67
66
  private
67
+
68
68
  def parse_tags(content)
69
69
  return {} if content.nil?
70
+
70
71
  tags = {}
71
72
  i = 0
72
- while i < content.bytesize do
73
+ while i < content.bytesize
73
74
  tag, size = content[i, 4].unpack('vv')
74
75
  i += 4
75
76
  break unless tag && size
77
+
76
78
  value = content[i, size]
77
79
  i += size
78
80
  tags[tag] = value
@@ -89,4 +91,4 @@ module Zip
89
91
  ((time.to_f + SEC_TO_UNIX_EPOCH) * WINDOWS_TICK).to_i
90
92
  end
91
93
  end
92
- end
94
+ end
@@ -1,7 +1,7 @@
1
1
  module Zip
2
2
  # Olf Info-ZIP Extra for UNIX uid/gid and file timestampes
3
3
  class ExtraField::OldUnix < ExtraField::Generic
4
- HEADER_ID = "UX"
4
+ HEADER_ID = 'UX'
5
5
  register_map
6
6
 
7
7
  def initialize(binstr = nil)
@@ -9,37 +9,38 @@ module Zip
9
9
  @gid = 0
10
10
  @atime = nil
11
11
  @mtime = nil
12
- binstr and merge(binstr)
12
+ binstr && merge(binstr)
13
13
  end
14
14
 
15
15
  attr_accessor :uid, :gid, :atime, :mtime
16
16
 
17
17
  def merge(binstr)
18
18
  return if binstr.empty?
19
+
19
20
  size, content = initial_parse(binstr)
20
21
  # size: 0 for central directory. 4 for local header
21
- return if (!size || size == 0)
22
- atime, mtime, uid, gid = content.unpack("VVvv")
22
+ return if !size || size == 0
23
+
24
+ atime, mtime, uid, gid = content.unpack('VVvv')
23
25
  @uid ||= uid
24
26
  @gid ||= gid
25
27
  @atime ||= atime
26
- @mtime ||= mtime
28
+ @mtime ||= mtime # rubocop:disable Naming/MemoizedInstanceVariableName
27
29
  end
28
30
 
29
31
  def ==(other)
30
32
  @uid == other.uid &&
31
33
  @gid == other.gid &&
32
- @atime == other.atime &&
33
- @mtime == other.mtime
34
+ @atime == other.atime &&
35
+ @mtime == other.mtime
34
36
  end
35
37
 
36
38
  def pack_for_local
37
- [@atime, @mtime, @uid, @gid].pack("VVvv")
39
+ [@atime, @mtime, @uid, @gid].pack('VVvv')
38
40
  end
39
41
 
40
42
  def pack_for_c_dir
41
- [@atime, @mtime].pack("VV")
43
+ [@atime, @mtime].pack('VV')
42
44
  end
43
45
  end
44
-
45
- end
46
+ end
@@ -1,27 +1,57 @@
1
1
  module Zip
2
2
  # Info-ZIP Additional timestamp field
3
3
  class ExtraField::UniversalTime < ExtraField::Generic
4
- HEADER_ID = "UT"
4
+ HEADER_ID = 'UT'
5
5
  register_map
6
6
 
7
+ ATIME_MASK = 0b010
8
+ CTIME_MASK = 0b100
9
+ MTIME_MASK = 0b001
10
+
7
11
  def initialize(binstr = nil)
8
12
  @ctime = nil
9
13
  @mtime = nil
10
14
  @atime = nil
11
- @flag = nil
12
- binstr and merge(binstr)
15
+ @flag = 0
16
+
17
+ merge(binstr) unless binstr.nil?
18
+ end
19
+
20
+ attr_reader :atime, :ctime, :mtime, :flag
21
+
22
+ def atime=(time)
23
+ @flag = time.nil? ? @flag & ~ATIME_MASK : @flag | ATIME_MASK
24
+ @atime = time
25
+ end
26
+
27
+ def ctime=(time)
28
+ @flag = time.nil? ? @flag & ~CTIME_MASK : @flag | CTIME_MASK
29
+ @ctime = time
13
30
  end
14
31
 
15
- attr_accessor :atime, :ctime, :mtime, :flag
32
+ def mtime=(time)
33
+ @flag = time.nil? ? @flag & ~MTIME_MASK : @flag | MTIME_MASK
34
+ @mtime = time
35
+ end
16
36
 
17
37
  def merge(binstr)
18
38
  return if binstr.empty?
39
+
19
40
  size, content = initial_parse(binstr)
20
- size or return
21
- @flag, mtime, atime, ctime = content.unpack("CVVV")
22
- mtime and @mtime ||= ::Zip::DOSTime.at(mtime)
23
- atime and @atime ||= ::Zip::DOSTime.at(atime)
24
- ctime and @ctime ||= ::Zip::DOSTime.at(ctime)
41
+ return if !size || size <= 0
42
+
43
+ @flag, *times = content.unpack('Cl<l<l<')
44
+
45
+ # Parse the timestamps, in order, based on which flags are set.
46
+ return if times[0].nil?
47
+
48
+ @mtime ||= ::Zip::DOSTime.at(times.shift) unless @flag & MTIME_MASK == 0
49
+ return if times[0].nil?
50
+
51
+ @atime ||= ::Zip::DOSTime.at(times.shift) unless @flag & ATIME_MASK == 0
52
+ return if times[0].nil?
53
+
54
+ @ctime ||= ::Zip::DOSTime.at(times.shift) unless @flag & CTIME_MASK == 0
25
55
  end
26
56
 
27
57
  def ==(other)
@@ -31,17 +61,17 @@ module Zip
31
61
  end
32
62
 
33
63
  def pack_for_local
34
- s = [@flag].pack("C")
35
- @flag & 1 != 0 and s << [@mtime.to_i].pack("V")
36
- @flag & 2 != 0 and s << [@atime.to_i].pack("V")
37
- @flag & 4 != 0 and s << [@ctime.to_i].pack("V")
64
+ s = [@flag].pack('C')
65
+ s << [@mtime.to_i].pack('l<') unless @flag & MTIME_MASK == 0
66
+ s << [@atime.to_i].pack('l<') unless @flag & ATIME_MASK == 0
67
+ s << [@ctime.to_i].pack('l<') unless @flag & CTIME_MASK == 0
38
68
  s
39
69
  end
40
70
 
41
71
  def pack_for_c_dir
42
- s = [@flag].pack("C")
43
- @flag & 1 == 1 and s << [@mtime.to_i].pack("V")
72
+ s = [@flag].pack('C')
73
+ s << [@mtime.to_i].pack('l<') unless @flag & MTIME_MASK == 0
44
74
  s
45
75
  end
46
76
  end
47
- end
77
+ end
@@ -1,25 +1,27 @@
1
1
  module Zip
2
2
  # Info-ZIP Extra for UNIX uid/gid
3
3
  class ExtraField::IUnix < ExtraField::Generic
4
- HEADER_ID = "Ux"
4
+ HEADER_ID = 'Ux'
5
5
  register_map
6
6
 
7
7
  def initialize(binstr = nil)
8
8
  @uid = 0
9
9
  @gid = 0
10
- binstr and merge(binstr)
10
+ binstr && merge(binstr)
11
11
  end
12
12
 
13
13
  attr_accessor :uid, :gid
14
14
 
15
15
  def merge(binstr)
16
16
  return if binstr.empty?
17
+
17
18
  size, content = initial_parse(binstr)
18
19
  # size: 0 for central directory. 4 for local header
19
- return if (!size || size == 0)
20
- uid, gid = content.unpack("vv")
21
- @uid ||= uid
22
- @gid ||= gid
20
+ return if !size || size == 0
21
+
22
+ uid, gid = content.unpack('vv')
23
+ @uid ||= uid
24
+ @gid ||= gid # rubocop:disable Naming/MemoizedInstanceVariableName
23
25
  end
24
26
 
25
27
  def ==(other)
@@ -27,12 +29,11 @@ module Zip
27
29
  end
28
30
 
29
31
  def pack_for_local
30
- [@uid, @gid].pack("vv")
32
+ [@uid, @gid].pack('vv')
31
33
  end
32
34
 
33
35
  def pack_for_c_dir
34
36
  ''
35
37
  end
36
38
  end
37
-
38
- end
39
+ end
@@ -6,25 +6,27 @@ module Zip
6
6
  register_map
7
7
 
8
8
  def initialize(binstr = nil)
9
- @content = nil # unparsed binary; we don't actually know what this contains
10
- # without looking for FFs in the associated file header
11
- # call parse after initializing with a binary string
9
+ # unparsed binary; we don't actually know what this contains
10
+ # without looking for FFs in the associated file header
11
+ # call parse after initializing with a binary string
12
+ @content = nil
12
13
  @original_size = nil
13
14
  @compressed_size = nil
14
15
  @relative_header_offset = nil
15
16
  @disk_start_number = nil
16
- binstr and merge(binstr)
17
+ binstr && merge(binstr)
17
18
  end
18
19
 
19
20
  def ==(other)
20
21
  other.original_size == @original_size &&
21
22
  other.compressed_size == @compressed_size &&
22
- other.relative_header_offset == @relative_header_offset &&
23
- other.disk_start_number == @disk_start_number
23
+ other.relative_header_offset == @relative_header_offset &&
24
+ other.disk_start_number == @disk_start_number
24
25
  end
25
26
 
26
27
  def merge(binstr)
27
28
  return if binstr.empty?
29
+
28
30
  _, @content = initial_parse(binstr)
29
31
  end
30
32
 
@@ -44,23 +46,24 @@ module Zip
44
46
  end
45
47
 
46
48
  def extract(size, format)
47
- @content.slice!(0, size).unpack(format)[0]
49
+ @content.slice!(0, size).unpack1(format)
48
50
  end
49
51
  private :extract
50
52
 
51
53
  def pack_for_local
52
54
  # local header entries must contain original size and compressed size; other fields do not apply
53
55
  return '' unless @original_size && @compressed_size
54
- [@original_size, @compressed_size].pack("Q<Q<")
56
+
57
+ [@original_size, @compressed_size].pack('Q<Q<')
55
58
  end
56
59
 
57
60
  def pack_for_c_dir
58
61
  # central directory entries contain only fields that didn't fit in the main entry part
59
62
  packed = ''.force_encoding('BINARY')
60
- packed << [@original_size].pack("Q<") if @original_size
61
- packed << [@compressed_size].pack("Q<") if @compressed_size
62
- packed << [@relative_header_offset].pack("Q<") if @relative_header_offset
63
- packed << [@disk_start_number].pack("V") if @disk_start_number
63
+ packed << [@original_size].pack('Q<') if @original_size
64
+ packed << [@compressed_size].pack('Q<') if @compressed_size
65
+ packed << [@relative_header_offset].pack('Q<') if @relative_header_offset
66
+ packed << [@disk_start_number].pack('V') if @disk_start_number
64
67
  packed
65
68
  end
66
69
  end
@@ -6,8 +6,7 @@ module Zip
6
6
  HEADER_ID = ['9999'].pack('H*') # this ID is used by other libraries such as .NET's Ionic.zip
7
7
  register_map
8
8
 
9
- def initialize(binstr = nil)
10
- end
9
+ def initialize(_binstr = nil); end
11
10
 
12
11
  def pack_for_local
13
12
  "\x00" * 16
@@ -3,30 +3,30 @@ module Zip
3
3
  ID_MAP = {}
4
4
 
5
5
  def initialize(binstr = nil)
6
- binstr and merge(binstr)
6
+ merge(binstr) if binstr
7
7
  end
8
8
 
9
- def extra_field_type_exist(binstr, id, len, i)
9
+ def extra_field_type_exist(binstr, id, len, index)
10
10
  field_name = ID_MAP[id].name
11
- if self.member?(field_name)
12
- self[field_name].merge(binstr[i, len + 4])
11
+ if member?(field_name)
12
+ self[field_name].merge(binstr[index, len + 4])
13
13
  else
14
- field_obj = ID_MAP[id].new(binstr[i, len + 4])
14
+ field_obj = ID_MAP[id].new(binstr[index, len + 4])
15
15
  self[field_name] = field_obj
16
16
  end
17
17
  end
18
18
 
19
- def extra_field_type_unknown(binstr, len, i)
19
+ def extra_field_type_unknown(binstr, len, index)
20
20
  create_unknown_item unless self['Unknown']
21
- if !len || len + 4 > binstr[i..-1].bytesize
22
- self['Unknown'] << binstr[i..-1]
21
+ if !len || len + 4 > binstr[index..-1].bytesize
22
+ self['Unknown'] << binstr[index..-1]
23
23
  return
24
24
  end
25
- self['Unknown'] << binstr[i, len + 4]
25
+ self['Unknown'] << binstr[index, len + 4]
26
26
  end
27
27
 
28
28
  def create_unknown_item
29
- s = ''
29
+ s = +''
30
30
  class << s
31
31
  alias_method :to_c_dir_bin, :to_s
32
32
  alias_method :to_local_bin, :to_s
@@ -36,10 +36,11 @@ module Zip
36
36
 
37
37
  def merge(binstr)
38
38
  return if binstr.empty?
39
+
39
40
  i = 0
40
41
  while i < binstr.bytesize
41
42
  id = binstr[i, 2]
42
- len = binstr[i + 2, 2].to_s.unpack('v').first
43
+ len = binstr[i + 2, 2].to_s.unpack1('v')
43
44
  if id && ID_MAP.member?(id)
44
45
  extra_field_type_exist(binstr, id, len, i)
45
46
  elsif id
@@ -51,9 +52,10 @@ module Zip
51
52
  end
52
53
 
53
54
  def create(name)
54
- unless field_class = ID_MAP.values.find { |k| k.name == name }
55
+ unless (field_class = ID_MAP.values.find { |k| k.name == name })
55
56
  raise Error, "Unknown extra field '#{name}'"
56
57
  end
58
+
57
59
  self[name] = field_class.new
58
60
  end
59
61
 
@@ -61,7 +63,7 @@ module Zip
61
63
  # does not prevent known fields from being read back in
62
64
  def ordered_values
63
65
  result = []
64
- self.each { |k,v| k == 'Unknown' ? result.push(v) : result.unshift(v) }
66
+ each { |k, v| k == 'Unknown' ? result.push(v) : result.unshift(v) }
65
67
  result
66
68
  end
67
69
 
@@ -69,7 +71,7 @@ module Zip
69
71
  ordered_values.map! { |v| v.to_local_bin.force_encoding('BINARY') }.join
70
72
  end
71
73
 
72
- alias :to_s :to_local_bin
74
+ alias to_s to_local_bin
73
75
 
74
76
  def to_c_dir_bin
75
77
  ordered_values.map! { |v| v.to_c_dir_bin.force_encoding('BINARY') }.join
@@ -83,8 +85,8 @@ module Zip
83
85
  to_local_bin.bytesize
84
86
  end
85
87
 
86
- alias :length :local_size
87
- alias :size :local_size
88
+ alias length local_size
89
+ alias size local_size
88
90
  end
89
91
  end
90
92