--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/htiui/HtiServicePlugins/HtiMessagesServicePlugin/src/MessageMgmntHandler.cpp Tue Feb 02 00:17:27 2010 +0200
@@ -0,0 +1,1879 @@
+/*
+* Copyright (c) 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: Functional implementation of HtiMessagesServicePlugin service
+*
+*/
+
+
+// INCLUDE FILES
+#include "HtiMessagesServicePlugin.h"
+#include "MessageMgmntHandler.h"
+
+#include <HtiDispatcherInterface.h>
+#include <HTILogging.h>
+#include <mtclreg.h>
+#include <smscmds.h>
+#include <smtcmtm.h>
+#include <smuthdr.h>
+#include <smsclnt.h>
+#include <utf.h>
+#include <mmsclient.h>
+#include <mmsconst.h>
+#include <miutset.h>
+#include <irmsgtypeuid.h>
+#include <btmsgtypeuid.h>
+#include <biouids.h>
+#include <apgcli.h>
+#include <apmstd.h>
+#include <bautils.h>
+#include <obexclientmtm.h>
+#include <cmsvmimeheaders.h>
+#include <mmsvattachmentmanager.h>
+
+// CONSTANTS
+_LIT8( KErrorMissingCommand, "Command was not given - message was empty" );
+_LIT8( KErrorUnrecognizedCommand, "Unrecognized command" );
+_LIT8( KErrorInvalidParameters, "Invalid command parameters");
+_LIT8( KErrorTooLongSmsBody, "Too long SMS body" );
+_LIT8( KErrorInvalidId, "Invalid SMS id parameter" );
+_LIT8( KErrorInvalidFolder, "Invalid folder parameter" );
+_LIT8( KErrorItemNotFound, "Item not found" );
+_LIT8( KErrorFailedDelete, "Failed to delete item" );
+_LIT8( KErrorNotSupported, "Not supported" );
+_LIT8( KErrorSmsSettingNotDefined, "SMS settings not defined" );
+_LIT8( KErrorMmsSettingNotDefined, "MMS settings not defined" );
+_LIT8( KErrorMailboxNotDefined, "Mailbox not defined" );
+_LIT8( KErrorMsgTypeNotFound, "Message type module not found" );
+_LIT8( KErrorMsgStoreOpenFailed, "Could not open message store" );
+_LIT8( KErrorRfsConnectFailed, "Could not connect to file server session" );
+_LIT8( KErrorAttachmentNotFound, "Attachment not found" );
+_LIT8( KErrorInvalidFolderForSmartMsg, "Only inbox allowed for smart messages" );
+
+const static TInt KAddSmsCmdMinLength = 7;
+const static TInt KAddMmsOrEmailCmdMinLength = 8;
+const static TInt KAddObexMsgCmdMinLength = 6;
+const static TInt KAddSmartMsgCmdMinLength = 11;
+const static TInt KAddAudioCmdMinLength = 10;
+
+// ----------------------------------------------------------------------------
+CMessageMgmntHandler* CMessageMgmntHandler::NewL()
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::NewL" );
+ CMessageMgmntHandler* self = new (ELeave) CMessageMgmntHandler();
+ CleanupStack::PushL ( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+ HTI_LOG_FUNC_OUT( "CMessageMgmntHandler::NewL: Done" );
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+CMessageMgmntHandler::CMessageMgmntHandler()
+ {
+ }
+
+// ----------------------------------------------------------------------------
+CMessageMgmntHandler::~CMessageMgmntHandler()
+ {
+ delete iMtmReg;
+ delete iSession;
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::ConstructL()
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::ConstructL" );
+ iSession = CMsvSession::OpenSyncL( *this );
+ iMtmReg = CClientMtmRegistry::NewL( *iSession );
+ HTI_LOG_FUNC_OUT( "CMessageMgmntHandler::ConstructL: Done" );
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::SetDispatcher( MHtiDispatcher* aDispatcher )
+ {
+ iDispatcher = aDispatcher;
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::ProcessMessageL( const TDesC8& aMessage,
+ THtiMessagePriority /*aPriority*/ )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::ProcessMessageL" );
+ HTI_LOG_FORMAT( "Msg length: %d", aMessage.Length() );
+
+ if ( aMessage.Length() == 0 )
+ {
+ SendErrorMessageL( KErrArgument, KErrorMissingCommand );
+ return;
+ }
+
+ switch ( aMessage[0] )
+ {
+ case CHtiMessagesServicePlugin::EAddSms:
+ HTI_LOG_TEXT( "Add SMS" );
+ HandleCreateSmsL( aMessage.Right( aMessage.Length() - 1 ) );
+ break;
+
+ case CHtiMessagesServicePlugin::EAddMms:
+ case CHtiMessagesServicePlugin::EAddAudioMsg: // special MMS sub type
+ HTI_LOG_TEXT( "Add MMS" );
+ HandleCreateMmsL( aMessage );
+ break;
+
+ case CHtiMessagesServicePlugin::EAddEmail:
+ HTI_LOG_TEXT( "Add Email" );
+ HandleCreateEmailL( aMessage );
+ break;
+
+ case CHtiMessagesServicePlugin::EAddIrMsg:
+ HTI_LOG_TEXT( "Add IR msg" );
+ HandleCreateObexMsgL( aMessage.Right( aMessage.Length() - 1 ),
+ TUid::Uid( KUidMsgTypeIrTInt32 ),
+ KUidMsgTypeIrUID );
+ break;
+
+ case CHtiMessagesServicePlugin::EAddBtMsg:
+ HTI_LOG_TEXT( "Add BT msg" );
+ HandleCreateObexMsgL( aMessage.Right( aMessage.Length() - 1 ),
+ TUid::Uid( KUidMsgTypeBtTInt32 ),
+ KUidMsgTypeBt );
+ break;
+
+ case CHtiMessagesServicePlugin::EAddSmartMsg:
+ HTI_LOG_TEXT( "Add smart msg" );
+ HandleCreateSmartMsgL( aMessage.Right( aMessage.Length() - 1 ) );
+ break;
+
+ case CHtiMessagesServicePlugin::EDeleteMessage:
+ HTI_LOG_TEXT( "Delete message" );
+ HandleDeleteMessageL( aMessage.Right( aMessage.Length() - 1 ) );
+ break;
+
+ case CHtiMessagesServicePlugin::EDeleteFolderContent:
+ HTI_LOG_TEXT( "Delete messages" );
+ HandleDeleteMessagesL( aMessage.Right( aMessage.Length() - 1 ) );
+ break;
+
+ default:
+ HTI_LOG_TEXT( "Unknown command" );
+ SendErrorMessageL( KErrUnknown, KErrorUnrecognizedCommand );
+ break;
+ }
+
+ HTI_LOG_FUNC_OUT( "CMessageMgmntHandler::ProcessMessageL: Done" );
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleCreateSmsL( const TDesC8& aData )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleSmsImportFuncL" );
+
+ if ( ValidateAddSmsCommand( aData ) )
+ {
+ TInt position( 0 );
+ HBufC16* fromTo = ExtractDesLC( aData, position, 1 );
+ HBufC16* description = ExtractDesLC( aData, position, 1 );
+ HBufC16* body = ExtractDesLC( aData, position, 2 );
+ TBool isNew = (TBool)aData[position];
+ TBool isUnread = (TBool)aData[position+1];
+ TFolder folder = (TFolder)aData[position+2];
+
+ CSmsClientMtm* smsMtm = NULL;
+ TRAPD( err, smsMtm = ( CSmsClientMtm* )iMtmReg->NewMtmL(
+ KUidMsgTypeSMS ) );
+ if ( err || !smsMtm )
+ {
+ HTI_LOG_TEXT( "SMS message type module not found" );
+ SendErrorMessageL( KErrNotFound, KErrorMsgTypeNotFound );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ CleanupStack::PushL( smsMtm );
+
+ CMsvEntry* entry = CMsvEntry::NewL( *iSession,
+ KMsvGlobalInBoxIndexEntryId,
+ TMsvSelectionOrdering() );
+ CleanupStack::PushL( entry );
+
+ // get the default service
+ TMsvId defaultServiceId = 0;
+ TRAP( err, defaultServiceId = smsMtm->DefaultServiceL() );
+ if ( err )
+ {
+ HTI_LOG_FORMAT( "Could not get default service, err: %d", err );
+ SendErrorMessageL( err, KErrorSmsSettingNotDefined );
+ CleanupStack::PopAndDestroy( entry );
+ CleanupStack::PopAndDestroy( smsMtm );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+
+ // map the folder parameter to folder id
+ TMsvId folderId = KMsvGlobalInBoxIndexEntryId;
+ TRAP( err, folderId = MapFolderToIdL( folder ) );
+ if ( err )
+ {
+ HTI_LOG_FORMAT( "Invalid folder: %d", folder );
+ SendErrorMessageL( err, KErrorInvalidFolder );
+ CleanupStack::PopAndDestroy( entry );
+ CleanupStack::PopAndDestroy( smsMtm );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ entry->SetEntryL( folderId );
+
+ // mtm takes ownership of entry context
+ smsMtm->SetCurrentEntryL( entry );
+ CleanupStack::Pop( entry );
+
+ // create a new message
+ smsMtm->CreateMessageL( defaultServiceId );
+
+ if ( folder == EInbox )
+ {
+ CSmsHeader* smsHeader = &( smsMtm->SmsHeader() );
+ delete smsHeader;
+ smsHeader = NULL;
+ smsHeader = CSmsHeader::NewL( CSmsPDU::ESmsDeliver, smsMtm->Body() );
+ smsHeader->SetFromAddressL( fromTo->Des() );
+ }
+ else
+ {
+ smsMtm->AddAddresseeL( fromTo->Des() );
+
+ // set delivery settings
+ CSmsSettings* sendOptions = CSmsSettings::NewL();
+ CleanupStack::PushL( sendOptions );
+ sendOptions->CopyL( smsMtm->ServiceSettings() );
+ sendOptions->SetDelivery( ESmsDeliveryImmediately );
+
+ CSmsHeader* smsHeader = &( smsMtm->SmsHeader() );
+ smsHeader->SetSmsSettingsL( *sendOptions );
+ CleanupStack::PopAndDestroy( sendOptions );
+ }
+
+
+
+ // set body
+ smsMtm->Body().Reset();
+ smsMtm->Body().InsertL( 0, *body );
+
+ // save the message
+ smsMtm->SaveMessageL();
+
+ // get the entry of the message
+ TMsvEntry tentry = smsMtm->Entry().Entry();
+
+ // set the details field
+ tentry.iDetails.Set( fromTo->Des() );
+
+ // set the description field if it is given.
+ // (with no description the beginning of the message body
+ // is used as a description)
+ if ( description->Length() > 0 )
+ {
+ tentry.iDescription.Set( description->Des() );
+ }
+
+ // final fine tuning
+ tentry.SetAttachment( EFalse );
+ tentry.iDate.UniversalTime();
+ tentry.SetVisible( ETrue );
+ tentry.SetInPreparation( EFalse );
+ tentry.SetUnread( isUnread );
+ tentry.SetNew( isNew );
+ tentry.SetComplete( ETrue );
+ tentry.SetSendingState( KMsvSendStateWaiting );
+ tentry.iServiceId = defaultServiceId;
+ tentry.iRelatedId = 0;
+ if ( folder == EInbox )
+ {
+ tentry.SetReadOnly( ETrue );
+ }
+
+ smsMtm->Entry().ChangeL( tentry );
+
+ // send the message, if it is in outbox
+ if ( folder == EOutbox )
+ {
+ CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
+ CleanupStack::PushL( selection );
+ selection->AppendL( tentry.Id() );
+
+ TBuf8<1> dummyParameter;
+ CMsvOperationWait* waiter = CMsvOperationWait::NewLC();
+ CMsvOperation* op = smsMtm->InvokeAsyncFunctionL(
+ ESmsMtmCommandScheduleCopy, *selection,
+ dummyParameter, waiter->iStatus );
+ CleanupStack::PushL( op );
+ waiter->Start();
+ CActiveScheduler::Start();
+ CleanupStack::PopAndDestroy( op );
+ CleanupStack::PopAndDestroy( waiter );
+ CleanupStack::PopAndDestroy( selection );
+ }
+
+ CleanupStack::PopAndDestroy( smsMtm );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+
+ TInt32 id = tentry.Id();
+ TBuf8<8> idStr;
+ idStr.Copy( ( TUint8* )( &id ), sizeof( id ) );
+ SendOkMsgL( idStr );
+ }
+
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleSmsImportFuncL: Done");
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleCreateMmsL( const TDesC8& aData )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleCreateMmsL" );
+
+ if ( !ValidateAddMmsOrAddEmailCommand( aData ) )
+ {
+ // Error message has been sent from validation method.
+ return;
+ }
+
+ // parse the parameters
+ TInt position( 0 );
+ TInt cmdCode = aData[position];
+ position++;
+ HBufC16* fromTo = ExtractDesLC( aData, position, 1 );
+ HBufC16* description = ExtractDesLC( aData, position, 1 );
+ HBufC8* body = NULL;
+ if ( cmdCode == CHtiMessagesServicePlugin::EAddMms )
+ {
+ body = ExtractDes8LC( aData, position, 2 );
+ }
+ else // Audio msg does not have body text
+ {
+ body = HBufC8::NewLC( 0 );
+ }
+ HBufC16* attPath = ExtractDesLC( aData, position, 1 );
+ TBool isNew = (TBool)aData[position];
+ TBool isUnread = (TBool)aData[position+1];
+ TFolder folder = (TFolder)aData[position+2];
+
+ HTI_LOG_TEXT( "Creating MMS Client MTM" );
+ CMmsClientMtm* mmsMtm = NULL;
+ TRAPD( err , mmsMtm = ( CMmsClientMtm* )iMtmReg->NewMtmL(
+ KUidMsgTypeMultimedia ) );
+ if ( err || !mmsMtm )
+ {
+ HTI_LOG_TEXT( "MMS message type module not found" );
+ SendErrorMessageL( KErrNotFound, KErrorMsgTypeNotFound );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ CleanupStack::PushL( mmsMtm );
+
+ HTI_LOG_TEXT( "Creating MMS Client MTM" );
+ CMsvEntry* entry = CMsvEntry::NewL( *iSession,
+ KMsvGlobalInBoxIndexEntryId,
+ TMsvSelectionOrdering() );
+ CleanupStack::PushL( entry );
+
+ // get the default service
+ TMsvId defaultServiceId = 0;
+ TRAP( err, defaultServiceId = mmsMtm->DefaultServiceL() );
+ if ( err )
+ {
+ HTI_LOG_FORMAT( "Could not get default service, err: %d", err );
+ SendErrorMessageL( err, KErrorMmsSettingNotDefined );
+ CleanupStack::PopAndDestroy( entry );
+ CleanupStack::PopAndDestroy( mmsMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+
+ // map the folder parameter to folder id
+ TMsvId folderId = KMsvGlobalInBoxIndexEntryId;
+ TRAP( err, folderId = MapFolderToIdL( folder ) );
+ if ( err )
+ {
+ HTI_LOG_FORMAT( "Invalid folder: %d", folder );
+ SendErrorMessageL( err, KErrorInvalidFolder );
+ CleanupStack::PopAndDestroy( entry );
+ CleanupStack::PopAndDestroy( mmsMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ entry->SetEntryL( folderId );
+
+ // mtm takes ownership of entry context
+ mmsMtm->SetCurrentEntryL( entry );
+ CleanupStack::Pop( entry );
+
+ HTI_LOG_TEXT( "Creating MMS..." );
+ mmsMtm->CreateMessageL( defaultServiceId );
+ mmsMtm->SetMessageClass( EMmsClassPersonal );
+ mmsMtm->SetExpiryInterval( 86400 );
+ mmsMtm->SetDeliveryTimeInterval( 0 );
+ mmsMtm->SetMessagePriority( EMmsPriorityNormal );
+ mmsMtm->SetSenderVisibility( EMmsMaximumSenderVisibility );
+ mmsMtm->SetDeliveryReport( EMmsDeliveryReportNo );
+ mmsMtm->SetReadReply( EMmsReadReplyYes );
+
+ if ( description->Length() > 0 )
+ {
+ mmsMtm->SetSubjectL( description->Des() );
+ }
+
+ if ( folder == EInbox )
+ {
+ mmsMtm->SetSenderL( fromTo->Des() );
+ }
+ else
+ {
+ mmsMtm->AddAddresseeL( fromTo->Des() );
+ }
+
+ // get an access to the message store
+ HTI_LOG_TEXT( "Getting message store..." );
+ CMsvStore* store = NULL;
+ TRAP( err, store = entry->EditStoreL() );
+ if ( err )
+ {
+ HTI_LOG_FORMAT( "Could not get access to message store, err: %d", err );
+ SendErrorMessageL( err, KErrorMsgStoreOpenFailed );
+ CleanupStack::PopAndDestroy( mmsMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ CleanupStack::PushL( store );
+
+ MMsvAttachmentManager& attachMan = store->AttachmentManagerL();
+ // set body attachment only for normal MMS - audio message doesn't have body
+ if ( cmdCode == CHtiMessagesServicePlugin::EAddMms )
+ {
+ // Set the message body as attachment
+ // Use UTF-8 as charset because MMS created with MMS editor seems to
+ // save text attachments also as UTF-8.
+ HTI_LOG_TEXT( "Setting body..." );
+ CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL();
+ CleanupStack::PushL( mimeHeaders );
+ mimeHeaders->SetContentTypeL( _L8( "text" ) );
+ mimeHeaders->SetContentSubTypeL( _L8( "plain" ) );
+ mimeHeaders->SetMimeCharset( KMmsUtf8 );
+ mimeHeaders->SetSuggestedFilenameL( _L( "body.txt" ) );
+
+ // ownership of bodyAttachment will be transferred
+ CMsvAttachment* bodyAttachment = CMsvAttachment::NewL(
+ CMsvAttachment::EMsvFile );
+ CleanupStack::PushL( bodyAttachment );
+ bodyAttachment->SetAttachmentNameL( _L( "body.txt" ) );
+ bodyAttachment->SetMimeTypeL( _L8( "text/plain" ) );
+ mimeHeaders->StoreL( *bodyAttachment );
+
+ RFile textFile;
+ CleanupClosePushL( textFile );
+ CWaiter* waiter = CWaiter::NewLC();
+ attachMan.CreateAttachmentL( _L( "body.txt" ), textFile,
+ bodyAttachment, waiter->iStatus );
+ waiter->StartAndWait();
+ CleanupStack::PopAndDestroy( waiter );
+
+ // write the UTF-8 body data to attachment file
+ textFile.Write( *body );
+ CleanupStack::PopAndDestroy(); // textFile
+ CleanupStack::Pop( bodyAttachment ); // ownership transfered
+ CleanupStack::PopAndDestroy( mimeHeaders );
+ }
+
+ // get the entry of the message
+ TMsvEntry tentry = mmsMtm->Entry().Entry();
+
+ // set the details field
+ tentry.iDetails.Set( *fromTo );
+
+ // set the description field
+ if ( description->Length() > 0 )
+ {
+ tentry.iDescription.Set( description->Left( KMmsMaxDescription ) );
+ }
+ else
+ {
+ TBuf<KMmsMaxDescription> descr;
+ CnvUtfConverter::ConvertToUnicodeFromUtf8( descr, *body );
+ tentry.iDescription.Set( descr );
+ }
+
+ // if this is audio message, set the bio type uid
+ if ( cmdCode == CHtiMessagesServicePlugin::EAddAudioMsg )
+ {
+ tentry.iBioType = KUidMsgSubTypeMmsAudioMsg.iUid;
+ }
+
+ // handle attachment
+ TBool attachmentsExist = EFalse;
+ if ( attPath->Length() > 0 )
+ {
+ HTI_LOG_TEXT( "Handling attachment..." );
+ // check that attachment exists
+ RFs fsSession;
+ if ( fsSession.Connect() != KErrNone )
+ {
+ HTI_LOG_FORMAT( "Error in connecting to file server session: %d", err );
+ SendErrorMessageL( KErrCouldNotConnect, KErrorRfsConnectFailed );
+ CleanupStack::PopAndDestroy( store );
+ CleanupStack::PopAndDestroy( mmsMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+
+ TBool fileExists = BaflUtils::FileExists( fsSession, attPath->Des() );
+ fsSession.Close();
+ if ( !fileExists )
+ {
+ HTI_LOG_TEXT( "Attachment file not found" );
+ SendErrorMessageL( KErrPathNotFound, KErrorAttachmentNotFound );
+ store->RevertL();
+ CleanupStack::PopAndDestroy( store );
+ CleanupStack::PopAndDestroy( mmsMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ else
+ {
+ // save the attachment
+ TParse parser;
+ parser.Set( *attPath, NULL, NULL);
+ TFileName shortFileName = parser.NameAndExt();
+
+ // get the mime type
+ RApaLsSession ls;
+ User::LeaveIfError( ls.Connect() );
+ CleanupClosePushL( ls );
+ TUid appUid;
+ TDataType dataType;
+ ls.AppForDocument( *attPath, appUid, dataType );
+ CleanupStack::PopAndDestroy(); // ls
+ TPtrC8 mimeType = dataType.Des8();
+
+ // attachment settings
+ // ownership of attachment will be transferred
+ CMsvAttachment* attachment = CMsvAttachment::NewL(
+ CMsvAttachment::EMsvFile );
+ attachment->SetAttachmentNameL( shortFileName );
+ attachment->SetMimeTypeL( mimeType );
+
+ // save
+ CWaiter* waiter = CWaiter::NewLC();
+ attachMan.AddAttachmentL( *attPath, attachment, waiter->iStatus );
+ waiter->StartAndWait();
+ CleanupStack::PopAndDestroy( waiter );
+ attachmentsExist = ETrue;
+ }
+ }
+
+ // save the changes made to the message store
+ store->CommitL();
+ CleanupStack::PopAndDestroy( store );
+
+ // save the message
+ mmsMtm->SaveMessageL();
+
+ // final fine tuning
+ tentry.SetAttachment( attachmentsExist );
+ tentry.iDate.UniversalTime();
+ tentry.SetVisible( ETrue );
+ tentry.SetInPreparation( EFalse );
+ if ( folder == EDrafts )
+ {
+ tentry.SetReadOnly( EFalse );
+ }
+ else
+ {
+ tentry.SetReadOnly( ETrue );
+ }
+ tentry.SetUnread( isUnread );
+ tentry.SetNew( isNew );
+ tentry.SetComplete( ETrue );
+ tentry.SetSendingState( KMsvSendStateWaiting );
+ tentry.iServiceId = defaultServiceId;
+ tentry.iRelatedId = 0;
+ tentry.iMtmData1 = KMmsMessageMRetrieveConf | KMmsMessageMobileTerminated;
+
+ mmsMtm->Entry().ChangeL( tentry );
+
+ HTI_LOG_TEXT( "MMS created and ready" );
+
+ // send the message, if it is in outbox
+ if ( folder == EOutbox )
+ {
+ HTI_LOG_TEXT( "MMS is in Outbox, sending it..." );
+
+ CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
+ CleanupStack::PushL( selection );
+ selection->AppendL( tentry.Id() );
+
+ CMsvOperationWait* waiter = CMsvOperationWait::NewLC();
+ CMsvOperation* op = mmsMtm->SendL( *selection,
+ waiter->iStatus,
+ tentry.iDate );
+ CleanupStack::PushL( op );
+ waiter->Start();
+ CActiveScheduler::Start();
+ CleanupStack::PopAndDestroy( op );
+ CleanupStack::PopAndDestroy( waiter );
+ CleanupStack::PopAndDestroy( selection );
+ }
+
+ HTI_LOG_TEXT( "Cleaning up" );
+ CleanupStack::PopAndDestroy( mmsMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+
+ // send the message id back
+ TInt32 id = tentry.Id();
+ TBuf8<8> idStr;
+ idStr.Copy( ( TUint8* )( &id ), sizeof( id ) );
+ SendOkMsgL( idStr );
+
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleCreateMmsL: Done");
+ }
+
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleCreateEmailL( const TDesC8& aData )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleCreateEmailL" );
+
+ if ( ValidateAddMmsOrAddEmailCommand( aData ) )
+ {
+ // parse the parameters
+ TInt position( 1 ); // position 0 is command code
+ HBufC16* fromTo = ExtractDesLC( aData, position, 1 );
+ HBufC16* description = ExtractDesLC( aData, position, 1 );
+ HBufC16* body = ExtractDesLC( aData, position, 2 );
+ HBufC16* attPath = ExtractDesLC( aData, position, 1 );
+ TBool isNew = (TBool)aData[position];
+ TBool isUnread = (TBool)aData[position+1];
+ TFolder folder = (TFolder)aData[position+2];
+
+ HTI_LOG_TEXT( "Creating SMTP Client MTM" );
+ CSmtpClientMtm* smtpMtm = NULL;
+ TRAPD( err, smtpMtm = ( CSmtpClientMtm* )iMtmReg->NewMtmL(
+ KUidMsgTypeSMTP ) );
+ if ( err || !smtpMtm )
+ {
+ HTI_LOG_TEXT( "SMTP message type module not found" );
+ SendErrorMessageL( KErrNotFound, KErrorMsgTypeNotFound );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ CleanupStack::PushL( smtpMtm );
+
+ HTI_LOG_TEXT( "Creating a new CMsvEntry" );
+ CMsvEntry* entry = CMsvEntry::NewL( *iSession,
+ KMsvGlobalInBoxIndexEntryId,
+ TMsvSelectionOrdering() );
+ CleanupStack::PushL( entry );
+
+ // get the default service
+ HTI_LOG_TEXT( "Getting the default service" );
+ TMsvId defaultServiceId = 0;
+ TRAP( err, defaultServiceId = smtpMtm->DefaultServiceL() );
+ if ( err )
+ {
+ HTI_LOG_FORMAT( "Could not get default service, err: %d", err );
+ SendErrorMessageL( err, KErrorMailboxNotDefined );
+ CleanupStack::PopAndDestroy( entry );
+ CleanupStack::PopAndDestroy( smtpMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+
+ // map the folder parameter to folder id
+ HTI_LOG_TEXT( "Mapping the folder parameter to folder id" );
+ TMsvId folderId = KMsvGlobalInBoxIndexEntryId;
+ TRAP( err, folderId = MapFolderToIdL( folder ) );
+ if ( err )
+ {
+ HTI_LOG_FORMAT( "Invalid folder: %d", folder );
+ SendErrorMessageL( err, KErrorInvalidFolder );
+ CleanupStack::PopAndDestroy( entry );
+ CleanupStack::PopAndDestroy( smtpMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ entry->SetEntryL( folderId );
+
+ // mtm takes ownership of entry context
+ smtpMtm->SetCurrentEntryL( entry );
+ CleanupStack::Pop( entry );
+
+ // create a message and set subject and body
+ smtpMtm->CreateMessageL( defaultServiceId );
+ smtpMtm->SetSubjectL( description->Des() );
+ smtpMtm->Body().Reset();
+ smtpMtm->Body().InsertL( 0, body->Des() );
+
+ // get the entry of the message
+ TMsvEntry tentry = smtpMtm->Entry().Entry();
+
+ // add addressee
+ smtpMtm->AddAddresseeL( fromTo->Des() );
+ tentry.iDetails.Set( fromTo->Des() );
+
+ // If creating to Inbox use other than KUidMsgTypeSMTP so that the
+ // mail displays "from" field and not "to" field.
+ if ( folder == EInbox )
+ {
+ tentry.iMtm = KUidMsgTypeIMAP4;
+ }
+
+ // set the description field same as the message subject
+ tentry.iDescription.Set( description->Des() );
+
+ // save the changes done above
+ smtpMtm->Entry().ChangeL( tentry );
+
+ // get an access to the message store
+ CMsvStore* store = entry->EditStoreL();
+ CleanupStack::PushL( store );
+ CImHeader* header = CImHeader::NewLC();
+ header->RestoreL( *store );
+ TUint charset = header->Charset();
+ CleanupStack::PopAndDestroy( header );
+ CleanupStack::PopAndDestroy( store );
+
+ // handle attachment
+ TBool attachmentsExist = EFalse;
+ if ( attPath->Length() > 0 )
+ {
+ // check that attachment exists
+ RFs fsSession;
+ if ( fsSession.Connect() != KErrNone )
+ {
+ HTI_LOG_FORMAT( "Error in connecting to file server session: %d", err );
+ SendErrorMessageL( KErrCouldNotConnect, KErrorRfsConnectFailed );
+ CleanupStack::PopAndDestroy( smtpMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ CleanupClosePushL( fsSession );
+
+ TBool fileExists = BaflUtils::FileExists( fsSession, attPath->Des() );
+ if ( !fileExists )
+ {
+ HTI_LOG_TEXT( "Attachment file not found" );
+ SendErrorMessageL( KErrPathNotFound, KErrorAttachmentNotFound );
+ CleanupStack::PopAndDestroy(); // fsSession
+ CleanupStack::PopAndDestroy( smtpMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ else
+ {
+ // get the mime type
+ HTI_LOG_TEXT( "Getting the attachment's mime type" );
+ RApaLsSession ls;
+ User::LeaveIfError( ls.Connect() );
+ TUid appUid;
+ TDataType dataType;
+ ls.AppForDocument( *attPath, appUid, dataType );
+ TPtrC8 mimeType = dataType.Des8();
+
+ HTI_LOG_TEXT( "Adding the attachment" );
+ CWaiter* waiter = CWaiter::NewLC();
+ smtpMtm->AddAttachmentL( attPath->Des(), mimeType, charset,
+ waiter->iStatus );
+ waiter->StartAndWait();
+ CleanupStack::PopAndDestroy( waiter );
+ HTI_LOG_TEXT( "Attachment added succesfully" );
+
+ attachmentsExist = ETrue;
+ }
+
+ CleanupStack::PopAndDestroy(); // fsSession
+ }
+
+ // save the message
+ smtpMtm->SaveMessageL();
+
+ // final fine tuning
+ TMsvEmailEntry temailEntry = static_cast<TMsvEmailEntry>( tentry );
+ temailEntry.SetMessageFolderType( EFolderTypeUnknown );
+ temailEntry.SetDisconnectedOperation( ENoDisconnectedOperations );
+ temailEntry.SetEncrypted( EFalse );
+ temailEntry.SetSigned( EFalse );
+ temailEntry.SetVCard( EFalse );
+ temailEntry.SetVCalendar( EFalse );
+ temailEntry.SetReceipt( EFalse );
+ temailEntry.SetMHTMLEmail( EFalse );
+ temailEntry.SetBodyTextComplete( ETrue );
+ temailEntry.SetAttachment( attachmentsExist );
+ temailEntry.iDate.UniversalTime();
+ temailEntry.SetVisible( ETrue );
+ temailEntry.SetInPreparation( EFalse );
+ temailEntry.SetSendingState( KMsvSendStateWaiting );
+ temailEntry.SetUnread( isUnread );
+ temailEntry.SetNew( isNew );
+ temailEntry.SetComplete( ETrue );
+ temailEntry.iServiceId = defaultServiceId;
+ temailEntry.iRelatedId = 0;
+
+ smtpMtm->Entry().ChangeL( temailEntry );
+
+ // get an access to the message store
+ store = entry->EditStoreL();
+ CleanupStack::PushL( store );
+
+ // set email header info
+ header = CImHeader::NewLC();
+ header->RestoreL( *store );
+ header->SetSubjectL( description->Des() );
+ header->SetFromL( fromTo->Des() );
+ header->SetReceiptAddressL( fromTo->Des() );
+ header->StoreL( *store );
+ store->CommitL();
+ CleanupStack::PopAndDestroy( header );
+ CleanupStack::PopAndDestroy( store );
+
+ // send the message, if it is in outbox
+ if ( folder == EOutbox )
+ {
+ HTI_LOG_TEXT( "E-Mail was created in outbox, marking it to be sent on next connection" );
+
+ CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
+ CleanupStack::PushL( selection );
+ selection->AppendL( temailEntry.Id() );
+
+ TBuf8<1> dummyParameter;
+ CMsvOperationActiveSchedulerWait* waiter =
+ CMsvOperationActiveSchedulerWait::NewLC();
+ CMsvOperation* op = smtpMtm->InvokeAsyncFunctionL(
+ KSMTPMTMSendOnNextConnection, *selection,
+ dummyParameter, waiter->iStatus );
+ CleanupStack::PushL( op );
+ waiter->Start();
+ CleanupStack::PopAndDestroy( op );
+ CleanupStack::PopAndDestroy( waiter );
+ CleanupStack::PopAndDestroy( selection );
+ }
+
+ HTI_LOG_TEXT( "Cleaning up" );
+ CleanupStack::PopAndDestroy( smtpMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+
+ // send the message id back
+ TInt32 id = tentry.Id();
+ TBuf8<8> idStr;
+ idStr.Copy( ( TUint8* )( &id ), sizeof( id ) );
+ SendOkMsgL( idStr );
+ }
+
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleCreateEmailL: Done");
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleCreateObexMsgL( const TDesC8& aData,
+ TUid aMtmUid,
+ TUid aMsgTypeUid )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleCreateObexMsgL" );
+
+ if ( ValidateAddObexMsgCommand( aData ) )
+ {
+ // parse the parameters
+ TInt position( 0 );
+ HBufC16* fromTo = ExtractDesLC( aData, position, 1 );
+ HBufC16* description = ExtractDesLC( aData, position, 1 );
+ HBufC16* attPath = ExtractDesLC( aData, position, 1 );
+ TBool isNew = (TBool)aData[position];
+ TBool isUnread = (TBool)aData[position+1];
+ TFolder folder = (TFolder)aData[position+2];
+
+ // Adding Obex messages to the outbox is not allowed
+ if ( folder == EOutbox )
+ {
+ HTI_LOG_TEXT( "Outbox not supported with Obex messages" );
+ SendErrorMessageL( KErrNotSupported, KErrorNotSupported );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+
+ CObexClientMtm* obexMtm = NULL;
+ TRAPD( err, obexMtm = ( CObexClientMtm* )iMtmReg->NewMtmL( aMtmUid ) );
+ if ( err || !obexMtm )
+ {
+ HTI_LOG_TEXT( "Obex message type module not found" );
+ SendErrorMessageL( KErrNotFound, KErrorMsgTypeNotFound );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ CleanupStack::PushL( obexMtm );
+
+ CMsvEntry* entry = CMsvEntry::NewL( *iSession,
+ KMsvGlobalInBoxIndexEntryId,
+ TMsvSelectionOrdering() );
+ CleanupStack::PushL( entry );
+
+ TMsvId defaultServiceId = 0;
+
+ // map the folder parameter to folder id
+ TMsvId folderId = KMsvGlobalInBoxIndexEntryId;
+ TRAP( err, folderId = MapFolderToIdL( folder ) );
+ if ( err )
+ {
+ HTI_LOG_FORMAT( "Invalid folder: %d", folder );
+ SendErrorMessageL( err, KErrorInvalidFolder );
+ CleanupStack::PopAndDestroy( entry );
+ CleanupStack::PopAndDestroy( obexMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ entry->SetEntryL( folderId );
+
+ // mtm takes ownership of entry context
+ obexMtm->SetCurrentEntryL( entry );
+ CleanupStack::Pop( entry );
+
+ // create a new message
+ obexMtm->CreateMessageL( defaultServiceId );
+
+ // get the entry of the message
+ TMsvEntry tentry = obexMtm->Entry().Entry();
+
+ // set subject
+ obexMtm->SetSubjectL( description->Des() );
+ tentry.iDescription.Set( description->Des() );
+
+ // set body, must be empty for obex messages
+ obexMtm->Body().Reset();
+
+ // set the details field and
+ tentry.iDetails.Set( fromTo->Des() );
+
+ // set mtm
+ tentry.iMtm = aMtmUid;
+ tentry.iType = KUidMsvMessageEntry;
+ tentry.iServiceId = KMsvUnknownServiceIndexEntryId;
+
+ // save the changes done above
+ obexMtm->Entry().ChangeL( tentry );
+
+ // save the message
+ obexMtm->SaveMessageL();
+
+ // final fine tuning
+ tentry.iDate.HomeTime();
+ tentry.SetVisible( ETrue );
+ tentry.SetInPreparation( EFalse );
+ tentry.SetUnread( isUnread );
+ tentry.SetNew( isNew );
+ tentry.SetComplete( ETrue );
+ obexMtm->Entry().ChangeL( tentry );
+
+ // handle attachment
+ if ( attPath->Length() > 0 )
+ {
+ // check that attachment exists
+ RFs fsSession;
+ if ( fsSession.Connect() != KErrNone )
+ {
+ HTI_LOG_FORMAT( "Error in connecting to file server session: %d", err );
+ SendErrorMessageL( KErrCouldNotConnect, KErrorRfsConnectFailed );
+ CleanupStack::PopAndDestroy( obexMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+
+ TBool fileExists = BaflUtils::FileExists( fsSession, attPath->Des() );
+ fsSession.Close();
+ if ( !fileExists )
+ {
+ HTI_LOG_TEXT( "Attachment file not found" );
+ SendErrorMessageL( KErrPathNotFound, KErrorAttachmentNotFound );
+ CleanupStack::PopAndDestroy( obexMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ else
+ {
+ // create a new entry for the attachment
+ TMsvEntry attachTEntry;
+ attachTEntry.iType = KUidMsvAttachmentEntry;
+ attachTEntry.iServiceId = KMsvUnknownServiceIndexEntryId;
+ attachTEntry.iMtm = aMsgTypeUid; //save as bt message
+
+ entry->CreateL( attachTEntry );
+
+ CMsvEntry* attachEntry = iSession->GetEntryL( attachTEntry.Id() );
+ obexMtm->SetCurrentEntryL( attachEntry );
+
+ // get source file
+ TFileName sourceFileName = attPath->Des();
+
+ // get the mime type
+ RApaLsSession ls;
+ User::LeaveIfError( ls.Connect() );
+ CleanupClosePushL<RApaLsSession>(ls);
+ TUid appUid;
+ TDataType mimeType;
+ ls.AppForDocument( sourceFileName, appUid, mimeType );
+ CleanupStack::PopAndDestroy(); //ls
+
+ CWaiter* waiter = CWaiter::NewLC();
+
+ // add an attachment to the current message entry
+ obexMtm->AddAttachmentL( sourceFileName, mimeType.Des8(), 0,
+ waiter->iStatus );
+ waiter->StartAndWait();
+ CleanupStack::PopAndDestroy( waiter );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( obexMtm );
+ CleanupStack::PopAndDestroy( attPath );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+
+ // send the message id back
+ TInt32 id = tentry.Id();
+ TBuf8<8> idStr;
+ idStr.Copy( ( TUint8* )( &id ), sizeof( id ) );
+ SendOkMsgL( idStr );
+ }
+
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleCreateObexMsgL: Done");
+ }
+
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleCreateSmartMsgL( const TDesC8& aData )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleCreateSmartMsgL" );
+
+ if ( ValidateAddSmartMsgCommand( aData ) )
+ {
+ TInt position( 0 );
+ HBufC16* fromTo = ExtractDesLC( aData, position, 1 );
+ HBufC16* description = ExtractDesLC( aData, position, 1 );
+ HBufC16* body = ExtractDesLC( aData, position, 2 );
+ TBool isNew = (TBool)aData[position];
+ TBool isUnread = (TBool)aData[position+1];
+ TFolder folder = (TFolder)aData[position+2];
+ TInt bioUidValue = aData[position+3] +
+ ( aData[position+4] << 8 ) +
+ ( aData[position+5] << 16 ) +
+ ( aData[position+6] << 24 );
+
+
+ // Smart messages can be created only to inbox.
+ // For sending smart messages, create a normal SMS with smart message
+ // content as a body and send it.
+ if ( folder != EInbox )
+ {
+ HTI_LOG_TEXT( "Invalid folder specified for smart message" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidFolderForSmartMsg );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+
+ }
+
+ CSmsClientMtm* smsMtm = NULL;
+ TRAPD( err, smsMtm = ( CSmsClientMtm* )iMtmReg->NewMtmL( KUidMsgTypeSMS ) );
+ if ( err || !smsMtm )
+ {
+ HTI_LOG_TEXT( "SMS message type module not found" );
+ SendErrorMessageL( KErrNotFound, KErrorMsgTypeNotFound );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+ CleanupStack::PushL( smsMtm );
+
+ CMsvEntry* entry = CMsvEntry::NewL( *iSession,
+ KMsvGlobalInBoxIndexEntryId, TMsvSelectionOrdering() );
+ CleanupStack::PushL( entry );
+
+ // get the default service
+ TMsvId defaultServiceId = 0;
+ TRAP( err, defaultServiceId = smsMtm->DefaultServiceL() );
+ if ( err )
+ {
+ HTI_LOG_FORMAT( "Could not get default service, err: %d", err );
+ SendErrorMessageL( err, KErrorSmsSettingNotDefined );
+ CleanupStack::PopAndDestroy( entry );
+ CleanupStack::PopAndDestroy( smsMtm );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+ return;
+ }
+
+ // no need for folder mapping, since only inbox allowed for smart messages
+ TMsvId folderId = KMsvGlobalInBoxIndexEntryId;
+ entry->SetEntryL( folderId );
+
+ // mtm takes ownership of entry context
+ smsMtm->SetCurrentEntryL( entry );
+ CleanupStack::Pop( entry );
+
+ // create a new message
+ smsMtm->CreateMessageL( defaultServiceId );
+
+ // update the message header
+ CSmsHeader* smsHeader = &( smsMtm->SmsHeader() );
+ delete smsHeader;
+ smsHeader = NULL;
+ smsHeader = CSmsHeader::NewL( CSmsPDU::ESmsDeliver, smsMtm->Body() );
+ smsHeader->SetFromAddressL( fromTo->Des() );
+
+ // set body, the actual BIO message content
+ smsMtm->Body().Reset();
+ smsMtm->Body().InsertL( 0, body->Des() );
+
+ // get the entry of the message
+ TMsvEntry tentry = smsMtm->Entry().Entry();
+
+ // set BIO message type specific data
+ tentry.iBioType = bioUidValue;
+ smsMtm->BioTypeChangedL( TUid::Uid( bioUidValue ) );
+
+ // set details field
+ tentry.iDetails.Set( fromTo->Des() );
+
+ // set the description field
+ tentry.iDescription.Set( description->Des() );
+
+ // set correct MTM type
+ tentry.iMtm= KUidBIOMessageTypeMtm;
+
+ // final fine tuning
+ tentry.SetAttachment( EFalse );
+ tentry.iDate.UniversalTime();
+ tentry.SetVisible( ETrue );
+ tentry.SetInPreparation( EFalse );
+ tentry.SetUnread( isUnread );
+ tentry.SetNew( isNew );
+ tentry.SetComplete( ETrue );
+ tentry.SetSendingState( KMsvSendStateWaiting );
+ tentry.iServiceId = defaultServiceId;
+ tentry.iRelatedId = 0;
+
+ // save the changes done above
+ smsMtm->Entry().ChangeL( tentry );
+
+ // save the message
+ smsMtm->SaveMessageL();
+
+ CleanupStack::PopAndDestroy( smsMtm );
+ CleanupStack::PopAndDestroy( body );
+ CleanupStack::PopAndDestroy( description );
+ CleanupStack::PopAndDestroy( fromTo );
+
+ TInt32 id = tentry.Id();
+ TBuf8<8> idStr;
+ idStr.Copy( ( TUint8* )( &id ), sizeof( id ) );
+ SendOkMsgL( idStr );
+ }
+
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleCreateSmartMsgL: Done");
+ }
+
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleDeleteMessageL( const TDesC8& aData )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleDeleteMessageL" );
+
+ if ( aData.Length() != 4 )
+ {
+ HTI_LOG_TEXT( "CMessageMgmntHandler: Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidId );
+ return;
+ }
+
+ TMsvId entryId = aData[0] +
+ ( aData[1] << 8 ) +
+ ( aData[2] << 16 ) +
+ ( aData[3] << 24 );
+ HTI_LOG_FORMAT( "CMessageMgmntHandler: Deleting one message, id: %d", entryId );
+ TMsvEntry entry;
+ TMsvId service;
+ User::LeaveIfError( iSession->GetEntry( entryId, service, entry ) );
+
+ CMsvEntry* parentCEntry = iSession->GetEntryL( entry.Parent() );
+ CleanupStack::PushL( parentCEntry );
+ TRAPD( err, parentCEntry->DeleteL( entry.Id() ) );
+ CleanupStack::PopAndDestroy( parentCEntry );
+
+ if ( err == KErrNone )
+ {
+ SendOkMsgL( KNullDesC8 );
+ }
+ else if ( err == KErrNotFound )
+ {
+ SendErrorMessageL( err, KErrorItemNotFound );
+ }
+ else
+ {
+ SendErrorMessageL( err, KErrorFailedDelete );
+ }
+
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleDeleteMessageL: Done");
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleDeleteMessagesL( const TDesC8& aData )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleDeleteMessagesFuncL" );
+
+ if ( aData.Length() != 2 )
+ {
+ HTI_LOG_TEXT( "CMessageMgmntHandler: Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidFolder );
+ return;
+ }
+
+ if ( aData[0] == EAllFolders )
+ {
+ HandleDeleteFromAllFoldersL( (TMessageType)aData[1] );
+ }
+ else if ( aData[1] == EAllMessageTypes )
+ {
+ HandleDeleteAllMessageTypesL( (TFolder)aData[0] );
+ }
+ else
+ {
+ HandleDeleteFromFolderByTypeL( (TFolder)aData[0],
+ (TMessageType)aData[1] );
+ }
+
+ SendOkMsgL( KNullDesC8 );
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleDeleteMessagesFuncL: Done");
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleDeleteFromAllFoldersL( TMessageType aType )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleDeleteFromAllFoldersL" );
+
+ if ( aType == EAllMessageTypes )
+ {
+ for ( TInt i = 1; i < ENumberOfFolders; i++ )
+ {
+ HandleDeleteAllMessageTypesL( (TFolder)i );
+ }
+ }
+ else
+ {
+ for ( TInt i = 1; i < ENumberOfFolders; i++ )
+ {
+ HandleDeleteFromFolderByTypeL( (TFolder)i, aType );
+ }
+ }
+
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleDeleteFromAllFoldersL: Done");
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleDeleteAllMessageTypesL( TFolder aFolder )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleDeleteAllMessageTypesL" );
+
+ if ( aFolder == EAllFolders )
+ {
+ for ( TInt i = 1; i < ENumberOfMessageTypes; i++ )
+ {
+ HandleDeleteFromAllFoldersL( (TMessageType)i );
+ }
+ }
+ else
+ {
+ for ( TInt i = 1; i < ENumberOfMessageTypes; i++ )
+ {
+ HandleDeleteFromFolderByTypeL( aFolder, (TMessageType)i );
+ }
+ }
+
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleDeleteAllMessageTypesL: Done");
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleDeleteFromFolderByTypeL( TFolder aFolder,
+ TMessageType aType )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleDeleteFromFolderByTypeL" );
+
+ TMsvId folderId = MapFolderToIdL( aFolder );
+ TUid msgTypeUid = MapMessageTypeToUidL( aType );
+
+ HTI_LOG_TEXT( "Deleting messages..." );
+ HTI_LOG_FORMAT( "Folder: %d", aFolder );
+ HTI_LOG_FORMAT( "Message type: %d", aType );
+
+ CMsvEntry* folder = CMsvEntry::NewL( *iSession,
+ folderId,
+ TMsvSelectionOrdering() );
+ CleanupStack::PushL( folder );
+ CMsvEntrySelection* sel = folder->ChildrenWithMtmL( msgTypeUid );
+
+ CleanupStack::PushL( sel );
+ HTI_LOG_FORMAT( "Found %d matching items", sel->Count() );
+
+ for ( TInt i = 0; i < sel->Count(); i++ )
+ {
+ TMsvId entryId = sel->At( i );
+ TMsvEntry entry;
+ TMsvId service;
+ User::LeaveIfError( iSession->GetEntry( entryId, service, entry ) );
+ if ( ( aType == EAudioMessage && entry.iBioType != KUidMsgSubTypeMmsAudioMsg.iUid ) ||
+ ( aType == EMMS && entry.iBioType == KUidMsgSubTypeMmsAudioMsg.iUid ) )
+ {
+ // do not delete audio messages when MMS deletion
+ // requested and vice versa
+ continue;
+ }
+ CMsvEntry* parentCEntry = iSession->GetEntryL( entry.Parent() );
+ CleanupStack::PushL( parentCEntry );
+ parentCEntry->DeleteL( entry.Id() );
+ CleanupStack::PopAndDestroy( parentCEntry );
+ }
+
+ CleanupStack::PopAndDestroy( sel );
+ CleanupStack::PopAndDestroy( folder );
+
+ if ( aType == EEmail )
+ {
+ HandleDeleteFromFolderByTypeL( aFolder, EEmailPOP3 );
+ HandleDeleteFromFolderByTypeL( aFolder, EEmailIMAP4 );
+ }
+
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleDeleteFromFolderByTypeL: Done");
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::SendOkMsgL( const TDesC8& aData )
+ {
+ HTI_LOG_FUNC_IN("CMessageMgmntHandler::SendOkMsgL: Starting");
+
+ User::LeaveIfNull( iDispatcher );
+
+ HBufC8* temp = HBufC8::NewL( aData.Length() + 1 );
+ TPtr8 response = temp->Des();
+ response.Append( (TChar) CHtiMessagesServicePlugin::EResultOk );
+ response.Append( aData );
+ User::LeaveIfError( iDispatcher->DispatchOutgoingMessage(
+ temp, KHtiMessagesServiceUid ) );
+
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::SendOkMsgL: Done");
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::SendErrorMessageL( TInt aError,
+ const TDesC8& aDescription )
+ {
+ HTI_LOG_FUNC_IN("CMessageMgmntHandler::SendErrorMessageL: Starting");
+ User::LeaveIfNull( iDispatcher );
+ User::LeaveIfError( iDispatcher->DispatchOutgoingErrorMessage(
+ aError, aDescription, KHtiMessagesServiceUid ) );
+ HTI_LOG_FUNC_OUT("CMessageMgmntHandler::SendErrorMessageL: Done");
+ }
+
+// ----------------------------------------------------------------------------
+TBool CMessageMgmntHandler::ValidateAddSmsCommand( const TDesC8& aData )
+ {
+ if ( aData.Length() < KAddSmsCmdMinLength )
+ {
+ HTI_LOG_TEXT( "ValidateAddSmsCommand: Error: missing data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+ TInt offset = 0;
+ TInt fromLength = aData[offset];
+
+ offset = 1 + fromLength;
+ if ( offset > aData.Length() - 1 )
+ {
+ HTI_LOG_TEXT( "ValidateAddSmsCommand: Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+ TInt descrLength = aData[offset];
+
+ offset = offset + 1 + descrLength;
+ if ( offset > aData.Length() - 2 ) // body length in two bytes
+ {
+ HTI_LOG_TEXT( "ValidateAddSmsCommand: Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+ TInt bodyLength = aData[offset] + ( aData[offset+1] << 8 );
+
+ TInt wholeLength = 1 + fromLength +
+ 1 + descrLength +
+ 2 + bodyLength +
+ 1 + // is new
+ 1 + // is unread
+ 1; // folder
+
+ if ( wholeLength != aData.Length() )
+ {
+ HTI_LOG_TEXT( "ValidateAddSmsCommand: Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+ if ( bodyLength > 160 )
+ {
+ HTI_LOG_TEXT( "ValidateAddSmsCommand: Error: too long SMS body" );
+ SendErrorMessageL( KErrOverflow, KErrorTooLongSmsBody );
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+
+// ----------------------------------------------------------------------------
+TBool CMessageMgmntHandler::ValidateAddMmsOrAddEmailCommand( const TDesC8& aData )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::ValidateAddMmsOrAddEmailCommand" );
+ if ( aData.Length() < KAddMmsOrEmailCmdMinLength + 1 ) // +1 = cmd code
+ {
+ HTI_LOG_TEXT( "Error: missing data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+ if ( aData[0] == CHtiMessagesServicePlugin::EAddAudioMsg &&
+ aData.Length() < KAddAudioCmdMinLength + 1 ) // +1 = cmd code
+ {
+ HTI_LOG_TEXT( "ValidateAddMmsOrAddEmailCommand: Error: missing data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+ TInt offset = 0;
+ TInt cmdCode = aData[offset];
+ offset++;
+ TInt fromToLength = aData[offset];
+ fromToLength++; // the length byte
+
+ offset = offset + fromToLength;
+ if ( offset > aData.Length() - 1 )
+ {
+ HTI_LOG_TEXT( "Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+ TInt descrLength = aData[offset];
+ descrLength++; // the length byte
+
+ offset = offset + descrLength;
+ TInt bodyLength = 0;
+ if ( cmdCode != CHtiMessagesServicePlugin::EAddAudioMsg )
+ {
+ if ( offset > aData.Length() - 2 ) // body length in two bytes
+ {
+ HTI_LOG_TEXT( "Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+ bodyLength = aData[offset] + ( aData[offset+1] << 8 );
+ bodyLength += 2; // the body length bytes
+ }
+
+ offset = offset + bodyLength;
+ if ( offset > aData.Length() - 1 )
+ {
+ HTI_LOG_TEXT( ": wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+ TInt attPathLength = aData[offset];
+ if ( attPathLength == 0 && cmdCode == CHtiMessagesServicePlugin::EAddAudioMsg )
+ {
+ // attachment (the audio) is mandatory for audio message
+ HTI_LOG_TEXT( "Error: missing attachment" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+ attPathLength++; // the length byte
+
+ TInt wholeLength = 1 + // command code
+ fromToLength + descrLength + bodyLength + attPathLength +
+ 1 + // is new
+ 1 + // is unread
+ 1; // folder
+
+ if ( wholeLength != aData.Length() )
+ {
+ HTI_LOG_TEXT( "Error: wrong length of data (wholeLength)" );
+ HTI_LOG_FORMAT( "Expected: %d", wholeLength );
+ HTI_LOG_FORMAT( "Was: %d", aData.Length() );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+
+// ----------------------------------------------------------------------------
+TBool CMessageMgmntHandler::ValidateAddObexMsgCommand( const TDesC8& aData )
+ {
+ if ( aData.Length() < KAddObexMsgCmdMinLength )
+ {
+ HTI_LOG_TEXT( "ValidateAddObexMsgCommand: Error: missing data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+ TInt offset = 0;
+ TInt fromToLength = aData[offset];
+
+ offset = 1 + fromToLength;
+ if ( offset > aData.Length() - 1 )
+ {
+ HTI_LOG_TEXT( "ValidateAddObexMsgCommand: Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+ TInt descrLength = aData[offset];
+
+ offset = offset + 1 + descrLength;
+ if ( offset > aData.Length() - 1 )
+ {
+ HTI_LOG_TEXT( "ValidateAddObexMsgCommand: Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+ TInt attPathLength = aData[offset];
+
+ TInt wholeLength = 1 + fromToLength +
+ 1 + descrLength +
+ 1 + attPathLength +
+ 1 + // is new
+ 1 + // is unread
+ 1; // folder
+
+ if ( wholeLength != aData.Length() )
+ {
+ HTI_LOG_TEXT( "ValidateAddObexMsgCommand: Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+// ----------------------------------------------------------------------------
+TBool CMessageMgmntHandler::ValidateAddSmartMsgCommand( const TDesC8& aData )
+ {
+ if ( aData.Length() < KAddSmartMsgCmdMinLength )
+ {
+ HTI_LOG_TEXT( "ValidateAddSmartMsgCommand: Error: missing data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+ TInt offset = 0;
+ TInt fromToLength = aData[offset];
+
+ offset = 1 + fromToLength;
+ if ( offset > aData.Length() - 1 )
+ {
+ HTI_LOG_TEXT( "ValidateAddSmartMsgCommand: Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+ TInt descrLength = aData[offset];
+
+ offset = offset + 1 + descrLength;
+ if ( offset > aData.Length() - 2 ) // body length in two bytes
+ {
+ HTI_LOG_TEXT( "ValidateAddSmartMsgCommand: Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+ TInt bodyLength = aData[offset] + ( aData[offset+1] << 8 );
+
+ TInt wholeLength = 1 + fromToLength +
+ 1 + descrLength +
+ 2 + bodyLength +
+ 1 + // is new
+ 1 + // is unread
+ 1 + // folder
+ 4; // biomessage uid
+
+ if ( wholeLength != aData.Length() )
+ {
+ HTI_LOG_TEXT( "ValidateAddSmartMsgCommand: Error: wrong length of data" );
+ SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+
+// ----------------------------------------------------------------------------
+// Extracts UTF-8 data, converts it to Unicode and returns as 16-bit descriptor.
+// Within aData, read descriptor from aPosition:
+// - first bytes tell the size of data for UTF8 formatted data
+// - next bytes are the data as indicated by the size
+// - position is finally set to the end of UTF8 data area
+// ----------------------------------------------------------------------------
+HBufC16* CMessageMgmntHandler::ExtractDesLC( const TDesC8& aUtf8Data,
+ TInt& aPosition,
+ TInt aSizeBytes )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::ExtractDesLC" );
+ TInt length = 0;
+ for ( TInt i = 0; i < aSizeBytes; i++ )
+ {
+ length += ( aUtf8Data[aPosition+i] << ( i * 8 ) );
+ }
+
+ if ( length < 0 ||
+ length > aUtf8Data.Mid( aPosition ).Length() )
+ {
+ User::Leave( KErrBadDescriptor );
+ }
+
+ HBufC16* result = NULL;
+
+ if ( length > 0 )
+ {
+ result = CnvUtfConverter::ConvertToUnicodeFromUtf8L(
+ aUtf8Data.Mid( aPosition + aSizeBytes, length ) );
+ HTI_LOG_TEXT( "ExtractDesLC: Conversion to Unicode done" );
+ CleanupStack::PushL( result );
+ }
+
+ else
+ {
+ result = HBufC16::NewLC( 0 );
+ }
+
+ aPosition += ( aSizeBytes + length );
+
+ HTI_LOG_FUNC_OUT( "CMessageMgmntHandler::ExtractDesLC" );
+ return result;
+ }
+
+
+// ----------------------------------------------------------------------------
+// Extracts UTF-8 data to 8-bit descriptor without doing any conversions.
+// ----------------------------------------------------------------------------
+HBufC8* CMessageMgmntHandler::ExtractDes8LC( const TDesC8& aUtf8Data,
+ TInt& aPosition,
+ TInt aSizeBytes )
+ {
+ HTI_LOG_FUNC_IN( "CMessageMgmntHandler::ExtractDes8LC" );
+ TInt length = 0;
+ for ( TInt i = 0; i < aSizeBytes; i++ )
+ {
+ length += ( aUtf8Data[aPosition+i] << ( i * 8 ) );
+ }
+
+ if ( length < 0 ||
+ length > aUtf8Data.Mid( aPosition ).Length() )
+ {
+ User::Leave( KErrBadDescriptor );
+ }
+
+ HBufC8* result = HBufC8::NewLC( length );
+
+ if ( length > 0 )
+ {
+ result->Des().Copy( aUtf8Data.Mid( aPosition + aSizeBytes, length ) );
+ }
+
+ aPosition += ( aSizeBytes + length );
+
+ HTI_LOG_FUNC_OUT( "CMessageMgmntHandler::ExtractDes8LC" );
+ return result;
+ }
+
+
+// ----------------------------------------------------------------------------
+TMsvId CMessageMgmntHandler::MapFolderToIdL( TFolder aFolder )
+ {
+ TMsvId id = 0;
+
+ switch ( aFolder )
+ {
+ case EInbox: { id = KMsvGlobalInBoxIndexEntryId; break; }
+ case EDrafts: { id = KMsvDraftEntryId; break; }
+ case ESent: { id = KMsvSentEntryId; break; }
+ case EOutbox: { id = KMsvGlobalOutBoxIndexEntryId; break; }
+ default: { User::Leave( KErrArgument ); break; }
+ }
+
+ return id;
+ }
+
+// ----------------------------------------------------------------------------
+TUid CMessageMgmntHandler::MapMessageTypeToUidL( TMessageType aType )
+ {
+ TUid uid = { 0 };
+
+ switch ( aType )
+ {
+ case ESMS: { uid = KUidMsgTypeSMS; break; }
+ case EAudioMessage: // fall through - audio msg is MMS sub type
+ case EMMS: { uid = KUidMsgTypeMultimedia; break; }
+ case ESmartMessage: { uid = KUidBIOMessageTypeMtm; break; }
+ case EEmail: { uid = KUidMsgTypeSMTP; break; }
+ case EEmailPOP3: { uid = KUidMsgTypePOP3; break; }
+ case EEmailIMAP4: { uid = KUidMsgTypeIMAP4; break; }
+ case EIrMessage: { uid = KUidMsgTypeIrUID; break; }
+ case EBtMessage: { uid = KUidMsgTypeBt; break; }
+ default: { User::Leave( KErrArgument ); break; }
+ }
+
+ return uid;
+ }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleSessionEventL( TMsvSessionEvent /*aEvent*/,
+ TAny* /*aArg1*/,
+ TAny* /*aArg2*/,
+ TAny* /*aArg3*/ )
+ {
+ }
+
+
+
+// ----------------------------------------------------------------------------
+CWaiter* CWaiter::NewL( TInt aPriority )
+ {
+ CWaiter* self = new(ELeave) CWaiter( aPriority );
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+CWaiter* CWaiter::NewLC( TInt aPriority )
+ {
+ CWaiter* self = new(ELeave) CWaiter( aPriority );
+ CleanupStack::PushL( self );
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+CWaiter::CWaiter( TInt aPriority ) : CActive( aPriority )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+// ----------------------------------------------------------------------------
+CWaiter::~CWaiter()
+ {
+ Cancel();
+ }
+
+// ----------------------------------------------------------------------------
+void CWaiter::StartAndWait()
+ {
+ iStatus = KRequestPending;
+ SetActive();
+ iWait.Start();
+ }
+
+// ----------------------------------------------------------------------------
+TInt CWaiter::Result() const
+ {
+ return iResult;
+ }
+
+// ----------------------------------------------------------------------------
+void CWaiter::RunL()
+ {
+ iResult = iStatus.Int();
+ iWait.AsyncStop();
+ }
+
+// ----------------------------------------------------------------------------
+void CWaiter::DoCancel()
+ {
+ iResult = KErrCancel;
+ if ( iStatus == KRequestPending )
+ {
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrCancel );
+ }
+
+ iWait.AsyncStop();
+ }
+
+
+// End of file