First public contribution.
1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // Decompression buffer manager for GZip data
18 #include "gzipbufmgr.h"
19 //-----------------------------------------------------------------------------
21 // NOTE: This code was taken from the DeflateFilter (s60/DeflateFilter/)
23 // ----------------------------------------------------------------------------
25 // Two-phase constructor
26 // ----------------------------------------------------------------------------
28 GZipBufMgr* GZipBufMgr::NewL(TPtrC8 in)
30 GZipBufMgr* self = new (ELeave)GZipBufMgr(in);
31 CleanupStack::PushL(self);
35 }//lint !e1746 const reference is not necessary here, because TPtrC8 takes only 4-bytes
37 // ----------------------------------------------------------------------------
38 // GZipBufMgr::GZipBufMgr
40 // ----------------------------------------------------------------------------
42 GZipBufMgr::GZipBufMgr(TPtrC8 in)
43 : iInput(in), iOutputDes(0, 0), iOutput(0),
44 iNeedInput(EFalse), iNeedOutput(EFalse),
45 iFinalized(EFalse), iOffset(0), iID1(31), iID2(139)
49 // ----------------------------------------------------------------------------
50 // GZipBufMgr::ConstructL
51 // Initialize the output buffer
52 // ----------------------------------------------------------------------------
54 void GZipBufMgr::ConstructL()
56 // Output buffer and descriptor
57 iOutput = HBufC8::NewMaxL(1<<15);
58 iOutputDes.Set(iOutput->Des());
60 // Setup the GZip header, this sets iOffset to after the header and start
63 ReadGZipHeaderL(header);
65 // Move pass the header and set the buffer to the data
66 TPtrC8 data(REINTERPRET_CAST(const TUint8*, iInput.Ptr() + iOffset), iInput.Length() - iOffset);
68 // Setup the data buffer
73 // ----------------------------------------------------------------------------
74 // GZipBufMgr::~GZipBufMgr
76 // ----------------------------------------------------------------------------
78 GZipBufMgr::~GZipBufMgr()
84 // ----------------------------------------------------------------------------
85 // GZipBufMgr::InitializeL
86 // Overriden function from MEZBufferManager
87 // ----------------------------------------------------------------------------
89 void GZipBufMgr::InitializeL(CEZZStream& aZStream)
92 aZStream.SetInput(iInput);
93 iOutputDes.SetLength(0);
94 aZStream.SetOutput(iOutputDes);
99 // ----------------------------------------------------------------------------
100 // GZipBufMgr::NeedInputL
101 // Overriden function from MEZBufferManager
102 // ----------------------------------------------------------------------------
104 void GZipBufMgr::NeedInputL(CEZZStream& /*aZStream*/)
106 //aZStream.SetInput(iInput);
110 // ----------------------------------------------------------------------------
111 // GZipBufMgr::NeedOutputL
112 // Overriden function from MEZBufferManager
113 // ----------------------------------------------------------------------------
115 void GZipBufMgr::NeedOutputL(CEZZStream& /*aZStream*/)
117 //aZStream.SetOutput(iOutputDes);
121 // ----------------------------------------------------------------------------
122 // GZipBufMgr::NeedOutputL
123 // Overriden function from MEZBufferManager
124 // ----------------------------------------------------------------------------
126 void GZipBufMgr::FinalizeL(CEZZStream& /*aZStream*/)
128 // do nothing now, should check the checksum value here
129 // read the checksum value from the last chunk
130 //const TInt32* checksum = REINTERPRET_CAST(const TInt32*, iInput.Ptr() + (iInput.Length() - sizeof(TInt32)*2));
135 // ----------------------------------------------------------------------------
137 // ----------------------------------------------------------------------------
139 // ----------------------------------------------------------------------------
140 // GZipBufMgr::ReadGZipHeaderL
141 // Read the header of Gzip-ed stream in Gzip format, RFC1952.
142 // Sets the iOffset pointer, which marks the end of the header and start of the
143 // data. This method needs to be called (or iOffset set) before calling
144 // SetGZipBuffer method.
145 // ----------------------------------------------------------------------------
147 void GZipBufMgr::ReadGZipHeaderL(TEZGZipHeader& aHeader)
149 // construct a stream for reading
150 RMemReadStream memBuf;
151 memBuf.Open(iInput.Ptr(), iInput.Length());
153 TInt obligatoryData = sizeof(aHeader.iId1) + sizeof(aHeader.iId2) +
154 sizeof(aHeader.iCompressionMethod) +
155 sizeof(aHeader.iFlags) + sizeof(aHeader.iTime) +
156 sizeof(aHeader.iExtraFlags) + sizeof(aHeader.iOs);
158 // copy the header data
159 TPtr8 des(&aHeader.iId1, 0, obligatoryData);
160 TRAPD(error, memBuf.ReadL(des));
162 if (error == KErrEof)
164 User::Leave(EZGZipFile::EBadGZipHeader);
167 if (des.Size() < obligatoryData)
169 // should consider the situation when not enough data has arrived
170 User::Leave(EZGZipFile::EBadGZipHeader);
173 if (aHeader.iId1 != iID1 || aHeader.iId2 != iID2)
175 User::Leave(EZGZipFile::EBadGZipHeader);
178 if (aHeader.iFlags & (1 << EZGZipFile::EFExtra))
180 // The extra bit is set
181 des.Set(REINTERPRET_CAST(TUint8 *, &aHeader.iXlen), 0, sizeof(aHeader.iXlen));
183 if (des.Size() != sizeof(aHeader.iXlen) || aHeader.iXlen < 0) //lint !e737 sign/unsigned doesn't realy matter here
185 User::Leave(EZGZipFile::EBadGZipHeader);
188 aHeader.iExtra = HBufC8::NewMaxL(aHeader.iXlen);
189 TPtr8 des1 = aHeader.iExtra->Des();
192 if (des1.Size() != aHeader.iXlen)
194 User::Leave(EZGZipFile::EBadGZipHeader);
198 if (aHeader.iFlags & (1 << EZGZipFile::EFName))
201 ReadStringIntoDescriptorL(memBuf, &aHeader.iFname);
204 if (aHeader.iFlags & (1 << EZGZipFile::EFComment))
207 ReadStringIntoDescriptorL(memBuf, &aHeader.iComment);
210 if (aHeader.iFlags & (1 << EZGZipFile::EFHcrc))
212 des.Set(REINTERPRET_CAST(TUint8*, &aHeader.iCrc), 0, sizeof(aHeader.iCrc));
214 if (des.Size() != sizeof(aHeader.iCrc)) //lint !e737 unsigned/signed doesn't matter
216 User::Leave(EZGZipFile::EBadGZipHeader);
220 // Set iOffset to mark end of header and beginning of data
221 iOffset = memBuf.Source()->TellL(MStreamBuf::ERead).Offset();
226 // ----------------------------------------------------------------------------
227 // GZipBufMgr::ReadStringIntoDescriptorL
228 // Read null-terminated strings into the buffer
229 // ----------------------------------------------------------------------------
231 void GZipBufMgr::ReadStringIntoDescriptorL(RMemReadStream& aMem, HBufC8 **aDes) const
234 CArrayFixFlat<TUint8> *bytes = new (ELeave) CArrayFixFlat<TUint8>(16);
235 CleanupStack::PushL(bytes);
238 while ((ch = aMem.ReadUint8L()) != '\0')
243 *aDes = HBufC8::NewMaxL(bytes->Count());
244 TPtr8 desPtr = (*aDes)->Des(); //lint because error #111 - separate desPtr used
246 for (i = 0; i < bytes->Count(); i++)
248 desPtr[i] = (*bytes)[i]; //lint !e1058 force conversion here
251 CleanupStack::PopAndDestroy(); // delete bytes
254 // ----------------------------------------------------------------------------
255 // GZipBufMgr::SetBuffer
256 // Set the input buffer
257 // ----------------------------------------------------------------------------
259 void GZipBufMgr::SetGZipBuffer(TPtrC8 data)