aboutsummaryrefslogtreecommitdiff
path: root/mp/src/public/zip_utils.cpp
diff options
context:
space:
mode:
authorJohn Schoenick <[email protected]>2015-09-09 18:35:41 -0700
committerJohn Schoenick <[email protected]>2015-09-09 18:35:41 -0700
commit0d8dceea4310fde5706b3ce1c70609d72a38efdf (patch)
treec831ef32c2c801a5c5a80401736b52c7b5a528ec /mp/src/public/zip_utils.cpp
parentUpdated the SDK with the latest code from the TF and HL2 branches. (diff)
downloadsource-sdk-2013-0d8dceea4310fde5706b3ce1c70609d72a38efdf.tar.xz
source-sdk-2013-0d8dceea4310fde5706b3ce1c70609d72a38efdf.zip
Updated the SDK with the latest code from the TF and HL2 branches.HEADmaster
Diffstat (limited to 'mp/src/public/zip_utils.cpp')
-rw-r--r--mp/src/public/zip_utils.cpp439
1 files changed, 277 insertions, 162 deletions
diff --git a/mp/src/public/zip_utils.cpp b/mp/src/public/zip_utils.cpp
index 79f51c5c..848e7a79 100644
--- a/mp/src/public/zip_utils.cpp
+++ b/mp/src/public/zip_utils.cpp
@@ -23,6 +23,13 @@
#include "byteswap.h"
#include "utlstring.h"
+#include "tier1/lzmaDecoder.h"
+
+// Not every user of zip utils wants to link LZMA encoder
+#ifdef ZIP_SUPPORT_LZMA_ENCODE
+#include "lzma/lzma.h"
+#endif
+
// Data descriptions for byte swapping - only needed
// for structures that are written to file for use by the game.
BEGIN_BYTESWAP_DATADESC( ZIP_EndOfCentralDirRecord )
@@ -248,7 +255,7 @@ public:
CBufferStream( CUtlBuffer& buff ) : IWriteStream(), m_buff( &buff ) {}
// Implementing IWriteStream method
- virtual void Put( const void* pMem, int size ) { m_buff->Put( pMem, size ); }
+ virtual void Put( const void* pMem, int size ) {m_buff->Put( pMem, size );}
// Implementing IWriteStream method
virtual unsigned int Tell( void ) { return m_buff->TellPut(); }
@@ -321,13 +328,13 @@ public:
void Reset( void );
// Add file to zip under relative name
- void AddFileToZip( const char *relativename, const char *fullpath );
+ void AddFileToZip( const char *relativename, const char *fullpath, IZip::eCompressionType compressionType );
// Delete file from zip
void RemoveFileFromZip( const char *relativename );
// Add buffer to zip as a file with given name
- void AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode );
+ void AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode, IZip::eCompressionType compressionType );
// Check if a file already exists in the zip.
bool FileExistsInZip( const char *relativename );
@@ -373,9 +380,12 @@ private:
typedef struct
{
- CUtlSymbol m_Name;
- unsigned int filepos;
- int filelen;
+ CUtlSymbol m_Name;
+ unsigned int filepos;
+ int filelen;
+ int uncompressedLen;
+ CRC32_t crc32;
+ IZip::eCompressionType compressionType;
} TmpFileInfo_t;
CByteswap m_Swap;
@@ -405,18 +415,25 @@ private:
CUtlSymbol m_Name;
// Lenth of data element
- int m_Length;
+ int m_nCompressedSize;
+
+ // Original, uncompressed size
+ int m_nUncompressedSize;
+
// Raw data, could be null and data may be in disk write cache
void *m_pData;
// Offset in Zip ( set and valid during final write )
unsigned int m_ZipOffset;
- // CRC of blob ( set and valid during final write )
+ // CRC of blob
CRC32_t m_ZipCRC;
// Location of data in disk cache
unsigned int m_DiskCacheOffset;
unsigned int m_SourceDiskOffset;
+
+ // The compression used on the data if any
+ IZip::eCompressionType m_eCompressionType;
};
// For fast name lookup and sorting
@@ -435,12 +452,14 @@ private:
CZipFile::CZipEntry::CZipEntry( void )
{
m_Name = "";
- m_Length = 0;
+ m_nCompressedSize = 0;
+ m_nUncompressedSize = 0;
m_pData = NULL;
m_ZipOffset = 0;
m_ZipCRC = 0;
m_DiskCacheOffset = 0;
m_SourceDiskOffset = 0;
+ m_eCompressionType = IZip::eCompressionType_None;
}
//-----------------------------------------------------------------------------
@@ -450,12 +469,14 @@ CZipFile::CZipEntry::CZipEntry( void )
CZipFile::CZipEntry::CZipEntry( const CZipFile::CZipEntry& src )
{
m_Name = src.m_Name;
- m_Length = src.m_Length;
+ m_nCompressedSize = src.m_nCompressedSize;
+ m_nUncompressedSize = src.m_nUncompressedSize;
+ m_eCompressionType = src.m_eCompressionType;
- if ( src.m_Length > 0 && src.m_pData )
+ if ( src.m_nCompressedSize > 0 && src.m_pData )
{
- m_pData = malloc( src.m_Length );
- memcpy( m_pData, src.m_pData, src.m_Length );
+ m_pData = malloc( src.m_nCompressedSize );
+ memcpy( m_pData, src.m_pData, src.m_nCompressedSize );
}
else
{
@@ -674,20 +695,27 @@ void CZipFile::ParseFromBuffer( void *buffer, int bufferlength )
ZIP_FileHeader zipFileHeader;
buf.GetObjects( &zipFileHeader );
Assert( zipFileHeader.signature == PKID( 1, 2 ) );
- Assert( zipFileHeader.compressionMethod == 0 );
-
- char tmpString[1024];
- buf.Get( tmpString, zipFileHeader.fileNameLength );
- tmpString[zipFileHeader.fileNameLength] = '\0';
+ if ( zipFileHeader.compressionMethod != IZip::eCompressionType_None &&
+ zipFileHeader.compressionMethod != IZip::eCompressionType_LZMA )
+ {
+ Assert( false );
+ Warning( "Opening ZIP file with unsupported compression type\n");
+ }
+
+ char tmpString[1024] = { 0 };
+ buf.Get( tmpString, Min( (unsigned int)zipFileHeader.fileNameLength, (unsigned int)sizeof( tmpString ) ) );
Q_strlower( tmpString );
// can determine actual filepos, assuming a well formed zip
newfiles[i].m_Name = tmpString;
newfiles[i].filelen = zipFileHeader.compressedSize;
+ newfiles[i].uncompressedLen = zipFileHeader.uncompressedSize;
+ newfiles[i].crc32 = zipFileHeader.crc32;
newfiles[i].filepos = zipFileHeader.relativeOffsetOfLocalHeader +
- sizeof( ZIP_LocalFileHeader ) +
- zipFileHeader.fileNameLength +
- zipFileHeader.extraFieldLength;
+ sizeof( ZIP_LocalFileHeader ) +
+ zipFileHeader.fileNameLength +
+ zipFileHeader.extraFieldLength;
+ newfiles[i].compressionType = (IZip::eCompressionType)zipFileHeader.compressionMethod;
int nextOffset;
if ( m_bCompatibleFormat )
@@ -706,16 +734,19 @@ void CZipFile::ParseFromBuffer( void *buffer, int bufferlength )
{
CZipEntry e;
e.m_Name = newfiles[i].m_Name;
- e.m_Length = newfiles[i].filelen;
-
+ e.m_nCompressedSize = newfiles[i].filelen;
+ e.m_ZipCRC = newfiles[i].crc32;
+ e.m_nUncompressedSize = newfiles[i].uncompressedLen;
+ e.m_eCompressionType = newfiles[i].compressionType;
+
// Make sure length is reasonable
- if ( e.m_Length > 0 )
+ if ( e.m_nCompressedSize > 0 )
{
- e.m_pData = malloc( e.m_Length );
+ e.m_pData = malloc( e.m_nCompressedSize );
// Copy in data
buf.SeekGet( CUtlBuffer::SEEK_HEAD, newfiles[i].filepos );
- buf.Get( e.m_pData, e.m_Length );
+ buf.Get( e.m_pData, e.m_nCompressedSize );
}
else
{
@@ -826,7 +857,9 @@ HANDLE CZipFile::ParseFromDisk( const char *pFilename )
ZIP_FileHeader zipFileHeader;
zipDirBuff.GetObjects( &zipFileHeader );
- if ( zipFileHeader.signature != PKID( 1, 2 ) || zipFileHeader.compressionMethod != 0 )
+ if ( zipFileHeader.signature != PKID( 1, 2 )
+ || ( zipFileHeader.compressionMethod != IZip::eCompressionType_None
+ && zipFileHeader.compressionMethod != IZip::eCompressionType_LZMA ) )
{
// bad contents
#ifdef WIN32
@@ -836,7 +869,7 @@ HANDLE CZipFile::ParseFromDisk( const char *pFilename )
#endif
return NULL;
}
-
+
char fileName[1024];
zipDirBuff.Get( fileName, zipFileHeader.fileNameLength );
fileName[zipFileHeader.fileNameLength] = '\0';
@@ -845,11 +878,15 @@ HANDLE CZipFile::ParseFromDisk( const char *pFilename )
// can determine actual filepos, assuming a well formed zip
CZipEntry e;
e.m_Name = fileName;
- e.m_Length = zipFileHeader.compressedSize;
+ e.m_nCompressedSize = zipFileHeader.compressedSize;
+ e.m_nUncompressedSize = zipFileHeader.uncompressedSize;
+ e.m_ZipCRC = zipFileHeader.crc32;
e.m_SourceDiskOffset = zipFileHeader.relativeOffsetOfLocalHeader +
- sizeof( ZIP_LocalFileHeader ) +
- zipFileHeader.fileNameLength +
- zipFileHeader.extraFieldLength;
+ sizeof( ZIP_LocalFileHeader ) +
+ zipFileHeader.fileNameLength +
+ zipFileHeader.extraFieldLength;
+ e.m_eCompressionType = (IZip::eCompressionType)zipFileHeader.compressionMethod;
+
// Add to tree
m_Files.Insert( e );
@@ -954,19 +991,85 @@ static void CopyTextData( char *pDst, const char *pSrc, int dstSize, int srcSize
// *data -
// length -
//-----------------------------------------------------------------------------
-void CZipFile::AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode )
+void CZipFile::AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode, IZip::eCompressionType compressionType )
{
// Lower case only
char name[512];
Q_strcpy( name, relativename );
Q_strlower( name );
- int dstLength = length;
+ int outLength = length;
+ int uncompressedLength = length;
+ void *outData = data;
+ CUtlBuffer textTransform;
+ CUtlBuffer compressionTransform;
+
if ( bTextMode )
{
- dstLength = GetLengthOfBinStringAsText( ( const char * )data, length );
+ int textLen = GetLengthOfBinStringAsText( ( const char * )outData, outLength );
+ textTransform.EnsureCapacity( textLen );
+ CopyTextData( (char *)textTransform.Base(), (char *)outData, textLen, outLength );
+
+ outData = (void *)textTransform.Base();
+ outLength = textLen;
+ uncompressedLength = textLen;
}
-
+
+ // uncompressed data final at this point (CRC is before compression)
+ CRC32_t zipCRC;
+ CRC32_Init( &zipCRC );
+ CRC32_ProcessBuffer( &zipCRC, outData, outLength );
+ CRC32_Final( &zipCRC );
+
+#ifdef ZIP_SUPPORT_LZMA_ENCODE
+ if ( compressionType == IZip::eCompressionType_LZMA )
+ {
+ unsigned int compressedSize = 0;
+ unsigned char *pCompressedOutput = LZMA_Compress( (unsigned char *)outData, outLength, &compressedSize );
+ if ( !pCompressedOutput || compressedSize < sizeof( lzma_header_t ) )
+ {
+ Warning( "ZipFile: LZMA compression failed\n" );
+ return;
+ }
+
+ // Fixup LZMA header for ZIP payload usage
+ // The output of LZMA_Compress uses lzma_header_t, defined alongside it.
+ //
+ // ZIP payload format, see ZIP spec 5.8.8:
+ // LZMA Version Information 2 bytes
+ // LZMA Properties Size 2 bytes
+ // LZMA Properties Data variable, defined by "LZMA Properties Size"
+ unsigned int nZIPHeader = 2 + 2 + sizeof( lzma_header_t().properties );
+ unsigned int finalCompressedSize = compressedSize - sizeof( lzma_header_t ) + nZIPHeader;
+ compressionTransform.EnsureCapacity( finalCompressedSize );
+
+ // LZMA version
+ compressionTransform.PutUnsignedChar( LZMA_SDK_VERSION_MAJOR );
+ compressionTransform.PutUnsignedChar( LZMA_SDK_VERSION_MINOR );
+ // properties size
+ uint16 nSwappedPropertiesSize = LittleWord( sizeof( lzma_header_t().properties ) );
+ compressionTransform.Put( &nSwappedPropertiesSize, sizeof( nSwappedPropertiesSize ) );
+ // properties
+ compressionTransform.Put( &(((lzma_header_t *)pCompressedOutput)->properties), sizeof( lzma_header_t().properties ) );
+ // payload
+ compressionTransform.Put( pCompressedOutput + sizeof( lzma_header_t ), compressedSize - sizeof( lzma_header_t ) );
+
+ // Free original
+ free( pCompressedOutput );
+ pCompressedOutput = NULL;
+
+ outData = (void *)compressionTransform.Base();
+ outLength = finalCompressedSize;
+ // (Not updating uncompressedLength)
+ }
+ else
+#endif
+ /* else from ifdef */ if ( compressionType != IZip::eCompressionType_None )
+ {
+ Error( "Calling AddBufferToZip with unknown compression type\n" );
+ return;
+ }
+
// See if entry is in list already
CZipEntry e;
e.m_Name = name;
@@ -981,23 +1084,17 @@ void CZipFile::AddBufferToZip( const char *relativename, void *data, int length,
free( update->m_pData );
}
- if ( bTextMode )
- {
- update->m_pData = malloc( dstLength );
- CopyTextData( ( char * )update->m_pData, ( char * )data, dstLength, length );
- update->m_Length = dstLength;
- }
- else
- {
- update->m_pData = malloc( length );
- memcpy( update->m_pData, data, length );
- update->m_Length = length;
- }
+ update->m_eCompressionType = compressionType;
+ update->m_pData = malloc( outLength );
+ memcpy( update->m_pData, outData, outLength );
+ update->m_nCompressedSize = outLength;
+ update->m_nUncompressedSize = uncompressedLength;
+ update->m_ZipCRC = zipCRC;
if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE )
{
update->m_DiskCacheOffset = CWin32File::FileTell( m_hDiskCacheWriteFile );
- CWin32File::FileWrite( m_hDiskCacheWriteFile, update->m_pData, update->m_Length );
+ CWin32File::FileWrite( m_hDiskCacheWriteFile, update->m_pData, update->m_nCompressedSize );
free( update->m_pData );
update->m_pData = NULL;
}
@@ -1005,24 +1102,19 @@ void CZipFile::AddBufferToZip( const char *relativename, void *data, int length,
else
{
// Create a new entry
- e.m_Length = dstLength;
- if ( dstLength > 0 )
+ e.m_nCompressedSize = outLength;
+ e.m_nUncompressedSize = uncompressedLength;
+ e.m_eCompressionType = compressionType;
+ e.m_ZipCRC = zipCRC;
+ if ( outLength > 0 )
{
- if ( bTextMode )
- {
- e.m_pData = malloc( dstLength );
- CopyTextData( (char *)e.m_pData, ( char * )data, dstLength, length );
- }
- else
- {
- e.m_pData = malloc( length );
- memcpy( e.m_pData, data, length );
- }
-
+ e.m_pData = malloc( outLength );
+ memcpy( e.m_pData, outData, outLength );
+
if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE )
{
e.m_DiskCacheOffset = CWin32File::FileTell( m_hDiskCacheWriteFile );
- CWin32File::FileWrite( m_hDiskCacheWriteFile, e.m_pData, e.m_Length );
+ CWin32File::FileWrite( m_hDiskCacheWriteFile, e.m_pData, e.m_nCompressedSize );
free( e.m_pData );
e.m_pData = NULL;
}
@@ -1042,38 +1134,11 @@ void CZipFile::AddBufferToZip( const char *relativename, void *data, int length,
//-----------------------------------------------------------------------------
bool CZipFile::ReadFileFromZip( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf )
{
- // Lower case only
- char pName[512];
- Q_strncpy( pName, pRelativeName, 512 );
- Q_strlower( pName );
-
- // See if entry is in list already
- CZipEntry e;
- e.m_Name = pName;
- int nIndex = m_Files.Find( e );
- if ( nIndex == m_Files.InvalidIndex() )
- {
- // not found
- return false;
- }
-
- CZipEntry *pEntry = &m_Files[ nIndex ];
- if ( bTextMode )
- {
- buf.SetBufferType( true, false );
- ReadTextData( (char*)pEntry->m_pData, pEntry->m_Length, buf );
- }
- else
- {
- buf.SetBufferType( false, false );
- buf.Put( pEntry->m_pData, pEntry->m_Length );
- }
-
- return true;
+ return ReadFileFromZip( 0, pRelativeName, bTextMode, buf );
}
//-----------------------------------------------------------------------------
-// Reads a file from the zip
+// Reads a file from the zip. Requires the zip file handle if this zip was loaded via ParseFromDisk
//-----------------------------------------------------------------------------
bool CZipFile::ReadFileFromZip( HANDLE hZipFile, const char *pRelativeName, bool bTextMode, CUtlBuffer &buf )
{
@@ -1094,27 +1159,63 @@ bool CZipFile::ReadFileFromZip( HANDLE hZipFile, const char *pRelativeName, bool
CZipEntry *pEntry = &m_Files[nIndex];
- void *pData = malloc( pEntry->m_Length );
- CWin32File::FileSeek( hZipFile, pEntry->m_SourceDiskOffset, FILE_BEGIN );
- if ( !CWin32File::FileRead( hZipFile, pData, pEntry->m_Length ) )
+ void *pData = pEntry->m_pData;
+ CUtlBuffer readBuffer;
+ if ( !pData && hZipFile )
{
- free( pData );
- return false;
+ readBuffer.EnsureCapacity( pEntry->m_nCompressedSize );
+ CWin32File::FileSeek( hZipFile, pEntry->m_SourceDiskOffset, FILE_BEGIN );
+ if ( !CWin32File::FileRead( hZipFile, readBuffer.Base(), pEntry->m_nCompressedSize ) )
+ {
+ return false;
+ }
+
+ pData = readBuffer.Base();
+ }
+
+ CUtlBuffer decompressTransform;
+ if ( pEntry->m_eCompressionType != IZip::eCompressionType_None )
+ {
+ if ( pEntry->m_eCompressionType == IZip::eCompressionType_LZMA )
+ {
+ decompressTransform.EnsureCapacity( pEntry->m_nUncompressedSize );
+
+ CLZMAStream decompressStream;
+ decompressStream.InitZIPHeader( pEntry->m_nCompressedSize, pEntry->m_nUncompressedSize );
+
+ unsigned int nCompressedBytesRead = 0;
+ unsigned int nOutputBytesWritten = 0;
+ bool bSuccess = decompressStream.Read( (unsigned char *)pData, pEntry->m_nCompressedSize,
+ (unsigned char *)decompressTransform.Base(), decompressTransform.Size(),
+ nCompressedBytesRead, nOutputBytesWritten );
+ if ( !bSuccess ||
+ (int)nCompressedBytesRead != pEntry->m_nCompressedSize ||
+ (int)nOutputBytesWritten != pEntry->m_nUncompressedSize )
+ {
+ Error( "Zip: Failed decompressing LZMA data\n" );
+ return false;
+ }
+
+ pData = decompressTransform.Base();
+ }
+ else
+ {
+ Error( "Unsupported compression type in Zip file: %u\n", pEntry->m_eCompressionType );
+ return false;
+ }
}
if ( bTextMode )
{
buf.SetBufferType( true, false );
- ReadTextData( (const char *)pData, pEntry->m_Length, buf );
+ ReadTextData( (const char *)pData, pEntry->m_nUncompressedSize, buf );
}
else
{
buf.SetBufferType( false, false );
- buf.Put( pData, pEntry->m_Length );
+ buf.Put( pData, pEntry->m_nUncompressedSize );
}
- free( pData );
-
return true;
}
@@ -1142,7 +1243,7 @@ bool CZipFile::FileExistsInZip( const char *pRelativeName )
//-----------------------------------------------------------------------------
// Purpose: Adds a new file to the zip.
//-----------------------------------------------------------------------------
-void CZipFile::AddFileToZip( const char *relativename, const char *fullpath )
+void CZipFile::AddFileToZip( const char *relativename, const char *fullpath, IZip::eCompressionType compressionType )
{
FILE *temp = fopen( fullpath, "rb" );
if ( !temp )
@@ -1159,8 +1260,8 @@ void CZipFile::AddFileToZip( const char *relativename, const char *fullpath )
fclose( temp );
// Now add as a buffer
- AddBufferToZip( relativename, buf, size, false );
-
+ AddBufferToZip( relativename, buf, size, false, compressionType );
+
free( buf );
}
@@ -1252,8 +1353,8 @@ unsigned int CZipFile::CalculateSize( void )
for ( int i = m_Files.FirstInorder(); i != m_Files.InvalidIndex(); i = m_Files.NextInorder( i ) )
{
CZipEntry *e = &m_Files[ i ];
-
- if ( e->m_Length == 0 )
+
+ if ( e->m_nCompressedSize == 0 )
continue;
// local file header
@@ -1268,7 +1369,7 @@ unsigned int CZipFile::CalculateSize( void )
{
// round up to next boundary
unsigned int nextBoundary = ( size + m_AlignmentSize ) & ~( m_AlignmentSize - 1 );
-
+
// the directory header also duplicates the padding
dirHeaders += nextBoundary - size;
@@ -1276,7 +1377,7 @@ unsigned int CZipFile::CalculateSize( void )
}
// data size
- size += e->m_Length;
+ size += e->m_nCompressedSize;
}
size += dirHeaders;
@@ -1322,7 +1423,7 @@ int CZipFile::GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileS
CZipEntry *e = &m_Files[id];
Q_strncpy( pBuffer, e->m_Name.String(), bufferSize );
- fileSize = e->m_Length;
+ fileSize = e->m_nUncompressedSize;
return id;
}
@@ -1373,6 +1474,9 @@ void CZipFile::SaveDirectory( IWriteStream& stream )
#endif
}
+ // Might be writing a zip into a larger stream
+ unsigned int zipOffsetInStream = stream.Tell();
+
int i;
for ( i = m_Files.FirstInorder(); i != m_Files.InvalidIndex(); i = m_Files.NextInorder( i ) )
{
@@ -1380,47 +1484,50 @@ void CZipFile::SaveDirectory( IWriteStream& stream )
Assert( e );
// Fix up the offset
- e->m_ZipOffset = stream.Tell();
+ e->m_ZipOffset = stream.Tell() - zipOffsetInStream;
- if ( e->m_Length > 0 && ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) )
- {
+ if ( e->m_nCompressedSize > 0 && ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) )
+ {
// get the data back from the write cache
- e->m_pData = malloc( e->m_Length );
+ e->m_pData = malloc( e->m_nCompressedSize );
if ( e->m_pData )
{
CWin32File::FileSeek( m_hDiskCacheWriteFile, e->m_DiskCacheOffset, FILE_BEGIN );
- CWin32File::FileRead( m_hDiskCacheWriteFile, e->m_pData, e->m_Length );
+ CWin32File::FileRead( m_hDiskCacheWriteFile, e->m_pData, e->m_nCompressedSize );
}
}
- if ( e->m_Length > 0 && e->m_pData != NULL )
+ if ( e->m_nCompressedSize > 0 && e->m_pData != NULL )
{
ZIP_LocalFileHeader hdr = { 0 };
hdr.signature = PKID( 3, 4 );
- hdr.versionNeededToExtract = 10; // This is the version that the winzip that I have writes.
+ hdr.versionNeededToExtract = 10; // No special features or even compression here, set to 1.0
+#ifdef ZIP_SUPPORT_LZMA_ENCODE
+ if ( e->m_eCompressionType == IZip::eCompressionType_LZMA )
+ {
+ // Per ZIP spec 5.8.8
+ hdr.versionNeededToExtract = 63;
+ }
+#endif
hdr.flags = 0;
- hdr.compressionMethod = 0; // NO COMPRESSION!
+ hdr.compressionMethod = e->m_eCompressionType;
hdr.lastModifiedTime = 0;
hdr.lastModifiedDate = 0;
-
- CRC32_Init( &e->m_ZipCRC );
- CRC32_ProcessBuffer( &e->m_ZipCRC, e->m_pData, e->m_Length );
- CRC32_Final( &e->m_ZipCRC );
hdr.crc32 = e->m_ZipCRC;
-
+
const char *pFilename = e->m_Name.String();
- hdr.compressedSize = e->m_Length;
- hdr.uncompressedSize = e->m_Length;
+ hdr.compressedSize = e->m_nCompressedSize;
+ hdr.uncompressedSize = e->m_nUncompressedSize;
hdr.fileNameLength = strlen( pFilename );
hdr.extraFieldLength = CalculatePadding( hdr.fileNameLength, e->m_ZipOffset );
int extraFieldLength = hdr.extraFieldLength;
-
+
// Swap header in place
m_Swap.SwapFieldsToTargetEndian( &hdr );
stream.Put( &hdr, sizeof( hdr ) );
stream.Put( pFilename, strlen( pFilename ) );
stream.Put( pPaddingBuffer, extraFieldLength );
- stream.Put( e->m_pData, e->m_Length );
+ stream.Put( e->m_pData, e->m_nCompressedSize );
if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE )
{
@@ -1437,7 +1544,7 @@ void CZipFile::SaveDirectory( IWriteStream& stream )
CWin32File::FileSeek( m_hDiskCacheWriteFile, 0, FILE_END );
}
- unsigned int centralDirStart = stream.Tell();
+ unsigned int centralDirStart = stream.Tell() - zipOffsetInStream;
if ( m_AlignmentSize )
{
// align the central directory starting position
@@ -1455,21 +1562,28 @@ void CZipFile::SaveDirectory( IWriteStream& stream )
{
CZipEntry *e = &m_Files[i];
Assert( e );
-
- if ( e->m_Length > 0 && e->m_pData != NULL )
+
+ if ( e->m_nCompressedSize > 0 && e->m_pData != NULL )
{
ZIP_FileHeader hdr = { 0 };
hdr.signature = PKID( 1, 2 );
hdr.versionMadeBy = 20; // This is the version that the winzip that I have writes.
- hdr.versionNeededToExtract = 10; // This is the version that the winzip that I have writes.
+ hdr.versionNeededToExtract = 10; // No special features or even compression here, set to 1.0
+#ifdef ZIP_SUPPORT_LZMA_ENCODE
+ if ( e->m_eCompressionType == IZip::eCompressionType_LZMA )
+ {
+ // Per ZIP spec 5.8.8
+ hdr.versionNeededToExtract = 63;
+ }
+#endif
hdr.flags = 0;
- hdr.compressionMethod = 0;
+ hdr.compressionMethod = e->m_eCompressionType;
hdr.lastModifiedTime = 0;
hdr.lastModifiedDate = 0;
hdr.crc32 = e->m_ZipCRC;
- hdr.compressedSize = e->m_Length;
- hdr.uncompressedSize = e->m_Length;
+ hdr.compressedSize = e->m_nCompressedSize;
+ hdr.uncompressedSize = e->m_nUncompressedSize;
hdr.fileNameLength = strlen( e->m_Name.String() );
hdr.extraFieldLength = CalculatePadding( hdr.fileNameLength, e->m_ZipOffset );
hdr.fileCommentLength = 0;
@@ -1498,7 +1612,7 @@ void CZipFile::SaveDirectory( IWriteStream& stream )
}
}
- unsigned int centralDirEnd = stream.Tell();
+ unsigned int centralDirEnd = stream.Tell() - zipOffsetInStream;
if ( m_AlignmentSize )
{
// align the central directory starting position
@@ -1541,56 +1655,57 @@ public:
CZip( const char *pDiskCacheWritePath, bool bSortByName );
virtual ~CZip();
- virtual void Reset();
+ virtual void Reset() OVERRIDE;
// Add a single file to a zip - maintains the zip's previous alignment state
- virtual void AddFileToZip( const char *relativename, const char *fullpath );
+ virtual void AddFileToZip( const char *relativename, const char *fullpath, eCompressionType compressionType ) OVERRIDE;
// Whether a file is contained in a zip - maintains alignment
- virtual bool FileExistsInZip( const char *pRelativeName );
+ virtual bool FileExistsInZip( const char *pRelativeName ) OVERRIDE;
// Reads a file from the zip - maintains alignement
- virtual bool ReadFileFromZip( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf );
- virtual bool ReadFileFromZip( HANDLE hZipFile, const char *relativename, bool bTextMode, CUtlBuffer &buf );
+ virtual bool ReadFileFromZip( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) OVERRIDE;
+ virtual bool ReadFileFromZip( HANDLE hZipFile, const char *relativename, bool bTextMode, CUtlBuffer &buf ) OVERRIDE;
// Removes a single file from the zip - maintains alignment
- virtual void RemoveFileFromZip( const char *relativename );
+ virtual void RemoveFileFromZip( const char *relativename ) OVERRIDE;
// Gets next filename in zip, for walking the directory - maintains alignment
- virtual int GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileSize );
+ virtual int GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileSize ) OVERRIDE;
// Prints the zip's contents - maintains alignment
- virtual void PrintDirectory( void );
+ virtual void PrintDirectory( void ) OVERRIDE;
// Estimate the size of the Zip (including header, padding, etc.)
- virtual unsigned int EstimateSize( void );
+ virtual unsigned int EstimateSize( void ) OVERRIDE;
// Add buffer to zip as a file with given name - uses current alignment size, default 0 (no alignment)
- virtual void AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode );
+ virtual void AddBufferToZip( const char *relativename, void *data, int length,
+ bool bTextMode, eCompressionType compressionType ) OVERRIDE;
- // Writes out zip file to a buffer - uses current alignment size
+ // Writes out zip file to a buffer - uses current alignment size
// (set by file's previous alignment, or a call to ForceAlignment)
- virtual void SaveToBuffer( CUtlBuffer& outbuf );
+ virtual void SaveToBuffer( CUtlBuffer& outbuf ) OVERRIDE;
- // Writes out zip file to a filestream - uses current alignment size
+ // Writes out zip file to a filestream - uses current alignment size
// (set by file's previous alignment, or a call to ForceAlignment)
- virtual void SaveToDisk( FILE *fout );
- virtual void SaveToDisk( HANDLE hOutFile );
+ virtual void SaveToDisk( FILE *fout ) OVERRIDE;
+ virtual void SaveToDisk( HANDLE hOutFile ) OVERRIDE;
- // Reads a zip file from a buffer into memory - sets current alignment size to
+ // Reads a zip file from a buffer into memory - sets current alignment size to
// the file's alignment size, unless overridden by a ForceAlignment call)
- virtual void ParseFromBuffer( void *buffer, int bufferlength );
- virtual HANDLE ParseFromDisk( const char *pFilename );
+ virtual void ParseFromBuffer( void *buffer, int bufferlength ) OVERRIDE;
+ virtual HANDLE ParseFromDisk( const char *pFilename ) OVERRIDE;
// Forces a specific alignment size for all subsequent file operations, overriding files' previous alignment size.
// Return to using files' individual alignment sizes by passing FALSE.
- virtual void ForceAlignment( bool aligned, bool bCompatibleFormat, unsigned int alignmentSize );
+ virtual void ForceAlignment( bool aligned, bool bCompatibleFormat, unsigned int alignmentSize ) OVERRIDE;
// Sets the endianess of the zip
- virtual void SetBigEndian( bool bigEndian );
- virtual void ActivateByteSwapping( bool bActivate );
+ virtual void SetBigEndian( bool bigEndian ) OVERRIDE;
+ virtual void ActivateByteSwapping( bool bActivate ) OVERRIDE;
- virtual unsigned int GetAlignment();
+ virtual unsigned int GetAlignment() OVERRIDE;
private:
CZipFile m_ZipFile;
@@ -1599,11 +1714,11 @@ private:
static CUtlLinkedList< CZip* > g_ZipUtils;
IZip *IZip::CreateZip( const char *pDiskCacheWritePath, bool bSortByName )
-{
+{
CZip *pZip = new CZip( pDiskCacheWritePath, bSortByName );
g_ZipUtils.AddToTail( pZip );
- return pZip;
+ return pZip;
}
void IZip::ReleaseZip( IZip *pZip )
@@ -1632,9 +1747,9 @@ void CZip::ActivateByteSwapping( bool bActivate )
m_ZipFile.ActivateByteSwapping( bActivate );
}
-void CZip::AddFileToZip( const char *relativename, const char *fullpath )
+void CZip::AddFileToZip( const char *relativename, const char *fullpath, eCompressionType compressionType )
{
- m_ZipFile.AddFileToZip( relativename, fullpath );
+ m_ZipFile.AddFileToZip( relativename, fullpath, compressionType );
}
bool CZip::FileExistsInZip( const char *pRelativeName )
@@ -1678,9 +1793,9 @@ unsigned int CZip::EstimateSize( void )
}
// Add buffer to zip as a file with given name
-void CZip::AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode )
+void CZip::AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode, eCompressionType compressionType )
{
- m_ZipFile.AddBufferToZip( relativename, data, length, bTextMode );
+ m_ZipFile.AddBufferToZip( relativename, data, length, bTextMode, compressionType );
}
void CZip::SaveToBuffer( CUtlBuffer& outbuf )