eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'ZipArchive':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: ZipArchive


Inheritance:

   Object
   |
   +--ZipArchive

Package:
stx:libbasic2
Category:
System-Support-FileFormats
Version:
rev: 1.208 date: 2024/03/06 12:34:56
user: cg
file: ZipArchive.st directory: libbasic2
module: stx stc-classLibrary: libbasic2

Description:


provides access to a zip archive.


Trailing slash.
    Some implementations require a trailing slash in directory
    names (such as the OpenOffice zip implementation). Others just
    ignore external file attributes and indicate a directory entry
    by adding a trailing slash (such as the Java zip implementation).

    Since ZipArchive 1.98 a trailing slash is added for all directory
    entries iff appendTrailingSlash instvar is set to true. By default
    it is set to the value of DefaultAppendTrailingSlash which defaults
    to true.

    Setting appendTrailingSlash to false inhibits trailing slash
    behavior.


Caveat:
    the only compression methods (for now) are store and deflate.


[classvars:]
    DefaultAppendTrailingSlash...a default value for appendTralingSlash instvar.
                                 For details, see above

copyright

COPYRIGHT (c) 1998 by eXept Software AG All Rights Reserved This software is furnished under a license and may be used only in accordance with the terms of that license and with the inclusion of the above copyright notice. This software may not be provided or otherwise made available to, or used by, any other person. No title to or ownership of the software is hereby transferred.

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 (uncompressed) 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 close. [exEnd] read from zip archive a entry into memory using selector extract:'crcTest_resume_compressed.txt' and store an uncompressed archive entry to disk using a writeStream extract: intoStream: [exBegin] |ziprd testDirectory testFileRd wrStreamFile wrFileStream data1| 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 close. wrFileStream close. [exEnd] add (compressed) to new zip archive a real file contents from disk e.g. a pdf identified by a readStream using selector addFile: fromStream: compressMethod: [exBegin] |zipwr testDirectory testFileWr rdStreamFile rdFileStream| testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'. testFileWr := 'streamtest_compressed.zip'. rdStreamFile := 'test.pdf'. rdFileStream := ('C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\', rdStreamFile) asFilename readStream. zipwr := ZipArchive newFileNamed:(testDirectory, testFileWr). zipwr addFileCompressed:rdStreamFile fromStream: rdFileStream. zipwr close. [exEnd] read from zip archive a compressed entry e.g. a pdf and store the contents to disk using a readStream using selector readStreamFor: rdStreamFile [exBegin] |ziprd testDirectory testFileRd wrStreamFile wrFileStream| testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'. testFileRd := 'streamtest_compressed.zip'. wrStreamFile := 'test_expecco.pdf'. ziprd := ZipArchive oldFileNamed:(testDirectory, testFileRd). wrFileStream := ('C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\', wrStreamFile) asFilename writeStream. (ziprd extract:'test.pdf' intoStream: wrFileStream) ifFalse: [ self halt. ]. ziprd close. wrFileStream close. [exEnd]

examples3

add to new zip archive recursive the contents of a directory (uncompressed) addArchiveDirectory: fromOsDirectory: [exBegin] |zipwr testDirectory testFileWr zipDirectory | testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'. testFileWr := 'zipDirectoryTest.zip'. zipDirectory := 'abc'. zipwr := ZipArchive newFileNamed:(testDirectory, testFileWr). zipwr addArchiveDirectory: 'attachments' fromOsDirectory: (testDirectory,zipDirectory). zipwr close. [exEnd] read from zip archive all entries which are stored in an archive directory (uncompressed) and store all those entries in a directory on the file system restoreOsDirectory: fromArchiveDirectory: [exBegin] |ziprd testDirectory testFileRd zipDirectory| testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'. testFileRd := 'zipDirectoryTest.zip'. zipDirectory := 'xxx'. ziprd := ZipArchive oldFileNamed:(testDirectory, testFileRd). ziprd restoreOsDirectory: (testDirectory,zipDirectory) fromArchiveDirectory: 'attachments'. ziprd close. [exEnd] add to new zip archive recursive the contents of a directory (compressed) addArchiveDirectoryCompressed: fromOsDirectory: [exBegin] |zipwr testDirectory testFileWr zipDirectory | testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'. testFileWr := 'zipDirectoryTestCompressed.zip'. zipDirectory := 'abc'. zipwr := ZipArchive newFileNamed:(testDirectory, testFileWr). zipwr addArchiveDirectoryCompressed: 'attachments' fromOsDirectory: (testDirectory,zipDirectory). zipwr close. [exEnd] read from zip archive all entries which are stored in an archive directory (compressed) and store all those entries in a directory on the file system restoreOsDirectory: fromArchiveDirectory: [exBegin] |ziprd testDirectory testFileRd zipDirectory| testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'. testFileRd := 'zipDirectoryTestCompressed.zip'. zipDirectory := 'xxx-compressed'. ziprd := ZipArchive oldFileNamed:(testDirectory, testFileRd). ziprd restoreOsDirectory: (testDirectory,zipDirectory) fromArchiveDirectory: 'attachments'. ziprd close. [exEnd]

examples4

can we handle zip42.zip (a zip bomb)? Yes, kind of: because I will only extract one level of files, there is no danger of a recursive extract. [exBegin] |badFile ziprd outDir| badFile := Filename downloadsDirectory / '42.zip'. (outDir := Filename downloadsDirectory / '42') makeDirectory. ziprd := ZipArchive oldFileNamed:badFile. ziprd restoreOsDirectory:outDir fromArchiveDirectory: '/'. ziprd close. FileBrowser default openOn:outDir [exEnd]

fileFormatDescription

File: APPNOTE.TXT - .ZIP File Format Specification

Class protocol:

Signal constants
o  unsupportedZipFileFormatErrorSignal

o  zipFileFormatErrorSignal

accessing-defaults
o  defaultAppendTrailingSlash
Returns the default trailing slash behavior. For details
see the class documentation

o  defaultAppendTrailingSlash: aBoolean
Sets the default trailing slash behavior. For details
see the class documentation

o  zipFileCachingTime: seconds
by default, zip files are cached for some time,
in case they are reconsulted soon.
The default time is 60s, but can be changed by this setter

class initialization
o  initialize
self initialize

cleanup
o  flush
forget about cached zipArchives

Usage example(s):

     self flush

o  installFlushBlock
forget about cached zipArchives

Usage example(s):

     self installFlushBlock

o  lowSpaceCleanup
forget about cached zipArchives

Usage example(s):

     self lowSpaceCleanup

constants
o  COMPRESSION_DEFLATED
please use compressionDeflated instead (Squeak compat.)

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  COMPR_DEFLATED
please use compressionDeflated instead (Squeak compat.)

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  LREC_SIZE

o  centralDirectoryMinimumSize

o  compressionDeflated
same as COMPRESSION_DEFLATED - squeak compatibility

o  compressionStored
same as COMPRESSION_STORED - squeak compatibility

o  streamBufferSize
chunk size when reading from/writing to a Stream

instance creation
o  appendFileNamed: aFilename
return a zipArchive open on a filename;
if the file exists, items are added;
if not, it is created anew.

o  new
(comment from inherited method)
return an instance of myself without indexed variables

o  newFileNamed: aFilename
return a zipArchive open on a new created filename

o  oldFileNamed: aFilename
return a zipArchive open on aFilename

o  oldFileNamed: aFilename startOfArchive: startOfArchive endOfArchive: endOfArchive
return a zipArchive open on aFilename

o  readingFile: aFilename do: aBlock
Open a instance on aFilename, evaluate aBlock, passing the archive,
and return the block's value.
Ensures that the archive is closed.

o  readingFrom: aPositionableStream
open an existing Zip archive - read data from aPositionableStream

o  writingTo: aPositionableStream
open an new Zip archive - write data to aPositionableStream

private
o  validZipFileNameFrom: zipFileName
construct a valid zip filename

Usage example(s):

    ZipArchive new validZipFileNameFrom:'hello//world'
    ZipArchive new validZipFileNameFrom:'hello\\world'
    ZipArchive new validZipFileNameFrom:'hello\/world'
    ZipArchive new validZipFileNameFrom:'hello/\world'
    ZipArchive new validZipFileNameFrom:'hello/\world/aaa bbb/ccc'

private - decompression
o  decode: rawBytes method: compressionMethod size: uncompressedSize asString: asStringBoolean
decode rawBytes into a byteArray or string.
Answer the decoded data or raise an Error.

queries
o  isZipArchive: aFilename
answer true, if aFilename references a Zip archive

utilities
o  dateToZipFileDate: aDate
data in msdos format

o  timeToZipFileTime: aTime
time in msdos format

o  zipFileDateToDate: zipDate
data in msdos format

Usage example(s):

     self zipFileDateToDate:0
     self zipFileDateToDate:0x354b                                  => 11-10-2006
     self dateToZipFileDate:(Date newDay:11 month:11 year:2006)     => 13675 (= 0x354b)
     
     File modification date  stored in standard MS-DOS format:
        Bits 00-04: day
        Bits 05-08: month
        Bits 09-15: years from 1980

o  zipFileTimeToTime: zipTime
time in msdos format

Usage example(s):

     self zipFileTimeToTime:0x7d1c                                  => 15:40:56
     self timeToZipFileTime:(Time hours:15 minutes:40 seconds:56)   => 32028 (= 0x7d1c)
     
     File modification time stored in standard MS-DOS format:
        Bits 00-04: seconds divided by 2
        Bits 05-10: minute
        Bits 11-15: hour

o  zipFileTimestampFromDate: zipDate time: zipTime
date in msdos format

Usage example(s):

     self zipFileTimestampFromDate:0x354b time:0x7d1c
                                                     => 11-10-2006 15:40:56
     self timeToZipFileTime:(Time hours:15 minutes:40 seconds:56)   => 32028 (= 0x7d1c)
     self dateToZipFileDate:(Date newDay:11 month:11 year:2006)     => 13675 (= 0x354b)


Instance protocol:

Compatibility-Squeak
o  binaryContentsOf: fileName

o  contentsOf: fileName
( an extension from the stx:libcompat package )

o  desiredCompressionMethod: aCompressionMethod
for now: ignored

o  testUTF8
( an extension from the stx:libcompat package )

accessing
o  appendTrailingSlash
Returns default trailing slash behavior, For details,
see class documentation

o  appendTrailingSlash: aBoolean
Sets trailing slash behavior. If true, all directory entries
will have a trailing slash in its nama. For details, see class
documentation

o  entries
return a collection of fileName entries

o  file

o  fileSize

o  memberNamed: aFilename

o  members
return a collection of members

o  membersMatching: aFileMatchPattern
return a collection of members which match aFileMatchPattern

o  name
return the (file-)name of this zipArchive

o  numberOfEntries
return the number of entries in the archive

o  pathName
FileStream compatibility: answer the name of the underlying file - a String

o  rawStream

o  setArchiveStartPosition: aStartposition endPosition: anEndPosition

o  signatureInformation
for compatibility with SignedZipArchive

o  size
Modified (format): / 17-02-2017 / 22:30:50 / stefan

o  zipMembersByName

accessing-misc
o  objectAttributes
return a Collection of attributes - nil if there is none.

o  objectAttributes: aDictionary
(comment from inherited method)
set the collection of attributes.

The default implementation here uses a global Dictionary to store
attributes which may be too slow for high frequency change&update.
Therefore, some classes may redefine this for better performance.

comparing
o  = aZipArchiveToCompare
open both archives
- check file size
- check number of archive members
- perform a binary compare of the archives.

o  hash
(comment from inherited method)
return an Integer useful as a hash key for the receiver.
This hash should return same values for objects with same
contents (i.e. use this to hash on structure)

error raising
o  error: anErrorString
redefined, to raise ZipFileFormatErrorSignal

open & close
o  close

o  closePrepareForReopen
close the underlying OS resources (stream),
but keep enough information to allow reopening later (i.e. the archive name)

o  flush
finish the zip archive, but do not close the underlying stream

o  name: filenameOrString mode: readOrWriteOrAppendModeSymbol
open read or writestream on archiveFileName.
readOrWriteOrAppendModeSymbol is either #read, #write or #append.

Usage example(s):

        self new name:'/tmp/zip.zip' mode:#write
        self new name:'/tmp/zip.zip' asFilename mode:#write

o  readFrom: aPositionableStreamOrFilenameString
initialize the archive to read from aPositionableStream,
or from the file by that name (pharo compatibility)
Obsolete - backward compatibility.

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  readingFrom: aPositionableStream
initialize the archive to read from aPositionableStream

o  reopenForReading

o  writingTo: aPositionableStream
initialize the archive to write to aPositionableStream

printing
o  printOn: aStream
(comment from inherited method)
append a user printed representation of the receiver to aStream.
The format is suitable for a human - not meant to be read back.

The default here is to output the receiver's class name.
BUT: this method is heavily redefined for objects which
can print prettier.

private
o  closeFile
backward compatibility

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  dataStartOf: zipEntry
fetch the absolute start address of the data of a given zipEntry.
Note: extra field and extra field length may be different from that in
the central directory entry. Sow e have to fetch the local header.

o  initialize
(comment from inherited method)
just to ignore initialize to objects which do not need it

o  openFile

o  setDefaultArchiveBounds
set start and end of archive if it is nil. That means no bounds have been defined
before. In that case the archive is the complete file.

private - directory stuff
o  addCentralZipDirectory
ensure that the file position is at end

o  addMember: zmemb
add a zipMember

o  checkZipArchive
check if my file is really a zip archive. answer true or false.

o  checkZipArchive: archiveFileName

o  findMember: name
find a zipMember by name

o  findMemberAllowForMissingTrailingSlash: name
find a zipMember by name. Allow for missing trailing slash for directories.
This method is currently used by JavaVM

o  findMemberForWhich: aOneArgBlock
find a zipMember by condition

o  readDirectory
read the zip directory into a linked-list of zipMembers

o  searchForEndOfCentralDirectorySignature
read the zip directory into a linked-list of zipMembers

o  zipMembersDo: aBlock
evaluate aBlock for all zipMembers

queries
o  isValidFile: path
Return true, if the receiver contains given file. false otherwise.

o  isValidPath: anArchivePathName

reading
o  extract: fileName
extract an entry identified by fileName as a byteArray;
nil on errors

o  extract: fileName asString: asStringBoolean
extract an entry identified by fileName as a byteArray or string;
return the extracted string or byteArray, nil on errors

o  nextBytes: nBytesToRead of: zmember startingAt: pos into: aByteArray startingAt: writeOffset

o  restoreOsDirectory: osDirectoryName fromArchiveDirectory: archiveDirectoryName
extracts all files from an archiveDirectory (that is the dir name inside the zip)
into a folder (that is a folder on the disk).
Abswer the number of extracted plain files.

o  withPositionAndMemberFor: fileName do: aBlock
return nil, if the file is not in the archive,
or the value from aBlock if it is

o  withPositionAndMemberFor: fileName do: aBlock onError: failBlock
return the value from failBlock, if the archive cannot be read
or the file is not in the archive,
or the value from aBlock if it is

reading - stream
o  extract: fileNameInZipArchive intoFile: aFilename restoreModificationTime: restoreModificationTime
extract an entry identified by fileNameInZipArchive into aFilename.
If restoreModificationTime is set to true restore the modificationTime of aFilename
to the time as stored in the archive.
Return nil if failed, number of bytes read on success

o  extract: fileName intoStream: aWriteStream
extract an entry identified by filename into aWriteStream.
Return nil if failed, number of bytes read on success

o  extract: fileName intoStream: aWriteStream restoreModificationTime: restoreModificationTime
extract an entry identified by filename into aWriteStream.
If restoreModificationTime is set to true and aWriteStream is a FileStream,
restore the modificationTime of the destination file to the time as stored in the archive.
Return nil if failed, number of bytes read on success.

o  extract: fileName toStream: outStream
marked as obsolete by Stefan Vogel at 13-Jul-2023

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  readStreamFor: nameOfFileInArchive
open a stream on archive contents identified by nameOfFileInArchive

o  readStreamForMember: zipEntry
open a stream on a member entry

o  reopenAndExtract: fileName intoStream: aWriteStream
extract an entry identified by filename into aWriteStream

writing
o  addArchiveDirectory: archiveDirectoryName fromOsDirectory: osDirectoryName

o  addArchiveDirectory: archiveDirectoryName fromOsDirectory: osDirectoryName compressMethod: theCompressMethod
do not create directories (isDirectory = true) - they are not compatible between operating systems

o  addArchiveDirectoryCompressed: archiveDirectoryName fromOsDirectory: osDirectoryName

o  addDirectory: dirNameInZip
do not create directories (isDirectory = true) - they are not compatible between operating systems

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  addFile: aFileName as: fileNameInZip

o  addFile: fileNameInZip fromStream: aStream

o  addFile: fileNameInZip fromStream: aStream compressMethod: theCompressMethodArg

o  addFile: fileNameInZip fromStream: aStream compressMethod: theCompressMethodArg asDirectory: isDirectory
Create a new entry named fileNameInZip in the archive.
Contents is read from aStream up to the end.
Do not create directories (isDirectory = true) - they are not compatible between operating systems

o  addFile: fileNameInZip fromStream: aStream compressMethod: theCompressMethodArg asDirectory: isDirectory preserveModificationTime: preserveModificationTime
Create a new entry named fileNameInZip in the archive.
Contents is read from aStream up to the end.
Do not create directories (isDirectory = true) - they are not compatible between operating systems.
If preserveModificationTime is set to true, set the modificationTime (time and date) stored in the
archive to the modificationTime of the file aStream originates from (only for FileStreams);
else the modificationTime will be set to now.

o  addFile: fileNameInZip withContents: data

o  addFile: fileNameInZip withContents: data compressMethod: compressMethod

o  addFile: fileNameInZip withContents: data compressMethod: theCompressMethodArg asDirectory: isDirectory
do not create directories (isDirectory = true) - they are not compatible between operating systems

o  addFileCompressed: fileNameInZip fromStream: aStream

o  addFileCompressed: fileNameInZip fromStream: aStream preserveModificationTime: preserveModificationTime

o  addFileCompressed: fileNameInZip withContents: data

o  addString: aString as: fileNameInZip
self addFile:fileNameInZip fromStream:(aString readStream)

o  basicAddFile: aFileName withContents: data compressMethod: theCompressMethodArg asDirectory: isDirectory
do not create directories (isDirectory = true) - they are not compatible between operating systems

writing - stream
o  compressedWriteStreamFor: nameOfFileInArchive
create new entry in central directory

o  writeStreamFor: nameOfFileInArchive compressMethod: theCompressMethodArg
create new entry in central directory


Private classes:

    AbstractZipStream
    ZipCentralDirectory
    ZipMember
    ZipReadStream
    ZipWriteStream

Examples:


    |zip bytes|

    'fooZZZZ.zip' asFilename remove.
    zip := ZipArchive newFileNamed:'fooZZZZ.zip'.
    zip addFileCompressed:'bar' withContents:'hello world'.
    zip close.
    |zip bytes|

    zip := ZipArchive oldFileNamed:'fooZZZZ.zip'.
    bytes := zip extract:'bar'.
    zip close.
    'fooZZZZ.zip' asFilename remove.
    bytes
    |zip bytes|

    zip := ZipArchive oldFileNamed:'source/stx/libbasic2.zip'.
    zip entries do:[:entry |
        Transcript showCR:entry
    ].
    zip close.
    |zip bytes|

    zip := ZipArchive oldFileNamed:'source/stx/libbasic2.zip'.
    bytes := zip extract:'TwoByteStr.st'.
    zip close.
    Transcript showCR:(bytes asString).
compatibility write check with winzip (compressed with deflate)
    |zipwr testDirectory testFileWr|

    testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'.
    testFileWr := 'crcTest_resume_compressed.zip'.

    zipwr := ZipArchive newFileNamed:(testDirectory, testFileWr).
    zipwr addFile:'crcTest_resume_compressed.txt' withContents: 'resume'.
    zipwr close.
compatibility read check with winzip (compressed with deflate)
    |ziprd testDirectory testFileRd contents|

    testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'.
    testFileRd := 'crcTest_resume_compressed.zip'.

    ziprd := ZipArchive oldFileNamed:(testDirectory, testFileRd).
    contents := ziprd extract: ziprd entries first.
    contents inspect.
    ziprd close.
compatibility write check with winzip (uncompressed)
    |zipwr testDirectory testFileWr|

    testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'.
    testFileWr := 'crcTest_resume_uncompressed.zip'.

    zipwr := ZipArchive newFileNamed:(testDirectory, testFileWr).

    zipwr addFile:'crcTest_resume_uncompressed.txt'
        withContents:'resume'
       compressMethod:0
          asDirectory:false.

    zipwr close.
compatibility read check with winzip (uncompressed)
    |ziprd testDirectory testFileRd contents|

    testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'.
    testFileRd := 'crcTest_resume_uncompressed.zip'.

    ziprd := ZipArchive oldFileNamed:(testDirectory, testFileRd).
    contents := ziprd extract: ziprd entries first.
    contents inspect.
    ziprd close.
read an archive with files and/or directories, fetch the entries and create a new archive with the same content
    |ziprd zipwr entryDict testDirectory testFileRd testFileWr|

    testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'.
    testFileRd := 'projects.zip'.
    testFileWr := 'projects_expecco_test.zip'.

    ziprd := ZipArchive oldFileNamed:(testDirectory, testFileRd).
    entryDict := Dictionary new.
    ziprd entries do: [:aFileName|
        entryDict at:aFileName put:(ziprd extract: aFileName) asString.
    ].
    ziprd close.

    zipwr := ZipArchive newFileNamed:(testDirectory, testFileWr).
    entryDict keysAndValuesDo: [:key :value|
        (value size == 0) ifTrue: [
            zipwr addDirectory:key.
        ] ifFalse: [
            zipwr addFile:key withContents:value
        ].
    ].
    zipwr close.
    |zipwr ziprd testDirectory testFileWr testFileRd zs|

    testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'.
    testFileWr := 'crcTest_resume_compressed.zip'.

    zipwr := ZipArchive newFileNamed:(testDirectory, testFileWr).
    zipwr addFile:'crcTest_resume_compressed.txt' withContents: 'Das ist ein test, das ist ein test, das ist ein test'.
    zipwr close.

    testFileRd := 'crcTest_resume_compressed.zip'.

    ziprd := ZipArchive oldFileNamed:(testDirectory, testFileRd).
    zs := ziprd readStreamFor: 'crcTest_resume_compressed.txt'.
    zs inspect.
    ziprd close.
    |zipwr ziprd testDirectory testFileWr testFileRd rs result|

    testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'.
    testFileWr := 'readStreamTest_HelloWorld.zip'.

    zipwr := ZipArchive newFileNamed:(testDirectory, testFileWr).
    zipwr addFile:'readStreamTest_HelloWorld.txt' withContents: 'Hello World!' compressed: false.
    zipwr close.

    testFileRd := 'readStreamTest_HelloWorld.zip'.
    ziprd := ZipArchive oldFileNamed:(testDirectory, testFileRd).
    rs := ziprd readStreamFor: 'readStreamTest_HelloWorld.txt'.

    result := ''.
    [ rs atEnd ] whileFalse: [
        result := result, (rs nextAvailable:5).
    ].
    result inspect.
    rs close.
    ziprd close.
read an archive with files and/or directories and/or zipArchives, fetch the entries (also from the include zip archives) and create a new archive
    |ziprd zipwr entryDict testDirectory testFileRd testFileWr zipRdSub1 zipRdSub2|

    testDirectory := 'C:\Dokumente und Einstellungen\stefan\Eigene Dateien\tmp\'.
    testFileRd := 'ZipInZipFileTest.zip'.
    testFileWr := 'ZipInZipFileTest_generated.zip'.

    ziprd := ZipArchive oldFileNamed:(testDirectory, testFileRd).
    entryDict := Dictionary new.
    ziprd entries do: [:aFileName|
        Transcript showCR: 'processing in top: ', aFileName.
        (aFileName endsWith:'.zip') ifTrue: [
            zipRdSub1 := ziprd extractArchive: aFileName.
            zipRdSub1 entries do: [:aFileName1|
                Transcript showCR: 'processing in sub 1: ', aFileName1.
                (aFileName1 endsWith:'.zip') ifTrue: [
                    zipRdSub2 := zipRdSub1 extractArchive: aFileName1.
                    zipRdSub2 entries do: [:aFileName2|
                        Transcript showCR: 'processing in sub 2: ', aFileName2.
                        (aFileName2 endsWith:'.zip') ifTrue: [
                            self halt.
                        ] ifFalse: [
                            entryDict at:aFileName2 put:(zipRdSub2 extract: aFileName2) asString.
                        ].
                    ].
                    zipRdSub2 close.
                ] ifFalse: [
                    entryDict at:aFileName1 put:(zipRdSub1 extract: aFileName1) asString.
                ].
            ].
            zipRdSub1 close.
        ] ifFalse: [
            entryDict at:aFileName put:(ziprd extract: aFileName) asString.
        ].
    ].
    ziprd close.

    zipwr := ZipArchive newFileNamed:(testDirectory, testFileWr).
    entryDict keysAndValuesDo: [:key :value|
        (value size == 0) ifTrue: [
            zipwr addDirectory:key.
        ] ifFalse: [
            zipwr addFile:key withContents:value
        ].
    ].
    zipwr close.


ST/X 7.7.0.0; WebServer 1.702 at 20f6060372b9.unknown:8081; Sat, 27 Jul 2024 02:28:01 GMT