hotplate 0.0.1

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 (116) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +1 -0
  4. data/bin/toast +2 -0
  5. data/hotplate.gemspec +30 -0
  6. data/lib/hotplate/cli/build.rb +51 -0
  7. data/lib/hotplate/cli/init.rb +64 -0
  8. data/lib/hotplate/cli/main.rb +39 -0
  9. data/lib/hotplate/gems/rubyzip-1.1.7/README.md +271 -0
  10. data/lib/hotplate/gems/rubyzip-1.1.7/Rakefile +19 -0
  11. data/lib/hotplate/gems/rubyzip-1.1.7/TODO +15 -0
  12. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/central_directory.rb +208 -0
  13. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/compressor.rb +10 -0
  14. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/constants.rb +63 -0
  15. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/crypto/encryption.rb +11 -0
  16. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/crypto/null_encryption.rb +45 -0
  17. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/crypto/traditional_encryption.rb +99 -0
  18. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/decompressor.rb +13 -0
  19. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/deflater.rb +32 -0
  20. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/dos_time.rb +49 -0
  21. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/entry.rb +696 -0
  22. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/entry_set.rb +86 -0
  23. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/errors.rb +16 -0
  24. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/extra_field/generic.rb +43 -0
  25. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/extra_field/ntfs.rb +92 -0
  26. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/extra_field/old_unix.rb +45 -0
  27. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/extra_field/universal_time.rb +47 -0
  28. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/extra_field/unix.rb +38 -0
  29. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/extra_field/zip64.rb +67 -0
  30. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/extra_field/zip64_placeholder.rb +16 -0
  31. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/extra_field.rb +101 -0
  32. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/file.rb +436 -0
  33. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/filesystem.rb +626 -0
  34. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/inflater.rb +66 -0
  35. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/input_stream.rb +164 -0
  36. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/ioextras/abstract_input_stream.rb +115 -0
  37. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/ioextras/abstract_output_stream.rb +45 -0
  38. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/ioextras.rb +38 -0
  39. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/null_compressor.rb +15 -0
  40. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/null_decompressor.rb +27 -0
  41. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/null_input_stream.rb +10 -0
  42. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/output_stream.rb +190 -0
  43. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/pass_thru_compressor.rb +23 -0
  44. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/pass_thru_decompressor.rb +41 -0
  45. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/streamable_directory.rb +15 -0
  46. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/streamable_stream.rb +56 -0
  47. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip/version.rb +3 -0
  48. data/lib/hotplate/gems/rubyzip-1.1.7/lib/zip.rb +63 -0
  49. data/lib/hotplate/gems/rubyzip-1.1.7/samples/example.rb +91 -0
  50. data/lib/hotplate/gems/rubyzip-1.1.7/samples/example_filesystem.rb +33 -0
  51. data/lib/hotplate/gems/rubyzip-1.1.7/samples/example_recursive.rb +48 -0
  52. data/lib/hotplate/gems/rubyzip-1.1.7/samples/gtkRubyzip.rb +86 -0
  53. data/lib/hotplate/gems/rubyzip-1.1.7/samples/qtzip.rb +101 -0
  54. data/lib/hotplate/gems/rubyzip-1.1.7/samples/write_simple.rb +13 -0
  55. data/lib/hotplate/gems/rubyzip-1.1.7/samples/zipfind.rb +74 -0
  56. data/lib/hotplate/gems/rubyzip-1.1.7/test/basic_zip_file_test.rb +64 -0
  57. data/lib/hotplate/gems/rubyzip-1.1.7/test/central_directory_entry_test.rb +73 -0
  58. data/lib/hotplate/gems/rubyzip-1.1.7/test/central_directory_test.rb +104 -0
  59. data/lib/hotplate/gems/rubyzip-1.1.7/test/crypto/null_encryption_test.rb +53 -0
  60. data/lib/hotplate/gems/rubyzip-1.1.7/test/crypto/traditional_encryption_test.rb +80 -0
  61. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/WarnInvalidDate.zip +0 -0
  62. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/file1.txt +46 -0
  63. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/file1.txt.deflatedData +0 -0
  64. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/file2.txt +1504 -0
  65. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/globTest/foo/bar/baz/foo.txt +0 -0
  66. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/globTest/foo.txt +0 -0
  67. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/globTest/food.txt +0 -0
  68. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/globTest.zip +0 -0
  69. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/mimetype +1 -0
  70. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/notzippedruby.rb +7 -0
  71. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/ntfs.zip +0 -0
  72. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/rubycode.zip +0 -0
  73. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/rubycode2.zip +0 -0
  74. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/testDirectory.bin +0 -0
  75. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/zip64-sample.zip +0 -0
  76. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/zipWithDirs.zip +0 -0
  77. data/lib/hotplate/gems/rubyzip-1.1.7/test/data/zipWithEncryption.zip +0 -0
  78. data/lib/hotplate/gems/rubyzip-1.1.7/test/deflater_test.rb +67 -0
  79. data/lib/hotplate/gems/rubyzip-1.1.7/test/encryption_test.rb +42 -0
  80. data/lib/hotplate/gems/rubyzip-1.1.7/test/entry_set_test.rb +138 -0
  81. data/lib/hotplate/gems/rubyzip-1.1.7/test/entry_test.rb +165 -0
  82. data/lib/hotplate/gems/rubyzip-1.1.7/test/errors_test.rb +36 -0
  83. data/lib/hotplate/gems/rubyzip-1.1.7/test/extra_field_test.rb +78 -0
  84. data/lib/hotplate/gems/rubyzip-1.1.7/test/file_extract_directory_test.rb +56 -0
  85. data/lib/hotplate/gems/rubyzip-1.1.7/test/file_extract_test.rb +90 -0
  86. data/lib/hotplate/gems/rubyzip-1.1.7/test/file_split_test.rb +60 -0
  87. data/lib/hotplate/gems/rubyzip-1.1.7/test/file_test.rb +559 -0
  88. data/lib/hotplate/gems/rubyzip-1.1.7/test/filesystem/dir_iterator_test.rb +62 -0
  89. data/lib/hotplate/gems/rubyzip-1.1.7/test/filesystem/directory_test.rb +131 -0
  90. data/lib/hotplate/gems/rubyzip-1.1.7/test/filesystem/file_mutating_test.rb +100 -0
  91. data/lib/hotplate/gems/rubyzip-1.1.7/test/filesystem/file_nonmutating_test.rb +514 -0
  92. data/lib/hotplate/gems/rubyzip-1.1.7/test/filesystem/file_stat_test.rb +66 -0
  93. data/lib/hotplate/gems/rubyzip-1.1.7/test/gentestfiles.rb +134 -0
  94. data/lib/hotplate/gems/rubyzip-1.1.7/test/inflater_test.rb +14 -0
  95. data/lib/hotplate/gems/rubyzip-1.1.7/test/input_stream_test.rb +170 -0
  96. data/lib/hotplate/gems/rubyzip-1.1.7/test/ioextras/abstract_input_stream_test.rb +103 -0
  97. data/lib/hotplate/gems/rubyzip-1.1.7/test/ioextras/abstract_output_stream_test.rb +106 -0
  98. data/lib/hotplate/gems/rubyzip-1.1.7/test/ioextras/fake_io_test.rb +18 -0
  99. data/lib/hotplate/gems/rubyzip-1.1.7/test/local_entry_test.rb +156 -0
  100. data/lib/hotplate/gems/rubyzip-1.1.7/test/output_stream_test.rb +129 -0
  101. data/lib/hotplate/gems/rubyzip-1.1.7/test/pass_thru_compressor_test.rb +31 -0
  102. data/lib/hotplate/gems/rubyzip-1.1.7/test/pass_thru_decompressor_test.rb +15 -0
  103. data/lib/hotplate/gems/rubyzip-1.1.7/test/settings_test.rb +92 -0
  104. data/lib/hotplate/gems/rubyzip-1.1.7/test/test_helper.rb +228 -0
  105. data/lib/hotplate/gems/rubyzip-1.1.7/test/unicode_file_names_and_comments_test.rb +52 -0
  106. data/lib/hotplate/gems/rubyzip-1.1.7/test/zip64_full_test.rb +53 -0
  107. data/lib/hotplate/gems/rubyzip-1.1.7/test/zip64_support_test.rb +15 -0
  108. data/lib/hotplate/java/build.gradle +38 -0
  109. data/lib/hotplate/java/gradle/wrapper/gradle-wrapper.jar +0 -0
  110. data/lib/hotplate/java/gradle/wrapper/gradle-wrapper.properties +6 -0
  111. data/lib/hotplate/java/gradlew +164 -0
  112. data/lib/hotplate/java/gradlew.bat +90 -0
  113. data/lib/hotplate/java/template.java +25 -0
  114. data/lib/hotplate/version.rb +3 -0
  115. data/lib/hotplate.rb +2 -0
  116. metadata +186 -0
