diff --git a/vendor/plugins/rubyzip-0.9.1/ChangeLog b/vendor/plugins/rubyzip-0.9.1/ChangeLog new file mode 100644 index 00000000..1e281443 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/ChangeLog @@ -0,0 +1,1081 @@ +2006-07-01 10:04 thomas + + * Rakefile: Don't autorequire zip/zip - autorequire is deprecated. + +2006-06-30 09:28 thomas + + * Rakefile: [no log message] + + * NEWS, lib/zip/zip.rb: Bumped version number and reformatted NEWS + a bit. + +2006-06-29 22:49 technorama + + * lib/zip/zip.rb, NEWS: documentation additions + +2006-04-30 06:25 technorama + + * TODO, lib/zip/zip.rb, test/ziptest.rb: add documentation and test + for new ZipFile::extract + + * lib/zip/zip.rb: add some of the API suggestions from sf.net + #1281314 + + * lib/zip/zip.rb: apply patch for bug #1446926 + + * lib/zip/zip.rb: apply patch for bug #1459902 + +2006-04-26 17:17 technorama + + * lib/zip/zip.rb: add ZipFile @restore_*, documentation update + +2006-04-07 21:13 technorama + + * test/: gentestfiles.rb, zipfilesystemtest.rb, ziptest.rb: + additional tests + +2006-03-28 04:11 technorama + + * lib/zip/zip.rb: start of unix_uid, unix_gid, restore_* support + + * lib/zip/zip.rb: follow_symlinks is now optional + + * lib/zip/zip.rb: add eof? methods + + * test/ziptest.rb: eof? tests + +2006-02-26 09:57 technorama + + * README: add to authors + + * TODO: [no log message] + +2006-02-25 12:04 thomas + + * lib/zip/zip.rb, test/ziptest.rb: Did away with ZipStreamableFile. + +2006-02-23 08:03 technorama + + * lib/zip/zip.rb: unix file permissions. symlink support. rework + ZipEntry and delegate classes. reduce memory usage during + decompression. + +2006-02-22 23:44 technorama + + * lib/zip/zipfilesystem.rb: update permissionInt for mkdir + +2006-02-04 10:42 thomas + + * lib/zip/: ioextras.rb, zip.rb: Merged patch from oss-ruby. + +2005-11-19 16:17 thomas + + * lib/zip/zip.rb: [no log message] + +2005-11-08 08:23 thomas + + * lib/zip/ioextras.rb: Accepted patch from oss-ruby + +2005-10-07 09:54 thomas + + * TODO: [no log message] + +2005-09-06 21:19 thomas + + * lib/zip/zip.rb: [no log message] + + * NEWS: [no log message] + + * lib/zip/zip.rb, test/gentestfiles.rb, test/ziptest.rb: Fixed + problem on windows - tempfile has to be set to binmode again when + it is reopened + +2005-09-04 16:45 thomas + + * Rakefile: [no log message] + + * TODO: [no log message] + + * test/ziptest.rb: [no log message] + +2005-09-03 10:27 thomas + + * NEWS: [no log message] + + * TODO, lib/zip/zip.rb: [no log message] + + * lib/zip/ioextras.rb, lib/zip/zip.rb, test/ziptest.rb: Merged + patch from oss-ruby at technorama.net + + * test/ziptest.rb: Added failing test that shows that read and gets + don't mix currently + +2005-08-29 08:50 thomas + + * lib/zip/: ioextras.rb, zip.rb: [no log message] + + * NEWS, lib/zip/zip.rb: [no log message] + + * lib/zip/zip.rb: [no log message] + + * lib/zip/zip.rb: [no log message] + +2005-08-07 14:27 thomas + + * lib/zip/zip.rb, NEWS: [no log message] + +2005-08-06 11:12 thomas + + * lib/zip/: ioextras.rb, zip.rb: [no log message] + +2005-08-03 18:54 thomas + + * lib/zip/zip.rb: Read/write in chunks to preserve memory + +2005-07-02 15:08 thomas + + * lib/zip/zip.rb: Applied received patch concerning FreeBSD 4.5 + issue + +2005-04-03 16:52 thomas + + * samples/.cvsignore: [no log message] + + * samples/: qtzip.rb, zipdialogui.ui: Added a qt example + +2005-03-31 21:58 thomas + + * lib/zip/zip.rb, test/ziptest.rb: [no log message] + + * test/zipfilesystemtest.rb: [no log message] + +2005-03-17 18:17 thomas + + * Rakefile: [no log message] + + * NEWS, README, lib/zip/zip.rb: [no log message] + + * install.rb: Fixed install.rb + +2005-03-03 18:38 thomas + + * Rakefile: [no log message] + +2005-02-27 16:23 thomas + + * lib/zip/ziprequire.rb: Added documentation to ziprequire + + * README, TODO, lib/zip/ziprequire.rb: Added documentation to + ziprequire + + * Rakefile, test/ziptest.rb: [no log message] + +2005-02-19 21:30 thomas + + * lib/zip/ioextras.rb, lib/zip/stdrubyext.rb, + lib/zip/tempfile_bugfixed.rb, lib/zip/zip.rb, + lib/zip/ziprequire.rb, test/ioextrastest.rb, + test/stdrubyexttest.rb, test/zipfilesystemtest.rb, + test/ziprequiretest.rb, test/ziptest.rb: Added more rdoc and + changed the remaining tests to Test::Unit + + * lib/zip/: ioextras.rb, zip.rb: Added documentation to + ZipInputStream and ZipOutputStream + +2005-02-18 10:27 thomas + + * README: [no log message] + +2005-02-17 23:21 thomas + + * README, Rakefile: Added ppackage (publish package) task to + Rakefile + + * README, Rakefile, TODO: Added pdoc (publish doc) task to Rakefile + + * README, Rakefile, TODO, lib/zip/stdrubyext.rb, lib/zip/zip.rb, + lib/zip/zipfilesystem.rb: Added a bunch of documentation + + * test/ziptest.rb: [no log message] + +2005-02-16 20:04 thomas + + * NEWS, README, Rakefile: Improved documentation and added rdoc + task to Rakefile + + * NEWS, Rakefile, lib/zip/zip.rb: [no log message] + + * Rakefile, samples/example.rb, samples/example_filesystem.rb, + samples/gtkRubyzip.rb, samples/write_simple.rb, + samples/zipfind.rb, test/.cvsignore, test/gentestfiles.rb: + Improvements to Rakefile + +2005-02-15 23:35 thomas + + * NEWS, TODO: [no log message] + + * Rakefile, rubyzip.gemspec: Now uses Rake to build gem + + * Rakefile: [no log message] + + * lib/zip/zip.rb, test/.cvsignore, test/ziptest.rb, NEWS: Fixed + compatibility issue with ruby 1.8.2. Migrated test suite to + Test::Unit + + * NEWS, lib/zip/ioextras.rb, lib/zip/stdrubyext.rb, + lib/zip/tempfile_bugfixed.rb, lib/zip/zip.rb, + lib/zip/zipfilesystem.rb, lib/zip/ziprequire.rb, test/.cvsignore, + test/file1.txt, test/file1.txt.deflatedData, test/file2.txt, + test/gentestfiles.rb, test/ioextrastest.rb, + test/notzippedruby.rb, test/rubycode.zip, test/rubycode2.zip, + test/stdrubyexttest.rb, test/testDirectory.bin, + test/zipWithDirs.zip, test/zipfilesystemtest.rb, + test/ziprequiretest.rb, test/ziptest.rb, test/data/.cvsignore, + test/data/file1.txt, test/data/file1.txt.deflatedData, + test/data/file2.txt, test/data/notzippedruby.rb, + test/data/rubycode.zip, test/data/rubycode2.zip, + test/data/testDirectory.bin, test/data/zipWithDirs.zip: Changed + directory structure + +2005-02-13 22:44 thomas + + * Rakefile, TODO: [no log message] + + * rubyzip.gemspec: [no log message] + + * install.rb: Made install.rb independent of the current path + (fixes bug reported by Drew Robinson) + +2004-12-12 11:22 thomas + + * NEWS, TODO, samples/write_simple.rb: Fixed 'version needed to + extract'-field wrong in local headers + +2004-05-02 15:17 thomas + + * rubyzip.gemspec: Added gemspec contributed by Chad Fowler + +2004-04-02 07:25 thomas + + * NEWS: Fix for FreeBSD 4.9 + +2004-03-29 00:28 thomas + + * NEWS: [no log message] + +2004-03-28 17:59 thomas + + * NEWS: [no log message] + +2004-03-27 16:09 thomas + + * test/stdrubyexttest.rb: Patch for stdrubyext.rb from Nobu Nakada + + * test/: ioextrastest.rb, stdrubyexttest.rb: converted some files + to unix line-endings + +2004-03-25 16:34 thomas + + * NEWS, install.rb: Significantly reduced memory footprint when + modifying zip files + +2004-03-16 18:20 thomas + + * install.rb, test/alltests.rb, test/ioextrastest.rb, + test/stdrubyexttest.rb, test/ziptest.rb: IO utility classes moved + to new file ioextras.rb. Tests moved to new file ioextrastest.rb + +2004-02-27 13:21 thomas + + * NEWS: Optimization to avoid decompression and recompression + +2004-01-30 16:17 thomas + + * NEWS: [no log message] + + * README, test/zipfilesystemtest.rb, test/ziptest.rb: Applied + extra-field patch + +2003-12-13 16:57 thomas + + * TODO: [no log message] + +2003-12-10 00:25 thomas + + * test/ziptest.rb: (Temporary) fix to bug reported by Takashi Sano + +2003-08-23 09:42 thomas + + * test/ziptest.rb, NEWS: Fixed ZipFile.get_ouput_stream bug - data + was never written to zip + +2003-08-21 16:05 thomas + + * install.rb: [no log message] + + * alltests.rb, stdrubyexttest.rb, zipfilesystemtest.rb, + ziprequiretest.rb, ziptest.rb, test/alltests.rb, + test/stdrubyexttest.rb, test/zipfilesystemtest.rb, + test/ziprequiretest.rb, test/ziptest.rb: Moved all test ruby + files to test/ + + * NEWS, install.rb, stdrubyext.rb, stdrubyexttest.rb, zip.rb, + zipfilesystem.rb, zipfilesystemtest.rb, ziprequire.rb, + ziprequiretest.rb, ziptest.rb, samples/example.rb, + samples/example_filesystem.rb, samples/gtkRubyzip.rb, + samples/zipfind.rb: Moved all production source files to zip/ so + they are in the same dir as when they are installed + + * NEWS, TODO, alltests.rb: [no log message] + + * filearchive.rb, filearchivetest.rb, fileutils.rb: Removed + filearchive.rb, filearchivetest.rb and fileutils.rb + + * samples/.cvsignore, samples/example_filesystem.rb, zip.rb, + samples/example_filesystem.rb: Added + samples/example_filesystem.rb. Fixed Tempfile creation for + entries created with get_output_stream where entries were in a + subdirectory + + * zip.rb, ziptest.rb: Fixed mkdir bug. ZipFile.mkdir didn't work if + the zipfile doesn't exist already + + * ziptest.rb: [no log message] + + * TODO, zipfilesystemtest.rb: Globbing test placeholder commented + out + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented ZipFsDir.new + and open + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented DirFsIterator + and tests + +2003-08-20 22:50 thomas + + * NEWS, TODO: [no log message] + + * zipfilesystemtest.rb: [no log message] + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsDir.foreach, ZipFsDir.entries now reimplemented in terms of + it + + * README: [no log message] + + * zipfilesystem.rb, zipfilesystemtest.rb: [no log message] + + * zipfilesystem.rb: All access from ZipFsFile and ZipFsDir to + ZipFile is now routed through ZipFileNameMapper which has the + single responsibility of mapping entry/filenames + + * alltests.rb, stdrubyext.rb, stdrubyexttest.rb: Added + stdrubyexttest.rb and added test test_select_map + + * zipfilesystem.rb: ZipFsDir was in the wrong module. ZipFileSystem + now has a ctor that creates ZipFsDir and ZipFsFile instances, + instead of creating them lazily. It then passes the dir instance + to the file instance and vice versa + + * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: ZipFsFile.open + honours chdir + + * stdrubyext.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb, + ziptest.rb: Fixed ZipEntry::parent_as_string. Implemented + ZipFsDir.chdir, pwd and entries including test + +2003-08-19 15:44 thomas + + * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsDir.mkdir + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsDir.delete (and aliases rmdir and unlink) + + * zipfilesystem.rb, zipfilesystemtest.rb: Another dummy + implementation and commented out a test for select() which can be + added later + +2003-08-18 20:40 thomas + + * ziptest.rb: Honoured 1.8.0 Object.to_a deprecation warning + + * zip.rb, ziptest.rb, samples/example.rb, samples/zipfind.rb: + Converted a few more names to ruby underscore style that I missed + with the automated processing the first time around + + * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb, ziptest.rb: + Implemented Zip::ZipFile.get_output_stream + +2003-08-17 18:28 thomas + + * README, install.rb, stdrubyext.rb, zipfilesystem.rb, + zipfilesystemtest.rb: Updated README with Documentation section. + Updated install.rb. Fixed three tests that failed on 1.8.0. + +2003-08-14 05:40 thomas + + * zipfilesystem.rb, zipfilesystemtest.rb: Added empty + implementations of atime and ctime + +2003-08-13 17:08 thomas + + * simpledist.rb: Moved simpledist to a separate repository called + 'misc' + + * NEWS: [no log message] + + * stdrubyext.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb, + ziprequire.rb, ziprequiretest.rb, ziptest.rb, samples/example.rb, + samples/gtkRubyzip.rb, samples/zipfind.rb: Changed all method + names to the ruby convention underscore style + + * alltests.rb, zipfilesystem.rb, zipfilesystemtest.rb: Implemented + a lot more of the stat methods. Mostly with dummy implementations + that return values that indicate that these features aren't + supported + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented more methods + and tests in zipfilesystem. Mostly empty methods as permissions + and file types other than files and directories are not supported + + * install.rb, stdrubyext.rb, zip.rb, zipfilesystem.rb, + zipfilesystemtest.rb: Addd file stdrubyext.rb and moved the + modifications to std ruby classes to it. Refactored the ZipFsStat + tests and ZipFsStat. Added Module.forwardMessages and used it to + implement the forwarding of calls in ZipFsStat + + * zipfilesystem.rb, zipfilesystemtest.rb: Added + Zip::ZipFsFile::ZipFsStat and started implementing it and its + methods + + * zipfilesystem.rb, zipfilesystemtest.rb, ziptest.rb: Updated and + added missing copyright notices + + * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: zipfilesystem.rb + is becoming big and not everyone will want to use that code. + Therefore zip.rb no longer requires it. Instead you must require + zipfilesystem.rb itself if you want to use it + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented dummy + permission test methods + + * TODO, zip.rb, ziptest.rb: Merged from patch from Kristoffer + Lunden. Fixed more 1.8.0 incompatibilites - tests run on 1.8.0 + now + +2003-08-12 19:18 thomas + + * zip.rb: Get rid of 1.8.0 warning + + * ziptest.rb: ruby 1.8.0 compatibility fix + + * NEWS, zip.rb: ruby-zlib 0.6.0 compatibility fix + +2002-12-22 20:12 thomas + + * zip.rb: [no log message] + +2002-09-16 22:11 thomas + + * NEWS: [no log message] + +2002-09-15 17:16 thomas + + * samples/zipfind.rb: [no log message] + + * samples/zipfind.rb: [no log message] + +2002-09-14 22:59 thomas + + * samples/zipfind.rb: Added simple zipfind script + +2002-09-13 23:53 thomas + + * TODO: Added TODO about openmode for zip entries binary/ascii + + * NEWS: ziptest now runs without errors with ruby-1.7.2-4 (Andy's + latest build) + + * zip.rb, ziprequiretest.rb, ziptest.rb: ziptest now runs without + errors with ruby-1.7.2-4 (Andy's latest build) + +2002-09-12 00:20 thomas + + * zipfilesystemtest.rb: Improved ZipFsFile.delete/unlink test + + * test/.cvsignore: [no log message] + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.delete/unlink + +2002-09-11 22:22 thomas + + * alltests.rb: [no log message] + + * NEWS, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: Fixed + AbstractInputStream.each_line ignored its aSeparator argument. + Implemented more ZipFsFile methods + + * zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: ZipFileSystem is + now a module instead of a class, and is mixed into ZipFile, + instead of being made available as a property fileSystem + +2002-09-10 23:45 thomas + + * NEWS: Updated NEWS file + + * zip.rb: [no log message] + + * NEWS, zip.rb, ziptest.rb: Fix bug: rewind should reset lineno. + Fix bug: Deflater.read uses separate buffer from produceInput + (feeding gets/readline etc) + +2002-09-09 23:48 thomas + + * .cvsignore: [no log message] + +2002-09-09 22:55 uid26649 + + * zip.rb, ziptest.rb: Implemented ZipInputStream.rewind and + AbstractInputStream.lineno. Tests for both + +2002-09-09 20:31 thomas + + * zip.rb, ziptest.rb: ZipInputStream and ZipOutstream (thru their + AbstractInputStream and AbstractOutputStream now lie about being + kind_of?(IO) + +2002-09-08 16:38 thomas + + * zipfilesystemtest.rb: [no log message] + + * filearchive.rb, filearchivetest.rb, zip.rb, ziptest.rb: Moved + String additions from filearchive.rb to zip.rb (and moved tests + along too to ziptest.rb). Added ZipEntry.parentAsString and + ZipEntrySet.parent + + * ziptest.rb: Implemented ZipEntrySetTest.testDup and testCompound + + * TODO, zip.rb, ziptest.rb: Replaced Array with EntrySet for + keeping entries in a zip file. Tagged repository before this + commit, so this change can be rolled back, if it stinks + +2002-09-07 20:21 thomas + + * zip.rb, ziptest.rb: Implemented ZipEntry.<=> + + * ziptest.rb: Removed unused code + +2002-08-11 15:14 thomas + + * zip.rb, ziptest.rb: Made some changes to accomodate ruby 1.7.2 + +2002-07-27 15:25 thomas + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented ZipFsFile.new + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.pipe + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.link + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.symlink + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.readlink, wrapped ZipFileSystem class in Zip module + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.zero? + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented test for + ZipFsFile.directory? + +2002-07-26 23:56 thomas + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.socket? + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.join + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.ftype + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.blockdev? + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.size? (slightly different from size) + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.split + + * zipfilesystem.rb, zipfilesystemtest.rb: Implemented + ZipFsFile.symlink? + + * alltests.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: + Implemented ZipFsFile.mtime + + * zipfilesystem.rb, zipfilesystemtest.rb: Implement ZipFsFile.file? + + * zip.rb, ziptest.rb: Implemented ZipEntry.file? + + * alltests.rb, filearchive.rb, filearchivetest.rb, zip.rb, + zipfilesystem.rb, zipfilesystemtest.rb, ziprequire.rb, + ziptest.rb: Implemented ZipFileSystem::ZipFsFile.size + + * zipfilesystem.rb, zipfilesystemtest.rb: [no log message] + + * test/zipWithDirs.zip: Changed zipWithDirs.zip so all the entries + in it have unix file endings + + * alltests.rb, zip.rb, zipfilesystem.rb, zipfilesystemtest.rb: + Started implementing ZipFileSystem + + * test/zipWithDirs.zip: Added a zip file for testing with a + directory structure + +2002-07-22 21:40 thomas + + * TODO: [no log message] + + * TODO: [no log message] + +2002-07-21 18:20 thomas + + * NEWS: [no log message] + + * TODO: Updated TODO with a refactoring idea for FileArchive + + * filearchive.rb, filearchivetest.rb: Added some FileArchiveAdd + tests and cleaned up some of the FileArchive tests. extract and + add now have individual test fixtures. + + * filearchive.rb, filearchivetest.rb: Added tests for extract + called with regex src arg and Enumerable src arg + + * filearchivetest.rb: Added test for continueOnExistsProc when + extracting from a file archive + +2002-07-20 17:13 thomas + + * TODO, filearchivetest.rb, fileutils.rb, ziptest.rb, + test/.cvsignore: Added (failing) tests for FileArchive.add, added + code for creating test files for FileArchive.add tests. Added + fileutils.rb, which is borrowed from ruby 1.7.2 + + * filearchive.rb, filearchivetest.rb: [no log message] + + * filearchivetest.rb: Added tests for String extensions + + * alltests.rb, ziprequiretest.rb, ziptest.rb: [no log message] + + * install.rb: [no log message] + + * TODO: Updated TODO + + * filearchive.rb, filearchivetest.rb: All FileArchive.extract tests + run + +2002-07-19 23:11 thomas + + * filearchive.rb, filearchivetest.rb: [no log message] + + * filearchivetest.rb: [no log message] + + * filearchive.rb, filearchivetest.rb: [no log message] + + * filearchive.rb, filearchivetest.rb, zip.rb: [no log message] + +2002-07-08 13:41 thomas + + * TODO: [no log message] + +2002-06-11 19:47 thomas + + * filearchive.rb, filearchivetest.rb, zip.rb, ziptest.rb: [no log + message] + +2002-05-25 00:41 thomas + + * simpledist.rb: Added hackish script for creating dist files + +2002-04-30 21:22 thomas + + * TODO: [no log message] + + * filearchive.rb, filearchivetest.rb: [no log message] + + * filearchive.rb, filearchivetest.rb: Improved testing and wrote + some of the skeleton of extract. Still to do: Fix glob, so it + returns a hashmap instead of a list. The map will need to map the + full entry name to the last part of the name (which is only + really interesting for recursively extracted entries, otherwise + it is just the name). Glob.expandPathList should also output + directories with a trailing slash, which is doesn't right now. + + * filearchive.rb, filearchivetest.rb: Implemented the first few + tests for FileArchive + +2002-04-24 22:06 thomas + + * ziprequire.rb, ziprequiretest.rb: Appended copyright message to + ziprequire.rb and ziprequiretest.rb + + * zip.rb: Made ZipEntry tolerate invalid dates + +2002-04-21 00:57 thomas + + * NEWS, TODO, zip.rb, ziptest.rb: Read and write entry modification + date/time correctly + +2002-04-20 02:44 thomas + + * ziprequiretest.rb, test/rubycode2.zip: improved ZipRequireTest + + * ziprequire.rb: Made a warning go away + + * ziprequire.rb, ziprequiretest.rb, test/notzippedruby.rb, + test/rubycode.zip: Fixed a bug in ziprequire. Added + ziprequiretest.rb and test data files + +2002-04-19 22:43 thomas + + * zip.rb, ziptest.rb: Added recursion support to Glob module + +2002-04-18 21:37 thomas + + * NEWS, TODO, zip.rb, ziptest.rb: Added Glob module and GlobTest + unit test suite. This module provides the functionality to expand + a 'glob pattern' given a list of files - Next step is to use this + module in ZipFile + +2002-04-01 22:55 thomas + + * NEWS: [no log message] + + * TODO, zip.rb, ziprequire.rb: Added ziprequire.rb which contains a + proof-of-concept implementation of a require implementation that + can load ruby modules from a zip file. Needs unit tests and + polish. + +2002-03-31 01:13 thomas + + * README: [no log message] + +2002-03-30 16:14 thomas + + * TODO: [no log message] + + * .cvsignore, README, zip.rb: Added rdoc markup (only #:nodoc:all + modifiers) to zip.rb. Made README 'RDoc compliant' + +2002-03-29 23:29 thomas + + * TODO: [no log message] + + * example.rb, samples/.cvsignore, samples/example.rb, + samples/gtkRubyzip.rb: Moved example.rb to samples/. Added + another sample gtkRubyzip.rb + + * NEWS, TODO, TODO: [no log message] + + * .cvsignore, file1.txt, file1.txt.deflatedData, testDirectory.bin, + ziptest.rb, test/.cvsignore, test/file1.txt, + test/file1.txt.deflatedData, test/file2.txt, + test/testDirectory.bin: Added test/ directory and moved the + manually created test data files into it. Changed ziptest.rb so + it runs in test/ directory + + * TODO: [no log message] + + * NEWS, zip.rb, ziptest.rb: Don't decompress and recompress zip + entries when changing zip file + + * zip.rb: Performance optimization: Only write new ZipFile, if it + has been changed. The test suite runs in half the time now. + +2002-03-28 22:12 thomas + + * TODO: [no log message] + +2002-03-23 17:31 thomas + + * TODO: [no log message] + +2002-03-22 22:47 thomas + + * NEWS: [no log message] + + * NEWS, TODO: [no log message] + + * ziptest.rb: Found the tests that didn't use blocks to make sure + input streams are closed as soon as they arent used anymore and + got rid of the GC.start + + * ziptest.rb: All tests run on windows ruby 1.6.6 + + * zip.rb, ziptest.rb: Windows fixes: Fixed ZipFile.initialize which + needed to open zipfile file in binary mode. Added another + workaround for the return value from File.open(name) where name + is the name of a directory - ruby returns different exceptions in + linux, win/cygwin and windows. A number of tests failed because + in windows you cant delete a file that is open. Fixed by changing + ziptest.rb to use ZipInputStream.getInputStream with blocks a few + places. There is a hack in CommanZipFileFixture.setup where the + GC is explicitly invoked. Should be fixed with blocks instead. + The only currently failing test fails because the test data + creation fails to add a comment to 4entry.zip, because echo eats + the remainder of the line including the pipe character and the + following zip -z 4 entry.zip command + +2002-03-21 22:18 thomas + + * NEWS: [no log message] + + * NEWS, README, TODO, install.rb: Added install.rb + + * ziptest.rb: [no log message] + + * NEWS, TODO: [no log message] + + * .cvsignore, TODO, zip.rb, ziptest.rb: Added + test_extractDirectoryExistsAsFileOverwrite and fixed to pass + + * zip.rb, ziptest.rb: Extraction of directory entries is now + supported + +2002-03-20 21:59 thomas + + * NEWS: [no log message] + + * COPYING, README, README.txt: Removed COPYING, renamed README.txt + to README. Updated README + + * example.rb: Fixed example.rb added example that shows zip file + manipulation with Zip::ZipFile + + * .cvsignore: [no log message] + + * TODO, zip.rb, ziptest.rb: Directories can now be added (not + recursively, the directory entry itself. Directories are + recognized by a empty entries with a trailing /. The purpose of + storing them explicitly in the zip file is to be able to store + permission and ownership information + + * TODO, zip.rb, ziptest.rb: zip.rb depended on ftools but it was + only included in ziptest.rb + + * zip.rb, ziptest.rb: ZipError is now a subclass of StandardError + instead of RuntimeError. ZipError now has several subclasses. + +2002-03-19 22:26 thomas + + * TODO: [no log message] + + * TODO, ziptest.rb: Unit test ZipFile.getInputStream with block + + * TODO, zip.rb, ziptest.rb: Unit test for adding new entry with + name that already exists in archive, and fixed to pass test + + * TODO, zip.rb, ziptest.rb: Added unit tests for rename to existing + entry + + * TODO: [no log message] + + * TODO, zip.rb, ziptest.rb: Unit test calling ZipFile.extract with + block + +2002-03-18 21:06 thomas + + * TODO: [no log message] + + * zip.rb, ziptest.rb: ZipFile#commit now reinitializes ZipFile. + + * TODO, zip.rb, ziptest.rb: Refactoring: + + Collapsed ZipEntry and ZipStreamableZipEntry into ZipEntry. + + Collapsed BasicZipFile and ZipFile into ZipFile. + + * zip.rb: Removed method that was never called + +2002-03-17 22:33 thomas + + * TODO: [no log message] + + * ziptest.rb: Run tests with =true as default + + * NEWS, TODO, zip.rb, ziptest.rb: Now runs with -w switch without + warnings + + * .cvsignore: [no log message] + + * zip.rb, ziptest.rb: Down to one failing test + + * zip.rb, ziptest.rb: [no log message] + + * TODO, zip.rb, ziptest.rb: [no log message] + +2002-02-25 19:42 thomas + + * TODO: Added more todos + +2002-02-23 15:51 thomas + + * zip.rb: [no log message] + + * zip.rb, ziptest.rb: [no log message] + + * zip.rb, ziptest.rb: [no log message] + +2002-02-03 18:47 thomas + + * ziptest.rb: [no log message] + +2002-02-02 15:58 thomas + + * example.rb, zip.rb, ziptest.rb: [no log message] + + * .cvsignore: [no log message] + + * example.rb, zip.rb, ziptest.rb: Renamed SimpleZipFile to + BasicZipFile + + * TODO: [no log message] + + * ziptest.rb: More test cases - all of them failing, so now there + are 18 failing test cases. Three more test cases to implement, + then it is time for the production code + +2002-02-01 21:49 thomas + + * ziptest.rb: [no log message] + + * ziptest.rb: Also run SimpleZipFile tests for ZipFile. + + * example.rb, zip.rb, ziptest.rb: ZipFile renamed to SimpleZipFile. + The new ZipFile will have many more methods that are useful for + managing archives. + +2002-01-29 20:30 thomas + + * TODO: [no log message] + +2002-01-26 00:18 thomas + + * NEWS: [no log message] + + * ziptest.rb: In unit test: work around ruby/cygwin weirdness. You + get an Errno::EEXISTS instead of an Errno::EISDIR if you try to + open a file for writing that is a directory. + + * ziptest.rb: Fixed test that failed on windows because of CRLF + line ending + +2002-01-25 23:58 thomas + + * ziptest.rb: [no log message] + + * .cvsignore, example.rb, zip.rb: Fixed bug reading from empty + deflated entry in zip file + + * .cvsignore: [no log message] + + * ziptest.rb: [no log message] + + * NEWS, README.txt, zip.rb, ziptest.rb: Zip write support is now + fully functional in the form of ZipOutputStream. + + * zip.rb, ziptest.rb: [no log message] + + * zip.rb, ziptest.rb: [no log message] + +2002-01-20 16:00 thomas + + * zip.rb, ziptest.rb: Added Deflater and DeflaterTest. + + * .cvsignore: [no log message] + + * .cvsignore: Added .cvsignore file + + * zip.rb, ziptest.rb: Added ZipEntry.writeCDirEntry and misc minor + fixes + +2002-01-19 23:28 thomas + + * example.rb, zip.rb, ziptest.rb: NOTICE: Not all tests run!! + + ZipOutputStream in progress + + Wrapped rubyzip in namespace module Zip. + +2002-01-17 18:52 thomas + + * ziptest.rb: Fail nicely if the user doesn't have info-zip + compatible zip in the path + +2002-01-10 18:02 thomas + + * zip.rb: Adjusted chunk size to 32k after a few perf measurements + +2002-01-09 22:10 thomas + + * README.txt: License now same as rubys, not just GPL + +2002-01-06 00:19 thomas + + * README.txt: [no log message] + +2002-01-05 23:09 thomas + + * NEWS, README.txt, NEWS: Updated NEWS file + + * README.txt, zip.rb, ziptest.rb, zlib.c.diff: Added tests for + decompressors and a tests for ZipLocalEntry, + ZipCentralDirectoryEntry and ZipCentralDirectory for handling of + corrupt data + + * file1.txt.deflatedData: deflated data extracted from a zip file. + contains file1.txt + + * zip.rb: Changed references to Inflate to Zlib::inflate for + compatibility with ruby-zlib-0.5 + + * README.txt, zip.rb, ziptest.rb: [no log message] + + * example.rb, NEWS: [no log message] + + * COPYING, README.txt: [no log message] + + * ziptest.rb: Fixed problem with test file creation + + * README.txt: Updated README.txt + + * zip.rb, ziptest.rb: ZipFile now works + +2002-01-04 21:51 thomas + + * testDirectory.bin, zip.rb, ziptest.rb: + ZipCentralDirectoryEntryTest now runs + + * ziptest.rb: Changed + ZIpLocalNEtryTest::test_ReadLocalEntryHeaderOfFirstTestZipEntry + so it works on both unix too. It only worked on windows because + the test made assumptions about the compressed size and crc of an + entry, but that differs depending on the OS because of the CRLF + thing. + + * README.txt: Added note about zlib.c patch + +2002-01-02 18:48 thomas + + * README.txt, example.rb, file1.txt, zip.rb, ziptest.rb, + zlib.c.diff: initial + + * README.txt, example.rb, file1.txt, zip.rb, ziptest.rb, + zlib.c.diff: Initial revision + diff --git a/vendor/plugins/rubyzip-0.9.1/NEWS b/vendor/plugins/rubyzip-0.9.1/NEWS new file mode 100644 index 00000000..0f46f727 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/NEWS @@ -0,0 +1,144 @@ += Version 0.9.1 + +Added symlink support and support for unix file permissions. Reduced +memory usage during decompression. + +New methods ZipFile::[follow_symlinks, restore_times, restore_permissions, restore_ownership]. +New methods ZipEntry::unix_perms, ZipInputStream::eof?. +Added documentation and test for new ZipFile::extract. +Added some of the API suggestions from sf.net #1281314. +Applied patch for sf.net bug #1446926. +Applied patch for sf.net bug #1459902. +Rework ZipEntry and delegate classes. + += Version 0.5.12 + +Fixed problem with writing binary content to a ZipFile in MS Windows. + += Version 0.5.11 + +Fixed name clash file method copy_stream from fileutils.rb. Fixed +problem with references to constant CHUNK_SIZE. +ZipInputStream/AbstractInputStream read is now buffered like ruby IO's +read method, which means that read and gets etc can be mixed. The +unbuffered read method has been renamed to sysread. + += Version 0.5.10 + +Fixed method name resolution problem with FileUtils::copy_stream and +IOExtras::copy_stream. + += Version 0.5.9 + +Fixed serious memory consumption issue + += Version 0.5.8 + +Fixed install script. + += Version 0.5.7 + +install.rb no longer assumes it is being run from the toplevel source +dir. Directory structure changed to reflect common ruby library +project structure. Migrated from RubyUnit to Test::Unit format. Now +uses Rake to build source packages and gems and run unit tests. + += Version 0.5.6 + +Fix for FreeBSD 4.9 which returns Errno::EFBIG instead of +Errno::EINVAL for some invalid seeks. Fixed 'version needed to +extract'-field incorrect in local headers. + += Version 0.5.5 + +Fix for a problem with writing zip files that concerns only ruby 1.8.1. + += Version 0.5.4 + +Significantly reduced memory footprint when modifying zip files. + += Version 0.5.3 + +Added optimization to avoid decompressing and recompressing individual +entries when modifying a zip archive. + += Version 0.5.2 + +Fixed ZipFile corruption bug in ZipFile class. Added basic unix +extra-field support. + += Version 0.5.1 + +Fixed ZipFile.get_output_stream bug. + += Version 0.5.0 + +List of changes: +* Ruby 1.8.0 and ruby-zlib 0.6.0 compatibility +* Changed method names from camelCase to rubys underscore style. +* Installs to zip/ subdir instead of directly to site_ruby +* Added ZipFile.directory and ZipFile.file - each method return an +object that can be used like Dir and File only for the contents of the +zip file. +* Added sample application zipfind which works like Find.find, only +Zip::ZipFind.find traverses into zip archives too. + +Bug fixes: +* AbstractInputStream.each_line with non-default separator + + += Version 0.5.0a + +Source reorganized. Added ziprequire, which can be used to load ruby +modules from a zip file, in a fashion similar to jar files in +Java. Added gtkRubyzip, another sample application. Implemented +ZipInputStream.lineno and ZipInputStream.rewind + +Bug fixes: + +* Read and write date and time information correctly for zip entries. +* Fixed read() using separate buffer, causing mix of gets/readline/read to +cause problems. + += Version 0.4.2 + +Performance optimizations. Test suite runs in half the time. + += Version 0.4.1 + +Windows compatibility fixes. + += Version 0.4.0 + +Zip::ZipFile is now mutable and provides a more convenient way of +modifying zip archives than Zip::ZipOutputStream. Operations for +adding, extracting, renaming, replacing and removing entries to zip +archives are now available. + +Runs without warnings with -w switch. + +Install script install.rb added. + + += Version 0.3.1 + +Rudimentary support for writing zip archives. + + += Version 0.2.2 + +Fixed and extended unit test suite. Updated to work with ruby/zlib +0.5. It doesn't work with earlier versions of ruby/zlib. + + += Version 0.2.0 + +Class ZipFile added. Where ZipInputStream is used to read the +individual entries in a zip file, ZipFile reads the central directory +in the zip archive, so you can get to any entry in the zip archive +without having to skipping through all the preceeding entries. + + += Version 0.1.0 + +First working version of ZipInputStream. diff --git a/vendor/plugins/rubyzip-0.9.1/README b/vendor/plugins/rubyzip-0.9.1/README new file mode 100644 index 00000000..81ec4c5d --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/README @@ -0,0 +1,72 @@ += rubyzip + +rubyzip is a ruby library for reading and writing zip files. + += Install + +If you have rubygems you can install rubyzip directly from the gem +repository + + gem install rubyzip + +Otherwise obtain the source (see below) and run + + ruby install.rb + +To run the unit tests you need to have test::unit installed + + rake test + + += Documentation + +There is more than one way to access or create a zip archive with +rubyzip. The basic API is modeled after the classes in +java.util.zip from the Java SDK. This means there are classes such +as Zip::ZipInputStream, Zip::ZipOutputStream and +Zip::ZipFile. Zip::ZipInputStream provides a basic interface for +iterating through the entries in a zip archive and reading from the +entries in the same way as from a regular File or IO +object. ZipOutputStream is the corresponding basic output +facility. Zip::ZipFile provides a mean for accessing the archives +central directory and provides means for accessing any entry without +having to iterate through the archive. Unlike Java's +java.util.zip.ZipFile rubyzip's Zip::ZipFile is mutable, which means +it can be used to change zip files as well. + +Another way to access a zip archive with rubyzip is to use rubyzip's +Zip::ZipFileSystem API. Using this API files can be read from and +written to the archive in much the same manner as ruby's builtin +classes allows files to be read from and written to the file system. + +rubyzip also features the +zip/ziprequire.rb[link:files/lib/zip/ziprequire_rb.html] module which +allows ruby to load ruby modules from zip archives. + +For details about the specific behaviour of classes and methods refer +to the test suite. Finally you can generate the rdoc documentation or +visit http://rubyzip.sourceforge.net. + += License + +rubyzip is distributed under the same license as ruby. See +http://www.ruby-lang.org/en/LICENSE.txt + + += Website and Project Home + +http://rubyzip.sourceforge.net + +http://sourceforge.net/projects/rubyzip + +== Download (tarballs and gems) + +http://sourceforge.net/project/showfiles.php?group_id=43107&package_id=35377 + += Authors + +Thomas Sondergaard (thomas at sondergaard.cc) + +Technorama Ltd. (oss-ruby-zip at technorama.net) + +extra-field support contributed by Tatsuki Sugiura (sugi at nemui.org) diff --git a/vendor/plugins/rubyzip-0.9.1/Rakefile b/vendor/plugins/rubyzip-0.9.1/Rakefile new file mode 100755 index 00000000..c6581cf6 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/Rakefile @@ -0,0 +1,110 @@ +# Rakefile for RubyGems -*- ruby -*- + +require 'rubygems' +require 'rake/clean' +require 'rake/testtask' +require 'rake/packagetask' +require 'rake/gempackagetask' +require 'rake/rdoctask' +require 'rake/contrib/sshpublisher' +require 'net/ftp' + +PKG_NAME = 'rubyzip' +PKG_VERSION = File.read('lib/zip/zip.rb').match(/\s+VERSION\s*=\s*'(.*)'/)[1] + +PKG_FILES = FileList.new + +PKG_FILES.add %w{ README NEWS TODO ChangeLog install.rb Rakefile } +PKG_FILES.add %w{ samples/*.rb } +PKG_FILES.add %w{ test/*.rb } +PKG_FILES.add %w{ test/data/* } +PKG_FILES.exclude "test/data/generated" +PKG_FILES.add %w{ lib/**/*.rb } + +def clobberFromCvsIgnore(path) + CLOBBER.add File.readlines(path+'/.cvsignore').map { + |f| File.join(path, f.chomp) + } rescue StandardError +end + +clobberFromCvsIgnore '.' +clobberFromCvsIgnore 'samples' +clobberFromCvsIgnore 'test' +clobberFromCvsIgnore 'test/data' + +task :default => [:test] + +desc "Run unit tests" +task :test do + ruby %{-C test alltests.rb} +end + +# Shortcuts for test targets +task :ut => [:test] + +spec = Gem::Specification.new do |s| + s.name = PKG_NAME + s.version = PKG_VERSION + s.author = "Thomas Sondergaard" + s.email = "thomas(at)sondergaard.cc" + s.homepage = "http://rubyzip.sourceforge.net/" + s.platform = Gem::Platform::RUBY + s.summary = "rubyzip is a ruby module for reading and writing zip files" + s.files = PKG_FILES.to_a + s.require_path = 'lib' +end + +Rake::GemPackageTask.new(spec) do |pkg| + pkg.need_zip = true + pkg.need_tar = true +end + +Rake::RDocTask.new do |rd| + rd.main = "README" + rd.rdoc_files.add %W{ lib/zip/*.rb README NEWS TODO ChangeLog } + rd.options << "--title 'rubyzip documentation' --webcvs http://cvs.sourceforge.net/viewcvs.py/rubyzip/rubyzip/" +# rd.options << "--all" +end + +desc "Publish documentation" +task :pdoc => [:rdoc] do + Rake::SshFreshDirPublisher. + new("thomas@rubyzip.sourceforge.net", "/home/groups/r/ru/rubyzip/htdocs", "html").upload +end + +desc "Publish package" +task :ppackage => [:package] do + Net::FTP.open("upload.sourceforge.net", + "ftp", + ENV['USER']+"@"+ENV['HOSTNAME']) { + |ftpclient| + ftpclient.passive = true + ftpclient.chdir "incoming" + Dir['pkg/*.{tgz,zip,gem}'].each { + |e| + ftpclient.putbinaryfile(e, File.basename(e)) + } + } +end + +desc "Generate the ChangeLog file" +task :ChangeLog do + puts "Updating ChangeLog" + system %{cvs2cl} +end + +desc "Make a release" +task :release => [:tag_release, :pdoc, :ppackage] do +end + +desc "Make a release tag" +task :tag_release do + tag = "release-#{PKG_VERSION.gsub('.','-')}" + + puts "Checking for tag '#{tag}'" + if (Regexp.new("^\\s+#{tag}") =~ `cvs log README`) + abort "Tag '#{tag}' already exists" + end + puts "Tagging module with '#{tag}'" + system("cvs tag #{tag}") +end diff --git a/vendor/plugins/rubyzip-0.9.1/TODO b/vendor/plugins/rubyzip-0.9.1/TODO new file mode 100644 index 00000000..e24cde57 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/TODO @@ -0,0 +1,16 @@ + +* ZipInputStream: Support zip-files with trailing data descriptors +* Adjust rdoc stylesheet to advertise inherited methods if possible +* Suggestion: Add ZipFile/ZipInputStream example that demonstrates extracting all entries. +* Suggestion: ZipFile#extract destination should default to "." +* Suggestion: ZipEntry should have extract(), get_input_stream() methods etc +* SUggestion: ZipInputStream/ZipOutputStream should accept an IO object in addition to a filename. +* (is buffering used anywhere with write?) +* Inflater.sysread should pass the buffer to produce_input. +* Implement ZipFsDir.glob +* ZipFile.checkIntegrity method +* non-MSDOS permission attributes +** See mail from Ned Konz to ruby-talk subj. "Re: SV: [ANN] Archive 0.2" +* Packager version, required unpacker version in zip headers +** See mail from Ned Konz to ruby-talk subj. "Re: SV: [ANN] Archive 0.2" +* implement storing attributes and ownership information diff --git a/vendor/plugins/rubyzip-0.9.1/install.rb b/vendor/plugins/rubyzip-0.9.1/install.rb new file mode 100755 index 00000000..405e2b0b --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/install.rb @@ -0,0 +1,22 @@ +#!/usr/bin/env ruby + +$VERBOSE = true + +require 'rbconfig' +require 'find' +require 'ftools' + +include Config + +files = %w{ stdrubyext.rb ioextras.rb zip.rb zipfilesystem.rb ziprequire.rb tempfile_bugfixed.rb } + +INSTALL_DIR = File.join(CONFIG["sitelibdir"], "zip") +File.makedirs(INSTALL_DIR) + +SOURCE_DIR = File.join(File.dirname($0), "lib/zip") + +files.each { + |filename| + installPath = File.join(INSTALL_DIR, filename) + File::install(File.join(SOURCE_DIR, filename), installPath, 0644, true) +} diff --git a/lib/zip/ioextras.rb b/vendor/plugins/rubyzip-0.9.1/lib/zip/ioextras.rb old mode 100644 new mode 100755 similarity index 76% rename from lib/zip/ioextras.rb rename to vendor/plugins/rubyzip-0.9.1/lib/zip/ioextras.rb index 7129e933..c458bb58 --- a/lib/zip/ioextras.rb +++ b/vendor/plugins/rubyzip-0.9.1/lib/zip/ioextras.rb @@ -1,5 +1,15 @@ module IOExtras #:nodoc: + CHUNK_SIZE = 32768 + + RANGE_ALL = 0..-1 + + def self.copy_stream(ostream, istream) + s = '' + ostream.write(istream.read(CHUNK_SIZE, s)) until istream.eof? + end + + # Implements kind_of? in order to pretend to be an IO object module FakeIO def kind_of?(object) @@ -22,6 +32,34 @@ module IOExtras #:nodoc: attr_accessor :lineno + def read(numberOfBytes = nil, buf = nil) + tbuf = nil + + if @outputBuffer.length > 0 + if numberOfBytes <= @outputBuffer.length + tbuf = @outputBuffer.slice!(0, numberOfBytes) + else + numberOfBytes -= @outputBuffer.length if (numberOfBytes) + rbuf = sysread(numberOfBytes, buf) + tbuf = @outputBuffer + tbuf << rbuf if (rbuf) + @outputBuffer = "" + end + else + tbuf = sysread(numberOfBytes, buf) + end + + return nil unless (tbuf) + + if buf + buf.replace(tbuf) + else + buf = tbuf + end + + buf + end + def readlines(aSepString = $/) retVal = [] each_line(aSepString) { |line| retVal << line } diff --git a/lib/zip/stdrubyext.rb b/vendor/plugins/rubyzip-0.9.1/lib/zip/stdrubyext.rb old mode 100644 new mode 100755 similarity index 100% rename from lib/zip/stdrubyext.rb rename to vendor/plugins/rubyzip-0.9.1/lib/zip/stdrubyext.rb diff --git a/lib/zip/tempfile_bugfixed.rb b/vendor/plugins/rubyzip-0.9.1/lib/zip/tempfile_bugfixed.rb old mode 100644 new mode 100755 similarity index 100% rename from lib/zip/tempfile_bugfixed.rb rename to vendor/plugins/rubyzip-0.9.1/lib/zip/tempfile_bugfixed.rb diff --git a/lib/zip/zip.rb b/vendor/plugins/rubyzip-0.9.1/lib/zip/zip.rb old mode 100644 new mode 100755 similarity index 76% rename from lib/zip/zip.rb rename to vendor/plugins/rubyzip-0.9.1/lib/zip/zip.rb index 57c0b4fa..19d90f51 --- a/lib/zip/zip.rb +++ b/vendor/plugins/rubyzip-0.9.1/lib/zip/zip.rb @@ -2,6 +2,7 @@ require 'delegate' require 'singleton' require 'tempfile' require 'ftools' +require 'stringio' require 'zlib' require 'zip/stdrubyext' require 'zip/ioextras' @@ -19,10 +20,12 @@ end module Zip - VERSION = '0.5.8' + VERSION = '0.9.1' RUBY_MINOR_VERSION = RUBY_VERSION.split(".")[1].to_i + RUNNING_ON_WINDOWS = /mswin32|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM + # Ruby 1.7.x compatibility # In ruby 1.6.x and 1.8.0 reading from an empty stream returns # an empty string the first time and then nil. @@ -104,9 +107,10 @@ module Zip # method on a newly created ZipInputStream before reading from # the first entry in the archive. Returns nil when there are # no more entries. + def get_next_entry @archiveIO.seek(@currentEntry.next_header_offset, - IO::SEEK_SET) if @currentEntry + IO::SEEK_SET) if @currentEntry open_entry end @@ -119,11 +123,16 @@ module Zip open_entry end - # Modeled after IO.read - def read(numberOfBytes = nil) - @decompressor.read(numberOfBytes) + # Modeled after IO.sysread + def sysread(numberOfBytes = nil, buf = nil) + @decompressor.sysread(numberOfBytes, buf) end + def eof + @outputBuffer.empty? && @decompressor.eof + end + alias :eof? :eof + protected def open_entry @@ -146,7 +155,7 @@ module Zip def produce_input @decompressor.produce_input end - + def input_finished? @decompressor.input_finished? end @@ -170,11 +179,11 @@ module Zip @hasReturnedEmptyString = ! EMPTY_FILE_RETURNS_EMPTY_STRING_FIRST end - def read(numberOfBytes = nil) + def sysread(numberOfBytes = nil, buf = nil) readEverything = (numberOfBytes == nil) while (readEverything || @outputBuffer.length < numberOfBytes) break if internal_input_finished? - @outputBuffer << internal_produce_input + @outputBuffer << internal_produce_input(buf) end return value_when_finished if @outputBuffer.length==0 && input_finished? endIndex= numberOfBytes==nil ? @outputBuffer.length : numberOfBytes @@ -190,14 +199,24 @@ module Zip end # to be used with produce_input, not read (as read may still have more data cached) + # is data cached anywhere other than @outputBuffer? the comment above may be wrong def input_finished? @outputBuffer.empty? && internal_input_finished? end + alias :eof :input_finished? + alias :eof? :input_finished? private - def internal_produce_input - @zlibInflater.inflate(@inputStream.read(Decompressor::CHUNK_SIZE)) + def internal_produce_input(buf = nil) + retried = 0 + begin + @zlibInflater.inflate(@inputStream.read(Decompressor::CHUNK_SIZE, buf)) + rescue Zlib::BufError + raise if (retried >= 5) # how many times should we retry? + retried += 1 + retry + end end def internal_input_finished? @@ -221,7 +240,7 @@ module Zip end # TODO: Specialize to handle different behaviour in ruby > 1.7.0 ? - def read(numberOfBytes = nil) + def sysread(numberOfBytes = nil, buf = nil) if input_finished? hasReturnedEmptyStringVal=@hasReturnedEmptyString @hasReturnedEmptyString=true @@ -233,21 +252,23 @@ module Zip numberOfBytes = @charsToRead-@readSoFar end @readSoFar += numberOfBytes - @inputStream.read(numberOfBytes) + @inputStream.read(numberOfBytes, buf) end def produce_input - read(Decompressor::CHUNK_SIZE) + sysread(Decompressor::CHUNK_SIZE) end def input_finished? (@readSoFar >= @charsToRead) end + alias :eof :input_finished? + alias :eof? :input_finished? end class NullDecompressor #:nodoc:all include Singleton - def read(numberOfBytes = nil) + def sysread(numberOfBytes = nil, buf = nil) nil end @@ -258,6 +279,11 @@ module Zip def input_finished? true end + + def eof + true + end + alias :eof? :eof end class NullInputStream < NullDecompressor #:nodoc:all @@ -267,9 +293,61 @@ module Zip class ZipEntry STORED = 0 DEFLATED = 8 + + FSTYPE_FAT = 0 + FSTYPE_AMIGA = 1 + FSTYPE_VMS = 2 + FSTYPE_UNIX = 3 + FSTYPE_VM_CMS = 4 + FSTYPE_ATARI = 5 + FSTYPE_HPFS = 6 + FSTYPE_MAC = 7 + FSTYPE_Z_SYSTEM = 8 + FSTYPE_CPM = 9 + FSTYPE_TOPS20 = 10 + FSTYPE_NTFS = 11 + FSTYPE_QDOS = 12 + FSTYPE_ACORN = 13 + FSTYPE_VFAT = 14 + FSTYPE_MVS = 15 + FSTYPE_BEOS = 16 + FSTYPE_TANDEM = 17 + FSTYPE_THEOS = 18 + FSTYPE_MAC_OSX = 19 + FSTYPE_ATHEOS = 30 + + FSTYPES = { + FSTYPE_FAT => 'FAT'.freeze, + FSTYPE_AMIGA => 'Amiga'.freeze, + FSTYPE_VMS => 'VMS (Vax or Alpha AXP)'.freeze, + FSTYPE_UNIX => 'Unix'.freeze, + FSTYPE_VM_CMS => 'VM/CMS'.freeze, + FSTYPE_ATARI => 'Atari ST'.freeze, + FSTYPE_HPFS => 'OS/2 or NT HPFS'.freeze, + FSTYPE_MAC => 'Macintosh'.freeze, + FSTYPE_Z_SYSTEM => 'Z-System'.freeze, + FSTYPE_CPM => 'CP/M'.freeze, + FSTYPE_TOPS20 => 'TOPS-20'.freeze, + FSTYPE_NTFS => 'NTFS'.freeze, + FSTYPE_QDOS => 'SMS/QDOS'.freeze, + FSTYPE_ACORN => 'Acorn RISC OS'.freeze, + FSTYPE_VFAT => 'Win32 VFAT'.freeze, + FSTYPE_MVS => 'MVS'.freeze, + FSTYPE_BEOS => 'BeOS'.freeze, + FSTYPE_TANDEM => 'Tandem NSK'.freeze, + FSTYPE_THEOS => 'Theos'.freeze, + FSTYPE_MAC_OSX => 'Mac OS/X (Darwin)'.freeze, + FSTYPE_ATHEOS => 'AtheOS'.freeze, + }.freeze attr_accessor :comment, :compressed_size, :crc, :extra, :compression_method, - :name, :size, :localHeaderOffset, :zipfile, :fstype, :externalFileAttributes + :name, :size, :localHeaderOffset, :zipfile, :fstype, :externalFileAttributes, :gp_flags, :header_signature + + attr_accessor :follow_symlinks + attr_accessor :restore_times, :restore_permissions, :restore_ownership + attr_accessor :unix_uid, :unix_gid, :unix_perms + + attr_reader :ftype, :filepath # :nodoc: def initialize(zipfile = "", name = "", comment = "", extra = "", compressed_size = 0, crc = 0, @@ -283,11 +361,37 @@ module Zip @internalFileAttributes = 1 @externalFileAttributes = 0 @version = 52 # this library's version - @fstype = 0 # default is fat + @ftype = nil # unspecified or unknown + @filepath = nil + if Zip::RUNNING_ON_WINDOWS + @fstype = FSTYPE_FAT + else + @fstype = FSTYPE_UNIX + end @zipfile, @comment, @compressed_size, @crc, @extra, @compression_method, @name, @size = zipfile, comment, compressed_size, crc, extra, compression_method, name, size @time = time + + @follow_symlinks = false + + @restore_times = true + @restore_permissions = false + @restore_ownership = false + +# BUG: need an extra field to support uid/gid's + @unix_uid = nil + @unix_gid = nil + @unix_perms = nil +# @posix_acl = nil +# @ntfs_acl = nil + + if name_is_directory? + @ftype = :directory + else + @ftype = :file + end + unless ZipExtraField === @extra @extra = ZipExtraField.new(@extra.to_s) end @@ -312,13 +416,27 @@ module Zip @time = aTime end + # Returns +true+ if the entry is a directory. def directory? - return (%r{\/$} =~ @name) != nil + raise ZipInternalError, "current filetype is unknown: #{self.inspect}" unless @ftype + @ftype == :directory end alias :is_directory :directory? + # Returns +true+ if the entry is a file. def file? - ! directory? + raise ZipInternalError, "current filetype is unknown: #{self.inspect}" unless @ftype + @ftype == :file + end + + # Returns +true+ if the entry is a symlink. + def symlink? + raise ZipInternalError, "current filetype is unknown: #{self.inspect}" unless @ftype + @ftype == :link + end + + def name_is_directory? #:nodoc:all + (%r{\/$} =~ @name) != nil end def local_entry_offset #:nodoc:all @@ -337,24 +455,42 @@ module Zip def next_header_offset #:nodoc:all local_entry_offset + self.compressed_size end - + + # Extracts entry to file destPath (defaults to @name). + def extract(destPath = @name, &onExistsProc) + onExistsProc ||= proc { false } + + if directory? + create_directory(destPath, &onExistsProc) + elsif file? + write_file(destPath, &onExistsProc) + elsif symlink? + create_symlink(destPath, &onExistsProc) + else + raise RuntimeError, "unknown file type #{self.inspect}" + end + + self + end + def to_s @name end protected - def ZipEntry.read_zip_short(io) + def ZipEntry.read_zip_short(io) # :nodoc: io.read(2).unpack('v')[0] end - def ZipEntry.read_zip_long(io) + def ZipEntry.read_zip_long(io) # :nodoc: io.read(4).unpack('V')[0] end public LOCAL_ENTRY_SIGNATURE = 0x04034b50 LOCAL_ENTRY_STATIC_HEADER_LENGTH = 30 + LOCAL_ENTRY_TRAILING_DESCRIPTOR_LENGTH = 4+4+4 def read_local_entry(io) #:nodoc:all @localHeaderOffset = io.tell @@ -363,10 +499,10 @@ module Zip raise ZipError, "Premature end of file. Not enough data for zip entry local header" end - localHeader , + @header_signature , @version , @fstype , - @gpFlags , + @gp_flags , @compression_method, lastModTime , lastModDate , @@ -376,7 +512,7 @@ module Zip nameLength , extraLength = staticSizedFieldsBuf.unpack('VCCvvvvVVVvv') - unless (localHeader == LOCAL_ENTRY_SIGNATURE) + unless (@header_signature == LOCAL_ENTRY_SIGNATURE) raise ZipError, "Zip local header magic not found at location '#{localHeaderOffset}'" end set_time(lastModDate, lastModTime) @@ -409,7 +545,7 @@ module Zip io << [LOCAL_ENTRY_SIGNATURE , 0 , - 0 , # @gpFlags , + 0 , # @gp_flags , @compression_method , @time.to_binary_dos_time , # @lastModTime , @time.to_binary_dos_date , # @lastModDate , @@ -430,12 +566,12 @@ module Zip unless (staticSizedFieldsBuf.size == CDIR_ENTRY_STATIC_HEADER_LENGTH) raise ZipError, "Premature end of file. Not enough data for zip cdir entry header" end - - cdirSignature , + + @header_signature , @version , # version of encoding software @fstype , # filesystem type @versionNeededToExtract, - @gpFlags , + @gp_flags , @compression_method , lastModTime , lastModDate , @@ -453,7 +589,7 @@ module Zip @extra , @comment = staticSizedFieldsBuf.unpack('VCCvvvvvVVVvvvvvVV') - unless (cdirSignature == CENTRAL_DIRECTORY_ENTRY_SIGNATURE) + unless (@header_signature == CENTRAL_DIRECTORY_ENTRY_SIGNATURE) raise ZipError, "Zip local header magic not found at location '#{localHeaderOffset}'" end set_time(lastModDate, lastModTime) @@ -468,6 +604,28 @@ module Zip unless (@comment && @comment.length == commentLength) raise ZipError, "Truncated cdir zip entry header" end + + case @fstype + when FSTYPE_UNIX + @unix_perms = (@externalFileAttributes >> 16) & 07777 + + case (@externalFileAttributes >> 28) + when 04 + @ftype = :directory + when 010 + @ftype = :file + when 012 + @ftype = :link + else + raise ZipInternalError, "unknown file type #{'0%o' % (@externalFileAttributes >> 28)}" + end + else + if name_is_directory? + @ftype = :directory + else + @ftype = :file + end + end end def ZipEntry.read_c_dir_entry(io) #:nodoc:all @@ -478,14 +636,65 @@ module Zip return nil end + def file_stat(path) # :nodoc: + if @follow_symlinks + return File::stat(path) + else + return File::lstat(path) + end + end + + def get_extra_attributes_from_path(path) # :nodoc: + unless Zip::RUNNING_ON_WINDOWS + stat = file_stat(path) + @unix_uid = stat.uid + @unix_gid = stat.gid + @unix_perms = stat.mode & 07777 + end + end + + def set_extra_attributes_on_path(destPath) # :nodoc: + return unless (file? or directory?) + + case @fstype + when FSTYPE_UNIX + # BUG: does not update timestamps into account + # ignore setuid/setgid bits by default. honor if @restore_ownership + unix_perms_mask = 01777 + unix_perms_mask = 07777 if (@restore_ownership) + File::chmod(@unix_perms & unix_perms_mask, destPath) if (@restore_permissions && @unix_perms) + File::chown(@unix_uid, @unix_gid, destPath) if (@restore_ownership && @unix_uid && @unix_gid && Process::egid == 0) + # File::utimes() + end + end def write_c_dir_entry(io) #:nodoc:all + case @fstype + when FSTYPE_UNIX + ft = nil + case @ftype + when :file + ft = 010 + @unix_perms ||= 0644 + when :directory + ft = 004 + @unix_perms ||= 0755 + when :symlink + ft = 012 + @unix_perms ||= 0755 + else + raise ZipInternalError, "unknown file type #{self.inspect}" + end + + @externalFileAttributes = (ft << 12 | (@unix_perms & 07777)) << 16 + end + io << [CENTRAL_DIRECTORY_ENTRY_SIGNATURE, @version , # version of encoding software @fstype , # filesystem type 0 , # @versionNeededToExtract , - 0 , # @gpFlags , + 0 , # @gp_flags , @compression_method , @time.to_binary_dos_time , # @lastModTime , @time.to_binary_dos_date , # @lastModDate , @@ -509,14 +718,15 @@ module Zip end def == (other) - return false unless other.class == ZipEntry + return false unless other.class == self.class # Compares contents of local entry and exposed fields (@compression_method == other.compression_method && @crc == other.crc && - @compressed_size == other.compressed_size && + @compressed_size == other.compressed_size && @size == other.size && @name == other.name && @extra == other.extra && + @filepath == other.filepath && self.time.dos_equals(other.time)) end @@ -524,23 +734,79 @@ module Zip return to_s <=> other.to_s end - def get_input_stream - zis = ZipInputStream.new(@zipfile, localHeaderOffset) - zis.get_next_entry - if block_given? - begin - return yield(zis) - ensure - zis.close - end + # Returns an IO like object for the given ZipEntry. + # Warning: may behave weird with symlinks. + def get_input_stream(&aProc) + if @ftype == :directory + return yield(NullInputStream.instance) if block_given? + return NullInputStream.instance + elsif @filepath + case @ftype + when :file + return File.open(@filepath, "rb", &aProc) + + when :symlink + linkpath = File::readlink(@filepath) + stringio = StringIO.new(linkpath) + return yield(stringio) if block_given? + return stringio + else + raise "unknown @ftype #{@ftype}" + end else - return zis + zis = ZipInputStream.new(@zipfile, localHeaderOffset) + zis.get_next_entry + if block_given? + begin + return yield(zis) + ensure + zis.close + end + else + return zis + end end end + def gather_fileinfo_from_srcpath(srcPath) # :nodoc: + stat = file_stat(srcPath) + case stat.ftype + when 'file' + if name_is_directory? + raise ArgumentError, + "entry name '#{newEntry}' indicates directory entry, but "+ + "'#{srcPath}' is not a directory" + end + @ftype = :file + when 'directory' + if ! name_is_directory? + @name += "/" + end + @ftype = :directory + when 'link' + if name_is_directory? + raise ArgumentError, + "entry name '#{newEntry}' indicates directory entry, but "+ + "'#{srcPath}' is not a directory" + end + @ftype = :symlink + else + raise RuntimeError, "unknown file type: #{srcPath.inspect} #{stat.inspect}" + end + + @filepath = srcPath + get_extra_attributes_from_path(@filepath) + end def write_to_zip_output_stream(aZipOutputStream) #:nodoc:all - aZipOutputStream.copy_raw_entry(self) + if @ftype == :directory + aZipOutputStream.put_next_entry(self) + elsif @filepath + aZipOutputStream.put_next_entry(self) + get_input_stream { |is| IOExtras.copy_stream(aZipOutputStream, is) } + else + aZipOutputStream.copy_raw_entry(self) + end end def parent_as_string @@ -554,11 +820,75 @@ module Zip end private + def set_time(binaryDosDate, binaryDosTime) @time = Time.parse_binary_dos_format(binaryDosDate, binaryDosTime) rescue ArgumentError puts "Invalid date/time in zip entry" end + + def write_file(destPath, continueOnExistsProc = proc { false }) + if File.exists?(destPath) && ! yield(self, destPath) + raise ZipDestinationFileExistsError, + "Destination '#{destPath}' already exists" + end + File.open(destPath, "wb") do |os| + get_input_stream do |is| + set_extra_attributes_on_path(destPath) + + buf = '' + while buf = is.sysread(Decompressor::CHUNK_SIZE, buf) + os << buf + end + end + end + end + + def create_directory(destPath) + if File.directory? destPath + return + elsif File.exists? destPath + if block_given? && yield(self, destPath) + File.rm_f destPath + else + raise ZipDestinationFileExistsError, + "Cannot create directory '#{destPath}'. "+ + "A file already exists with that name" + end + end + Dir.mkdir destPath + set_extra_attributes_on_path(destPath) + end + +# BUG: create_symlink() does not use &onExistsProc + def create_symlink(destPath) + stat = nil + begin + stat = File::lstat(destPath) + rescue Errno::ENOENT + end + + io = get_input_stream + linkto = io.read + + if stat + if stat.symlink? + if File::readlink(destPath) == linkto + return + else + raise ZipDestinationFileExistsError, + "Cannot create symlink '#{destPath}'. "+ + "A symlink already exists with that name" + end + else + raise ZipDestinationFileExistsError, + "Cannot create symlink '#{destPath}'. "+ + "A file already exists with that name" + end + end + + File::symlink(linkto, destPath) + end end @@ -624,7 +954,7 @@ module Zip def put_next_entry(entry, level = Zlib::DEFAULT_COMPRESSION) raise ZipError, "zip stream is closed" if @closed newEntry = entry.kind_of?(ZipEntry) ? entry : ZipEntry.new(@fileName, entry.to_s) - init_next_entry(newEntry) + init_next_entry(newEntry, level) @currentEntry=newEntry end @@ -811,6 +1141,13 @@ module Zip @entrySet[entry.parent_as_string] end + def glob(pattern, flags = File::FNM_PATHNAME|File::FNM_DOTMATCH) + entries.select { + |entry| + File.fnmatch(pattern, entry.name.chomp('/'), flags) + } + end + #TODO attr_accessor :auto_create_directories protected attr_accessor :entrySet @@ -898,10 +1235,23 @@ module Zip io.seek(-MAX_END_OF_CENTRAL_DIRECTORY_STRUCTURE_SIZE, IO::SEEK_END) rescue Errno::EINVAL io.seek(0, IO::SEEK_SET) - rescue Errno::EFBIG # FreeBSD 4.9 returns Errno::EFBIG instead of Errno::EINVAL + rescue Errno::EFBIG # FreeBSD 4.9 raise Errno::EFBIG instead of Errno::EINVAL io.seek(0, IO::SEEK_SET) end - buf = io.read + + # 'buf = io.read' substituted with lump of code to work around FreeBSD 4.5 issue + retried = false + buf = nil + begin + buf = io.read + rescue Errno::EFBIG # FreeBSD 4.5 may raise Errno::EFBIG + raise if (retried) + retried = true + + io.seek(0, IO::SEEK_SET) + retry + end + sigIndex = buf.rindex([END_OF_CENTRAL_DIRECTORY_SIGNATURE].pack('V')) raise ZipError, "Zip end of central directory signature not found" unless sigIndex buf=buf.slice!((sigIndex+4)...(buf.size)) @@ -943,6 +1293,7 @@ module Zip class ZipDestinationFileExistsError < ZipError; end class ZipCompressionMethodError < ZipError; end class ZipEntryNameError < ZipError; end + class ZipInternalError < ZipError; end # ZipFile is modeled after java.util.zip.ZipFile from the Java SDK. # The most important methods are those inherited from @@ -993,6 +1344,13 @@ module Zip attr_reader :name + # default -> false + attr_accessor :restore_ownership + # default -> false + attr_accessor :restore_permissions + # default -> true + attr_accessor :restore_times + # Opens a zip archive. Pass true as the second parameter to create # a new archive if it doesn't exist already. def initialize(fileName, create = nil) @@ -1008,6 +1366,10 @@ module Zip end @create = create @storedEntries = @entrySet.dup + + @restore_ownership = false + @restore_permissions = false + @restore_times = true end # Same as #new. If a block is passed the ZipFile object is passed @@ -1078,11 +1440,8 @@ module Zip continueOnExistsProc ||= proc { false } check_entry_exists(entry, continueOnExistsProc, "add") newEntry = entry.kind_of?(ZipEntry) ? entry : ZipEntry.new(@name, entry.to_s) - if is_directory(newEntry, srcPath) - @entrySet << ZipStreamableDirectory.new(newEntry) - else - @entrySet << ZipStreamableFile.new(newEntry, srcPath) - end + newEntry.gather_fileinfo_from_srcpath(srcPath) + @entrySet << newEntry end # Removes the specified entry. @@ -1108,11 +1467,7 @@ module Zip def extract(entry, destPath, &onExistsProc) onExistsProc ||= proc { false } foundEntry = get_entry(entry) - if foundEntry.is_directory - create_directory(foundEntry, destPath, &onExistsProc) - else - write_file(foundEntry, destPath, &onExistsProc) - end + foundEntry.extract(destPath, &onExistsProc) end # Commits changes that has been made since the previous commit to @@ -1159,34 +1514,23 @@ module Zip unless selectedEntry raise Errno::ENOENT, entry end + selectedEntry.restore_ownership = @restore_ownership + selectedEntry.restore_permissions = @restore_permissions + selectedEntry.restore_times = @restore_times + return selectedEntry end # Creates a directory - def mkdir(entryName, permissionInt = 0) #permissionInt ignored + def mkdir(entryName, permissionInt = 0755) if find_entry(entryName) raise Errno::EEXIST, "File exists - #{entryName}" end - @entrySet << ZipStreamableDirectory.new(ZipEntry.new(name, entryName.to_s.ensure_end("/"))) + @entrySet << ZipStreamableDirectory.new(@name, entryName.to_s.ensure_end("/"), nil, permissionInt) end private - def create_directory(entry, destPath) - if File.directory? destPath - return - elsif File.exists? destPath - if block_given? && yield(entry, destPath) - File.rm_f destPath - else - raise ZipDestinationFileExistsError, - "Cannot create directory '#{destPath}'. "+ - "A file already exists with that name" - end - end - Dir.mkdir destPath - end - def is_directory(newEntry, srcPath) srcPathIsDirectory = File.directory?(srcPath) if newEntry.is_directory && ! srcPathIsDirectory @@ -1211,17 +1555,6 @@ module Zip end end - def write_file(entry, destPath, continueOnExistsProc = proc { false }) - if File.exists?(destPath) && ! yield(entry, destPath) - raise ZipDestinationFileExistsError, - "Destination '#{destPath}' already exists" - end - File.open(destPath, "wb") { - |os| - entry.get_input_stream { |is| os << is.read } - } - end - def check_file(path) unless File.readable? path raise Errno::ENOENT, path @@ -1245,43 +1578,13 @@ module Zip end - class ZipStreamableFile < DelegateClass(ZipEntry) #:nodoc:all - def initialize(entry, filepath) - super(entry) - @delegate = entry - @filepath = filepath - end + class ZipStreamableDirectory < ZipEntry + def initialize(zipfile, entry, srcPath = nil, permissionInt = nil) + super(zipfile, entry) - def get_input_stream(&aProc) - File.open(@filepath, "rb", &aProc) - end - - def write_to_zip_output_stream(aZipOutputStream) - aZipOutputStream.put_next_entry(self) - aZipOutputStream << get_input_stream { |is| is.read } - end - - def == (other) - return false unless other.class == ZipStreamableFile - @filepath == other.filepath && super(other.delegate) - end - - protected - attr_reader :filepath, :delegate - end - - class ZipStreamableDirectory < DelegateClass(ZipEntry) #:nodoc:all - def initialize(entry) - super(entry) - end - - def get_input_stream(&aProc) - return yield(NullInputStream.instance) if block_given? - NullInputStream.instance - end - - def write_to_zip_output_stream(aZipOutputStream) - aZipOutputStream.put_next_entry(self) + @ftype = :directory + entry.get_extra_attributes_from_path(srcPath) if (srcPath) + @unix_perms = permissionInt if (permissionInt) end end @@ -1309,6 +1612,7 @@ module Zip raise StandardError, "cannot open entry for reading while its open for writing - #{name}" end @tempFile.open # reopens tempfile from top + @tempFile.binmode if block_given? begin yield(@tempFile) @@ -1322,7 +1626,7 @@ module Zip def write_to_zip_output_stream(aZipOutputStream) aZipOutputStream.put_next_entry(self) - aZipOutputStream << get_input_stream { |is| is.read } + get_input_stream { |is| IOExtras.copy_stream(aZipOutputStream, is) } end end diff --git a/lib/zip/zipfilesystem.rb b/vendor/plugins/rubyzip-0.9.1/lib/zip/zipfilesystem.rb old mode 100644 new mode 100755 similarity index 99% rename from lib/zip/zipfilesystem.rb rename to vendor/plugins/rubyzip-0.9.1/lib/zip/zipfilesystem.rb index 75645b43..3fa3748c --- a/lib/zip/zipfilesystem.rb +++ b/vendor/plugins/rubyzip-0.9.1/lib/zip/zipfilesystem.rb @@ -482,7 +482,7 @@ module Zip alias rmdir delete alias unlink delete - def mkdir(entryName, permissionInt = 0) + def mkdir(entryName, permissionInt = 0755) @mappedZip.mkdir(entryName, permissionInt) end @@ -571,7 +571,7 @@ module Zip &continueOnExistsProc) end - def mkdir(fileName, permissionInt = 0) + def mkdir(fileName, permissionInt = 0755) @zipFile.mkdir(expand_to_entry(fileName), permissionInt) end diff --git a/lib/zip/ziprequire.rb b/vendor/plugins/rubyzip-0.9.1/lib/zip/ziprequire.rb old mode 100644 new mode 100755 similarity index 100% rename from lib/zip/ziprequire.rb rename to vendor/plugins/rubyzip-0.9.1/lib/zip/ziprequire.rb diff --git a/vendor/plugins/rubyzip-0.9.1/samples/example.rb b/vendor/plugins/rubyzip-0.9.1/samples/example.rb new file mode 100755 index 00000000..741afa76 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/samples/example.rb @@ -0,0 +1,69 @@ +#!/usr/bin/env ruby + +$: << "../lib" +system("zip example.zip example.rb gtkRubyzip.rb") + +require 'zip/zip' + +####### Using ZipInputStream alone: ####### + +Zip::ZipInputStream.open("example.zip") { + |zis| + entry = zis.get_next_entry + print "First line of '#{entry.name} (#{entry.size} bytes): " + puts "'#{zis.gets.chomp}'" + entry = zis.get_next_entry + print "First line of '#{entry.name} (#{entry.size} bytes): " + puts "'#{zis.gets.chomp}'" +} + + +####### Using ZipFile to read the directory of a zip file: ####### + +zf = Zip::ZipFile.new("example.zip") +zf.each_with_index { + |entry, index| + + puts "entry #{index} is #{entry.name}, size = #{entry.size}, compressed size = #{entry.compressed_size}" + # use zf.get_input_stream(entry) to get a ZipInputStream for the entry + # entry can be the ZipEntry object or any object which has a to_s method that + # returns the name of the entry. +} + + +####### Using ZipOutputStream to write a zip file: ####### + +Zip::ZipOutputStream.open("exampleout.zip") { + |zos| + zos.put_next_entry("the first little entry") + zos.puts "Hello hello hello hello hello hello hello hello hello" + + zos.put_next_entry("the second little entry") + zos.puts "Hello again" + + # Use rubyzip or your zip client of choice to verify + # the contents of exampleout.zip +} + +####### Using ZipFile to change a zip file: ####### + +Zip::ZipFile.open("exampleout.zip") { + |zf| + zf.add("thisFile.rb", "example.rb") + zf.rename("thisFile.rb", "ILikeThisName.rb") + zf.add("Again", "example.rb") +} + +# Lets check +Zip::ZipFile.open("exampleout.zip") { + |zf| + puts "Changed zip file contains: #{zf.entries.join(', ')}" + zf.remove("Again") + puts "Without 'Again': #{zf.entries.join(', ')}" +} + +# For other examples, look at zip.rb and ziptest.rb + +# Copyright (C) 2002 Thomas Sondergaard +# rubyzip is free software; you can redistribute it and/or +# modify it under the terms of the ruby license. diff --git a/vendor/plugins/rubyzip-0.9.1/samples/example_filesystem.rb b/vendor/plugins/rubyzip-0.9.1/samples/example_filesystem.rb new file mode 100755 index 00000000..867e8d4f --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/samples/example_filesystem.rb @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby + +$: << "../lib" + +require 'zip/zipfilesystem' +require 'ftools' + +EXAMPLE_ZIP = "filesystem.zip" + +File.delete(EXAMPLE_ZIP) if File.exists?(EXAMPLE_ZIP) + +Zip::ZipFile.open(EXAMPLE_ZIP, Zip::ZipFile::CREATE) { + |zf| + zf.file.open("file1.txt", "w") { |os| os.write "first file1.txt" } + zf.dir.mkdir("dir1") + zf.dir.chdir("dir1") + zf.file.open("file1.txt", "w") { |os| os.write "second file1.txt" } + puts zf.file.read("file1.txt") + puts zf.file.read("../file1.txt") + zf.dir.chdir("..") + zf.file.open("file2.txt", "w") { |os| os.write "first file2.txt" } + puts "Entries: #{zf.entries.join(', ')}" +} + +Zip::ZipFile.open(EXAMPLE_ZIP) { + |zf| + puts "Entries from reloaded zip: #{zf.entries.join(', ')}" +} + +# For other examples, look at zip.rb and ziptest.rb + +# Copyright (C) 2003 Thomas Sondergaard +# rubyzip is free software; you can redistribute it and/or +# modify it under the terms of the ruby license. diff --git a/vendor/plugins/rubyzip-0.9.1/samples/gtkRubyzip.rb b/vendor/plugins/rubyzip-0.9.1/samples/gtkRubyzip.rb new file mode 100755 index 00000000..5d91829d --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/samples/gtkRubyzip.rb @@ -0,0 +1,86 @@ +#!/usr/bin/env ruby + +$: << "../lib" + +$VERBOSE = true + +require 'gtk' +require 'zip/zip' + +class MainApp < Gtk::Window + def initialize + super() + set_usize(400, 256) + set_title("rubyzip") + signal_connect(Gtk::Window::SIGNAL_DESTROY) { Gtk.main_quit } + + box = Gtk::VBox.new(false, 0) + add(box) + + @zipfile = nil + @buttonPanel = ButtonPanel.new + @buttonPanel.openButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) { + show_file_selector + } + @buttonPanel.extractButton.signal_connect(Gtk::Button::SIGNAL_CLICKED) { + puts "Not implemented!" + } + box.pack_start(@buttonPanel, false, false, 0) + + sw = Gtk::ScrolledWindow.new + sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC) + box.pack_start(sw, true, true, 0) + + @clist = Gtk::CList.new(["Name", "Size", "Compression"]) + @clist.set_selection_mode(Gtk::SELECTION_BROWSE) + @clist.set_column_width(0, 120) + @clist.set_column_width(1, 120) + @clist.signal_connect(Gtk::CList::SIGNAL_SELECT_ROW) { + |w, row, column, event| + @selected_row = row + } + sw.add(@clist) + end + + class ButtonPanel < Gtk::HButtonBox + attr_reader :openButton, :extractButton + def initialize + super + set_layout(Gtk::BUTTONBOX_START) + set_spacing(0) + @openButton = Gtk::Button.new("Open archive") + @extractButton = Gtk::Button.new("Extract entry") + pack_start(@openButton) + pack_start(@extractButton) + end + end + + def show_file_selector + @fileSelector = Gtk::FileSelection.new("Open zip file") + @fileSelector.show + @fileSelector.ok_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) { + open_zip(@fileSelector.filename) + @fileSelector.destroy + } + @fileSelector.cancel_button.signal_connect(Gtk::Button::SIGNAL_CLICKED) { + @fileSelector.destroy + } + end + + def open_zip(filename) + @zipfile = Zip::ZipFile.open(filename) + @clist.clear + @zipfile.each { + |entry| + @clist.append([ entry.name, + entry.size.to_s, + (100.0*entry.compressedSize/entry.size).to_s+"%" ]) + } + end +end + +mainApp = MainApp.new() + +mainApp.show_all + +Gtk.main diff --git a/vendor/plugins/rubyzip-0.9.1/samples/qtzip.rb b/vendor/plugins/rubyzip-0.9.1/samples/qtzip.rb new file mode 100755 index 00000000..3d76bd18 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/samples/qtzip.rb @@ -0,0 +1,101 @@ +#!/usr/bin/env ruby + +$VERBOSE=true + +$: << "../lib" + +require 'Qt' +system('rbuic -o zipdialogui.rb zipdialogui.ui') +require 'zipdialogui.rb' +require 'zip/zip' + + + +a = Qt::Application.new(ARGV) + +class ZipDialog < ZipDialogUI + + + def initialize() + super() + connect(child('add_button'), SIGNAL('clicked()'), + self, SLOT('add_files()')) + connect(child('extract_button'), SIGNAL('clicked()'), + self, SLOT('extract_files()')) + end + + def zipfile(&proc) + Zip::ZipFile.open(@zip_filename, &proc) + end + + def each(&proc) + Zip::ZipFile.foreach(@zip_filename, &proc) + end + + def refresh() + lv = child("entry_list_view") + lv.clear + each { + |e| + lv.insert_item(Qt::ListViewItem.new(lv, e.name, e.size.to_s)) + } + end + + + def load(zipfile) + @zip_filename = zipfile + refresh + end + + def add_files + l = Qt::FileDialog.getOpenFileNames(nil, nil, self) + zipfile { + |zf| + l.each { + |path| + zf.add(File.basename(path), path) + } + } + refresh + end + + def extract_files + selected_items = [] + unselected_items = [] + lv_item = entry_list_view.first_child + while (lv_item) + if entry_list_view.is_selected(lv_item) + selected_items << lv_item.text(0) + else + unselected_items << lv_item.text(0) + end + lv_item = lv_item.next_sibling + end + puts "selected_items.size = #{selected_items.size}" + puts "unselected_items.size = #{unselected_items.size}" + items = selected_items.size > 0 ? selected_items : unselected_items + puts "items.size = #{items.size}" + + d = Qt::FileDialog.get_existing_directory(nil, self) + if (!d) + puts "No directory chosen" + else + zipfile { |zf| items.each { |e| zf.extract(e, File.join(d, e)) } } + end + + end + + slots 'add_files()', 'extract_files()' +end + +if !ARGV[0] + puts "usage: #{$0} zipname" + exit +end + +zd = ZipDialog.new +zd.load(ARGV[0]) + +a.mainWidget = zd +zd.show() +a.exec() diff --git a/vendor/plugins/rubyzip-0.9.1/samples/write_simple.rb b/vendor/plugins/rubyzip-0.9.1/samples/write_simple.rb new file mode 100755 index 00000000..5a1f26b1 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/samples/write_simple.rb @@ -0,0 +1,13 @@ +#!/usr/bin/env ruby + +$: << "../lib" + +require 'zip/zip' + +include Zip + +ZipOutputStream.open('simple.zip') { + |zos| + ze = zos.put_next_entry 'entry.txt' + zos.puts "Hello world" +} diff --git a/vendor/plugins/rubyzip-0.9.1/samples/zipfind.rb b/vendor/plugins/rubyzip-0.9.1/samples/zipfind.rb new file mode 100755 index 00000000..54ad936e --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/samples/zipfind.rb @@ -0,0 +1,74 @@ +#!/usr/bin/env ruby + +$VERBOSE = true + +$: << "../lib" + +require 'zip/zip' +require 'find' + +module Zip + module ZipFind + def self.find(path, zipFilePattern = /\.zip$/i) + Find.find(path) { + |fileName| + yield(fileName) + if zipFilePattern.match(fileName) && File.file?(fileName) + begin + Zip::ZipFile.foreach(fileName) { + |zipEntry| + yield(fileName + File::SEPARATOR + zipEntry.to_s) + } + rescue Errno::EACCES => ex + puts ex + end + end + } + end + + def self.find_file(path, fileNamePattern, zipFilePattern = /\.zip$/i) + self.find(path, zipFilePattern) { + |fileName| + yield(fileName) if fileNamePattern.match(fileName) + } + end + + end +end + +if __FILE__ == $0 + module ZipFindConsoleRunner + + PATH_ARG_INDEX = 0; + FILENAME_PATTERN_ARG_INDEX = 1; + ZIPFILE_PATTERN_ARG_INDEX = 2; + + def self.run(args) + check_args(args) + Zip::ZipFind.find_file(args[PATH_ARG_INDEX], + args[FILENAME_PATTERN_ARG_INDEX], + args[ZIPFILE_PATTERN_ARG_INDEX]) { + |fileName| + report_entry_found fileName + } + end + + def self.check_args(args) + if (args.size != 3) + usage + exit + end + end + + def self.usage + puts "Usage: #{$0} PATH ZIPFILENAME_PATTERN FILNAME_PATTERN" + end + + def self.report_entry_found(fileName) + puts fileName + end + + end + + ZipFindConsoleRunner.run(ARGV) +end diff --git a/vendor/plugins/rubyzip-0.9.1/test/alltests.rb b/vendor/plugins/rubyzip-0.9.1/test/alltests.rb new file mode 100755 index 00000000..691349af --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/test/alltests.rb @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby + +$VERBOSE = true + +require 'stdrubyexttest' +require 'ioextrastest' +require 'ziptest' +require 'zipfilesystemtest' +require 'ziprequiretest' diff --git a/vendor/plugins/rubyzip-0.9.1/test/data/file1.txt b/vendor/plugins/rubyzip-0.9.1/test/data/file1.txt new file mode 100644 index 00000000..23ea2f73 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/test/data/file1.txt @@ -0,0 +1,46 @@ + +AUTOMAKE_OPTIONS = gnu + +EXTRA_DIST = test.zip + +CXXFLAGS= -g + +noinst_LIBRARIES = libzipios.a + +bin_PROGRAMS = test_zip test_izipfilt test_izipstream +# test_flist + +libzipios_a_SOURCES = backbuffer.h fcol.cpp fcol.h \ + fcol_common.h fcolexceptions.cpp fcolexceptions.h \ + fileentry.cpp fileentry.h flist.cpp \ + flist.h flistentry.cpp flistentry.h \ + flistscanner.h ifiltstreambuf.cpp ifiltstreambuf.h \ + inflatefilt.cpp inflatefilt.h izipfilt.cpp \ + izipfilt.h izipstream.cpp izipstream.h \ + zipfile.cpp zipfile.h ziphead.cpp \ + ziphead.h flistscanner.ll + +# test_flist_SOURCES = test_flist.cpp + +test_izipfilt_SOURCES = test_izipfilt.cpp + +test_izipstream_SOURCES = test_izipstream.cpp + +test_zip_SOURCES = test_zip.cpp + +# Notice that libzipios.a is not specified as -L. -lzipios +# If it was, automake would not include it as a dependency. + +# test_flist_LDADD = libzipios.a + +test_izipfilt_LDADD = libzipios.a -lz + +test_zip_LDADD = libzipios.a -lz + +test_izipstream_LDADD = libzipios.a -lz + + + +flistscanner.cc : flistscanner.ll + $(LEX) -+ -PFListScanner -o$@ $^ + diff --git a/vendor/plugins/rubyzip-0.9.1/test/data/file1.txt.deflatedData b/vendor/plugins/rubyzip-0.9.1/test/data/file1.txt.deflatedData new file mode 100644 index 00000000..bfbb4f42 Binary files /dev/null and b/vendor/plugins/rubyzip-0.9.1/test/data/file1.txt.deflatedData differ diff --git a/vendor/plugins/rubyzip-0.9.1/test/data/file2.txt b/vendor/plugins/rubyzip-0.9.1/test/data/file2.txt new file mode 100644 index 00000000..cc9ef6ad --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/test/data/file2.txt @@ -0,0 +1,1504 @@ +#!/usr/bin/env ruby + +$VERBOSE = true + +require 'rubyunit' +require 'zip' + +include Zip + +Dir.chdir "test" + +class AbstractInputStreamTest < RUNIT::TestCase + # AbstractInputStream subclass that provides a read method + + TEST_LINES = [ "Hello world#{$/}", + "this is the second line#{$/}", + "this is the last line"] + TEST_STRING = TEST_LINES.join + class TestAbstractInputStream + include AbstractInputStream + def initialize(aString) + @contents = aString + @readPointer = 0 + end + + def read(charsToRead) + retVal=@contents[@readPointer, charsToRead] + @readPointer+=charsToRead + return retVal + end + + def produceInput + read(100) + end + + def inputFinished? + @contents[@readPointer] == nil + end + end + + def setup + @io = TestAbstractInputStream.new(TEST_STRING) + end + + def test_gets + assert_equals(TEST_LINES[0], @io.gets) + assert_equals(TEST_LINES[1], @io.gets) + assert_equals(TEST_LINES[2], @io.gets) + assert_equals(nil, @io.gets) + end + + def test_getsMultiCharSeperator + assert_equals("Hell", @io.gets("ll")) + assert_equals("o world#{$/}this is the second l", @io.gets("d l")) + end + + def test_each_line + lineNumber=0 + @io.each_line { + |line| + assert_equals(TEST_LINES[lineNumber], line) + lineNumber+=1 + } + end + + def test_readlines + assert_equals(TEST_LINES, @io.readlines) + end + + def test_readline + test_gets + begin + @io.readline + fail "EOFError expected" + rescue EOFError + end + end +end + +class ZipEntryTest < RUNIT::TestCase + TEST_ZIPFILE = "someZipFile.zip" + TEST_COMMENT = "a comment" + TEST_COMPRESSED_SIZE = 1234 + TEST_CRC = 325324 + TEST_EXTRA = "Some data here" + TEST_COMPRESSIONMETHOD = ZipEntry::DEFLATED + TEST_NAME = "entry name" + TEST_SIZE = 8432 + TEST_ISDIRECTORY = false + + def test_constructorAndGetters + entry = ZipEntry.new(TEST_ZIPFILE, + TEST_NAME, + TEST_COMMENT, + TEST_EXTRA, + TEST_COMPRESSED_SIZE, + TEST_CRC, + TEST_COMPRESSIONMETHOD, + TEST_SIZE) + + assert_equals(TEST_COMMENT, entry.comment) + assert_equals(TEST_COMPRESSED_SIZE, entry.compressedSize) + assert_equals(TEST_CRC, entry.crc) + assert_equals(TEST_EXTRA, entry.extra) + assert_equals(TEST_COMPRESSIONMETHOD, entry.compressionMethod) + assert_equals(TEST_NAME, entry.name) + assert_equals(TEST_SIZE, entry.size) + assert_equals(TEST_ISDIRECTORY, entry.isDirectory) + end + + def test_equality + entry1 = ZipEntry.new("file.zip", "name", "isNotCompared", + "something extra", 123, 1234, + ZipEntry::DEFLATED, 10000) + entry2 = ZipEntry.new("file.zip", "name", "isNotComparedXXX", + "something extra", 123, 1234, + ZipEntry::DEFLATED, 10000) + entry3 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extra", 123, 1234, + ZipEntry::DEFLATED, 10000) + entry4 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extraXX", 123, 1234, + ZipEntry::DEFLATED, 10000) + entry5 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extraXX", 12, 1234, + ZipEntry::DEFLATED, 10000) + entry6 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extraXX", 12, 123, + ZipEntry::DEFLATED, 10000) + entry7 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extraXX", 12, 123, + ZipEntry::STORED, 10000) + entry8 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extraXX", 12, 123, + ZipEntry::STORED, 100000) + + assert_equals(entry1, entry1) + assert_equals(entry1, entry2) + + assert(entry2 != entry3) + assert(entry3 != entry4) + assert(entry4 != entry5) + assert(entry5 != entry6) + assert(entry6 != entry7) + assert(entry7 != entry8) + + assert(entry7 != "hello") + assert(entry7 != 12) + end +end + +module IOizeString + attr_reader :tell + + def read(count = nil) + @tell ||= 0 + count = size unless count + retVal = slice(@tell, count) + @tell += count + return retVal + end + + def seek(index, offset) + @tell ||= 0 + case offset + when IO::SEEK_END + newPos = size + index + when IO::SEEK_SET + newPos = index + when IO::SEEK_CUR + newPos = @tell + index + else + raise "Error in test method IOizeString::seek" + end + if (newPos < 0 || newPos >= size) + raise Errno::EINVAL + else + @tell=newPos + end + end + + def reset + @tell = 0 + end +end + +class ZipLocalEntryTest < RUNIT::TestCase + def test_readLocalEntryHeaderOfFirstTestZipEntry + File.open(TestZipFile::TEST_ZIP3.zipName) { + |file| + entry = ZipEntry.readLocalEntry(file) + + assert_equal("", entry.comment) + # Differs from windows and unix because of CR LF + # assert_equal(480, entry.compressedSize) + # assert_equal(0x2a27930f, entry.crc) + # extra field is 21 bytes long + # probably contains some unix attrutes or something + # disabled: assert_equal(nil, entry.extra) + assert_equal(ZipEntry::DEFLATED, entry.compressionMethod) + assert_equal(TestZipFile::TEST_ZIP3.entryNames[0], entry.name) + assert_equal(File.size(TestZipFile::TEST_ZIP3.entryNames[0]), entry.size) + assert(! entry.isDirectory) + } + end + + def test_readLocalEntryFromNonZipFile + File.open("ziptest.rb") { + |file| + assert_equals(nil, ZipEntry.readLocalEntry(file)) + } + end + + def test_readLocalEntryFromTruncatedZipFile + zipFragment="" + File.open(TestZipFile::TEST_ZIP2.zipName) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes + zipFragment.extend(IOizeString).reset + entry = ZipEntry.new + entry.readLocalEntry(zipFragment) + fail "ZipError expected" + rescue ZipError + end + + def test_writeEntry + entry = ZipEntry.new("file.zip", "entryName", "my little comment", + "thisIsSomeExtraInformation", 100, 987654, + ZipEntry::DEFLATED, 400) + writeToFile("localEntryHeader.bin", "centralEntryHeader.bin", entry) + entryReadLocal, entryReadCentral = readFromFile("localEntryHeader.bin", "centralEntryHeader.bin") + compareLocalEntryHeaders(entry, entryReadLocal) + compareCDirEntryHeaders(entry, entryReadCentral) + end + + private + def compareLocalEntryHeaders(entry1, entry2) + assert_equals(entry1.compressedSize , entry2.compressedSize) + assert_equals(entry1.crc , entry2.crc) + assert_equals(entry1.extra , entry2.extra) + assert_equals(entry1.compressionMethod, entry2.compressionMethod) + assert_equals(entry1.name , entry2.name) + assert_equals(entry1.size , entry2.size) + assert_equals(entry1.localHeaderOffset, entry2.localHeaderOffset) + end + + def compareCDirEntryHeaders(entry1, entry2) + compareLocalEntryHeaders(entry1, entry2) + assert_equals(entry1.comment, entry2.comment) + end + + def writeToFile(localFileName, centralFileName, entry) + File.open(localFileName, "wb") { |f| entry.writeLocalEntry(f) } + File.open(centralFileName, "wb") { |f| entry.writeCDirEntry(f) } + end + + def readFromFile(localFileName, centralFileName) + localEntry = nil + cdirEntry = nil + File.open(localFileName, "rb") { |f| localEntry = ZipEntry.readLocalEntry(f) } + File.open(centralFileName, "rb") { |f| cdirEntry = ZipEntry.readCDirEntry(f) } + return [localEntry, cdirEntry] + end +end + + +module DecompressorTests + # expects @refText and @decompressor + + def test_readEverything + assert_equals(@refText, @decompressor.read) + end + + def test_readInChunks + chunkSize = 5 + while (decompressedChunk = @decompressor.read(chunkSize)) + assert_equals(@refText.slice!(0, chunkSize), decompressedChunk) + end + assert_equals(0, @refText.size) + end +end + +class InflaterTest < RUNIT::TestCase + include DecompressorTests + + def setup + @file = File.new("file1.txt.deflatedData", "rb") + @refText="" + File.open("file1.txt") { |f| @refText = f.read } + @decompressor = Inflater.new(@file) + end + + def teardown + @file.close + end +end + + +class PassThruDecompressorTest < RUNIT::TestCase + include DecompressorTests + TEST_FILE="file1.txt" + def setup + @file = File.new(TEST_FILE) + @refText="" + File.open(TEST_FILE) { |f| @refText = f.read } + @decompressor = PassThruDecompressor.new(@file, File.size(TEST_FILE)) + end + + def teardown + @file.close + end +end + + +module AssertEntry + def assertNextEntry(filename, zis) + assertEntry(filename, zis, zis.getNextEntry.name) + end + + def assertEntry(filename, zis, entryName) + assert_equals(filename, entryName) + assertEntryContentsForStream(filename, zis, entryName) + end + + def assertEntryContentsForStream(filename, zis, entryName) + File.open(filename, "rb") { + |file| + expected = file.read + actual = zis.read + if (expected != actual) + if (expected.length > 400 || actual.length > 400) + zipEntryFilename=entryName+".zipEntry" + File.open(zipEntryFilename, "wb") { |file| file << actual } + fail("File '#{filename}' is different from '#{zipEntryFilename}'") + else + assert_equals(expected, actual) + end + end + } + end + + def AssertEntry.assertContents(filename, aString) + fileContents = "" + File.open(filename, "rb") { |f| fileContents = f.read } + if (fileContents != aString) + if (expected.length > 400 || actual.length > 400) + stringFile = filename + ".other" + File.open(stringFile, "wb") { |f| f << aString } + fail("File '#{filename}' is different from contents of string stored in '#{stringFile}'") + else + assert_equals(expected, actual) + end + end + end + + def assertStreamContents(zis, testZipFile) + assert(zis != nil) + testZipFile.entryNames.each { + |entryName| + assertNextEntry(entryName, zis) + } + assert_equals(nil, zis.getNextEntry) + end + + def assertTestZipContents(testZipFile) + ZipInputStream.open(testZipFile.zipName) { + |zis| + assertStreamContents(zis, testZipFile) + } + end + + def assertEntryContents(zipFile, entryName, filename = entryName.to_s) + zis = zipFile.getInputStream(entryName) + assertEntryContentsForStream(filename, zis, entryName) + ensure + zis.close if zis + end +end + + + +class ZipInputStreamTest < RUNIT::TestCase + include AssertEntry + + def test_new + zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zipName) + assertStreamContents(zis, TestZipFile::TEST_ZIP2) + zis.close + end + + def test_openWithBlock + ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) { + |zis| + assertStreamContents(zis, TestZipFile::TEST_ZIP2) + } + end + + def test_openWithoutBlock + zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) + assertStreamContents(zis, TestZipFile::TEST_ZIP2) + end + + def test_incompleteReads + ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) { + |zis| + entry = zis.getNextEntry + assert_equals(TestZipFile::TEST_ZIP2.entryNames[0], entry.name) + assert zis.gets.length > 0 + entry = zis.getNextEntry + assert_equals(TestZipFile::TEST_ZIP2.entryNames[1], entry.name) + assert_equals(0, entry.size) + assert_equals(nil, zis.gets) + entry = zis.getNextEntry + assert_equals(TestZipFile::TEST_ZIP2.entryNames[2], entry.name) + assert zis.gets.length > 0 + entry = zis.getNextEntry + assert_equals(TestZipFile::TEST_ZIP2.entryNames[3], entry.name) + assert zis.gets.length > 0 + } + end + +end + +class TestFiles + RANDOM_ASCII_FILE1 = "randomAscii1.txt" + RANDOM_ASCII_FILE2 = "randomAscii2.txt" + RANDOM_ASCII_FILE3 = "randomAscii3.txt" + RANDOM_BINARY_FILE1 = "randomBinary1.bin" + RANDOM_BINARY_FILE2 = "randomBinary2.bin" + + EMPTY_TEST_DIR = "emptytestdir" + + ASCII_TEST_FILES = [ RANDOM_ASCII_FILE1, RANDOM_ASCII_FILE2, RANDOM_ASCII_FILE3 ] + BINARY_TEST_FILES = [ RANDOM_BINARY_FILE1, RANDOM_BINARY_FILE2 ] + TEST_DIRECTORIES = [ EMPTY_TEST_DIR ] + TEST_FILES = [ ASCII_TEST_FILES, BINARY_TEST_FILES, EMPTY_TEST_DIR ].flatten! + + def TestFiles.createTestFiles(recreate) + if (recreate || + ! (TEST_FILES.inject(true) { |accum, element| accum && File.exists?(element) })) + + ASCII_TEST_FILES.each_with_index { + |filename, index| + createRandomAscii(filename, 1E4 * (index+1)) + } + + BINARY_TEST_FILES.each_with_index { + |filename, index| + createRandomBinary(filename, 1E4 * (index+1)) + } + + ensureDir(EMPTY_TEST_DIR) + end + end + + private + def TestFiles.createRandomAscii(filename, size) + File.open(filename, "wb") { + |file| + while (file.tell < size) + file << rand + end + } + end + + def TestFiles.createRandomBinary(filename, size) + File.open(filename, "wb") { + |file| + while (file.tell < size) + file << rand.to_a.pack("V") + end + } + end + + def TestFiles.ensureDir(name) + if File.exists?(name) + return if File.stat(name).directory? + File.delete(name) + end + Dir.mkdir(name) + end + +end + +# For representation and creation of +# test data +class TestZipFile + attr_accessor :zipName, :entryNames, :comment + + def initialize(zipName, entryNames, comment = "") + @zipName=zipName + @entryNames=entryNames + @comment = comment + end + + def TestZipFile.createTestZips(recreate) + files = Dir.entries(".") + if (recreate || + ! (files.index(TEST_ZIP1.zipName) && + files.index(TEST_ZIP2.zipName) && + files.index(TEST_ZIP3.zipName) && + files.index(TEST_ZIP4.zipName) && + files.index("empty.txt") && + files.index("short.txt") && + files.index("longAscii.txt") && + files.index("longBinary.bin") )) + raise "failed to create test zip '#{TEST_ZIP1.zipName}'" unless + system("zip #{TEST_ZIP1.zipName} ziptest.rb") + raise "failed to remove entry from '#{TEST_ZIP1.zipName}'" unless + system("zip #{TEST_ZIP1.zipName} -d ziptest.rb") + + File.open("empty.txt", "w") {} + + File.open("short.txt", "w") { |file| file << "ABCDEF" } + ziptestTxt="" + File.open("ziptest.rb") { |file| ziptestTxt=file.read } + File.open("longAscii.txt", "w") { + |file| + while (file.tell < 1E5) + file << ziptestTxt + end + } + + testBinaryPattern="" + File.open("empty.zip") { |file| testBinaryPattern=file.read } + testBinaryPattern *= 4 + + File.open("longBinary.bin", "wb") { + |file| + while (file.tell < 3E5) + file << testBinaryPattern << rand + end + } + raise "failed to create test zip '#{TEST_ZIP2.zipName}'" unless + system("zip #{TEST_ZIP2.zipName} #{TEST_ZIP2.entryNames.join(' ')}") + + # without bash system interprets everything after echo as parameters to + # echo including | zip -z ... + raise "failed to add comment to test zip '#{TEST_ZIP2.zipName}'" unless + system("bash -c \"echo #{TEST_ZIP2.comment} | zip -z #{TEST_ZIP2.zipName}\"") + + raise "failed to create test zip '#{TEST_ZIP3.zipName}'" unless + system("zip #{TEST_ZIP3.zipName} #{TEST_ZIP3.entryNames.join(' ')}") + + raise "failed to create test zip '#{TEST_ZIP4.zipName}'" unless + system("zip #{TEST_ZIP4.zipName} #{TEST_ZIP4.entryNames.join(' ')}") + end + rescue + raise $!.to_s + + "\n\nziptest.rb requires the Info-ZIP program 'zip' in the path\n" + + "to create test data. If you don't have it you can download\n" + + "the necessary test files at http://sf.net/projects/rubyzip." + end + + TEST_ZIP1 = TestZipFile.new("empty.zip", []) + TEST_ZIP2 = TestZipFile.new("4entry.zip", %w{ longAscii.txt empty.txt short.txt longBinary.bin}, + "my zip comment") + TEST_ZIP3 = TestZipFile.new("test1.zip", %w{ file1.txt }) + TEST_ZIP4 = TestZipFile.new("zipWithDir.zip", [ "file1.txt", + TestFiles::EMPTY_TEST_DIR]) +end + + +class AbstractOutputStreamTest < RUNIT::TestCase + class TestOutputStream + include AbstractOutputStream + + attr_accessor :buffer + + def initialize + @buffer = "" + end + + def << (data) + @buffer << data + self + end + end + + def setup + @outputStream = TestOutputStream.new + + @origCommaSep = $, + @origOutputSep = $\ + end + + def teardown + $, = @origCommaSep + $\ = @origOutputSep + end + + def test_write + count = @outputStream.write("a little string") + assert_equals("a little string", @outputStream.buffer) + assert_equals("a little string".length, count) + + count = @outputStream.write(". a little more") + assert_equals("a little string. a little more", @outputStream.buffer) + assert_equals(". a little more".length, count) + end + + def test_print + $\ = nil # record separator set to nil + @outputStream.print("hello") + assert_equals("hello", @outputStream.buffer) + + @outputStream.print(" world.") + assert_equals("hello world.", @outputStream.buffer) + + @outputStream.print(" You ok ", "out ", "there?") + assert_equals("hello world. You ok out there?", @outputStream.buffer) + + $\ = "\n" + @outputStream.print + assert_equals("hello world. You ok out there?\n", @outputStream.buffer) + + @outputStream.print("I sure hope so!") + assert_equals("hello world. You ok out there?\nI sure hope so!\n", @outputStream.buffer) + + $, = "X" + @outputStream.buffer = "" + @outputStream.print("monkey", "duck", "zebra") + assert_equals("monkeyXduckXzebra\n", @outputStream.buffer) + + $\ = nil + @outputStream.buffer = "" + @outputStream.print(20) + assert_equals("20", @outputStream.buffer) + end + + def test_printf + @outputStream.printf("%d %04x", 123, 123) + assert_equals("123 007b", @outputStream.buffer) + end + + def test_putc + @outputStream.putc("A") + assert_equals("A", @outputStream.buffer) + @outputStream.putc(65) + assert_equals("AA", @outputStream.buffer) + end + + def test_puts + @outputStream.puts + assert_equals("\n", @outputStream.buffer) + + @outputStream.puts("hello", "world") + assert_equals("\nhello\nworld\n", @outputStream.buffer) + + @outputStream.buffer = "" + @outputStream.puts("hello\n", "world\n") + assert_equals("hello\nworld\n", @outputStream.buffer) + + @outputStream.buffer = "" + @outputStream.puts(["hello\n", "world\n"]) + assert_equals("hello\nworld\n", @outputStream.buffer) + + @outputStream.buffer = "" + @outputStream.puts(["hello\n", "world\n"], "bingo") + assert_equals("hello\nworld\nbingo\n", @outputStream.buffer) + + @outputStream.buffer = "" + @outputStream.puts(16, 20, 50, "hello") + assert_equals("16\n20\n50\nhello\n", @outputStream.buffer) + end +end + + +module CrcTest + def runCrcTest(compressorClass) + str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed." + fakeOut = AbstractOutputStreamTest::TestOutputStream.new + + deflater = compressorClass.new(fakeOut) + deflater << str + assert_equals(0x919920fc, deflater.crc) + end +end + + + +class PassThruCompressorTest < RUNIT::TestCase + include CrcTest + + def test_size + File.open("dummy.txt", "wb") { + |file| + compressor = PassThruCompressor.new(file) + + assert_equals(0, compressor.size) + + t1 = "hello world" + t2 = "" + t3 = "bingo" + + compressor << t1 + assert_equals(compressor.size, t1.size) + + compressor << t2 + assert_equals(compressor.size, t1.size + t2.size) + + compressor << t3 + assert_equals(compressor.size, t1.size + t2.size + t3.size) + } + end + + def test_crc + runCrcTest(PassThruCompressor) + end +end + +class DeflaterTest < RUNIT::TestCase + include CrcTest + + def test_outputOperator + txt = loadFile("ziptest.rb") + deflate(txt, "deflatertest.bin") + inflatedTxt = inflate("deflatertest.bin") + assert_equals(txt, inflatedTxt) + end + + private + def loadFile(fileName) + txt = nil + File.open(fileName, "rb") { |f| txt = f.read } + end + + def deflate(data, fileName) + File.open(fileName, "wb") { + |file| + deflater = Deflater.new(file) + deflater << data + deflater.finish + assert_equals(deflater.size, data.size) + file << "trailing data for zlib with -MAX_WBITS" + } + end + + def inflate(fileName) + txt = nil + File.open(fileName, "rb") { + |file| + inflater = Inflater.new(file) + txt = inflater.read + } + end + + def test_crc + runCrcTest(Deflater) + end +end + +class ZipOutputStreamTest < RUNIT::TestCase + include AssertEntry + + TEST_ZIP = TestZipFile::TEST_ZIP2.clone + TEST_ZIP.zipName = "output.zip" + + def test_new + zos = ZipOutputStream.new(TEST_ZIP.zipName) + zos.comment = TEST_ZIP.comment + writeTestZip(zos) + zos.close + assertTestZipContents(TEST_ZIP) + end + + def test_open + ZipOutputStream.open(TEST_ZIP.zipName) { + |zos| + zos.comment = TEST_ZIP.comment + writeTestZip(zos) + } + assertTestZipContents(TEST_ZIP) + end + + def test_writingToClosedStream + assertIOErrorInClosedStream { |zos| zos << "hello world" } + assertIOErrorInClosedStream { |zos| zos.puts "hello world" } + assertIOErrorInClosedStream { |zos| zos.write "hello world" } + end + + def test_cannotOpenFile + name = TestFiles::EMPTY_TEST_DIR + begin + zos = ZipOutputStream.open(name) + rescue Exception + assert($!.kind_of?(Errno::EISDIR) || # Linux + $!.kind_of?(Errno::EEXIST) || # Windows/cygwin + $!.kind_of?(Errno::EACCES), # Windows + "Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.type}") + end + end + + def assertIOErrorInClosedStream + assert_exception(IOError) { + zos = ZipOutputStream.new("test_putOnClosedStream.zip") + zos.close + yield zos + } + end + + def writeTestZip(zos) + TEST_ZIP.entryNames.each { + |entryName| + zos.putNextEntry(entryName) + File.open(entryName, "rb") { |f| zos.write(f.read) } + } + end +end + + + +module Enumerable + def compareEnumerables(otherEnumerable) + otherAsArray = otherEnumerable.to_a + index=0 + each_with_index { + |element, index| + return false unless yield(element, otherAsArray[index]) + } + return index+1 == otherAsArray.size + end +end + + +class ZipCentralDirectoryEntryTest < RUNIT::TestCase + + def test_readFromStream + File.open("testDirectory.bin", "rb") { + |file| + entry = ZipEntry.readCDirEntry(file) + + assert_equals("longAscii.txt", entry.name) + assert_equals(ZipEntry::DEFLATED, entry.compressionMethod) + assert_equals(106490, entry.size) + assert_equals(3784, entry.compressedSize) + assert_equals(0xfcd1799c, entry.crc) + assert_equals("", entry.comment) + + entry = ZipEntry.readCDirEntry(file) + assert_equals("empty.txt", entry.name) + assert_equals(ZipEntry::STORED, entry.compressionMethod) + assert_equals(0, entry.size) + assert_equals(0, entry.compressedSize) + assert_equals(0x0, entry.crc) + assert_equals("", entry.comment) + + entry = ZipEntry.readCDirEntry(file) + assert_equals("short.txt", entry.name) + assert_equals(ZipEntry::STORED, entry.compressionMethod) + assert_equals(6, entry.size) + assert_equals(6, entry.compressedSize) + assert_equals(0xbb76fe69, entry.crc) + assert_equals("", entry.comment) + + entry = ZipEntry.readCDirEntry(file) + assert_equals("longBinary.bin", entry.name) + assert_equals(ZipEntry::DEFLATED, entry.compressionMethod) + assert_equals(1000024, entry.size) + assert_equals(70847, entry.compressedSize) + assert_equals(0x10da7d59, entry.crc) + assert_equals("", entry.comment) + + entry = ZipEntry.readCDirEntry(file) + assert_equals(nil, entry) +# Fields that are not check by this test: +# version made by 2 bytes +# version needed to extract 2 bytes +# general purpose bit flag 2 bytes +# last mod file time 2 bytes +# last mod file date 2 bytes +# compressed size 4 bytes +# uncompressed size 4 bytes +# disk number start 2 bytes +# internal file attributes 2 bytes +# external file attributes 4 bytes +# relative offset of local header 4 bytes + +# file name (variable size) +# extra field (variable size) +# file comment (variable size) + + } + end + + def test_ReadEntryFromTruncatedZipFile + fragment="" + File.open("testDirectory.bin") { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes + fragment.extend(IOizeString) + entry = ZipEntry.new + entry.readCDirEntry(fragment) + fail "ZipError expected" + rescue ZipError + end + +end + +class ZipCentralDirectoryTest < RUNIT::TestCase + + def test_readFromStream + File.open(TestZipFile::TEST_ZIP2.zipName, "rb") { + |zipFile| + cdir = ZipCentralDirectory.readFromStream(zipFile) + + assert_equals(TestZipFile::TEST_ZIP2.entryNames.size, cdir.size) + assert(cdir.compareEnumerables(TestZipFile::TEST_ZIP2.entryNames) { + |cdirEntry, testEntryName| + cdirEntry.name == testEntryName + }) + assert_equals(TestZipFile::TEST_ZIP2.comment, cdir.comment) + } + end + + def test_readFromInvalidStream + File.open("ziptest.rb", "rb") { + |zipFile| + cdir = ZipCentralDirectory.new + cdir.readFromStream(zipFile) + } + fail "ZipError expected!" + rescue ZipError + end + + def test_ReadFromTruncatedZipFile + fragment="" + File.open("testDirectory.bin") { |f| fragment = f.read } + fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete + fragment.extend(IOizeString) + entry = ZipCentralDirectory.new + entry.readFromStream(fragment) + fail "ZipError expected" + rescue ZipError + end + + def test_writeToStream + entries = [ ZipEntry.new("file.zip", "flimse", "myComment", "somethingExtra"), + ZipEntry.new("file.zip", "secondEntryName"), + ZipEntry.new("file.zip", "lastEntry.txt", "Has a comment too") ] + cdir = ZipCentralDirectory.new(entries, "my zip comment") + File.open("cdirtest.bin", "wb") { |f| cdir.writeToStream(f) } + cdirReadback = ZipCentralDirectory.new + File.open("cdirtest.bin", "rb") { |f| cdirReadback.readFromStream(f) } + + assert_equals(cdir.entries, cdirReadback.entries) + end + + def test_equality + cdir1 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, + "somethingExtra"), + ZipEntry.new("file.zip", "secondEntryName"), + ZipEntry.new("file.zip", "lastEntry.txt") ], + "my zip comment") + cdir2 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, + "somethingExtra"), + ZipEntry.new("file.zip", "secondEntryName"), + ZipEntry.new("file.zip", "lastEntry.txt") ], + "my zip comment") + cdir3 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, + "somethingExtra"), + ZipEntry.new("file.zip", "secondEntryName"), + ZipEntry.new("file.zip", "lastEntry.txt") ], + "comment?") + cdir4 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, + "somethingExtra"), + ZipEntry.new("file.zip", "lastEntry.txt") ], + "comment?") + assert_equals(cdir1, cdir1) + assert_equals(cdir1, cdir2) + + assert(cdir1 != cdir3) + assert(cdir2 != cdir3) + assert(cdir2 != cdir3) + assert(cdir3 != cdir4) + + assert(cdir3 != "hello") + end +end + + +class BasicZipFileTest < RUNIT::TestCase + include AssertEntry + + def setup + @zipFile = ZipFile.new(TestZipFile::TEST_ZIP2.zipName) + @testEntryNameIndex=0 + end + + def nextTestEntryName + retVal=TestZipFile::TEST_ZIP2.entryNames[@testEntryNameIndex] + @testEntryNameIndex+=1 + return retVal + end + + def test_entries + assert_equals(TestZipFile::TEST_ZIP2.entryNames, @zipFile.entries.map {|e| e.name} ) + end + + def test_each + @zipFile.each { + |entry| + assert_equals(nextTestEntryName, entry.name) + } + assert_equals(4, @testEntryNameIndex) + end + + def test_foreach + ZipFile.foreach(TestZipFile::TEST_ZIP2.zipName) { + |entry| + assert_equals(nextTestEntryName, entry.name) + } + assert_equals(4, @testEntryNameIndex) + end + + def test_getInputStream + @zipFile.each { + |entry| + assertEntry(nextTestEntryName, @zipFile.getInputStream(entry), + entry.name) + } + assert_equals(4, @testEntryNameIndex) + end + + def test_getInputStreamBlock + fileAndEntryName = @zipFile.entries.first.name + @zipFile.getInputStream(fileAndEntryName) { + |zis| + assertEntryContentsForStream(fileAndEntryName, + zis, + fileAndEntryName) + } + end +end + +class CommonZipFileFixture < RUNIT::TestCase + include AssertEntry + + EMPTY_FILENAME = "emptyZipFile.zip" + + TEST_ZIP = TestZipFile::TEST_ZIP2.clone + TEST_ZIP.zipName = "4entry_copy.zip" + + def setup + File.delete(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME) + File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName) + end +end + +class ZipFileTest < CommonZipFileFixture + + def test_createFromScratch + comment = "a short comment" + + zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) + zf.comment = comment + zf.close + + zfRead = ZipFile.new(EMPTY_FILENAME) + assert_equals(comment, zfRead.comment) + assert_equals(0, zfRead.entries.length) + end + + def test_add + srcFile = "ziptest.rb" + entryName = "newEntryName.rb" + assert(File.exists? srcFile) + zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) + zf.add(entryName, srcFile) + zf.close + + zfRead = ZipFile.new(EMPTY_FILENAME) + assert_equals("", zfRead.comment) + assert_equals(1, zfRead.entries.length) + assert_equals(entryName, zfRead.entries.first.name) + AssertEntry.assertContents(srcFile, + zfRead.getInputStream(entryName) { |zis| zis.read }) + end + + def test_addExistingEntryName + assert_exception(ZipEntryExistsError) { + ZipFile.open(TEST_ZIP.zipName) { + |zf| + zf.add(zf.entries.first.name, "ziptest.rb") + } + } + end + + def test_addExistingEntryNameReplace + gotCalled = false + replacedEntry = nil + ZipFile.open(TEST_ZIP.zipName) { + |zf| + replacedEntry = zf.entries.first.name + zf.add(replacedEntry, "ziptest.rb") { gotCalled = true; true } + } + assert(gotCalled) + ZipFile.open(TEST_ZIP.zipName) { + |zf| + assertContains(zf, replacedEntry, "ziptest.rb") + } + end + + def test_addDirectory + ZipFile.open(TEST_ZIP.zipName) { + |zf| + zf.add(TestFiles::EMPTY_TEST_DIR, TestFiles::EMPTY_TEST_DIR) + } + ZipFile.open(TEST_ZIP.zipName) { + |zf| + dirEntry = zf.entries.detect { |e| e.name == TestFiles::EMPTY_TEST_DIR+"/" } + assert(dirEntry.isDirectory) + } + end + + def test_remove + entryToRemove, *remainingEntries = TEST_ZIP.entryNames + + File.copy(TestZipFile::TEST_ZIP2.zipName, TEST_ZIP.zipName) + + zf = ZipFile.new(TEST_ZIP.zipName) + assert(zf.entries.map { |e| e.name }.include?(entryToRemove)) + zf.remove(entryToRemove) + assert(! zf.entries.map { |e| e.name }.include?(entryToRemove)) + assert_equals(zf.entries.map {|x| x.name }.sort, remainingEntries.sort) + zf.close + + zfRead = ZipFile.new(TEST_ZIP.zipName) + assert(! zfRead.entries.map { |e| e.name }.include?(entryToRemove)) + assert_equals(zfRead.entries.map {|x| x.name }.sort, remainingEntries.sort) + zfRead.close + end + + + def test_rename + entryToRename, *remainingEntries = TEST_ZIP.entryNames + + zf = ZipFile.new(TEST_ZIP.zipName) + assert(zf.entries.map { |e| e.name }.include? entryToRename) + + newName = "changed name" + assert(! zf.entries.map { |e| e.name }.include?(newName)) + + zf.rename(entryToRename, newName) + assert(zf.entries.map { |e| e.name }.include? newName) + + zf.close + + zfRead = ZipFile.new(TEST_ZIP.zipName) + assert(zfRead.entries.map { |e| e.name }.include? newName) + zfRead.close + end + + def test_renameToExistingEntry + oldEntries = nil + ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries } + + assert_exception(ZipEntryExistsError) { + ZipFile.open(TEST_ZIP.zipName) { + |zf| + zf.rename(zf.entries[0], zf.entries[1].name) + } + } + + ZipFile.open(TEST_ZIP.zipName) { + |zf| + assert_equals(oldEntries.map{ |e| e.name }, zf.entries.map{ |e| e.name }) + } + end + + def test_renameToExistingEntryOverwrite + oldEntries = nil + ZipFile.open(TEST_ZIP.zipName) { |zf| oldEntries = zf.entries } + + gotCalled = false + ZipFile.open(TEST_ZIP.zipName) { + |zf| + zf.rename(zf.entries[0], zf.entries[1].name) { gotCalled = true; true } + } + + assert(gotCalled) + oldEntries.delete_at(0) + ZipFile.open(TEST_ZIP.zipName) { + |zf| + assert_equals(oldEntries.map{ |e| e.name }, + zf.entries.map{ |e| e.name }) + } + end + + def test_renameNonEntry + nonEntry = "bogusEntry" + targetEntry = "targetEntryName" + zf = ZipFile.new(TEST_ZIP.zipName) + assert(! zf.entries.include?(nonEntry)) + assert_exception(ZipNoSuchEntryError) { + zf.rename(nonEntry, targetEntry) + } + zf.commit + assert(! zf.entries.include?(targetEntry)) + ensure + zf.close + end + + def test_renameEntryToExistingEntry + entry1, entry2, *remaining = TEST_ZIP.entryNames + zf = ZipFile.new(TEST_ZIP.zipName) + assert_exception(ZipEntryExistsError) { + zf.rename(entry1, entry2) + } + ensure + zf.close + end + + def test_replace + unchangedEntries = TEST_ZIP.entryNames.dup + entryToReplace = unchangedEntries.delete_at(2) + newEntrySrcFilename = "ziptest.rb" + + zf = ZipFile.new(TEST_ZIP.zipName) + zf.replace(entryToReplace, newEntrySrcFilename) + + zf.close + + zfRead = ZipFile.new(TEST_ZIP.zipName) + AssertEntry::assertContents(newEntrySrcFilename, + zfRead.getInputStream(entryToReplace) { |is| is.read }) + zfRead.close + end + + def test_replaceNonEntry + entryToReplace = "nonExistingEntryname" + ZipFile.open(TEST_ZIP.zipName) { + |zf| + assert_exception(ZipNoSuchEntryError) { + zf.replace(entryToReplace, "ziptest.rb") + } + } + end + + def test_commit + newName = "renamedFirst" + zf = ZipFile.new(TEST_ZIP.zipName) + oldName = zf.entries.first + zf.rename(oldName, newName) + zf.commit + + zfRead = ZipFile.new(TEST_ZIP.zipName) + assert(zfRead.entries.detect { |e| e.name == newName } != nil) + assert(zfRead.entries.detect { |e| e.name == oldName } == nil) + zfRead.close + + zf.close + end + + # This test tests that after commit, you + # can delete the file you used to add the entry to the zip file + # with + def test_commitUseZipEntry + File.copy(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt") + zf = ZipFile.open(TEST_ZIP.zipName) + zf.add("okToDelete.txt", "okToDelete.txt") + assertContains(zf, "okToDelete.txt") + zf.commit + File.move("okToDelete.txt", "okToDeleteMoved.txt") + assertContains(zf, "okToDelete.txt", "okToDeleteMoved.txt") + end + +# def test_close +# zf = ZipFile.new(TEST_ZIP.zipName) +# zf.close +# assert_exception(IOError) { +# zf.extract(TEST_ZIP.entryNames.first, "hullubullu") +# } +# end + + def test_compound1 + renamedName = "renamedName" + originalEntries = [] + begin + zf = ZipFile.new(TEST_ZIP.zipName) + originalEntries = zf.entries.dup + + assertNotContains(zf, TestFiles::RANDOM_ASCII_FILE1) + zf.add(TestFiles::RANDOM_ASCII_FILE1, + TestFiles::RANDOM_ASCII_FILE1) + assertContains(zf, TestFiles::RANDOM_ASCII_FILE1) + + zf.rename(zf.entries[0], renamedName) + assertContains(zf, renamedName) + + TestFiles::BINARY_TEST_FILES.each { + |filename| + zf.add(filename, filename) + assertContains(zf, filename) + } + + assertContains(zf, originalEntries.last.to_s) + zf.remove(originalEntries.last.to_s) + assertNotContains(zf, originalEntries.last.to_s) + + ensure + zf.close + end + begin + zfRead = ZipFile.new(TEST_ZIP.zipName) + assertContains(zfRead, TestFiles::RANDOM_ASCII_FILE1) + assertContains(zfRead, renamedName) + TestFiles::BINARY_TEST_FILES.each { + |filename| + assertContains(zfRead, filename) + } + assertNotContains(zfRead, originalEntries.last.to_s) + ensure + zfRead.close + end + end + + def test_compound2 + begin + zf = ZipFile.new(TEST_ZIP.zipName) + originalEntries = zf.entries.dup + + originalEntries.each { + |entry| + zf.remove(entry) + assertNotContains(zf, entry) + } + assert(zf.entries.empty?) + + TestFiles::ASCII_TEST_FILES.each { + |filename| + zf.add(filename, filename) + assertContains(zf, filename) + } + assert_equals(zf.entries.map { |e| e.name }, TestFiles::ASCII_TEST_FILES) + + zf.rename(TestFiles::ASCII_TEST_FILES[0], "newName") + assertNotContains(zf, TestFiles::ASCII_TEST_FILES[0]) + assertContains(zf, "newName") + ensure + zf.close + end + begin + zfRead = ZipFile.new(TEST_ZIP.zipName) + asciiTestFiles = TestFiles::ASCII_TEST_FILES.dup + asciiTestFiles.shift + asciiTestFiles.each { + |filename| + assertContains(zf, filename) + } + + assertContains(zf, "newName") + ensure + zfRead.close + end + end + + private + def assertContains(zf, entryName, filename = entryName) + assert(zf.entries.detect { |e| e.name == entryName} != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}") + assertEntryContents(zf, entryName, filename) if File.exists?(filename) + end + + def assertNotContains(zf, entryName) + assert(zf.entries.detect { |e| e.name == entryName} == nil, "entry #{entryName} in #{zf.entries.join(', ')} in zip file #{zf}") + end +end + +class ZipFileExtractTest < CommonZipFileFixture + EXTRACTED_FILENAME = "extEntry" + ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entryNames.reverse + + def setup + super + File.delete(EXTRACTED_FILENAME) if File.exists?(EXTRACTED_FILENAME) + end + + def test_extract + ZipFile.open(TEST_ZIP.zipName) { + |zf| + zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME) + + assert(File.exists? EXTRACTED_FILENAME) + AssertEntry::assertContents(EXTRACTED_FILENAME, + zf.getInputStream(ENTRY_TO_EXTRACT) { |is| is.read }) + } + end + + def test_extractExists + writtenText = "written text" + File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } + + assert_exception(ZipDestinationFileExistsError) { + ZipFile.open(TEST_ZIP.zipName) { + |zf| + zf.extract(zf.entries.first, EXTRACTED_FILENAME) + } + } + File.open(EXTRACTED_FILENAME, "r") { + |f| + assert_equals(writtenText, f.read) + } + end + + def test_extractExistsOverwrite + writtenText = "written text" + File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } + + gotCalled = false + ZipFile.open(TEST_ZIP.zipName) { + |zf| + zf.extract(zf.entries.first, EXTRACTED_FILENAME) { gotCalled = true; true } + } + + assert(gotCalled) + File.open(EXTRACTED_FILENAME, "r") { + |f| + assert(writtenText != f.read) + } + end + + def test_extractNonEntry + zf = ZipFile.new(TEST_ZIP.zipName) + assert_exception(ZipNoSuchEntryError) { zf.extract("nonExistingEntry", "nonExistingEntry") } + ensure + zf.close if zf + end + + def test_extractNonEntry2 + outFile = "outfile" + assert_exception(ZipNoSuchEntryError) { + zf = ZipFile.new(TEST_ZIP.zipName) + nonEntry = "hotdog-diddelidoo" + assert(! zf.entries.include?(nonEntry)) + zf.extract(nonEntry, outFile) + zf.close + } + assert(! File.exists?(outFile)) + end + +end + +class ZipFileExtractDirectoryTest < CommonZipFileFixture + TEST_OUT_NAME = "emptyOutDir" + + def openZip(&aProc) + assert(aProc != nil) + ZipFile.open(TestZipFile::TEST_ZIP4.zipName, &aProc) + end + + def extractTestDir(&aProc) + openZip { + |zf| + zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc) + } + end + + def setup + super + + Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME + File.delete(TEST_OUT_NAME) if File.exists? TEST_OUT_NAME + end + + def test_extractDirectory + extractTestDir + assert(File.directory? TEST_OUT_NAME) + end + + def test_extractDirectoryExistsAsDir + Dir.mkdir TEST_OUT_NAME + extractTestDir + assert(File.directory? TEST_OUT_NAME) + end + + def test_extractDirectoryExistsAsFile + File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } + assert_exception(ZipDestinationFileExistsError) { extractTestDir } + end + + def test_extractDirectoryExistsAsFileOverwrite + File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } + gotCalled = false + extractTestDir { + |entry, destPath| + gotCalled = true + assert_equals(TEST_OUT_NAME, destPath) + assert(entry.isDirectory) + true + } + assert(gotCalled) + assert(File.directory? TEST_OUT_NAME) + end +end + + +TestFiles::createTestFiles(ARGV.index("recreate") != nil || + ARGV.index("recreateonly") != nil) +TestZipFile::createTestZips(ARGV.index("recreate") != nil || + ARGV.index("recreateonly") != nil) +exit if ARGV.index("recreateonly") != nil + +#require 'runit/cui/testrunner' +#RUNIT::CUI::TestRunner.run(ZipFileTest.suite) + +# Copyright (C) 2002 Thomas Sondergaard +# rubyzip is free software; you can redistribute it and/or +# modify it under the terms of the ruby license. diff --git a/vendor/plugins/rubyzip-0.9.1/test/data/notzippedruby.rb b/vendor/plugins/rubyzip-0.9.1/test/data/notzippedruby.rb new file mode 100755 index 00000000..036d25e9 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/test/data/notzippedruby.rb @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby + +class NotZippedRuby + def returnTrue + true + end +end diff --git a/vendor/plugins/rubyzip-0.9.1/test/data/rubycode.zip b/vendor/plugins/rubyzip-0.9.1/test/data/rubycode.zip new file mode 100644 index 00000000..8a68560e Binary files /dev/null and b/vendor/plugins/rubyzip-0.9.1/test/data/rubycode.zip differ diff --git a/vendor/plugins/rubyzip-0.9.1/test/data/rubycode2.zip b/vendor/plugins/rubyzip-0.9.1/test/data/rubycode2.zip new file mode 100644 index 00000000..8e1cd08f Binary files /dev/null and b/vendor/plugins/rubyzip-0.9.1/test/data/rubycode2.zip differ diff --git a/vendor/plugins/rubyzip-0.9.1/test/data/testDirectory.bin b/vendor/plugins/rubyzip-0.9.1/test/data/testDirectory.bin new file mode 100644 index 00000000..cbdb9f7d Binary files /dev/null and b/vendor/plugins/rubyzip-0.9.1/test/data/testDirectory.bin differ diff --git a/vendor/plugins/rubyzip-0.9.1/test/data/zipWithDirs.zip b/vendor/plugins/rubyzip-0.9.1/test/data/zipWithDirs.zip new file mode 100644 index 00000000..4b01f011 Binary files /dev/null and b/vendor/plugins/rubyzip-0.9.1/test/data/zipWithDirs.zip differ diff --git a/vendor/plugins/rubyzip-0.9.1/test/gentestfiles.rb b/vendor/plugins/rubyzip-0.9.1/test/gentestfiles.rb new file mode 100755 index 00000000..b1b25339 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/test/gentestfiles.rb @@ -0,0 +1,157 @@ +#!/usr/bin/env ruby + +$VERBOSE = true + +class TestFiles + RANDOM_ASCII_FILE1 = "data/generated/randomAscii1.txt" + RANDOM_ASCII_FILE2 = "data/generated/randomAscii2.txt" + RANDOM_ASCII_FILE3 = "data/generated/randomAscii3.txt" + RANDOM_BINARY_FILE1 = "data/generated/randomBinary1.bin" + RANDOM_BINARY_FILE2 = "data/generated/randomBinary2.bin" + + EMPTY_TEST_DIR = "data/generated/emptytestdir" + + ASCII_TEST_FILES = [ RANDOM_ASCII_FILE1, RANDOM_ASCII_FILE2, RANDOM_ASCII_FILE3 ] + BINARY_TEST_FILES = [ RANDOM_BINARY_FILE1, RANDOM_BINARY_FILE2 ] + TEST_DIRECTORIES = [ EMPTY_TEST_DIR ] + TEST_FILES = [ ASCII_TEST_FILES, BINARY_TEST_FILES, EMPTY_TEST_DIR ].flatten! + + def TestFiles.create_test_files(recreate) + if (recreate || + ! (TEST_FILES.inject(true) { |accum, element| accum && File.exists?(element) })) + + Dir.mkdir "data/generated" rescue Errno::EEXIST + + ASCII_TEST_FILES.each_with_index { + |filename, index| + create_random_ascii(filename, 1E4 * (index+1)) + } + + BINARY_TEST_FILES.each_with_index { + |filename, index| + create_random_binary(filename, 1E4 * (index+1)) + } + + ensure_dir(EMPTY_TEST_DIR) + end + end + + private + def TestFiles.create_random_ascii(filename, size) + File.open(filename, "wb") { + |file| + while (file.tell < size) + file << rand + end + } + end + + def TestFiles.create_random_binary(filename, size) + File.open(filename, "wb") { + |file| + while (file.tell < size) + file << [rand].pack("V") + end + } + end + + def TestFiles.ensure_dir(name) + if File.exists?(name) + return if File.stat(name).directory? + File.delete(name) + end + Dir.mkdir(name) + end + +end + + + +# For representation and creation of +# test data +class TestZipFile + attr_accessor :zip_name, :entry_names, :comment + + def initialize(zip_name, entry_names, comment = "") + @zip_name=zip_name + @entry_names=entry_names + @comment = comment + end + + def TestZipFile.create_test_zips(recreate) + files = Dir.entries("data/generated") + if (recreate || + ! (files.index(File.basename(TEST_ZIP1.zip_name)) && + files.index(File.basename(TEST_ZIP2.zip_name)) && + files.index(File.basename(TEST_ZIP3.zip_name)) && + files.index(File.basename(TEST_ZIP4.zip_name)) && + files.index("empty.txt") && + files.index("empty_chmod640.txt") && + files.index("short.txt") && + files.index("longAscii.txt") && + files.index("longBinary.bin") )) + raise "failed to create test zip '#{TEST_ZIP1.zip_name}'" unless + system("zip #{TEST_ZIP1.zip_name} data/file2.txt") + raise "failed to remove entry from '#{TEST_ZIP1.zip_name}'" unless + system("zip #{TEST_ZIP1.zip_name} -d data/file2.txt") + + File.open("data/generated/empty.txt", "w") {} + File.open("data/generated/empty_chmod640.txt", "w") { |f| f.chmod(0640) } + + File.open("data/generated/short.txt", "w") { |file| file << "ABCDEF" } + ziptestTxt="" + File.open("data/file2.txt") { |file| ziptestTxt=file.read } + File.open("data/generated/longAscii.txt", "w") { + |file| + while (file.tell < 1E5) + file << ziptestTxt + end + } + + testBinaryPattern="" + File.open("data/generated/empty.zip") { |file| testBinaryPattern=file.read } + testBinaryPattern *= 4 + + File.open("data/generated/longBinary.bin", "wb") { + |file| + while (file.tell < 3E5) + file << testBinaryPattern << rand << "\0" + end + } + raise "failed to create test zip '#{TEST_ZIP2.zip_name}'" unless + system("zip #{TEST_ZIP2.zip_name} #{TEST_ZIP2.entry_names.join(' ')}") + + # without bash system interprets everything after echo as parameters to + # echo including | zip -z ... + raise "failed to add comment to test zip '#{TEST_ZIP2.zip_name}'" unless + system("bash -c \"echo #{TEST_ZIP2.comment} | zip -z #{TEST_ZIP2.zip_name}\"") + + raise "failed to create test zip '#{TEST_ZIP3.zip_name}'" unless + system("zip #{TEST_ZIP3.zip_name} #{TEST_ZIP3.entry_names.join(' ')}") + + raise "failed to create test zip '#{TEST_ZIP4.zip_name}'" unless + system("zip #{TEST_ZIP4.zip_name} #{TEST_ZIP4.entry_names.join(' ')}") + end + rescue + raise $!.to_s + + "\n\nziptest.rb requires the Info-ZIP program 'zip' in the path\n" + + "to create test data. If you don't have it you can download\n" + + "the necessary test files at http://sf.net/projects/rubyzip." + end + + TEST_ZIP1 = TestZipFile.new("data/generated/empty.zip", []) + TEST_ZIP2 = TestZipFile.new("data/generated/5entry.zip", %w{ data/generated/longAscii.txt data/generated/empty.txt data/generated/empty_chmod640.txt data/generated/short.txt data/generated/longBinary.bin}, + "my zip comment") + TEST_ZIP3 = TestZipFile.new("data/generated/test1.zip", %w{ data/file1.txt }) + TEST_ZIP4 = TestZipFile.new("data/generated/zipWithDir.zip", [ "data/file1.txt", + TestFiles::EMPTY_TEST_DIR]) +end + + +END { + TestFiles::create_test_files(ARGV.index("recreate") != nil || + ARGV.index("recreateonly") != nil) + TestZipFile::create_test_zips(ARGV.index("recreate") != nil || + ARGV.index("recreateonly") != nil) + exit if ARGV.index("recreateonly") != nil +} diff --git a/vendor/plugins/rubyzip-0.9.1/test/ioextrastest.rb b/vendor/plugins/rubyzip-0.9.1/test/ioextrastest.rb new file mode 100755 index 00000000..b18e9db9 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/test/ioextrastest.rb @@ -0,0 +1,208 @@ +#!/usr/bin/env ruby + +$VERBOSE = true + +$: << "../lib" + +require 'test/unit' +require 'zip/ioextras' + +include IOExtras + +class FakeIOTest < Test::Unit::TestCase + class FakeIOUsingClass + include FakeIO + end + + def test_kind_of? + obj = FakeIOUsingClass.new + + assert(obj.kind_of?(Object)) + assert(obj.kind_of?(FakeIOUsingClass)) + assert(obj.kind_of?(IO)) + assert(!obj.kind_of?(Fixnum)) + assert(!obj.kind_of?(String)) + end +end + +class AbstractInputStreamTest < Test::Unit::TestCase + # AbstractInputStream subclass that provides a read method + + TEST_LINES = [ "Hello world#{$/}", + "this is the second line#{$/}", + "this is the last line"] + TEST_STRING = TEST_LINES.join + class TestAbstractInputStream + include AbstractInputStream + def initialize(aString) + super() + @contents = aString + @readPointer = 0 + end + + def read(charsToRead) + retVal=@contents[@readPointer, charsToRead] + @readPointer+=charsToRead + return retVal + end + + def produce_input + read(100) + end + + def input_finished? + @contents[@readPointer] == nil + end + end + + def setup + @io = TestAbstractInputStream.new(TEST_STRING) + end + + def test_gets + assert_equal(TEST_LINES[0], @io.gets) + assert_equal(1, @io.lineno) + assert_equal(TEST_LINES[1], @io.gets) + assert_equal(2, @io.lineno) + assert_equal(TEST_LINES[2], @io.gets) + assert_equal(3, @io.lineno) + assert_equal(nil, @io.gets) + assert_equal(4, @io.lineno) + end + + def test_getsMultiCharSeperator + assert_equal("Hell", @io.gets("ll")) + assert_equal("o world#{$/}this is the second l", @io.gets("d l")) + end + + def test_each_line + lineNumber=0 + @io.each_line { + |line| + assert_equal(TEST_LINES[lineNumber], line) + lineNumber+=1 + } + end + + def test_readlines + assert_equal(TEST_LINES, @io.readlines) + end + + def test_readline + test_gets + begin + @io.readline + fail "EOFError expected" + rescue EOFError + end + end +end + +class AbstractOutputStreamTest < Test::Unit::TestCase + class TestOutputStream + include AbstractOutputStream + + attr_accessor :buffer + + def initialize + @buffer = "" + end + + def << (data) + @buffer << data + self + end + end + + def setup + @outputStream = TestOutputStream.new + + @origCommaSep = $, + @origOutputSep = $\ + end + + def teardown + $, = @origCommaSep + $\ = @origOutputSep + end + + def test_write + count = @outputStream.write("a little string") + assert_equal("a little string", @outputStream.buffer) + assert_equal("a little string".length, count) + + count = @outputStream.write(". a little more") + assert_equal("a little string. a little more", @outputStream.buffer) + assert_equal(". a little more".length, count) + end + + def test_print + $\ = nil # record separator set to nil + @outputStream.print("hello") + assert_equal("hello", @outputStream.buffer) + + @outputStream.print(" world.") + assert_equal("hello world.", @outputStream.buffer) + + @outputStream.print(" You ok ", "out ", "there?") + assert_equal("hello world. You ok out there?", @outputStream.buffer) + + $\ = "\n" + @outputStream.print + assert_equal("hello world. You ok out there?\n", @outputStream.buffer) + + @outputStream.print("I sure hope so!") + assert_equal("hello world. You ok out there?\nI sure hope so!\n", @outputStream.buffer) + + $, = "X" + @outputStream.buffer = "" + @outputStream.print("monkey", "duck", "zebra") + assert_equal("monkeyXduckXzebra\n", @outputStream.buffer) + + $\ = nil + @outputStream.buffer = "" + @outputStream.print(20) + assert_equal("20", @outputStream.buffer) + end + + def test_printf + @outputStream.printf("%d %04x", 123, 123) + assert_equal("123 007b", @outputStream.buffer) + end + + def test_putc + @outputStream.putc("A") + assert_equal("A", @outputStream.buffer) + @outputStream.putc(65) + assert_equal("AA", @outputStream.buffer) + end + + def test_puts + @outputStream.puts + assert_equal("\n", @outputStream.buffer) + + @outputStream.puts("hello", "world") + assert_equal("\nhello\nworld\n", @outputStream.buffer) + + @outputStream.buffer = "" + @outputStream.puts("hello\n", "world\n") + assert_equal("hello\nworld\n", @outputStream.buffer) + + @outputStream.buffer = "" + @outputStream.puts(["hello\n", "world\n"]) + assert_equal("hello\nworld\n", @outputStream.buffer) + + @outputStream.buffer = "" + @outputStream.puts(["hello\n", "world\n"], "bingo") + assert_equal("hello\nworld\nbingo\n", @outputStream.buffer) + + @outputStream.buffer = "" + @outputStream.puts(16, 20, 50, "hello") + assert_equal("16\n20\n50\nhello\n", @outputStream.buffer) + end +end + + +# Copyright (C) 2002-2004 Thomas Sondergaard +# rubyzip is free software; you can redistribute it and/or +# modify it under the terms of the ruby license. diff --git a/vendor/plugins/rubyzip-0.9.1/test/stdrubyexttest.rb b/vendor/plugins/rubyzip-0.9.1/test/stdrubyexttest.rb new file mode 100755 index 00000000..f11608f7 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/test/stdrubyexttest.rb @@ -0,0 +1,52 @@ +#!/usr/bin/env ruby + +$VERBOSE = true + +$: << "../lib" + +require 'test/unit' +require 'zip/stdrubyext' + +class ModuleTest < Test::Unit::TestCase + + def test_select_map + assert_equal([2, 4, 8, 10], [1, 2, 3, 4, 5].select_map { |e| e == 3 ? nil : 2*e }) + end + +end + +class StringExtensionsTest < Test::Unit::TestCase + + def test_starts_with + assert("hello".starts_with("")) + assert("hello".starts_with("h")) + assert("hello".starts_with("he")) + assert(! "hello".starts_with("hello there")) + assert(! "hello".starts_with(" he")) + + assert_raise(TypeError, "type mismatch: NilClass given") { + "hello".starts_with(nil) + } + end + + def test_ends_with + assert("hello".ends_with("o")) + assert("hello".ends_with("lo")) + assert("hello".ends_with("hello")) + assert(!"howdy".ends_with("o")) + assert(!"howdy".ends_with("oy")) + assert(!"howdy".ends_with("howdy doody")) + assert(!"howdy".ends_with("doody howdy")) + end + + def test_ensure_end + assert_equal("hello!", "hello!".ensure_end("!")) + assert_equal("hello!", "hello!".ensure_end("o!")) + assert_equal("hello!", "hello".ensure_end("!")) + assert_equal("hello!", "hel".ensure_end("lo!")) + end +end + +# Copyright (C) 2002, 2003 Thomas Sondergaard +# rubyzip is free software; you can redistribute it and/or +# modify it under the terms of the ruby license. diff --git a/vendor/plugins/rubyzip-0.9.1/test/zipfilesystemtest.rb b/vendor/plugins/rubyzip-0.9.1/test/zipfilesystemtest.rb new file mode 100755 index 00000000..f17b2d80 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/test/zipfilesystemtest.rb @@ -0,0 +1,831 @@ +#!/usr/bin/env ruby + +$VERBOSE = true + +$: << "../lib" + +require 'zip/zipfilesystem' +require 'test/unit' + +module ExtraAssertions + + def assert_forwarded(anObject, method, retVal, *expectedArgs) + callArgs = nil + setCallArgsProc = proc { |args| callArgs = args } + anObject.instance_eval <<-"end_eval" + alias #{method}_org #{method} + def #{method}(*args) + ObjectSpace._id2ref(#{setCallArgsProc.object_id}).call(args) + ObjectSpace._id2ref(#{retVal.object_id}) + end + end_eval + + assert_equal(retVal, yield) # Invoke test + assert_equal(expectedArgs, callArgs) + ensure + anObject.instance_eval "alias #{method} #{method}_org" + end + +end + +include Zip + +class ZipFsFileNonmutatingTest < Test::Unit::TestCase + def setup + @zipFile = ZipFile.new("data/zipWithDirs.zip") + end + + def teardown + @zipFile.close if @zipFile + end + + def test_umask + assert_equal(File.umask, @zipFile.file.umask) + @zipFile.file.umask(0006) + end + + def test_exists? + assert(! @zipFile.file.exists?("notAFile")) + assert(@zipFile.file.exists?("file1")) + assert(@zipFile.file.exists?("dir1")) + assert(@zipFile.file.exists?("dir1/")) + assert(@zipFile.file.exists?("dir1/file12")) + assert(@zipFile.file.exist?("dir1/file12")) # notice, tests exist? alias of exists? ! + + @zipFile.dir.chdir "dir1/" + assert(!@zipFile.file.exists?("file1")) + assert(@zipFile.file.exists?("file12")) + end + + def test_open_read + blockCalled = false + @zipFile.file.open("file1", "r") { + |f| + blockCalled = true + assert_equal("this is the entry 'file1' in my test archive!", + f.readline.chomp) + } + assert(blockCalled) + + blockCalled = false + @zipFile.dir.chdir "dir2" + @zipFile.file.open("file21", "r") { + |f| + blockCalled = true + assert_equal("this is the entry 'dir2/file21' in my test archive!", + f.readline.chomp) + } + assert(blockCalled) + @zipFile.dir.chdir "/" + + assert_raise(Errno::ENOENT) { + @zipFile.file.open("noSuchEntry") + } + + begin + is = @zipFile.file.open("file1") + assert_equal("this is the entry 'file1' in my test archive!", + is.readline.chomp) + ensure + is.close if is + end + end + + def test_new + begin + is = @zipFile.file.new("file1") + assert_equal("this is the entry 'file1' in my test archive!", + is.readline.chomp) + ensure + is.close if is + end + begin + is = @zipFile.file.new("file1") { + fail "should not call block" + } + ensure + is.close if is + end + end + + def test_symlink + assert_raise(NotImplementedError) { + @zipFile.file.symlink("file1", "aSymlink") + } + end + + def test_size + assert_raise(Errno::ENOENT) { @zipFile.file.size("notAFile") } + assert_equal(72, @zipFile.file.size("file1")) + assert_equal(0, @zipFile.file.size("dir2/dir21")) + + assert_equal(72, @zipFile.file.stat("file1").size) + assert_equal(0, @zipFile.file.stat("dir2/dir21").size) + end + + def test_size? + assert_equal(nil, @zipFile.file.size?("notAFile")) + assert_equal(72, @zipFile.file.size?("file1")) + assert_equal(nil, @zipFile.file.size?("dir2/dir21")) + + assert_equal(72, @zipFile.file.stat("file1").size?) + assert_equal(nil, @zipFile.file.stat("dir2/dir21").size?) + end + + + def test_file? + assert(@zipFile.file.file?("file1")) + assert(@zipFile.file.file?("dir2/file21")) + assert(! @zipFile.file.file?("dir1")) + assert(! @zipFile.file.file?("dir1/dir11")) + + assert(@zipFile.file.stat("file1").file?) + assert(@zipFile.file.stat("dir2/file21").file?) + assert(! @zipFile.file.stat("dir1").file?) + assert(! @zipFile.file.stat("dir1/dir11").file?) + end + + include ExtraAssertions + + def test_dirname + assert_forwarded(File, :dirname, "retVal", "a/b/c/d") { + @zipFile.file.dirname("a/b/c/d") + } + end + + def test_basename + assert_forwarded(File, :basename, "retVal", "a/b/c/d") { + @zipFile.file.basename("a/b/c/d") + } + end + + def test_split + assert_forwarded(File, :split, "retVal", "a/b/c/d") { + @zipFile.file.split("a/b/c/d") + } + end + + def test_join + assert_equal("a/b/c", @zipFile.file.join("a/b", "c")) + assert_equal("a/b/c/d", @zipFile.file.join("a/b", "c/d")) + assert_equal("/c/d", @zipFile.file.join("", "c/d")) + assert_equal("a/b/c/d", @zipFile.file.join("a", "b", "c", "d")) + end + + def test_utime + t_now = Time.now + t_bak = @zipFile.file.mtime("file1") + @zipFile.file.utime(t_now, "file1") + assert_equal(t_now, @zipFile.file.mtime("file1")) + @zipFile.file.utime(t_bak, "file1") + assert_equal(t_bak, @zipFile.file.mtime("file1")) + end + + + def assert_always_false(operation) + assert(! @zipFile.file.send(operation, "noSuchFile")) + assert(! @zipFile.file.send(operation, "file1")) + assert(! @zipFile.file.send(operation, "dir1")) + assert(! @zipFile.file.stat("file1").send(operation)) + assert(! @zipFile.file.stat("dir1").send(operation)) + end + + def assert_true_if_entry_exists(operation) + assert(! @zipFile.file.send(operation, "noSuchFile")) + assert(@zipFile.file.send(operation, "file1")) + assert(@zipFile.file.send(operation, "dir1")) + assert(@zipFile.file.stat("file1").send(operation)) + assert(@zipFile.file.stat("dir1").send(operation)) + end + + def test_pipe? + assert_always_false(:pipe?) + end + + def test_blockdev? + assert_always_false(:blockdev?) + end + + def test_symlink? + assert_always_false(:symlink?) + end + + def test_socket? + assert_always_false(:socket?) + end + + def test_chardev? + assert_always_false(:chardev?) + end + + def test_truncate + assert_raise(StandardError, "truncate not supported") { + @zipFile.file.truncate("file1", 100) + } + end + + def assert_e_n_o_e_n_t(operation, args = ["NoSuchFile"]) + assert_raise(Errno::ENOENT) { + @zipFile.file.send(operation, *args) + } + end + + def test_ftype + assert_e_n_o_e_n_t(:ftype) + assert_equal("file", @zipFile.file.ftype("file1")) + assert_equal("directory", @zipFile.file.ftype("dir1/dir11")) + assert_equal("directory", @zipFile.file.ftype("dir1/dir11/")) + end + + def test_link + assert_raise(NotImplementedError) { + @zipFile.file.link("file1", "someOtherString") + } + end + + def test_directory? + assert(! @zipFile.file.directory?("notAFile")) + assert(! @zipFile.file.directory?("file1")) + assert(! @zipFile.file.directory?("dir1/file11")) + assert(@zipFile.file.directory?("dir1")) + assert(@zipFile.file.directory?("dir1/")) + assert(@zipFile.file.directory?("dir2/dir21")) + + assert(! @zipFile.file.stat("file1").directory?) + assert(! @zipFile.file.stat("dir1/file11").directory?) + assert(@zipFile.file.stat("dir1").directory?) + assert(@zipFile.file.stat("dir1/").directory?) + assert(@zipFile.file.stat("dir2/dir21").directory?) + end + + def test_chown + assert_equal(2, @zipFile.file.chown(1,2, "dir1", "file1")) + assert_equal(1, @zipFile.file.stat("dir1").uid) + assert_equal(2, @zipFile.file.stat("dir1").gid) + assert_equal(2, @zipFile.file.chown(nil, nil, "dir1", "file1")) + end + + def test_zero? + assert(! @zipFile.file.zero?("notAFile")) + assert(! @zipFile.file.zero?("file1")) + assert(@zipFile.file.zero?("dir1")) + blockCalled = false + ZipFile.open("data/generated/5entry.zip") { + |zf| + blockCalled = true + assert(zf.file.zero?("data/generated/empty.txt")) + } + assert(blockCalled) + + assert(! @zipFile.file.stat("file1").zero?) + assert(@zipFile.file.stat("dir1").zero?) + blockCalled = false + ZipFile.open("data/generated/5entry.zip") { + |zf| + blockCalled = true + assert(zf.file.stat("data/generated/empty.txt").zero?) + } + assert(blockCalled) + end + + def test_expand_path + ZipFile.open("data/zipWithDirs.zip") { + |zf| + assert_equal("/", zf.file.expand_path(".")) + zf.dir.chdir "dir1" + assert_equal("/dir1", zf.file.expand_path(".")) + assert_equal("/dir1/file12", zf.file.expand_path("file12")) + assert_equal("/", zf.file.expand_path("..")) + assert_equal("/dir2/dir21", zf.file.expand_path("../dir2/dir21")) + } + end + + def test_mtime + assert_equal(Time.at(1027694306), + @zipFile.file.mtime("dir2/file21")) + assert_equal(Time.at(1027690863), + @zipFile.file.mtime("dir2/dir21")) + assert_raise(Errno::ENOENT) { + @zipFile.file.mtime("noSuchEntry") + } + + assert_equal(Time.at(1027694306), + @zipFile.file.stat("dir2/file21").mtime) + assert_equal(Time.at(1027690863), + @zipFile.file.stat("dir2/dir21").mtime) + end + + def test_ctime + assert_nil(@zipFile.file.ctime("file1")) + assert_nil(@zipFile.file.stat("file1").ctime) + end + + def test_atime + assert_nil(@zipFile.file.atime("file1")) + assert_nil(@zipFile.file.stat("file1").atime) + end + + def test_readable? + assert(! @zipFile.file.readable?("noSuchFile")) + assert(@zipFile.file.readable?("file1")) + assert(@zipFile.file.readable?("dir1")) + assert(@zipFile.file.stat("file1").readable?) + assert(@zipFile.file.stat("dir1").readable?) + end + + def test_readable_real? + assert(! @zipFile.file.readable_real?("noSuchFile")) + assert(@zipFile.file.readable_real?("file1")) + assert(@zipFile.file.readable_real?("dir1")) + assert(@zipFile.file.stat("file1").readable_real?) + assert(@zipFile.file.stat("dir1").readable_real?) + end + + def test_writable? + assert(! @zipFile.file.writable?("noSuchFile")) + assert(@zipFile.file.writable?("file1")) + assert(@zipFile.file.writable?("dir1")) + assert(@zipFile.file.stat("file1").writable?) + assert(@zipFile.file.stat("dir1").writable?) + end + + def test_writable_real? + assert(! @zipFile.file.writable_real?("noSuchFile")) + assert(@zipFile.file.writable_real?("file1")) + assert(@zipFile.file.writable_real?("dir1")) + assert(@zipFile.file.stat("file1").writable_real?) + assert(@zipFile.file.stat("dir1").writable_real?) + end + + def test_executable? + assert(! @zipFile.file.executable?("noSuchFile")) + assert(! @zipFile.file.executable?("file1")) + assert(@zipFile.file.executable?("dir1")) + assert(! @zipFile.file.stat("file1").executable?) + assert(@zipFile.file.stat("dir1").executable?) + end + + def test_executable_real? + assert(! @zipFile.file.executable_real?("noSuchFile")) + assert(! @zipFile.file.executable_real?("file1")) + assert(@zipFile.file.executable_real?("dir1")) + assert(! @zipFile.file.stat("file1").executable_real?) + assert(@zipFile.file.stat("dir1").executable_real?) + end + + def test_owned? + assert_true_if_entry_exists(:owned?) + end + + def test_grpowned? + assert_true_if_entry_exists(:grpowned?) + end + + def test_setgid? + assert_always_false(:setgid?) + end + + def test_setuid? + assert_always_false(:setgid?) + end + + def test_sticky? + assert_always_false(:sticky?) + end + + def test_readlink + assert_raise(NotImplementedError) { + @zipFile.file.readlink("someString") + } + end + + def test_stat + s = @zipFile.file.stat("file1") + assert(s.kind_of?(File::Stat)) # It pretends + assert_raise(Errno::ENOENT, "No such file or directory - noSuchFile") { + @zipFile.file.stat("noSuchFile") + } + end + + def test_lstat + assert(@zipFile.file.lstat("file1").file?) + end + + + def test_chmod + assert_raise(Errno::ENOENT, "No such file or directory - noSuchFile") { + @zipFile.file.chmod(0644, "file1", "NoSuchFile") + } + assert_equal(2, @zipFile.file.chmod(0644, "file1", "dir1")) + end + + def test_pipe + assert_raise(NotImplementedError) { + @zipFile.file.pipe + } + end + + def test_foreach + ZipFile.open("data/generated/zipWithDir.zip") { + |zf| + ref = [] + File.foreach("data/file1.txt") { |e| ref << e } + + index = 0 + zf.file.foreach("data/file1.txt") { + |l| + assert_equal(ref[index], l) + index = index.next + } + assert_equal(ref.size, index) + } + + ZipFile.open("data/generated/zipWithDir.zip") { + |zf| + ref = [] + File.foreach("data/file1.txt", " ") { |e| ref << e } + + index = 0 + zf.file.foreach("data/file1.txt", " ") { + |l| + assert_equal(ref[index], l) + index = index.next + } + assert_equal(ref.size, index) + } + end + + def test_popen + cmd = /mswin/i =~ RUBY_PLATFORM ? 'dir' : 'ls' + + assert_equal(File.popen(cmd) { |f| f.read }, + @zipFile.file.popen(cmd) { |f| f.read }) + end + +# Can be added later +# def test_select +# fail "implement test" +# end + + def test_readlines + ZipFile.open("data/generated/zipWithDir.zip") { + |zf| + assert_equal(File.readlines("data/file1.txt"), + zf.file.readlines("data/file1.txt")) + } + end + + def test_read + ZipFile.open("data/generated/zipWithDir.zip") { + |zf| + assert_equal(File.read("data/file1.txt"), + zf.file.read("data/file1.txt")) + } + end + +end + +class ZipFsFileStatTest < Test::Unit::TestCase + + def setup + @zipFile = ZipFile.new("data/zipWithDirs.zip") + end + + def teardown + @zipFile.close if @zipFile + end + + def test_blocks + assert_equal(nil, @zipFile.file.stat("file1").blocks) + end + + def test_ino + assert_equal(0, @zipFile.file.stat("file1").ino) + end + + def test_uid + assert_equal(0, @zipFile.file.stat("file1").uid) + end + + def test_gid + assert_equal(0, @zipFile.file.stat("file1").gid) + end + + def test_ftype + assert_equal("file", @zipFile.file.stat("file1").ftype) + assert_equal("directory", @zipFile.file.stat("dir1").ftype) + end + + def test_mode + assert_equal(0600, @zipFile.file.stat("file1").mode & 0777) + assert_equal(0600, @zipFile.file.stat("file1").mode & 0777) + assert_equal(0755, @zipFile.file.stat("dir1").mode & 0777) + assert_equal(0755, @zipFile.file.stat("dir1").mode & 0777) + end + + def test_dev + assert_equal(0, @zipFile.file.stat("file1").dev) + end + + def test_rdev + assert_equal(0, @zipFile.file.stat("file1").rdev) + end + + def test_rdev_major + assert_equal(0, @zipFile.file.stat("file1").rdev_major) + end + + def test_rdev_minor + assert_equal(0, @zipFile.file.stat("file1").rdev_minor) + end + + def test_nlink + assert_equal(1, @zipFile.file.stat("file1").nlink) + end + + def test_blksize + assert_nil(@zipFile.file.stat("file1").blksize) + end + +end + +class ZipFsFileMutatingTest < Test::Unit::TestCase + TEST_ZIP = "zipWithDirs_copy.zip" + def setup + File.copy("data/zipWithDirs.zip", TEST_ZIP) + end + + def teardown + end + + def test_delete + do_test_delete_or_unlink(:delete) + end + + def test_unlink + do_test_delete_or_unlink(:unlink) + end + + def test_open_write + ZipFile.open(TEST_ZIP) { + |zf| + + zf.file.open("test_open_write_entry", "w") { + |f| + blockCalled = true + f.write "This is what I'm writing" + } + assert_equal("This is what I'm writing", + zf.file.read("test_open_write_entry")) + + # Test with existing entry + zf.file.open("file1", "w") { + |f| + blockCalled = true + f.write "This is what I'm writing too" + } + assert_equal("This is what I'm writing too", + zf.file.read("file1")) + } + end + + def test_rename + ZipFile.open(TEST_ZIP) { + |zf| + assert_raise(Errno::ENOENT, "") { + zf.file.rename("NoSuchFile", "bimse") + } + zf.file.rename("file1", "newNameForFile1") + } + + ZipFile.open(TEST_ZIP) { + |zf| + assert(! zf.file.exists?("file1")) + assert(zf.file.exists?("newNameForFile1")) + } + end + + def do_test_delete_or_unlink(symbol) + ZipFile.open(TEST_ZIP) { + |zf| + assert(zf.file.exists?("dir2/dir21/dir221/file2221")) + zf.file.send(symbol, "dir2/dir21/dir221/file2221") + assert(! zf.file.exists?("dir2/dir21/dir221/file2221")) + + assert(zf.file.exists?("dir1/file11")) + assert(zf.file.exists?("dir1/file12")) + zf.file.send(symbol, "dir1/file11", "dir1/file12") + assert(! zf.file.exists?("dir1/file11")) + assert(! zf.file.exists?("dir1/file12")) + + assert_raise(Errno::ENOENT) { zf.file.send(symbol, "noSuchFile") } + assert_raise(Errno::EISDIR) { zf.file.send(symbol, "dir1/dir11") } + assert_raise(Errno::EISDIR) { zf.file.send(symbol, "dir1/dir11/") } + } + + ZipFile.open(TEST_ZIP) { + |zf| + assert(! zf.file.exists?("dir2/dir21/dir221/file2221")) + assert(! zf.file.exists?("dir1/file11")) + assert(! zf.file.exists?("dir1/file12")) + + assert(zf.file.exists?("dir1/dir11")) + assert(zf.file.exists?("dir1/dir11/")) + } + end + +end + +class ZipFsDirectoryTest < Test::Unit::TestCase + TEST_ZIP = "zipWithDirs_copy.zip" + + def setup + File.copy("data/zipWithDirs.zip", TEST_ZIP) + end + + def test_delete + ZipFile.open(TEST_ZIP) { + |zf| + assert_raise(Errno::ENOENT, "No such file or directory - NoSuchFile.txt") { + zf.dir.delete("NoSuchFile.txt") + } + assert_raise(Errno::EINVAL, "Invalid argument - file1") { + zf.dir.delete("file1") + } + assert(zf.file.exists?("dir1")) + zf.dir.delete("dir1") + assert(! zf.file.exists?("dir1")) + } + end + + def test_mkdir + ZipFile.open(TEST_ZIP) { + |zf| + assert_raise(Errno::EEXIST, "File exists - dir1") { + zf.dir.mkdir("file1") + } + assert_raise(Errno::EEXIST, "File exists - dir1") { + zf.dir.mkdir("dir1") + } + assert(!zf.file.exists?("newDir")) + zf.dir.mkdir("newDir") + assert(zf.file.directory?("newDir")) + assert(!zf.file.exists?("newDir2")) + zf.dir.mkdir("newDir2", 3485) + assert(zf.file.directory?("newDir2")) + } + end + + def test_pwd_chdir_entries + ZipFile.open(TEST_ZIP) { + |zf| + assert_equal("/", zf.dir.pwd) + + assert_raise(Errno::ENOENT, "No such file or directory - no such dir") { + zf.dir.chdir "no such dir" + } + + assert_raise(Errno::EINVAL, "Invalid argument - file1") { + zf.dir.chdir "file1" + } + + assert_equal(["dir1", "dir2", "file1"].sort, zf.dir.entries(".").sort) + zf.dir.chdir "dir1" + assert_equal("/dir1", zf.dir.pwd) + assert_equal(["dir11", "file11", "file12"], zf.dir.entries(".").sort) + + zf.dir.chdir "../dir2/dir21" + assert_equal("/dir2/dir21", zf.dir.pwd) + assert_equal(["dir221"].sort, zf.dir.entries(".").sort) + } + end + + def test_foreach + ZipFile.open(TEST_ZIP) { + |zf| + + blockCalled = false + assert_raise(Errno::ENOENT, "No such file or directory - noSuchDir") { + zf.dir.foreach("noSuchDir") { |e| blockCalled = true } + } + assert(! blockCalled) + + assert_raise(Errno::ENOTDIR, "Not a directory - file1") { + zf.dir.foreach("file1") { |e| blockCalled = true } + } + assert(! blockCalled) + + entries = [] + zf.dir.foreach(".") { |e| entries << e } + assert_equal(["dir1", "dir2", "file1"].sort, entries.sort) + + entries = [] + zf.dir.foreach("dir1") { |e| entries << e } + assert_equal(["dir11", "file11", "file12"], entries.sort) + } + end + + def test_chroot + ZipFile.open(TEST_ZIP) { + |zf| + assert_raise(NotImplementedError) { + zf.dir.chroot + } + } + end + + # Globbing not supported yet + #def test_glob + # # test alias []-operator too + # fail "implement test" + #end + + def test_open_new + ZipFile.open(TEST_ZIP) { + |zf| + + assert_raise(Errno::ENOTDIR, "Not a directory - file1") { + zf.dir.new("file1") + } + + assert_raise(Errno::ENOENT, "No such file or directory - noSuchFile") { + zf.dir.new("noSuchFile") + } + + d = zf.dir.new(".") + assert_equal(["file1", "dir1", "dir2"].sort, d.entries.sort) + d.close + + zf.dir.open("dir1") { + |d| + assert_equal(["dir11", "file11", "file12"].sort, d.entries.sort) + } + } + end + +end + +class ZipFsDirIteratorTest < Test::Unit::TestCase + + FILENAME_ARRAY = [ "f1", "f2", "f3", "f4", "f5", "f6" ] + + def setup + @dirIt = ZipFileSystem::ZipFsDirIterator.new(FILENAME_ARRAY) + end + + def test_close + @dirIt.close + assert_raise(IOError, "closed directory") { + @dirIt.each { |e| p e } + } + assert_raise(IOError, "closed directory") { + @dirIt.read + } + assert_raise(IOError, "closed directory") { + @dirIt.rewind + } + assert_raise(IOError, "closed directory") { + @dirIt.seek(0) + } + assert_raise(IOError, "closed directory") { + @dirIt.tell + } + + end + + def test_each + # Tested through Enumerable.entries + assert_equal(FILENAME_ARRAY, @dirIt.entries) + end + + def test_read + FILENAME_ARRAY.size.times { + |i| + assert_equal(FILENAME_ARRAY[i], @dirIt.read) + } + end + + def test_rewind + @dirIt.read + @dirIt.read + assert_equal(FILENAME_ARRAY[2], @dirIt.read) + @dirIt.rewind + assert_equal(FILENAME_ARRAY[0], @dirIt.read) + end + + def test_tell_seek + @dirIt.read + @dirIt.read + pos = @dirIt.tell + valAtPos = @dirIt.read + @dirIt.read + @dirIt.seek(pos) + assert_equal(valAtPos, @dirIt.read) + end + +end + + +# Copyright (C) 2002, 2003 Thomas Sondergaard +# rubyzip is free software; you can redistribute it and/or +# modify it under the terms of the ruby license. diff --git a/vendor/plugins/rubyzip-0.9.1/test/ziprequiretest.rb b/vendor/plugins/rubyzip-0.9.1/test/ziprequiretest.rb new file mode 100755 index 00000000..68d2c714 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/test/ziprequiretest.rb @@ -0,0 +1,43 @@ +#!/usr/bin/env ruby + +$VERBOSE = true + +$: << "../lib" + +require 'test/unit' +require 'zip/ziprequire' + +$: << 'data/rubycode.zip' << 'data/rubycode2.zip' + +class ZipRequireTest < Test::Unit::TestCase + def test_require + assert(require('data/notzippedruby')) + assert(!require('data/notzippedruby')) + + assert(require('zippedruby1')) + assert(!require('zippedruby1')) + + assert(require('zippedruby2')) + assert(!require('zippedruby2')) + + assert(require('zippedruby3')) + assert(!require('zippedruby3')) + + c1 = NotZippedRuby.new + assert(c1.returnTrue) + assert(ZippedRuby1.returnTrue) + assert(!ZippedRuby2.returnFalse) + assert_equal(4, ZippedRuby3.multiplyValues(2, 2)) + end + + def test_get_resource + get_resource("aResource.txt") { + |f| + assert_equal("Nothing exciting in this file!", f.read) + } + end +end + +# Copyright (C) 2002 Thomas Sondergaard +# rubyzip is free software; you can redistribute it and/or +# modify it under the terms of the ruby license. diff --git a/vendor/plugins/rubyzip-0.9.1/test/ziptest.rb b/vendor/plugins/rubyzip-0.9.1/test/ziptest.rb new file mode 100755 index 00000000..56176446 --- /dev/null +++ b/vendor/plugins/rubyzip-0.9.1/test/ziptest.rb @@ -0,0 +1,1599 @@ +#!/usr/bin/env ruby + +$VERBOSE = true + +$: << "../lib" + +require 'test/unit' +require 'zip/zip' +require 'gentestfiles' + +include Zip + + +class ZipEntryTest < Test::Unit::TestCase + TEST_ZIPFILE = "someZipFile.zip" + TEST_COMMENT = "a comment" + TEST_COMPRESSED_SIZE = 1234 + TEST_CRC = 325324 + TEST_EXTRA = "Some data here" + TEST_COMPRESSIONMETHOD = ZipEntry::DEFLATED + TEST_NAME = "entry name" + TEST_SIZE = 8432 + TEST_ISDIRECTORY = false + + def test_constructorAndGetters + entry = ZipEntry.new(TEST_ZIPFILE, + TEST_NAME, + TEST_COMMENT, + TEST_EXTRA, + TEST_COMPRESSED_SIZE, + TEST_CRC, + TEST_COMPRESSIONMETHOD, + TEST_SIZE) + + assert_equal(TEST_COMMENT, entry.comment) + assert_equal(TEST_COMPRESSED_SIZE, entry.compressed_size) + assert_equal(TEST_CRC, entry.crc) + assert_instance_of(Zip::ZipExtraField, entry.extra) + assert_equal(TEST_COMPRESSIONMETHOD, entry.compression_method) + assert_equal(TEST_NAME, entry.name) + assert_equal(TEST_SIZE, entry.size) + assert_equal(TEST_ISDIRECTORY, entry.is_directory) + end + + def test_is_directoryAndIsFile + assert(ZipEntry.new(TEST_ZIPFILE, "hello").file?) + assert(! ZipEntry.new(TEST_ZIPFILE, "hello").directory?) + + assert(ZipEntry.new(TEST_ZIPFILE, "dir/hello").file?) + assert(! ZipEntry.new(TEST_ZIPFILE, "dir/hello").directory?) + + assert(ZipEntry.new(TEST_ZIPFILE, "hello/").directory?) + assert(! ZipEntry.new(TEST_ZIPFILE, "hello/").file?) + + assert(ZipEntry.new(TEST_ZIPFILE, "dir/hello/").directory?) + assert(! ZipEntry.new(TEST_ZIPFILE, "dir/hello/").file?) + end + + def test_equality + entry1 = ZipEntry.new("file.zip", "name", "isNotCompared", + "something extra", 123, 1234, + ZipEntry::DEFLATED, 10000) + entry2 = ZipEntry.new("file.zip", "name", "isNotComparedXXX", + "something extra", 123, 1234, + ZipEntry::DEFLATED, 10000) + entry3 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extra", 123, 1234, + ZipEntry::DEFLATED, 10000) + entry4 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extraXX", 123, 1234, + ZipEntry::DEFLATED, 10000) + entry5 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extraXX", 12, 1234, + ZipEntry::DEFLATED, 10000) + entry6 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extraXX", 12, 123, + ZipEntry::DEFLATED, 10000) + entry7 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extraXX", 12, 123, + ZipEntry::STORED, 10000) + entry8 = ZipEntry.new("file.zip", "name2", "isNotComparedXXX", + "something extraXX", 12, 123, + ZipEntry::STORED, 100000) + + assert_equal(entry1, entry1) + assert_equal(entry1, entry2) + + assert(entry2 != entry3) + assert(entry3 != entry4) + assert(entry4 != entry5) + assert(entry5 != entry6) + assert(entry6 != entry7) + assert(entry7 != entry8) + + assert(entry7 != "hello") + assert(entry7 != 12) + end + + def test_compare + assert_equal(0, (ZipEntry.new("zf.zip", "a") <=> ZipEntry.new("zf.zip", "a"))) + assert_equal(1, (ZipEntry.new("zf.zip", "b") <=> ZipEntry.new("zf.zip", "a"))) + assert_equal(-1, (ZipEntry.new("zf.zip", "a") <=> ZipEntry.new("zf.zip", "b"))) + + entries = [ + ZipEntry.new("zf.zip", "5"), + ZipEntry.new("zf.zip", "1"), + ZipEntry.new("zf.zip", "3"), + ZipEntry.new("zf.zip", "4"), + ZipEntry.new("zf.zip", "0"), + ZipEntry.new("zf.zip", "2") + ] + + entries.sort! + assert_equal("0", entries[0].to_s) + assert_equal("1", entries[1].to_s) + assert_equal("2", entries[2].to_s) + assert_equal("3", entries[3].to_s) + assert_equal("4", entries[4].to_s) + assert_equal("5", entries[5].to_s) + end + + def test_parentAsString + entry1 = ZipEntry.new("zf.zip", "aa") + entry2 = ZipEntry.new("zf.zip", "aa/") + entry3 = ZipEntry.new("zf.zip", "aa/bb") + entry4 = ZipEntry.new("zf.zip", "aa/bb/") + entry5 = ZipEntry.new("zf.zip", "aa/bb/cc") + entry6 = ZipEntry.new("zf.zip", "aa/bb/cc/") + + assert_equal(nil, entry1.parent_as_string) + assert_equal(nil, entry2.parent_as_string) + assert_equal("aa/", entry3.parent_as_string) + assert_equal("aa/", entry4.parent_as_string) + assert_equal("aa/bb/", entry5.parent_as_string) + assert_equal("aa/bb/", entry6.parent_as_string) + end + + def test_entry_name_cannot_start_with_slash + assert_raise(ZipEntryNameError) { ZipEntry.new("zf.zip", "/hej/der") } + end +end + +module IOizeString + attr_reader :tell + + def read(count = nil) + @tell ||= 0 + count = size unless count + retVal = slice(@tell, count) + @tell += count + return retVal + end + + def seek(index, offset) + @tell ||= 0 + case offset + when IO::SEEK_END + newPos = size + index + when IO::SEEK_SET + newPos = index + when IO::SEEK_CUR + newPos = @tell + index + else + raise "Error in test method IOizeString::seek" + end + if (newPos < 0 || newPos >= size) + raise Errno::EINVAL + else + @tell=newPos + end + end + + def reset + @tell = 0 + end +end + +class ZipLocalEntryTest < Test::Unit::TestCase + def test_read_local_entryHeaderOfFirstTestZipEntry + File.open(TestZipFile::TEST_ZIP3.zip_name, "rb") { + |file| + entry = ZipEntry.read_local_entry(file) + + assert_equal("", entry.comment) + # Differs from windows and unix because of CR LF + # assert_equal(480, entry.compressed_size) + # assert_equal(0x2a27930f, entry.crc) + # extra field is 21 bytes long + # probably contains some unix attrutes or something + # disabled: assert_equal(nil, entry.extra) + assert_equal(ZipEntry::DEFLATED, entry.compression_method) + assert_equal(TestZipFile::TEST_ZIP3.entry_names[0], entry.name) + assert_equal(File.size(TestZipFile::TEST_ZIP3.entry_names[0]), entry.size) + assert(! entry.is_directory) + } + end + + def test_readDateTime + File.open("data/rubycode.zip", "rb") { + |file| + entry = ZipEntry.read_local_entry(file) + assert_equal("zippedruby1.rb", entry.name) + assert_equal(Time.at(1019261638), entry.time) + } + end + + def test_read_local_entryFromNonZipFile + File.open("data/file2.txt") { + |file| + assert_equal(nil, ZipEntry.read_local_entry(file)) + } + end + + def test_read_local_entryFromTruncatedZipFile + zipFragment="" + File.open(TestZipFile::TEST_ZIP2.zip_name) { |f| zipFragment = f.read(12) } # local header is at least 30 bytes + zipFragment.extend(IOizeString).reset + entry = ZipEntry.new + entry.read_local_entry(zipFragment) + fail "ZipError expected" + rescue ZipError + end + + def test_writeEntry + entry = ZipEntry.new("file.zip", "entryName", "my little comment", + "thisIsSomeExtraInformation", 100, 987654, + ZipEntry::DEFLATED, 400) + write_to_file("localEntryHeader.bin", "centralEntryHeader.bin", entry) + entryReadLocal, entryReadCentral = read_from_file("localEntryHeader.bin", "centralEntryHeader.bin") + compare_local_entry_headers(entry, entryReadLocal) + compare_c_dir_entry_headers(entry, entryReadCentral) + end + + private + def compare_local_entry_headers(entry1, entry2) + assert_equal(entry1.compressed_size , entry2.compressed_size) + assert_equal(entry1.crc , entry2.crc) + assert_equal(entry1.extra , entry2.extra) + assert_equal(entry1.compression_method, entry2.compression_method) + assert_equal(entry1.name , entry2.name) + assert_equal(entry1.size , entry2.size) + assert_equal(entry1.localHeaderOffset, entry2.localHeaderOffset) + end + + def compare_c_dir_entry_headers(entry1, entry2) + compare_local_entry_headers(entry1, entry2) + assert_equal(entry1.comment, entry2.comment) + end + + def write_to_file(localFileName, centralFileName, entry) + File.open(localFileName, "wb") { |f| entry.write_local_entry(f) } + File.open(centralFileName, "wb") { |f| entry.write_c_dir_entry(f) } + end + + def read_from_file(localFileName, centralFileName) + localEntry = nil + cdirEntry = nil + File.open(localFileName, "rb") { |f| localEntry = ZipEntry.read_local_entry(f) } + File.open(centralFileName, "rb") { |f| cdirEntry = ZipEntry.read_c_dir_entry(f) } + return [localEntry, cdirEntry] + end +end + + +module DecompressorTests + # expects @refText, @refLines and @decompressor + + TEST_FILE="data/file1.txt" + + def setup + @refText="" + File.open(TEST_FILE) { |f| @refText = f.read } + @refLines = @refText.split($/) + end + + def test_readEverything + assert_equal(@refText, @decompressor.sysread) + end + + def test_readInChunks + chunkSize = 5 + while (decompressedChunk = @decompressor.sysread(chunkSize)) + assert_equal(@refText.slice!(0, chunkSize), decompressedChunk) + end + assert_equal(0, @refText.size) + end + + def test_mixingReadsAndProduceInput + # Just some preconditions to make sure we have enough data for this test + assert(@refText.length > 1000) + assert(@refLines.length > 40) + + + assert_equal(@refText[0...100], @decompressor.sysread(100)) + + assert(! @decompressor.input_finished?) + buf = @decompressor.produce_input + assert_equal(@refText[100...(100+buf.length)], buf) + end +end + +class InflaterTest < Test::Unit::TestCase + include DecompressorTests + + def setup + super + @file = File.new("data/file1.txt.deflatedData", "rb") + @decompressor = Inflater.new(@file) + end + + def teardown + @file.close + end +end + + +class PassThruDecompressorTest < Test::Unit::TestCase + include DecompressorTests + def setup + super + @file = File.new(TEST_FILE) + @decompressor = PassThruDecompressor.new(@file, File.size(TEST_FILE)) + end + + def teardown + @file.close + end +end + + +module AssertEntry + def assert_next_entry(filename, zis) + assert_entry(filename, zis, zis.get_next_entry.name) + end + + def assert_entry(filename, zis, entryName) + assert_equal(filename, entryName) + assert_entryContentsForStream(filename, zis, entryName) + end + + def assert_entryContentsForStream(filename, zis, entryName) + File.open(filename, "rb") { + |file| + expected = file.read + actual = zis.read + if (expected != actual) + if ((expected && actual) && (expected.length > 400 || actual.length > 400)) + zipEntryFilename=entryName+".zipEntry" + File.open(zipEntryFilename, "wb") { |file| file << actual } + fail("File '#{filename}' is different from '#{zipEntryFilename}'") + else + assert_equal(expected, actual) + end + end + } + end + + def AssertEntry.assert_contents(filename, aString) + fileContents = "" + File.open(filename, "rb") { |f| fileContents = f.read } + if (fileContents != aString) + if (fileContents.length > 400 || aString.length > 400) + stringFile = filename + ".other" + File.open(stringFile, "wb") { |f| f << aString } + fail("File '#{filename}' is different from contents of string stored in '#{stringFile}'") + else + assert_equal(fileContents, aString) + end + end + end + + def assert_stream_contents(zis, testZipFile) + assert(zis != nil) + testZipFile.entry_names.each { + |entryName| + assert_next_entry(entryName, zis) + } + assert_equal(nil, zis.get_next_entry) + end + + def assert_test_zip_contents(testZipFile) + ZipInputStream.open(testZipFile.zip_name) { + |zis| + assert_stream_contents(zis, testZipFile) + } + end + + def assert_entryContents(zipFile, entryName, filename = entryName.to_s) + zis = zipFile.get_input_stream(entryName) + assert_entryContentsForStream(filename, zis, entryName) + ensure + zis.close if zis + end +end + + + +class ZipInputStreamTest < Test::Unit::TestCase + include AssertEntry + + def test_new + zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zip_name) + assert_stream_contents(zis, TestZipFile::TEST_ZIP2) + assert_equal(true, zis.eof?) + zis.close + end + + def test_openWithBlock + ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) { + |zis| + assert_stream_contents(zis, TestZipFile::TEST_ZIP2) + assert_equal(true, zis.eof?) + } + end + + def test_openWithoutBlock + zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) + assert_stream_contents(zis, TestZipFile::TEST_ZIP2) + end + + def test_incompleteReads + ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) { + |zis| + entry = zis.get_next_entry # longAscii.txt + assert_equal(false, zis.eof?) + assert_equal(TestZipFile::TEST_ZIP2.entry_names[0], entry.name) + assert zis.gets.length > 0 + assert_equal(false, zis.eof?) + entry = zis.get_next_entry # empty.txt + assert_equal(TestZipFile::TEST_ZIP2.entry_names[1], entry.name) + assert_equal(0, entry.size) + assert_equal(nil, zis.gets) + assert_equal(true, zis.eof?) + entry = zis.get_next_entry # empty_chmod640.txt + assert_equal(TestZipFile::TEST_ZIP2.entry_names[2], entry.name) + assert_equal(0, entry.size) + assert_equal(nil, zis.gets) + assert_equal(true, zis.eof?) + entry = zis.get_next_entry # short.txt + assert_equal(TestZipFile::TEST_ZIP2.entry_names[3], entry.name) + assert zis.gets.length > 0 + entry = zis.get_next_entry # longBinary.bin + assert_equal(TestZipFile::TEST_ZIP2.entry_names[4], entry.name) + assert zis.gets.length > 0 + } + end + + def test_rewind + ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) { + |zis| + e = zis.get_next_entry + assert_equal(TestZipFile::TEST_ZIP2.entry_names[0], e.name) + + # Do a little reading + buf = "" + buf << zis.read(100) + buf << (zis.gets || "") + buf << (zis.gets || "") + assert_equal(false, zis.eof?) + + zis.rewind + + buf2 = "" + buf2 << zis.read(100) + buf2 << (zis.gets || "") + buf2 << (zis.gets || "") + + assert_equal(buf, buf2) + + zis.rewind + assert_equal(false, zis.eof?) + + assert_entry(e.name, zis, e.name) + } + end + + def test_mix_read_and_gets + ZipInputStream.open(TestZipFile::TEST_ZIP2.zip_name) { + |zis| + e = zis.get_next_entry + assert_equal("#!/usr/bin/env ruby", zis.gets.chomp) + assert_equal(false, zis.eof?) + assert_equal("", zis.gets.chomp) + assert_equal(false, zis.eof?) + assert_equal("$VERBOSE =", zis.read(10)) + assert_equal(false, zis.eof?) + } + end + +end + + +module CrcTest + + class TestOutputStream + include IOExtras::AbstractOutputStream + + attr_accessor :buffer + + def initialize + @buffer = "" + end + + def << (data) + @buffer << data + self + end + end + + def run_crc_test(compressorClass) + str = "Here's a nice little text to compute the crc for! Ho hum, it is nice nice nice nice indeed." + fakeOut = TestOutputStream.new + + deflater = compressorClass.new(fakeOut) + deflater << str + assert_equal(0x919920fc, deflater.crc) + end +end + + + +class PassThruCompressorTest < Test::Unit::TestCase + include CrcTest + + def test_size + File.open("dummy.txt", "wb") { + |file| + compressor = PassThruCompressor.new(file) + + assert_equal(0, compressor.size) + + t1 = "hello world" + t2 = "" + t3 = "bingo" + + compressor << t1 + assert_equal(compressor.size, t1.size) + + compressor << t2 + assert_equal(compressor.size, t1.size + t2.size) + + compressor << t3 + assert_equal(compressor.size, t1.size + t2.size + t3.size) + } + end + + def test_crc + run_crc_test(PassThruCompressor) + end +end + +class DeflaterTest < Test::Unit::TestCase + include CrcTest + + def test_outputOperator + txt = load_file("data/file2.txt") + deflate(txt, "deflatertest.bin") + inflatedTxt = inflate("deflatertest.bin") + assert_equal(txt, inflatedTxt) + end + + private + def load_file(fileName) + txt = nil + File.open(fileName, "rb") { |f| txt = f.read } + end + + def deflate(data, fileName) + File.open(fileName, "wb") { + |file| + deflater = Deflater.new(file) + deflater << data + deflater.finish + assert_equal(deflater.size, data.size) + file << "trailing data for zlib with -MAX_WBITS" + } + end + + def inflate(fileName) + txt = nil + File.open(fileName, "rb") { + |file| + inflater = Inflater.new(file) + txt = inflater.sysread + } + end + + def test_crc + run_crc_test(Deflater) + end +end + +class ZipOutputStreamTest < Test::Unit::TestCase + include AssertEntry + + TEST_ZIP = TestZipFile::TEST_ZIP2.clone + TEST_ZIP.zip_name = "output.zip" + + def test_new + zos = ZipOutputStream.new(TEST_ZIP.zip_name) + zos.comment = TEST_ZIP.comment + write_test_zip(zos) + zos.close + assert_test_zip_contents(TEST_ZIP) + end + + def test_open + ZipOutputStream.open(TEST_ZIP.zip_name) { + |zos| + zos.comment = TEST_ZIP.comment + write_test_zip(zos) + } + assert_test_zip_contents(TEST_ZIP) + end + + def test_writingToClosedStream + assert_i_o_error_in_closed_stream { |zos| zos << "hello world" } + assert_i_o_error_in_closed_stream { |zos| zos.puts "hello world" } + assert_i_o_error_in_closed_stream { |zos| zos.write "hello world" } + end + + def test_cannotOpenFile + name = TestFiles::EMPTY_TEST_DIR + begin + zos = ZipOutputStream.open(name) + rescue Exception + assert($!.kind_of?(Errno::EISDIR) || # Linux + $!.kind_of?(Errno::EEXIST) || # Windows/cygwin + $!.kind_of?(Errno::EACCES), # Windows + "Expected Errno::EISDIR (or on win/cygwin: Errno::EEXIST), but was: #{$!.class}") + end + end + + def assert_i_o_error_in_closed_stream + assert_raise(IOError) { + zos = ZipOutputStream.new("test_putOnClosedStream.zip") + zos.close + yield zos + } + end + + def write_test_zip(zos) + TEST_ZIP.entry_names.each { + |entryName| + zos.put_next_entry(entryName) + File.open(entryName, "rb") { |f| zos.write(f.read) } + } + end +end + + + +module Enumerable + def compare_enumerables(otherEnumerable) + otherAsArray = otherEnumerable.to_a + index=0 + each_with_index { + |element, index| + return false unless yield(element, otherAsArray[index]) + } + return index+1 == otherAsArray.size + end +end + + +class ZipCentralDirectoryEntryTest < Test::Unit::TestCase + + def test_read_from_stream + File.open("data/testDirectory.bin", "rb") { + |file| + entry = ZipEntry.read_c_dir_entry(file) + + assert_equal("longAscii.txt", entry.name) + assert_equal(ZipEntry::DEFLATED, entry.compression_method) + assert_equal(106490, entry.size) + assert_equal(3784, entry.compressed_size) + assert_equal(0xfcd1799c, entry.crc) + assert_equal("", entry.comment) + + entry = ZipEntry.read_c_dir_entry(file) + assert_equal("empty.txt", entry.name) + assert_equal(ZipEntry::STORED, entry.compression_method) + assert_equal(0, entry.size) + assert_equal(0, entry.compressed_size) + assert_equal(0x0, entry.crc) + assert_equal("", entry.comment) + + entry = ZipEntry.read_c_dir_entry(file) + assert_equal("short.txt", entry.name) + assert_equal(ZipEntry::STORED, entry.compression_method) + assert_equal(6, entry.size) + assert_equal(6, entry.compressed_size) + assert_equal(0xbb76fe69, entry.crc) + assert_equal("", entry.comment) + + entry = ZipEntry.read_c_dir_entry(file) + assert_equal("longBinary.bin", entry.name) + assert_equal(ZipEntry::DEFLATED, entry.compression_method) + assert_equal(1000024, entry.size) + assert_equal(70847, entry.compressed_size) + assert_equal(0x10da7d59, entry.crc) + assert_equal("", entry.comment) + + entry = ZipEntry.read_c_dir_entry(file) + assert_equal(nil, entry) +# Fields that are not check by this test: +# version made by 2 bytes +# version needed to extract 2 bytes +# general purpose bit flag 2 bytes +# last mod file time 2 bytes +# last mod file date 2 bytes +# compressed size 4 bytes +# uncompressed size 4 bytes +# disk number start 2 bytes +# internal file attributes 2 bytes +# external file attributes 4 bytes +# relative offset of local header 4 bytes + +# file name (variable size) +# extra field (variable size) +# file comment (variable size) + + } + end + + def test_ReadEntryFromTruncatedZipFile + fragment="" + File.open("data/testDirectory.bin") { |f| fragment = f.read(12) } # cdir entry header is at least 46 bytes + fragment.extend(IOizeString) + entry = ZipEntry.new + entry.read_c_dir_entry(fragment) + fail "ZipError expected" + rescue ZipError + end + +end + + +class ZipEntrySetTest < Test::Unit::TestCase + ZIP_ENTRIES = [ + ZipEntry.new("zipfile.zip", "name1", "comment1"), + ZipEntry.new("zipfile.zip", "name2", "comment1"), + ZipEntry.new("zipfile.zip", "name3", "comment1"), + ZipEntry.new("zipfile.zip", "name4", "comment1"), + ZipEntry.new("zipfile.zip", "name5", "comment1"), + ZipEntry.new("zipfile.zip", "name6", "comment1") + ] + + def setup + @zipEntrySet = ZipEntrySet.new(ZIP_ENTRIES) + end + + def test_include + assert(@zipEntrySet.include?(ZIP_ENTRIES.first)) + assert(! @zipEntrySet.include?(ZipEntry.new("different.zip", "different", "aComment"))) + end + + def test_size + assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size) + assert_equal(ZIP_ENTRIES.size, @zipEntrySet.length) + @zipEntrySet << ZipEntry.new("a", "b", "c") + assert_equal(ZIP_ENTRIES.size + 1, @zipEntrySet.length) + end + + def test_add + zes = ZipEntrySet.new + entry1 = ZipEntry.new("zf.zip", "name1") + entry2 = ZipEntry.new("zf.zip", "name2") + zes << entry1 + assert(zes.include?(entry1)) + zes.push(entry2) + assert(zes.include?(entry2)) + end + + def test_delete + assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size) + entry = @zipEntrySet.delete(ZIP_ENTRIES.first) + assert_equal(ZIP_ENTRIES.size - 1, @zipEntrySet.size) + assert_equal(ZIP_ENTRIES.first, entry) + + entry = @zipEntrySet.delete(ZIP_ENTRIES.first) + assert_equal(ZIP_ENTRIES.size - 1, @zipEntrySet.size) + assert_nil(entry) + end + + def test_each + # Tested indirectly via each_with_index + count = 0 + @zipEntrySet.each_with_index { + |entry, index| + assert(ZIP_ENTRIES.include?(entry)) + count = count.succ + } + assert_equal(ZIP_ENTRIES.size, count) + end + + def test_entries + assert_equal(ZIP_ENTRIES.sort, @zipEntrySet.entries.sort) + end + + def test_compound + newEntry = ZipEntry.new("zf.zip", "new entry", "new entry's comment") + assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size) + @zipEntrySet << newEntry + assert_equal(ZIP_ENTRIES.size + 1, @zipEntrySet.size) + assert(@zipEntrySet.include?(newEntry)) + + @zipEntrySet.delete(newEntry) + assert_equal(ZIP_ENTRIES.size, @zipEntrySet.size) + end + + def test_dup + copy = @zipEntrySet.dup + assert_equal(@zipEntrySet, copy) + + # demonstrate that this is a deep copy + copy.entries[0].name = "a totally different name" + assert(@zipEntrySet != copy) + end + + def test_parent + entries = [ + ZipEntry.new("zf.zip", "a"), + ZipEntry.new("zf.zip", "a/"), + ZipEntry.new("zf.zip", "a/b"), + ZipEntry.new("zf.zip", "a/b/"), + ZipEntry.new("zf.zip", "a/b/c"), + ZipEntry.new("zf.zip", "a/b/c/") + ] + entrySet = ZipEntrySet.new(entries) + + assert_equal(nil, entrySet.parent(entries[0])) + assert_equal(nil, entrySet.parent(entries[1])) + assert_equal(entries[1], entrySet.parent(entries[2])) + assert_equal(entries[1], entrySet.parent(entries[3])) + assert_equal(entries[3], entrySet.parent(entries[4])) + assert_equal(entries[3], entrySet.parent(entries[5])) + end + + def test_glob + res = @zipEntrySet.glob('name[2-4]') + assert_equal(3, res.size) + assert_equal(ZIP_ENTRIES[1,3], res) + end + + def test_glob2 + entries = [ + ZipEntry.new("zf.zip", "a/"), + ZipEntry.new("zf.zip", "a/b/b1"), + ZipEntry.new("zf.zip", "a/b/c/"), + ZipEntry.new("zf.zip", "a/b/c/c1") + ] + entrySet = ZipEntrySet.new(entries) + + assert_equal(entries[0,1], entrySet.glob("*")) +# assert_equal(entries[FIXME], entrySet.glob("**")) +# res = entrySet.glob('a*') +# assert_equal(entries.size, res.size) +# assert_equal(entrySet.map { |e| e.name }, res.map { |e| e.name }) + end +end + + +class ZipCentralDirectoryTest < Test::Unit::TestCase + + def test_read_from_stream + File.open(TestZipFile::TEST_ZIP2.zip_name, "rb") { + |zipFile| + cdir = ZipCentralDirectory.read_from_stream(zipFile) + + assert_equal(TestZipFile::TEST_ZIP2.entry_names.size, cdir.size) + assert(cdir.entries.sort.compare_enumerables(TestZipFile::TEST_ZIP2.entry_names.sort) { + |cdirEntry, testEntryName| + cdirEntry.name == testEntryName + }) + assert_equal(TestZipFile::TEST_ZIP2.comment, cdir.comment) + } + end + + def test_readFromInvalidStream + File.open("data/file2.txt", "rb") { + |zipFile| + cdir = ZipCentralDirectory.new + cdir.read_from_stream(zipFile) + } + fail "ZipError expected!" + rescue ZipError + end + + def test_ReadFromTruncatedZipFile + fragment="" + File.open("data/testDirectory.bin") { |f| fragment = f.read } + fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete + fragment.extend(IOizeString) + entry = ZipCentralDirectory.new + entry.read_from_stream(fragment) + fail "ZipError expected" + rescue ZipError + end + + def test_write_to_stream + entries = [ ZipEntry.new("file.zip", "flimse", "myComment", "somethingExtra"), + ZipEntry.new("file.zip", "secondEntryName"), + ZipEntry.new("file.zip", "lastEntry.txt", "Has a comment too") ] + cdir = ZipCentralDirectory.new(entries, "my zip comment") + File.open("cdirtest.bin", "wb") { |f| cdir.write_to_stream(f) } + cdirReadback = ZipCentralDirectory.new + File.open("cdirtest.bin", "rb") { |f| cdirReadback.read_from_stream(f) } + + assert_equal(cdir.entries.sort, cdirReadback.entries.sort) + end + + def test_equality + cdir1 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, + "somethingExtra"), + ZipEntry.new("file.zip", "secondEntryName"), + ZipEntry.new("file.zip", "lastEntry.txt") ], + "my zip comment") + cdir2 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, + "somethingExtra"), + ZipEntry.new("file.zip", "secondEntryName"), + ZipEntry.new("file.zip", "lastEntry.txt") ], + "my zip comment") + cdir3 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, + "somethingExtra"), + ZipEntry.new("file.zip", "secondEntryName"), + ZipEntry.new("file.zip", "lastEntry.txt") ], + "comment?") + cdir4 = ZipCentralDirectory.new([ ZipEntry.new("file.zip", "flimse", nil, + "somethingExtra"), + ZipEntry.new("file.zip", "lastEntry.txt") ], + "comment?") + assert_equal(cdir1, cdir1) + assert_equal(cdir1, cdir2) + + assert(cdir1 != cdir3) + assert(cdir2 != cdir3) + assert(cdir2 != cdir3) + assert(cdir3 != cdir4) + + assert(cdir3 != "hello") + end +end + + +class BasicZipFileTest < Test::Unit::TestCase + include AssertEntry + + def setup + @zipFile = ZipFile.new(TestZipFile::TEST_ZIP2.zip_name) + @testEntryNameIndex=0 + end + + def test_entries + assert_equal(TestZipFile::TEST_ZIP2.entry_names.sort, + @zipFile.entries.entries.sort.map {|e| e.name} ) + end + + def test_each + count = 0 + visited = {} + @zipFile.each { + |entry| + assert(TestZipFile::TEST_ZIP2.entry_names.include?(entry.name)) + assert(! visited.include?(entry.name)) + visited[entry.name] = nil + count = count.succ + } + assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count) + end + + def test_foreach + count = 0 + visited = {} + ZipFile.foreach(TestZipFile::TEST_ZIP2.zip_name) { + |entry| + assert(TestZipFile::TEST_ZIP2.entry_names.include?(entry.name)) + assert(! visited.include?(entry.name)) + visited[entry.name] = nil + count = count.succ + } + assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count) + end + + def test_get_input_stream + count = 0 + visited = {} + @zipFile.each { + |entry| + assert_entry(entry.name, @zipFile.get_input_stream(entry), entry.name) + assert(! visited.include?(entry.name)) + visited[entry.name] = nil + count = count.succ + } + assert_equal(TestZipFile::TEST_ZIP2.entry_names.length, count) + end + + def test_get_input_streamBlock + fileAndEntryName = @zipFile.entries.first.name + @zipFile.get_input_stream(fileAndEntryName) { + |zis| + assert_entryContentsForStream(fileAndEntryName, + zis, + fileAndEntryName) + } + end +end + +module CommonZipFileFixture + include AssertEntry + + EMPTY_FILENAME = "emptyZipFile.zip" + + TEST_ZIP = TestZipFile::TEST_ZIP2.clone + TEST_ZIP.zip_name = "5entry_copy.zip" + + def setup + File.delete(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME) + File.copy(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name) + end +end + +class ZipFileTest < Test::Unit::TestCase + include CommonZipFileFixture + + def test_createFromScratch + comment = "a short comment" + + zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) + zf.get_output_stream("myFile") { |os| os.write "myFile contains just this" } + zf.mkdir("dir1") + zf.comment = comment + zf.close + + zfRead = ZipFile.new(EMPTY_FILENAME) + assert_equal(comment, zfRead.comment) + assert_equal(2, zfRead.entries.length) + end + + def test_get_output_stream + entryCount = nil + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + entryCount = zf.size + zf.get_output_stream('newEntry.txt') { + |os| + os.write "Putting stuff in newEntry.txt" + } + assert_equal(entryCount+1, zf.size) + assert_equal("Putting stuff in newEntry.txt", zf.read("newEntry.txt")) + + zf.get_output_stream(zf.get_entry('data/generated/empty.txt')) { + |os| + os.write "Putting stuff in data/generated/empty.txt" + } + assert_equal(entryCount+1, zf.size) + assert_equal("Putting stuff in data/generated/empty.txt", zf.read("data/generated/empty.txt")) + + zf.get_output_stream('entry.bin') { + |os| + os.write(File.open('data/generated/5entry.zip', 'rb').read) + } + } + + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + assert_equal(entryCount+2, zf.size) + assert_equal("Putting stuff in newEntry.txt", zf.read("newEntry.txt")) + assert_equal("Putting stuff in data/generated/empty.txt", zf.read("data/generated/empty.txt")) + assert_equal(File.open('data/generated/5entry.zip', 'rb').read, zf.read("entry.bin")) + } + end + + def test_add + srcFile = "data/file2.txt" + entryName = "newEntryName.rb" + assert(File.exists?(srcFile)) + zf = ZipFile.new(EMPTY_FILENAME, ZipFile::CREATE) + zf.add(entryName, srcFile) + zf.close + + zfRead = ZipFile.new(EMPTY_FILENAME) + assert_equal("", zfRead.comment) + assert_equal(1, zfRead.entries.length) + assert_equal(entryName, zfRead.entries.first.name) + AssertEntry.assert_contents(srcFile, + zfRead.get_input_stream(entryName) { |zis| zis.read }) + end + + def test_addExistingEntryName + assert_raise(ZipEntryExistsError) { + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + zf.add(zf.entries.first.name, "data/file2.txt") + } + } + end + + def test_addExistingEntryNameReplace + gotCalled = false + replacedEntry = nil + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + replacedEntry = zf.entries.first.name + zf.add(replacedEntry, "data/file2.txt") { gotCalled = true; true } + } + assert(gotCalled) + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + assert_contains(zf, replacedEntry, "data/file2.txt") + } + end + + def test_addDirectory + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + zf.add(TestFiles::EMPTY_TEST_DIR, TestFiles::EMPTY_TEST_DIR) + } + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + dirEntry = zf.entries.detect { |e| e.name == TestFiles::EMPTY_TEST_DIR+"/" } + assert(dirEntry.is_directory) + } + end + + def test_remove + entryToRemove, *remainingEntries = TEST_ZIP.entry_names + + File.copy(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name) + + zf = ZipFile.new(TEST_ZIP.zip_name) + assert(zf.entries.map { |e| e.name }.include?(entryToRemove)) + zf.remove(entryToRemove) + assert(! zf.entries.map { |e| e.name }.include?(entryToRemove)) + assert_equal(zf.entries.map {|x| x.name }.sort, remainingEntries.sort) + zf.close + + zfRead = ZipFile.new(TEST_ZIP.zip_name) + assert(! zfRead.entries.map { |e| e.name }.include?(entryToRemove)) + assert_equal(zfRead.entries.map {|x| x.name }.sort, remainingEntries.sort) + zfRead.close + end + + + def test_rename + entryToRename, *remainingEntries = TEST_ZIP.entry_names + + zf = ZipFile.new(TEST_ZIP.zip_name) + assert(zf.entries.map { |e| e.name }.include?(entryToRename)) + + newName = "changed name" + assert(! zf.entries.map { |e| e.name }.include?(newName)) + + zf.rename(entryToRename, newName) + assert(zf.entries.map { |e| e.name }.include?(newName)) + + zf.close + + zfRead = ZipFile.new(TEST_ZIP.zip_name) + assert(zfRead.entries.map { |e| e.name }.include?(newName)) + zfRead.close + end + + def test_renameToExistingEntry + oldEntries = nil + ZipFile.open(TEST_ZIP.zip_name) { |zf| oldEntries = zf.entries } + + assert_raise(ZipEntryExistsError) { + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + zf.rename(zf.entries[0], zf.entries[1].name) + } + } + + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + assert_equal(oldEntries.sort.map{ |e| e.name }, zf.entries.sort.map{ |e| e.name }) + } + end + + def test_renameToExistingEntryOverwrite + oldEntries = nil + ZipFile.open(TEST_ZIP.zip_name) { |zf| oldEntries = zf.entries } + + gotCalled = false + renamedEntryName = nil + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + renamedEntryName = zf.entries[0].name + zf.rename(zf.entries[0], zf.entries[1].name) { gotCalled = true; true } + } + + assert(gotCalled) + oldEntries.delete_if { |e| e.name == renamedEntryName } + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + assert_equal(oldEntries.sort.map{ |e| e.name }, + zf.entries.sort.map{ |e| e.name }) + } + end + + def test_renameNonEntry + nonEntry = "bogusEntry" + target_entry = "target_entryName" + zf = ZipFile.new(TEST_ZIP.zip_name) + assert(! zf.entries.include?(nonEntry)) + assert_raise(Errno::ENOENT) { + zf.rename(nonEntry, target_entry) + } + zf.commit + assert(! zf.entries.include?(target_entry)) + ensure + zf.close + end + + def test_renameEntryToExistingEntry + entry1, entry2, *remaining = TEST_ZIP.entry_names + zf = ZipFile.new(TEST_ZIP.zip_name) + assert_raise(ZipEntryExistsError) { + zf.rename(entry1, entry2) + } + ensure + zf.close + end + + def test_replace + entryToReplace = TEST_ZIP.entry_names[2] + newEntrySrcFilename = "data/file2.txt" + zf = ZipFile.new(TEST_ZIP.zip_name) + zf.replace(entryToReplace, newEntrySrcFilename) + + zf.close + zfRead = ZipFile.new(TEST_ZIP.zip_name) + AssertEntry::assert_contents(newEntrySrcFilename, + zfRead.get_input_stream(entryToReplace) { |is| is.read }) + AssertEntry::assert_contents(TEST_ZIP.entry_names[0], + zfRead.get_input_stream(TEST_ZIP.entry_names[0]) { |is| is.read }) + AssertEntry::assert_contents(TEST_ZIP.entry_names[1], + zfRead.get_input_stream(TEST_ZIP.entry_names[1]) { |is| is.read }) + AssertEntry::assert_contents(TEST_ZIP.entry_names[3], + zfRead.get_input_stream(TEST_ZIP.entry_names[3]) { |is| is.read }) + zfRead.close + end + + def test_replaceNonEntry + entryToReplace = "nonExistingEntryname" + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + assert_raise(Errno::ENOENT) { + zf.replace(entryToReplace, "data/file2.txt") + } + } + end + + def test_commit + newName = "renamedFirst" + zf = ZipFile.new(TEST_ZIP.zip_name) + oldName = zf.entries.first + zf.rename(oldName, newName) + zf.commit + + zfRead = ZipFile.new(TEST_ZIP.zip_name) + assert(zfRead.entries.detect { |e| e.name == newName } != nil) + assert(zfRead.entries.detect { |e| e.name == oldName } == nil) + zfRead.close + + zf.close + end + + # This test tests that after commit, you + # can delete the file you used to add the entry to the zip file + # with + def test_commitUseZipEntry + File.copy(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt") + zf = ZipFile.open(TEST_ZIP.zip_name) + zf.add("okToDelete.txt", "okToDelete.txt") + assert_contains(zf, "okToDelete.txt") + zf.commit + File.move("okToDelete.txt", "okToDeleteMoved.txt") + assert_contains(zf, "okToDelete.txt", "okToDeleteMoved.txt") + end + +# def test_close +# zf = ZipFile.new(TEST_ZIP.zip_name) +# zf.close +# assert_raise(IOError) { +# zf.extract(TEST_ZIP.entry_names.first, "hullubullu") +# } +# end + + def test_compound1 + renamedName = "renamedName" + originalEntries = [] + begin + zf = ZipFile.new(TEST_ZIP.zip_name) + originalEntries = zf.entries.dup + + assert_not_contains(zf, TestFiles::RANDOM_ASCII_FILE1) + zf.add(TestFiles::RANDOM_ASCII_FILE1, + TestFiles::RANDOM_ASCII_FILE1) + assert_contains(zf, TestFiles::RANDOM_ASCII_FILE1) + + zf.rename(zf.entries[0], renamedName) + assert_contains(zf, renamedName) + + TestFiles::BINARY_TEST_FILES.each { + |filename| + zf.add(filename, filename) + assert_contains(zf, filename) + } + + assert_contains(zf, originalEntries.last.to_s) + zf.remove(originalEntries.last.to_s) + assert_not_contains(zf, originalEntries.last.to_s) + + ensure + zf.close + end + begin + zfRead = ZipFile.new(TEST_ZIP.zip_name) + assert_contains(zfRead, TestFiles::RANDOM_ASCII_FILE1) + assert_contains(zfRead, renamedName) + TestFiles::BINARY_TEST_FILES.each { + |filename| + assert_contains(zfRead, filename) + } + assert_not_contains(zfRead, originalEntries.last.to_s) + ensure + zfRead.close + end + end + + def test_compound2 + begin + zf = ZipFile.new(TEST_ZIP.zip_name) + originalEntries = zf.entries.dup + + originalEntries.each { + |entry| + zf.remove(entry) + assert_not_contains(zf, entry) + } + assert(zf.entries.empty?) + + TestFiles::ASCII_TEST_FILES.each { + |filename| + zf.add(filename, filename) + assert_contains(zf, filename) + } + assert_equal(zf.entries.sort.map { |e| e.name }, TestFiles::ASCII_TEST_FILES) + + zf.rename(TestFiles::ASCII_TEST_FILES[0], "newName") + assert_not_contains(zf, TestFiles::ASCII_TEST_FILES[0]) + assert_contains(zf, "newName") + ensure + zf.close + end + begin + zfRead = ZipFile.new(TEST_ZIP.zip_name) + asciiTestFiles = TestFiles::ASCII_TEST_FILES.dup + asciiTestFiles.shift + asciiTestFiles.each { + |filename| + assert_contains(zf, filename) + } + + assert_contains(zf, "newName") + ensure + zfRead.close + end + end + + private + def assert_contains(zf, entryName, filename = entryName) + assert(zf.entries.detect { |e| e.name == entryName} != nil, "entry #{entryName} not in #{zf.entries.join(', ')} in zip file #{zf}") + assert_entryContents(zf, entryName, filename) if File.exists?(filename) + end + + def assert_not_contains(zf, entryName) + assert(zf.entries.detect { |e| e.name == entryName} == nil, "entry #{entryName} in #{zf.entries.join(', ')} in zip file #{zf}") + end +end + +class ZipFileExtractTest < Test::Unit::TestCase + include CommonZipFileFixture + EXTRACTED_FILENAME = "extEntry" + ENTRY_TO_EXTRACT, *REMAINING_ENTRIES = TEST_ZIP.entry_names.reverse + + def setup + super + File.delete(EXTRACTED_FILENAME) if File.exists?(EXTRACTED_FILENAME) + end + + def test_extract + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + zf.extract(ENTRY_TO_EXTRACT, EXTRACTED_FILENAME) + + assert(File.exists?(EXTRACTED_FILENAME)) + AssertEntry::assert_contents(EXTRACTED_FILENAME, + zf.get_input_stream(ENTRY_TO_EXTRACT) { |is| is.read }) + + + File::unlink(EXTRACTED_FILENAME) + + entry = zf.get_entry(ENTRY_TO_EXTRACT) + entry.extract(EXTRACTED_FILENAME) + + assert(File.exists?(EXTRACTED_FILENAME)) + AssertEntry::assert_contents(EXTRACTED_FILENAME, + entry.get_input_stream() { |is| is.read }) + + } + end + + def test_extractExists + writtenText = "written text" + File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } + + assert_raise(ZipDestinationFileExistsError) { + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + zf.extract(zf.entries.first, EXTRACTED_FILENAME) + } + } + File.open(EXTRACTED_FILENAME, "r") { + |f| + assert_equal(writtenText, f.read) + } + end + + def test_extractExistsOverwrite + writtenText = "written text" + File.open(EXTRACTED_FILENAME, "w") { |f| f.write(writtenText) } + + gotCalledCorrectly = false + ZipFile.open(TEST_ZIP.zip_name) { + |zf| + zf.extract(zf.entries.first, EXTRACTED_FILENAME) { + |entry, extractLoc| + gotCalledCorrectly = zf.entries.first == entry && + extractLoc == EXTRACTED_FILENAME + true + } + } + + assert(gotCalledCorrectly) + File.open(EXTRACTED_FILENAME, "r") { + |f| + assert(writtenText != f.read) + } + end + + def test_extractNonEntry + zf = ZipFile.new(TEST_ZIP.zip_name) + assert_raise(Errno::ENOENT) { zf.extract("nonExistingEntry", "nonExistingEntry") } + ensure + zf.close if zf + end + + def test_extractNonEntry2 + outFile = "outfile" + assert_raise(Errno::ENOENT) { + zf = ZipFile.new(TEST_ZIP.zip_name) + nonEntry = "hotdog-diddelidoo" + assert(! zf.entries.include?(nonEntry)) + zf.extract(nonEntry, outFile) + zf.close + } + assert(! File.exists?(outFile)) + end + +end + +class ZipFileExtractDirectoryTest < Test::Unit::TestCase + include CommonZipFileFixture + TEST_OUT_NAME = "emptyOutDir" + + def open_zip(&aProc) + assert(aProc != nil) + ZipFile.open(TestZipFile::TEST_ZIP4.zip_name, &aProc) + end + + def extract_test_dir(&aProc) + open_zip { + |zf| + zf.extract(TestFiles::EMPTY_TEST_DIR, TEST_OUT_NAME, &aProc) + } + end + + def setup + super + + Dir.rmdir(TEST_OUT_NAME) if File.directory? TEST_OUT_NAME + File.delete(TEST_OUT_NAME) if File.exists? TEST_OUT_NAME + end + + def test_extractDirectory + extract_test_dir + assert(File.directory?(TEST_OUT_NAME)) + end + + def test_extractDirectoryExistsAsDir + Dir.mkdir TEST_OUT_NAME + extract_test_dir + assert(File.directory?(TEST_OUT_NAME)) + end + + def test_extractDirectoryExistsAsFile + File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } + assert_raise(ZipDestinationFileExistsError) { extract_test_dir } + end + + def test_extractDirectoryExistsAsFileOverwrite + File.open(TEST_OUT_NAME, "w") { |f| f.puts "something" } + gotCalled = false + extract_test_dir { + |entry, destPath| + gotCalled = true + assert_equal(TEST_OUT_NAME, destPath) + assert(entry.is_directory) + true + } + assert(gotCalled) + assert(File.directory?(TEST_OUT_NAME)) + end +end + +class ZipExtraFieldTest < Test::Unit::TestCase + def test_new + extra_pure = ZipExtraField.new("") + extra_withstr = ZipExtraField.new("foo") + assert_instance_of(ZipExtraField, extra_pure) + assert_instance_of(ZipExtraField, extra_withstr) + end + + def test_unknownfield + extra = ZipExtraField.new("foo") + assert_equal(extra["Unknown"], "foo") + extra.merge("a") + assert_equal(extra["Unknown"], "fooa") + extra.merge("barbaz") + assert_equal(extra.to_s, "fooabarbaz") + end + + + def test_merge + str = "UT\x5\0\x3\250$\r@Ux\0\0" + extra1 = ZipExtraField.new("") + extra2 = ZipExtraField.new(str) + assert(! extra1.member?("UniversalTime")) + assert(extra2.member?("UniversalTime")) + extra1.merge(str) + assert_equal(extra1["UniversalTime"].mtime, extra2["UniversalTime"].mtime) + end + + def test_length + str = "UT\x5\0\x3\250$\r@Ux\0\0Te\0\0testit" + extra = ZipExtraField.new(str) + assert_equal(extra.local_length, extra.to_local_bin.length) + assert_equal(extra.c_dir_length, extra.to_c_dir_bin.length) + extra.merge("foo") + assert_equal(extra.local_length, extra.to_local_bin.length) + assert_equal(extra.c_dir_length, extra.to_c_dir_bin.length) + end + + + def test_to_s + str = "UT\x5\0\x3\250$\r@Ux\0\0Te\0\0testit" + extra = ZipExtraField.new(str) + assert_instance_of(String, extra.to_s) + + s = extra.to_s + extra.merge("foo") + assert_equal(s.length + 3, extra.to_s.length) + end + + def test_equality + str = "UT\x5\0\x3\250$\r@" + extra1 = ZipExtraField.new(str) + extra2 = ZipExtraField.new(str) + extra3 = ZipExtraField.new(str) + assert_equal(extra1, extra2) + + extra2["UniversalTime"].mtime = Time.now + assert(extra1 != extra2) + + extra3.create("IUnix") + assert(extra1 != extra3) + + extra1.create("IUnix") + assert_equal(extra1, extra3) + end + +end + +# Copyright (C) 2002-2005 Thomas Sondergaard +# rubyzip is free software; you can redistribute it and/or +# modify it under the terms of the ruby license.