diff -r 000000000000 -r 72b543305e3a mobilemessaging/unieditor/mtm/src/UniClientMtm.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mobilemessaging/unieditor/mtm/src/UniClientMtm.cpp Thu Dec 17 08:44:11 2009 +0200 @@ -0,0 +1,1427 @@ +/* +* Copyright (c) 2005-2007 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: UniClientMtm implementation +* +*/ + + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include +#include // CMsvFindText +#include +#include +#include + +#include +#include +#include +#include + +#include "UniMsvEntry.h" +#include "UniMtmPanic.h" +#include "UniHeaders.h" +#include "UniClientMtm.h" +#include "UniEditorUids.hrh" +#include "UniEditorLogging.h" + +// ================= MEMBER FUNCTIONS ======================= + +// --------------------------------------------------------- +// Factory function +// --------------------------------------------------------- +// +EXPORT_C CUniClientMtm* CUniClientMtm::NewL( + CRegisteredMtmDll& aRegisteredMtmDll, + CMsvSession& aSession ) + { + CUniClientMtm* self=new ( ELeave ) CUniClientMtm( + aRegisteredMtmDll, aSession ); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------- +// Constructor +// --------------------------------------------------------- +// +CUniClientMtm::CUniClientMtm( + CRegisteredMtmDll& aRegisteredMtmDll, + CMsvSession& aSession ) + : CBaseMtm( aRegisteredMtmDll, aSession ), + iUniHeaders ( NULL ) + { + } + +// --------------------------------------------------------- +// Destructor +// --------------------------------------------------------- +// +CUniClientMtm::~CUniClientMtm() + { + delete iAttaWaiter; + delete iUniHeaders; + delete iTextUtils; + } + +// --------------------------------------------------------- +// CUniClientMtm::CreateNewEntryL +// --------------------------------------------------------- +// +TMsvId CUniClientMtm::CreateNewEntryL( TMsvId aDestination ) + { + UNILOGGER_WRITE_TIMESTAMP( "CUniClientMtm::CreateNewEntryL start" ); + // Create new message entry + TMsvEntry entry; + entry.iType = KUidMsvMessageEntry; + entry.iServiceId = KMsvLocalServiceIndexEntryId; + entry.iMtm = TUid::Uid( KUidUniMtm ); + entry.iDate.UniversalTime(); + + // The following ones will be set in completion. + entry.SetInPreparation( ETrue ); + entry.SetVisible( EFalse ); + entry.iSize = 0; + + // Check that sufficient disk space available + // for index entry + if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( + &Session().FileSession(), + sizeof( TMsvEntry ), + Session().CurrentDriveL() ) ) + { + // we use standard error code here + User::Leave( KErrDiskFull ); + } + + SwitchCurrentEntryL( aDestination ); + iMsvEntry->CreateL( entry ); + SwitchCurrentEntryL( entry.Id() ); + + UNILOGGER_WRITE_TIMESTAMP( "CUniClientMtm::CreateNewEntryL end" ); + + return entry.Id(); + } + +//---------------------------------------------------------- +// METHODS FROM BASE CLASS +//---------------------------------------------------------- + +// --------------------------------------------------------- +// CUniClientMtm::SaveMessageL +// Stores the multimedia message +// --------------------------------------------------------- +// +void CUniClientMtm::SaveMessageL() + { + // First we should assert that iMsvEntry is not NULL, and panic, if it is + __ASSERT_DEBUG( iMsvEntry!=NULL, Panic( EUniNotAMessage )); + // SaveMessageL should only be supported for message entries. + __ASSERT_DEBUG( iMsvEntry->Entry().iType.iUid == KUidMsvMessageEntryValue, + Panic( EUniNotAMessage ) ); + + CMsvStore* store = iMsvEntry->EditStoreL(); + CleanupStack::PushL( store ); + + TMsvEntry indexEntry = iMsvEntry->Entry(); + + SaveMessageL( *store, indexEntry ); + + // Commit the stream store + store->CommitL(); + CleanupStack::PopAndDestroy( store ); + + // commit the index changes. + iMsvEntry->ChangeL( indexEntry ); + } + +// --------------------------------------------------------- +// CUniClientMtm::SaveMessageL +// Stores the multimedia message +// --------------------------------------------------------- +// +void CUniClientMtm::SaveMessageL( CMsvStore& aEditStore, TMsvEntry& aEntry ) + { + // Store headers of a message + + // Because of attachments are handled using the new + // attacment manager, the caller must store and commit the attachments + // either one by one or after all have been added. + // After saving all attachments the edit store used for that purpose + // must be freed. + // The store must be freed because all attachment info and uni headers + // are saved in the actual message entry, there are no separate + // attachment entries anymore. + + // Check that sufficient disk space available + if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( + &Session().FileSession(), + iUniHeaders->Size(), + iMessageDrive ) ) + { + User::Leave( KErrDiskFull ); + } + + // Note: Body text not supported. + iUniHeaders->StoreL( aEditStore ); + + // needed to convert unimessages to sms messages + StoreBodyL( aEditStore ); + + // attachment size + TInt32 totalSizeOfAllAttachments = AttachmentsSizeL( aEditStore ); + aEntry.iSize = iUniHeaders->Size() + totalSizeOfAllAttachments; + + // If there are multiple recipients then set the flag + if (( iUniHeaders->ToRecipients().Count() + //lint !e115 !e1013 !e48 !e10 !e1055 !e746 !e628 + iUniHeaders->CcRecipients().Count() + //lint !e115 !e1013 !e48 !e10 !e1055 !e746 !e628 + iUniHeaders->BccRecipients().Count() ) >= 2 ) //lint !e115 !e1013 !e48 !e10 !e1055 !e746 !e628 + { + aEntry.SetMultipleRecipients( ETrue ); + } + else + { + // clear multiple recipients in case recipients have + // been deleted after the message was saved the last time + aEntry.SetMultipleRecipients( EFalse ); + } + + // Set iDetails (recipient) + TPtrC to; + if ( iUniHeaders->ToRecipients().Count() ) //lint !e115 !e1013 !e48 !e10 + { + to.Set( TMmsGenUtils::Alias( iUniHeaders->ToRecipients()[0] ) ); //lint !e115 !e1013 !e48 !e10 !e64 + if ( to.Length() <= 0 ) + { + // If no alias part then set the real address in details + to.Set( iUniHeaders->ToRecipients()[0] ); //lint !e115 !e1013 !e48 !e10 !e1025 !e1703 !e64 !e118 + } + } + aEntry.iDetails.Set( to ); + + if ( totalSizeOfAllAttachments > 0 ) + { + aEntry.SetAttachment( ETrue ); + } + + switch ( iUniHeaders->MessageTypeLocking() ) + { + case EUniMessageTypeLocked: + TUniMsvEntry::SetMessageTypeLocked( aEntry, ETrue ); + break; + case EUniMessageTypeNotLocked: + TUniMsvEntry::SetMessageTypeLocked( aEntry, EFalse ); + break; + case EUniMessageTypeLockingNotSet: + default: + // Don't touch TMsvEntry. + break; + } + } + +// --------------------------------------------------------- +// CUniClientMtm::LoadMessageL +// Loads the unified message +// --------------------------------------------------------- +// +void CUniClientMtm::LoadMessageL() + { + // First we should assert that iMsvEntry is not NULL, and panic, if it is + __ASSERT_DEBUG( iMsvEntry, Panic( EUniNotAMessage ) ); + // LoadMessageL should only be supported for message entries. + __ASSERT_DEBUG( iMsvEntry->Entry().iType.iUid == KUidMsvMessageEntryValue, + Panic( EUniNotAMessage ) ); + + // Old data must be reset first.... + // CMmsSettings resets itself before doing restore, so that's ok. + + TMsvEntry indexEntry = iMsvEntry->Entry(); //lint !e1924 + + + // load the correct data + // get read-only message store + CMsvStore* store = iMsvEntry->ReadStoreL(); + CleanupStack::PushL( store ); + + // Restore headers of unified message + // if headers do not exist does nothing. Default headers will be used. + iUniHeaders->RestoreL( *store ); + + if ( iUniHeaders->MessageTypeLocking() == EUniMessageTypeLockingNotSet && + TUniMsvEntry::IsMessageTypeLocked( indexEntry ) ) + { + switch ( TUniMsvEntry::CurrentMessageType( indexEntry ) ) + { + case EUniMessageCurrentTypeSms: + { + iUniHeaders->SetMessageTypeSetting( EUniMessageTypeSettingSms ); + iUniHeaders->SetMessageTypeLocking( EUniMessageTypeLocked ); + break; + } + case EUniMessageCurrentTypeMms: + { + iUniHeaders->SetMessageTypeSetting( EUniMessageTypeSettingMms ); + iUniHeaders->SetMessageTypeLocking( EUniMessageTypeLocked ); + break; + } + default: + break; + } + } + + // Attachment info is not restored. + // It makes no sense to cache the attachment info as new attachments + // can be added with the help of the attachment magager without + // informing uni Client MTM of the additions. + // Caller must use attachment manager to get attachment info. + + CleanupStack::PopAndDestroy( store ); + store = NULL; + + // Build the iAddresseeList up + BuildAddresseeListL(); + } + +// --------------------------------------------------------- +// CUniClientMtm::ReplyL +// Send a reply to current message +// --------------------------------------------------------- +// +CMsvOperation* CUniClientMtm::ReplyL( + TMsvId /*aDestination*/, + TMsvPartList /*aPartList*/, + TRequestStatus& /*aCompletionStatus*/ ) + { + User::Leave( KErrNotSupported ); + return NULL; + } + +// --------------------------------------------------------- +// CUniClientMtm::ForwardL +// Forward current message +// --------------------------------------------------------- +// +CMsvOperation* CUniClientMtm::ForwardL( + TMsvId /*aDestination*/, + TMsvPartList /*aPartList*/, + TRequestStatus& /*aCompletionStatus*/ ) + { + User::Leave( KErrNotSupported ); + return NULL; + } + +// --------------------------------------------------------- +// CUniClientMtm::ValidateMessage +// Validate selected parts of current message +// --------------------------------------------------------- +// +TMsvPartList CUniClientMtm::ValidateMessage( + TMsvPartList aPartList ) + { + __ASSERT_DEBUG( iMsvEntry, Panic( EUniNotAMessage )); + + TMsvPartList retVal = 0; + if ( iMsvEntry->Entry().iType.iUid != KUidMsvMessageEntryValue ) + { + // not a message, no part is valid + retVal = aPartList; + } + + if ( aPartList & KMsvMessagePartRecipient ) + { + if ( iAddresseeList->Count() == 0) + { + retVal |= KMsvMessagePartRecipient; + } + else + { + // check the recipient list for valid 'addresses' + for (TInt ii=0; ii < iAddresseeList->Count(); ++ii) + { + TPtrC oneAddress = (*iAddresseeList)[ii]; + TPtrC pureAddress = TMmsGenUtils::PureAddress( oneAddress ); + if ( ( pureAddress.Length() == 0 ) || + !TMmsGenUtils::IsValidAddress( pureAddress, ETrue ) ) + { + retVal |= KMsvMessagePartRecipient; + break; + } + } + } + } + + // all attachments are considered valid - even no attachments + + return retVal; + + } + +// --------------------------------------------------------- +// CUniClientMtm::Find +// Find text in selected message parts +// --------------------------------------------------------- +// +TMsvPartList CUniClientMtm::Find( + const TDesC& aTextToFind, + TMsvPartList aPartList ) + { + TMsvPartList foundList( KMsvMessagePartNone ); + TRAP_IGNORE( foundList = DoFindL( aTextToFind, aPartList) ); + return foundList; + } + +// --------------------------------------------------------- +// CUniClientMtm::DoFindL +// Find text in selected message parts +// --------------------------------------------------------- +// +TMsvPartList CUniClientMtm::DoFindL( + const TDesC& aTextToFind, + TMsvPartList aPartList ) + { + // The final version will not have a rich text body, but we could + // search for example the originator and description. + + __ASSERT_DEBUG( iMsvEntry, Panic( EUniNotAMessage ) ); + TMsvPartList foundList = KMsvMessagePartNone; + TMsvEntry entry = iMsvEntry->Entry(); + + CMsvFindText* findText = CMsvFindText::NewL(); + CleanupStack::PushL( findText ); + + if ( aPartList & KMsvMessagePartRecipient ) + { + // Find from To, Cc and Bcc fields + if ( FindInRecipientL( aTextToFind, + aPartList, iUniHeaders->ToRecipients(), *findText)) + { + foundList |= KMsvMessagePartRecipient; + } + else if ( FindInRecipientL( aTextToFind, + aPartList, iUniHeaders->CcRecipients(), *findText )) + { + foundList |= KMsvMessagePartRecipient; + } + else if ( FindInRecipientL( aTextToFind, + aPartList, iUniHeaders->BccRecipients(), *findText )) + { + foundList |= KMsvMessagePartRecipient; + } + } + + if ( aPartList & KMsvMessagePartDescription ) + { + if ( findText->FindTextL( aTextToFind, entry.iDescription, + aPartList ) ) + { + foundList |= KMsvMessagePartDescription; + } + } + + CleanupStack::PopAndDestroy( findText ); + return foundList; + } + +// --------------------------------------------------------- +// CUniClientMtm::AddAddresseeL +// --------------------------------------------------------- +// +void CUniClientMtm::AddAddresseeL( const TDesC& aRealAddress ) + { + // Add to general list + // When no type is specified, the address will have type "to" + iAddresseeList->AppendL( EMsvRecipientTo, aRealAddress ); + + // Add to "To" recipient list + iUniHeaders->AddTypedAddresseeL( aRealAddress, EMsvRecipientTo ); //lint !e115 !e1013 !e48 !e10 !e1514 !e64 + } + +// --------------------------------------------------------- +// CUniClientMtm::AddAddresseeL +// --------------------------------------------------------- +// +void CUniClientMtm::AddAddresseeL( + const TDesC& aRealAddress, + const TDesC& aAlias ) + { + + if ( aAlias.Length() > 0 ) + { + HBufC* buf = TMmsGenUtils::GenerateAddressL( aRealAddress, aAlias ); + CleanupStack::PushL( buf ); + AddAddresseeL( buf->Des() ); + CleanupStack::PopAndDestroy( buf ); + } + else + { + AddAddresseeL( aRealAddress ); + } + } + +// --------------------------------------------------------- +// CUniClientMtm::AddAddresseeL +// --------------------------------------------------------- +// +void CUniClientMtm::AddAddresseeL( TMsvRecipientType aType, + const TDesC& aRealAddress ) + { + // Add to general list + // When no type is specified, the address will have type "to", + // "cc" or "bcc" + iAddresseeList->AppendL( aType, aRealAddress ); + + // Add to recipient list + iUniHeaders->AddTypedAddresseeL( aRealAddress, aType ); + + } + +// --------------------------------------------------------- +// CUniClientMtm::AddAddresseeL +// --------------------------------------------------------- +// +void CUniClientMtm::AddAddresseeL( + TMsvRecipientType aType, + const TDesC& aRealAddress, + const TDesC& aAlias ) + { + + if ( aAlias.Length() > 0 ) + { + HBufC* buf = TMmsGenUtils::GenerateAddressL( aRealAddress, aAlias ); + CleanupStack::PushL( buf ); + AddAddresseeL(aType, buf->Des()); + CleanupStack::PopAndDestroy( buf ); + } + else + { + AddAddresseeL( aType, aRealAddress ); + } + } + +// --------------------------------------------------------- +// CUniClientMtm::RemoveAddressee +// --------------------------------------------------------- +// +void CUniClientMtm::RemoveAddressee( TInt aIndex ) + { + + if ( aIndex < 0 ) + { + return; + } + if ( iAddresseeList->Count() > aIndex ) + { + // Delete from typed list + TPtrC address = (*iAddresseeList)[ aIndex ]; + iUniHeaders->RemoveAddressee( address ); + // delete from untyped list + iAddresseeList->Delete( aIndex ); + } + + } + +// --------------------------------------------------------- +// CUniClientMtm::SetSubjectL +// --------------------------------------------------------- +// +void CUniClientMtm::SetSubjectL( const TDesC& aSubject ) + { + iUniHeaders->SetSubjectL( aSubject ); //lint !e115 !e1013 !e48 !e10 !e1514 !e64 + } + +// --------------------------------------------------------- +// CUniClientMtm::SubjectL +// --------------------------------------------------------- +// +const TPtrC CUniClientMtm::SubjectL() const + { + return iUniHeaders->Subject(); //lint !e115 !e1013 !e48 !e10 !e746 !e64 !e1055 !e628 + } + +// --------------------------------------------------------- +// CUniClientMtm::AddAttachmentL +// --------------------------------------------------------- +// +void CUniClientMtm::AddAttachmentL( const TDesC& aFilePath, + const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus ) + { + + TInt error = KErrNone; + TUint charset = aCharset; + RFile file; + if ( aMimeType.CompareF( KMmsTextPlain ) == 0 && charset == 0 ) + { + // try to recognize character set + // We trap the recognization process + // If cannot recognize, the result will be 0 and default to us-ascii + TRAP ( error, + { + error = file.Open( Session().FileSession(), aFilePath, + EFileRead|EFileShareReadersOnly ); + if ( error == KErrNone ) + { + CleanupClosePushL( file ); + charset = RecognizeCharSetL( file ); + CleanupStack::PopAndDestroy( &file ); + } + } + ); + } + + // if the attachment character set is unicode, it should be converted to utf-8 + // (see MMS conformance document) + + if ( aMimeType.CompareF( KMmsTextPlain ) == 0 && + ( charset == KCharacterSetMIBEnumIso10646Ucs2 || + charset == KCharacterSetMIBEnumUTF16 || + charset == KCharacterSetMIBEnumUTF16BE || + charset == KCharacterSetMIBEnumUTF16LE ) ) + { + // If we have unicode character set, we must convert the file to utf8 + error = file.Open( Session().FileSession(), aFilePath, + EFileRead|EFileShareReadersOnly ); + if ( error == KErrNone ) + { + CleanupClosePushL( file ); + CMsvStore* store = iMsvEntry->EditStoreL(); + CleanupStack::PushL( store ); + TMsvAttachmentId attaId = 0; + CMmsAttachmentHandler::CreateUTF8TextAttachmentFromFileL( + *store, attaId, file, Session().FileSession(), + Session().CurrentDriveL() ); + + SetContentLocationForConvertedAttL( *store, attaId, aFilePath ); + + store->CommitL(); + CleanupStack::PopAndDestroy( store ); + CleanupStack::PopAndDestroy( &file ); + } + TRequestStatus* status = &aStatus; + aStatus = KRequestPending; + User::RequestComplete( status, error ); + return; + } + else + { + // Disk space is checked in AddFilePathAttachmentL after everything has been initialized + AddFilePathAttachmentL( aFilePath, aMimeType, CMsvAttachment::EMsvFile, aStatus, charset ); + } + } + +// --------------------------------------------------------- +// CUniClientMtm::AddAttachmentL +// --------------------------------------------------------- +// +void CUniClientMtm::AddAttachmentL( RFile& aFile, const TDesC8& aMimeType, + TUint aCharset, TRequestStatus& aStatus ) + { + TInt size = 0; + User::LeaveIfError( aFile.Size( size ) ); + + TFileName fileName; + User::LeaveIfError( aFile.Name( fileName ) ); + + TInt charset = aCharset; + if ( aMimeType.CompareF( KMmsTextPlain ) == 0 && charset == 0 ) + { + // If no character set defined for a plain text attachment + // we try to recognize the character set. + // But if recogization fails, we say 0 (us-ascii) + TRAP_IGNORE ( charset = RecognizeCharSetL( aFile ) ); + } + + if ( aMimeType.CompareF( KMmsTextPlain ) == 0 ) + { + // If we have unicode character set, we must convert the file to utf8 + if ( charset == KCharacterSetMIBEnumIso10646Ucs2 || + charset == KCharacterSetMIBEnumUTF16 || + charset == KCharacterSetMIBEnumUTF16BE || + charset == KCharacterSetMIBEnumUTF16LE ) + { + CMsvStore* store = iMsvEntry->EditStoreL(); + CleanupStack::PushL( store ); + TMsvAttachmentId attaId = 0; + CMmsAttachmentHandler::CreateUTF8TextAttachmentFromFileL( *store, + attaId, aFile, Session().FileSession(), + Session().CurrentDriveL() ); + + SetContentLocationForConvertedAttL( *store, attaId, fileName ); + + store->CommitL(); + CleanupStack::PopAndDestroy( store ); // store + // We must close the file handle because the attachment manager will also + // close the handle. + // The open file handle is always closed unless the funtion leaves + aFile.Close(); + TRequestStatus* status = &aStatus; + aStatus = KRequestPending; + User::RequestComplete( status, KErrNone ); + return; + } + } + + if( !iAttaWaiter ) + { + iAttaWaiter = CMmsAttachmentWaiter::NewL(); + } + + // store must be the first item allocated because it is the last one to be popped + CMsvStore* store = iMsvEntry->EditStoreL(); + CleanupStack::PushL( store ); + MMsvAttachmentManager& manager = store->AttachmentManagerL(); + + CMsvAttachment* attachment = CMsvAttachment::NewL( CMsvAttachment::EMsvFile ); + CleanupStack::PushL( attachment ); + + size += InitializeAttachmentL( + manager, + *attachment, + fileName, + aMimeType, + size, + charset ); + + // Check that sufficient disk space available + if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( + &Session().FileSession(), + size, + iMessageDrive ) ) + { + User::Leave( KErrDiskFull ); + } + + // attachment is initialised, pass to the attachment manager + if ( iAttaWaiter->IsActive() ) + { + // can't start an active operation because already active + User::Leave( KErrInUse ); + } + manager.AddAttachmentL( aFile, attachment, iAttaWaiter->iStatus ); + CleanupStack::Pop( attachment ); //ownership passed to manager + // We cannot start waiting before we know that the function we are waiting for + // did not leave. If we become active, and the function leaves, we are in trouble + iAttaWaiter->StartWaitingL( aStatus, store, &manager ); + CleanupStack::Pop( store ); //ownership passed + } +// --------------------------------------------------------- +// CUniClientMtm::AddLinkedAttachmentL +// --------------------------------------------------------- +// +void CUniClientMtm::AddLinkedAttachmentL( const TDesC& aFilePath, + const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus ) + { + TInt error = KErrNone; + TUint charset = aCharset; + if ( aMimeType.CompareF( KMmsTextPlain ) == 0 && aCharset == 0) + { + // try to recognize character set + // We trap the recognization process + // If cannot recognize, the result will be 0 and default to us-ascii + TRAP ( error, + { + RFile file; + error = file.Open( Session().FileSession(), aFilePath, + EFileRead|EFileShareReadersOnly); + if ( error == KErrNone ) + { + CleanupClosePushL( file ); + charset = RecognizeCharSetL( file ); + CleanupStack::PopAndDestroy( &file ); + } + } + ); + } + // Linked files cannot be converted to utf8. They must be sent as is no + // matter what the character set is. + + // Disk space is checked in AddFilePathAttachmentL after everything has + // been initialized. + if ( aMimeType.CompareF( KMmsTextPlain ) == 0 && + ( charset == KCharacterSetMIBEnumIso10646Ucs2 || + charset == KCharacterSetMIBEnumUTF16 || + charset == KCharacterSetMIBEnumUTF16BE || + charset == KCharacterSetMIBEnumUTF16LE ) ) + { + AddAttachmentL( aFilePath, aMimeType, charset, aStatus ); + } + else + { + AddFilePathAttachmentL( aFilePath, aMimeType, + CMsvAttachment::EMsvLinkedFile, aStatus, charset ); + } + } + +// --------------------------------------------------------- +// CUniClientMtm::AddEntryAsAttachmentL +// --------------------------------------------------------- +// +void CUniClientMtm::AddEntryAsAttachmentL( TMsvId /*aAttachmentId*/, + TRequestStatus& aStatus ) + { + TRequestStatus* status = &aStatus; + User::RequestComplete( status, KErrNotSupported ); + } + +// --------------------------------------------------------- +// CUniClientMtm::CreateAttachmentL +// --------------------------------------------------------- +// +void CUniClientMtm::CreateAttachmentL( const TDesC& aFileName, + RFile& aAttachmentFile, const TDesC8& aMimeType, + TUint aCharset, TRequestStatus& aStatus ) + { + if( !iAttaWaiter ) + { + iAttaWaiter = CMmsAttachmentWaiter::NewL(); + } + + // store must be the first item allocated because it is the last one to be popped + CMsvStore* store = iMsvEntry->EditStoreL(); + CleanupStack::PushL( store ); + MMsvAttachmentManager& manager = store->AttachmentManagerL(); + + CMsvAttachment* attachment = + CMsvAttachment::NewL( CMsvAttachment::EMsvFile ); + CleanupStack::PushL( attachment ); + + TInt size = InitializeAttachmentL( + manager, + *attachment, + aFileName, + aMimeType, + 0, // Creating empty attachment! + aCharset ); + + // Check that sufficient disk space available + if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( + &Session().FileSession(), + size, + iMessageDrive ) ) + { + User::Leave( KErrDiskFull ); + } + + if ( iAttaWaiter->IsActive() ) + { + // can't start an active operation because already active + User::Leave( KErrInUse ); + } + manager.CreateAttachmentL( aFileName, aAttachmentFile, attachment, + iAttaWaiter->iStatus ); + CleanupStack::Pop( attachment ); //ownership passed to manager + iAttaWaiter->StartWaitingL( aStatus, store, &manager ); + CleanupStack::Pop( store ); //ownership passed + } +// --------------------------------------------------------- +// CUniClientMtm::CancelAttachmentOperation +// --------------------------------------------------------- +// +void CUniClientMtm::CancelAttachmentOperation() + { + + if ( iAttaWaiter ) + { + iAttaWaiter->Cancel(); + delete iAttaWaiter; + iAttaWaiter = NULL; + } + } + + +// --------------------------------------------------------- +// CUniClientMtm::CreateTextAttachmentL +// --------------------------------------------------------- +// +void CUniClientMtm::CreateTextAttachmentL( + CMsvStore& aStore, + TMsvAttachmentId& aAttachmentId, + const TDesC& aText, + const TDesC& aFile, + TBool aConvertParagraphSeparator ) + { + + CMmsAttachmentHandler::CreateTextAttachmentL( aStore, + aAttachmentId, + aText, + aFile, + Session().FileSession(), + Session().CurrentDriveL(), + aConvertParagraphSeparator ); + + } + +// --------------------------------------------------------- +// CUniClientMtm::MessageTypeSetting +// --------------------------------------------------------- +// +TUniMessageTypeSetting CUniClientMtm::MessageTypeSetting() const + { + return TUniMessageTypeSetting( iUniHeaders->MessageTypeSetting() ); + } + +// --------------------------------------------------------- +// CUniClientMtm::SetMessageTypeSetting +// --------------------------------------------------------- +// +void CUniClientMtm::SetMessageTypeSetting( TUniMessageTypeSetting aSetting ) + { + iUniHeaders->SetMessageTypeSetting( aSetting ); + } + +// --------------------------------------------------------- +// CUniClientMtm::MessageTypeLocking +// --------------------------------------------------------- +// +TUniMessageTypeLocking CUniClientMtm::MessageTypeLocking() const + { + return TUniMessageTypeLocking( iUniHeaders->MessageTypeLocking() ); + } + +// --------------------------------------------------------- +// CUniClientMtm::SetMessageTypeLocking +// --------------------------------------------------------- +// +void CUniClientMtm::SetMessageTypeLocking( TUniMessageTypeLocking aLocking ) + { + iUniHeaders->SetMessageTypeLocking( aLocking ); + } + +// --------------------------------------------------------- +// CUniClientMtm::MessageRoot +// --------------------------------------------------------- +// +TMsvAttachmentId CUniClientMtm::MessageRoot() const + { + return iUniHeaders->MessageRoot(); + } + +// --------------------------------------------------------- +// CUniClientMtm::SetMessageRoot +// --------------------------------------------------------- +// +void CUniClientMtm::SetMessageRoot( TMsvAttachmentId aRoot ) + { + iUniHeaders->SetMessageRoot( aRoot ); + } + +// --------------------------------------------------------- +// CUniClientMtm::CreateMessageL +// --------------------------------------------------------- +// +void CUniClientMtm::CreateMessageL( + TMsvId aServiceId ) + { + // Check that sufficient disk space available + // for index entry + if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( + &Session().FileSession(), + KMmsIndexEntryExtra, + iMessageDrive ) ) + { + // we use standard error code here + User::Leave( KErrDiskFull ); + } + + // just call the base class function + CBaseMtm::CreateMessageL( aServiceId ); + + iUniHeaders->Reset(); + } + +// --------------------------------------------------------- +// CUniClientMtm::BioTypeChangedL +// --------------------------------------------------------- +// +void CUniClientMtm::BioTypeChangedL( TUid /*aBioTypeUid*/ ) + { + // Do nothing. + } + +// --------------------------------------------------------- +// CUniClientMtm::DefaultServiceL +// --------------------------------------------------------- +// +TMsvId CUniClientMtm::DefaultServiceL() const + { + return KMsvLocalServiceIndexEntryId; + } + +// --------------------------------------------------------- +// CUniClientMtm::RemoveDefaultServiceL +// --------------------------------------------------------- +// +void CUniClientMtm::RemoveDefaultServiceL() + { + // not supported + } + +// --------------------------------------------------------- +// CUniClientMtm::ChangeDefaultServiceL +// --------------------------------------------------------- +// +void CUniClientMtm::ChangeDefaultServiceL( const TMsvId& /*aService*/ ) + { + // not supported + } + +// --------------------------------------------------------- +// CUniClientMtm::QueryCapability +// --------------------------------------------------------- +// +TInt CUniClientMtm::QueryCapability( + TUid aCapability, + TInt& aResponse ) + { + TInt error = KErrNone; + switch ( aCapability.iUid ) + { + // Supported: + case KUidMtmQueryMaxTotalMsgSizeValue: + aResponse = KMaxTInt; + break; + case KUidMsvMtmQueryEditorUidValue: + aResponse = KUidMsgMmsEditor; + break; + case KUidMtmQuerySupportSubjectValue: + case KUidMtmQuerySupportAttachmentsValue: + case KUidMtmQueryCanSendMsgValue: + case KUidMtmQuerySendAsMessageSendSupportValue: + case KUidMtmQuerySupportsRecipientTypeValue: + // returns KErrNone + break; + // All others - Not Supported: + default: + error = KErrNotSupported; + } + return error; + + } //lint !e1746 + +// --------------------------------------------------------- +// CUniClientMtm::InvokeSyncFunctionL +// --------------------------------------------------------- +// +void CUniClientMtm::InvokeSyncFunctionL( + TInt /*aFunctionId*/, + const CMsvEntrySelection& /*aSelection*/, + TDes8& /*aParameter*/ ) + { + User::Leave( KErrNotSupported ); + } + +// --------------------------------------------------------- +// CUniClientMtm::InvokeAsyncFunctionL +// --------------------------------------------------------- +// +CMsvOperation* CUniClientMtm::InvokeAsyncFunctionL( + TInt /* aFunctionId */, + const CMsvEntrySelection& /* aSelection*/, + TDes8& /* aParameter*/, + TRequestStatus& aCompletionStatus ) + { + TPckgC < TMsvId > progress = 0; + return CMsvCompletedOperation::NewL( Session(), Type(), progress, + KMsvLocalServiceIndexEntryId, aCompletionStatus, KErrNotSupported ); + } + +// --------------------------------------------------------- +// CUniClientMtm::ContextEntrySwitched +// --------------------------------------------------------- +// +void CUniClientMtm::ContextEntrySwitched() + { + // Context change notification. + // Reset data. + + // Note: Body text reset would be here if supported. + iAddresseeList->Reset(); + iUniHeaders->Reset(); + } + +// --------------------------------------------------------- +// CUniClientMtm::HandleEntryEventL +// --------------------------------------------------------- +// +void CUniClientMtm::HandleEntryEventL( + TMsvEntryEvent /*aEvent*/, + TAny* /*arg1*/, + TAny* /*arg2*/, + TAny* /*arg3*/ ) + { + // No operation + } + +// --------------------------------------------------------- +// CUniClientMtm::ConstructL +// --------------------------------------------------------- +// +void CUniClientMtm::ConstructL() + { + iMessageDrive = EDriveC; + TInt error = KErrNone; + + TRAP ( error, { iMessageDrive = Session().CurrentDriveL(); } ); + + if ( error != KErrNone ) + { + // if cannot ask, use default + iMessageDrive = EDriveC; + } + + iUniHeaders = CUniHeaders::NewL(); + } + +// --------------------------------------------------------- +// CUniClientMtm::MessageSize +// --------------------------------------------------------- +// +TInt32 CUniClientMtm::MessageSize() + { + // First we should assert that iMsvEntry is not NULL, and panic, if it is + __ASSERT_DEBUG( iMsvEntry, Panic( EUniNotAMessage )); + TUint size = 0; + TRAPD( error, {size = AttachmentsSizeL() + iUniHeaders->Size();} ); + if ( error != KErrNone ) // this is needed to get rid of compiler warning + { + size = 0; + } + return size; //lint !e713 nothing lost here + } + +// --------------------------------------------------------- +// CUniClientMtm::SetMessageDescriptionL +// --------------------------------------------------------- +// +void CUniClientMtm::SetMessageDescriptionL( const TDesC& aText ) + { + // First we should assert that iMsvEntry is not NULL, and panic, if it is + __ASSERT_DEBUG( iMsvEntry, Panic( EUniNotAMessage ) ); + TMsvEntry entry = iMsvEntry->Entry(); + entry.iDescription.Set( aText ); + iMsvEntry->ChangeL( entry ); + } + +// --------------------------------------------------------- +// CUniClientMtm::BuildAddresseeListL +// --------------------------------------------------------- +// +void CUniClientMtm::BuildAddresseeListL() + { + + iAddresseeList->Reset(); + + const CDesCArray& array1 = iUniHeaders->ToRecipients(); //lint !e115 !e1013 !e48 !e10 !e64 + const CDesCArray& array2 = iUniHeaders->CcRecipients(); //lint !e115 !e1013 !e48 !e10 !e64 + const CDesCArray& array3 = iUniHeaders->BccRecipients(); //lint !e115 !e1013 !e48 !e10 !e64 + + BuildAddresseeListL( array1, EMsvRecipientTo ); + BuildAddresseeListL( array2, EMsvRecipientCc ); + BuildAddresseeListL( array3, EMsvRecipientBcc ); + + } + +// --------------------------------------------------------- +// CUniClientMtm::BuildAddresseeListL +// --------------------------------------------------------- +// +void CUniClientMtm::BuildAddresseeListL( + const CDesCArray& aArray, TMsvRecipientType aValue ) + { + + TInt size; + size = aArray.Count(); + for ( TInt i=0; i < size; i++ ) + { + iAddresseeList->AppendL( aValue, aArray[i] ); + } + } + +// --------------------------------------------------------- +// CUniClientMtm::AttachmentsSizeL +// --------------------------------------------------------- +// +TInt32 CUniClientMtm::AttachmentsSizeL() + { + CMsvStore* store = iMsvEntry->ReadStoreL(); + CleanupStack::PushL( store ); + TInt32 attaSize = AttachmentsSizeL( *store ); + CleanupStack::PopAndDestroy( store ); + return attaSize; + } + +// --------------------------------------------------------- +// CUniClientMtm::AttachmentsSizeL +// --------------------------------------------------------- +// +TInt32 CUniClientMtm::AttachmentsSizeL( CMsvStore& aStore ) + { + TInt32 size = 0; + + MMsvAttachmentManager& attachMan = aStore.AttachmentManagerL(); + TInt numAttachments = attachMan.AttachmentCount(); + + for ( TInt i = 0; i < numAttachments; i++ ) + { + CMsvAttachment* attachmentInfo = attachMan.GetAttachmentInfoL( i ); + CleanupStack::PushL( attachmentInfo ); + + CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL(); + CleanupStack::PushL( mimeHeaders ); + + mimeHeaders->RestoreL( *attachmentInfo ); + + RFile attaFile = attachMan.GetAttachmentFileL( i ); + CleanupClosePushL( attaFile ); + TInt fileSize = 0; + + // If we cannot access the file, we are in trouble + User::LeaveIfError( attaFile.Size( fileSize ) ); + + // This adds up mime header size + actual attachment binary data + size += mimeHeaders->Size() + fileSize; + + CleanupStack::PopAndDestroy( &attaFile ); + CleanupStack::PopAndDestroy( mimeHeaders ); + CleanupStack::PopAndDestroy( attachmentInfo ); + } + + return size; + } + +// --------------------------------------------------------- +// CUniClientMtm::FindInRecipientL +// --------------------------------------------------------- +// +TBool CUniClientMtm::FindInRecipientL( + const TDesC& aTextToFind, + TMsvPartList aPartlist, + const CDesCArray& aRecipients, + CMsvFindText& aFindText ) + { + TInt count = aRecipients.Count(); + TBool found = EFalse; + for (TInt i=0; i < count; i++ ) + { + // Check alias and real address parts + // separately. Otherwise separator character could + // spoil the check. + if ( aFindText.FindTextL( aTextToFind, + TMmsGenUtils::Alias( aRecipients[i] ), aPartlist ) ) + { + found = ETrue; + break; + } + else if ( aFindText.FindTextL( aTextToFind, + TMmsGenUtils::PureAddress( aRecipients[i] ), aPartlist ) ) + { + found = ETrue; + break; + } + } + return found; + } + +// --------------------------------------------------------- +// CUniClientMtm::AddFilePathAttachmentL +// --------------------------------------------------------- +// +void CUniClientMtm::AddFilePathAttachmentL( + const TDesC& aFilePath, + const TDesC8& aMimeType, + CMsvAttachment::TMsvAttachmentType aType, + TRequestStatus& aStatus, + const TUint aCharacterSet /* = 0 */ ) + { + __ASSERT_DEBUG( aType != CMsvAttachment::EMsvMessageEntry, + User::Invariant() ); + + TEntry fileEntry; + User::LeaveIfError( Session().FileSession().Entry( aFilePath, fileEntry ) ); + + if( !iAttaWaiter ) + { + iAttaWaiter = CMmsAttachmentWaiter::NewL(); + } + + // store must be the first item allocated because it is the last one to be popped + CMsvStore* store = iMsvEntry->EditStoreL(); + CleanupStack::PushL( store ); + MMsvAttachmentManager& manager = store->AttachmentManagerL(); + + CMsvAttachment* attachment = CMsvAttachment::NewL( aType ); + CleanupStack::PushL( attachment ); + + TInt size = InitializeAttachmentL( + manager, + *attachment, + aFilePath, + aMimeType, + fileEntry.iSize, + aCharacterSet ); + + // now we know how much disk space we need + if ( aType == CMsvAttachment::EMsvFile ) + { + size += attachment->Size(); + } + + // Check that sufficient disk space available + if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( + &Session().FileSession(), + size, + iMessageDrive ) ) + { + // we use standard error code here + User::Leave( KErrDiskFull ); + } + + // attachment is initialised, pass to the attachment manager + if ( iAttaWaiter->IsActive() ) + { + // can't start an active operation because already active + User::Leave( KErrInUse ); + } + switch( aType ) + { + case CMsvAttachment::EMsvLinkedFile: + manager.AddLinkedAttachmentL( aFilePath, attachment, + iAttaWaiter->iStatus ); + break; + default: // CMsvAttachment::EMsvFile + manager.AddAttachmentL( aFilePath, attachment, + iAttaWaiter->iStatus ); + break; + } + + CleanupStack::Pop( attachment); //ownership passed to manager + // We cannot start waiting before we know that the function we are waiting for + // did not leave. If we become active, and the function leaves, we are in trouble + iAttaWaiter->StartWaitingL( aStatus, store, &manager ); + CleanupStack::Pop( store ); // ownership passed to iAttaWaiter + } + +// --------------------------------------------------------- +// CUniClientMtm::RecognizeCharSetL +// --------------------------------------------------------- +// +TUint CUniClientMtm::RecognizeCharSetL( RFile& aFile ) + { + TUint charSet = CMsgTextUtils::RecognizeCharSetL( Session().FileSession(), aFile ); + if ( !iTextUtils ) + { + iTextUtils = CMsgTextUtils::NewL( Session().FileSession() ); + } + return iTextUtils->CharconvIdToMibIdL( charSet ); + } + +// --------------------------------------------------------- +// CUniClientMtm::InitializeAttachmentL +// --------------------------------------------------------- +// +TInt CUniClientMtm::InitializeAttachmentL( + MMsvAttachmentManager& aManager, + CMsvAttachment& aAttachment, + const TDesC& aFileName, + const TDesC8& aMimeType, + TInt aFileSize, + TUint aCharset ) + { + CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL(); + CleanupStack::PushL( mimeHeaders ); + + aAttachment.SetSize( aFileSize ); + + // set the mime-type if provided + if ( aMimeType.Length() > 0 ) + { + aAttachment.SetMimeTypeL( aMimeType ); + TInt position = aMimeType.Find( KMmsSlash8 ); + if ( position > 0 ) + { + mimeHeaders->SetContentTypeL( aMimeType.Left( position ) ); + } + if ( position < aMimeType.Length() - 1 ) + { + mimeHeaders->SetContentSubTypeL( aMimeType.Mid( position + 1 ) ); + } + } + + TParsePtrC parse( aFileName ); + mimeHeaders->SetSuggestedFilenameL( parse.NameAndExt() ); + HBufC* contentLocation = CMsgTextUtils::GetSafeAttachmentNameLC( + aManager, + parse.NameAndExt(), + aAttachment.Id(), + ETrue ); + mimeHeaders->SetContentLocationL( *contentLocation ); + CleanupStack::PopAndDestroy( contentLocation ); + + mimeHeaders->SetMimeCharset( aCharset ); + + TInt size = KMmsIndexEntryExtra + mimeHeaders->Size(); + mimeHeaders->StoreL( aAttachment ); + + // mime headers have been streamed to CMsvAttachment, they can go now + CleanupStack::PopAndDestroy( mimeHeaders ); + return size; + } + +// --------------------------------------------------------- +// CUniClientMtm::SetContentLocationForConvertedAttL +// --------------------------------------------------------- +// +void CUniClientMtm::SetContentLocationForConvertedAttL( + CMsvStore& aStore, + TMsvAttachmentId aAttaId, + const TDesC& aFileName ) + { + MMsvAttachmentManager& manager = aStore.AttachmentManagerL(); + CMsvAttachment* attachment = manager.GetAttachmentInfoL( aAttaId ); + CleanupStack::PushL( attachment ); + + CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL(); + CleanupStack::PushL( mimeHeaders ); + mimeHeaders->RestoreL( *attachment ); + + TParsePtrC parse( aFileName ); + HBufC* contentLocation = CMsgTextUtils::GetSafeAttachmentNameLC( + manager, + parse.NameAndExt(), + aAttaId, + ETrue ); + mimeHeaders->SetContentLocationL( *contentLocation ); + CleanupStack::PopAndDestroy( contentLocation ); + + mimeHeaders->StoreL( *attachment ); + // Mime headers have been streamed into the attachment info + CleanupStack::PopAndDestroy( mimeHeaders ); + + MMsvAttachmentManagerSync& syncManager = aStore.AttachmentManagerExtensionsL(); + + syncManager.ModifyAttachmentInfoL( attachment ); + // Ownership transferred + CleanupStack::Pop( attachment ); + } + + +// End of File