--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/secureswitools/swisistools/source/rscparser/barscimpl.cpp Fri Apr 16 15:05:20 2010 +0300
@@ -0,0 +1,539 @@
+// Copyright (c) 2009 - 2010 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:
+//
+/**
+* @file BaRscImpl.cpp
+*
+* @internalComponent
+* @released
+*/
+#include <iostream>
+#include <fstream>
+#include <cassert>
+#include <sys/stat.h>
+#include <sstream>
+#include "barsc2.h"
+#include "barscimpl.h"
+#include "ucmp.h"
+
+
+RResourceFileImpl::TExtra::TExtra():
+ iBitArrayOfResourcesContainingCompressedUnicode(NULL),
+ iFileOffset(0),
+ iFileSize(0)
+ {
+ }
+
+
+RResourceFileImpl::TExtra::~TExtra()
+ {
+ delete iBitArrayOfResourcesContainingCompressedUnicode;
+ }
+
+
+TInt32 RResourceFileImpl::TExtra::ContainsCompressedUnicode(const TInt& aRscIdx) const
+ {
+ assert(aRscIdx>=0);
+
+ if (iBitArrayOfResourcesContainingCompressedUnicode==NULL)
+ {
+ return EFalse;
+ }
+
+ TInt index = aRscIdx/8;
+
+ return (iBitArrayOfResourcesContainingCompressedUnicode)[index]&(1<<(aRscIdx%8));
+ }
+
+
+RResourceFileImpl::RResourceFileImpl() :
+ iResourceContents(NULL),
+ iSizeOfLargestResourceWhenCompletelyUncompressed(0),
+ iIndex(0),
+ iOffset(0),
+ iExtra(NULL),
+ iFlagsAndNumberOfResources(0)
+ {
+ // Fixed class size - because of the BC reasons.
+ // RResourceFileImpl size must be the same as CResourceFile size.
+ enum
+ {
+ KRscFileImplSize = 24
+ };
+ assert(sizeof(RResourceFileImpl) == KRscFileImplSize);
+
+ //Fixed "iOffset" position - because of the BC reasons.
+ assert(offsetof(RResourceFileImpl, iOffset)==12);
+ }
+
+
+RResourceFileImpl::~RResourceFileImpl()
+{
+ if(iResourceContents)
+ {
+ if (iResourceContents->is_open())
+ {
+ iResourceContents->close();
+ }
+ delete iResourceContents;
+ }
+ iSizeOfLargestResourceWhenCompletelyUncompressed=0;
+ delete iIndex;
+ iIndex=NULL;
+ if (iExtra)
+ {
+ delete iExtra;
+ iExtra=NULL;
+ }
+
+ iFlagsAndNumberOfResources=0;
+ iOffset=0;
+}
+
+
+void RResourceFileImpl::OpenL(
+ const std::string& aName,
+ TUint32 aFileOffset,
+ TInt aFileSize)
+{
+ iResourceContents= new std::ifstream(aName.c_str(), std::ios::in|std::ios::binary);
+
+ if(!iResourceContents->good())
+ {
+ std::string errMsg= "Unable to open RSC file. " + aName;
+ if (iResourceContents->is_open())
+ iResourceContents->close();
+ if(iResourceContents)
+ delete iResourceContents;
+ throw CResourceFileException(errMsg);
+ }
+
+ iExtra=new TExtra();
+ iExtra->iFileOffset = aFileOffset;
+
+ TInt fileSize = 0;
+ if (aFileSize)
+ {
+ fileSize = aFileSize;
+ assert(fileSize > TInt(aFileOffset));
+ }
+ else
+ {
+ // Get the resource file size
+ struct stat resourceFileStats;
+
+ if (stat(aName.c_str(),&resourceFileStats) == 0)
+ {
+ // The size of the file in bytes is in
+ // resourceFileStats.st_size
+ fileSize=resourceFileStats.st_size;
+ assert(fileSize > 0);
+ }
+ else
+ {
+ if (iResourceContents->is_open())
+ iResourceContents->close();
+ std::string errMsg="Invalid RSC File";
+ throw CResourceFileException(errMsg);
+ }
+ }
+
+ iExtra->iFileSize = fileSize;
+
+ // Verify the header of the RSC and get the resource index
+ ReadHeaderAndResourceIndexL();
+}
+
+
+Ptr8* RResourceFileImpl::GetDecompressedResourceDataL(
+ const TInt& aResourceIndex,
+ const TUint32& aFlags)
+ {
+ const TInt positionOfResourceData= iIndex[aResourceIndex];
+ const TInt numberOfBytes= iIndex[aResourceIndex+1]-positionOfResourceData;
+
+ assert(numberOfBytes >= 0);
+
+ Ptr8* outputResourceData=new Ptr8(numberOfBytes);
+ ReadL(aFlags, positionOfResourceData, outputResourceData->GetPtr(), numberOfBytes);
+ outputResourceData->UpdateLength(numberOfBytes);
+
+ return outputResourceData;
+ }
+
+
+Ptr8* RResourceFileImpl::AllocReadL(const TInt& aResourceId)
+ {
+
+ // Check if the resource id is present in the RSC file
+ if (!OwnsResourceId(aResourceId))
+ {
+ std::ostringstream errDispStream;
+
+ errDispStream<<"Resource ID:";
+ errDispStream<<aResourceId;
+ errDispStream<<" is not present in the RSC file";
+
+ throw CResourceFileException(errDispStream.str());
+ }
+
+ //"-1" because the first resource has ID 0x*****001 (not 0x*****000)
+ TInt resourceIndex= (aResourceId & EIdBits)-1;
+ assert(resourceIndex>=0);
+
+ Ptr8* decompressedResourceData=
+ GetDecompressedResourceDataL(
+ resourceIndex,
+ iFlagsAndNumberOfResources & static_cast<TUint32>(EAllFlags));
+
+ // Return the resource data if its not unicode compressed.
+ if (!iExtra->ContainsCompressedUnicode(resourceIndex))
+ {
+ return decompressedResourceData;
+ }
+
+ // Get the decompressed unicode data.
+ Ptr8* finalResourceData= DecompressUnicodeL(decompressedResourceData);
+
+ delete decompressedResourceData;
+ return finalResourceData;
+ }
+
+
+Ptr8* RResourceFileImpl::DecompressUnicodeL(const Ptr8* aInputResourceData) const
+ {
+ const TInt numberOfBytesInInput= aInputResourceData->GetLength();
+ assert(iSizeOfLargestResourceWhenCompletelyUncompressed>0);
+
+ Ptr8* outputResourceData= new Ptr8(iSizeOfLargestResourceWhenCompletelyUncompressed);
+
+ const TUint8* input= aInputResourceData->GetPtr();
+ TInt index=0;
+
+ TBool decompressRun=ETrue;
+ while (1)
+ {
+ assert(index<numberOfBytesInInput);
+
+ TInt runLength=input[index];
+
+ // The run-length occupies a single byte if it is less than 128,
+ // otherwise it occupies two bytes (in little-endian byte order),
+ // with the most significant bit of the first byte set to non-zero
+ //to indicate that the run-length occupies two bytes.
+ if (runLength & 0x80)
+ {
+ ++index;
+ if (index>=numberOfBytesInInput)
+ {
+ std::string errMsg="Invalid Rsc File";
+ throw CResourceFileException(errMsg);
+ }
+ runLength &= ~0x80;
+ runLength <<= 8;
+ runLength |= input[index];
+ }
+ ++index;
+ if (runLength>0)
+ {
+ if (decompressRun)
+ {
+ AppendDecompressedUnicodeL(
+ outputResourceData,
+ const_cast<unsigned char *>(input+index),
+ runLength);
+ }
+ else
+ {
+ assert(
+ (outputResourceData->GetLength() + runLength) <=
+ iSizeOfLargestResourceWhenCompletelyUncompressed);
+
+ memcpy((char*)(outputResourceData->GetPtr()+outputResourceData->GetLength()),(char*)(input+index),runLength);
+ outputResourceData->UpdateLength(runLength);
+ }
+ index+=runLength;
+ }
+ if (index>numberOfBytesInInput)
+ {
+ std::string errMsg="Invalid Rsc File";
+ throw CResourceFileException(errMsg);
+ }
+ if (index>=numberOfBytesInInput)
+ {
+ break;
+ }
+ decompressRun=!decompressRun;
+ }
+ return outputResourceData;
+ }
+
+
+
+/** @internalComponent
+@return The first resource record.
+@panic Some BAFL panic codes, if the file is corrupted.
+@leave KErrCorrupt The file is corrupted.
+Some other error codes are possible too.
+The method could panic or leave depending on the state of
+iAssertObj member of RResourceFileImpl::TExtra class. */
+RResourceFileImpl::SSigRecord RResourceFileImpl::FirstRecordL() const
+ {
+ // Added to support reading of rel 6.x resource files.
+ // rel 6.x files do not have signatures!
+ Ptr8* const firstResource=AllocReadL(1);
+
+ // Basic check to test if the signature is of the correct size.
+ if (firstResource->GetLength()!= sizeof(SSigRecord))
+ {
+ std::string errMsg="Invalid RSS Signature";
+ throw CResourceFileException(errMsg);
+ }
+ SSigRecord sigRecord = *reinterpret_cast<const SSigRecord*>(firstResource->GetPtr());
+ delete firstResource;
+ return sigRecord;
+}
+
+/** Initialises the offset value from the first resource.
+
+The function tests to catch cases where the first resource is not an RSS_SIGNATURE.
+It assumes that the first resource in the file consists of
+two 32-bit integers. The first integer contains the version number and
+the second is a self-referencing link whose value is the offset for
+the resources in the file, plus 1.This function must be called before
+calling Offset(), AllocReadL(), AllocReadLC() or ReadL().
+
+@see Offset()
+@see AllocReadL()
+@see AllocReadLC()
+@see ReadL()
+@internalComponent
+@pre OpenL() is called.
+@panic Some BAFL panic codes, if the file is corrupted.
+@leave KErrCorrupt The file is corrupted.
+Some other error codes are possible too.
+The method could panic or leave depending on the state of
+iAssertObj member of RResourceFileImpl::TExtra class. */
+void RResourceFileImpl::ConfirmSignatureL()
+{
+ // Added to support reading of rel 6.x resource files.
+ SSigRecord firstRecord=FirstRecordL();
+
+ // If the resource offset does not correspond to the first resource
+ // this is not a resource signature.
+ if ((firstRecord.offset & EIdBits) != 1)
+ {
+ std::string errMsg="Failed : Invalid RSS Signature";
+ throw CResourceFileException(errMsg);
+ }
+ iOffset=(firstRecord.offset & EOffsetBits);
+}
+
+void RResourceFileImpl::AppendDecompressedUnicodeL(
+ Ptr8* aBuffer,
+ const TUint8* aCompressedUnicode,
+ const TInt& aLengthOfCompressedUnicode) const
+ {
+
+ if (aLengthOfCompressedUnicode>0)
+ {
+ TUint8* startOfDecompressedUnicode= aBuffer->GetPtr() + aBuffer->GetLength();
+
+ if (reinterpret_cast<TUint32>(startOfDecompressedUnicode) & 0x01)
+ {
+ TUint8 padChar = 0xab;
+ memcpy(startOfDecompressedUnicode,&padChar,1);
+ ++startOfDecompressedUnicode;
+ aBuffer->UpdateLength(1);
+ }
+
+ const TInt maximumOutputLength= (
+ iSizeOfLargestResourceWhenCompletelyUncompressed - (aBuffer->GetLength()))/2;
+
+ TMemoryUnicodeSink decompressedUnicode(reinterpret_cast<TUint16*>(startOfDecompressedUnicode));
+
+ TInt lengthOfDecompressedUnicode;
+ TInt numberOfInputBytesConsumed;
+ TUnicodeExpander unicodeExpander;
+
+ unicodeExpander.ExpandL(decompressedUnicode,
+ aCompressedUnicode,
+ maximumOutputLength,
+ aLengthOfCompressedUnicode,
+ &lengthOfDecompressedUnicode,
+ &numberOfInputBytesConsumed);
+ TInt temp;
+ unicodeExpander.FlushL(decompressedUnicode,maximumOutputLength,temp);
+ lengthOfDecompressedUnicode+=temp;
+ aBuffer->UpdateLength(lengthOfDecompressedUnicode*2);
+
+ assert(numberOfInputBytesConsumed == aLengthOfCompressedUnicode);
+ }
+ }
+
+
+TBool RResourceFileImpl::OwnsResourceId(const TInt& aResourceId) const
+ {
+ // Checks whether Rsc file owns the resource:
+ // does so if offset is 0, or matches that given,
+ // and id is in index.
+ const TInt offset=(aResourceId & EOffsetBits);
+// if ((offset!=0) && (offset!=iOffset))
+// {
+// return EFalse;
+// }
+
+ const TInt resourceIndex=(aResourceId & EIdBits)-1;
+ TInt numberOfResources=(iFlagsAndNumberOfResources & ~EAllFlags);
+
+ return (resourceIndex >= 0) && (resourceIndex < numberOfResources);
+ }
+
+
+void RResourceFileImpl::ReadL(
+ const TUint32& aFlags,
+ TInt aPos,
+ TUint8* aData,
+ const TInt& aLength)
+ {
+ aPos += iExtra->iFileOffset;
+
+ assert(aPos >= iExtra->iFileOffset);
+ assert(aLength >= 0);
+ assert((aPos + aLength) <= (iExtra->iFileOffset + iExtra->iFileSize));
+
+ // Seek to the offset specified by "aPos"
+ iResourceContents->seekg(aPos, std::ios_base::beg);
+ iResourceContents->read((char*)aData, aLength);
+ }
+
+
+void RResourceFileImpl::ReadL(TInt aPos, TUint8* aData, const TInt& aLength)
+ {
+ ReadL(iFlagsAndNumberOfResources & static_cast<TUint32>(EAllFlags),aPos,aData,aLength);
+ }
+
+
+TInt RResourceFileImpl::LittleEndianTwoByteInteger(
+ TUint8* aBuffer,
+ const TInt& aIndexOfFirstByte) const
+ {
+ return aBuffer[aIndexOfFirstByte] | (aBuffer[aIndexOfFirstByte+1]<<8);
+ }
+
+
+void RResourceFileImpl::ReadHeaderAndResourceIndexL()
+ {
+
+ // Unicode compressed RSC file will have 19 bytes header.
+ const TUint8 kHeaderSize= 19;
+ TUint8 header[kHeaderSize];
+
+ sTUid uid;
+
+ // Verify the header of the RSC file.
+ if(iExtra->iFileSize >= kHeaderSize)
+ {
+
+ // Get the RSC header
+ ReadL(0,0,header,kHeaderSize);
+ // Get the first UID
+ memcpy((TUint8*)&uid.iUid1,header,4);
+
+ // First uid of unicode compressed RSC is "0x101f4a6b"
+ TUint32 unicodeCompressedFirstUid = 0x101f4a6b;
+
+ if (uid.iUid1 == unicodeCompressedFirstUid)
+ {
+ iFlagsAndNumberOfResources |= EFlagPotentiallyContainsCompressedUnicode;
+ iSizeOfLargestResourceWhenCompletelyUncompressed= LittleEndianTwoByteInteger(header,16+1);
+ }
+ else
+ {
+ if (iResourceContents->is_open())
+ iResourceContents->close();
+ std::string errMsg="Failed : Unsupported RSC file type";
+ throw CResourceFileException(errMsg);
+ }
+ }
+
+ TInt numberOfResources= 0;
+ TUint8* bitArrayOfResourcesContainingCompressedUnicode= NULL;
+
+ if (iFlagsAndNumberOfResources & EFlagPotentiallyContainsCompressedUnicode)
+ {
+ // Cache the resource-index (in iIndex) to minimize disk access.
+ const TInt KMaximumNumberOfBytesCached= 256;
+ TUint8 cache[KMaximumNumberOfBytesCached];
+ const TInt numberOfBytesCached=
+ ((iExtra->iFileSize>KMaximumNumberOfBytesCached) ? KMaximumNumberOfBytesCached : iExtra->iFileSize);
+
+ ReadL(iExtra->iFileSize-numberOfBytesCached, cache, numberOfBytesCached);
+
+ const TInt positionOfStartOfIndex=
+ ((cache[numberOfBytesCached-1]<<8) | cache[numberOfBytesCached-2]);
+ const TInt numberOfBytesOfIndex=iExtra->iFileSize-positionOfStartOfIndex;
+
+ assert(numberOfBytesOfIndex%2==0);
+ assert(numberOfBytesOfIndex>=0);
+
+ const TInt numberOfBytesOfIndexStillToRetrieve = numberOfBytesOfIndex-numberOfBytesCached;
+
+ if (numberOfBytesOfIndexStillToRetrieve<=0)
+ {
+ iIndex= new TUint16[numberOfBytesOfIndex/2];
+ memcpy(iIndex, cache+(numberOfBytesCached-numberOfBytesOfIndex), numberOfBytesOfIndex);
+ }
+ else
+ {
+ TUint16* index= new TUint16(numberOfBytesOfIndex/2);
+ ReadL(positionOfStartOfIndex, reinterpret_cast<TUint8*>(index), numberOfBytesOfIndexStillToRetrieve);
+ memcpy((index+numberOfBytesOfIndexStillToRetrieve),cache,numberOfBytesCached);
+
+ iIndex=index;
+ }
+
+ //"-1" because the last thing in the index (which is in fact the last thing in the
+ //file itself) is the position of the start of the index which is therefore not
+ //pointing to a resource
+ numberOfResources=(numberOfBytesOfIndex/2) - 1;
+
+ if (numberOfResources <= 0)
+ {
+ if (iResourceContents->is_open())
+ iResourceContents->close();
+ std::string errMsg="Failed : Invalid RSC file.";
+ throw CResourceFileException(errMsg);
+ }
+
+ const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
+ bitArrayOfResourcesContainingCompressedUnicode=
+ new TUint8(lengthOfBitArrayInBytes);
+
+ //"16+1+2": 16 bytes of checked-UID + 1 byte of flags (these flags are for a
+ //dictionary-compressing program's use rather than directly for Bafl's use,
+ //so we ignore them) + 2 bytes containing the size of the largest resource when
+ //uncompressed
+ ReadL(16+1+2,bitArrayOfResourcesContainingCompressedUnicode,lengthOfBitArrayInBytes);
+
+ }
+
+ assert((numberOfResources & EAllFlags)==0);
+ assert((iFlagsAndNumberOfResources & ~EAllFlags)==0);
+
+ iFlagsAndNumberOfResources |= (numberOfResources & ~EAllFlags);
+ iExtra->iUid = uid;
+ iExtra->iBitArrayOfResourcesContainingCompressedUnicode = bitArrayOfResourcesContainingCompressedUnicode;
+
+ }