diff -r 000000000000 -r e4d67989cc36 compressionlibs/ziplib/src/ezlib/gzip.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/compressionlibs/ziplib/src/ezlib/gzip.cpp Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,597 @@ +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include "libzcore.h" + +const TUint8 EZGZipFile::ID1 = 31; +const TUint8 EZGZipFile::ID2 = 139; + +/** +Constructor +*/ +EXPORT_C TEZGZipHeader::TEZGZipHeader() : iId1(EZGZipFile::ID1), iId2(EZGZipFile::ID2), iCompressionMethod(8), iFlags(0), iTime(0), + iExtraFlags(0), iOs(255), iXlen(0), iExtra(NULL), iFname(NULL), iComment(NULL), iCrc(0) + { + + } + +/** +Destructor +*/ +EXPORT_C TEZGZipHeader::~TEZGZipHeader() + { + delete iExtra; + delete iFname; + delete iComment; + } + +/** +Constructor +*/ +EXPORT_C TEZGZipTrailer::TEZGZipTrailer() : iCrc32(0), iSize(0) + { + + } + +/** +Constructor + +@param aCrc the CRC to use for archive checking +@param aSize the size of the trailer +*/ +EXPORT_C TEZGZipTrailer::TEZGZipTrailer(TInt32 aCrc, TInt32 aSize) : iCrc32(aCrc), iSize(aSize) + { + + } + +//-------------------------------------------------------------------------------------------------------- + +/** +Read the zip header from the specified zip file into the TEZGZipHeader object + +@param aFile the zip file to read from +@param aHeader the target header object +@leave KEZlibErrBadGZipHeader invalid zip header +@leave ... Any of the system wide error codes +*/ +EXPORT_C void EZGZipFile::ReadHeaderL(RFile &aFile, TEZGZipHeader &aHeader) + { + TInt obligatoryData = sizeof(aHeader.iId1) + sizeof(aHeader.iId2) + sizeof(aHeader.iCompressionMethod) + + sizeof(aHeader.iFlags) + sizeof(aHeader.iTime) + sizeof(aHeader.iExtraFlags) + sizeof(aHeader.iOs); + + TPtr8 des(&aHeader.iId1,0,obligatoryData); + TInt err = aFile.Read(des); + if (err != KErrNone || (des.Size() != obligatoryData)) + User::Leave(KEZlibErrBadGZipHeader); + + if (aHeader.iId1 != ID1 || aHeader.iId2 != ID2) + User::Leave(KEZlibErrBadGZipHeader); + + if (aHeader.iFlags & (1 << EFExtra)) // then the extra bit is set + { + des.Set(REINTERPRET_CAST(TUint8 *,&aHeader.iXlen),0,sizeof(aHeader.iXlen)); + err = aFile.Read(des); + if (err != KErrNone || des.Size() != sizeof(aHeader.iXlen) || aHeader.iXlen < 0) + User::Leave(KEZlibErrBadGZipHeader); + + aHeader.iExtra = HBufC8::NewMaxL(aHeader.iXlen); + TPtr8 des = aHeader.iExtra->Des(); + err = aFile.Read(des); + if (err != KErrNone || des.Size() != aHeader.iXlen) + User::Leave(KEZlibErrBadGZipHeader); + } + + if (aHeader.iFlags & (1 << EFName)) // then read in filename + ReadStringIntoDescriptorL(aFile,&aHeader.iFname); + + if (aHeader.iFlags & (1 << EFComment)) // then read in comment + ReadStringIntoDescriptorL(aFile,&aHeader.iComment); + + if (aHeader.iFlags & (1 << EFHcrc)) + { + des.Set(REINTERPRET_CAST(TUint8*,&aHeader.iCrc),0,sizeof(aHeader.iCrc)); + err = aFile.Read(des); + if (err != KErrNone || des.Size() != sizeof(aHeader.iCrc)) + User::Leave(KEZlibErrBadGZipHeader); + } + } + +/** +Write the zip header to the specified file + +@param aFile the file to write to +@param aHeader the header object to write to the file +@leave ... Any of the system wide error codes +*/ +EXPORT_C void EZGZipFile::WriteHeaderL(RFile &aFile, TEZGZipHeader &aHeader) + { + TInt obligatoryData = sizeof(aHeader.iId1) + sizeof(aHeader.iId2) + sizeof(aHeader.iCompressionMethod) + + sizeof(aHeader.iFlags) + sizeof(aHeader.iTime) + sizeof(aHeader.iExtraFlags) + sizeof(aHeader.iOs); + + TPtrC8 des(&aHeader.iId1,obligatoryData); + User::LeaveIfError(aFile.Write(des)); + TBuf8<1> null(1); + null[0] = '\0'; + + if (aHeader.iFlags & (1 << EFExtra)) // then the extra bit is set + { + des.Set(REINTERPRET_CAST(TUint8 *,&aHeader.iXlen),sizeof(aHeader.iXlen)); + User::LeaveIfError(aFile.Write(des)); + + User::LeaveIfError(aFile.Write(*aHeader.iExtra)); + } + + if (aHeader.iFlags & (1 << EFName)) // then read in filename + { + User::LeaveIfError(aFile.Write(*aHeader.iFname)); + User::LeaveIfError(aFile.Write(null)); + } + + if (aHeader.iFlags & (1 << EFComment)) // then read in comment + { + User::LeaveIfError(aFile.Write(*aHeader.iComment)); + User::LeaveIfError(aFile.Write(null)); + } + + if (aHeader.iFlags & (1 << EFHcrc)) + { + des.Set(REINTERPRET_CAST(TUint8*,&aHeader.iCrc),sizeof(aHeader.iCrc)); + User::LeaveIfError(aFile.Write(des)); + } + } + +void EZGZipFile::ReadStringIntoDescriptorL(RFile &aFile, HBufC8 **aDes) + { + TInt i, err; + CArrayFixFlat *bytes = new (ELeave) CArrayFixFlat(16); + CleanupStack::PushL(bytes); + TBuf8<1> ch; + while ((err = aFile.Read(ch)) == KErrNone) + { + if (ch.Length() != 1) + User::Leave(KEZlibErrBadGZipHeader); + else if (ch[0] != '\0') + bytes->AppendL(*ch.Ptr()); + else + break; + } + + if (err != KErrNone) + User::Leave(KEZlibErrBadGZipHeader); + + *aDes = HBufC8::NewMaxL(bytes->Count()); + + for (i = 0; i < bytes->Count(); i++) + (*aDes)->Des()[i] = (*bytes)[i]; + + CleanupStack::PopAndDestroy(); // delete bytes + } + +/** +Read the zip trailer from the specified zip file into the TEZGZipTrailer object + +@param aFile the zip file to read from +@param aTrailer the target trailer object +@leave KEZlibErrBadGZipTrailer invalid zip trailer +@leave ... Any of the system wide error codes +*/ +EXPORT_C void EZGZipFile::ReadTrailerL(RFile &aFile, TEZGZipTrailer &aTrailer) + { + TPtr8 des(REINTERPRET_CAST(TUint8*,&aTrailer.iCrc32),0,sizeof(TEZGZipTrailer)); + + TInt err = aFile.Read(des); + if (err != KErrNone || des.Size() != sizeof(TEZGZipTrailer)) + User::Leave(KEZlibErrBadGZipTrailer); + } + +/** +Write the zip trailer to the specified file + +@param aFile the file to write to +@param aTrailer the trailer object to write to the file +@leave ... Any of the system wide error codes +*/ +EXPORT_C void EZGZipFile::WriteTrailerL(RFile &aFile, TEZGZipTrailer &aTrailer) + { + TPtrC8 des(REINTERPRET_CAST(TUint8*,&aTrailer.iCrc32),sizeof(TEZGZipTrailer)); + User::LeaveIfError(aFile.Write(des)); + } + +/** +Find the zip trailer within the specified file, and read it into the TEZGZipTrailer object + +@param aRfs file server session +@param aFname the file to read from +@param aTrailer the target trailer object +@leave KEZlibErrBadGZipHeader Invalid zip header +@leave ... Any of the system wide error codes +*/ +EXPORT_C void EZGZipFile::LocateAndReadTrailerL(RFs &aRfs, const TDesC &aFname, TEZGZipTrailer &aTrailer) + { + TInt fileSize; + + RFile file; + + User::LeaveIfError(file.Open(aRfs,aFname,EFileStream | EFileRead | EFileShareAny)); + CleanupClosePushL(file); + + TUint8 magic[2]; + TPtr8 des(magic,0,sizeof(TUint8) * 2); + User::LeaveIfError(file.Read(des)); + if (magic[0] != ID1 || magic[1] != ID2) + User::Leave(KEZlibErrBadGZipHeader); + + User::LeaveIfError(file.Size(fileSize)); + TInt sizePos = fileSize - (sizeof (TInt32) * 2); + User::LeaveIfError(file.Seek(ESeekStart,sizePos)); + + des.Set(REINTERPRET_CAST(TUint8 *,&aTrailer),0,sizeof(TInt32)*2); + + User::LeaveIfError(file.Read(des)); + + CleanupStack::PopAndDestroy(); + } + +/** +@deprecated Interface is deprecated because it is unsafe as it may leave. It is available for backward compatibility reasons only. +@see EZGZipFile::IsGzipFileL +*/ +EXPORT_C TBool EZGZipFile::IsGzipFile(RFs &aRfs, const TDesC &aFname) + { + TBool retBool = true; + TRAPD(errCode, retBool = IsGzipFileL(aRfs, aFname)); + if(errCode != KErrNone) + { + retBool = false; + } + return retBool; + } + +/** +Determine if the given file is a valid zip file + +@param aRfs file server session +@param aFname name of the file to check +@leave ... Any of the system wide error codes +@return ETrue if the file is valid zip file, EFalse otherwise +*/ +EXPORT_C TBool EZGZipFile::IsGzipFileL(RFs &aRfs, const TDesC &aFname) + { + TUint8 ids[2]; + RFile file; + + User::LeaveIfError(file.Open(aRfs,aFname,EFileStream | EFileRead | EFileShareAny)); + CleanupClosePushL(file); + + TPtr8 des(ids,0,sizeof(TUint8) * 2); + + User::LeaveIfError(file.Read(des)); + CleanupStack::PopAndDestroy(); + return (ids[0] == ID1 && ids[1] == ID2); + } + +//-------------------------------------------------------------------------------------------------------- + + +CEZFileToGzipBM::CEZFileToGzipBM(RFile &aInput, RFile &aOutput) : CEZFileBufferManager(aInput,aOutput) + { + iCrc = crc32_r(iCrc,NULL,0); + } + + +CEZFileToGzipBM* CEZFileToGzipBM::NewLC(RFile &aInput, RFile &aOutput, TInt aBufferSize) + { + CEZFileToGzipBM *bm = new (ELeave) CEZFileToGzipBM(aInput,aOutput); + CleanupStack::PushL(bm); + bm->ConstructL(aBufferSize); + return bm; + } + +CEZFileToGzipBM* CEZFileToGzipBM::NewL(RFile &aInput, RFile &aOutput, TInt aBufferSize) + { + CEZFileToGzipBM *bm = new (ELeave) CEZFileToGzipBM(aInput,aOutput); + CleanupStack::PushL(bm); + bm->ConstructL(aBufferSize); + CleanupStack::Pop(); + return bm; + } + +void CEZFileToGzipBM::NeedInputL(CEZZStream &aZStream) + { + CEZFileBufferManager::NeedInputL(aZStream); + iCrc = crc32_r(iCrc,iInputDescriptor.Ptr(),iInputDescriptor.Size()); + } + +void CEZFileToGzipBM::InitializeL(CEZZStream &aZStream) + { + CEZFileBufferManager::InitializeL(aZStream); + iCrc = crc32_r(iCrc,iInputDescriptor.Ptr(),iInputDescriptor.Size()); + } + +//-------------------------------------------------------------------------------------------------------- + + +CEZGzipToFileBM::CEZGzipToFileBM(RFile &aInput, RFile &aOutput) : CEZFileBufferManager(aInput,aOutput) + { + iCrc = crc32_r(iCrc,NULL,0); + } + +CEZGzipToFileBM* CEZGzipToFileBM::NewLC(RFile &aInput, RFile &aOutput, TInt aBufferSize) + { + CEZGzipToFileBM *bm = new (ELeave) CEZGzipToFileBM(aInput,aOutput); + CleanupStack::PushL(bm); + bm->ConstructL(aBufferSize); + return bm; + } + +CEZGzipToFileBM* CEZGzipToFileBM::NewL(RFile &aInput, RFile &aOutput, TInt aBufferSize) + { + CEZGzipToFileBM *bm = new (ELeave) CEZGzipToFileBM(aInput,aOutput); + CleanupStack::PushL(bm); + bm->ConstructL(aBufferSize); + CleanupStack::Pop(); + return bm; + } + +void CEZGzipToFileBM::NeedOutputL(CEZZStream &aZStream) + { + TPtrC8 od = aZStream.OutputDescriptor(); + iCrc = crc32_r(iCrc,od.Ptr(),od.Size()); + CEZFileBufferManager::NeedOutputL(aZStream); + } + +void CEZGzipToFileBM::FinalizeL(CEZZStream &aZStream) + { + TPtrC8 od = aZStream.OutputDescriptor(); + iCrc = crc32_r(iCrc,od.Ptr(),od.Size()); + CEZFileBufferManager::FinalizeL(aZStream); + } + + +//-------------------------------------------------------------------------------------------------------- +CEZGZipToFile::CEZGZipToFile() : iDecompressor(NULL), iBufferManager(NULL) + { + + } + +CEZGZipToFile::~CEZGZipToFile() + { + delete iDecompressor; + delete iBufferManager; + iGZipFile.Close(); + } + +/** +Creates a new CEZGZipToFile object and leaves it on the CleanupStack + +@param aRfs open file server session +@param aGzFileName name of the file to be de-compressed +@param aOutput the target file to hold the un-compressed data +@param aBufferSize required size of buffers +@return a pointer to the new CEZGZipToFile object, left on the CleanupStack +*/ +EXPORT_C CEZGZipToFile* CEZGZipToFile::NewLC(RFs &aRfs, const TDesC &aGzFileName, RFile &aOutput, TInt aBufferSize) + { + CEZGZipToFile* dec = new (ELeave) CEZGZipToFile; + CleanupStack::PushL(dec); + dec->ConstructL(aRfs,aGzFileName,aOutput,aBufferSize); + return dec; + } + +/** +Creates a new CEZGZipToFile object + +@param aRfs open file server session +@param aGzFileName name of the file to be de-compressed +@param aOutput the target file to hold the un-compressed data +@param aBufferSize required size of buffers +@return a pointer to the new CEZGZipToFile object +*/ +EXPORT_C CEZGZipToFile* CEZGZipToFile::NewL(RFs &aRfs, const TDesC &aGzFileName, RFile &aOutput, TInt aBufferSize) + { + CEZGZipToFile* dec = new (ELeave) CEZGZipToFile; + CleanupStack::PushL(dec); + dec->ConstructL(aRfs,aGzFileName,aOutput,aBufferSize); + CleanupStack::Pop(); + return dec; + } + +/** +Quits the current de-compression operation and restarts with the specified arguments + +@param aRfs open file server session +@param aGzFileName name of the file to be de-compressed +@param aOutput the target file to hold the un-compressed data +@param aBufferSize required size of buffers +@leave ... Any of the system wide error codes +*/ +EXPORT_C void CEZGZipToFile::ResetL(RFs &aRfs, const TDesC &aGzFileName, RFile &aOutput, TInt aBufferSize) + { + delete iBufferManager; + iBufferManager = NULL; + InitialiseBufManL(aRfs,aGzFileName,aOutput,aBufferSize); + iDecompressor->ResetL(*iBufferManager); + } + +/** +De-compresses the current zip file in stages. The function needs to called again until the de-compression +is finalised, in which case it will return EFalse - for example... + +@code +while ( decompressor->InflateL() ) + { + // No action required + } +@endcode + +@leave KEZlibErrBadGZipCrc Invalid CRC check +@leave ... Any of the system wide error codes +@return ETrue if the de-compression is not complete, and function must be called again +@return EFalse if the de-compression is finalised +*/ +EXPORT_C TBool CEZGZipToFile::InflateL() + { + TBool keepGoing = iDecompressor->InflateL(); + + if (!keepGoing) + { + if (iBufferManager->Crc() != iTrailer.iCrc32) + { + User::Leave(KEZlibErrBadGZipCrc); + + } + iGZipFile.Close(); + } + + return keepGoing; + } + +void CEZGZipToFile::InitialiseBufManL(RFs &aRfs, const TDesC &aGzFileName, RFile &aOutput, TInt aBufferSize) + { + EZGZipFile::LocateAndReadTrailerL(aRfs,aGzFileName,iTrailer); + User::LeaveIfError(iGZipFile.Open(aRfs,aGzFileName,EFileStream | EFileRead | EFileShareAny)); + EZGZipFile::ReadHeaderL(iGZipFile,iHeader); + iBufferManager = CEZGzipToFileBM::NewL(iGZipFile,aOutput,aBufferSize); + } + +void CEZGZipToFile::ConstructL(RFs &aRfs, const TDesC &aGzFileName, RFile &aOutput, TInt aBufferSize) + { + InitialiseBufManL(aRfs,aGzFileName,aOutput,aBufferSize); + + // this is a special zlib modification to stop it choking when it can't find the normal zlib stream header. + + iDecompressor = CEZDecompressor::NewL(*iBufferManager,-CEZDecompressor::EMaxWBits); + } + + +//-------------------------------------------------------------------------------------------------------- + + +CEZFileToGZip::CEZFileToGZip() : iCompressor(NULL), iBufferManager(NULL) + { + + } + +CEZFileToGZip::~CEZFileToGZip() + { + delete iCompressor; + delete iBufferManager; + iGZipFile.Close(); + } + +/** +Creates a new CEZFileToGZip object and leaves it on the CleanupStack + +@param aRfs open file server session +@param aGzFileName the name of the target zip file +@param aInput the file to compress +@param aBufferSize required size of buffers +@return a pointer to the new CEZFileToGZip object, left on the CleanupStack +*/ +EXPORT_C CEZFileToGZip* CEZFileToGZip::NewLC(RFs &aRfs, const TDesC &aGzFileName, RFile &aInput, TInt aBufferSize) + { + CEZFileToGZip* com = new (ELeave) CEZFileToGZip; + CleanupStack::PushL(com); + com->ConstructL(aRfs,aGzFileName,aInput,aBufferSize); + return com; + } + +/** +Creates a new CEZFileToGZip object and leaves it on the CleanupStack + +@param aRfs open file server session +@param aGzFileName the name of the target zip file +@param aInput the file to compress +@param aBufferSize required size of buffers +@return a pointer to the new CEZFileToGZip object, left on the CleanupStack +*/ +EXPORT_C CEZFileToGZip* CEZFileToGZip::NewL(RFs &aRfs, const TDesC &aGzFileName, RFile &aInput, TInt aBufferSize) + { + CEZFileToGZip* com = new (ELeave) CEZFileToGZip; + CleanupStack::PushL(com); + com->ConstructL(aRfs,aGzFileName,aInput,aBufferSize); + CleanupStack::Pop(); + return com; + } + +/** +Quits the current compression operation and restarts with the specified arguments + +@param aRfs open file server session +@param aGzFileName the name of the target zip file +@param aInput the file to compress +@param aBufferSize required size of buffers +@leave ... Any of the system wide error codes +*/ +EXPORT_C void CEZFileToGZip::ResetL(RFs &aRfs, const TDesC &aGzFileName, RFile &aInput, TInt aBufferSize) + { + delete iBufferManager; + iBufferManager = NULL; + InitialiseBufManL(aRfs,aGzFileName,aInput,aBufferSize); + iCompressor->ResetL(*iBufferManager); + } + +/** +Compresses the current file in stages. The function needs to called again until the compression +is finalised, in which case it will return EFalse - for example... + +@code +while ( compressor->DeflateL() ) + { + // No action required + } +@endcode + +@leave ... Any of the system wide error codes +@return ETrue if the compression is not complete, and function must be called again +@return EFalse if the compression is finalised +*/ +EXPORT_C TBool CEZFileToGZip::DeflateL() + { + TBool keepgoing = iCompressor->DeflateL(); + if (!keepgoing) + { + TEZGZipTrailer trailer(iBufferManager->Crc(), iUncompressedDataSize); + EZGZipFile::WriteTrailerL(iGZipFile, trailer); + iGZipFile.Close(); + } + + return keepgoing; + } + +void CEZFileToGZip::InitialiseBufManL(RFs &aRfs, const TDesC &aGzFileName, RFile &aInput, TInt aBufferSize) + { + User::LeaveIfError(aInput.Size(iUncompressedDataSize)); + TInt err; + + err = iGZipFile.Create(aRfs, aGzFileName,EFileStream | EFileWrite | EFileShareExclusive); + if (err == KErrAlreadyExists) + User::LeaveIfError(iGZipFile.Open(aRfs,aGzFileName,EFileStream | EFileWrite | EFileShareExclusive)); + else + User::LeaveIfError(err); + + EZGZipFile::WriteHeaderL(iGZipFile,iHeader); + iBufferManager = CEZFileToGzipBM::NewL(aInput,iGZipFile,aBufferSize); + } + +void CEZFileToGZip::ConstructL(RFs &aRfs, const TDesC &aGzFileName, RFile &aInput, TInt aBufferSize) + { + InitialiseBufManL(aRfs,aGzFileName,aInput,aBufferSize); + + // this is a special zlib modification to stop zlib writing out its normal zlib stream header. + + iCompressor = CEZCompressor::NewL(*iBufferManager,CEZCompressor::EDefaultCompression,-CEZCompressor::EMaxWBits); + }