rubyzip 0.9.9 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +284 -41
  3. data/Rakefile +11 -6
  4. data/TODO +0 -1
  5. data/lib/zip/central_directory.rb +208 -0
  6. data/lib/zip/compressor.rb +1 -2
  7. data/lib/zip/constants.rb +59 -7
  8. data/lib/zip/crypto/encryption.rb +11 -0
  9. data/lib/zip/crypto/null_encryption.rb +43 -0
  10. data/lib/zip/crypto/traditional_encryption.rb +99 -0
  11. data/lib/zip/decompressor.rb +4 -4
  12. data/lib/zip/deflater.rb +17 -13
  13. data/lib/zip/dos_time.rb +13 -14
  14. data/lib/zip/entry.rb +700 -0
  15. data/lib/zip/entry_set.rb +86 -0
  16. data/lib/zip/errors.rb +18 -0
  17. data/lib/zip/extra_field/generic.rb +43 -0
  18. data/lib/zip/extra_field/ntfs.rb +90 -0
  19. data/lib/zip/extra_field/old_unix.rb +44 -0
  20. data/lib/zip/extra_field/universal_time.rb +47 -0
  21. data/lib/zip/extra_field/unix.rb +37 -0
  22. data/lib/zip/extra_field/zip64.rb +68 -0
  23. data/lib/zip/extra_field/zip64_placeholder.rb +15 -0
  24. data/lib/zip/extra_field.rb +101 -0
  25. data/lib/zip/file.rb +443 -0
  26. data/lib/zip/{zipfilesystem.rb → filesystem.rb} +162 -157
  27. data/lib/zip/inflater.rb +29 -28
  28. data/lib/zip/input_stream.rb +173 -0
  29. data/lib/zip/ioextras/abstract_input_stream.rb +111 -0
  30. data/lib/zip/ioextras/abstract_output_stream.rb +43 -0
  31. data/lib/zip/ioextras.rb +21 -149
  32. data/lib/zip/null_compressor.rb +2 -2
  33. data/lib/zip/null_decompressor.rb +8 -6
  34. data/lib/zip/null_input_stream.rb +3 -2
  35. data/lib/zip/output_stream.rb +189 -0
  36. data/lib/zip/pass_thru_compressor.rb +6 -6
  37. data/lib/zip/pass_thru_decompressor.rb +19 -19
  38. data/lib/zip/{zip_streamable_directory.rb → streamable_directory.rb} +3 -3
  39. data/lib/zip/streamable_stream.rb +56 -0
  40. data/lib/zip/version.rb +3 -0
  41. data/lib/zip.rb +71 -0
  42. data/samples/example.rb +44 -32
  43. data/samples/example_filesystem.rb +16 -18
  44. data/samples/example_recursive.rb +33 -28
  45. data/samples/{gtkRubyzip.rb → gtk_ruby_zip.rb} +26 -28
  46. data/samples/qtzip.rb +22 -31
  47. data/samples/write_simple.rb +12 -13
  48. data/samples/zipfind.rb +31 -39
  49. data/test/basic_zip_file_test.rb +60 -0
  50. data/test/case_sensitivity_test.rb +69 -0
  51. data/test/central_directory_entry_test.rb +69 -0
  52. data/test/central_directory_test.rb +100 -0
  53. data/test/crypto/null_encryption_test.rb +57 -0
  54. data/test/crypto/traditional_encryption_test.rb +80 -0
  55. data/test/data/WarnInvalidDate.zip +0 -0
  56. data/test/data/file1.txt +46 -0
  57. data/test/data/file1.txt.deflatedData +0 -0
  58. data/test/data/file2.txt +1504 -0
  59. data/test/data/globTest/foo/bar/baz/foo.txt +0 -0
  60. data/test/data/globTest/foo.txt +0 -0
  61. data/test/data/globTest/food.txt +0 -0
  62. data/test/data/globTest.zip +0 -0
  63. data/test/data/gpbit3stored.zip +0 -0
  64. data/test/data/mimetype +1 -0
  65. data/test/data/notzippedruby.rb +7 -0
  66. data/test/data/ntfs.zip +0 -0
  67. data/test/data/oddExtraField.zip +0 -0
  68. data/test/data/path_traversal/Makefile +10 -0
  69. data/test/data/path_traversal/jwilk/README.md +5 -0
  70. data/test/data/path_traversal/jwilk/absolute1.zip +0 -0
  71. data/test/data/path_traversal/jwilk/absolute2.zip +0 -0
  72. data/test/data/path_traversal/jwilk/dirsymlink.zip +0 -0
  73. data/test/data/path_traversal/jwilk/dirsymlink2a.zip +0 -0
  74. data/test/data/path_traversal/jwilk/dirsymlink2b.zip +0 -0
  75. data/test/data/path_traversal/jwilk/relative0.zip +0 -0
  76. data/test/data/path_traversal/jwilk/relative2.zip +0 -0
  77. data/test/data/path_traversal/jwilk/symlink.zip +0 -0
  78. data/test/data/path_traversal/relative1.zip +0 -0
  79. data/test/data/path_traversal/tilde.zip +0 -0
  80. data/test/data/path_traversal/tuzovakaoff/README.md +3 -0
  81. data/test/data/path_traversal/tuzovakaoff/absolutepath.zip +0 -0
  82. data/test/data/path_traversal/tuzovakaoff/symlink.zip +0 -0
  83. data/test/data/rubycode.zip +0 -0
  84. data/test/data/rubycode2.zip +0 -0
  85. data/test/data/test.xls +0 -0
  86. data/test/data/testDirectory.bin +0 -0
  87. data/test/data/zip64-sample.zip +0 -0
  88. data/test/data/zipWithDirs.zip +0 -0
  89. data/test/data/zipWithEncryption.zip +0 -0
  90. data/test/deflater_test.rb +65 -0
  91. data/test/encryption_test.rb +42 -0
  92. data/test/entry_set_test.rb +163 -0
  93. data/test/entry_test.rb +154 -0
  94. data/test/errors_test.rb +35 -0
  95. data/test/extra_field_test.rb +76 -0
  96. data/test/file_extract_directory_test.rb +54 -0
  97. data/test/file_extract_test.rb +145 -0
  98. data/test/file_permissions_test.rb +65 -0
  99. data/test/file_split_test.rb +57 -0
  100. data/test/file_test.rb +666 -0
  101. data/test/filesystem/dir_iterator_test.rb +58 -0
  102. data/test/filesystem/directory_test.rb +139 -0
  103. data/test/filesystem/file_mutating_test.rb +87 -0
  104. data/test/filesystem/file_nonmutating_test.rb +508 -0
  105. data/test/filesystem/file_stat_test.rb +64 -0
  106. data/test/gentestfiles.rb +126 -0
  107. data/test/inflater_test.rb +14 -0
  108. data/test/input_stream_test.rb +182 -0
  109. data/test/ioextras/abstract_input_stream_test.rb +102 -0
  110. data/test/ioextras/abstract_output_stream_test.rb +106 -0
  111. data/test/ioextras/fake_io_test.rb +18 -0
  112. data/test/local_entry_test.rb +154 -0
  113. data/test/output_stream_test.rb +128 -0
  114. data/test/pass_thru_compressor_test.rb +30 -0
  115. data/test/pass_thru_decompressor_test.rb +14 -0
  116. data/test/path_traversal_test.rb +141 -0
  117. data/test/samples/example_recursive_test.rb +37 -0
  118. data/test/settings_test.rb +95 -0
  119. data/test/test_helper.rb +234 -0
  120. data/test/unicode_file_names_and_comments_test.rb +62 -0
  121. data/test/zip64_full_test.rb +51 -0
  122. data/test/zip64_support_test.rb +14 -0
  123. metadata +274 -41
  124. data/NEWS +0 -172
  125. data/lib/zip/settings.rb +0 -10
  126. data/lib/zip/tempfile_bugfixed.rb +0 -195
  127. data/lib/zip/zip.rb +0 -56
  128. data/lib/zip/zip_central_directory.rb +0 -135
  129. data/lib/zip/zip_entry.rb +0 -638
  130. data/lib/zip/zip_entry_set.rb +0 -77
  131. data/lib/zip/zip_extra_field.rb +0 -213
  132. data/lib/zip/zip_file.rb +0 -340
  133. data/lib/zip/zip_input_stream.rb +0 -144
  134. data/lib/zip/zip_output_stream.rb +0 -173
  135. data/lib/zip/zip_streamable_stream.rb +0 -47
