hotplate 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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.