Class for accessing Zip files.
ZipArchive provides two interfaces for reading or writing zip files. The first is a stream based interface that should be familiar to anyone who's ever written code, and the other is an archiver interface that should be familiar to anyone who's ever used a standard Zip application.
The two interfaces are not mutually exclusive so you can use both if you wish. For example, you may want to use the stream interface to add a configuration file to a zip without having to create a temporary file and then add a number of existing files using the addFile() method.
Both interfaces have their advantages and disadvantages, which will be discussed below.
Accessing a Zip file
Before you can access any files in the zip, you first need to open the archive. This is the same regardless of which interface you use, and there are two ways to accomplish it.
Opening from a file on the file system
The simplest method of opening a zip file is to use openArchive(const char *, AccessMode) to open a file that is on the disk.
When opening a zip file on the file system, the filename is automatically set.
Opening a file from a stream
A more advanced way to open the zip file is from an arbitrary stream. The only requirements are that the stream supports seeking and was opened with the correct access mode. Use the openArchive(Stream *, AccessMode) method to do this.
Opening zip files from arbitrary streams is a very powerful feature and opens many interesting doors. For example, combined with some small changes to the resource manager and startup code, it was possible to implement a VFS that allows the entire game to run from a single executable with no external files.
Note that the filename is not automatically set when you open the zip file from a stream. The filename is used in error reporting and by the resource manager, so you may wish to set it to something meaningful.
Regardless of which method you use to open the file, the AccessMode controls what you can do with it. If you open the archive as ReadWrite, you can both write to and read from files in the zip. However, it is not possible to open files in the zip as ReadWrite.
Closing the zip file
When you are done with the zip file, call closeArchive() to free any resources and rebuild the zip file if it was open for Write.
Example
Archiver Interface
The archiver style interface allows you to add, extract and delete files in the zip in a way similar to that of an standard archiver application.
While the archiver interface is simple to use, it is blocking and thus difficult to use asynchronously. If you require zip file support and responsive UI then you should consider using the stream interface instead.
See the following method documentation for more information:
Example
{
za.
addFile(
"test.txt",
"test.txt");
}
The stream based interface allows you to access files within the zip in a similar way to accessing the file system through the ResourceManager.
There are a few small caveats to the stream interface:
-
When writing files, the whole file must be written sequentially. You cannot seek in the stream.
-
It may or may not be possible to seek in streams opened for read. Files that were not compressed in the zip file support seeking with no penalty. In all cases where the file is compressed, if seeking is supported by the decompression and/or decryption filter then it carries with it an extreme performance penalty and should be avoided. All currently available decompression filters (Deflate and BZip2) and decryption filters (Zip 2.0 and AES) support seeking, but have to reset their state and re-decompress/decrypt the entire file up to the point you are seeking to. An extreme example would be that if you had a 20MB file and were currently at the end of the file, seeking back 1 byte of the file would cause the entire file to be decompressed again. This would be a blocking operation that would lock Torque up for an appreciable chunk of time.
-
Files can only be open as Read or Write, but not ReadWrite
-
Only one file can be open for read at a time, but multiple files can be open for write at a time. - [tom, 2/9/2007] Check this
See the following method documentation for more information:
CRC Checking
Unlike the archiver interface, there is no automatic CRC checking when reading from files using the stream interface. If you will only be reading files sequentially, see the documentation for ZipStatFilter for a useful trick to get easy CRC checking.
Example
{
{
stream->
writeLine((U8 *)
"Hello, Zipped World!");
}
}
Compressed Files
The zip code included with stock Torque supports "stored" (uncompressed) files and deflate compressed files. The code is easily extensible to support any compression format that the Zip file format supports.
In addition to the deflate and stored formats, BZip2 is supported but not included with stock Torque. BZip2 support will be released as a resource in the future.
Encrypted Files
Preliminary support for Encrypted/Passworded files is included in TGB Pro only. Currently, only Zip 2.0 encryption is supported by the stock code. AES support exists and may be released as a resource in the future.
To set the password used for zips, you need to modify the DEFAULT_ZIP_PASSWORD define in core/zip/zipArchive.h. This password will be used for all zips that require a password. The default password is changeme. This may be used by TGB Binary users to test encrypted zips with their game. Shipping with the default password is not recommended for obvious reasons.
The intended use of encrypted zips is for preventing casual copying of your game's assets. Zip 2.0 encryption has known weaknesses that allow an attacker to decrypt the contents of the zip. AES encryption is significantly more secure, but as the password must be stored in the executable it will not stop a determined attacker.
A script accessible mechanism for setting the password does not currently exist. To use encrypted mod zips, if the password was in script then the password would be clearly visible to anyone that cared to poke around in your scripts.
Encrypted zip support will be improved in a future version. For now, a more secure method of storing the password is left as an exercise for the reader.
Accessing Zip files from script
ZipArchive is a C++ class and thus cannot be used from script. However, a wrapper is provided to allow script access to zips. See the documentation on ZipObject for more information.
More Examples
More in depth example code than that featured here can be found in the unit tests for the zip code (in the core/zip/unitTests directory) and the script code for the packaging utility.