@@ -0,0 +1,86 @@
1
+ module Zip
2
+ class EntrySet #:nodoc:all
3
+ include Enumerable
4
+ attr_accessor :entry_set, :entry_order
5
+
6
+ def initialize(an_enumerable = [])
7
+ super()
8
+ @entry_set = {}
9
+ an_enumerable.each { |o| push(o) }
10
+ end
11
+
12
+ def include?(entry)
13
+ @entry_set.include?(to_key(entry))
14
+ end
15
+
16
+ def find_entry(entry)
17
+ @entry_set[to_key(entry)]
18
+ end
19
+
20
+ def <<(entry)
21
+ @entry_set[to_key(entry)] = entry
22
+ end
23
+
24
+ alias :push :<<
25
+
26
+ def size
27
+ @entry_set.size
28
+ end
29
+
30
+ alias :length :size
31
+
32
+ def delete(entry)
33
+ if @entry_set.delete(to_key(entry))
34
+ entry
35
+ else
36
+ nil
37
+ end
38
+ end
39
+
40
+ def each(&block)
41
+ @entry_set = sorted_entries.dup.each do |_, value|
42
+ block.call(value)
43
+ end
44
+ end
45
+
46
+ def entries
47
+ sorted_entries.values
48
+ end
49
+
50
+ # deep clone
51
+ def dup
52
+ EntrySet.new(@entry_set.map { |key, value| value.dup })
53
+ end
54
+
55
+ def ==(other)
56
+ return false unless other.kind_of?(EntrySet)
57
+ @entry_set.values == other.entry_set.values
58
+ end
59
+
60
+ def parent(entry)
61
+ @entry_set[to_key(entry.parent_as_string)]
62
+ end
63
+
64
+ def glob(pattern, flags = ::File::FNM_PATHNAME|::File::FNM_DOTMATCH)
65
+ entries.map do |entry|
66
+ next nil unless ::File.fnmatch(pattern, entry.name.chomp('/'), flags)
67
+ yield(entry) if block_given?
68
+ entry
69
+ end.compact
70
+ end
71
+
72
+ protected
73
+ def sorted_entries
74
+ ::Zip.sort_entries ? Hash[@entry_set.sort] : @entry_set
75
+ end
76
+
77
+ private
78
+ def to_key(entry)
79
+ entry.to_s.chomp('/')
80
+ end
81
+ end
82
+ end
83
+
84
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
85
+ # rubyzip is free software; you can redistribute it and/or
86
+ # modify it under the terms of the ruby license.
@@ -0,0 +1,16 @@
1
+ module Zip
2
+ class Error < StandardError; end
3
+ class EntryExistsError < Error; end
4
+ class DestinationFileExistsError < Error; end
5
+ class CompressionMethodError < Error; end
6
+ class EntryNameError < Error; end
7
+ class InternalError < Error; end
8
+
9
+ # Backwards compatibility with v1 (delete in v2)
10
+ ZipError = Error
11
+ ZipEntryExistsError = EntryExistsError
12
+ ZipDestinationFileExistsError = DestinationFileExistsError
13
+ ZipCompressionMethodError = CompressionMethodError
14
+ ZipEntryNameError = EntryNameError
15
+ ZipInternalError = InternalError
16
+ end
@@ -0,0 +1,43 @@
1
+ module Zip
2
+ class ExtraField::Generic
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
7
+ end
8
+
9
+ def self.name
10
+ @name ||= self.to_s.split("::")[-1]
11
+ end
12
+
13
+ # return field [size, content] or false
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"
20
+ return false
21
+ end
22
+ [binstr[2, 2].unpack("v")[0], binstr[4..-1]]
23
+ end
24
+
25
+ def ==(other)
26
+ return false if self.class != other.class
27
+ each do |k, v|
28
+ v != other[k] and return false
29
+ end
30
+ true
31
+ end
32
+
33
+ def to_local_bin
34
+ s = pack_for_local
35
+ self.class.const_get(:HEADER_ID) + [s.bytesize].pack("v") << s
36
+ end
37
+
38
+ def to_c_dir_bin
39
+ s = pack_for_c_dir
40
+ self.class.const_get(:HEADER_ID) + [s.bytesize].pack("v") << s
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,92 @@
1
+ module Zip
2
+ # PKWARE NTFS Extra Field (0x000a)
3
+ # Only Tag 0x0001 is supported
4
+ class ExtraField::NTFS < ExtraField::Generic
5
+ HEADER_ID = [0x000A].pack('v')
6
+ register_map
7
+
8
+ WINDOWS_TICK = 10000000.0
9
+ SEC_TO_UNIX_EPOCH = 11644473600
10
+
11
+ def initialize(binstr = nil)
12
+ @ctime = nil
13
+ @mtime = nil
14
+ @atime = nil
15
+ binstr and merge(binstr)
16
+ end
17
+
18
+ attr_accessor :atime, :ctime, :mtime
19
+
20
+ def merge(binstr)
21
+ return if binstr.empty?
22
+ size, content = initial_parse(binstr)
23
+ (size && content) or return
24
+
25
+ content = content[4..-1]
26
+ tags = parse_tags(content)
27
+
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
35
+ end
36
+
37
+ def ==(other)
38
+ @mtime == other.mtime &&
39
+ @atime == other.atime &&
40
+ @ctime == other.ctime
41
+ end
42
+
43
+ # Info-ZIP note states this extra field is stored at local header
44
+ def pack_for_local
45
+ pack_for_c_dir
46
+ end
47
+
48
+ # But 7-zip for Windows only stores at central dir
49
+ def pack_for_c_dir
50
+ # reserved 0 and tag 1
51
+ s = [0, 1].pack("Vv")
52
+
53
+ tag1 = ''.force_encoding(Encoding::BINARY)
54
+ if @mtime
55
+ tag1 << [to_ntfs_time(@mtime)].pack('Q<')
56
+ if @atime
57
+ tag1 << [to_ntfs_time(@atime)].pack('Q<')
58
+ if @ctime
59
+ tag1 << [to_ntfs_time(@ctime)].pack('Q<')
60
+ end
61
+ end
62
+ end
63
+ s << [tag1.bytesize].pack('v') << tag1
64
+ s
65
+ end
66
+
67
+ private
68
+ def parse_tags(content)
69
+ return {} if content.nil?
70
+ tags = {}
71
+ i = 0
72
+ while i < content.bytesize do
73
+ tag, size = content[i, 4].unpack('vv')
74
+ i += 4
75
+ break unless tag && size
76
+ value = content[i, size]
77
+ i += size
78
+ tags[tag] = value
79
+ end
80
+
81
+ tags
82
+ end
83
+
84
+ def from_ntfs_time(ntfs_time)
85
+ ::Zip::DOSTime.at(ntfs_time / WINDOWS_TICK - SEC_TO_UNIX_EPOCH)
86
+ end
87
+
88
+ def to_ntfs_time(time)
89
+ ((time.to_f + SEC_TO_UNIX_EPOCH) * WINDOWS_TICK).to_i
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,45 @@
1
+ module Zip
2
+ # Olf Info-ZIP Extra for UNIX uid/gid and file timestampes
3
+ class ExtraField::OldUnix < ExtraField::Generic
4
+ HEADER_ID = "UX"
5
+ register_map
6
+
7
+ def initialize(binstr = nil)
8
+ @uid = 0
9
+ @gid = 0
10
+ @atime = nil
11
+ @mtime = nil
12
+ binstr and merge(binstr)
13
+ end
14
+
15
+ attr_accessor :uid, :gid, :atime, :mtime
16
+
17
+ def merge(binstr)
18
+ return if binstr.empty?
19
+ size, content = initial_parse(binstr)
20
+ # size: 0 for central directory. 4 for local header
21
+ return if (!size || size == 0)
22
+ atime, mtime, uid, gid = content.unpack("VVvv")
23
+ @uid ||= uid
24
+ @gid ||= gid
25
+ @atime ||= atime
26
+ @mtime ||= mtime
27
+ end
28
+
29
+ def ==(other)
30
+ @uid == other.uid &&
31
+ @gid == other.gid &&
32
+ @atime == other.atime &&
33
+ @mtime == other.mtime
34
+ end
35
+
36
+ def pack_for_local
37
+ [@atime, @mtime, @uid, @gid].pack("VVvv")
38
+ end
39
+
40
+ def pack_for_c_dir
41
+ [@atime, @mtime].pack("VV")
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,47 @@
1
+ module Zip
2
+ # Info-ZIP Additional timestamp field
3
+ class ExtraField::UniversalTime < ExtraField::Generic
4
+ HEADER_ID = "UT"
5
+ register_map
6
+
7
+ def initialize(binstr = nil)
8
+ @ctime = nil
9
+ @mtime = nil
10
+ @atime = nil
11
+ @flag = nil
12
+ binstr and merge(binstr)
13
+ end
14
+
15
+ attr_accessor :atime, :ctime, :mtime, :flag
16
+
17
+ def merge(binstr)
18
+ return if binstr.empty?
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)
25
+ end
26
+
27
+ def ==(other)
28
+ @mtime == other.mtime &&
29
+ @atime == other.atime &&
30
+ @ctime == other.ctime
31
+ end
32
+
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")
38
+ s
39
+ end
40
+
41
+ def pack_for_c_dir
42
+ s = [@flag].pack("C")
43
+ @flag & 1 == 1 and s << [@mtime.to_i].pack("V")
44
+ s
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,38 @@
1
+ module Zip
2
+ # Info-ZIP Extra for UNIX uid/gid
3
+ class ExtraField::IUnix < ExtraField::Generic
4
+ HEADER_ID = "Ux"
5
+ register_map
6
+
7
+ def initialize(binstr = nil)
8
+ @uid = 0
9
+ @gid = 0
10
+ binstr and merge(binstr)
11
+ end
12
+
13
+ attr_accessor :uid, :gid
14
+
15
+ def merge(binstr)
16
+ return if binstr.empty?
17
+ size, content = initial_parse(binstr)
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
23
+ end
24
+
25
+ def ==(other)
26
+ @uid == other.uid && @gid == other.gid
27
+ end
28
+
29
+ def pack_for_local
30
+ [@uid, @gid].pack("vv")
31
+ end
32
+
33
+ def pack_for_c_dir
34
+ ''
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,67 @@
1
+ module Zip
2
+ # Info-ZIP Extra for Zip64 size
3
+ class ExtraField::Zip64 < ExtraField::Generic
4
+ attr_accessor :original_size, :compressed_size, :relative_header_offset, :disk_start_number
5
+ HEADER_ID = ['0100'].pack('H*')
6
+ register_map
7
+
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
12
+ @original_size = nil
13
+ @compressed_size = nil
14
+ @relative_header_offset = nil
15
+ @disk_start_number = nil
16
+ binstr and merge(binstr)
17
+ end
18
+
19
+ def ==(other)
20
+ other.original_size == @original_size &&
21
+ other.compressed_size == @compressed_size &&
22
+ other.relative_header_offset == @relative_header_offset &&
23
+ other.disk_start_number == @disk_start_number
24
+ end
25
+
26
+ def merge(binstr)
27
+ return if binstr.empty?
28
+ _, @content = initial_parse(binstr)
29
+ end
30
+
31
+ # pass the values from the base entry (if applicable)
32
+ # wider values are only present in the extra field for base values set to all FFs
33
+ # returns the final values for the four attributes (from the base or zip64 extra record)
34
+ def parse(original_size, compressed_size, relative_header_offset = nil, disk_start_number = nil)
35
+ @original_size = extract(8, 'Q<') if original_size == 0xFFFFFFFF
36
+ @compressed_size = extract(8, 'Q<') if compressed_size == 0xFFFFFFFF
37
+ @relative_header_offset = extract(8, 'Q<') if relative_header_offset && relative_header_offset == 0xFFFFFFFF
38
+ @disk_start_number = extract(4, 'V') if disk_start_number && disk_start_number == 0xFFFF
39
+ @content = nil
40
+ [@original_size || original_size,
41
+ @compressed_size || compressed_size,
42
+ @relative_header_offset || relative_header_offset,
43
+ @disk_start_number || disk_start_number]
44
+ end
45
+
46
+ def extract(size, format)
47
+ @content.slice!(0, size).unpack(format)[0]
48
+ end
49
+ private :extract
50
+
51
+ def pack_for_local
52
+ # local header entries must contain original size and compressed size; other fields do not apply
53
+ return '' unless @original_size && @compressed_size
54
+ [@original_size, @compressed_size].pack("Q<Q<")
55
+ end
56
+
57
+ def pack_for_c_dir
58
+ # central directory entries contain only fields that didn't fit in the main entry part
59
+ 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
64
+ packed
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,16 @@
1
+ module Zip
2
+ # placeholder to reserve space for a Zip64 extra information record, for the
3
+ # local file header only, that we won't know if we'll need until after
4
+ # we write the file data
5
+ class ExtraField::Zip64Placeholder < ExtraField::Generic
6
+ HEADER_ID = ['9999'].pack('H*') # this ID is used by other libraries such as .NET's Ionic.zip
7
+ register_map
8
+
9
+ def initialize(binstr = nil)
10
+ end
11
+
12
+ def pack_for_local
13
+ "\x00" * 16
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,101 @@
1
+ module Zip
2
+ class ExtraField < Hash
3
+ ID_MAP = {}
4
+
5
+ def initialize(binstr = nil)
6
+ binstr and merge(binstr)
7
+ end
8
+
9
+ def extra_field_type_exist(binstr, id, len, i)
10
+ field_name = ID_MAP[id].name
11
+ if self.member?(field_name)
12
+ self[field_name].merge(binstr[i, len + 4])
13
+ else
14
+ field_obj = ID_MAP[id].new(binstr[i, len + 4])
15
+ self[field_name] = field_obj
16
+ end
17
+ end
18
+
19
+ def extra_field_type_unknown(binstr, len, i)
20
+ create_unknown_item unless self['Unknown']
21
+ if !len || len + 4 > binstr[i..-1].bytesize
22
+ self['Unknown'] << binstr[i..-1]
23
+ return
24
+ end
25
+ self['Unknown'] << binstr[i, len + 4]
26
+ end
27
+
28
+ def create_unknown_item
29
+ s = ''
30
+ class << s
31
+ alias_method :to_c_dir_bin, :to_s
32
+ alias_method :to_local_bin, :to_s
33
+ end
34
+ self['Unknown'] = s
35
+ end
36
+
37
+ def merge(binstr)
38
+ return if binstr.empty?
39
+ i = 0
40
+ while i < binstr.bytesize
41
+ id = binstr[i, 2]
42
+ len = binstr[i + 2, 2].to_s.unpack('v').first
43
+ if id && ID_MAP.member?(id)
44
+ extra_field_type_exist(binstr, id, len, i)
45
+ elsif id
46
+ create_unknown_item unless self['Unknown']
47
+ break unless extra_field_type_unknown(binstr, len, i)
48
+ end
49
+ i += len + 4
50
+ end
51
+ end
52
+
53
+ def create(name)
54
+ unless field_class = ID_MAP.values.find { |k| k.name == name }
55
+ raise Error, "Unknown extra field '#{name}'"
56
+ end
57
+ self[name] = field_class.new
58
+ end
59
+
60
+ # place Unknown last, so "extra" data that is missing the proper signature/size
61
+ # does not prevent known fields from being read back in
62
+ def ordered_values
63
+ result = []
64
+ self.each { |k,v| k == 'Unknown' ? result.push(v) : result.unshift(v) }
65
+ result
66
+ end
67
+
68
+ def to_local_bin
69
+ ordered_values.map! { |v| v.to_local_bin.force_encoding('BINARY') }.join
70
+ end
71
+
72
+ alias :to_s :to_local_bin
73
+
74
+ def to_c_dir_bin
75
+ ordered_values.map! { |v| v.to_c_dir_bin.force_encoding('BINARY') }.join
76
+ end
77
+
78
+ def c_dir_size
79
+ to_c_dir_bin.bytesize
80
+ end
81
+
82
+ def local_size
83
+ to_local_bin.bytesize
84
+ end
85
+
86
+ alias :length :local_size
87
+ alias :size :local_size
88
+ end
89
+ end
90
+
91
+ require 'zip/extra_field/generic'
92
+ require 'zip/extra_field/universal_time'
93
+ require 'zip/extra_field/old_unix'
94
+ require 'zip/extra_field/unix'
95
+ require 'zip/extra_field/zip64'
96
+ require 'zip/extra_field/zip64_placeholder'
97
+ require 'zip/extra_field/ntfs'
98
+
99
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
100
+ # rubyzip is free software; you can redistribute it and/or
101
+ # modify it under the terms of the ruby license.