diff -r 84a16765cd86 -r 98b66e4fb0be secureswitools/swisistools/source/rscparser/barscimpl.cpp --- /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 +#include +#include +#include +#include +#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<=0); + + Ptr8* decompressedResourceData= + GetDecompressedResourceDataL( + resourceIndex, + iFlagsAndNumberOfResources & static_cast(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) + { + 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(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(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(startOfDecompressedUnicode) & 0x01) + { + TUint8 padChar = 0xab; + memcpy(startOfDecompressedUnicode,&padChar,1); + ++startOfDecompressedUnicode; + aBuffer->UpdateLength(1); + } + + const TInt maximumOutputLength= ( + iSizeOfLargestResourceWhenCompletelyUncompressed - (aBuffer->GetLength()))/2; + + TMemoryUnicodeSink decompressedUnicode(reinterpret_cast(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(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(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; + + }