--- a/ZipArchive.st Wed May 28 18:20:00 2008 +0200
+++ b/ZipArchive.st Fri May 30 10:59:59 2008 +0200
@@ -1247,6 +1247,53 @@
"
!
+examples2
+"
+ add to new zip archive a entry which is located in memory using selector
+ addFile:'crcTest_resume_compressed.txt' withContents:
+ and real file contents from disk identified by a readStream using selector
+ addFile:rdStreamFile fromStream:
+ [exBegin]
+ |zipwr testDirectory testFileWr rdStreamFile rdFileStream |
+
+ testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'.
+ testFileWr := 'streamtest_uncompressed.zip'.
+ rdStreamFile := 'projects.zip'.
+
+ rdFileStream := ('C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\', rdStreamFile) asFilename readStream.
+ zipwr := ZipArchive newFileNamed:(testDirectory, testFileWr).
+ zipwr addFile:'crcTest_resume_compressed.txt' withContents: 'resume'.
+ zipwr addFile:rdStreamFile fromStream: rdFileStream.
+
+ zipwr closeFile.
+ [exEnd]
+
+ read from zip archive a entry which into memory using selector
+ extract:'crcTest_resume_compressed.txt'
+ and store real file contents from disk using a readStream on archive contents entry
+ readStreamFor: rdStreamFile
+ [exBegin]
+ |ziprd testDirectory testFileRd wrStreamFile wrFileStream archiveRdStream data1
+ buffer streamAtEnd nextBlockSize |
+
+ testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'.
+ testFileRd := 'streamtest_uncompressed.zip'.
+ wrStreamFile := 'test_projects.zip'.
+
+ ziprd := ZipArchive oldFileNamed:(testDirectory, testFileRd).
+ data1 := ziprd extract:'crcTest_resume_compressed.txt'.
+
+ wrFileStream := ('C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\', wrStreamFile) asFilename writeStream.
+ (ziprd extract:'projects.zip' intoStream: wrFileStream) ifFalse: [
+ self halt.
+ ].
+
+ ziprd closeFile.
+ [exEnd]
+
+"
+!
+
fileFormatDescription
"/File: APPNOTE.TXT - .ZIP File Format Specification
@@ -2902,6 +2949,12 @@
^ 46
"Created: / 29.3.1998 / 19:11:20 / cg"
+!
+
+streamBufferSize
+ ^ 65536 "/ 1024 * 64
+
+ "Created: / 29.3.1998 / 19:11:20 / cg"
! !
!ZipArchive class methodsFor:'debugging'!
@@ -3610,7 +3663,7 @@
!ZipArchive methodsFor:'reading'!
extract:fileName
- "extract a filename entry as a byteArray;
+ "extract an entry identified by fileName as a byteArray;
nil on errors"
|zmemb rawContents data|
@@ -3640,6 +3693,64 @@
^ data.
!
+extract:fileName intoStream: aWriteStream
+ "extract a entry indentified by filename into write stream
+ return false on error
+ "
+
+ |zmemb rawContents data buffer rdSize nextBlockSize streamBufferSize|
+
+ (file isNil or: [mode ~~ #read]) ifTrue: [
+ self error: 'Archiv not open for reading ...'.
+ ^ false
+ ].
+
+ zmemb := self findMember:fileName.
+ zmemb isNil ifTrue:[^ false].
+
+ (zmemb fileStart + startOfArchive) > endOfArchive ifTrue: [
+ ZipFileFormatErrorSignal raiseRequestErrorString:' - zipEntry start is out of the archive bounds'.
+ ^ false
+ ].
+
+ (zmemb fileStart + startOfArchive + (zmemb compressedSize)) > endOfArchive ifTrue: [
+ ZipFileFormatErrorSignal raiseRequestErrorString:' - zipEntry end is out of the archive bounds'.
+ ^ false
+ ].
+
+ file position0Based:(zmemb fileStart + startOfArchive).
+
+ zmemb compressionMethod == 8 ifTrue: [
+ self shouldImplement.
+ rawContents := file nextBytes:(zmemb compressedSize).
+ data := self
+ decode:rawContents
+ method:(zmemb compressionMethod)
+ size:(zmemb uncompressedSize).
+ ^ false
+ ].
+
+ rdSize := zmemb compressedSize.
+ streamBufferSize := self class streamBufferSize.
+ buffer := ByteArray new: streamBufferSize.
+ [rdSize > 0] whileTrue: [
+ rdSize > (self class streamBufferSize) ifTrue: [
+ nextBlockSize := streamBufferSize.
+ ] ifFalse: [
+ (nextBlockSize := rdSize) > 0 ifTrue: [
+ buffer := ByteArray new: nextBlockSize.
+ ].
+ ].
+ nextBlockSize > 0 ifTrue: [
+ file nextBytes:nextBlockSize into:buffer startingAt:1.
+ aWriteStream nextPutBytes:nextBlockSize from:buffer startingAt:1.
+ ].
+ rdSize := rdSize - nextBlockSize.
+ ].
+
+ ^ true.
+!
+
extractArchive:fileName
"extract a filename entry as a byteArray;
nil on errors"
@@ -3667,31 +3778,6 @@
endOfArchive:(zmemb fileStart + startOfArchive + (zmemb compressedSize)).
!
-readStreamFor:nameOfFileInArchive
- "open a stream on archive contents identified by nameOfFileInArchive"
-
- |zmemb rs zs|
-
- (file isNil or: [mode ~~ #read]) ifTrue: [
- ^ self error: 'Archiv not open for reading ...'.
- ].
-
- zmemb := self findMember:nameOfFileInArchive.
- zmemb isNil ifTrue:[^ nil].
-
- zmemb compressionMethod == 0 ifTrue: [
- rs := ZipUncompressedArchiveStream readonlyFileNamed: archiveName asFilename.
- rs position0Based:zmemb fileStart.
- rs readLimit:(zmemb fileStart + zmemb uncompressedSize).
- ^ rs
- ].
-
- zs := ZipCompressedArchiveStream readOpenOn:rs
- position:zmemb fileStart
- readLimit:zmemb compressedSize.
- ^ zs
-!
-
restoreContentsFromZipDirectory:zipDirectoryName intoDirectory:intoDirectory
"restore the contents of a file or directory (recursive) from zip archive -> zipDirectoryName
into directory -> intoDirectory"
@@ -3701,6 +3787,35 @@
^ true
! !
+!ZipArchive methodsFor:'reading - stream'!
+
+readStreamFor:nameOfFileInArchive
+ "open a stream on archive contents identified by nameOfFileInArchive"
+ self shouldImplement.
+"/
+"/ |zmemb rs zs|
+"/
+"/ (file isNil or: [mode ~~ #read]) ifTrue: [
+"/ ^ self error: 'Archiv not open for reading ...'.
+"/ ].
+"/
+"/ zmemb := self findMember:nameOfFileInArchive.
+"/ zmemb isNil ifTrue:[^ nil].
+"/
+"/ zmemb compressionMethod == 0 ifTrue: [
+"/ rs := ZipUncompressedArchiveStream readonlyFileNamed: archiveName asFilename.
+"/ rs position0Based:zmemb fileStart.
+"/ rs readLimit:(zmemb fileStart + zmemb uncompressedSize).
+"/ ^ rs
+"/ ].
+"/
+"/ "/ did not work right now proberly
+"/ zs := ZipCompressedArchiveStream readOpenOn:rs
+"/ position:zmemb fileStart
+"/ readLimit:zmemb compressedSize.
+"/ ^ zs
+! !
+
!ZipArchive methodsFor:'writing'!
addContentsFromFileOrDirectory:realFileOrDirectoryName toZipDirectory:zipDirectoryName
@@ -3724,6 +3839,107 @@
^ self addFile: aDirectoryName withContents: nil compressMethod: 0 asDirectory: true.
!
+addFile: aFileName fromStream: aStream
+ ^ self addFile: aFileName fromStream: aStream compressMethod: 0
+!
+
+addFile: aFileName fromStream: aStream compressMethod: theCompressMethod
+ |zipEntry curTime curDate crc32Pos crc32 unCompressedDataSize
+ compressedDataSize buffer rdSize nextBlockSize streamBufferSize|
+
+ (file isNil or: [mode ~~ #write]) ifTrue: [
+ ^ self error: 'Archiv not open for writing ...'.
+ ].
+ zipEntry := ZipMember new default.
+
+ firstEntry isNil ifTrue: [
+ firstEntry := zipEntry.
+ ] ifFalse: [
+ lastEntry next: zipEntry.
+ ].
+
+ lastEntry := zipEntry.
+
+ zipEntry fileName: aFileName.
+ zipEntry fileNameLength: aFileName size.
+ zipEntry uncompressedSize: 0.
+
+ zipEntry compressionMethod: theCompressMethod.
+ zipEntry internalFileAttributes: 1.
+ zipEntry externalFileAttributes: 32.
+
+ curTime := Time now.
+ curDate := Date today.
+ "/ data and time in msdos format
+ zipEntry lastModFileTime: (((curTime seconds // 2) bitOr: (curTime minutes rightShift: -5)) bitOr: (curTime hours rightShift: -11)).
+ zipEntry lastModFileDate: (((curDate day) bitOr: (curDate month rightShift: -5)) bitOr: (((curDate year) - 1980) rightShift: -9)).
+
+ "/ ensure that the file position is at the end
+ file setToEnd.
+
+ zipEntry relativeLocalHeaderOffset:(file position).
+ file nextPutLong: 16r04034b50 MSB:false.
+ file nextPutShort:zipEntry versionNeedToExtract MSB:false.
+ file nextPutShort:zipEntry generalPurposBitFlag MSB:false.
+ file nextPutShort:zipEntry compressionMethod MSB:false.
+ file nextPutShort:zipEntry lastModFileTime MSB:false.
+ file nextPutShort:zipEntry lastModFileDate MSB:false.
+ crc32Pos := file position.
+ file nextPutLong:zipEntry crc32 MSB:false.
+ file nextPutLong:zipEntry compressedSize MSB:false.
+ file nextPutLong:zipEntry uncompressedSize MSB:false.
+ file nextPutShort:zipEntry fileNameLength MSB:false.
+ file nextPutShort:zipEntry extraFieldLength MSB:false.
+ file nextPutAll:zipEntry fileName.
+ zipEntry extraField notNil ifTrue: [
+ file nextPutAll:zipEntry extraField.
+ ].
+
+ (theCompressMethod == 8) ifTrue: [
+ self shouldImplement.
+"/ |tmpCompressedData tmpCompressedDataSize|
+"/ tmpCompressedData := ByteArray new:(data size + 16). "/ if the compression is less then the additional overhead we need more space in buffer
+"/ tmpCompressedDataSize := ZipStream compress:data into:tmpCompressedData.
+"/
+"/ zipEntry compressedSize: (tmpCompressedDataSize - 6). "/6 = the zlib specific data 2 bytes in front and 4 bytes behind the real data
+"/ theCompressedData := tmpCompressedData copyFrom: 3. "/ 2 bytes before the real data
+ ] ifFalse: [
+ crc32 := 0.
+ streamBufferSize := self class streamBufferSize.
+ buffer := ByteArray new: streamBufferSize.
+ rdSize := aStream size.
+ unCompressedDataSize := rdSize.
+ [rdSize > 0] whileTrue: [
+ rdSize > (self class streamBufferSize) ifTrue: [
+ nextBlockSize := streamBufferSize.
+ ] ifFalse: [
+ (nextBlockSize := rdSize) > 0 ifTrue:[
+ buffer := ByteArray new: nextBlockSize.
+ ].
+ ].
+ nextBlockSize > 0 ifTrue: [
+ aStream nextBytes:nextBlockSize into:buffer startingAt:1.
+ file nextPutBytes:nextBlockSize from:buffer startingAt:1.
+ crc32 := (ZipStream crc32BytesIn: buffer crc: crc32).
+ ].
+ rdSize := rdSize - nextBlockSize.
+ ].
+ compressedDataSize := unCompressedDataSize.
+ ].
+
+ zipEntry crc32: crc32.
+ zipEntry uncompressedSize: unCompressedDataSize.
+ zipEntry compressedSize: compressedDataSize.
+
+ file position0Based:crc32Pos.
+
+ file nextPutLong:zipEntry crc32 MSB:false.
+ file nextPutLong:zipEntry compressedSize MSB:false.
+ file nextPutLong:zipEntry uncompressedSize MSB:false.
+
+ file setToEnd.
+!
+
addFile: aFileName withContents: data
^ self addFile: aFileName withContents: data compressMethod: 8 asDirectory: false.
!
@@ -3804,6 +4020,65 @@
].
! !
+!ZipArchive methodsFor:'writing - stream'!
+
+writeStreamFor:nameOfFileInArchive
+ "create new entry in central directory"
+ self shouldImplement.
+"/ |zipEntry curTime curDate|
+"/
+"/ (file isNil or: [mode ~~ #write]) ifTrue: [
+"/ ^ self error: 'Archiv not open for writing ...'.
+"/ ].
+"/ zipEntry := ZipMember new default.
+"/
+"/ firstEntry isNil ifTrue: [
+"/ firstEntry := zipEntry.
+"/ ] ifFalse: [
+"/ lastEntry next: zipEntry.
+"/ ].
+"/
+"/ lastEntry := zipEntry.
+"/
+"/ zipEntry fileName: nameOfFileInArchive.
+"/ zipEntry fileNameLength: nameOfFileInArchive size.
+"/ zipEntry uncompressedSize: 0.
+"/
+"/ zipEntry compressionMethod: 0.
+"/ zipEntry internalFileAttributes: 1.
+"/ zipEntry externalFileAttributes: 32.
+"/
+"/ curTime := Time now.
+"/ curDate := Date today.
+"/ "/ data and time in msdos format
+"/ zipEntry lastModFileTime: (((curTime seconds // 2) bitOr: (curTime minutes rightShift: -5)) bitOr: (curTime hours rightShift: -11)).
+"/ zipEntry lastModFileDate: (((curDate day) bitOr: (curDate month rightShift: -5)) bitOr: (((curDate year) - 1980) rightShift: -9)).
+"/
+"/ zipEntry compressedSize: zipEntry uncompressedSize.
+"/
+"/ "/ ensure that the file position is at the end
+"/ file setToEnd.
+"/
+"/ zipEntry relativeLocalHeaderOffset:(file position).
+"/ file nextPutLong: 16r04034b50 MSB:false.
+"/ file nextPutShort:zipEntry versionNeedToExtract MSB:false.
+"/ file nextPutShort:zipEntry generalPurposBitFlag MSB:false.
+"/ file nextPutShort:zipEntry compressionMethod MSB:false.
+"/ file nextPutShort:zipEntry lastModFileTime MSB:false.
+"/ file nextPutShort:zipEntry lastModFileDate MSB:false.
+"/ file nextPutLong:zipEntry crc32 MSB:false.
+"/ file nextPutLong:zipEntry compressedSize MSB:false.
+"/ file nextPutLong:zipEntry uncompressedSize MSB:false.
+"/ file nextPutShort:zipEntry fileNameLength MSB:false.
+"/ file nextPutShort:zipEntry extraFieldLength MSB:false.
+"/ file nextPutAll:zipEntry fileName.
+"/ zipEntry extraField notNil ifTrue: [
+"/ file nextPutAll:zipEntry extraField.
+"/ ].
+"/
+"/ ^ file
+! !
+
!ZipArchive::ZipCentralDirectory methodsFor:'accessing'!
centralDirectorySize
@@ -4265,7 +4540,7 @@
!ZipArchive class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic2/ZipArchive.st,v 1.62 2008-05-28 16:20:00 ab Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic2/ZipArchive.st,v 1.63 2008-05-30 08:59:59 ab Exp $'
! !
ZipArchive initialize!