rubyzip 1.1.7 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +143 -54
  3. data/Rakefile +3 -4
  4. data/lib/zip/central_directory.rb +8 -8
  5. data/lib/zip/compressor.rb +1 -2
  6. data/lib/zip/constants.rb +5 -5
  7. data/lib/zip/crypto/null_encryption.rb +4 -6
  8. data/lib/zip/crypto/traditional_encryption.rb +5 -5
  9. data/lib/zip/decompressor.rb +3 -3
  10. data/lib/zip/deflater.rb +8 -6
  11. data/lib/zip/dos_time.rb +5 -6
  12. data/lib/zip/entry.rb +132 -128
  13. data/lib/zip/entry_set.rb +14 -14
  14. data/lib/zip/errors.rb +2 -0
  15. data/lib/zip/extra_field/generic.rb +8 -8
  16. data/lib/zip/extra_field/ntfs.rb +14 -16
  17. data/lib/zip/extra_field/old_unix.rb +9 -10
  18. data/lib/zip/extra_field/universal_time.rb +14 -14
  19. data/lib/zip/extra_field/unix.rb +8 -9
  20. data/lib/zip/extra_field/zip64.rb +12 -11
  21. data/lib/zip/extra_field/zip64_placeholder.rb +1 -2
  22. data/lib/zip/extra_field.rb +8 -8
  23. data/lib/zip/file.rb +88 -81
  24. data/lib/zip/filesystem.rb +144 -143
  25. data/lib/zip/inflater.rb +5 -5
  26. data/lib/zip/input_stream.rb +22 -13
  27. data/lib/zip/ioextras/abstract_input_stream.rb +6 -10
  28. data/lib/zip/ioextras/abstract_output_stream.rb +3 -5
  29. data/lib/zip/ioextras.rb +1 -3
  30. data/lib/zip/null_compressor.rb +2 -2
  31. data/lib/zip/null_decompressor.rb +3 -3
  32. data/lib/zip/null_input_stream.rb +0 -0
  33. data/lib/zip/output_stream.rb +13 -14
  34. data/lib/zip/pass_thru_compressor.rb +4 -4
  35. data/lib/zip/pass_thru_decompressor.rb +3 -4
  36. data/lib/zip/streamable_directory.rb +2 -2
  37. data/lib/zip/streamable_stream.rb +3 -3
  38. data/lib/zip/version.rb +1 -1
  39. data/lib/zip.rb +13 -5
  40. data/samples/example.rb +29 -39
  41. data/samples/example_filesystem.rb +16 -18
  42. data/samples/example_recursive.rb +31 -25
  43. data/samples/{gtkRubyzip.rb → gtk_ruby_zip.rb} +23 -25
  44. data/samples/qtzip.rb +18 -27
  45. data/samples/write_simple.rb +12 -13
  46. data/samples/zipfind.rb +26 -34
  47. data/test/basic_zip_file_test.rb +11 -15
  48. data/test/case_sensitivity_test.rb +69 -0
  49. data/test/central_directory_entry_test.rb +32 -36
  50. data/test/central_directory_test.rb +46 -50
  51. data/test/crypto/null_encryption_test.rb +8 -4
  52. data/test/crypto/traditional_encryption_test.rb +5 -5
  53. data/test/data/gpbit3stored.zip +0 -0
  54. data/test/data/notzippedruby.rb +1 -1
  55. data/test/data/oddExtraField.zip +0 -0
  56. data/test/data/path_traversal/Makefile +10 -0
  57. data/test/data/path_traversal/jwilk/README.md +5 -0
  58. data/test/data/path_traversal/jwilk/absolute1.zip +0 -0
  59. data/test/data/path_traversal/jwilk/absolute2.zip +0 -0
  60. data/test/data/path_traversal/jwilk/dirsymlink.zip +0 -0
  61. data/test/data/path_traversal/jwilk/dirsymlink2a.zip +0 -0
  62. data/test/data/path_traversal/jwilk/dirsymlink2b.zip +0 -0
  63. data/test/data/path_traversal/jwilk/relative0.zip +0 -0
  64. data/test/data/path_traversal/jwilk/relative2.zip +0 -0
  65. data/test/data/path_traversal/jwilk/symlink.zip +0 -0
  66. data/test/data/path_traversal/relative1.zip +0 -0
  67. data/test/data/path_traversal/tilde.zip +0 -0
  68. data/test/data/path_traversal/tuzovakaoff/README.md +3 -0
  69. data/test/data/path_traversal/tuzovakaoff/absolutepath.zip +0 -0
  70. data/test/data/path_traversal/tuzovakaoff/symlink.zip +0 -0
  71. data/test/data/rubycode.zip +0 -0
  72. data/test/data/test.xls +0 -0
  73. data/test/deflater_test.rb +10 -12
  74. data/test/encryption_test.rb +2 -2
  75. data/test/entry_set_test.rb +50 -25
  76. data/test/entry_test.rb +76 -87
  77. data/test/errors_test.rb +1 -2
  78. data/test/extra_field_test.rb +19 -21
  79. data/test/file_extract_directory_test.rb +12 -14
  80. data/test/file_extract_test.rb +94 -39
  81. data/test/file_permissions_test.rb +65 -0
  82. data/test/file_split_test.rb +24 -27
  83. data/test/file_test.rb +286 -179
  84. data/test/filesystem/dir_iterator_test.rb +13 -17
  85. data/test/filesystem/directory_test.rb +101 -93
  86. data/test/filesystem/file_mutating_test.rb +52 -65
  87. data/test/filesystem/file_nonmutating_test.rb +223 -229
  88. data/test/filesystem/file_stat_test.rb +17 -19
  89. data/test/gentestfiles.rb +54 -62
  90. data/test/inflater_test.rb +1 -1
  91. data/test/input_stream_test.rb +52 -40
  92. data/test/ioextras/abstract_input_stream_test.rb +22 -23
  93. data/test/ioextras/abstract_output_stream_test.rb +33 -33
  94. data/test/ioextras/fake_io_test.rb +1 -1
  95. data/test/local_entry_test.rb +36 -38
  96. data/test/output_stream_test.rb +20 -21
  97. data/test/pass_thru_compressor_test.rb +5 -6
  98. data/test/pass_thru_decompressor_test.rb +0 -1
  99. data/test/path_traversal_test.rb +141 -0
  100. data/test/samples/example_recursive_test.rb +37 -0
  101. data/test/settings_test.rb +18 -15
  102. data/test/test_helper.rb +52 -46
  103. data/test/unicode_file_names_and_comments_test.rb +17 -7
  104. data/test/zip64_full_test.rb +10 -12
  105. data/test/zip64_support_test.rb +0 -1
  106. metadata +100 -66
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,7 +45,7 @@ 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)
@@ -61,7 +57,7 @@ module Zip
61
57
  @entry_set[to_key(entry.parent_as_string)]
