diff -r 000000000000 -r 8e480a14352b messagingfw/wappushfw/MiscPushMsgUtils/src/Cunknownpushmsgentry.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingfw/wappushfw/MiscPushMsgUtils/src/Cunknownpushmsgentry.cpp Mon Jan 18 20:36:02 2010 +0200 @@ -0,0 +1,835 @@ +// Copyright (c) 2003-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 // Bafl +#include // RResourceFile +#include // TResourceReader +#include + +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "PushEntryPanic.h" +#endif//SYMBIAN_ENABLE_SPLIT_HEADERS + +#ifdef __MESSAGING_API_V2__ +#include "CAsyncWaiter.h" + +#include +#include +#endif // __MESSAGING_API_V2__ + +_LIT(KContentResourceFile, "\\system\\data\\wappushunknown.rsc"); + +GLDEF_C TPtrC16 LimitStringSize(const TPtrC16& aString, TInt aMaxSize); + + +/** +Allocates and constructs a new Unknown WAP Push message object. + +@return CUnknownPushMsgEntry* +New Unknown WAP Push message object. +*/ +EXPORT_C CUnknownPushMsgEntry* CUnknownPushMsgEntry::NewL() + { + CUnknownPushMsgEntry* self = new (ELeave) CUnknownPushMsgEntry(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + + +/** +Allocates and constructs a new Unknown WAP Push message object, specifying the AppId +as a string. + +@param aAppURI +AppId value as a string. + +@return CUnknownPushMsgEntry* +New Unknown WAP Push message object. +*/ +EXPORT_C CUnknownPushMsgEntry* CUnknownPushMsgEntry::NewL(const TPtrC8& aAppURI) + { + CUnknownPushMsgEntry* self = new (ELeave) CUnknownPushMsgEntry(); + CleanupStack::PushL(self); + self->ConstructL(aAppURI); + CleanupStack::Pop(); + return self; + } + + +/** +Allocates and constructs a new Unknown WAP Push message object, +specifying the AppId as a number. + +@param aAppID +AppId value as a number. + +@return CUnknownPushMsgEntry* +New Unknown WAP Push message object. +*/ +EXPORT_C CUnknownPushMsgEntry* CUnknownPushMsgEntry::NewL(TInt& aAppID) + { + CUnknownPushMsgEntry* self = new (ELeave) CUnknownPushMsgEntry(); + CleanupStack::PushL(self); + self->ConstructL(aAppID); + CleanupStack::Pop(); + return self; + } + + +/** +Destructor. +*/ +EXPORT_C CUnknownPushMsgEntry::~CUnknownPushMsgEntry() + { + iRFs.Close(); + delete iMessageData; + delete iContentType; + delete iFilename; + } + + +/** +Sets the Content Type of the message. + +@param aContentType +The content type of the message +*/ +EXPORT_C void CUnknownPushMsgEntry::SetContentTypeL(const TDesC& aContentType) + { + HBufC* tempBuf = aContentType.AllocL(); + + delete iContentType; + iContentType = tempBuf; + } + + +EXPORT_C const TDesC8& CUnknownPushMsgEntry::MessageData() const +/** +Gets the message data. + +If the buffer for the message data does not exist, a null descriptor is returned. + +@return +Message data +*/ + { + if (iMessageData) + return *iMessageData; + else + return KNullDesC8; + } + + +/** +Sets the message data. + +@param aMessageData +Message data +*/ +EXPORT_C void CUnknownPushMsgEntry::SetMessageDataL(const TDesC8& aMessageData) + { + HBufC8* tempBuf = aMessageData.AllocL(); + + delete iMessageData; + iMessageData = tempBuf; + } + + +/** +Gets the content filename of the message. Content Filename is the name of the file where the +Push message content is stored. + +If filename does not exist then a default filename is returned, which is defined in wappushunknown.rss file. + +Note the function will return the filename in memory which may not necessarily be the filename stored in the +message store. RetrieveL should be called before calling this function to get the filename stored in the +message store. + +@code + // Create an unknown push message object. + CUnknownPushMsgEntry* entry = CUnknownPushMsgEntry::NewL(); + CleanupStack::PushL(entry); + + // Retrieve the required message from the message store. + entry->RetrieveL(session, messageId); + + // Get file name + TFileName fileName = entry->ContentFileNameL(); + + CleanupStack::PopAndDestroy(entry); +@endcode + +@return +The content filename of the message. + +@see CUnknownPushMsgEntry::RetrieveL() +*/ +EXPORT_C const TDesC& CUnknownPushMsgEntry::ContentFileNameL() + { + if (iFilename && iFilename->Length()>0 && iFilename->Length() <= KMaxFileName) + { + // filename has been set + return *iFilename; + } + else + { + TFileName filename = iDefaultBaseFilename; + // append the extension based on the content type + filename.Append(ContentTypeExtension(ContentType())); + SetContentFileNameL(filename); + return *iFilename; + } + } + + +/** +Sets the content filename of the message. Content Filename is the name of the file where the +Push message content is stored. + +Note the function will only save the filename in memory. SaveL or UpdateL will have +to be called to commit the changes to the message store. + +@code + // Create an unknown push message object. + CUnknownPushMsgEntry* entry = CUnknownPushMsgEntry::NewL(); + CleanupStack::PushL(entry); + + // Retrieve the required message from the message store. + entry->RetrieveL(session, messageId); + + // Set file name + _LIT(KFilename, "image.jpg"); + entry->SetContentFileNameL(KFilename); + + // Commit the changes to the message store. + entry->UpdateL(session); + + CleanupStack::PopAndDestroy(entry); +@endcode + +@param aFilename +The content filename. + +@leave KErrBadName aFilename is not a valid Symbian OS file name. +@leave TDesC::AllocL() +*/ +EXPORT_C void CUnknownPushMsgEntry::SetContentFileNameL(const TDesC& aFilename) + { + // Check for valid filname. + if (!iRFs.IsValidName(aFilename)) + User::Leave(KErrBadName); + + HBufC* tempBuf = aFilename.AllocL(); + delete iFilename; + iFilename = tempBuf; + } + + +/** +Constructor. +Simply connects to the File Server before calling base class ConstructL(). +*/ +void CUnknownPushMsgEntry::ConstructL() + { + User::LeaveIfError(iRFs.Connect()); + CPushMsgEntryBase::ConstructL(); + SetDefaultBaseFileNameL(); + } + + +/** +Constructor. +Simply connects to the File Server before calling base class ConstructL(). + +@param +aAppURI set this value if AppId is in string form (must set aIsAnInt to EFalse). +*/ +void CUnknownPushMsgEntry::ConstructL(const TPtrC8& aAppURI) + { + User::LeaveIfError(iRFs.Connect()); + CPushMsgEntryBase::ConstructL(aAppURI); + SetDefaultBaseFileNameL(); + } + + +/** +Constructor. +Simply connects to the File Server before calling base class ConstructL(). + +@param +aAppID set this value if AppId is a number (must set aIsAnInt to ETrue). +*/ +void CUnknownPushMsgEntry::ConstructL(TInt& aAppID) + { + User::LeaveIfError(iRFs.Connect()); + CPushMsgEntryBase::ConstructL(aAppID); + SetDefaultBaseFileNameL(); + } + + +/** +Constructor. +*/ +CUnknownPushMsgEntry::CUnknownPushMsgEntry() + { + } + + +/** +Opens wappushunknown.rss resource file for reading. + +@param aFile +A resource file. +*/ +void CUnknownPushMsgEntry::OpenResourceFileL(RResourceFile& aFile) + { + // open resource file + TFileName fileName; + Dll::FileName(fileName); + TParse parse; + parse.Set(KContentResourceFile, &fileName, 0); + fileName=parse.FullName(); + + BaflUtils::NearestLanguageFile(iRFs, fileName); + aFile.OpenL(iRFs, fileName); + } + + +/** +Sets default content base filename +*/ +void CUnknownPushMsgEntry::SetDefaultBaseFileNameL() + { + // generate default filename from the wappushunknown resource file. + RResourceFile resourceFile; + OpenResourceFileL(resourceFile); + CleanupClosePushL(resourceFile); + + HBufC8* buf = resourceFile.AllocReadLC(CONTENT); + TResourceReader reader; + reader.SetBuffer(buf); + + iDefaultBaseFilename.Copy(reader.ReadTPtrC()); + CleanupStack::PopAndDestroy(2,&resourceFile); // buf, resourceFile + } + + +/** +Stores the Unknown Push message in the message store. + +Saves the message data in a new attachment file. This makes it more efficient for the UI +to read the data. + +@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. + +@see CPushMsgEntryBase::SaveL() +*/ +EXPORT_C TMsvId CUnknownPushMsgEntry::SaveL(CMsvSession& aSession, TMsvId aParent) + + { + CMsvEntry* entryPtr = aSession.GetEntryL(KMsvRootIndexEntryId); + CleanupStack::PushL(entryPtr); + + // This tidies itself up + TMsvId newEntry = CPushMsgEntryBase::SaveL(aSession, aParent); + +#ifdef __MESSAGING_API_V2__ + TRAPD( + saveError, + TFileName fileName = ContentFileNameL(); + entryPtr->SetEntryL(newEntry); + CMsvStore* store = entryPtr->EditStoreL(); + CleanupStack::PushL(store); + SaveMessageBodyL(store->AttachmentManagerL(), fileName); + store->CommitL(); + CleanupStack::PopAndDestroy(store); + ) +#else + TRAPD( + saveError, + TFileName fileName = ContentFileNameL(); + entryPtr->SetEntryL(newEntry); + SaveMessageBodyL(*entryPtr, fileName); + ) +#endif // __MESSAGING_API_V2__ + + if (saveError != KErrNone) + { + aSession.RemoveEntry(iEntry.Id()); + User::Leave(saveError); + } + CleanupStack::PopAndDestroy(); //entryPtr + return newEntry; + } + +#ifdef __MESSAGING_API_V2__ +void CUnknownPushMsgEntry::SaveMessageBodyL(MMsvAttachmentManager& aAttachManager, const TDesC& aFileName) +#else +/** +Stores the Push message body data in an attachment file in the message store. + +@param aEntry +Reference to the message entry. + +@param aFileName +The name of the file where the message body data is to be stored. +*/ +void CUnknownPushMsgEntry::SaveMessageBodyL(const CMsvEntry& aEntry, TFileName& aFileName) +#endif // __MESSAGING_API_V2__ + { +#ifdef __MESSAGING_API_V2__ + // Create an empty file attachment store the data + CAsyncWaiter* waiter = CAsyncWaiter::NewL(); + CleanupStack::PushL(waiter); + CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile); + CleanupStack::PushL(attachment); + attachment->SetAttachmentNameL(aFileName); + RFile file; + aAttachManager.CreateAttachmentL(aFileName, file, attachment, waiter->iStatus); + CleanupStack::Pop(attachment); // ownership passed + waiter->StartAndWait(); + User::LeaveIfError(waiter->Result()); + CleanupStack::PopAndDestroy(waiter); + CleanupClosePushL(file); + + // write the data to the attachment file, if message data exists + if( iMessageData ) + User::LeaveIfError(file.Write(*iMessageData)); + + CleanupStack::PopAndDestroy(&file); +#else + TFileName filePath; + + // create directory path for current entry, to put file into + aEntry.GetFilePath(filePath); + + // check the path and file name is not too long... + TParse parse; + if (parse.Set(aFileName, &filePath, NULL) != KErrNone) + { + // Try with the default file name as the file name the client set may be too long. + // If this leaves then the entry path is probably too long. Not much we + // can do about that. + TFileName defaultFileName; + defaultFileName.Copy(iDefaultBaseFilename); + defaultFileName.Append(ContentTypeExtension(ContentType())); + User::LeaveIfError(parse.Set(defaultFileName, &filePath, NULL)); + }; + + RFile file; + User::LeaveIfError(file.Replace(iRFs, parse.FullName(), EFileWrite|EFileShareExclusive|EFileStream)); + CleanupClosePushL(file); + + // Got this far, so it worked - write data to it + TInt fileErr = KErrNone; + if (iMessageData) + { + fileErr = file.Write(*iMessageData); + } + + if(fileErr!=KErrNone) + { + iRFs.Delete(parse.FullName()); + User::Leave(fileErr); + } + CleanupStack::PopAndDestroy(&file); // file +#endif // __MESSAGING_API_V2__ + } + + +/** +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 + +@see CUnknownPushMsgEntry::SaveL() +@see CUnknownPushMsgEntry::RetrieveL() +@see CPushMsgEntryBase::UpdateL() +*/ +EXPORT_C void CUnknownPushMsgEntry::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 = msvEntry->EditStoreL(); + CleanupStack::PushL(store); + + TUid streamId; + streamId.iUid = PushMsgType(); + RMsvWriteStream out; + out.AssignLC(*store, streamId); + ExternalizeL(out); + +#ifdef __MESSAGING_API_V2__ + // remove all previous attachments + MMsvAttachmentManager& manager = store->AttachmentManagerL(); + CAsyncWaiter* waiter = CAsyncWaiter::NewL(); + CleanupStack::PushL(waiter); + TInt attachCount = manager.AttachmentCount(); + for( TInt ii=attachCount-1; ii>=0; --ii ) + { + manager.RemoveAttachmentL(ii, waiter->iStatus); + waiter->StartAndWait(); + User::LeaveIfError(waiter->Result()); + } + CleanupStack::PopAndDestroy(waiter); + + // the message body data as an attachment + TFileName dataFile = ContentFileNameL(); + SaveMessageBodyL(manager, dataFile); + + // update the entry + iEntry.iMtm = KUidMtmWapPush; + SetPushMsgType(); + msvEntry->ChangeL(iEntry); +#else + TFileName tempfile; + tempfile.Copy(KTempUnknownFileName); + tempfile.Append(ContentTypeExtension(ContentType())); + SaveMessageBodyL(*msvEntry, tempfile); // NB this tidies up if it leaves + + // Ensure the defaults are set correctly. Assume others set by user + iEntry.iMtm = KUidMtmWapPush; + SetPushMsgType(); + + TRAPD(error, msvEntry->ChangeL(iEntry) ); + + TFileName filePath; + msvEntry->GetFilePath(filePath); + User::LeaveIfError(iRFs.SetSessionPath(filePath)); + + if (error != KErrNone) + { + // Delete the temporary file and then leave + iRFs.Delete(tempfile); + User::Leave(error); + } + + // delete the old data file, rename the temp file + CDir* dirList = NULL; + User::LeaveIfError(iRFs.GetDir(filePath, KEntryAttNormal, ESortByName, dirList)); + + if (dirList) + { + TFileName localFile; + for (TInt i=0; i< dirList->Count(); i++) + { + localFile = (*dirList)[i].iName; + if (localFile.CompareF(tempfile) != 0) + { + // Delete if it is not the tempfile + User::LeaveIfError(iRFs.Delete(localFile));// Delete the old file + } + } + } + delete dirList; + + // Construct the new filename + TFileName dataFile = ContentFileNameL(); + User::LeaveIfError(iRFs.Rename(tempfile, dataFile)); // Rename the temp file +#endif // __MESSAGING_API_V2__ + + // 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; + } + + +/** +Retrieves Unknown Push message from the message store into the object. + +@param aSession +Message server session + +@param aMsgId +ID of the message entry to load + +@see CPushMsgEntryBase::RetrieveL() +*/ +EXPORT_C void CUnknownPushMsgEntry::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(); + + //Create store & load in base class data + CMsvStore* store = msvEntry->ReadStoreL(); + CleanupStack::PushL(store); + RestoreL(*store); + +#ifdef __MESSAGING_API_V2__ + DoRetrieveAttachmentL(store->AttachmentManagerL()); +#else + DoRetrieveAttachmentL(*msvEntry); +#endif // __MESSAGING_API_V2__ + + CleanupStack::PopAndDestroy(2); //store, msvEntry + // Obviously has a server entry + iHasServerEntry = ETrue; + } + +#ifdef __MESSAGING_API_V2__ +void CUnknownPushMsgEntry::DoRetrieveAttachmentL(MMsvAttachmentManager& aAttachManager) +#else +/** +This function performs the loading of the data from the attachment file. +It should be noted that if there is a lot of data then the creation of a copy of the +data will squeeze the free memory. + +@param aEntry +Current message entry to load + +@leave KErrNotFound The attachment file cannot be located in the message store. +@leave KErrBadName Will leave if filename is not a valid Symbian OS file name. +@leave TDesC::AllocL() +@leave RFile::Open() +*/ +void CUnknownPushMsgEntry::DoRetrieveAttachmentL(const CMsvEntry& aEntry) +#endif // __MESSAGING_API_V2__ + { + TFileName fileName = ContentFileNameL(); + +#ifdef __MESSAGING_API_V2__ + // get the attachment file that matches the filename + RFile file; + for( TInt ii=0; iiAttachmentName().CompareF(fileName) == 0 ) + { + // found the attachment, get the file and break from the loop + CleanupStack::PopAndDestroy(attachment); // dont need anymore + file = aAttachManager.GetAttachmentFileL(ii); + break; + } + // if we get here, the attachment was not found, destroying the attachment + // will be handled by the leave + User::Leave(KErrNotFound); + } +#else + // get directory for file from current entry + TFileName filePath; + aEntry.GetFilePath(filePath); + + // create the full file name with path + TParse parse; + parse.Set(fileName, &filePath, NULL); + + // create the file + RFile file; + User::LeaveIfError(file.Open(iRFs, parse.FullName(), EFileShareExclusive|EFileStream)); +#endif // __MESSAGING_API_V2__ + + CleanupClosePushL(file); + + // find the size of the file + TInt fileSize = 0; + User::LeaveIfError(file.Size(fileSize)); + + // read into descriptor resizing as we go + HBufC8* data = HBufC8::NewL(fileSize); + TBuf8 fileChunk; + TInt fileError = KErrNone; + + while(fileError ==KErrNone) + { + fileError = file.Read(fileChunk, fileChunk.MaxLength()); + if(fileChunk.Length()==0) + break; + data->Des().Append(fileChunk); + } + + // if it worked assign data to our message buffer + delete iMessageData; + iMessageData = data; + + // Close the file and the file server session + CleanupStack::PopAndDestroy();//file + if(fileError!=KErrNone) + User::Leave(fileError); + } + + +/** +Gets the Content type extension based on the content type supplied + +@param aContentType +The content type +*/ +const TDesC& CUnknownPushMsgEntry::ContentTypeExtension(const TDesC& aContentType) + { + if (aContentType.CompareF(KTextBasic)==0 || aContentType.Compare(KTextPlain)==0) + return KUnknownTextExt; + else if (aContentType.CompareF(KUnknownRTextExt)==0 ) + return KUnknownRTextExt; + else if (aContentType.CompareF(KTextXML) ==0 || aContentType.CompareF(KAppXML)==0) + return KUnknownXmlExt; + else if (aContentType.CompareF(KTextHTML) ==0) + return KUnknownHtmlExt; + else if (aContentType.CompareF(KTextWML)==0) + return KUnknownWmlExt; + else if (aContentType.CompareF(KImageGIF)==0) + return KUnknownGifExt; + else if (aContentType.CompareF(KImageJPEG)==0) + return KUnknownJpegExt; + else if (aContentType.CompareF(KImageTIFF)==0) + return KUnknownTiffExt; + else if (aContentType.CompareF(KImageWBMP) ==0) + return KUnknownWbmpExt; + else if (aContentType.CompareF(KAppSIS)==0) + return KUnknownSISExt; + else if (aContentType.CompareF(KAppWMLC)==0 || aContentType.CompareF(KAppWBXML)==0) + return KUnknownWmlcExt; + else if (aContentType.CompareF(KTextMSWord)==0 || + aContentType.CompareF(KTextMSWord95)==0 || + aContentType.CompareF(KTextMSWord97)==0 || + aContentType.CompareF(KTextMSWord00)==0 || + aContentType.CompareF(KTextMSWord2000)==0 ) + return KUnknownDocExt; + else + return KStdUnknownExt; + } + + +/** +Gets the value of the Uid for the Push Message type of the Push Entry. + +@return TInt32 +Uid as a long integer. +*/ +TInt32 CUnknownPushMsgEntry::PushMsgType() const + { + return KUidWapPushMsgUnknown.iUid; + } + + +/** +Sets the Uid of the Push Message Entry to the value for an Unknown Push message. +*/ +void CUnknownPushMsgEntry::SetPushMsgType() + { + iEntry.iBioType = KUidWapPushMsgUnknown.iUid; + } + + +/** +Externalises Push message data to a write stream. + +Apart from the data stored by the base class, other data stored are Content Type, +Time Sent and Content Filename. + +@param aStream +The stream to which the data should be externalised. + +@see CPushMsgEntryBase::ExternalizeL() +*/ +EXPORT_C void CUnknownPushMsgEntry::ExternalizeL(RMsvWriteStream& aStream) + { + CPushMsgEntryBase::ExternalizeL(aStream); + + aStream<> timeSent; + iTimeSent = timeSent; + + delete iFilename; + iFilename = NULL; + TRAPD(error, iFilename = HBufC::NewL(aStream, KLongestStringAllowed)); + if (error != KErrNone && error != KErrEof) + { + User::Leave(error); + } + else if(error == KErrEof) + { + User::Leave(KErrNotSupported); + } + } + + +#ifndef EKA2 +GLDEF_C TInt E32Dll(TDllReason/* aReason*/) + { + return (KErrNone); + } +#endif