ZipArchive.st
changeset 5238 09078186400b
parent 5228 20c3ce687385
child 5263 350d509151c9
--- a/ZipArchive.st	Sat Nov 09 19:42:20 2019 +0100
+++ b/ZipArchive.st	Fri Nov 15 19:57:57 2019 +0100
@@ -3471,18 +3471,21 @@
     "initialize the archive to write to aPositionableStream"
 
     stream notNil ifTrue: [
-	self close.
+        self close.
     ].
 
     mode := #write.
     aPositionableStream binary.
     stream := aPositionableStream.
+    startOfArchive := aPositionableStream position.
     aPositionableStream isFileStream ifTrue:[
-	archiveName := aPositionableStream pathName.
+        archiveName := aPositionableStream pathName.
     ] ifFalse:[
-	archiveName := 'internal stream'.
+        archiveName := 'internal stream'.
     ].
     zipMembersByName := Dictionary new.
+
+    "Modified: / 15-11-2019 / 19:31:15 / Stefan Vogel"
 ! !
 
 !ZipArchive methodsFor:'private'!
@@ -3752,7 +3755,7 @@
     "/ ensure that the file position is at end
     stream setToEnd.
 
-    centralDirectory centralDirectoryStartOffset: stream position.
+    centralDirectory centralDirectoryStartOffset: stream position-startOfArchive.
 
     self zipMembersDo:[:zipEntry |
         noEntries := noEntries + 1.
@@ -3789,7 +3792,7 @@
 
     centralDirectory centralDirectoryTotalNoOfEntries: noEntries.
     centralDirectory centralDirectoryTotalNoOfEntriesOnThisDisk: noEntries.
-    centralDirectory centralDirectorySize: (stream position) - (centralDirectory centralDirectoryStartOffset).
+    centralDirectory centralDirectorySize: (stream position-startOfArchive) - (centralDirectory centralDirectoryStartOffset).
 
     stream nextPutByte:($P codePoint).
     stream nextPutByte:($K codePoint).
@@ -3808,7 +3811,7 @@
     ].
 
     "Modified: / 19-11-2010 / 16:23:36 / cg"
-    "Modified: / 22-11-2018 / 15:36:07 / Stefan Vogel"
+    "Modified: / 15-11-2019 / 19:34:40 / Stefan Vogel"
 !
 
 addMember:zmemb
@@ -3928,15 +3931,15 @@
 
     size := endOfArchive - startOfArchive.
     (size == 0) ifTrue:[
-	^ self
+        ^ self
     ].
 
     (size < (ECREC_SIZE+4)) ifTrue:[
-	^ ZipFileFormatErrorSignal raiseRequestErrorString:' - zipfile too short'.
+        ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - zipfile too short'.
     ].
 
     self searchForEndOfCentralDirectorySignature ifFalse: [
-	^ ZipFileFormatErrorSignal raiseRequestErrorString:' - could not find end of directory signature'.
+        ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - could not find end of directory signature'.
     ].
 
     "/ position before end of central directory signature
