rubyzip 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rubyzip might be problematic. Click here for more details.

Files changed (45) hide show
  1. data/{README → README.md} +16 -17
  2. data/Rakefile +6 -104
  3. data/lib/zip/compressor.rb +10 -0
  4. data/lib/zip/constants.rb +10 -0
  5. data/lib/zip/decompressor.rb +13 -0
  6. data/lib/zip/deflater.rb +30 -0
  7. data/lib/zip/inflater.rb +65 -0
  8. data/lib/zip/ioextras.rb +35 -36
  9. data/lib/zip/null_compressor.rb +15 -0
  10. data/lib/zip/null_decompressor.rb +25 -0
  11. data/lib/zip/null_input_stream.rb +9 -0
  12. data/lib/zip/pass_thru_compressor.rb +23 -0
  13. data/lib/zip/pass_thru_decompressor.rb +40 -0
  14. data/lib/zip/stdrubyext.rb +10 -44
  15. data/lib/zip/zip.rb +22 -1848
  16. data/lib/zip/zip_central_directory.rb +139 -0
  17. data/lib/zip/zip_entry.rb +639 -0
  18. data/lib/zip/zip_entry_set.rb +66 -0
  19. data/lib/zip/zip_extra_field.rb +213 -0
  20. data/lib/zip/zip_file.rb +318 -0
  21. data/lib/zip/zip_input_stream.rb +134 -0
  22. data/lib/zip/zip_output_stream.rb +172 -0
  23. data/lib/zip/zip_streamable_directory.rb +15 -0
  24. data/lib/zip/zip_streamable_stream.rb +47 -0
  25. data/lib/zip/zipfilesystem.rb +90 -88
  26. data/samples/example_recursive.rb +49 -0
  27. metadata +54 -60
  28. data/ChangeLog +0 -1146
  29. data/install.rb +0 -23
  30. data/lib/zip/ziprequire.rb +0 -90
  31. data/test/alltests.rb +0 -9
  32. data/test/data/file1.txt +0 -46
  33. data/test/data/file1.txt.deflatedData +0 -0
  34. data/test/data/file2.txt +0 -1504
  35. data/test/data/notzippedruby.rb +0 -7
  36. data/test/data/rubycode.zip +0 -0
  37. data/test/data/rubycode2.zip +0 -0
  38. data/test/data/testDirectory.bin +0 -0
  39. data/test/data/zipWithDirs.zip +0 -0
  40. data/test/gentestfiles.rb +0 -157
  41. data/test/ioextrastest.rb +0 -208
  42. data/test/stdrubyexttest.rb +0 -52
  43. data/test/zipfilesystemtest.rb +0 -841
  44. data/test/ziprequiretest.rb +0 -43
  45. data/test/ziptest.rb +0 -1620