62
58
  end
63
59
 
64
- def glob(pattern, flags = ::File::FNM_PATHNAME|::File::FNM_DOTMATCH)
60
+ def glob(pattern, flags = ::File::FNM_PATHNAME | ::File::FNM_DOTMATCH | ::File::FNM_EXTGLOB)
65
61
  entries.map do |entry|
66
62
  next nil unless ::File.fnmatch(pattern, entry.name.chomp('/'), flags)
67
63
  yield(entry) if block_given?
@@ -70,13 +66,17 @@ module Zip
70
66
  end
71
67
 
72
68
  protected
69
+
73
70
  def sorted_entries
74
71
  ::Zip.sort_entries ? Hash[@entry_set.sort] : @entry_set
75
72
  end
76
73
 
77
74
  private
75
+
78
76
  def to_key(entry)
79
- entry.to_s.chomp('/')
77
+ k = entry.to_s.chomp('/')
78
+ k.downcase! if ::Zip.case_insensitive_match
79
+ k
80
80
  end
81
81
  end
82
82
  end
data/lib/zip/errors.rb CHANGED
@@ -4,7 +4,9 @@ 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
8
10
 
9
11
  # Backwards compatibility with v1 (delete in v2)
10
12
  ZipError = Error
@@ -1,13 +1,13 @@
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
4
+ if const_defined?(:HEADER_ID)
5
+ ::Zip::ExtraField::ID_MAP[const_get(:HEADER_ID)] = self
6
6
  end
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
@@ -16,28 +16,28 @@ module Zip
16
16
  # If nil, start with empty.
