diff -r 000000000000 -r ba25891c3a9e installationservices/swi/source/sisfile/siscontents.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/installationservices/swi/source/sisfile/siscontents.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,241 @@ +/* +* Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: +* Definition of the Swi::Sis::CContents +* +*/ + + +#include +#include +#include "sisinstallerrors.h" +#include "siscontents.h" +#include "siscrc.h" +#include "siscompressed.h" +#include "sisdata.h" +#include "sisblob.h" + +#include "sisdataprovider.h" +#include "compresseddataprovider.h" + +using namespace Swi; +using namespace Swi::Sis; + +// This line is commented so that SWI does not enforce CRC +// checking. If CRC checking was enforced existing SIS +// files created before DEF063815 was fixed would fail +// Uncommenting this line would cause a data compatibility break + +// #define SIS_CRC_CHECK_ENABLED + + +/*static*/ CContents* CContents::NewL(MSisDataProvider& aDataProvider, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour) + { + CContents* self = new(ELeave) CContents(aDataProvider); + CleanupStack::PushL(self); + self->ConstructL(aBytesRead, aTypeReadBehaviour); + CleanupStack::Pop(self); + return self; + } + +CContents::~CContents() + { + delete iCompressed; + delete iData; + delete iDataCrc; + delete iControllerCrc; + } + +CContents::CContents(MSisDataProvider& aDataProvider) : iDataProvider(aDataProvider) + { + } + +void CContents::ConstructL(TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour) + { + + CField::ConstructL(iDataProvider, EFieldTypeContents, aBytesRead, aTypeReadBehaviour); + + TFieldType fieldType; + CField::ReadEnumL(iDataProvider, fieldType, aBytesRead); + + if (fieldType == EFieldTypeControllerCRC) + { + // Controller Checksum present + iControllerCrc = CCrc::NewL(iDataProvider, aBytesRead, EAssumeType); + + CField::ReadEnumL(iDataProvider, fieldType, aBytesRead); + } + + if (fieldType == EFieldTypeDataCRC) + { + // Data Checksum present + iDataCrc = CCrc::NewL(iDataProvider, aBytesRead, EAssumeType); + + CField::ReadEnumL(iDataProvider, fieldType, aBytesRead); + } + + if (fieldType != EFieldTypeCompressed) + { + User::Leave(KErrSISUnexpectedFieldType); + } + + iCompressed = CCompressed::NewL(iDataProvider, aBytesRead, EAssumeType); + iData = CData::NewL(iDataProvider, aBytesRead); + +#ifdef SIS_CRC_CHECK_ENABLED + // This line is commented because existing SIS files had an + // incorrect CRC so enforcing the checksum now would be a data + // compatibility break. + // See DEF057005 + CheckCrcL(); +#endif + } + +EXPORT_C HBufC8* CContents::ReadControllerL() const + { + return iCompressed->ReadControllerDataL(); + } + +EXPORT_C void CContents::ReadDataL(RFile& aFile, TInt aFileIndex, TInt aDataUnit) + { + iData->ReadDataL(aFile, aFileIndex, aDataUnit); + } + +EXPORT_C void CContents::ReadDataL(RFile& aFile, TInt aFileIndex, TInt aDataUnit, TInt64 aLength) + { + iData->ReadDataL(aFile, aFileIndex, aDataUnit, aLength); + } + +void CContents::WriteStubFieldsL(RFile& aFile, MSisDataProvider& aDataProvider) + { + // create a buffer to receive the fields of the CSisContent for the stub + CBufFlat* buf = CBufFlat::NewL(250); + CleanupStack::PushL(buf); + + // create write stream + RBufWriteStream writeStream(*buf); + CleanupClosePushL(writeStream); + + // Skip over the SisContents header + CContents* self = new(ELeave) CContents(aDataProvider); + CleanupStack::PushL(self); + self->ReadHeaderL(); + TInt64 maxLength = self->Length() + self->PaddingSize(); + CleanupStack::PopAndDestroy(self); + + // Extract the relevant fields from the SISContents, write them + // to the buffer via the stream + ExtractSisStubFieldsL(writeStream, aDataProvider, maxLength); + CData::AppendStubDataFieldL(writeStream); + + CleanupStack::PopAndDestroy(&writeStream); + TPtr8 sisContentsBuf = buf->Ptr(0); + + TBuf8<3 * sizeof(TInt32)> header; + CField::CreateHeader(EFieldTypeContents, TInt64(sisContentsBuf.Length()), header); + // Write sis contents header + User::LeaveIfError(aFile.Write(header)); + // Write sis contents + User::LeaveIfError(aFile.Write(sisContentsBuf)); + // Write sis contents padding, + TInt lengthMod4 = (header.Length() + sisContentsBuf.Length()) % 4; + + TBuf8<1> padding; + padding.Append(0); + while(lengthMod4 > 0) + { + User::LeaveIfError(aFile.Write(padding)); + lengthMod4--; + } + + // finished + CleanupStack::PopAndDestroy(buf); + } + +void CContents::ExtractSisStubFieldsL(RWriteStream& aWriteStream, MSisDataProvider& aDataProvider, TInt64& aMaxLength) + { + TInt64 bytesRead = 0; + + // write the sis file to the stream but skip the Data and DataCRC fields + // This assumes all the other fields are correct, no checking is performed + TFieldType fieldType(EFieldTypeContents); + while(fieldType != EFieldTypeData) + { + // get field type from data provider + CField::ReadEnumL(aDataProvider, fieldType, bytesRead); + + if (fieldType == EFieldTypeDataCRC) + { + // read data checksum in order to skip over it + CCrc* crc = CCrc::NewL(aDataProvider, bytesRead, EAssumeType); + delete crc; + crc = NULL; + } + else if (fieldType == EFieldTypeData) + { + // read data field in order to skip over it + // could be many megabytes so we don't want to create + // it as a blob + CData* data = CData::NewL(aDataProvider, bytesRead, EAssumeType); + delete data; + data = NULL; + } + else + { + // load the field as a blob, we don't care whats inside + CBlob* blob = CBlob::NewLC(aDataProvider, bytesRead, EAssumeType); + + // Write the field to the output stream + // Cant do this inside CSisBlob because it's TCB in SisController.mmp + // and the streaming classes are not TCB + + // Create a header for the fieldType with a given length + TBuf8<3 * sizeof(TInt32)> header; + CField::CreateHeader(fieldType, TInt64(blob->Length()), header); + aWriteStream.WriteL(header); + aWriteStream.WriteL(blob->Data()); + for(TInt i = 0; i < blob->PaddingSize(); i++) + { + // write out zero padding at the end of the SisField + aWriteStream.WriteInt8L(0); + } + CleanupStack::PopAndDestroy(blob); + } + if(bytesRead > aMaxLength) + { + // we have read past the end of the SisContents field + User::Leave(KErrCorrupt); + } + } + } + +void CContents::ReadHeaderL() + { + // This just skips over the header without actually reading any of the data + TInt64 bytesRead =0; + CField::ConstructL(iDataProvider, EFieldTypeContents, bytesRead, EReadType); + } + +EXPORT_C void CContents::CheckCrcL() + { + if(iControllerCrc && iControllerCrc->Checksum() != iCompressed->Crc()) + { + User::Leave(KErrCorrupt); + } + + if(iDataCrc && iDataCrc->Checksum() != iData->Crc()) + { + User::Leave(KErrCorrupt); + } + }