@@ -0,0 +1,134 @@
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)
50
+ super()
51
+ @archiveIO = File.open(filename, "rb")
52
+ @archiveIO.seek(offset, IO::SEEK_SET)
53
+ @decompressor = NullDecompressor.instance
54
+ @currentEntry = nil
55
+ end
56
+
57
+ def close
58
+ @archiveIO.close
59
+ end
60
+
61
+ # Same as #initialize but if a block is passed the opened
62
+ # stream is passed to the block and closed when the block
63
+ # returns.
64
+ def ZipInputStream.open(filename)
65
+ return new(filename) unless block_given?
66
+
67
+ zio = new(filename)
68
+ yield zio
69
+ ensure
70
+ zio.close if zio
71
+ end
72
+
73
+ # Returns a ZipEntry object. It is necessary to call this
74
+ # method on a newly created ZipInputStream before reading from
75
+ # the first entry in the archive. Returns nil when there are
76
+ # no more entries.
77
+
78
+ def get_next_entry
79
+ @archiveIO.seek(@currentEntry.next_header_offset,
80
+ IO::SEEK_SET) if @currentEntry
81
+ open_entry
82
+ end
83
+
84
+ # Rewinds the stream to the beginning of the current entry
85
+ def rewind
86
+ return if @currentEntry.nil?
87
+ @lineno = 0
88
+ @archiveIO.seek(@currentEntry.localHeaderOffset,
89
+ IO::SEEK_SET)
90
+ open_entry
91
+ end
92
+
93
+ # Modeled after IO.sysread
94
+ def sysread(numberOfBytes = nil, buf = nil)
95
+ @decompressor.sysread(numberOfBytes, buf)
96
+ end
97
+
98
+ def eof
99
+ @outputBuffer.empty? && @decompressor.eof
100
+ end
101
+ alias :eof? :eof
102
+
103
+ protected
104
+
105
+ def open_entry
106
+ @currentEntry = ZipEntry.read_local_entry(@archiveIO)
107
+ if (@currentEntry == nil)
108
+ @decompressor = NullDecompressor.instance
109
+ elsif @currentEntry.compression_method == ZipEntry::STORED
110
+ @decompressor = PassThruDecompressor.new(@archiveIO,
111
+ @currentEntry.size)
112
+ elsif @currentEntry.compression_method == ZipEntry::DEFLATED
113
+ @decompressor = Inflater.new(@archiveIO)
114
+ else
115
+ raise ZipCompressionMethodError,
116
+ "Unsupported compression method #{@currentEntry.compression_method}"
117
+ end
118
+ flush
119
+ return @currentEntry
120
+ end
121
+
122
+ def produce_input
123
+ @decompressor.produce_input
124
+ end
125
+
126
+ def input_finished?
127
+ @decompressor.input_finished?
128
+ end
129
+ end
130
+ end
131
+
132
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
133
+ # rubyzip is free software; you can redistribute it and/or
134
+ # modify it under the terms of the ruby license.
@@ -0,0 +1,172 @@
1
+ module Zip
2
+ # ZipOutputStream is the basic class for writing zip files. It is
3
+ # possible to create a ZipOutputStream object directly, passing
4
+ # the zip file name to the constructor, but more often than not
5
+ # the ZipOutputStream 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 ZipOutputStream inherits IOExtras::AbstractOutputStream in order
10
+ # to provide an IO-like interface for writing to a single zip
11
+ # entry. Beyond methods for mimicking an IO-object it contains
12
+ # the method put_next_entry that closes the current entry
13
+ # and creates a new.
14
+ #
15
+ # Please refer to ZipInputStream for example code.
16
+ #
17
+ # java.util.zip.ZipOutputStream is the original inspiration for this
18
+ # class.
19
+
20
+ class ZipOutputStream
21
+ include IOExtras::AbstractOutputStream
22
+
23
+ attr_accessor :comment
24
+
25
+ # Opens the indicated zip file. If a file with that name already
26
+ # exists it will be overwritten.
27
+ def initialize(fileName, stream=false)
28
+ super()
29
+ @fileName = fileName
30
+ if stream
31
+ @outputStream = StringIO.new
32
+ else
33
+ @outputStream = File.new(@fileName, "wb")
34
+ end
35
+ @entrySet = ZipEntrySet.new
36
+ @compressor = NullCompressor.instance
37
+ @closed = false
38
+ @currentEntry = nil
39
+ @comment = nil
40
+ end
41
+
42
+ # Same as #initialize but if a block is passed the opened
43
+ # stream is passed to the block and closed when the block
44
+ # returns.
45
+ def ZipOutputStream.open(fileName)
46
+ return new(fileName) unless block_given?
47
+ zos = new(fileName)
48
+ yield zos
49
+ ensure
50
+ zos.close if zos
51
+ end
52
+
53
+ # Same as #open but writes to a filestream instead
54
+ def ZipOutputStream.write_buffer
55
+ zos = new('', true)
56
+ yield zos
57
+ return zos.close_buffer
58
+ end
59
+
60
+ # Closes the stream and writes the central directory to the zip file
61
+ def close
62
+ return if @closed
63
+ finalize_current_entry
64
+ update_local_headers
65
+ write_central_directory
66
+ @outputStream.close
67
+ @closed = true
68
+ end
69
+
70
+ # Closes the stream and writes the central directory to the zip file
71
+ def close_buffer
72
+ return @outputStream if @closed
73
+ finalize_current_entry
74
+ update_local_headers
75
+ write_central_directory
76
+ @closed = true
77
+ return @outputStream
78
+ end
79
+
80
+ # Closes the current entry and opens a new for writing.
81
+ # +entry+ can be a ZipEntry object or a string.
82
+ def put_next_entry(entryname, comment = nil, extra = nil, compression_method = ZipEntry::DEFLATED, level = Zlib::DEFAULT_COMPRESSION)
83
+ raise ZipError, "zip stream is closed" if @closed
84
+ new_entry = ZipEntry.new(@fileName, entryname.to_s)
85
+ new_entry.unix_perms = entryname.unix_perms if entryname.respond_to? :unix_perms
86
+ new_entry.comment = comment if !comment.nil?
87
+ if (!extra.nil?)
88
+ new_entry.extra = ZipExtraField === extra ? extra : ZipExtraField.new(extra.to_s)
89
+ end
90
+ new_entry.compression_method = compression_method
91
+ init_next_entry(new_entry, level)
92
+ @currentEntry = new_entry
93
+ end
94
+
95
+ def copy_raw_entry(entry)
96
+ entry = entry.dup
97
+ raise ZipError, "zip stream is closed" if @closed
98
+ raise ZipError, "entry is not a ZipEntry" if !entry.kind_of?(ZipEntry)
99
+ finalize_current_entry
100
+ @entrySet << entry
101
+ src_pos = entry.local_entry_offset
102
+ entry.write_local_entry(@outputStream)
103
+ @compressor = NullCompressor.instance
104
+ entry.get_raw_input_stream {
105
+ |is|
106
+ is.seek(src_pos, IO::SEEK_SET)
107
+ IOExtras.copy_stream_n(@outputStream, is, entry.compressed_size)
108
+ }
109
+ @compressor = NullCompressor.instance
110
+ @currentEntry = nil
111
+ end
112
+
113
+ private
114
+ def finalize_current_entry
115
+ return unless @currentEntry
116
+ finish
117
+ @currentEntry.compressed_size = @outputStream.tell - @currentEntry.localHeaderOffset -
118
+ @currentEntry.calculate_local_header_size
119
+ @currentEntry.size = @compressor.size
120
+ @currentEntry.crc = @compressor.crc
121
+ @currentEntry = nil
122
+ @compressor = NullCompressor.instance
123
+ end
124
+
125
+ def init_next_entry(entry, level = Zlib::DEFAULT_COMPRESSION)
126
+ finalize_current_entry
127
+ @entrySet << entry
128
+ entry.write_local_entry(@outputStream)
129
+ @compressor = get_compressor(entry, level)
130
+ end
131
+
132
+ def get_compressor(entry, level)
133
+ case entry.compression_method
134
+ when ZipEntry::DEFLATED then Deflater.new(@outputStream, level)
135
+ when ZipEntry::STORED then PassThruCompressor.new(@outputStream)
136
+ else raise ZipCompressionMethodError,
137
+ "Invalid compression method: '#{entry.compression_method}'"
138
+ end
139
+ end
140
+
141
+ def update_local_headers
142
+ pos = @outputStream.tell
143
+ @entrySet.each {
144
+ |entry|
145
+ @outputStream.pos = entry.localHeaderOffset
146
+ entry.write_local_entry(@outputStream)
147
+ }
148
+ @outputStream.pos = pos
149
+ end
150
+
151
+ def write_central_directory
152
+ cdir = ZipCentralDirectory.new(@entrySet, @comment)
153
+ cdir.write_to_stream(@outputStream)
154
+ end
155
+
156
+ protected
157
+
158
+ def finish
159
+ @compressor.finish
160
+ end
161
+
162
+ public
163
+ # Modeled after IO.<<
164
+ def << (data)
165
+ @compressor << data
166
+ end
167
+ end
168
+ end
169
+
170
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
171
+ # rubyzip is free software; you can redistribute it and/or
172
+ # modify it under the terms of the ruby license.
@@ -0,0 +1,15 @@
1
+ module Zip
2
+ class ZipStreamableDirectory < ZipEntry
3
+ def initialize(zipfile, entry, srcPath = nil, permissionInt = nil)
4
+ super(zipfile, entry)
5
+
6
+ @ftype = :directory
7
+ entry.get_extra_attributes_from_path(srcPath) if (srcPath)
8
+ @unix_perms = permissionInt if (permissionInt)
9
+ end
10
+ end
11
+ end
12
+
13
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
14
+ # rubyzip is free software; you can redistribute it and/or
15
+ # modify it under the terms of the ruby license.
@@ -0,0 +1,47 @@
1
+ module Zip
2
+ class ZipStreamableStream < DelegateClass(ZipEntry) #nodoc:all
3
+ def initialize(entry)
4
+ super(entry)
5
+ @tempFile = Tempfile.new(File.basename(name), File.dirname(zipfile))
6
+ @tempFile.binmode
7
+ end
8
+
9
+ def get_output_stream
10
+ if block_given?
11
+ begin
12
+ yield(@tempFile)
13
+ ensure
14
+ @tempFile.close
15
+ end
16
+ else
17
+ @tempFile
18
+ end
19
+ end
20
+
21
+ def get_input_stream
22
+ if ! @tempFile.closed?
23
+ raise StandardError, "cannot open entry for reading while its open for writing - #{name}"
24
+ end
25
+ @tempFile.open # reopens tempfile from top
26
+ @tempFile.binmode
27
+ if block_given?
28
+ begin
29
+ yield(@tempFile)
30
+ ensure
31
+ @tempFile.close
32
+ end
33
+ else
34
+ @tempFile
35
+ end
36
+ end
37
+
38
+ def write_to_zip_output_stream(aZipOutputStream)
39
+ aZipOutputStream.put_next_entry(self)
40
+ get_input_stream { |is| IOExtras.copy_stream(aZipOutputStream, is) }
41
+ end
42
+ end
43
+ end
44
+
45
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
46
+ # rubyzip is free software; you can redistribute it and/or
47
+ # modify it under the terms of the ruby license.
@@ -50,7 +50,7 @@ module Zip
50
50
  def dir