17
17
  return false
18
18
  elsif binstr[0, 2] != self.class.const_get(:HEADER_ID)
19
- $stderr.puts "Warning: weired extra feild header ID. skip parsing"
19
+ $stderr.puts 'Warning: weired extra feild header ID. skip parsing'
20
20
  return false
21
21
  end
22
- [binstr[2, 2].unpack("v")[0], binstr[4..-1]]
22
+ [binstr[2, 2].unpack('v')[0], binstr[4..-1]]
23
23
  end
24
24
 
25
25
  def ==(other)
26
26
  return false if self.class != other.class
27
27
  each do |k, v|
28
- v != other[k] and return false
28
+ return false if v != other[k]
29
29
  end
30
30
  true
31
31
  end
32
32
 
33
33
  def to_local_bin
34
34
  s = pack_for_local
35
- self.class.const_get(:HEADER_ID) + [s.bytesize].pack("v") << s
35
+ self.class.const_get(:HEADER_ID) + [s.bytesize].pack('v') << s
36
36
  end
37
37
 
38
38
  def to_c_dir_bin
39
39
  s = pack_for_c_dir
40
- self.class.const_get(:HEADER_ID) + [s.bytesize].pack("v") << s
40
+ self.class.const_get(:HEADER_ID) + [s.bytesize].pack('v') << s
41
41
  end
42
42
  end
43
43
  end
@@ -5,14 +5,14 @@ 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
@@ -20,18 +20,17 @@ module Zip
20
20
  def merge(binstr)
21
21
  return if binstr.empty?
22
22
  size, content = initial_parse(binstr)
23
- (size && content) or return
23
+ (size && content) || return
24
24
 
25
25
  content = content[4..-1]
26
26
  tags = parse_tags(content)
27
27
 
28
28
  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
29
+ return unless tag1
30
+ ntfs_mtime, ntfs_atime, ntfs_ctime = tag1.unpack('Q<Q<Q<')
31
+ ntfs_mtime && @mtime ||= from_ntfs_time(ntfs_mtime)
32
+ ntfs_atime && @atime ||= from_ntfs_time(ntfs_atime)
33
+ ntfs_ctime && @ctime ||= from_ntfs_time(ntfs_ctime)
35
34
  end
36
35
 
37
36
  def ==(other)
@@ -48,16 +47,14 @@ module Zip
48
47
  # But 7-zip for Windows only stores at central dir
49
48
  def pack_for_c_dir
50
49
  # reserved 0 and tag 1
51
- s = [0, 1].pack("Vv")
50
+ s = [0, 1].pack('Vv')
52
51
 
53
52
  tag1 = ''.force_encoding(Encoding::BINARY)
54
53
  if @mtime
55
54
  tag1 << [to_ntfs_time(@mtime)].pack('Q<')
56
55
  if @atime
57
56
  tag1 << [to_ntfs_time(@atime)].pack('Q<')
58
- if @ctime
59
- tag1 << [to_ntfs_time(@ctime)].pack('Q<')
60
- end
57
+ tag1 << [to_ntfs_time(@ctime)].pack('Q<') if @ctime
61
58
  end
62
59
  end
