diff -r 9f5ae1728557 -r db3f5fa34ec7 messagingfw/wappushfw/PushMsgEntry/src/Pushentry.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingfw/wappushfw/PushMsgEntry/src/Pushentry.cpp Wed Nov 03 22:41:46 2010 +0530 @@ -0,0 +1,606 @@ +// Copyright (c) 2000-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: +// + +#include +#include +#include +#include +#include +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "PushEntryPanic.h" +#endif//SYMBIAN_ENABLE_SPLIT_HEADERS + +GLDEF_C TPtrC16 LimitStringSize(const TPtrC16& aString, TInt aMaxSize) + { + if (aString.Length() < aMaxSize) + return aString; + else + return aString.Left(aMaxSize); + } + +GLDEF_C TPtrC8 LimitStringSize(const TPtrC8& aString, TInt aMaxSize) + { + if (aString.Length() < aMaxSize) + return aString; + else + return aString.Left(aMaxSize); + } + + +/** +Destructor. +*/ +EXPORT_C CPushMsgEntryBase::~CPushMsgEntryBase() + { + delete iMsgDetails; + delete iMsgDescription; + delete iHeader; + delete iFrom; + delete iAppIDString; + } + + +/** +Stores the Push message in the message store. + +It creates an entry in the message server as a child of the specified parent, +sets the relevant index entry fields, and calls ExternalizeL() to save additional +data to a message store for the entry. + +If the operation fails the entry is deleted, along with the data in its message +store. + +@param aSession +Message server session. + +@param aParent +ID of the parent for the new entry. It is the caller's responsibility to ensure +that the parent ID is correct. + +@return +ID of the new message server entry. +*/ +EXPORT_C TMsvId CPushMsgEntryBase::SaveL(CMsvSession& aSession, TMsvId aParent) + { + __ASSERT_ALWAYS(aParent != KMsvNullIndexEntryId, + User::Panic(KPushPanicMoniker, EPushEntryNullMsgId)); + // Ensure that the entry parameters are correctly set. + iEntry.iServiceId = KMsvLocalServiceIndexEntryId; //Saving under the local service + iEntry.iMtm = KUidMtmWapPush; + iEntry.iType = KUidMsvMessageEntry; + iEntry.SetInPreparation(ETrue); + iEntry.SetReadOnly(EFalse); + iEntry.SetUnread(ETrue); + SetPushMsgType(); + + // Create this outside of the TRAP - otherwise the leave would get trapped and + // We'd tried to delete an entry that doesn't exist. + CMsvEntry* msvEntry = aSession.GetEntryL(aParent); //Get parent entry + CleanupStack::PushL(msvEntry); + + TUid mtmUid = msvEntry->Entry().iMtm; + __ASSERT_ALWAYS((mtmUid == KUidMtmWapPush)||(mtmUid == KUidMsvLocalServiceMtm), + User::Panic(KPushPanicMoniker,EPushEntryWrongMTMtype)); + msvEntry->CreateL(iEntry); + + // CMsvSession::CleanupEntryPushL() can fail, leaving an partially complete + // entry in the store. Use a TRAP and RemoveEntry to do the same job. + TRAPD(createErr, DoSaveL(*msvEntry)); + + if (createErr != KErrNone) + { + aSession.RemoveEntry(iEntry.Id()); + User::Leave(createErr); + } + + iHasServerEntry = ETrue; + + // CMsvEntry is gone, so ensure iDescription & iDetails point + // to persistent copies of the strings, if they exist else set to null + if (iMsgDescription) + iEntry.iDescription.Set(*iMsgDescription); + else + iEntry.iDescription.Set(KNullDesC); + if (iMsgDetails) + iEntry.iDetails.Set(*iMsgDetails); + else + iEntry.iDescription.Set(KNullDesC); + + iEntry.SetInPreparation(EFalse); + UpdateL(aSession); + + CleanupStack::PopAndDestroy(); //msvEntry + return iEntry.Id(); + } + + +/** +Helper function that does the actual saving of various data members to the message store +attached to the entry. It is done this way so that if any function call leaves, the +error can be trapped in SaveL, and the new entry deleted before SaveL leaves. + +@param aMsvEntry Parent of the new entry. + +@internalComponent +*/ +void CPushMsgEntryBase::DoSaveL(CMsvEntry& aMsvEntry) + { + // synchronous create in the Push Msg folder under Local Service + aMsvEntry.SetEntryL(iEntry.Id()); + __ASSERT_ALWAYS(iEntry.iBioType == PushMsgType(), + User::Panic(KPushPanicMoniker,EPushEntryWrongMsgtype)); + + CMsvStore* store = aMsvEntry.EditStoreL(); + CleanupStack::PushL(store); + + RMsvWriteStream out; + TUid streamId; + streamId.iUid = PushMsgType(); + out.AssignLC(*store, streamId); + ExternalizeL(out); //call this polymorphic function to save data + out.CommitL(); + out.Close(); // make sure we close the file + store->CommitL(); + CleanupStack::PopAndDestroy(2); //out, store + } + + +/** +Updates an existing message server entry. + +The functionality is similiar to SaveL(), except no new entry is created. +Before calling this function, the existing entry must be loaded into the object +using RetrieveL(). + +@param aSession +Message server session. +*/ +EXPORT_C void CPushMsgEntryBase::UpdateL(CMsvSession& aSession) + { + if (iHasServerEntry ==EFalse ) + User::Leave(KWPushNoMsgIndexEntry); + CMsvEntry* msvEntry = aSession.GetEntryL(iEntry.Id()); + CleanupStack::PushL(msvEntry); + + //Can only overwrite a pushmessage of the same type + // Mtm & Push Type Uid must be correct + __ASSERT_ALWAYS( msvEntry->Entry().iMtm == KUidMtmWapPush, + User::Panic(KPushPanicMoniker, EPushEntryWrongMTMtype)); + __ASSERT_ALWAYS( msvEntry->Entry().iBioType == PushMsgType(), + User::Panic(KPushPanicMoniker, EPushEntryWrongMsgtype)); + + // Remove existing contents of stream and store new data + CMsvStore* store; + store = msvEntry->EditStoreL(); + CleanupStack::PushL(store); + + RMsvWriteStream out; + TUid streamId; + streamId.iUid = PushMsgType(); + out.AssignLC(*store, streamId); + ExternalizeL(out); + + // Ensure the defaults are set correctly. Assume others set by user + iEntry.iMtm = KUidMtmWapPush; + SetPushMsgType(); + msvEntry->ChangeL(iEntry); + + // Done the changes to the TMsvEntry, now commit changes to the stream & store + out.CommitL(); + out.Close(); // make sure we close the file + store->CommitL(); + CleanupStack::PopAndDestroy(3); //out, store, msventry + iHasServerEntry = ETrue; + + // CMsvEntry is gone, so ensure iDescription & iDetails point to persistent + // copies of the strings, if they exist else point them to Null Descriptors + if (iMsgDescription) + iEntry.iDescription.Set(*iMsgDescription); + else + iEntry.iDescription.Set(KNullDesC); + + if (iMsgDetails) + iEntry.iDetails.Set(*iMsgDetails); + else + iEntry.iDescription.Set(KNullDesC); + } + + +/** +Retrieves Push message from the message store into the object. + +The data held in TMsvEntry::iDetails and TMsvEntry::iDescription is copied +to member descriptors to ensure that it persists after the local CMsvEntry +variable is destroyed. + +@param aSession +Message server session. + +@param aMsgId +ID of the entry to load. + +@leave KErrNotFound +The push message cannot be located in the Message Store. +@leave CMsvSession::GetEntryL +@leave TDesC::AllocL +@leave CMsvEntry::ReadStoreL +@leave CPushMsgEntryBase::RestoreL +*/ +EXPORT_C void CPushMsgEntryBase::RetrieveL(CMsvSession& aSession, TMsvId aMsgId) + { + __ASSERT_ALWAYS(aMsgId!= KMsvNullIndexEntryId, + User::Panic(KPushPanicMoniker, EPushEntryNullMsgId)); + + // Switch to our entry & then get the associated message store. + CMsvEntry* msvEntry = aSession.GetEntryL(aMsgId); + CleanupStack::PushL(msvEntry); + + // Set our TMsvEntry member variable + iEntry = msvEntry->Entry(); + + // Make iDetails and iDescription persist as long as this object exists. + // Delete any existing buffers + delete iMsgDetails; + iMsgDetails = NULL; + iMsgDetails = iEntry.iDetails.AllocL(); + iEntry.iDetails.Set(*iMsgDetails); + + delete iMsgDescription; + iMsgDescription =NULL; + iMsgDescription = iEntry.iDescription.AllocL(); + iEntry.iDescription.Set(*iMsgDescription); + + CMsvStore* store = msvEntry->ReadStoreL(); + CleanupStack::PushL(store); + + //Load in the additional data from the message store + RestoreL(*store); + + CleanupStack::PopAndDestroy(2); //store, msvEntry + // Obviously has a server entry + iHasServerEntry = ETrue; + } + + +/** +Restores data from the associated message store. + +The data is loaded by a call to the derived class InternalizeL(). + +@param aStore +Store to load from. +*/ +EXPORT_C void CPushMsgEntryBase::RestoreL(CMsvStore& aStore) + { + RMsvReadStream in; + TUid streamId; + streamId.iUid = PushMsgType(); + in.OpenLC(aStore, streamId); + InternalizeL(in); + CleanupStack::PopAndDestroy(); //in + } + + +/** +Sets directly the TMsvEntry for the message. + +This resets the context of the Push Entry, and the caller should ensure that all +data member variables of the class are up to date. + +@param aEntry +Message server index entry. +*/ +EXPORT_C void CPushMsgEntryBase::SetEntry(const TMsvEntry& aEntry) + { + iEntry = aEntry; + iEntry.iMtm = KUidMtmWapPush; + } + + +/** +Sets the Status field for the Push Message Entry. + +The bits of the TMsvEntry::iMtmData1 member holding the Status are reset. + +@param aStatusFlags +Status value for the message entry. +*/ +EXPORT_C void CPushMsgEntryBase::SetStatus(TInt aStatusFlags) + { + // Get everything except the Status bits from iMtmData1 + TInt everythingButStatus = iEntry.MtmData1() & KPushMaskEverythingButStatus; + // Remove any extraneous bits from the new status & then set the status + action values + iEntry.SetMtmData1( everythingButStatus + (aStatusFlags & KPushMaskOnlyStatus) ); + } + + +/** +Gets the raw WAP Push message header. + +@return +Message header, or KNullDesC8 if it has not been set with SetHeaderL(). +*/ +EXPORT_C const TDesC8& CPushMsgEntryBase::Header() const + { + if (iHeader) // check the header exists + return *iHeader; + else + return KNullDesC8; + } + + +/** +Sets a buffer that specifies the WAP Push message header. + +Any existing buffer is deleted. + +@param aHeader +Message header +*/ +EXPORT_C void CPushMsgEntryBase::SetHeaderL(const TDesC8& aHeader) + { + HBufC8* temp = aHeader.AllocL(); + delete iHeader; + iHeader = temp; + } + + +/** +Gets a buffer holding the From field. + +@return +From field, or KNullDesC8 if it has not been set with SetFromL(). +*/ +EXPORT_C const TDesC8& CPushMsgEntryBase::From() const + { + if (iFrom) + return *iFrom; + else + return KNullDesC8; + } + + +/** +Sets a buffer that specifies the From field. + +Any existing buffer is deleted. + +@param aFrom +From field +*/ +EXPORT_C void CPushMsgEntryBase::SetFromL(const TDesC8& aFrom) + { + HBufC8* temp = aFrom.AllocL(); + delete iFrom; + iFrom = temp; + } + + +/** +Constructor. + +This initialises TMsvEntry::iDate. +*/ +EXPORT_C CPushMsgEntryBase::CPushMsgEntryBase() + { + iEntry.iDate.UniversalTime(); + } + + +/** +Externalises the object to a message store stream. + +Derived classes should override this function if required, and call the base +class function. + +@param aStream +Message store stream. +*/ +EXPORT_C void CPushMsgEntryBase::ExternalizeL(RMsvWriteStream& aStream) + { + aStream<< LimitStringSize(Header(), KLongestStringAllowed); + aStream<< LimitStringSize(From(), KLongestStringAllowed); + + if (iAppIDString) + aStream<< *iAppIDString; + else + aStream<< KNullDesC; + + aStream.WriteInt32L(iAppIdInt); + } + + +/** +Internalises the object from a message store stream. + +Derived classes should override this function if required, and call the base +class function. + +@param aStream +Message store stream. +*/ +EXPORT_C void CPushMsgEntryBase::InternalizeL(RMsvReadStream& aStream) + { + delete iHeader; + iHeader = NULL; + iHeader = HBufC8::NewL(aStream, KLongestStringAllowed); + + delete iFrom; + iFrom = NULL; + iFrom = HBufC8::NewL(aStream, KLongestStringAllowed); + + delete iAppIDString; + iAppIDString = NULL; + iAppIDString = HBufC8::NewL(aStream, KLongestStringAllowed); + + iAppIdInt = aStream.ReadUint32L(); + } + + +/** +Constructor, with the message AppID in string form. + +It calls SetPushMsgType() to ensure that TMsvEntry::iBioType is set to the +correct Push Message Type UID. + +@param aAppURI +AppID in string form. +*/ +EXPORT_C void CPushMsgEntryBase::ConstructL(const TPtrC8& aAppURI) + { + ConstructL(); + iAppIDString = aAppURI.AllocL(); + } + + +/** +Constructor, with message AppID in numeric form. + +It calls SetPushMsgType() to ensure that TMsvEntry::iBioType is set to the +correct Push Message Type UID. + +@param aAppID +AppID in numeric form. +*/ +EXPORT_C void CPushMsgEntryBase::ConstructL(const TInt& aAppID) + { + ConstructL(); + iAppIdInt=aAppID; + } + +/** +Constructor. + +It calls SetPushMsgType() to ensure that TMsvEntry::iBioType is set to the +correct Push Message Type Uid. +*/ +EXPORT_C void CPushMsgEntryBase::ConstructL() + { + SetStatus(EPushMsgStatusValid); + SetPushMsgType(); //Make sure this is set, need it for both StoreL & RestoreL + } + + +/** +Gets the message description field. + +@return +Message description field, or KNullDesC if not set. +*/ +EXPORT_C const TDesC& CPushMsgEntryBase::MsgDescription() const + { + if (iMsgDescription) + return *iMsgDescription; + else + return KNullDesC; + } + + +/** +Sets the message description field. + +@param aDescription +Message description field value to copy. +*/ +EXPORT_C void CPushMsgEntryBase::SetMsgDescriptionL(const TDesC& aDescription) + { + HBufC* tempBuf = aDescription.AllocL(); + + delete iMsgDescription; + iMsgDescription = tempBuf; + iEntry.iDescription.Set(*iMsgDescription); + } + + +/** +Gets the message details field. + +@return +Message details field, or KNullDesC if not set. +*/ +EXPORT_C const TDesC& CPushMsgEntryBase::MsgDetails() const + { + if (iMsgDetails) + return *iMsgDetails; + else + return KNullDesC; + } + + +/** +Sets the message details field. + +@param aDetails +Message details field value to copy. +*/ +EXPORT_C void CPushMsgEntryBase::SetMsgDetailsL(const TDesC& aDetails) + { + HBufC* tempBuf = aDetails.AllocL(); + + delete iMsgDetails; + iMsgDetails = tempBuf; + iEntry.iDetails.Set(*iMsgDetails); + } + + +/** +Gets the date/time that the push message was received. + +@return +Date/time that the push message was received. +*/ +EXPORT_C const TTime& CPushMsgEntryBase::ReceivedDate() const + { + return iEntry.iDate; + } + + +/** +Gets the AppID of the message. + +The AppID can either be an integer or a string. It is returned in one of the two +parameters, while the third parameter indicates what form it takes. + +@param aAppURI +On return, AppId in string form. + +@param aAppID +On return, AppId in numeric form. + +@param aIsAnInt +On return, true if the AppID is an integer value, false if a string. + +@return +KErrNone if successful. +KErrNotFound if the appId has not been set. +*/ +EXPORT_C TInt CPushMsgEntryBase::AppID(TPtrC8& aAppURI, TInt& aAppID, TBool& aIsAnInt) const + { + if (iAppIDString && iAppIDString->Length() > 0) + { + aAppURI.Set(*iAppIDString); + aIsAnInt=EFalse; + return KErrNone; + } + else if (iAppIdInt > 0) + { + aAppID=iAppIdInt; + aIsAnInt=ETrue; + return KErrNone; + } + return KErrNotFound; + } +