51
51
  @zipFsDir
52
52
  end
53
-
53
+
54
54
  # Returns a ZipFsFile which is much like ruby's builtin File (class)
55
55
  # object, except it works on the ZipFile on which this method is
56
56
  # invoked
@@ -74,7 +74,7 @@ module Zip
74
74
  @zipFsFile = zipFsFile
75
75
  @entryName = entryName
76
76
  end
77
-
77
+
78
78
  def forward_invoke(msg)
79
79
  @zipFsFile.send(msg, @entryName)
80
80
  end
@@ -82,7 +82,7 @@ module Zip
82
82
  def kind_of?(t)
83
83
  super || t == ::File::Stat
84
84
  end
85
-
85
+
86
86
  forward_message :forward_invoke, :file?, :directory?, :pipe?, :chardev?
87
87
  forward_message :forward_invoke, :symlink?, :socket?, :blockdev?
88
88
  forward_message :forward_invoke, :readable?, :readable_real?
@@ -93,7 +93,7 @@ module Zip
93
93
  forward_message :forward_invoke, :zero?
94
94
  forward_message :forward_invoke, :size, :size?
95
95
  forward_message :forward_invoke, :mtime, :atime, :ctime
96
-
96
+
97
97
  def blocks; nil; end
98
98
 
99
99
  def get_entry