@@ -3945,52 +3948,52 @@
     "/ Now we have found the end of central directory record
     centralDirectory := ZipCentralDirectory new.
     EndOfStreamNotification handle:[:ex|
-	ZipFileFormatErrorSignal raiseRequestErrorString:' - file format error or short file: ' ,
-					(stream isFileStream ifTrue:[stream pathName] ifFalse:['inStream']).
-	^ self.
+        ZipFileFormatErrorSignal raiseRequestErrorString:' - file format error or short file: ' ,
+                                        (stream isFileStream ifTrue:[stream pathName] ifFalse:['inStream']).
+        ^ self.
     ] do:[
-	centralDirectory readFrom:stream.
-
-	"/ set file position to start of central directory
-	(pos0 - centralDirectory centralDirectoryStartOffset - centralDirectory centralDirectorySize) < startOfArchive ifTrue: [
-	    ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - central directory start is out of the archive bounds'.
-	].
-
-	startOfArchive := pos0 - centralDirectory centralDirectoryStartOffset - centralDirectory centralDirectorySize.
-	stream position:(pos0 - (centralDirectory centralDirectorySize)).
-
-	zipMembersByName := Dictionary new:centralDirectory centralDirectoryTotalNoOfEntries.
-
-	"/ read central directory entries
-	1 to:(centralDirectory centralDirectoryTotalNoOfEntries) do:[:i |
-	    |zipd  centralFileHeaderSignature|
-
-	    (stream position + (self class centralDirectoryMinimumSize)) > endOfArchive ifTrue: [
-		^ ZipFileFormatErrorSignal raiseRequestErrorString:' - central directory entry out of archive bounds'.
-	    ].
-	    centralFileHeaderSignature := stream nextInt32MSB:false.
-	    centralFileHeaderSignature ~= C_CENTRAL_HEADER_SIGNATURE ifTrue:[
-		ZipFileFormatErrorSignal raiseRequestErrorString:' - file format error - bad centralHeaderSignature in: ' ,
-						(stream isFileStream ifTrue:[stream pathName] ifFalse:['inStream']).
-		^ self.
-	    ].
-
-	    zipd := ZipMember new readCentralDirectoryEntryFrom:stream.
-	    self addMember:zipd.
-	].
-
-	(stream position + 6) > endOfArchive ifTrue: [
-	    "/ archive has no digital signature
-	    ^ self.
-	].
-
-	"/ check for digital signature
-	((stream nextByte ~~ ($P codePoint))
-	 or:[stream nextByte ~~ ($K codePoint)
-	 or:[stream nextByte ~~ 8r005
-	 or:[stream nextByte ~~ 8r005]]]) ifTrue:[
-	    centralDirectory readDigitalSignatureFrom:stream.
-	].
+        centralDirectory readFrom:stream.
+
+        "/ set file position to start of central directory
+        (pos0 - centralDirectory centralDirectoryStartOffset - centralDirectory centralDirectorySize) < startOfArchive ifTrue: [
+            ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - central directory start is out of the archive bounds'.
+        ].
+
+        startOfArchive := pos0 - centralDirectory centralDirectoryStartOffset - centralDirectory centralDirectorySize.
+        stream position:(pos0 - (centralDirectory centralDirectorySize)).
+
+        zipMembersByName := Dictionary new:centralDirectory centralDirectoryTotalNoOfEntries.
+
+        "/ read central directory entries
+        1 to:(centralDirectory centralDirectoryTotalNoOfEntries) do:[:i |
+            |zipd  centralFileHeaderSignature|
+
+            (stream position + (self class centralDirectoryMinimumSize)) > endOfArchive ifTrue: [
+                ^ ZipFileFormatErrorSignal raiseRequestErrorString:' - central directory entry out of archive bounds'.
+            ].
+            centralFileHeaderSignature := stream nextInt32MSB:false.
+            centralFileHeaderSignature ~= C_CENTRAL_HEADER_SIGNATURE ifTrue:[
+                ZipFileFormatErrorSignal raiseRequestErrorString:' - file format error - bad centralHeaderSignature in: ' ,
+                                                (stream isFileStream ifTrue:[stream pathName] ifFalse:['inStream']).
+                ^ self.
+            ].
+
+            zipd := ZipMember new readCentralDirectoryEntryFrom:stream.
+            self addMember:zipd.
+        ].
+
+        (stream position + 6) > endOfArchive ifTrue: [
+            "/ archive has no digital signature
+            ^ self.
+        ].
+
+        "/ check for digital signature
+        ((stream nextByte ~~ ($P codePoint))
+         or:[stream nextByte ~~ ($K codePoint)
+         or:[stream nextByte ~~ 8r005
+         or:[stream nextByte ~~ 8r005]]]) ifTrue:[
+            centralDirectory readDigitalSignatureFrom:stream.
+        ].
     ]
 
     "
@@ -4001,14 +4004,14 @@
 
     "Modified: / 19-11-2010 / 15:43:24 / cg"
     "Modified (format): / 17-02-2017 / 22:20:26 / stefan"
+    "Modified: / 15-11-2019 / 19:57:40 / Stefan Vogel"
 !
 
 searchForEndOfCentralDirectorySignature
     "read the zip directory into a linked-list of zipMembers"
 
-    |size foundPK pos0 searchEndPos|
-
-    foundPK := false.
+    |size pos0 searchEndPos|
+
     size := endOfArchive - startOfArchive.
     stream position:(pos0 := endOfArchive - ECREC_SIZE - 4).
 
