--- /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.
+ */
+ {
+ }
+
+