@@ -140,7 +140,7 @@ module Zip
140
140
  end
141
141
 
142
142
  def nlink; 1; end
143
-
143
+
144
144
  def blksize; nil; end
145
145
 
146
146
  def mode
@@ -154,7 +154,7 @@ module Zip
154
154
  end
155
155
 
156
156
  def initialize(mappedZip)
157
- @mappedZip = mappedZip
157
+ @mappedZip = mappedZip
158
158
  end
159
159
 
160
160
  def get_entry(fileName)
@@ -174,12 +174,12 @@ module Zip
174
174
  end
175
175
  end
176
176
  private :unix_mode_cmp
177
-
177
+
178
178
  def exists?(fileName)
179
179
  expand_path(fileName) == "/" || @mappedZip.find_entry(fileName) != nil
180
180
  end
181
181
  alias :exist? :exists?
182
-
182
+
183
183
  # Permissions not implemented, so if the file exists it is accessible
184
184
  alias owned? exists?
185
185
  alias grpowned? exists?
@@ -206,7 +206,7 @@ module Zip
206
206
  def setgid?(fileName)
207
207
  unix_mode_cmp(fileName, 02000)
208
208
  end
209
-
209
+
210
210
  def sticky?(fileName)
211
211
  unix_mode_cmp(fileName, 01000)