63
60
  s << [tag1.bytesize].pack('v') << tag1
@@ -65,11 +62,12 @@ module Zip
65
62
  end
66
63
 
67
64
  private
65
+
68
66
  def parse_tags(content)
69
67
  return {} if content.nil?
70
68
  tags = {}
71
69
  i = 0
72
- while i < content.bytesize do
70
+ while i < content.bytesize
73
71
  tag, size = content[i, 4].unpack('vv')
74
72
  i += 4
75
73
  break unless tag && size
@@ -89,4 +87,4 @@ module Zip
89
87
  ((time.to_f + SEC_TO_UNIX_EPOCH) * WINDOWS_TICK).to_i
90
88
  end
91
89
  end
92
- end
90
+ 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,7 +9,7 @@ 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
@@ -18,8 +18,8 @@ module Zip
18
18
  return if binstr.empty?
19
19
  size, content = initial_parse(binstr)
20
20
  # size: 0 for central directory. 4 for local header
21
- return if (!size || size == 0)
22
- atime, mtime, uid, gid = content.unpack("VVvv")
21
+ return if !size || size == 0
22
+ atime, mtime, uid, gid = content.unpack('VVvv')
23
23
  @uid ||= uid
24
24
  @gid ||= gid
25
25
  @atime ||= atime
@@ -29,17 +29,16 @@ module Zip
29
29
  def ==(other)
30
30
  @uid == other.uid &&
31
31
  @gid == other.gid &&
32
- @atime == other.atime &&
33
- @mtime == other.mtime
32
+ @atime == other.atime &&
33
+ @mtime == other.mtime
34
34
  end
35
35
 
36
36
  def pack_for_local
37
- [@atime, @mtime, @uid, @gid].pack("VVvv")
37
+ [@atime, @mtime, @uid, @gid].pack('VVvv')
38
38
  end
39
39
 
40
40
  def pack_for_c_dir
41
- [@atime, @mtime].pack("VV")
41
+ [@atime, @mtime].pack('VV')
42
42
  end
43
43
  end
44
-
45
- end
44
+ end
@@ -1,7 +1,7 @@
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
7
  def initialize(binstr = nil)
@@ -9,7 +9,7 @@ module Zip
9
9
  @mtime = nil
10
10
  @atime = nil
11
11
  @flag = nil
12
- binstr and merge(binstr)
12
+ binstr && merge(binstr)
13
13
  end
14
14
 
15
15
  attr_accessor :atime, :ctime, :mtime, :flag
@@ -17,11 +17,11 @@ module Zip
17
17
  def merge(binstr)
18
18
  return if binstr.empty?
19
19
  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)
20
+ size || return
21
+ @flag, mtime, atime, ctime = content.unpack('CVVV')
22
+ mtime && @mtime ||= ::Zip::DOSTime.at(mtime)
23
+ atime && @atime ||= ::Zip::DOSTime.at(atime)
24
+ ctime && @ctime ||= ::Zip::DOSTime.at(ctime)
25
25
  end
26
26
 
27
27
  def ==(other)
@@ -31,17 +31,17 @@ module Zip
31
31
  end
32
32
 
33
33
  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")
34
+ s = [@flag].pack('C')
35
+ @flag & 1 != 0 && s << [@mtime.to_i].pack('V')
36
+ @flag & 2 != 0 && s << [@atime.to_i].pack('V')
37
+ @flag & 4 != 0 && s << [@ctime.to_i].pack('V')
38
38
  s
39
39
  end
40
40
 
41
41
  def pack_for_c_dir
42
- s = [@flag].pack("C")
43
- @flag & 1 == 1 and s << [@mtime.to_i].pack("V")
42
+ s = [@flag].pack('C')
43
+ @flag & 1 == 1 && s << [@mtime.to_i].pack('V')
44
44
  s
45
45
  end
46
46
  end
47
- end
47
+ end
@@ -1,13 +1,13 @@
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
@@ -16,10 +16,10 @@ module Zip
16
16
  return if binstr.empty?
