Initial revision
This commit is contained in:
commit
609f3527d5
|
|
@ -0,0 +1,29 @@
|
|||
= rubyzip =
|
||||
|
||||
rubyzip is a ruby library for reading and writing zip (pkzip format)
|
||||
files, with the restriction that only uncompressed and deflated zip
|
||||
entries are supported. All this library does is handling of the zip
|
||||
file format. the actual compression/decompression is handled by zlib
|
||||
|
||||
|
||||
= Resources =
|
||||
zlib http://www.gzip.org/zlib/
|
||||
ruby-zlib: http://www.blue.sky.or.jp/atelier/#ruby-zlib
|
||||
|
||||
|
||||
= Ruby/zlib issue =
|
||||
|
||||
There is a problem with ruby/zlib version 0.4.0 and earlier concerning
|
||||
wbits, that prevents rubyzip from working. The ruby wrapper does some
|
||||
parameters checks of its own, and restrict the wbits parameter passed
|
||||
to inflateInit2 from being negative. Apply the patch 'zlib.c.diff' to
|
||||
zlib.c from ruby/zlib, then rebuild and install ruby/zlib to fix the
|
||||
issue.
|
||||
|
||||
= Missing tests =
|
||||
|
||||
zip.rb is only 280 lines. Go through it and check for each line
|
||||
whether there is a test for it!
|
||||
|
||||
= todo for release 0.2.0 =
|
||||
Write ZipFile or ZipDir that reads the zip central directory
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
system("zip example.zip example.rb")
|
||||
|
||||
require 'zip'
|
||||
|
||||
ZipInputStream.open("example.zip") {
|
||||
|zis|
|
||||
entry = zis.getNextEntry
|
||||
puts "Zip entry '#{entry.name}' contains:"
|
||||
puts zis.read
|
||||
}
|
||||
|
||||
# For other examples, look at zip.rb and ziptest.rb
|
||||
|
|
@ -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$@ $^
|
||||
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'singleton'
|
||||
require 'zlib'
|
||||
|
||||
# Implements many of the convenience methods of IO
|
||||
# such as gets, getc, readline and readlines
|
||||
module PseudoIO
|
||||
def readlines(aSepString = $/)
|
||||
retVal = []
|
||||
each_line(aSepString) { |line| retVal << line }
|
||||
return retVal
|
||||
end
|
||||
|
||||
def gets(aSepString=$/)
|
||||
@outputBuffer="" unless @outputBuffer
|
||||
return read if aSepString == nil
|
||||
aSepString="#{$/}#{$/}" if aSepString == ""
|
||||
|
||||
bufferIndex=0
|
||||
while ((matchIndex = @outputBuffer.index(aSepString, bufferIndex)) == nil)
|
||||
bufferIndex=@outputBuffer.length
|
||||
if inputFinished?
|
||||
return @outputBuffer.length==0 ? nil : flush
|
||||
end
|
||||
@outputBuffer << produceInput
|
||||
end
|
||||
sepIndex=matchIndex + aSepString.length
|
||||
return @outputBuffer.slice!(0...sepIndex)
|
||||
end
|
||||
|
||||
def flush
|
||||
retVal=@outputBuffer
|
||||
@outputBuffer=""
|
||||
return retVal
|
||||
end
|
||||
|
||||
def readline(aSepString = $/)
|
||||
retVal = gets(aSepString)
|
||||
raise EOFError if retVal == nil
|
||||
return retVal
|
||||
end
|
||||
|
||||
def each_line(aSepString = $/)
|
||||
while true
|
||||
yield readline
|
||||
end
|
||||
rescue EOFError
|
||||
end
|
||||
|
||||
alias_method :each, :each_line
|
||||
end
|
||||
|
||||
|
||||
|
||||
class ZipInputStream
|
||||
include PseudoIO
|
||||
|
||||
def initialize(filename)
|
||||
@archiveIO = File.open(filename, "rb")
|
||||
@decompressor = NullDecompressor.instance
|
||||
end
|
||||
|
||||
def close
|
||||
puts "IMPLEMENT ME: ZipInputStream::close"
|
||||
end
|
||||
|
||||
def ZipInputStream.open(filename)
|
||||
return new(filename) unless block_given?
|
||||
|
||||
zio = new(filename)
|
||||
yield zio
|
||||
zio.close
|
||||
end
|
||||
|
||||
def getNextEntry
|
||||
@archiveIO.seek(@currentEntry.nextHeaderOffset,
|
||||
IO::SEEK_SET) if @currentEntry
|
||||
|
||||
@currentEntry = ZipLocalEntry.readFromStream(@archiveIO)
|
||||
if (@currentEntry == nil)
|
||||
@decompressor = NullDecompressor.instance
|
||||
elsif @currentEntry.compressionMethod == ZipEntry::STORED
|
||||
@decompressor = PassThruDecompressor.new(@archiveIO,
|
||||
@currentEntry.size)
|
||||
elsif @currentEntry.compressionMethod == ZipEntry::DEFLATED
|
||||
@decompressor = Inflater.new(@archiveIO)
|
||||
else
|
||||
raise "Unsupported compression method #{@currentEntry.compressionMethod}"
|
||||
end
|
||||
flush
|
||||
return @currentEntry
|
||||
end
|
||||
|
||||
def read(numberOfBytes = nil)
|
||||
@decompressor.read(numberOfBytes)
|
||||
end
|
||||
protected
|
||||
def produceInput
|
||||
@decompressor.produceInput
|
||||
end
|
||||
|
||||
def inputFinished?
|
||||
@decompressor.inputFinished?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class Decompressor
|
||||
CHUNK_SIZE=8192
|
||||
def initialize(inputStream)
|
||||
@inputStream=inputStream
|
||||
end
|
||||
end
|
||||
|
||||
class Inflater < Decompressor
|
||||
def initialize(inputStream)
|
||||
super
|
||||
@zlibInflater = Inflate.new(-Inflate::MAX_WBITS)
|
||||
@outputBuffer=""
|
||||
end
|
||||
|
||||
def read(numberOfBytes = nil)
|
||||
readEverything = (numberOfBytes == nil)
|
||||
while (readEverything || @outputBuffer.length < numberOfBytes)
|
||||
break if inputFinished?
|
||||
@outputBuffer << produceInput
|
||||
end
|
||||
return nil if @outputBuffer.length==0 && inputFinished?
|
||||
endIndex= numberOfBytes==nil ? @outputBuffer.length : numberOfBytes
|
||||
return @outputBuffer.slice!(0...endIndex)
|
||||
end
|
||||
|
||||
def produceInput
|
||||
@zlibInflater.inflate(@inputStream.read(Decompressor::CHUNK_SIZE))
|
||||
end
|
||||
|
||||
def inputFinished?
|
||||
@zlibInflater.finished?
|
||||
end
|
||||
end
|
||||
|
||||
class PassThruDecompressor < Decompressor
|
||||
def initialize(inputStream, charsToRead)
|
||||
super inputStream
|
||||
@charsToRead = charsToRead
|
||||
@readSoFar = 0
|
||||
@isFirst=true
|
||||
end
|
||||
|
||||
def read(numberOfBytes = nil)
|
||||
if inputFinished?
|
||||
isFirstVal=@isFirst
|
||||
@isFirst=false
|
||||
return "" if isFirstVal
|
||||
return nil
|
||||
end
|
||||
|
||||
if (numberOfBytes == nil || @readSoFar+numberOfBytes > @charsToRead)
|
||||
numberOfBytes = @charsToRead-@readSoFar
|
||||
end
|
||||
@readSoFar += numberOfBytes
|
||||
@inputStream.read(numberOfBytes)
|
||||
end
|
||||
|
||||
def produceInput
|
||||
read(Decompressor::CHUNK_SIZE)
|
||||
end
|
||||
|
||||
def inputFinished?
|
||||
(@readSoFar >= @charsToRead)
|
||||
end
|
||||
end
|
||||
|
||||
class NullDecompressor
|
||||
include Singleton
|
||||
def read(numberOfBytes = nil)
|
||||
nil
|
||||
end
|
||||
|
||||
def produceInput
|
||||
nil
|
||||
end
|
||||
|
||||
def inputFinished?
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class ZipEntry
|
||||
STORED = 0
|
||||
DEFLATED = 8
|
||||
|
||||
attr_reader :comment, :compressedSize, :crc, :extra, :compressionMethod,
|
||||
:name, :size, :localHeaderOffset
|
||||
|
||||
def initialize(comment = nil, compressedSize = nil, crc = nil, extra = nil,
|
||||
compressionMethod = nil, name = nil, size = nil)
|
||||
@comment, @compressedSize, @crc, @extra, @compressionMethod,
|
||||
@name, @size, @isDirectory = comment, compressedSize, crc,
|
||||
extra, compressionMethod, name, size
|
||||
end
|
||||
|
||||
def isDirectory
|
||||
return (/\/$/ =~ @name) != nil
|
||||
end
|
||||
|
||||
def localEntryOffset
|
||||
localHeaderOffset + localHeaderSize
|
||||
end
|
||||
|
||||
def localHeaderSize
|
||||
30 + name.size + extra.size
|
||||
end
|
||||
|
||||
def nextHeaderOffset
|
||||
localEntryOffset + self.compressedSize
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def ZipEntry.readZipShort(io)
|
||||
io.read(2).unpack('v')[0]
|
||||
end
|
||||
|
||||
def ZipEntry.readZipLong(io)
|
||||
io.read(4).unpack('V')[0]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
class ZipLocalEntry < ZipEntry
|
||||
LOCAL_ENTRY_SIGNATURE = 0x04034b50
|
||||
|
||||
def readFromStream(io)
|
||||
unless (ZipEntry::readZipLong(io) == LOCAL_ENTRY_SIGNATURE)
|
||||
raise ZipError,
|
||||
"Zip Local Header magic '#{LOCAL_ENTRY_SIGNATURE} not found"
|
||||
end
|
||||
@localHeaderOffset = io. tell - 4
|
||||
@version = ZipEntry::readZipShort(io)
|
||||
@gpFlags = ZipEntry::readZipShort(io)
|
||||
@compressionMethod = ZipEntry::readZipShort(io)
|
||||
@lastModTime = ZipEntry::readZipShort(io)
|
||||
@lastModDate = ZipEntry::readZipShort(io)
|
||||
@crc = ZipEntry::readZipLong(io)
|
||||
@compressedSize = ZipEntry::readZipLong(io)
|
||||
@size = ZipEntry::readZipLong(io)
|
||||
nameLength = ZipEntry::readZipShort(io)
|
||||
extraLength = ZipEntry::readZipShort(io)
|
||||
@name = io.read(nameLength)
|
||||
@extra = io.read(extraLength)
|
||||
end
|
||||
|
||||
def ZipLocalEntry.readFromStream(io)
|
||||
entry = new()
|
||||
entry.readFromStream(io)
|
||||
return entry
|
||||
rescue ZipError
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
# class ZipCentralDirectoryEntry < ZipEntry
|
||||
# ZIP_CENTRAL_DIRECTORY_ENTRY_SIGNATURE = 0x02014b50
|
||||
|
||||
# def readFromStream(io)
|
||||
# end
|
||||
|
||||
# def ZipCentralDirectoryEntry.readFromStream(io)
|
||||
# entry = new()
|
||||
# entry.readFromStream(io)
|
||||
# return entry
|
||||
# rescue ZipError
|
||||
# return nil
|
||||
# end
|
||||
# end
|
||||
|
||||
class ZipError < RuntimeError
|
||||
end
|
||||
|
||||
class ZipFile
|
||||
include Enumerable
|
||||
|
||||
attr_reader :name
|
||||
|
||||
def initialize(name)
|
||||
@name=name
|
||||
end
|
||||
|
||||
def ZipFile.foreach(aZipFileName, &block)
|
||||
zipFile = ZipFile.new(aZipFileName)
|
||||
zipFile.each &block
|
||||
end
|
||||
|
||||
def each
|
||||
end
|
||||
|
||||
def getInputStream(entry)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,372 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'runit/testcase'
|
||||
require 'runit/cui/testrunner'
|
||||
require 'zip'
|
||||
|
||||
class PseudoIOTest < RUNIT::TestCase
|
||||
# PseudoIO 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 TestPseudoIO
|
||||
include PseudoIO
|
||||
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 = TestPseudoIO.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_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_COMMENT,
|
||||
TEST_COMPRESSED_SIZE,
|
||||
TEST_CRC,
|
||||
TEST_EXTRA,
|
||||
TEST_COMPRESSIONMETHOD,
|
||||
TEST_NAME,
|
||||
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
|
||||
end
|
||||
|
||||
class ZipLocalEntryTest < RUNIT::TestCase
|
||||
def test_ReadLocalEntryHeaderOfFirstTestZipEntry
|
||||
File.open(TestZipFile::TEST_ZIP3.zipName) {
|
||||
|file|
|
||||
entry = ZipLocalEntry.readFromStream(file)
|
||||
|
||||
assert_equal(nil, entry.comment)
|
||||
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(1373, entry.size)
|
||||
assert_equal(false, entry.isDirectory)
|
||||
}
|
||||
end
|
||||
def test_ReadLocalEntryFromNonZipFile
|
||||
File.open("ziptest.rb") {
|
||||
|file|
|
||||
ZipLocalEntry.readFromStream(file)
|
||||
}
|
||||
fail "Excepted exception"
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
module AssertEntry
|
||||
def assertNextEntry(filename, zis)
|
||||
assertEntry(filename, zis, zis.getNextEntry.name)
|
||||
end
|
||||
|
||||
def assertEntry(filename, zis, entryName)
|
||||
assert_equals(filename, 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
|
||||
end
|
||||
|
||||
class ZipInputStreamTest < RUNIT::TestCase
|
||||
include AssertEntry
|
||||
|
||||
def test_new
|
||||
zis = ZipInputStream.new(TestZipFile::TEST_ZIP2.zipName)
|
||||
assertTestfileContents(zis)
|
||||
zis.close
|
||||
end
|
||||
|
||||
def test_openWithBlock
|
||||
ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName) {
|
||||
|zis|
|
||||
assertTestfileContents(zis)
|
||||
}
|
||||
end
|
||||
|
||||
def test_openWithoutBlock
|
||||
zis = ZipInputStream.open(TestZipFile::TEST_ZIP2.zipName)
|
||||
assertTestfileContents(zis)
|
||||
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
|
||||
|
||||
private
|
||||
|
||||
def assertTestfileContents(zis)
|
||||
assert(zis)
|
||||
assertNextEntry(TestZipFile::TEST_ZIP2.entryNames[0], zis)
|
||||
assertNextEntry(TestZipFile::TEST_ZIP2.entryNames[1], zis)
|
||||
assertNextEntry(TestZipFile::TEST_ZIP2.entryNames[2], zis)
|
||||
assertNextEntry(TestZipFile::TEST_ZIP2.entryNames[3], zis)
|
||||
assert_equals(nil, zis.getNextEntry)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# For representation and creation of
|
||||
# test data
|
||||
class TestZipFile
|
||||
attr_reader :zipName, :entryNames
|
||||
|
||||
def initialize(zipName, entryNames)
|
||||
@zipName=zipName
|
||||
@entryNames=entryNames
|
||||
@@testZips << self
|
||||
end
|
||||
|
||||
def TestZipFile.testZips
|
||||
@@testZips
|
||||
end
|
||||
|
||||
@@testZips = []
|
||||
|
||||
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("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 < 1E6)
|
||||
file << testBinaryPattern << rand
|
||||
end
|
||||
}
|
||||
raise "failed to create test zip '#{TEST_ZIP2.zipName}'" unless
|
||||
system("zip #{TEST_ZIP2.zipName} #{TEST_ZIP2.entryNames.join(' ')}")
|
||||
|
||||
raise "failed to create test zip '#{TEST_ZIP3.zipName}'" unless
|
||||
system("zip #{TEST_ZIP3.zipName} #{TEST_ZIP3.entryNames.join(' ')}")
|
||||
end
|
||||
end
|
||||
|
||||
TEST_ZIP1 = TestZipFile.new("empty.zip", [])
|
||||
TEST_ZIP2 = TestZipFile.new("4entry.zip", %w{ longAscii.txt empty.txt short.txt longBinary.bin})
|
||||
TEST_ZIP3 = TestZipFile.new("test1.zip", %w{ file1.txt })
|
||||
end
|
||||
|
||||
class ZipCentralDirectoryTest < RUNIT::TestCase
|
||||
|
||||
def test_readFromStream
|
||||
File.open(TestZipFile::TEST_ZIP2.zipName, "rb") {
|
||||
|zipFile|
|
||||
cdir = ZipCentralDirectory.new(zipFile)
|
||||
######################################################################
|
||||
# IN PROGRESS: write this test, then ZipCentralDirectory,
|
||||
# then ZipCentralDirectoryEntryTest, then ZipCentralDirectory,
|
||||
# then check ZipFileTest, then write ZipFile
|
||||
######################################################################
|
||||
|
||||
# end of central dir signature 4 bytes (0x06054b50)
|
||||
# number of this disk 2 bytes
|
||||
# number of the disk with the
|
||||
# start of the central directory 2 bytes
|
||||
# total number of entries in the
|
||||
# central directory on this disk 2 bytes
|
||||
# total number of entries in
|
||||
# the central directory 2 bytes
|
||||
# size of the central directory 4 bytes
|
||||
# offset of start of central
|
||||
# directory with respect to
|
||||
# the starting disk number 4 bytes
|
||||
# .ZIP file comment length 2 bytes
|
||||
# .ZIP file comment (variable size)
|
||||
}
|
||||
end
|
||||
|
||||
def test_readFromInvalidStream
|
||||
File.open("ziptest.rb", "rb") {
|
||||
|zipFile|
|
||||
cdir = ZipCentralDirectory.new(zipFile)
|
||||
}
|
||||
fail "ZipError expected!"
|
||||
rescue ZipError
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: Tests yet to write
|
||||
# ZipFile
|
||||
class ZipFileTest < 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
|
||||
entries = @zipFile.entries
|
||||
assert_equals(4, entries.size)
|
||||
assert_equals(nextTestEntryName, entries[0])
|
||||
assert_equals(nextTestEntryName, entries[1])
|
||||
assert_equals(nextTestEntryName, entries[2])
|
||||
assert_equals(nextTestEntryName, entries[3])
|
||||
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
|
||||
end
|
||||
|
||||
|
||||
|
||||
TestZipFile::createTestZips(ARGV.index("recreate") != nil)
|
||||
|
||||
RUNIT::CUI::TestRunner.run(RUNIT::TestCase.all_suite)
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
--- zlib.c.org Tue Jan 1 21:31:08 2002
|
||||
+++ zlib.c Tue Jan 1 21:32:41 2002
|
||||
@@ -514,7 +514,7 @@
|
||||
|
||||
Check_Type(val, T_FIXNUM);
|
||||
wbits = FIX2INT(val);
|
||||
- if (wbits < 8 || MAX_WBITS < wbits)
|
||||
+ if (abs(wbits) < 8 || MAX_WBITS < abs(wbits))
|
||||
rb_raise(rb_eArgError, "window bits out of range");
|
||||
return wbits;
|
||||
}
|
||||
Loading…
Reference in New Issue