212
212
  end
@@ -220,36 +220,36 @@ module Zip
220
220
  end
221
221
 
222
222
  def directory?(fileName)
223
- entry = @mappedZip.find_entry(fileName)
224
- expand_path(fileName) == "/" || (entry != nil && entry.directory?)
223
+ entry = @mappedZip.find_entry(fileName)
224
+ expand_path(fileName) == "/" || (entry != nil && entry.directory?)
225
225
  end
226
-
227
- def open(fileName, openMode = "r", &block)
226
+
227
+ def open(fileName, openMode = "r", permissionInt = 0644, &block)
228
228
  openMode.gsub!("b", "") # ignore b option
229
229
  case openMode
230
- when "r"
231
- @mappedZip.get_input_stream(fileName, &block)
232
- when "w"
233
- @mappedZip.get_output_stream(fileName, &block)
234
- else
235
- raise StandardError, "openmode '#{openMode} not supported" unless openMode == "r"
230
+ when "r"
231
+ @mappedZip.get_input_stream(fileName, &block)
232
+ when "w"
233
+ @mappedZip.get_output_stream(fileName, permissionInt, &block)
234
+ else
235
+ raise StandardError, "openmode '#{openMode} not supported" unless openMode == "r"
236
236
  end
237
237
  end
238
238
 
239
239
  def new(fileName, openMode = "r")
240
- open(fileName, openMode)
240
+ open(fileName, openMode)
241
241
  end
242
-
242
+
243
243
  def size(fileName)
244
- @mappedZip.get_entry(fileName).size
244
+ @mappedZip.get_entry(fileName).size
245
245
  end
246
-
246
+
247
247
  # Returns nil for not found and nil for directories
248
248
  def size?(fileName)
249
- entry = @mappedZip.find_entry(fileName)
250
- return (entry == nil || entry.directory?) ? nil : entry.size
249
+ entry = @mappedZip.find_entry(fileName)
250
+ return (entry == nil || entry.directory?) ? nil : entry.size
251
251
  end
252
-
252
+
253
253
  def chown(ownerInt, groupInt, *filenames)
