sl@0: // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Decompression buffer manager for GZip data sl@0: // sl@0: sl@0: #include sl@0: #include "gzipbufmgr.h" sl@0: //----------------------------------------------------------------------------- sl@0: sl@0: // NOTE: This code was taken from the DeflateFilter (s60/DeflateFilter/) sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // StreamBufMgr::NewL sl@0: // Two-phase constructor sl@0: // ---------------------------------------------------------------------------- sl@0: // sl@0: GZipBufMgr* GZipBufMgr::NewL(TPtrC8 in) sl@0: { sl@0: GZipBufMgr* self = new (ELeave)GZipBufMgr(in); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: }//lint !e1746 const reference is not necessary here, because TPtrC8 takes only 4-bytes sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // GZipBufMgr::GZipBufMgr sl@0: // Constructor sl@0: // ---------------------------------------------------------------------------- sl@0: // sl@0: GZipBufMgr::GZipBufMgr(TPtrC8 in) sl@0: : iInput(in), iOutputDes(0, 0), iOutput(0), sl@0: iNeedInput(EFalse), iNeedOutput(EFalse), sl@0: iFinalized(EFalse), iOffset(0), iID1(31), iID2(139) sl@0: { sl@0: } //lint !e1746 sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // GZipBufMgr::ConstructL sl@0: // Initialize the output buffer sl@0: // ---------------------------------------------------------------------------- sl@0: // sl@0: void GZipBufMgr::ConstructL() sl@0: { sl@0: // Output buffer and descriptor sl@0: iOutput = HBufC8::NewMaxL(1<<15); sl@0: iOutputDes.Set(iOutput->Des()); sl@0: sl@0: // Setup the GZip header, this sets iOffset to after the header and start sl@0: // of the data sl@0: TEZGZipHeader header; sl@0: ReadGZipHeaderL(header); sl@0: sl@0: // Move pass the header and set the buffer to the data sl@0: TPtrC8 data(REINTERPRET_CAST(const TUint8*, iInput.Ptr() + iOffset), iInput.Length() - iOffset); sl@0: sl@0: // Setup the data buffer sl@0: SetGZipBuffer(data); sl@0: sl@0: } sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // GZipBufMgr::~GZipBufMgr sl@0: // Destructor sl@0: // ---------------------------------------------------------------------------- sl@0: // sl@0: GZipBufMgr::~GZipBufMgr() sl@0: { sl@0: delete iOutput; sl@0: iOutput = NULL; sl@0: } sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // GZipBufMgr::InitializeL sl@0: // Overriden function from MEZBufferManager sl@0: // ---------------------------------------------------------------------------- sl@0: // sl@0: void GZipBufMgr::InitializeL(CEZZStream& aZStream) sl@0: { sl@0: // read more sl@0: aZStream.SetInput(iInput); sl@0: iOutputDes.SetLength(0); sl@0: aZStream.SetOutput(iOutputDes); sl@0: iNeedInput = EFalse; sl@0: iNeedOutput = EFalse; sl@0: } sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // GZipBufMgr::NeedInputL sl@0: // Overriden function from MEZBufferManager sl@0: // ---------------------------------------------------------------------------- sl@0: // sl@0: void GZipBufMgr::NeedInputL(CEZZStream& /*aZStream*/) sl@0: { sl@0: //aZStream.SetInput(iInput); sl@0: iNeedInput = ETrue; sl@0: } sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // GZipBufMgr::NeedOutputL sl@0: // Overriden function from MEZBufferManager sl@0: // ---------------------------------------------------------------------------- sl@0: // sl@0: void GZipBufMgr::NeedOutputL(CEZZStream& /*aZStream*/) sl@0: { sl@0: //aZStream.SetOutput(iOutputDes); sl@0: iNeedOutput = ETrue; sl@0: } sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // GZipBufMgr::NeedOutputL sl@0: // Overriden function from MEZBufferManager sl@0: // ---------------------------------------------------------------------------- sl@0: // sl@0: void GZipBufMgr::FinalizeL(CEZZStream& /*aZStream*/) sl@0: { sl@0: // do nothing now, should check the checksum value here sl@0: // read the checksum value from the last chunk sl@0: //const TInt32* checksum = REINTERPRET_CAST(const TInt32*, iInput.Ptr() + (iInput.Length() - sizeof(TInt32)*2)); sl@0: iFinalized = ETrue; sl@0: } sl@0: sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // Public methods sl@0: // ---------------------------------------------------------------------------- sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // GZipBufMgr::ReadGZipHeaderL sl@0: // Read the header of Gzip-ed stream in Gzip format, RFC1952. sl@0: // Sets the iOffset pointer, which marks the end of the header and start of the sl@0: // data. This method needs to be called (or iOffset set) before calling sl@0: // SetGZipBuffer method. sl@0: // ---------------------------------------------------------------------------- sl@0: // sl@0: void GZipBufMgr::ReadGZipHeaderL(TEZGZipHeader& aHeader) sl@0: { sl@0: // construct a stream for reading sl@0: RMemReadStream memBuf; sl@0: memBuf.Open(iInput.Ptr(), iInput.Length()); sl@0: sl@0: TInt obligatoryData = sizeof(aHeader.iId1) + sizeof(aHeader.iId2) + sl@0: sizeof(aHeader.iCompressionMethod) + sl@0: sizeof(aHeader.iFlags) + sizeof(aHeader.iTime) + sl@0: sizeof(aHeader.iExtraFlags) + sizeof(aHeader.iOs); sl@0: sl@0: // copy the header data sl@0: TPtr8 des(&aHeader.iId1, 0, obligatoryData); sl@0: TRAPD(error, memBuf.ReadL(des)); sl@0: sl@0: if (error == KErrEof) sl@0: { sl@0: User::Leave(EZGZipFile::EBadGZipHeader); sl@0: } sl@0: sl@0: if (des.Size() < obligatoryData) sl@0: { sl@0: // should consider the situation when not enough data has arrived sl@0: User::Leave(EZGZipFile::EBadGZipHeader); sl@0: } sl@0: sl@0: if (aHeader.iId1 != iID1 || aHeader.iId2 != iID2) sl@0: { sl@0: User::Leave(EZGZipFile::EBadGZipHeader); sl@0: } sl@0: sl@0: if (aHeader.iFlags & (1 << EZGZipFile::EFExtra)) sl@0: { sl@0: // The extra bit is set sl@0: des.Set(REINTERPRET_CAST(TUint8 *, &aHeader.iXlen), 0, sizeof(aHeader.iXlen)); sl@0: memBuf.ReadL(des); sl@0: if (des.Size() != sizeof(aHeader.iXlen) || aHeader.iXlen < 0) //lint !e737 sign/unsigned doesn't realy matter here sl@0: { sl@0: User::Leave(EZGZipFile::EBadGZipHeader); sl@0: } sl@0: sl@0: aHeader.iExtra = HBufC8::NewMaxL(aHeader.iXlen); sl@0: TPtr8 des1 = aHeader.iExtra->Des(); sl@0: memBuf.ReadL(des1); sl@0: sl@0: if (des1.Size() != aHeader.iXlen) sl@0: { sl@0: User::Leave(EZGZipFile::EBadGZipHeader); sl@0: } sl@0: } sl@0: sl@0: if (aHeader.iFlags & (1 << EZGZipFile::EFName)) sl@0: { sl@0: // Read in filename sl@0: ReadStringIntoDescriptorL(memBuf, &aHeader.iFname); sl@0: } sl@0: sl@0: if (aHeader.iFlags & (1 << EZGZipFile::EFComment)) sl@0: { sl@0: // Read in comment sl@0: ReadStringIntoDescriptorL(memBuf, &aHeader.iComment); sl@0: } sl@0: sl@0: if (aHeader.iFlags & (1 << EZGZipFile::EFHcrc)) sl@0: { sl@0: des.Set(REINTERPRET_CAST(TUint8*, &aHeader.iCrc), 0, sizeof(aHeader.iCrc)); sl@0: memBuf.ReadL(des); sl@0: if (des.Size() != sizeof(aHeader.iCrc)) //lint !e737 unsigned/signed doesn't matter sl@0: { sl@0: User::Leave(EZGZipFile::EBadGZipHeader); sl@0: } sl@0: } sl@0: sl@0: // Set iOffset to mark end of header and beginning of data sl@0: iOffset = memBuf.Source()->TellL(MStreamBuf::ERead).Offset(); sl@0: sl@0: memBuf.Close(); sl@0: } sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // GZipBufMgr::ReadStringIntoDescriptorL sl@0: // Read null-terminated strings into the buffer sl@0: // ---------------------------------------------------------------------------- sl@0: // sl@0: void GZipBufMgr::ReadStringIntoDescriptorL(RMemReadStream& aMem, HBufC8 **aDes) const sl@0: { sl@0: TInt i; sl@0: CArrayFixFlat *bytes = new (ELeave) CArrayFixFlat(16); sl@0: CleanupStack::PushL(bytes); sl@0: TUint8 ch; sl@0: sl@0: while ((ch = aMem.ReadUint8L()) != '\0') sl@0: { sl@0: bytes->AppendL(ch); sl@0: } sl@0: sl@0: *aDes = HBufC8::NewMaxL(bytes->Count()); sl@0: TPtr8 desPtr = (*aDes)->Des(); //lint because error #111 - separate desPtr used sl@0: sl@0: for (i = 0; i < bytes->Count(); i++) sl@0: { sl@0: desPtr[i] = (*bytes)[i]; //lint !e1058 force conversion here sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(); // delete bytes sl@0: } sl@0: sl@0: // ---------------------------------------------------------------------------- sl@0: // GZipBufMgr::SetBuffer sl@0: // Set the input buffer sl@0: // ---------------------------------------------------------------------------- sl@0: // sl@0: void GZipBufMgr::SetGZipBuffer(TPtrC8 data) sl@0: { sl@0: iInput.Set(data); sl@0: }//lint !e1746