17
17
  size, content = initial_parse(binstr)
18
18
  # 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
19
+ return if !size || size == 0
20
+ uid, gid = content.unpack('vv')
21
+ @uid ||= uid
22
+ @gid ||= gid
23
23
  end
24
24
 
25
25
  def ==(other)
@@ -27,12 +27,11 @@ module Zip
27
27
  end
28
28
 
29
29
  def pack_for_local
30
- [@uid, @gid].pack("vv")
30
+ [@uid, @gid].pack('vv')
31
31
  end
32
32
 
33
33
  def pack_for_c_dir
34
34
  ''
35
35
  end
36
36
  end
37
-
38
- end
37
+ end
@@ -6,21 +6,22 @@ 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)
@@ -51,16 +52,16 @@ module Zip
51
52
  def pack_for_local
52
53
  # local header entries must contain original size and compressed size; other fields do not apply
53
54
  return '' unless @original_size && @compressed_size
54
- [@original_size, @compressed_size].pack("Q<Q<")
55
+ [@original_size, @compressed_size].pack('Q<Q<')
55
56
  end
56
57
 
57
58
  def pack_for_c_dir
58
59
  # central directory entries contain only fields that didn't fit in the main entry part
59
60
  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
61
+ packed << [@original_size].pack('Q<') if @original_size
62
+ packed << [@compressed_size].pack('Q<') if @compressed_size
63
+ packed << [@relative_header_offset].pack('Q<') if @relative_header_offset
64
+ packed << [@disk_start_number].pack('V') if @disk_start_number
64
65
  packed
65
66
  end
66
67
  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,12 +3,12 @@ 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
9
  def extra_field_type_exist(binstr, id, len, i)
10
10
  field_name = ID_MAP[id].name
11
- if self.member?(field_name)
11
+ if member?(field_name)
12
12
  self[field_name].merge(binstr[i, len + 4])
13
13
  else
14
14
  field_obj = ID_MAP[id].new(binstr[i, len + 4])
@@ -26,7 +26,7 @@ module Zip
26
26
  end
27
27
 
28
28
  def create_unknown_item
29
- s = ''
29
+ s = ''.dup
30
30
  class << s
31
31
  alias_method :to_c_dir_bin, :to_s
32
32
  alias_method :to_local_bin, :to_s
@@ -51,7 +51,7 @@ module Zip
51
51
  end
52
52
 
53
53
  def create(name)
54
- unless field_class = ID_MAP.values.find { |k| k.name == name }
54
+ unless (field_class = ID_MAP.values.find { |k| k.name == name })
55
55
  raise Error, "Unknown extra field '#{name}'"
56
56
  end
57
57
  self[name] = field_class.new
@@ -61,7 +61,7 @@ module Zip
61
61
  # does not prevent known fields from being read back in
62
62
  def ordered_values
63
63
  result = []
64
- self.each { |k,v| k == 'Unknown' ? result.push(v) : result.unshift(v) }
64
+ each { |k, v| k == 'Unknown' ? result.push(v) : result.unshift(v) }
65
65
  result
66
66
  end
67
67
 
@@ -69,7 +69,7 @@ module Zip
69
69
  ordered_values.map! { |v| v.to_local_bin.force_encoding('BINARY') }.join
70
70
  end
71
71
 
72
- alias :to_s :to_local_bin
72
+ alias to_s to_local_bin
73
73
 
74
74
  def to_c_dir_bin
75
75
  ordered_values.map! { |v| v.to_c_dir_bin.force_encoding('BINARY') }.join
@@ -83,8 +83,8 @@ module Zip
83
83
  to_local_bin.bytesize
84
84
  end
85
85
 
86
- alias :length :local_size
87
- alias :size :local_size
86
+ alias length local_size
87
+ alias size local_size
88
88
  end
89
89
  end
90
90