diff -r 000000000000 -r 72b543305e3a messagingappbase/obexmtms/obexmtm/obexutil/source/obexMtmUtil.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingappbase/obexmtms/obexmtm/obexutil/source/obexMtmUtil.cpp Thu Dec 17 08:44:11 2009 +0200 @@ -0,0 +1,404 @@ +// Copyright (c) 2001-2009 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: +// $Workfile: obexMtmUtil.cpp $ +// $Author: Stevep $ +// $Revision: 7 $ +// $Date: 8/02/02 10:11 $ +// +// + +//class include +#include "obexMtmUtil.h" +#include "obexheaderlist.h" + +#ifdef _DEBUG +#define DEBPRINT(Z) User::InfoPrint(Z); +#else +#define DEBPRINT(Z) +#endif + +// Uncomment this to test data compatibility with builds older than PHAR-5SDJG9. +// (if uncommented, messages are externalised the same way it was done before the PHAR-5SDJG9 changes) +//#define TEST_INC042468 + +static const TInt KObexArrayGranularity = 4; + +// +// +// Class for externalising a set of filenames to the same message entry store. Rolls back if not explicitely committed. +// + +// Static functions that do the whole process in one go: +EXPORT_C void CObexMtmFileNameExternaliser::ExternaliseAndCommit1FileNameL(CMsvEntry* aEntry, const TDesC16* aFileName) +/** +* Static function to write one and only one filename to the message store, then finalise and commit it. This function +* should be called ONCE ONLY. To externalise more than one filename, instantiate this class and use ExternaliseFileNameL() +* followed by CommitStoreL(). +* @param aEntry the entry whose store is to be written to +* @param aFileName The filename to write to the store +* @leave KErrXXX system-wide error codes +*/ + { + CMsvStore* messageStore = aEntry->EditStoreL(); + CleanupStack::PushL(messageStore); + + RMsvWriteStream messageWriteStream; + CleanupClosePushL(messageWriteStream); + + messageWriteStream.AssignL(*messageStore, KObexFileNameStreamUid); + + // write the identifier so we know we are internalizing a stream later +#ifndef TEST_INC042468 + messageWriteStream.WriteInt32L(KObexFileNameStreamFileNameUid); +#endif + messageWriteStream.WriteInt32L(aFileName->Length()); + messageWriteStream.WriteL(*aFileName); + +#ifndef TEST_INC042468 + messageWriteStream.WriteInt32L(KObexFileNameStreamFileNameUid); +#endif + messageWriteStream.WriteInt32L(0); //Mark the end of the filename list + + messageWriteStream.CommitL(); + + CleanupStack::PopAndDestroy(); // trigger a call to Close(); on messageWriteStream as well as removing from the stack + + messageStore->CommitL(); + CleanupStack::PopAndDestroy(messageStore); + } + + +EXPORT_C void CObexMtmFileNameExternaliser::Internalise1FileNameL(CMsvEntry* aEntry, TDes16* aFileName) +/** +* Static function to read in one filename from the store. +* +* @param aEntry entry to read the filename from +* @param aFileName Descriptor to recieve the new filename. Any existing data will be overwritten. MUST be long enough to contain the name. +* @leave KErrXXX system wide error codes. +*/ + { + CMsvStore* messageStore = aEntry->ReadStoreL(); + CleanupStack::PushL(messageStore); + + RMsvReadStream messageReadStream; + messageReadStream.OpenLC(*messageStore, KObexFileNameStreamUid); // If data hasn't been stored then this will provide the error. + + // verify that we're reading the right type of data from the stream + + + // INC042468: "AV21: Data Compatibility break caused by "PHAR-5SDJG9"" + // To regain compatibility, if the first integer read from the stream + // is not the expected "KObexFileNameStreamFileNameUid", it is assumed it + // is the filename length. An extra check is made that it is a valid filename + // length (<= KMaxFileName). + // "KObexFileNameStreamFileNameUid" has also been modified so that there cannot + // be a file with a name length equal to KObexFileNameStreamFileNameUid (in which + // case we would have been in trouble ;-) ) + + TInt32 firstInt = messageReadStream.ReadInt32L(); + TInt32 fileNameLength = 0; + if (firstInt == KObexFileNameStreamFileNameUid) + { + // next will be the filename length + fileNameLength = messageReadStream.ReadInt32L(); + } + else if (firstInt <= KMaxFileName) + { + // let's assume the first integer in the stream was the filename length + // (this happens if the message was saved by an old build (previous to PHAR-5SDJG9) + fileNameLength = firstInt; + } + else + { + // neither the expected "KObexFileNameStreamFileNameUid" nor a valid filename length + User::Leave(KErrArgument); + } + + messageReadStream.ReadL(*aFileName, fileNameLength); + + CleanupStack::PopAndDestroy(2, messageStore); // messageStore, messageReadStream (calls Close() first) + } + +// +// +// Class for storing multiple Filenames within a CMsvEntry store. +// +EXPORT_C CObexMtmFileNameExternaliser* CObexMtmFileNameExternaliser::NewL(CMsvSession* aSession, TMsvId aId) +/** +* Canonical NewL factory function. +* +* @param aSession A messaging server session +* @param aId TMsvId of the entry to externalise/internalise to/from. This association is fixed for the lifetime of this instance of the class. +* @return a newly constucted CObexMtmFileNameExternaliser +* @leave KErrXXX system wide error codes +*/ + { + CObexMtmFileNameExternaliser* self = new(ELeave) CObexMtmFileNameExternaliser(aSession); + CleanupStack::PushL(self); + self->InitialiseStoreL(aId); + CleanupStack::Pop(); // self + return self; + } +CObexMtmFileNameExternaliser::CObexMtmFileNameExternaliser(CMsvSession* aSession) : iSession(aSession) +/** +* Constructor +* +* @param aSession A messaging server session +*/ + {} +CObexMtmFileNameExternaliser::~CObexMtmFileNameExternaliser() +/** +* Destructor. Will revert the stream to its original state if the store hasn't been comitted. +*/ + { + if(! iHaveCommitted) + { + iMessageWriteStream.Close(); + iMessageStore->Revert(); // Don't commit. Should have been called explicitly using CommitStoreL(). + } + delete iMessageStore; + delete iEntry; + } + +void CObexMtmFileNameExternaliser::InitialiseStoreL(TMsvId aId) +/** + * Initialises the store of the given entry, ready for reading or writing. + * + * @param aId The TMsvId of the entry whose store should be initialised. + * @leave KErrXXX system wide error codes. + */ + { + iEntry = iSession->GetEntryL(aId); + + iMessageStore = iEntry->EditStoreL(); + + iMessageWriteStream.AssignL(*iMessageStore, KObexFileNameStreamUid); + iHaveCommitted = EFalse; + } + +EXPORT_C void CObexMtmFileNameExternaliser::ExternaliseFileNameL(const TDesC16* aFileName) +/** + * Externalises a single filename to the associated entry's message store. + * + * @param aFileName the filename to externalise. + * @leave KErrXXX system-wide error codes. + */ + { +#ifndef TEST_INC042468 + iMessageWriteStream.WriteInt32L(KObexFileNameStreamFileNameUid); +#endif + iMessageWriteStream.WriteInt32L(aFileName->Length()); + iMessageWriteStream.WriteL(*aFileName); + } + +EXPORT_C void CObexMtmFileNameExternaliser::ExternaliseFileNameAndHeadersL(const TDesC16* aFileName, const CObexHeaderList* aHeaderList) +/** + * Externalises a single filename to the associated entry's message store. + * + * @param aFileName the filename to externalise. + * @leave KErrXXX system-wide error codes. + */ + { + ExternaliseFileNameL(aFileName); +#ifndef TEST_INC042468 + iMessageWriteStream.WriteInt32L(KObexFileNameStreamHeaderListUid); + aHeaderList->ExternalizeL(iMessageWriteStream); +#endif + } + +EXPORT_C void CObexMtmFileNameExternaliser::CommitStoreL() +/** + * Finalises and commits the store. This function MUST be called once all of the filenames have been externalised, and not + * before. If it is not called, any changes will be lost and the store will revert to its former state. + * + * @leave KErrXXX system wide error codes. + */ + { +#ifndef TEST_INC042468 + iMessageWriteStream.WriteInt32L(KObexFileNameStreamFileNameUid); +#endif + iMessageWriteStream.WriteInt32L(0); // length == 0 --> no more names in store. + iMessageWriteStream.CommitL(); + iHaveCommitted = ETrue; + iMessageWriteStream.Close(); + + iMessageStore->CommitL(); + + delete iMessageStore; + iMessageStore=NULL; + } + +EXPORT_C RObexMtmFileNameWithHeadersArray* CObexMtmFileNameExternaliser::InternaliseFileNamesLC(CMsvStore& aMessageStore) +/** + * Static function to get the filenames stored within the message entry. The returned array is pushed onto the cleanup + * stack. + * + * @param aMessageStore Store from which the names are to be read + * @return Array of filenames, pushed onto the cleanup stack. + * @leave System wide error codes + */ + { + RObexMtmFileNameWithHeadersArray* fileNameArray = new(ELeave) RObexMtmFileNameWithHeadersArray(KObexArrayGranularity); + CleanupStack::PushL(fileNameArray); + + RMsvReadStream newMessageReadStream; + newMessageReadStream.OpenL(aMessageStore, KObexFileNameStreamUid); // If data hasn't been stored then this will provide the error. + CleanupClosePushL(newMessageReadStream); + + + + + // INC042468: "AV21: Data Compatibility break caused by "PHAR-5SDJG9"" + // To regain compatibility, if the first integer read from the stream + // is not the expected "KObexFileNameStreamFileNameUid", it is assumed it + // is the filename length. An extra check is made that it is a valid filename + // length (<= KMaxFileName). + // "KObexFileNameStreamFileNameUid" has also been modified so that there cannot + // be a file with a name length equal to KObexFileNameStreamFileNameUid (in which + // case we would have been in trouble ;-) ) + + TInt32 firstInt = newMessageReadStream.ReadInt32L(); + + TInt32 fileNameLength = 0; + if (firstInt == KObexFileNameStreamFileNameUid) + { + // next will be the filename length + fileNameLength = newMessageReadStream.ReadInt32L(); + } + else if (firstInt <= KMaxFileName) + { + // let's assume the first integer in the stream was the filename length + // (this happens if the message was saved by an old build (previous to PHAR-5SDJG9) + fileNameLength = firstInt; + } + else + { + // neither the expected "KObexFileNameStreamFileNameUid" nor a valid filename length + User::Leave(KErrArgument); + } + + TInt32 elementTypeID; + TBool lengthAlreadyReadFlag; + TFileName thisName; + CObexMtmFileNameWithHeaders *thisPackage; + while(fileNameLength) + { + + thisPackage = CObexMtmFileNameWithHeaders::NewL(); + CleanupStack::PushL(thisPackage); + + // read 'bodylength' bytes into a descriptor + newMessageReadStream.ReadL(thisName, fileNameLength); + + // store this descriptor in the container + thisPackage->iFileName = new(ELeave) TFileName(thisName); + CleanupStack::PushL(thisPackage->iFileName); + + lengthAlreadyReadFlag = EFalse; + // get the type of the next element + elementTypeID = newMessageReadStream.ReadInt32L(); + + switch(elementTypeID) + { + case KObexFileNameStreamHeaderListUid: + // this filename has some headers associated with it + + // read these headers in... + thisPackage->iHeaderList = CObexHeaderList::NewLC(); + thisPackage->iHeaderList->InternalizeL(newMessageReadStream); + + // get the type of the next element + elementTypeID = newMessageReadStream.ReadInt32L(); + + // fall through to add this container to the array + case KObexFileNameStreamFileNameUid: + // this filename has no headers associated with it, this is OK. + fileNameArray->Append(thisPackage); + break; + + default: + // builds previous to PHAR-5SDJG9: + // no stream Uids are externalised and elementTypeID contains already the filename length + if (elementTypeID <= KMaxFileName) + { + fileNameArray->Append(thisPackage); + fileNameLength = elementTypeID; + lengthAlreadyReadFlag = ETrue; + } + else + { + User::Leave(KErrArgument); + } + // if this value is not one of the two element types, then we can't read the stream + + break; + } + + // this member will be zero if there were no headers on this filename + if(thisPackage->iHeaderList) + { + CleanupStack::Pop(thisPackage->iHeaderList); + } + + // safely added filename and headers to list, pop the allocations off the cleanup stack. + CleanupStack::Pop(thisPackage->iFileName); + + CleanupStack::Pop(thisPackage); + + // get the length of the next element + if (!lengthAlreadyReadFlag) + { + TRAPD (err, fileNameLength = newMessageReadStream.ReadInt32L();) // Length == 0 --> end of array + } + } + + newMessageReadStream.Close(); + CleanupStack::PopAndDestroy(); //newMessageReadStream + + return fileNameArray; + } + +// +// CObexMtmFileNameWithHeaders +// + +EXPORT_C CObexMtmFileNameWithHeaders* CObexMtmFileNameWithHeaders::NewL() + /** + * Canonical NewL factory function. + * + * @return an empty CObexMtmFileNameWithHeaders class + * @leave KErrXXX system wide error codes + */ + { + CObexMtmFileNameWithHeaders *self = new(ELeave)CObexMtmFileNameWithHeaders; + return self; + } + +CObexMtmFileNameWithHeaders::~CObexMtmFileNameWithHeaders() +/** + * Destructor. Will destroy the data pointed to by the 2 member pointers. + */ + { + delete iFileName; + delete iHeaderList; + } + +CObexMtmFileNameWithHeaders::CObexMtmFileNameWithHeaders() + /** + * Constructor. + */ + { + } + +