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,696 @@
1
+ module Zip
2
+ class Entry
3
+ STORED = 0
4
+ DEFLATED = 8
5
+ # Language encoding flag (EFS) bit
6
+ EFS = 0b100000000000
7
+
8
+ attr_accessor :comment, :compressed_size, :crc, :extra, :compression_method,
9
+ :name, :size, :local_header_offset, :zipfile, :fstype, :external_file_attributes,
10
+ :gp_flags, :header_signature, :follow_symlinks,
11
+ :restore_times, :restore_permissions, :restore_ownership,
12
+ :unix_uid, :unix_gid, :unix_perms,
13
+ :dirty
14
+ attr_reader :ftype, :filepath # :nodoc:
15
+
16
+ def set_default_vars_values
17
+ @local_header_offset = 0
18
+ @local_header_size = nil # not known until local entry is created or read
19
+ @internal_file_attributes = 1
20
+ @external_file_attributes = 0
21
+ @header_signature = ::Zip::CENTRAL_DIRECTORY_ENTRY_SIGNATURE
22
+
23
+ @version_needed_to_extract = VERSION_NEEDED_TO_EXTRACT
24
+ @version = VERSION_MADE_BY
25
+
26
+ @ftype = nil # unspecified or unknown
27
+ @filepath = nil
28
+ @gp_flags = 0
29
+ if ::Zip.unicode_names
30
+ @gp_flags |= EFS
31
+ @version = 63
32
+ end
33
+ @follow_symlinks = false
34
+
35
+ @restore_times = true
36
+ @restore_permissions = false
37
+ @restore_ownership = false
38
+ # BUG: need an extra field to support uid/gid's
39
+ @unix_uid = nil
40
+ @unix_gid = nil
41
+ @unix_perms = nil
42
+ #@posix_acl = nil
43
+ #@ntfs_acl = nil
44
+ @dirty = false
45
+ end
46
+
47
+ def check_name(name)
48
+ if name.start_with?('/')
49
+ raise ::Zip::EntryNameError, "Illegal ZipEntry name '#{name}', name must not start with /"
50
+ end
51
+ end
52
+
53
+ def initialize(*args)
54
+ name = args[1] || ''
55
+ check_name(name)
56
+
57
+ set_default_vars_values
58
+ @fstype = ::Zip::RUNNING_ON_WINDOWS ? ::Zip::FSTYPE_FAT : ::Zip::FSTYPE_UNIX
59
+
60
+ @zipfile = args[0] || ''
61
+ @name = name
62
+ @comment = args[2] || ''
63
+ @extra = args[3] || ''
64
+ @compressed_size = args[4] || 0
65
+ @crc = args[5] || 0
66
+ @compression_method = args[6] || ::Zip::Entry::DEFLATED
67
+ @size = args[7] || 0
68
+ @time = args[8] || ::Zip::DOSTime.now
69
+
70
+ @ftype = name_is_directory? ? :directory : :file
71
+ @extra = ::Zip::ExtraField.new(@extra.to_s) unless ::Zip::ExtraField === @extra
72
+ end
73
+
74
+ def time
75
+ if @extra['UniversalTime']
76
+ @extra['UniversalTime'].mtime
77
+ elsif @extra['NTFS']
78
+ @extra['NTFS'].mtime
79
+ else
80
+ # Standard time field in central directory has local time
81
+ # under archive creator. Then, we can't get timezone.
82
+ @time
83
+ end
84
+ end
85
+
86
+ alias :mtime :time
87
+
88
+ def time=(value)
89
+ unless @extra.member?('UniversalTime') || @extra.member?('NTFS')
90
+ @extra.create('UniversalTime')
91
+ end
92
+ (@extra['UniversalTime'] || @extra['NTFS']).mtime = value
93
+ @time = value
94
+ end
95
+
96
+ def file_type_is?(type)
97
+ raise InternalError, "current filetype is unknown: #{self.inspect}" unless @ftype
98
+ @ftype == type
99
+ end
100
+
101
+ # Dynamic checkers
102
+ %w(directory file symlink).each do |k|
103
+ define_method "#{k}?" do
104
+ file_type_is?(k.to_sym)
105
+ end
106
+ end
107
+
108
+ def name_is_directory? #:nodoc:all
109
+ @name.end_with?('/')
110
+ end
111
+
112
+ def local_entry_offset #:nodoc:all
113
+ local_header_offset + @local_header_size
114
+ end
115
+
116
+ def name_size
117
+ @name ? @name.bytesize : 0
118
+ end
119
+
120
+ def extra_size
121
+ @extra ? @extra.local_size : 0
122
+ end
123
+
124
+ def comment_size
125
+ @comment ? @comment.bytesize : 0
126
+ end
127
+
128
+ def calculate_local_header_size #:nodoc:all
129
+ LOCAL_ENTRY_STATIC_HEADER_LENGTH + name_size + extra_size
130
+ end
131
+
132
+ # check before rewriting an entry (after file sizes are known)
133
+ # that we didn't change the header size (and thus clobber file data or something)
134
+ def verify_local_header_size!
135
+ return if @local_header_size.nil?
136
+ new_size = calculate_local_header_size
137
+ raise Error, "local header size changed (#{@local_header_size} -> #{new_size})" if @local_header_size != new_size
138
+ end
139
+
140
+ def cdir_header_size #:nodoc:all
141
+ CDIR_ENTRY_STATIC_HEADER_LENGTH + name_size +
142
+ (@extra ? @extra.c_dir_size : 0) + comment_size
143
+ end
144
+
145
+ def next_header_offset #:nodoc:all
146
+ local_entry_offset + self.compressed_size + data_descriptor_size
147
+ end
148
+
149
+ # Extracts entry to file dest_path (defaults to @name).
150
+ def extract(dest_path = @name, &block)
151
+ block ||= proc { ::Zip.on_exists_proc }
152
+
153
+ if directory? || file? || symlink?
154
+ self.__send__("create_#{@ftype}", dest_path, &block)
155
+ else
156
+ raise RuntimeError, "unknown file type #{self.inspect}"
157
+ end
158
+
159
+ self
160
+ end
161
+
162
+ def to_s
163
+ @name
164
+ end
165
+
166
+ protected
167
+
168
+ class << self
169
+ def read_zip_short(io) # :nodoc:
170
+ io.read(2).unpack('v')[0]
171
+ end
172
+
173
+ def read_zip_long(io) # :nodoc:
174
+ io.read(4).unpack('V')[0]
175
+ end
176
+
177
+ def read_zip_64_long(io) # :nodoc:
178
+ io.read(8).unpack('Q<')[0]
179
+ end
180
+
181
+ def read_c_dir_entry(io) #:nodoc:all
182
+ path = if io.is_a?(::IO)
183
+ io.path
184
+ else
185
+ io
186
+ end
187
+ entry = new(path)
188
+ entry.read_c_dir_entry(io)
189
+ entry
190
+ rescue Error
191
+ nil
192
+ end
193
+
194
+ def read_local_entry(io)
195
+ entry = self.new(io)
196
+ entry.read_local_entry(io)
197
+ entry
198
+ rescue Error
199
+ nil
200
+ end
201
+
202
+ end
203
+
204
+ public
205
+
206
+ def unpack_local_entry(buf)
207
+ @header_signature,
208
+ @version,
209
+ @fstype,
210
+ @gp_flags,
211
+ @compression_method,
212
+ @last_mod_time,
213
+ @last_mod_date,
214
+ @crc,
215
+ @compressed_size,
216
+ @size,
217
+ @name_length,
218
+ @extra_length = buf.unpack('VCCvvvvVVVvv')
219
+ end
220
+
221
+ def read_local_entry(io) #:nodoc:all
222
+ @local_header_offset = io.tell
223
+
224
+ static_sized_fields_buf = io.read(::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH)
225
+
226
+ unless static_sized_fields_buf.bytesize == ::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH
227
+ raise Error, "Premature end of file. Not enough data for zip entry local header"
228
+ end
229
+
230
+ unpack_local_entry(static_sized_fields_buf)
231
+
232
+ unless @header_signature == ::Zip::LOCAL_ENTRY_SIGNATURE
233
+ raise ::Zip::Error, "Zip local header magic not found at location '#{local_header_offset}'"
234
+ end
235
+ set_time(@last_mod_date, @last_mod_time)
236
+
237
+ @name = io.read(@name_length)
238
+ extra = io.read(@extra_length)
239
+
240
+ @name.gsub!('\\', '/')
241
+
242
+ if extra && extra.bytesize != @extra_length
243
+ raise ::Zip::Error, "Truncated local zip entry header"
244
+ else
245
+ if ::Zip::ExtraField === @extra
246
+ @extra.merge(extra)
247
+ else
248
+ @extra = ::Zip::ExtraField.new(extra)
249
+ end
250
+ end
251
+ parse_zip64_extra(true)
252
+ @local_header_size = calculate_local_header_size
253
+ end
254
+
255
+ def pack_local_entry
256
+ zip64 = @extra['Zip64']
257
+ [::Zip::LOCAL_ENTRY_SIGNATURE,
258
+ @version_needed_to_extract, # version needed to extract
259
+ @gp_flags, # @gp_flags ,
260
+ @compression_method,
261
+ @time.to_binary_dos_time, # @last_mod_time ,
262
+ @time.to_binary_dos_date, # @last_mod_date ,
263
+ @crc,
264
+ (zip64 && zip64.compressed_size) ? 0xFFFFFFFF : @compressed_size,
265
+ (zip64 && zip64.original_size) ? 0xFFFFFFFF : @size,
266
+ name_size,
267
+ @extra ? @extra.local_size : 0].pack('VvvvvvVVVvv')
268
+ end
269
+
270
+ def write_local_entry(io, rewrite = false) #:nodoc:all
271
+ prep_zip64_extra(true)
272
+ verify_local_header_size! if rewrite
273
+ @local_header_offset = io.tell
274
+
275
+ io << pack_local_entry
276
+
277
+ io << @name
278
+ io << @extra.to_local_bin if @extra
279
+ @local_header_size = io.tell - @local_header_offset
280
+ end
281
+
282
+ def unpack_c_dir_entry(buf)
283
+ @header_signature,
284
+ @version, # version of encoding software
285
+ @fstype, # filesystem type
286
+ @version_needed_to_extract,
287
+ @gp_flags,
288
+ @compression_method,
289
+ @last_mod_time,
290
+ @last_mod_date,
291
+ @crc,
292
+ @compressed_size,
293
+ @size,
294
+ @name_length,
295
+ @extra_length,
296
+ @comment_length,
297
+ _, # diskNumberStart
298
+ @internal_file_attributes,
299
+ @external_file_attributes,
300
+ @local_header_offset,
301
+ @name,
302
+ @extra,
303
+ @comment = buf.unpack('VCCvvvvvVVVvvvvvVV')
304
+ end
305
+
306
+ def set_ftype_from_c_dir_entry
307
+ @ftype = case @fstype
308
+ when ::Zip::FSTYPE_UNIX
309
+ @unix_perms = (@external_file_attributes >> 16) & 07777
310
+ case (@external_file_attributes >> 28)
311
+ when ::Zip::FILE_TYPE_DIR
312
+ :directory
313
+ when ::Zip::FILE_TYPE_FILE
314
+ :file
315
+ when ::Zip::FILE_TYPE_SYMLINK
316
+ :symlink
317
+ else
318
+ #best case guess for whether it is a file or not
319
+ #Otherwise this would be set to unknown and that entry would never be able to extracted
320
+ if name_is_directory?
321
+ :directory
322
+ else
323
+ :file
324
+ end
325
+ end
326
+ else
327
+ if name_is_directory?
328
+ :directory
329
+ else
330
+ :file
331
+ end
332
+ end
333
+ end
334
+
335
+ def check_c_dir_entry_static_header_length(buf)
336
+ unless buf.bytesize == ::Zip::CDIR_ENTRY_STATIC_HEADER_LENGTH
337
+ raise Error, 'Premature end of file. Not enough data for zip cdir entry header'
338
+ end
339
+ end
340
+
341
+ def check_c_dir_entry_signature
342
+ unless header_signature == ::Zip::CENTRAL_DIRECTORY_ENTRY_SIGNATURE
343
+ raise Error, "Zip local header magic not found at location '#{local_header_offset}'"
344
+ end
345
+ end
346
+
347
+ def check_c_dir_entry_comment_size
348
+ unless @comment && @comment.bytesize == @comment_length
349
+ raise ::Zip::Error, "Truncated cdir zip entry header"
350
+ end
351
+ end
352
+
353
+ def read_c_dir_extra_field(io)
354
+ if @extra.is_a?(::Zip::ExtraField)
355
+ @extra.merge(io.read(@extra_length))
356
+ else
357
+ @extra = ::Zip::ExtraField.new(io.read(@extra_length))
358
+ end
359
+ end
360
+
361
+ def read_c_dir_entry(io) #:nodoc:all
362
+ static_sized_fields_buf = io.read(::Zip::CDIR_ENTRY_STATIC_HEADER_LENGTH)
363
+ check_c_dir_entry_static_header_length(static_sized_fields_buf)
364
+ unpack_c_dir_entry(static_sized_fields_buf)
365
+ check_c_dir_entry_signature
366
+ set_time(@last_mod_date, @last_mod_time)
367
+ @name = io.read(@name_length).tr('\\', '/')
368
+ read_c_dir_extra_field(io)
369
+ @comment = io.read(@comment_length)
370
+ check_c_dir_entry_comment_size
371
+ set_ftype_from_c_dir_entry
372
+ parse_zip64_extra(false)
373
+ end
374
+
375
+ def file_stat(path) # :nodoc:
376
+ if @follow_symlinks
377
+ ::File::stat(path)
378
+ else
379
+ ::File::lstat(path)
380
+ end
381
+ end
382
+
383
+ def get_extra_attributes_from_path(path) # :nodoc:
384
+ unless Zip::RUNNING_ON_WINDOWS
385
+ stat = file_stat(path)
386
+ @unix_uid = stat.uid
387
+ @unix_gid = stat.gid
388
+ @unix_perms = stat.mode & 07777
389
+ end
390
+ end
391
+
392
+ def set_unix_permissions_on_path(dest_path)
393
+ # BUG: does not update timestamps into account
394
+ # ignore setuid/setgid bits by default. honor if @restore_ownership
395
+ unix_perms_mask = 01777
396
+ unix_perms_mask = 07777 if @restore_ownership
397
+ ::FileUtils.chmod(@unix_perms & unix_perms_mask, dest_path) if @restore_permissions && @unix_perms
398
+ ::FileUtils.chown(@unix_uid, @unix_gid, dest_path) if @restore_ownership && @unix_uid && @unix_gid && ::Process.egid == 0
399
+ # File::utimes()
400
+ end
401
+
402
+ def set_extra_attributes_on_path(dest_path) # :nodoc:
403
+ return unless (file? || directory?)
404
+
405
+ case @fstype
406
+ when ::Zip::FSTYPE_UNIX
407
+ set_unix_permissions_on_path(dest_path)
408
+ end
409
+ end
410
+
411
+ def pack_c_dir_entry
412
+ zip64 = @extra['Zip64']
413
+ [
414
+ @header_signature,
415
+ @version, # version of encoding software
416
+ @fstype, # filesystem type
417
+ @version_needed_to_extract, # @versionNeededToExtract ,
418
+ @gp_flags, # @gp_flags ,
419
+ @compression_method,
420
+ @time.to_binary_dos_time, # @last_mod_time ,
421
+ @time.to_binary_dos_date, # @last_mod_date ,
422
+ @crc,
423
+ (zip64 && zip64.compressed_size) ? 0xFFFFFFFF : @compressed_size,
424
+ (zip64 && zip64.original_size) ? 0xFFFFFFFF : @size,
425
+ name_size,
426
+ @extra ? @extra.c_dir_size : 0,
427
+ comment_size,
428
+ (zip64 && zip64.disk_start_number) ? 0xFFFF : 0, # disk number start
429
+ @internal_file_attributes, # file type (binary=0, text=1)
430
+ @external_file_attributes, # native filesystem attributes
431
+ (zip64 && zip64.relative_header_offset) ? 0xFFFFFFFF : @local_header_offset,
432
+ @name,
433
+ @extra,
434
+ @comment
435
+ ].pack('VCCvvvvvVVVvvvvvVV')
436
+ end
437
+
438
+ def write_c_dir_entry(io) #:nodoc:all
439
+ prep_zip64_extra(false)
440
+ case @fstype
441
+ when ::Zip::FSTYPE_UNIX
442
+ ft = case @ftype
443
+ when :file
444
+ @unix_perms ||= 0644
445
+ ::Zip::FILE_TYPE_FILE
446
+ when :directory
447
+ @unix_perms ||= 0755
448
+ ::Zip::FILE_TYPE_DIR
449
+ when :symlink
450
+ @unix_perms ||= 0755
451
+ ::Zip::FILE_TYPE_SYMLINK
452
+ end
453
+
454
+ unless ft.nil?
455
+ @external_file_attributes = (ft << 12 | (@unix_perms & 07777)) << 16
456
+ end
457
+ end
458
+
459
+ io << pack_c_dir_entry
460
+
461
+ io << @name
462
+ io << (@extra ? @extra.to_c_dir_bin : '')
463
+ io << @comment
464
+ end
465
+
466
+ def ==(other)
467
+ return false unless other.class == self.class
468
+ # Compares contents of local entry and exposed fields
469
+ keys_equal = %w(compression_method crc compressed_size size name extra filepath).all? do |k|
470
+ other.__send__(k.to_sym) == self.__send__(k.to_sym)
471
+ end
472
+ keys_equal && self.time.dos_equals(other.time)
473
+ end
474
+
475
+ def <=> (other)
476
+ self.to_s <=> other.to_s
477
+ end
478
+
479
+ # Returns an IO like object for the given ZipEntry.
480
+ # Warning: may behave weird with symlinks.
481
+ def get_input_stream(&block)
482
+ if @ftype == :directory
483
+ yield ::Zip::NullInputStream if block_given?
484
+ ::Zip::NullInputStream
485
+ elsif @filepath
486
+ case @ftype
487
+ when :file
488
+ ::File.open(@filepath, 'rb', &block)
489
+ when :symlink
490
+ linkpath = ::File.readlink(@filepath)
491
+ stringio = ::StringIO.new(linkpath)
492
+ yield(stringio) if block_given?
493
+ stringio
494
+ else
495
+ raise "unknown @file_type #{@ftype}"
496
+ end
497
+ else
498
+ zis = ::Zip::InputStream.new(@zipfile, local_header_offset)
499
+ zis.get_next_entry
500
+ if block_given?
501
+ begin
502
+ yield(zis)
503
+ ensure
504
+ zis.close
505
+ end
506
+ else
507
+ zis
508
+ end
509
+ end
510
+ end
511
+
512
+ def gather_fileinfo_from_srcpath(src_path) # :nodoc:
513
+ stat = file_stat(src_path)
514
+ @ftype = case stat.ftype
515
+ when 'file'
516
+ if name_is_directory?
517
+ raise ArgumentError,
518
+ "entry name '#{newEntry}' indicates directory entry, but "+
519
+ "'#{src_path}' is not a directory"
520
+ end
521
+ :file
522
+ when 'directory'
523
+ @name += '/' unless name_is_directory?
524
+ :directory
525
+ when 'link'
526
+ if name_is_directory?
527
+ raise ArgumentError,
528
+ "entry name '#{newEntry}' indicates directory entry, but "+
529
+ "'#{src_path}' is not a directory"
530
+ end
531
+ :symlink
532
+ else
533
+ raise RuntimeError, "unknown file type: #{src_path.inspect} #{stat.inspect}"
534
+ end
535
+
536
+ @filepath = src_path
537
+ get_extra_attributes_from_path(@filepath)
538
+ end
539
+
540
+ def write_to_zip_output_stream(zip_output_stream) #:nodoc:all
541
+ if @ftype == :directory
542
+ zip_output_stream.put_next_entry(self, nil, nil, ::Zip::Entry::STORED)
543
+ elsif @filepath
544
+ zip_output_stream.put_next_entry(self, nil, nil, self.compression_method || ::Zip::Entry::DEFLATED)
545
+ get_input_stream { |is| ::Zip::IOExtras.copy_stream(zip_output_stream, is) }
546
+ else
547
+ zip_output_stream.copy_raw_entry(self)
548
+ end
549
+ end
550
+
551
+ def parent_as_string
552
+ entry_name = name.chomp('/')
553
+ slash_index = entry_name.rindex('/')
554
+ slash_index ? entry_name.slice(0, slash_index+1) : nil
555
+ end
556
+
557
+ def get_raw_input_stream(&block)
558
+ if @zipfile.is_a?(::IO) || @zipfile.is_a?(::StringIO)
559
+ yield @zipfile
560
+ else
561
+ ::File.open(@zipfile, "rb", &block)
562
+ end
563
+ end
564
+
565
+ def clean_up
566
+ # By default, do nothing
567
+ end
568
+
569
+ private
570
+
571
+ def set_time(binary_dos_date, binary_dos_time)
572
+ @time = ::Zip::DOSTime.parse_binary_dos_format(binary_dos_date, binary_dos_time)
573
+ rescue ArgumentError
574
+ puts "Invalid date/time in zip entry" if ::Zip.warn_invalid_date
575
+ end
576
+
577
+ def create_file(dest_path, continue_on_exists_proc = proc { Zip.continue_on_exists_proc })
578
+ if ::File.exist?(dest_path) && !yield(self, dest_path)
579
+ raise ::Zip::DestinationFileExistsError,
580
+ "Destination '#{dest_path}' already exists"
581
+ end
582
+ ::File.open(dest_path, "wb") do |os|
583
+ get_input_stream do |is|
584
+ set_extra_attributes_on_path(dest_path)
585
+
586
+ buf = ''
587
+ while buf = is.sysread(::Zip::Decompressor::CHUNK_SIZE, buf)
588
+ os << buf
589
+ end
590
+ end
591
+ end
592
+ end
593
+
594
+ def create_directory(dest_path)
595
+ return if ::File.directory?(dest_path)
596
+ if ::File.exist?(dest_path)
597
+ if block_given? && yield(self, dest_path)
598
+ ::FileUtils::rm_f dest_path
599
+ else
600
+ raise ::Zip::DestinationFileExistsError,
601
+ "Cannot create directory '#{dest_path}'. "+
602
+ "A file already exists with that name"
603
+ end
604
+ end
605
+ ::FileUtils.mkdir_p(dest_path)
606
+ set_extra_attributes_on_path(dest_path)
607
+ end
608
+
609
+ # BUG: create_symlink() does not use &block
610
+ def create_symlink(dest_path)
611
+ stat = nil
612
+ begin
613
+ stat = ::File.lstat(dest_path)
614
+ rescue Errno::ENOENT
615
+ end
616
+
617
+ io = get_input_stream
618
+ linkto = io.read
619
+
620
+ if stat
621
+ if stat.symlink?
622
+ if ::File.readlink(dest_path) == linkto
623
+ return
624
+ else
625
+ raise ::Zip::DestinationFileExistsError,
626
+ "Cannot create symlink '#{dest_path}'. "+
627
+ "A symlink already exists with that name"
628
+ end
629
+ else
630
+ raise ::Zip::DestinationFileExistsError,
631
+ "Cannot create symlink '#{dest_path}'. "+
632
+ "A file already exists with that name"
633
+ end
634
+ end
635
+
636
+ ::File.symlink(linkto, dest_path)
637
+ end
638
+
639
+ # apply missing data from the zip64 extra information field, if present
640
+ # (required when file sizes exceed 2**32, but can be used for all files)
641
+ def parse_zip64_extra(for_local_header) #:nodoc:all
642
+ if zip64 = @extra['Zip64']
643
+ if for_local_header
644
+ @size, @compressed_size = zip64.parse(@size, @compressed_size)
645
+ else
646
+ @size, @compressed_size, @local_header_offset = zip64.parse(@size, @compressed_size, @local_header_offset)
647
+ end
648
+ end
649
+ end
650
+
651
+ def data_descriptor_size
652
+ (@gp_flags & 0x0008) > 0 ? 16 : 0
653
+ end
654
+
655
+ # create a zip64 extra information field if we need one
656
+ def prep_zip64_extra(for_local_header) #:nodoc:all
657
+ return unless ::Zip.write_zip64_support
658
+ need_zip64 = @size >= 0xFFFFFFFF || @compressed_size >= 0xFFFFFFFF
659
+ unless for_local_header
660
+ need_zip64 ||= @local_header_offset >= 0xFFFFFFFF
661
+ end
662
+
663
+ if need_zip64
664
+ @version_needed_to_extract = VERSION_NEEDED_TO_EXTRACT_ZIP64
665
+ @extra.delete('Zip64Placeholder')
666
+ zip64 = @extra.create('Zip64')
667
+ if for_local_header
668
+ # local header always includes size and compressed size
669
+ zip64.original_size = @size
670
+ zip64.compressed_size = @compressed_size
671
+ else
672
+ # central directory entry entries include whichever fields are necessary
673
+ zip64.original_size = @size if @size >= 0xFFFFFFFF
674
+ zip64.compressed_size = @compressed_size if @compressed_size >= 0xFFFFFFFF
675
+ zip64.relative_header_offset = @local_header_offset if @local_header_offset >= 0xFFFFFFFF
676
+ end
677
+ else
678
+ @extra.delete('Zip64')
679
+
680
+ # if this is a local header entry, create a placeholder
681
+ # so we have room to write a zip64 extra field afterward
682
+ # (we won't know if it's needed until the file data is written)
683
+ if for_local_header
684
+ @extra.create('Zip64Placeholder')
685
+ else
686
+ @extra.delete('Zip64Placeholder')
687
+ end
688
+ end
689
+ end
690
+
691
+ end
692
+ end
693
+
694
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
695
+ # rubyzip is free software; you can redistribute it and/or
696
+ # modify it under the terms of the ruby license.