@@ -4017,38 +4020,40 @@
     or:[stream nextByte ~~ ($K codePoint)
     or:[stream nextByte ~~ 8r005
     or:[stream nextByte ~~ 8r006]]]) ifTrue:[
-	"/ search from end of archive backwards for "end of central directory signature",
-	"/ this is necessary if the archive includes a .ZIP file comment or a digital signature
-	"/ then the end of the directory signature may be on an other position
-
-	"/ but the "end of central directory signature" must be located in the
-	"/ last 64k of the archive
-	size > 65536 ifTrue: [
-	    searchEndPos := (endOfArchive - 65536).
-	] ifFalse: [
-	    searchEndPos := startOfArchive.
-	].
-
-	stream position: (pos0 := endOfArchive - 4).
-
-	[foundPK] whileFalse: [
-	    (stream nextByte == ($P codePoint)
-	    and:[stream nextByte == ($K codePoint)
-	    and:[stream nextByte == 8r005
-	    and:[stream nextByte == 8r006]]]) ifTrue:[
-		^ true
-	    ].
-	    stream position <= searchEndPos ifTrue: [
-		^ false.
-	    ].
-	    pos0 == 0 ifTrue:[
-		^ false.
-	    ].
-	    stream position: (pos0 := pos0 - 1).
-	].
-	^ false
+        "/ search from end of archive backwards for "end of central directory signature",
+        "/ this is necessary if the archive includes a .ZIP file comment or a digital signature
+        "/ then the end of the directory signature may be on an other position
+
+        "/ but the "end of central directory signature" must be located in the
+        "/ last 64k of the archive
+        size > 65536 ifTrue: [
+            searchEndPos := (endOfArchive - 65536).
+        ] ifFalse: [
+            searchEndPos := startOfArchive.
+        ].
+
+        stream position: (pos0 := endOfArchive - 4).
+
+        [true] whileTrue:[
+            (stream nextByte == ($P codePoint)
+            and:[stream nextByte == ($K codePoint)
+            and:[stream nextByte == 5
+            and:[stream nextByte == 6]]]) ifTrue:[
+                ^ true
+            ].
+            stream position <= searchEndPos ifTrue: [
+                ^ false.
+            ].
+            pos0 == 0 ifTrue:[
+                ^ false.
+            ].
+            stream position: (pos0 := pos0 - 1).
+        ].
+        ^ false
     ].
     ^ true
+
+    "Modified: / 15-11-2019 / 19:02:40 / Stefan Vogel"
 !
 
 zipMembersDo:aBlock
@@ -4379,8 +4384,8 @@
 
     theCompressMethod := theCompressMethodArg.
 