254
254
  filenames.each { |fileName|
255
255
  e = get_entry(fileName)
@@ -266,39 +266,41 @@ module Zip
266
266
  filenames.each { |fileName|
267
267
  e = get_entry(fileName)
268
268
  e.fstype = 3 # force convertion filesystem type to unix
269
+ e.unix_perms = modeInt
269
270
  e.externalFileAttributes = modeInt << 16
271
+ e.dirty = true
270
272
  }
271
273
  filenames.size
272
274
  end
273
275
 
274
276
  def zero?(fileName)
275
- sz = size(fileName)
276
- sz == nil || sz == 0
277
+ sz = size(fileName)
278
+ sz == nil || sz == 0
277
279
  rescue Errno::ENOENT
278
- false
280
+ false
279
281
  end
280
-
282
+
281
283
  def file?(fileName)
282
- entry = @mappedZip.find_entry(fileName)
283
- entry != nil && entry.file?
284
+ entry = @mappedZip.find_entry(fileName)
285
+ entry != nil && entry.file?
284
286
  end
285
-
287
+
286
288
  def dirname(fileName)
287
- ::File.dirname(fileName)
289
+ ::File.dirname(fileName)
288
290
  end
289
-
291
+
290
292
  def basename(fileName)
291
- ::File.basename(fileName)
293
+ ::File.basename(fileName)
292
294
  end
293
-
295
+
294
296
  def split(fileName)
295
- ::File.split(fileName)
297
+ ::File.split(fileName)
296
298
  end
297
-
299
+
298
300
  def join(*fragments)
299
- ::File.join(*fragments)
301
+ ::File.join(*fragments)
300
302
  end
301
-
303
+
302
304
  def utime(modifiedTime, *fileNames)
303
305
  fileNames.each { |fileName|
304
306
  get_entry(fileName).time = modifiedTime
@@ -306,9 +308,9 @@ module Zip
306
308
  end
307
309
 
308
310
  def mtime(fileName)
309
- @mappedZip.get_entry(fileName).mtime
311
+ @mappedZip.get_entry(fileName).mtime
310
312
  end
311
-
313
+
312
314
  def atime(fileName)
313
315
  e = get_entry(fileName)
314
316
  if e.extra.member? "UniversalTime"
@@ -317,7 +319,7 @@ module Zip
317
319
  nil
318
320
  end
319
321
  end
320
-
322
+
321
323
  def ctime(fileName)
322
324
  e = get_entry(fileName)
323
325
  if e.extra.member? "UniversalTime"
@@ -328,43 +330,43 @@ module Zip
328
330
  end
329
331
 
330
332
  def pipe?(filename)
331
- false
333
+ false
332
334
  end
333
-
335
+
334
336
  def blockdev?(filename)
335
- false
337
+ false
336
338
  end
337
-
339
+
338
340
  def chardev?(filename)
339
- false
341
+ false
340
342
  end
341
-
343
+
342
344
  def symlink?(fileName)
343
- false
345
+ false
344
346
  end
345
-
347
+
346
348
  def socket?(fileName)
347
- false
349
+ false
348
350
  end
349
-
351
+
350
352
  def ftype(fileName)
351
- @mappedZip.get_entry(fileName).directory? ? "directory" : "file"
353
+ @mappedZip.get_entry(fileName).directory? ? "directory" : "file"
352
354
  end
353
-
355
+
354
356
  def readlink(fileName)
355
- raise NotImplementedError, "The readlink() function is not implemented"
357
+ raise NotImplementedError, "The readlink() function is not implemented"
356
358
  end
357
-
359
+
358
360
  def symlink(fileName, symlinkName)
359
- raise NotImplementedError, "The symlink() function is not implemented"
361
+ raise NotImplementedError, "The symlink() function is not implemented"
360
362
  end
361
363
 
362
364
  def link(fileName, symlinkName)
363
- raise NotImplementedError, "The link() function is not implemented"
365
+ raise NotImplementedError, "The link() function is not implemented"
364
366
  end
365
367
 
366
368
  def pipe
367
- raise NotImplementedError, "The pipe() function is not implemented"
369
+ raise NotImplementedError, "The pipe() function is not implemented"
368
370
  end
369
371
 
370
372
  def stat(fileName)
@@ -377,7 +379,7 @@ module Zip
377
379
  alias lstat stat
378
380
 
379
381
  def readlines(fileName)
380
- open(fileName) { |is| is.readlines }
382
+ open(fileName) { |is| is.readlines }
381
383
  end
382
384
 
383
385
  def read(fileName)
@@ -385,21 +387,21 @@ module Zip
385
387
  end
386
388
 
387
389
  def popen(*args, &aProc)
388
- File.popen(*args, &aProc)
390
+ File.popen(*args, &aProc)
389
391
  end
390
392
 
391
393
  def foreach(fileName, aSep = $/, &aProc)
392
- open(fileName) { |is| is.each_line(aSep, &aProc) }
394
+ open(fileName) { |is| is.each_line(aSep, &aProc) }
393
395
  end
394
396
 
395
397
  def delete(*args)
396
- args.each {
397
- |fileName|
398
- if directory?(fileName)
399
- raise Errno::EISDIR, "Is a directory - \"#{fileName}\""
400
- end
401
- @mappedZip.remove(fileName)
402
- }
398
+ args.each {
399
+ |fileName|
400
+ if directory?(fileName)
401
+ raise Errno::EISDIR, "Is a directory - \"#{fileName}\""
402
+ end
403
+ @mappedZip.remove(fileName)
404
+ }
403
405
  end
404
406
 
405
407
  def rename(fileToRename, newName)
@@ -420,11 +422,11 @@ module Zip
420
422
  # The individual methods are not documented due to their
421
423
  # similarity with the methods in Dir
422
424
  class ZipFsDir
423
-
425
+
424
426
  def initialize(mappedZip)
425
427
  @mappedZip = mappedZip
426
428
  end
427
-
429
+
428
430
  attr_writer :file
429
431
 
430
432
  def new(aDirectoryName)
@@ -446,14 +448,14 @@ module Zip
446
448
 
447
449
  def pwd; @mappedZip.pwd; end
448
450
  alias getwd pwd
449
-
451
+
450
452
  def chdir(aDirectoryName)
451
453
  unless @file.stat(aDirectoryName).directory?
452
454
  raise Errno::EINVAL, "Invalid argument - #{aDirectoryName}"
453
455
  end
454
456
  @mappedZip.pwd = @file.expand_path(aDirectoryName)
455
457
  end
456
-
458
+
457
459
  def entries(aDirectoryName)
458
460
  entries = []
459
461
  foreach(aDirectoryName) { |e| entries << e }
@@ -465,7 +467,7 @@ module Zip
465
467
  raise Errno::ENOTDIR, aDirectoryName
466
468
  end
467
469
  path = @file.expand_path(aDirectoryName).ensure_end("/")
468
-
470
+ path = Regexp.escape(path)
469
471
  subDirEntriesRegex = Regexp.new("^#{path}([^/]+)$")
470
472
  @mappedZip.each {
471
473
  |fileName|
@@ -482,13 +484,13 @@ module Zip
482
484
  end
483
485
  alias rmdir delete
484
486
  alias unlink delete
485
-
487
+
486
488
  def mkdir(entryName, permissionInt = 0755)
487
489
  @mappedZip.mkdir(entryName, permissionInt)
488
490
  end
489
-
491
+
490
492
  def chroot(*args)
491
- raise NotImplementedError, "The chroot() function is not implemented"
493
+ raise NotImplementedError, "The chroot() function is not implemented"
492
494
  end
493
495
 
494
496
  end
@@ -540,13 +542,13 @@ module Zip
540
542
  @zipFile = zipFile
541
543
  @pwd = "/"
542
544
  end
543
-
545
+
544
546
  attr_accessor :pwd
545
-
547
+
546
548
  def find_entry(fileName)
547
549
  @zipFile.find_entry(expand_to_entry(fileName))
548
550
  end
549
-
551
+
550
552
  def get_entry(fileName)
551
553
  @zipFile.get_entry(expand_to_entry(fileName))
552
554
  end
@@ -554,15 +556,15 @@ module Zip
554
556
  def get_input_stream(fileName, &aProc)
555
557
  @zipFile.get_input_stream(expand_to_entry(fileName), &aProc)
556
558
  end
557
-
558
- def get_output_stream(fileName, &aProc)
559
- @zipFile.get_output_stream(expand_to_entry(fileName), &aProc)
559
+
560
+ def get_output_stream(fileName, permissionInt = nil, &aProc)
561
+ @zipFile.get_output_stream(expand_to_entry(fileName), permissionInt, &aProc)
560
562
  end
561
563
 
562
564
  def read(fileName)
563
565
  @zipFile.read(expand_to_entry(fileName))
564
566
  end
565
-
567
+
566
568
  def remove(fileName)
567
569
  @zipFile.remove(expand_to_entry(fileName))
568
570
  end
@@ -584,9 +586,9 @@ module Zip
584
586
  yield("/"+e.to_s.chomp("/"))
585
587
  }
586
588
  end
587
-
589
+
588
590
  def expand_path(aPath)
589
- expanded = aPath.starts_with("/") ? aPath : @pwd.ensure_end("/") + aPath
591
+ expanded = aPath.start_with?("/") ? aPath : @pwd.ensure_end("/") + aPath
590
592
  expanded.gsub!(/\/\.(\/|$)/, "")
591
593
  expanded.gsub!(/[^\/]+\/\.\.(\/|$)/, "")
592
594
  expanded.empty? ? "/" : expanded