mmsengine/clientmtm/src/mmsnotificationclient.cpp
changeset 0 72b543305e3a
child 23 238255e8b033
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmsengine/clientmtm/src/mmsnotificationclient.cpp	Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,1056 @@
+/*
+* Copyright (c) 2002-2006 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:  
+*     A Client MTM to access MMS notifications in a manual fetch mode.
+*     All this is needed to support new mtm type for Symbian OS messaging
+*     UI components.
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <msvids.h>
+#include "mmsheaders.h"
+#include "mmsnotificationclient.h"
+#include "mmscmds.h"
+#include "mmsmessageoperation.h"
+#include "mmsmmboxviewheaders.h"
+#include "mmssettings.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES  
+
+// CONSTANTS
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+const TInt KMmsAttributeArrayGranularity = 8;
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// ==================== LOCAL FUNCTIONS ====================
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CMmsClientNotificationMtm::NewL
+// ---------------------------------------------------------
+//
+EXPORT_C CMmsNotificationClientMtm* CMmsNotificationClientMtm::NewL(
+    CRegisteredMtmDll& aRegisteredMtmDll,
+    CMsvSession& aSession )
+    {
+    CMmsNotificationClientMtm* self = new ( ELeave ) CMmsNotificationClientMtm(
+        aRegisteredMtmDll, aSession );
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+
+// ---------------------------------------------------------
+// CMmsClientNotificationMtm::CMmsNotificationClientMtm
+// ---------------------------------------------------------
+//
+CMmsNotificationClientMtm::CMmsNotificationClientMtm(
+    CRegisteredMtmDll& aRegisteredMtmDll,
+    CMsvSession& aSession )
+    : CMmsClientMtm( aRegisteredMtmDll, aSession )
+    {
+    __ASSERT_DEBUG( Type() == KUidMsgMMSNotification, gPanic( EMmsBadMtmTypeUid ) );
+    }
+
+// ---------------------------------------------------------
+// CMmsClientNotificationMtm::~CMmsNotificationClientMtm
+// ---------------------------------------------------------
+//
+CMmsNotificationClientMtm::~CMmsNotificationClientMtm()
+    {
+    
+    }
+
+// ---------------------------------------------------------
+// CMmsClientNotificationMtm::ConstructL
+// 
+// ---------------------------------------------------------
+//
+void CMmsNotificationClientMtm::ConstructL()
+    {
+    // First loading settings
+    iMmsSettings = CMmsSettings::NewL();
+    iMmsSettings->LoadSettingsL();
+    // Get the base values to detect changes
+    iHomeMode = iMmsSettings->ReceivingModeHome();
+    iRoamingMode = iMmsSettings->ReceivingModeForeign();
+    iAccessPointCount = iMmsSettings->AccessPointCount();
+    
+    iMessageDrive = EDriveC;
+    TInt error = KErrNone;
+
+    TRAP ( error, { iMessageDrive = Session().CurrentDriveL(); } );
+
+    if ( error != KErrNone )
+        {
+        // if cannot ask, use default
+        iMessageDrive = EDriveC;
+        }
+
+    // Notification client mtm does not create new service
+    iServiceId = iMmsSettings->Service();
+
+    iMmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
+
+    iAttributes  = new( ELeave ) CDesCArrayFlat( KMmsAttributeArrayGranularity );
+
+    // Set the original context to the service entry
+    SwitchCurrentEntryL( iServiceId );
+    }
+
+// ---------------------------------------------------------
+// CMmsClientMtm::QueryCapability
+// ---------------------------------------------------------
+//
+TInt CMmsNotificationClientMtm::QueryCapability(
+    TUid /*aCapability*/,
+    TInt& /*aResponse*/ )
+    {
+    // Nothing Supported at the moment
+    return KErrNotSupported;
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::ForwardL
+// ---------------------------------------------------------
+//
+CMsvOperation* CMmsNotificationClientMtm::ForwardL(
+    TMsvId aDestination,
+    TMsvPartList /*aPartList*/,
+    TRequestStatus& aCompletionStatus )
+    {
+    //
+    // Actual creation is done synchronously below
+    //
+    TMsvId id = CreateForwardEntryL( aDestination );
+
+    //
+    // This method has to be asynchronous..
+    //
+    TPckgC < TMsvId > progress = id;
+    return  CMsvCompletedOperation::NewL( Session(), Type(), progress, 
+        KMsvLocalServiceIndexEntryId, aCompletionStatus );
+    }
+
+// ---------------------------------------------------------
+// CMmsClientNotificationMtm::CreateForwardEntryL
+// ---------------------------------------------------------
+//
+TMsvId CMmsNotificationClientMtm::CreateForwardEntryL( TMsvId aDestination )
+    {
+    //
+    // Check that current context is valid
+    //
+    if( iMsvEntry->Entry().iType != KUidMsvMessageEntry
+        || iMsvEntry->Entry().iMtm != KUidMsgMMSNotification )
+        {
+        User::Leave( KErrUnknown );
+        }
+
+    // It is assumed that a created forward entry can not be saved to drafts.
+    // I.e. the application calling this, is responsible to take care that
+    // the entry is either SENT or DESTROYED.
+
+    //
+    // Load entry to local cache if necessary
+    //
+    if( iMmsHeaders->ContentLocation() == TPtrC8() )
+        {
+        LoadMessageL();
+        }
+
+    //
+    // Create new Mms message object into aDestination folder
+    //
+    TMsvId forwardId = CMmsMessageOperation::CreateForwardWithoutRetrievalL(
+        Session(),
+        *iMmsHeaders,
+        iMsvEntry->EntryId(),
+        aDestination,
+        iServiceId );
+
+    return forwardId;
+    }
+
+// ---------------------------------------------------------
+// CMmsClientNotificationMtm::SendL
+// ---------------------------------------------------------
+//
+CMsvOperation* CMmsNotificationClientMtm::SendL( 
+    TRequestStatus& aCompletionStatus,
+    const TTime aSendingTime )
+    {
+    //
+    // Is it possible to proceed with the operation...
+    // If yes, the notification is marked as "further-operations-not-allowed"
+    //
+    TMsvId relatedNotificationId = iMmsHeaders->RelatedEntry();
+    TInt retval = ReserveNotificationOperationL( relatedNotificationId, KMmsOperationForward );
+    if( retval != KErrNone )
+        {
+        TPckgC < TMsvId > progress = relatedNotificationId;
+      	return CMsvCompletedOperation::NewL(
+      	    Session(),
+      	    KUidMsgMMSNotification,
+      	    progress, // progress contains the related entry id
+      	    iServiceId,
+      	    aCompletionStatus,
+      	    KErrInUse);
+        }
+
+    //
+    // Create the selection to be sent
+    //
+    CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection;
+    CleanupStack::PushL( selection ); // ***
+    selection->AppendL( iMsvEntry->Entry().Id() );
+
+    //
+    // Make sure the message is in OUTBOX
+    //
+    TMsvId currentParent = iMsvEntry->Entry().Parent();
+    if ( currentParent != KMsvGlobalOutBoxIndexEntryId )
+        {
+        CMsvEntry* cEntry = NULL;
+        cEntry = Session().GetEntryL( currentParent );
+        CleanupStack::PushL( cEntry );
+        cEntry->MoveL( iMsvEntry->Entry().Id(), KMsvGlobalOutBoxIndexEntryId );
+        CleanupStack::PopAndDestroy( cEntry );
+        }
+
+    //
+    // Create parameters structure
+    //
+    TCommandParameters parameters;
+    TTime now;
+    now.UniversalTime();
+    if ( aSendingTime > now )
+        {
+        aSendingTime.SecondsFrom( now, parameters.iInitialDelay );
+        }
+    TCommandParametersBuf paramPack( parameters );
+
+    //
+    // Call Server MTM
+    //
+    CMsvOperation* op = InvokeAsyncFunctionL(
+        EMmsScheduledForward,
+        *selection,
+        paramPack,
+        aCompletionStatus );
+ 
+    //
+    // Cleanup and return
+    //
+    CleanupStack::PopAndDestroy( selection );
+    return op;
+    }
+
+// ---------------------------------------------------------
+// CMmsClientNotificationMtm::SendL
+// ---------------------------------------------------------
+//
+CMsvOperation* CMmsNotificationClientMtm::SendL(
+    CMsvEntrySelection& /*aSelection*/,
+    TRequestStatus& /*aCompletionStatus*/,
+    TTime /*aSendingTime*/ )
+    {
+    User::Leave( KErrNotSupported );
+    return NULL; // makes the compiler happy
+    }
+
+// ---------------------------------------------------------
+// CMmsClientNotificationMtm::ReserveNotificationOperationL
+// ---------------------------------------------------------
+//
+TInt CMmsNotificationClientMtm::ReserveNotificationOperationL( 
+    TMsvId aNotifId,
+    const TUint32 aOperation )
+    {
+    //
+    // Get hands on index entry based on entryId
+    //
+    CMsvEntry* cEntry = NULL;
+    cEntry = Session().GetEntryL( aNotifId );
+    CleanupStack::PushL( cEntry ); // ***
+    TMsvEntry tEntry = cEntry->Entry();
+
+    //
+    // Check that entry is a notification
+    //
+    if( cEntry->Entry().iType != KUidMsvMessageEntry
+        || cEntry->Entry().iMtm != KUidMsgMMSNotification )
+        {
+        CleanupStack::PopAndDestroy( cEntry );
+        return KErrNotSupported;
+        }
+
+    //
+    // Make some checks concerning the current status of notification and
+    // return with error if reservation is not possible
+    //
+    // if operation is forbidden OR
+    // if ( (the aOperation is fetch or forward) and notification is deleted successfully from mmbox)
+    if( tEntry.iMtmData2 & KMmsNewOperationForbidden ||
+        ( ( aOperation == KMmsOperationFetch || aOperation == KMmsOperationForward ) &&
+        tEntry.iMtmData2 & KMmsOperationFinished && 
+        ! ( tEntry.iMtmData2 & KMmsOperationResult ) &&
+        ! ( tEntry.iMtmData2 & KMmsStoredInMMBox ) &&
+        tEntry.iMtmData2 & KMmsOperationDelete ) )
+        {
+        CleanupStack::PopAndDestroy( cEntry );
+        return KErrInUse;        
+        }
+
+    //
+    // Set the flags
+    //
+    // reserve the operation
+    MarkNotificationOperationReserved( tEntry, aOperation );
+    tEntry.SetReadOnly( EFalse );
+
+    //
+    // Save the entry
+    //
+    cEntry->ChangeL( tEntry );
+    CleanupStack::PopAndDestroy( cEntry );
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::MarkFreeNotificationsReservedL
+// ---------------------------------------------------------
+//
+void CMmsNotificationClientMtm::MarkFreeNotificationsReservedL(
+    CMsvEntrySelection& aNotifications, const TUint32 aOperation )
+    {
+    TInt count = aNotifications.Count();
+    if ( count == 0 )
+        {
+        return;
+        }
+    CMsvEntry* clientEntry = Session().GetEntryL( aNotifications.At( 0 ));
+    CleanupStack::PushL( clientEntry );
+
+    for ( TInt i = aNotifications.Count() - 1 ; i >= 0 ; i-- ) 
+        {
+        TBool drop = EFalse;
+        TBool alreadyMarked = EFalse;
+
+        clientEntry->SetEntryL( aNotifications.At( i ) );
+        TMsvEntry entry = clientEntry->Entry();
+        TMsvId duplicate = KMsvNullIndexEntryId;
+        if ( FreeNotification( entry, aOperation ) )
+            {
+            // Check possible duplicate, if mmbox folder even exists
+            TMsvId mmboxFolder = iMmsSettings->MMBoxFolder();
+            if ( mmboxFolder != KMsvNullIndexEntryId )
+                {
+                TMsvId parent = entry.Parent();
+                
+                CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
+                CleanupStack::PushL( mmsHeaders );
+                CMsvStore* store = clientEntry->ReadStoreL();
+                CleanupStack::PushL( store );
+                mmsHeaders->RestoreL( *store );
+                CleanupStack::PopAndDestroy( store );
+                store = NULL;
+                
+                if ( parent == KMsvGlobalInBoxIndexEntryId )
+                    {
+                    
+                    FindDuplicateNotificationL( mmboxFolder, 
+                        *mmsHeaders, duplicate );
+                    }
+                else if ( parent == mmboxFolder )
+                    {
+                    FindDuplicateNotificationL( KMsvGlobalInBoxIndexEntryId, 
+                        *mmsHeaders, duplicate );
+                    }
+                else
+                    {
+                    // keep LINT happy
+                    }
+                if ( duplicate != KMsvNullIndexEntryId )
+                    {
+                    // check if duplicate is free for a operation
+                    clientEntry->SetEntryL( duplicate );
+                    TMsvEntry dupEntry = clientEntry->Entry();
+                    if ( FreeNotification( dupEntry, aOperation ))
+                        {
+                        // if original notification is in mmbox folder
+                        // mark the duplicate reserved too.
+                        if ( parent == mmboxFolder )
+                            {
+                            MarkNotificationOperationReserved( dupEntry, aOperation );
+                            clientEntry->ChangeL( dupEntry );
+
+                            clientEntry->SetEntryL( aNotifications.At( i ) );
+                            entry = clientEntry->Entry();
+                            MarkNotificationOperationReserved( entry, aOperation );
+                            entry.SetReadOnly( EFalse );
+                            clientEntry->ChangeL( entry );
+                            alreadyMarked = ETrue;
+
+                            store = clientEntry->EditStoreL();
+                            CleanupStack::PushL( store );
+                            mmsHeaders->RestoreL( *store );
+                            mmsHeaders->SetRelatedEntry( duplicate );
+                            mmsHeaders->StoreL( *store );
+                            store->CommitL();
+                            CleanupStack::PopAndDestroy( store );
+                            store = NULL; 
+                            }
+                        clientEntry->SetEntryL( aNotifications.At( i ) );
+                       
+                        }
+                    else // duplicate is not free-> original notification has to be dropped
+                        {
+                        drop = ETrue;
+                        }
+                    
+                    }
+                CleanupStack::PopAndDestroy( mmsHeaders );
+                }
+            
+            }
+        else // original notification is not free
+            {
+            drop = ETrue;
+            }
+
+        if ( drop )
+            {
+            // Remove the entry from selection
+            aNotifications.Delete( i );
+            }
+        else // mark original notification reserved, unless it is already marked
+            {
+            if ( !alreadyMarked) 
+                {
+                clientEntry->SetEntryL( aNotifications.At( i ) );              
+                entry = clientEntry->Entry();
+                MarkNotificationOperationReserved( entry, aOperation );
+                entry.SetReadOnly( EFalse );
+                clientEntry->ChangeL( entry );
+                }   
+            }
+        }
+    aNotifications.Compress();
+
+    CleanupStack::PopAndDestroy( clientEntry );
+
+    }
+
+ 
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::FreeNotification
+// ---------------------------------------------------------
+//       
+TBool CMmsNotificationClientMtm::FreeNotification( TMsvEntry& aEntry, const TUint32 aOperation )
+    {
+    if ( aEntry.iMtm != KUidMsgMMSNotification)
+        {
+        return EFalse;
+        }
+    if ( aEntry.iMtmData2 & KMmsNewOperationForbidden ||
+        ( aEntry.iMtmData2 & KMmsOperationFinished &&
+        !( aEntry.iMtmData2 & KMmsOperationResult ) &&
+        !( aEntry.iMtmData2 & KMmsStoredInMMBox ) &&
+        ( aOperation == KMmsOperationFetch || aOperation == KMmsOperationForward )))
+        {
+        return EFalse;
+        }
+
+    return ETrue;
+    
+    }
+
+ 
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::MarkNotificationOperationReserved
+// ---------------------------------------------------------
+//       
+void CMmsNotificationClientMtm::MarkNotificationOperationReserved( TMsvEntry& aEntry, 
+                                                                  const TUint32 aOperation )
+    {
+    aEntry.iMtmData2 &= ~KMmsOperationIdentifier;   // clear possible old operation
+    aEntry.iMtmData2 |= KMmsNewOperationForbidden;  // forbidden   
+    aEntry.iMtmData2 |= KMmsOperationOngoing;       // operation is active
+    aEntry.iMtmData2 |= aOperation;                 // operation
+    aEntry.iMtmData2 &= ~KMmsOperationFinished;     // not finished
+    aEntry.iMtmData2 &= ~KMmsOperationResult;       // not failed  
+    }
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::FindDuplicateNotificationL
+// ---------------------------------------------------------
+// 
+void CMmsNotificationClientMtm::FindDuplicateNotificationL( TMsvId aParent, 
+                                                           CMmsHeaders& aHeaders, 
+                                                           TMsvId& aDuplicate )
+    {
+
+    aDuplicate = KMsvNullIndexEntryId;
+    if ( aParent == KMsvNullIndexEntryId )
+        {
+        return;
+        }
+
+    CMsvEntry* cEntry = Session().GetEntryL( aParent );
+    CleanupStack::PushL( cEntry );
+
+    CMsvEntrySelection* selection = cEntry->ChildrenWithMtmL( KUidMsgMMSNotification );
+    CleanupStack::PushL( selection );
+
+    TInt count = selection->Count();
+    if ( count == 0 )
+        {
+        CleanupStack::PopAndDestroy( selection );
+        CleanupStack::PopAndDestroy( cEntry );
+        return;
+        }
+
+    CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
+    CleanupStack::PushL( mmsHeaders );
+     
+    for ( TInt i = count; i > 0 && ( aDuplicate == KMsvNullIndexEntryId ); i-- )
+        {
+        cEntry->SetEntryL( selection->At( i - 1 ) );
+                   
+        CMsvStore* store = cEntry->ReadStoreL();
+        CleanupStack::PushL( store );
+        mmsHeaders->RestoreL( *store );
+        CleanupStack::PopAndDestroy( store );
+
+        // content location must match 
+        if ( mmsHeaders->ContentLocation().Compare( aHeaders.ContentLocation() ) == 0 )
+            {
+            aDuplicate = selection->At( i - 1 );
+            }        
+        }
+
+    CleanupStack::PopAndDestroy( mmsHeaders );
+    CleanupStack::PopAndDestroy( selection );
+    CleanupStack::PopAndDestroy( cEntry );
+    }
+    
+// ---------------------------------------------------------
+// CMmsClientNotificationMtm::GetExtendedText
+// ---------------------------------------------------------
+//
+const TPtrC CMmsNotificationClientMtm::GetExtendedText() const
+    {
+    return iMmsHeaders->ExtendedNotification();
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::FetchMessagesL
+// ---------------------------------------------------------
+//
+CMsvOperation* CMmsNotificationClientMtm::FetchMessagesL( 
+    const CMsvEntrySelection& aSelection,
+    TRequestStatus& aCompletionStatus )
+    {
+    if ( aSelection.Count() == 0 )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    CMsvEntrySelection* notifications = aSelection.CopyLC();
+  
+     // mark free notifications reserved. Others are dropped out.
+    MarkFreeNotificationsReservedL( *notifications, KMmsOperationFetch );
+
+    // check if none of the entries are allowed to start fetch
+    if ( notifications->Count() == 0 )
+        {
+        // leave will destroy reserved items from cleanupstack
+        User::Leave( KErrNotSupported );
+        }
+
+    TCommandParameters parameters; // initialized to zero
+    TCommandParametersBuf paramPack( parameters );
+
+    // Fetch messages
+    CMsvOperation* op = InvokeAsyncFunctionL(
+        EMmsScheduledReceiveForced,
+        *notifications,
+        paramPack,
+        aCompletionStatus ); 
+
+    CleanupStack::PopAndDestroy( notifications );
+    return op;
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::FetchMessageL
+// ---------------------------------------------------------
+//
+CMsvOperation* CMmsNotificationClientMtm::FetchMessageL( 
+    TMsvId aUid, 
+    TRequestStatus& aCompletionStatus )
+    {
+    CMsvEntrySelection* selection = new ( ELeave ) CMsvEntrySelection;
+    CleanupStack::PushL( selection );
+    selection->AppendL( aUid );
+
+    // Mark the notification reserved for fetching is possible
+    MarkFreeNotificationsReservedL( *selection, KMmsOperationFetch );
+
+    // if notification is not allowed to be fetched, 
+    // the notification is dropped from selection. 
+    if ( selection->Count() == 0 )
+        {
+        CleanupStack::PopAndDestroy( selection );
+        return NULL;
+        }
+
+    TCommandParameters parameters; // initialized to zero
+    TCommandParametersBuf paramPack( parameters );
+
+    // Fetch the message
+    CMsvOperation* op = InvokeAsyncFunctionL(
+        EMmsScheduledReceiveForced,
+        *selection,
+        paramPack,
+        aCompletionStatus ); 
+
+    CleanupStack::PopAndDestroy( selection );
+    return op;
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::FetchAllL
+// ---------------------------------------------------------
+//
+
+CMsvOperation* CMmsNotificationClientMtm::FetchAllL( TRequestStatus& aCompletionStatus,
+    TBool aForced )
+    {
+    // List notifications that have no active operation
+    CMsvEntrySelection* notifications = ListNotificationsL();
+    if ( notifications->Count() == 0 )
+        {
+        delete notifications;
+        notifications = NULL;
+        User::Leave( KErrNotFound );
+        }
+    CleanupStack::PushL( notifications );
+   
+    // Loop through the notifications and reserve them for the operation
+    TInt retval = KErrNone;
+    TInt count = notifications->Count();
+    for ( TInt i = count; i > 0; i-- ) 
+        {
+        retval = ReserveNotificationOperationL( notifications->At( i - 1 ), KMmsOperationFetch );
+        if( retval != KErrNone )
+            {
+            // Remove the entry from selection
+            notifications->Delete( i - 1 );
+            } 
+        }
+
+    TCommandParameters parameters; // initialized to zero
+    TCommandParametersBuf paramPack( parameters );
+
+    // Fetch the message
+    CMsvOperation* op = NULL;
+    if ( aForced )
+        {
+        op = InvokeAsyncFunctionL(
+            EMmsScheduledReceiveForced,
+            *notifications,
+            paramPack,
+            aCompletionStatus ); 
+        }
+    else
+        {
+        op = InvokeAsyncFunctionL(
+            EMmsScheduledReceive,
+            *notifications,
+            paramPack,
+            aCompletionStatus ); 
+        }
+
+    CleanupStack::PopAndDestroy( notifications );
+    return op;
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::NotificationCount
+// ---------------------------------------------------------
+//
+TInt CMmsNotificationClientMtm::NotificationCount()
+    {
+    TInt numberOfNotifications = -1;
+
+    TInt error = KErrNone;
+    CMsvEntrySelection* notifications = NULL;
+
+    TRAP( error, 
+        { notifications = ListNotificationsL();
+        });
+        
+    if ( error == KErrNone )
+        {
+        numberOfNotifications = notifications->Count();
+        }
+        
+    delete notifications;
+    notifications = NULL;    
+    
+    return numberOfNotifications;
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::ListNotificationsL
+// ---------------------------------------------------------
+//
+CMsvEntrySelection* CMmsNotificationClientMtm::ListNotificationsL()
+    {
+    return CMmsClientMtm::ListNotificationsInInboxL();
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::DeleteNotificationL
+// ---------------------------------------------------------
+//
+CMsvOperation* CMmsNotificationClientMtm::DeleteNotificationL( 
+    const CMsvEntrySelection& aSelection,
+    TMmsDeleteOperationType aDeleteType,
+    TRequestStatus& aCompletionStatus )
+    {
+    
+    if ( aSelection.Count() == 0 )
+        {
+        // if nothing to delete, operation is complete
+        TPckgC < TMsvId > progress = 0;
+        return  CMsvCompletedOperation::NewL( Session(), Type(), progress, 
+            KMsvLocalServiceIndexEntryId, aCompletionStatus, KErrNone );
+        }
+    
+    //
+    // aDeleteType has to be delivered to server side.
+    // Using TCommandParameters.iError for it on purpose.
+    //
+    TCommandParameters parameters;
+    parameters.iError = aDeleteType;
+    TCommandParametersBuf paramPack( parameters );
+
+    //
+    // Modifying indexentries
+    //
+    CMsvEntry* cEntry = NULL;
+    cEntry = Session().GetEntryL( aSelection.At( 0 ) );
+    CleanupStack::PushL( cEntry ); // ***
+    for ( TInt i = 0; i < aSelection.Count(); i++ ) 
+        {
+        cEntry->SetEntryL( aSelection.At( i ) );
+        TMsvEntry tEntry = cEntry->Entry();
+        tEntry.SetReadOnly( EFalse );
+        cEntry->ChangeL( tEntry );
+        }
+    CleanupStack::PopAndDestroy( cEntry );
+
+    //
+    // NOTE: Notification delete operations perform majority of the work in
+    // the server side. This includes also notification reservation for the operation.
+    //
+
+    //
+    // Calling server side
+    //
+    CMsvOperation* op = InvokeAsyncFunctionL(
+        EMmsScheduledNotificationDelete,
+        aSelection,
+        paramPack,
+        aCompletionStatus ); 
+    return op;
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::UnscheduledDeleteNotificationL
+// ---------------------------------------------------------
+//
+CMsvOperation* CMmsNotificationClientMtm::UnscheduledDeleteNotificationL( 
+    const CMsvEntrySelection& aSelection,
+    TMmsDeleteOperationType aDeleteType,
+    TRequestStatus& aCompletionStatus )
+    {
+    
+    if ( aSelection.Count() == 0 )
+       {
+        // if nothing to delete, operation is complete
+        TPckgC < TMsvId > progress = 0;
+        return  CMsvCompletedOperation::NewL( Session(), Type(), progress, 
+            KMsvLocalServiceIndexEntryId, aCompletionStatus, KErrNone );
+        }
+    
+    //
+    // aDeleteType has to be delivered to server side.
+    // Using TCommandParameters.iError for it on purpose.
+    //
+    TCommandParameters parameters;
+    parameters.iError = aDeleteType;
+    TCommandParametersBuf paramPack( parameters );
+
+    //
+    // NOTE: Notification delete operations perform majority of the work in
+    // the server side. This includes also notification reservation for the operation.
+    //
+
+    //
+    // Calling server side
+    //
+    CMsvOperation* op = InvokeAsyncFunctionL(
+        EMmsNotificationDelete,
+        aSelection,
+        paramPack,
+        aCompletionStatus ); 
+    return op;
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::DeleteAllNotificationsL
+// ---------------------------------------------------------
+//
+CMsvOperation* CMmsNotificationClientMtm::DeleteAllNotificationsL( 
+    TMmsDeleteOperationType aDeleteType,
+    TRequestStatus& aCompletionStatus )
+    {
+    //
+    // Get selection of all the notifications in Inbox
+    // (operations that do not have ongoing operations)
+    // 
+    CMsvEntrySelection* selection = ListNotificationsL();
+    
+    if ( selection->Count() == 0 )
+        {
+        delete selection;
+        selection = NULL;
+        // if nothing to delete, operation is complete
+        TPckgC < TMsvId > progress = 0;
+        return  CMsvCompletedOperation::NewL( Session(), Type(), progress, 
+            KMsvLocalServiceIndexEntryId, aCompletionStatus, KErrNone );
+        }
+    
+    CleanupStack::PushL( selection );
+
+    //
+    // Call DeleteNotificationL with the selection just created
+    //
+    CMsvOperation* op = DeleteNotificationL( 
+        *selection, 
+        aDeleteType, 
+        aCompletionStatus );
+    CleanupStack::PopAndDestroy( selection );
+    return op;
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::DeleteForwardEntryL
+// ---------------------------------------------------------
+//
+void CMmsNotificationClientMtm::DeleteForwardEntryL( const CMsvEntrySelection& aSelection )
+    {
+    //
+    // Loop through the selection of forward entries
+    //
+    TInt count = aSelection.Count();
+    for( TInt index = 0; index < count; index++ )
+        {
+        iMsvEntry->SetEntryL( aSelection.At( index ) );
+        TMsvEntry tEntry = iMsvEntry->Entry();
+        // Test entry type
+        if( tEntry.iType != KUidMsvMessageEntry ||
+            tEntry.iMtm != KUidMsgMMSNotification ||
+            !( tEntry.iMtmData1 & KMmsMessageForwardReq ) )
+            {
+            continue;
+            }
+        // Test entry location
+        TMsvId parentId = tEntry.Parent();
+        if( ( parentId != KMsvGlobalOutBoxIndexEntryId ) &&
+            ( parentId != KMsvSentEntryId ) )
+            {
+            continue;
+            }
+        // Test that entry is not in a middle of some other action
+        if( tEntry.SendingState() == KMsvSendStateSending )
+            {
+            // Too late to delete
+            continue;
+            }
+        else
+            {
+            // Quickly "reserve" the entry for deletion
+            tEntry.SetSendingState( KMsvSendStateSuspended );
+            iMsvEntry->ChangeL( tEntry );
+            }
+        //
+        // Entry will do; it will be deleted.
+        //
+
+        // But first clearing possible related notification
+        CMsvStore* store = iMsvEntry->ReadStoreL();
+        CleanupStack::PushL( store ); // ***
+        CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
+        CleanupStack::PushL( mmsHeaders );
+        mmsHeaders->RestoreL( *store );
+        TMsvId relatedId = mmsHeaders->RelatedEntry();
+        CleanupStack::PopAndDestroy( mmsHeaders );
+        CleanupStack::PopAndDestroy( store );
+
+        // If forward entry has a "related id" (i.e. id of the notification),
+        // context is changed to it and it will be cleared.
+        if( relatedId != KMsvNullIndexEntryId )
+            {
+            // Change to related notification
+            iMsvEntry->SetEntryL( relatedId );
+            tEntry = iMsvEntry->Entry();
+            // "Clear" the flags
+            tEntry.iMtmData2 &= ~KMmsOperationIdentifier;   // clear possible old operations
+            tEntry.iMtmData2 &= ~KMmsNewOperationForbidden; // not forbidden
+            tEntry.iMtmData2 &= ~KMmsOperationOngoing;      // not ongoing
+            tEntry.iMtmData2 &= ~KMmsOperationFinished;     // not finished (this is notification's initial state)
+            tEntry.iMtmData2 &= ~KMmsOperationResult;       // clear also the result flag ("assuming OK")
+            tEntry.SetReadOnly( ETrue );
+            iMsvEntry->ChangeL( tEntry );
+            }
+
+        // Activating parent entry of the forward entry
+        iMsvEntry->SetEntryL( parentId );
+        // Delete forward entry
+        iMsvEntry->DeleteL( aSelection.At( index ) );
+        } // for loop
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::MmboxInfoL
+// ---------------------------------------------------------
+//
+TBool CMmsNotificationClientMtm::MmboxInfoL( TMmboxInfo& aMmboxInfo )
+    {
+    // check first, if quota information is available.
+    TMsvId mmboxFolder = iMmsSettings->MMBoxFolder();
+    CMsvEntry* cEntry = Session().GetEntryL( KMsvLocalServiceIndexEntryId );
+    CleanupStack::PushL( cEntry );
+    TInt pushedToStack = 1;
+
+    cEntry->SetEntryL( mmboxFolder );
+    // Show invisible entries
+    cEntry->SetSortTypeL( TMsvSelectionOrdering( KMsvNoGrouping, EMsvSortByIdReverse, ETrue ) );
+    CMsvEntrySelection* selection = cEntry->ChildrenWithMtmL( KUidMsgTypeMultimedia );
+    CleanupStack::PushL( selection );
+    pushedToStack++;
+
+    TBool quotaInfoAvailable = EFalse;
+
+    if ( selection->Count() > 0 )
+        {                
+        cEntry->SetEntryL( selection->At( 0 ));
+        CMsvStore* store = cEntry->ReadStoreL();
+        CleanupStack::PushL( store );
+        pushedToStack++;
+        CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
+        CleanupStack::PushL( mmsHeaders );
+        pushedToStack++;
+        mmsHeaders->RestoreL( *store );
+        
+        // Get quota info
+        CMmsMMBoxViewHeaders& viewHeaders = mmsHeaders->MMBoxViewHeadersL();
+
+        aMmboxInfo.mmboxTotalInBytes = viewHeaders.MMBoxTotalSize();
+        aMmboxInfo.mmboxTotalInMessageCount = viewHeaders.MMBoxTotalNumber();
+        aMmboxInfo.mmboxQuotaInBytes = viewHeaders.MMBoxQuotaSize();
+        aMmboxInfo.mmboxQuotaInMessageCount = viewHeaders.MMBoxQuotaNumber();
+
+        // get Date info
+        TMsvEntry tEntry = cEntry->Entry();
+        aMmboxInfo.date = tEntry.iDate;
+        
+        // error
+        aMmboxInfo.error = tEntry.iError;
+        
+        quotaInfoAvailable = ETrue;
+        }
+
+    CleanupStack::PopAndDestroy( pushedToStack );
+    return quotaInfoAvailable;
+    }
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::UpdateMmBoxListL
+// ---------------------------------------------------------
+//
+CMsvOperation* CMmsNotificationClientMtm::UpdateMmBoxListL(
+            TRequestStatus& aCompletionStatus )
+    {
+    TCommandParameters parameters; // initialized to zero
+    TCommandParametersBuf paramPack( parameters );
+
+    CMsvEntrySelection* selection = new ( ELeave ) CMsvEntrySelection;
+    CleanupStack::PushL( selection ); 
+    selection->AppendL( iServiceId );
+
+    // Update mmbox list
+    CMsvOperation* op = InvokeAsyncFunctionL(
+        EMmsUpdateMmboxList,
+        *selection,
+        paramPack,
+        aCompletionStatus ); 
+
+    CleanupStack::PopAndDestroy( selection );
+    return op;
+    }
+
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm::GetMmboxFolderL
+// ---------------------------------------------------------
+//
+TMsvId CMmsNotificationClientMtm::GetMmboxFolderL()
+    {
+    return iMmsSettings->MMBoxFolder();
+    }
+   
+// ---------------------------------------------------------
+// CMmsNotificationClientMtm
+// ---------------------------------------------------------
+//
+const TPtrC CMmsNotificationClientMtm::GetApplicationId() const
+    {
+    return iMmsHeaders->ApplicId();
+    }
+
+// ================= OTHER EXPORTED FUNCTIONS ==============
+
+//  End of File  
+
+