-    ((theCompressMethod == COMPRESSION_DEFLATED)
-    or:[ theCompressMethod == COMPRESSION_STORED ]) ifFalse:[
+    (theCompressMethod ~~ COMPRESSION_DEFLATED
+     and:[theCompressMethod ~~ COMPRESSION_STORED]) ifTrue:[
         UnsupportedZipFileFormatErrorSignal raiseRequestErrorString:'unsupported compressMethod'.
         "/ if proceeded, write as uncompressed
         theCompressMethod := COMPRESSION_STORED
@@ -4389,7 +4394,7 @@
     zipEntry := ZipMember new default.
     theZipFileName := self validZipFileNameFrom:aFileName.
 
-    zipEntry fileName: theZipFileName.
+    zipEntry fileName:theZipFileName.
     zipEntry uncompressedSize: 0.
 
     isDirectory ifTrue: [
@@ -4407,7 +4412,7 @@
     "/ ensure that the file position is at the end
     stream setToEnd.
 
-    zipEntry writeTo:stream.
+    zipEntry writeTo:stream position:stream position - startOfArchive.
 
     streamBufferSize := self class streamBufferSize.
     buffer := ByteArray new:streamBufferSize.
@@ -4440,7 +4445,7 @@
         ].
     ].
 
-    zipEntry compressedSize:(stream position) - startDataPosition.
+    zipEntry compressedSize:stream position - startDataPosition.
 
     "/ crc32 is always required (not as written in docu to be zero in case of uncompressed mode)
     zipEntry crc32:crc32.
@@ -4452,7 +4457,7 @@
     stream setToEnd.
 
     "Modified: / 19-11-2010 / 15:39:32 / cg"
-    "Modified: / 22-11-2018 / 12:27:39 / Stefan Vogel"
+    "Modified: / 15-11-2019 / 19:44:42 / Stefan Vogel"
 !
 
 addFile: aFileName withContents: data
@@ -4495,9 +4500,9 @@
 basicAddFile:aFileName withContents:data compressMethod:theCompressMethodArg asDirectory:isDirectory
     "do not create directories (isDirectory = true) - they are not compatible between operating systems"
 
-    |zipEntry theCompressedData theZipFileName theCompressMethod  compressedDataOffset compressedDataSize|
-
-    (stream isNil or:[ mode ~~ #write ]) ifTrue:[
+    |zipEntry theCompressedData theZipFileName theCompressMethod compressedDataOffset compressedDataSize|
+
+    (stream isNil or:[mode ~~ #write]) ifTrue:[
         ^ self error:'ZipArchive not open for writing ...'.
     ].
     theCompressMethod := theCompressMethodArg.
@@ -4513,7 +4518,7 @@
     theZipFileName := self validZipFileNameFrom:aFileName.
 
     (isDirectory and:[self appendTrailingSlash and:[theZipFileName last ~~ $/]]) ifTrue:[
-        zipEntry fileName:theZipFileName , $/.
+        zipEntry fileName:theZipFileName, $/.
     ] ifFalse:[
         zipEntry fileName:theZipFileName.
     ].
@@ -4547,7 +4552,7 @@
 
     "/ ensure that the file position is at the end
     stream setToEnd.
-    zipEntry writeTo:stream.
+    zipEntry writeTo:stream position:stream position - startOfArchive.
     theCompressedData notNil ifTrue:[
         stream 
             nextPutAll:theCompressedData
@@ -4559,7 +4564,7 @@
     "Created: / 18-11-2010 / 19:31:10 / cg"
     "Modified: / 19-11-2010 / 17:47:01 / cg"
     "Modified: / 19-11-2012 / 12:04:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 22-11-2018 / 15:42:25 / Stefan Vogel"
+    "Modified (format): / 15-11-2019 / 19:50:43 / Stefan Vogel"
 ! !
 
 !ZipArchive methodsFor:'writing - stream'!
@@ -4578,16 +4583,16 @@
     |zipEntry theZipFileName theCompressMethod|
 
     (stream isNil or:[mode ~~ #write]) ifTrue: [
-	^ self error: 'ZipArchive not open for writing ...'.
+        ^ self error: 'ZipArchive not open for writing ...'.
     ].
 
     theCompressMethod := theCompressMethodArg.
 
     ((theCompressMethod == COMPRESSION_DEFLATED)
      or:[theCompressMethod == COMPRESSION_STORED]) ifFalse:[
-	UnsupportedZipFileFormatErrorSignal raiseRequestErrorString:'unsupported compressMethod'.
-	"/ if proceeded, write as uncompressed
-	theCompressMethod := COMPRESSION_STORED
+        UnsupportedZipFileFormatErrorSignal raiseRequestErrorString:'unsupported compressMethod'.
+        "/ if proceeded, write as uncompressed
+        theCompressMethod := COMPRESSION_STORED
     ].
 
     zipEntry := ZipMember new default.
@@ -4606,12 +4611,13 @@
     "/ ensure that the file position is at the end
     stream setToEnd.
 
-    zipEntry writeTo:stream.
+    zipEntry writeTo:stream position:stream position - startOfArchive.
     self addMember:zipEntry.
 
     ^ (ZipWriteStream zipFileStream:stream zipEntry:zipEntry) zipArchive:self.
 
     "Modified: / 19-11-2010 / 15:38:54 / cg"
+    "Modified: / 15-11-2019 / 19:45:48 / Stefan Vogel"
 ! !
 
 !ZipArchive::AbstractZipStream class methodsFor:'instance creation'!
@@ -5163,10 +5169,10 @@
 	nextPutInt32:uncompressedSize MSB:false.
 !
 
-writeTo:aStream
+writeTo:aStream position:position
     "represent myself on aStream"
 
-    relativeLocalHeaderOffset := aStream position.
+    relativeLocalHeaderOffset := position.
 
     aStream
         nextPutInt32:C_LOCAL_HEADER_SIGNATURE MSB:false;
@@ -5187,8 +5193,7 @@
         aStream nextPutAll:extraField.
     ].
 
-    "Modified: / 19-11-2010 / 15:45:38 / cg"
-    "Modified: / 22-11-2018 / 15:37:03 / Stefan Vogel"
+    "Created: / 15-11-2019 / 19:44:10 / Stefan Vogel"
 ! !
 
 !ZipArchive::ZipReadStream methodsFor:'accessing'!