@@ -1,213 +0,0 @@
1
- module Zip
2
- class ZipExtraField < Hash
3
- ID_MAP = {}
4
-
5
- # Meta class for extra fields
6
- class Generic
7
- def self.register_map
8
- if self.const_defined?(:HEADER_ID)
9
- ID_MAP[self.const_get(:HEADER_ID)] = self
10
- end
11
- end
12
-
13
- def self.name
14
- self.to_s.split("::")[-1]
15
- end
16
-
17
- # return field [size, content] or false
18
- def initial_parse(binstr)
19
- if ! binstr
20
- # If nil, start with empty.
21
- return false
22
- elsif binstr[0,2] != self.class.const_get(:HEADER_ID)
23
- $stderr.puts "Warning: weired extra feild header ID. skip parsing"
24
- return false
25
- end
26
- [binstr[2,2].unpack("v")[0], binstr[4..-1]]
27
- end
28
-
29
- def ==(other)
30
- return false if self.class != other.class
31
- each do |k, v|
32
- v != other[k] and return false
33
- end
34
- true
35
- end
36
-
37
- def to_local_bin
38
- s = pack_for_local
39
- self.class.const_get(:HEADER_ID) + [s.bytesize].pack("v") + s
40
- end
41
-
42
- def to_c_dir_bin
43
- s = pack_for_c_dir
44
- self.class.const_get(:HEADER_ID) + [s.bytesize].pack("v") + s
45
- end
46
- end
47
-
48
- # Info-ZIP Additional timestamp field
49
- class UniversalTime < Generic
50
- HEADER_ID = "UT"
51
- register_map
52
-
53
- def initialize(binstr = nil)
54
- @ctime = nil
55
- @mtime = nil
56
- @atime = nil
57
- @flag = nil
58
- binstr and merge(binstr)
59
- end
60
- attr_accessor :atime, :ctime, :mtime, :flag
61
-
62
- def merge(binstr)
63
- return if binstr.empty?
64
- size, content = initial_parse(binstr)
65
- size or return
66
- @flag, mtime, atime, ctime = content.unpack("CVVV")
67
- mtime and @mtime ||= DOSTime.at(mtime)
68
- atime and @atime ||= DOSTime.at(atime)
69
- ctime and @ctime ||= DOSTime.at(ctime)
70
- end
71
-
72
- def ==(other)
73
- @mtime == other.mtime &&
74
- @atime == other.atime &&
75
- @ctime == other.ctime
76
- end
77
-
78
- def pack_for_local
79
- s = [@flag].pack("C")
80
- @flag & 1 != 0 and s << [@mtime.to_i].pack("V")
81
- @flag & 2 != 0 and s << [@atime.to_i].pack("V")
82
- @flag & 4 != 0 and s << [@ctime.to_i].pack("V")
83
- s
84
- end
85
-
86
- def pack_for_c_dir
87
- s = [@flag].pack("C")
88
- @flag & 1 == 1 and s << [@mtime.to_i].pack("V")
89
- s
90
- end
91
- end
92
-
93
- # Info-ZIP Extra for UNIX uid/gid
94
- class IUnix < Generic
95
- HEADER_ID = "Ux"
96
- register_map
97
-
98
- def initialize(binstr = nil)
99
- @uid = 0
100
- @gid = 0
101
- binstr and merge(binstr)
102
- end
103
- attr_accessor :uid, :gid
104
-
105
- def merge(binstr)
106
- return if binstr.empty?
107
- size, content = initial_parse(binstr)
108
- # size: 0 for central directory. 4 for local header
109
- return if(!size || size == 0)
110
- uid, gid = content.unpack("vv")
111
- @uid ||= uid
112
- @gid ||= gid
113
- end
114
-
115
- def ==(other)
116
- @uid == other.uid &&
117
- @gid == other.gid
118
- end
119
-
120
- def pack_for_local
121
- [@uid, @gid].pack("vv")
122
- end
123
-
124
- def pack_for_c_dir
125
- ""
126
- end
127
- end
128
-
129
- ## start main of ZipExtraField < Hash
130
- def initialize(binstr = nil)
131
- binstr and merge(binstr)
132
- end
133
-
134
- def merge(binstr)
135
- return if binstr.empty?
136
- i = 0
137
- while i < binstr.bytesize
138
- id = binstr[i,2]
139
- len = binstr[i + 2,2].to_s.unpack("v")[0]
140
- if id && ID_MAP.member?(id)
141
- field_name = ID_MAP[id].name
142
- if self.member?(field_name)
143
- self[field_name].mergea(binstr[i, len + 4])
144
- else
145
- field_obj = ID_MAP[id].new(binstr[i, len + 4])
146
- self[field_name] = field_obj
147
- end
148
- elsif id
149
- unless self["Unknown"]
150
- s = ""
151
- class << s
152
- alias_method :to_c_dir_bin, :to_s
153
- alias_method :to_local_bin, :to_s
154
- end
155
- self["Unknown"] = s
156
- end
157
- if !len || len + 4 > binstr[i..-1].bytesize
158
- self["Unknown"] << binstr[i..-1]
159
- break
160
- end
161
- self["Unknown"] << binstr[i, len + 4]
162
- end
163
- i += len + 4
164
- end
165
- end
166
-
167
- def create(name)
168
- field_class = nil
169
- ID_MAP.each { |id, klass|
170
- if klass.name == name
171
- field_class = klass
172
- break
173
- end
174
- }
175
- if ! field_class
176
- raise ZipError, "Unknown extra field '#{name}'"
177
- end
178
- self[name] = field_class.new()
179
- end
180
-
181
- def to_local_bin
182
- s = ""
183
- each do |k, v|
184
- s << v.to_local_bin
185
- end
186
- s
187
- end
188
- alias :to_s :to_local_bin
189
-
190
- def to_c_dir_bin
191
- s = ""
192
- each do |k, v|
193
- s << v.to_c_dir_bin
194
- end
195
- s
196
- end
197
-
198
- def c_dir_length
199
- to_c_dir_bin.bytesize
200
- end
201
- def local_length
202
- to_local_bin.bytesize
203
- end
204
- alias :c_dir_size :c_dir_length
205
- alias :local_size :local_length
206
- alias :length :local_length
207
- alias :size :local_length
208
- end
209
- end
210
-
211
- # Copyright (C) 2002, 2003 Thomas Sondergaard
212
- # rubyzip is free software; you can redistribute it and/or
213
- # modify it under the terms of the ruby license.
data/lib/zip/zip_file.rb DELETED
@@ -1,340 +0,0 @@
1
- module Zip
2
- # ZipFile is modeled after java.util.zip.ZipFile from the Java SDK.
3
- # The most important methods are those inherited from
4
- # ZipCentralDirectory for accessing information about the entries in
5
- # the archive and methods such as get_input_stream and
6
- # get_output_stream for reading from and writing entries to the
7
- # archive. The class includes a few convenience methods such as
8
- # #extract for extracting entries to the filesystem, and #remove,
9
- # #replace, #rename and #mkdir for making simple modifications to
10
- # the archive.
11
- #
12
- # Modifications to a zip archive are not committed until #commit or
13
- # #close is called. The method #open accepts a block following
14
- # the pattern from File.open offering a simple way to
15
- # automatically close the archive when the block returns.
16
- #
17
- # The following example opens zip archive <code>my.zip</code>
18
- # (creating it if it doesn't exist) and adds an entry
19
- # <code>first.txt</code> and a directory entry <code>a_dir</code>
20
- # to it.
21
- #
22
- # require 'zip/zip'
23
- #
24
- # Zip::ZipFile.open("my.zip", Zip::ZipFile::CREATE) {
25
- # |zipfile|
26
- # zipfile.get_output_stream("first.txt") { |f| f.puts "Hello from ZipFile" }
27
- # zipfile.mkdir("a_dir")
28
- # }
29
- #
30
- # The next example reopens <code>my.zip</code> writes the contents of
31
- # <code>first.txt</code> to standard out and deletes the entry from
32
- # the archive.
33
- #
34
- # require 'zip/zip'
35
- #
36
- # Zip::ZipFile.open("my.zip", Zip::ZipFile::CREATE) {
37
- # |zipfile|
38
- # puts zipfile.read("first.txt")
39
- # zipfile.remove("first.txt")
40
- # }
41
- #
42
- # ZipFileSystem offers an alternative API that emulates ruby's
43
- # interface for accessing the filesystem, ie. the File and Dir classes.
44
-
45
- class ZipFile < ZipCentralDirectory
46
-
47
- CREATE = 1
48
-
49
- attr_reader :name
50
-
51
- # default -> false
52
- attr_accessor :restore_ownership
53
- # default -> false
54
- attr_accessor :restore_permissions
55
- # default -> true
56
- attr_accessor :restore_times
57
-
58
- # Opens a zip archive. Pass true as the second parameter to create
59
- # a new archive if it doesn't exist already.
60
- def initialize(fileName, create = nil, buffer = false)
61
- super()
62
- @name = fileName
63
- @comment = ""
64
- case
65
- when ::File.exists?(fileName) && !buffer
66
- ::File.open(name, "rb") do |f|
67
- read_from_stream(f)
68
- end
69
- when create
70
- @entrySet = ZipEntrySet.new
71
- else
72
- raise ZipError, "File #{fileName} not found"
73
- end
74
- @create = create
75
- @storedEntries = @entrySet.dup
76
- @storedComment = @comment
77
- @restore_ownership = false
78
- @restore_permissions = false
79
- @restore_times = true
80
- end
81
-
82
- class << self
83
- # Same as #new. If a block is passed the ZipFile object is passed
84
- # to the block and is automatically closed afterwards just as with
85
- # ruby's builtin File.open method.
86
- def open(fileName, create = nil)
87
- zf = ZipFile.new(fileName, create)
88
- if block_given?
89
- begin
90
- yield zf
91
- ensure
92
- zf.close
93
- end
94
- else
95
- zf
96
- end
97
- end
98
-
99
- # Same as #open. But outputs data to a buffer instead of a file
100
- def add_buffer
101
- zf = ZipFile.new('', true, true)
102
- yield zf
103
- zf.write_buffer
104
- end
105
-
106
- # Like #open, but reads zip archive contents from a String or open IO
107
- # stream, and outputs data to a buffer.
108
- # (This can be used to extract data from a
109
- # downloaded zip archive without first saving it to disk.)
110
- def open_buffer(io)
111
- zf = ZipFile.new('',true,true)
112
- if io.is_a? IO
113
- zf.read_from_stream(io)
114
- elsif io.is_a? String
115
- require 'stringio'
116
- zf.read_from_stream(StringIO.new(io))
117
- else
118
- raise "Zip::ZipFile.open_buffer expects an argument of class String or IO. Found: #{io.class}"
119
- end
120
- yield zf
121
- zf.write_buffer
122
- end
123
-
124
- # Iterates over the contents of the ZipFile. This is more efficient
125
- # than using a ZipInputStream since this methods simply iterates
126
- # through the entries in the central directory structure in the archive
127
- # whereas ZipInputStream jumps through the entire archive accessing the
128
- # local entry headers (which contain the same information as the
129
- # central directory).
130
- def foreach(aZipFileName, &block)
131
- open(aZipFileName) do |zipFile|
132
- zipFile.each(&block)
133
- end
134
- end
135
- end
136
-
137
- # Returns the zip files comment, if it has one
138
- attr_accessor :comment
139
-
140
- # Returns an input stream to the specified entry. If a block is passed
141
- # the stream object is passed to the block and the stream is automatically
142
- # closed afterwards just as with ruby's builtin File.open method.
143
- def get_input_stream(entry, &aProc)
144
- get_entry(entry).get_input_stream(&aProc)
145
- end
146
-
147
- # Returns an output stream to the specified entry. If a block is passed
148
- # the stream object is passed to the block and the stream is automatically
149
- # closed afterwards just as with ruby's builtin File.open method.
150
- def get_output_stream(entry, permissionInt = nil, &aProc)
151
- newEntry = entry.kind_of?(ZipEntry) ? entry : ZipEntry.new(@name, entry.to_s)
152
- if newEntry.directory?
153
- raise ArgumentError,
154
- "cannot open stream to directory entry - '#{newEntry}'"
155
- end
156
- newEntry.unix_perms = permissionInt
157
- zipStreamableEntry = ZipStreamableStream.new(newEntry)
158
- @entrySet << zipStreamableEntry
159
- zipStreamableEntry.get_output_stream(&aProc)
160
- end
161
-
162
- # Returns the name of the zip archive
163
- def to_s
164
- @name
165
- end
166
-
167
- # Returns a string containing the contents of the specified entry
168
- def read(entry)
169
- get_input_stream(entry) { |is| is.read }
170
- end
171
-
172
- # Convenience method for adding the contents of a file to the archive
173
- def add(entry, srcPath, &continueOnExistsProc)
174
- continueOnExistsProc ||= proc { Zip.options[:continue_on_exists_proc] }
175
- check_entry_exists(entry, continueOnExistsProc, "add")
176
- newEntry = entry.kind_of?(ZipEntry) ? entry : ZipEntry.new(@name, entry.to_s)
177
- newEntry.gather_fileinfo_from_srcpath(srcPath)
178
- @entrySet << newEntry
179
- end
180
-
181
- # Removes the specified entry.
182
- def remove(entry)
183
- @entrySet.delete(get_entry(entry))
184
- end
185
-
186
- # Renames the specified entry.
187
- def rename(entry, newName, &continueOnExistsProc)
188
- foundEntry = get_entry(entry)
189
- check_entry_exists(newName, continueOnExistsProc, "rename")
190
- @entrySet.delete(foundEntry)
191
- foundEntry.name = newName
192
- @entrySet << foundEntry
193
- end
194
-
195
- # Replaces the specified entry with the contents of srcPath (from
196
- # the file system).
197
- def replace(entry, srcPath)
198
- check_file(srcPath)
199
- remove(entry)
200
- add(entry, srcPath)
201
- end
202
-
203
- # Extracts entry to file destPath.
204
- def extract(entry, destPath, &onExistsProc)
205
- onExistsProc ||= proc { Zip.options[:on_exists_proc] }
206
- foundEntry = get_entry(entry)
207
- foundEntry.extract(destPath, &onExistsProc)
208
- end
209
-
210
- # Commits changes that has been made since the previous commit to
211
- # the zip archive.
212
- def commit
213
- return if !commit_required?
214
- on_success_replace(name) {
215
- |tmpFile|
216
- ZipOutputStream.open(tmpFile) {
217
- |zos|
218
-
219
- @entrySet.each {
220
- |e|
221
- e.write_to_zip_output_stream(zos)
222
- e.dirty = false
223
- }
224
- zos.comment = comment
225
- }
226
- true
227
- }
228
- initialize(name)
229
- end
230
-
231
- # Write buffer write changes to buffer and return
232
- def write_buffer
233
- buffer = ZipOutputStream.write_buffer do |zos|
234
- @entrySet.each { |e| e.write_to_zip_output_stream(zos) }
235
- zos.comment = comment
236
- end
237
- return buffer
238
- end
239
-
240
- # Closes the zip file committing any changes that has been made.
241
- def close
242
- commit
243
- end
244
-
245
- # Returns true if any changes has been made to this archive since
246
- # the previous commit
247
- def commit_required?
248
- @entrySet.each do |e|
249
- return true if e.dirty
250
- end
251
- @comment != @storedComment || @entrySet != @storedEntries || @create == ZipFile::CREATE
252
- end
253
-
254
- # Searches for entry with the specified name. Returns nil if
255
- # no entry is found. See also get_entry
256
- def find_entry(entry_name)
257
- @entrySet.find_entry(entry_name)
258
- end
259
-
260
- # Searches for entries given a glob
261
- def glob(*args,&block)
262
- @entrySet.glob(*args,&block)
263
- end
264
-
265
- # Searches for an entry just as find_entry, but throws Errno::ENOENT
266
- # if no entry is found.
267
- def get_entry(entry)
268
- selectedEntry = find_entry(entry)
269
- unless selectedEntry
270
- raise Errno::ENOENT, entry
271
- end
272
- selectedEntry.restore_ownership = @restore_ownership
273
- selectedEntry.restore_permissions = @restore_permissions
274
- selectedEntry.restore_times = @restore_times
275
- selectedEntry
276
- end
277
-
278
- # Creates a directory
279
- def mkdir(entryName, permissionInt = 0755)
280
- if find_entry(entryName)
281
- raise Errno::EEXIST, "File exists - #{entryName}"
282
- end
283
- entryName = entryName.dup.to_s
284
- entryName << '/' unless entryName.end_with?('/')
285
- @entrySet << ZipStreamableDirectory.new(@name, entryName, nil, permissionInt)
286
- end
287
-
288
- private
289
-
290
- def is_directory(newEntry, srcPath)
291
- srcPathIsDirectory = ::File.directory?(srcPath)
292
- if newEntry.is_directory && ! srcPathIsDirectory
293
- raise ArgumentError,
294
- "entry name '#{newEntry}' indicates directory entry, but "+
295
- "'#{srcPath}' is not a directory"
296
- elsif !newEntry.is_directory && srcPathIsDirectory
297
- newEntry.name += "/"
298
- end
299
- newEntry.is_directory && srcPathIsDirectory
300
- end
301
-
302
- def check_entry_exists(entryName, continueOnExistsProc, procedureName)
303
- continueOnExistsProc ||= proc { Zip.options[:continue_on_exists_proc] }
304
- if @entrySet.include?(entryName)
305
- if continueOnExistsProc.call
306
- remove get_entry(entryName)
307
- else
308
- raise ZipEntryExistsError,
309
- procedureName + " failed. Entry #{entryName} already exists"
310
- end
311
- end
312
- end
313
-
314
- def check_file(path)
315
- unless ::File.readable?(path)
316
- raise Errno::ENOENT, path
317
- end
318
- end
319
-
320
- def on_success_replace(aFilename)
321
- tmpfile = get_tempfile
322
- tmpFilename = tmpfile.path
323
- tmpfile.close
324
- if yield tmpFilename
325
- ::File.rename(tmpFilename, name)
326
- end
327
- end
328
-
329
- def get_tempfile
330
- tempFile = Tempfile.new(::File.basename(name), ::File.dirname(name))
331
- tempFile.binmode
332
- tempFile
333
- end
334
-
335
- end
336
- end
337
-
338
- # Copyright (C) 2002, 2003 Thomas Sondergaard
339
- # rubyzip is free software; you can redistribute it and/or
340
- # modify it under the terms of the ruby license.
@@ -1,144 +0,0 @@
1
- module Zip
2
- # ZipInputStream is the basic class for reading zip entries in a
3
- # zip file. It is possible to create a ZipInputStream object directly,
4
- # passing the zip file name to the constructor, but more often than not
5
- # the ZipInputStream will be obtained from a ZipFile (perhaps using the
6
- # ZipFileSystem interface) object for a particular entry in the zip
7
- # archive.
8
- #
9
- # A ZipInputStream inherits IOExtras::AbstractInputStream in order
10
- # to provide an IO-like interface for reading from a single zip
11
- # entry. Beyond methods for mimicking an IO-object it contains
12
- # the method get_next_entry for iterating through the entries of
13
- # an archive. get_next_entry returns a ZipEntry object that describes
14
- # the zip entry the ZipInputStream is currently reading from.
15
- #
16
- # Example that creates a zip archive with ZipOutputStream and reads it
17
- # back again with a ZipInputStream.
18
- #
19
- # require 'zip/zip'
20
- #
21
- # Zip::ZipOutputStream::open("my.zip") {
22
- # |io|
23
- #
24
- # io.put_next_entry("first_entry.txt")
25
- # io.write "Hello world!"
26
- #
27
- # io.put_next_entry("adir/first_entry.txt")
28
- # io.write "Hello again!"
29
- # }
30
- #
31
- #
32
- # Zip::ZipInputStream::open("my.zip") {
33
- # |io|
34
- #
35
- # while (entry = io.get_next_entry)
36
- # puts "Contents of #{entry.name}: '#{io.read}'"
37
- # end
38
- # }
39
- #
40
- # java.util.zip.ZipInputStream is the original inspiration for this
41
- # class.
42
-
43
- class ZipInputStream
44
- include IOExtras::AbstractInputStream
45
-
46
- # Opens the indicated zip file. An exception is thrown
47
- # if the specified offset in the specified filename is
48
- # not a local zip entry header.
49
- def initialize(filename, offset = 0, io = nil)
50
- super()
51
- if (io.nil?)
52
- @archiveIO = ::File.open(filename, "rb")
53
- @archiveIO.seek(offset, IO::SEEK_SET)
54
- else
55
- @archiveIO = io
56
- end
57
- @decompressor = NullDecompressor.instance
58
- @currentEntry = nil
59
- end
60
-
61
- def close
62
- @archiveIO.close
63
- end
64
-
65
- # Same as #initialize but if a block is passed the opened
66
- # stream is passed to the block and closed when the block
67
- # returns.
68
- def ZipInputStream.open(filename)
69
- return new(filename) unless block_given?
70
-
71
- zio = new(filename)
72
- yield zio
73
- ensure
74
- zio.close if zio
75
- end
76
-
77
- def ZipInputStream.open_buffer(io)
78
- return new('',0,io) unless block_given?
79
- zio = new('',0,io)
80
- yield zio
81
- ensure
82
- zio.close if zio
83
- end
84
-
85
- # Returns a ZipEntry object. It is necessary to call this
86
- # method on a newly created ZipInputStream before reading from
87
- # the first entry in the archive. Returns nil when there are
88
- # no more entries.
89
-
90
- def get_next_entry
91
- @archiveIO.seek(@currentEntry.next_header_offset, IO::SEEK_SET) if @currentEntry
92
- open_entry
93
- end
94
-
95
- # Rewinds the stream to the beginning of the current entry
96
- def rewind
97
- return if @currentEntry.nil?
98
- @lineno = 0
99
- @archiveIO.seek(@currentEntry.localHeaderOffset,
100
- IO::SEEK_SET)
101
- open_entry
102
- end
103
-
104
- # Modeled after IO.sysread
105
- def sysread(numberOfBytes = nil, buf = nil)
106
- @decompressor.sysread(numberOfBytes, buf)
107
- end
108
-
109
- def eof
110
- @outputBuffer.empty? && @decompressor.eof
111
- end
112
- alias :eof? :eof
113
-
114
- protected
115
-
116
- def open_entry
117
- @currentEntry = ZipEntry.read_local_entry(@archiveIO)
118
- if @currentEntry.nil?
119
- @decompressor = NullDecompressor.instance
120
- elsif @currentEntry.compression_method == ZipEntry::STORED
121
- @decompressor = PassThruDecompressor.new(@archiveIO, @currentEntry.size)
122
- elsif @currentEntry.compression_method == ZipEntry::DEFLATED
123
- @decompressor = Inflater.new(@archiveIO)
124
- else
125
- raise ZipCompressionMethodError,
126
- "Unsupported compression method #{@currentEntry.compression_method}"
127
- end
128
- flush
129
- return @currentEntry
130
- end
131
-
132
- def produce_input
133
- @decompressor.produce_input
134
- end
135
-
136
- def input_finished?
137
- @decompressor.input_finished?
138
- end
139
- end
140
- end
141
-
142
- # Copyright (C) 2002, 2003 Thomas Sondergaard
143
- # rubyzip is free software; you can redistribute it and/or
144
- # modify it under the terms of the ruby license.