--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmsengine/mmsserver/src/mmsdeleteoperation.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,920 @@
+/*
+* Copyright (c) 2004-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+* State machine for sending a delete request to network
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <apparc.h>
+#include <msventry.h>
+#include <msvids.h>
+#include <logcli.h>
+#include <commdb.h>
+#include <in_sock.h>
+#include <commdbconnpref.h>
+#include <AknGlobalNote.h>
+
+// the rest are local includes, needed always
+#include "mmsconst.h"
+#include "mmsdeleteoperation.h"
+#include "mmssession.h"
+#include "mmssettings.h"
+#include "mmsservercommon.h"
+#include "mmsheaders.h"
+#include "mmsmmboxmessageheaders.h"
+#include "mmsencode.h"
+#include "mmsdecode.h"
+#include "mmsscheduledentry.h"
+#include "mmsgenutils.h"
+#include "mmserrors.h"
+#include "mmsserverentry.h"
+#include "mmsconninit.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+extern void gPanic( TMmsPanic aPanic );
+
+// CONSTANTS
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// ==================== LOCAL FUNCTIONS ====================
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::CMmsDeleteOperation
+//
+// ---------------------------------------------------------
+//
+CMmsDeleteOperation::CMmsDeleteOperation( RFs& aFs ):
+ CMmsBaseOperation( aFs )
+ {
+ //
+ // members that get initial value 0, need not be intialized here
+ //
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::ConstructL
+//
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::ConstructL( CMmsSettings* aMmsSettings )
+ {
+ CMmsBaseOperation::ConstructL( aMmsSettings );
+ iMmsRequestHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
+ CActiveScheduler::Add( this );
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::NewL
+//
+// ---------------------------------------------------------
+//
+CMmsDeleteOperation* CMmsDeleteOperation::NewL( RFs& aFs, CMmsSettings* aMmsSettings )
+ {
+ CMmsDeleteOperation* self = new ( ELeave ) CMmsDeleteOperation( aFs );
+ CleanupStack::PushL( self );
+ self->ConstructL( aMmsSettings );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::~CMmsDeleteOperation
+//
+// ---------------------------------------------------------
+//
+CMmsDeleteOperation::~CMmsDeleteOperation()
+ {
+ Cancel();
+ delete iMmsRequestHeaders;
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::DoCancel
+//
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::DoCancel()
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("CMmsDeleteOperation::DoCancel") );
+ #endif
+ CMmsBaseOperation::DoCancel();
+
+ // Clear possible flags
+ for( TInt i = iSelection->Count()-1; i >= 0; i-- )
+ {
+ // original entry
+ if ( iServerEntry->SetEntry( iSelection->At( i ) ) == KErrNone )
+ {
+ TMsvEntry tEntry = iServerEntry->Entry();
+ TMsvId parent = tEntry.Parent();
+ // If notification in iSelection is in mmbox folder, mark the
+ // possible duplicate notification in inbox too.
+ if ( parent == iMmsSettings->MMBoxFolder() )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("possible duplicates has to be checked") );
+ #endif
+ TInt error = KErrNone;
+ TRAP ( error, MarkDuplicateL( EMmsNotificationOperationFailed, *iServerEntry ) );
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("Trap failed: error %d "), error );
+ #endif
+ }
+
+ // reload to make sure any changes are included
+ // (there should be no changes)
+ tEntry = iServerEntry->Entry();
+ MarkNotificationOperationFailed( tEntry );
+
+ // put to read only state after duplicates have been marked
+ // because MarkDuplicateL may want to edit link to related entry
+ tEntry.SetReadOnly( ETrue );
+ iServerEntry->ChangeEntry( tEntry );
+
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::StartL
+//
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::StartL(
+ TMmsDeleteOperationType aDeleteType,
+ CMsvEntrySelection& aSelection,
+ CMsvServerEntry& aServerEntry,
+ TMsvId aService,
+ TRequestStatus& aStatus )
+ {
+ iDeleteType = aDeleteType;
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("CMmsDeleteOperation::StartL") );
+ if( iDeleteType == EMmsDeleteNotificationOnly ) TMmsLogger::Log( _L("- EMmsDeleteNotificationOnly") );
+ if( iDeleteType == EMmsDeleteMMBoxOnly ) TMmsLogger::Log( _L("- EMmsDeleteMMBoxOnly") );
+ if( iDeleteType == EMmsDeleteBoth ) TMmsLogger::Log( _L("- EMmsDeleteBoth") );
+ #endif
+ // Make sure the version number is correctly set
+ CMmsBaseOperation::StartL( aSelection, aServerEntry, aService, aStatus );
+ iMmsRequestHeaders->Reset();
+
+ //
+ // Delete operation does not work as regular operations:
+ //
+ // iFailed list is emptied because retries are not used for delete
+ iFailed->Reset();
+ // iCurrentMessageNo makes no sense in case of delete
+ iCurrentMessageNo = 0;
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::StartL
+// This just overrides the base class version.
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::StartL(
+ CMsvEntrySelection&,
+ CMsvServerEntry&,
+ TMsvId,
+ TRequestStatus& )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::EncodePDUL
+//
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::EncodePDUL()
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("CMmsDeleteOperation::EncodePDU") );
+ #endif
+ TInt err = KErrNone; // used to trap errors that are not propagated further
+
+ // Go through iSelection and make various checks
+ TMsvEntry tEntry;
+ for( TInt i = iSelection->Count()-1; i >= 0; i-- )
+ {
+ if ( iServerEntry->SetEntry( iSelection->At( i ) ) == KErrNone )
+ {
+ tEntry = iServerEntry->Entry();
+
+ // Check that selection contains only "idle" notifications
+ if( ( tEntry.iMtm != KUidMsgMMSNotification ) ||
+ ( tEntry.iMtm == KUidMsgMMSNotification &&
+ tEntry.iMtmData2 & KMmsNewOperationForbidden ) )
+ {
+ // Take out all non-notifications and notifications that have some operation ongoing
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- notif not idle, skipping" ) );
+ #endif
+ iSelection->Delete( i );
+ }
+ else
+ {
+ // If only local delete requested, delete the entry
+ if( iDeleteType == EMmsDeleteNotificationOnly )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- just deleting the notif entry" ) );
+ #endif
+ TRAP( err, DeleteNotificationEntryL() );
+ #ifndef _NO_MMSS_LOGGING_
+ if( err != KErrNone )
+ {
+ TMmsLogger::Log( _L( "- ERROR: DeleteNotificationEntryL left" ) );
+ }
+ #endif
+ iSelection->Delete( i );
+ }
+ else // EMmsDeleteMMBoxOnly OR EMmsDeleteBoth
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- mmbox deletion wanted" ) );
+ #endif
+ // Is there a message in MMBox.
+ if( !(tEntry.iMtmData2 & KMmsStoredInMMBox ) )
+ {
+ // No need to care about possible duplicate notification.
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- accordig to mmbox flag, message is not in mmbox" ) );
+ #endif
+ // If both requested, but no message in MMBox,
+ // just delete the notification.
+ if( iDeleteType == EMmsDeleteBoth )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- local deletion requested, performing it" ) );
+ #endif
+ TRAP( err, DeleteNotificationEntryL() );
+ #ifndef _NO_MMSS_LOGGING_
+ if( err != KErrNone )
+ {
+ TMmsLogger::Log( _L( "- ERROR: DeleteNotificationEntryL left" ) );
+ }
+ #endif
+ }
+ else // iDeleteType == EMmsDeleteMMBoxOnly
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- can not delete from mmbox, clearing entry flags" ) );
+ #endif
+ MarkNotificationOperationFailed( tEntry );
+ tEntry.SetReadOnly( ETrue );
+ iServerEntry->ChangeEntry( tEntry );
+ }
+ // As message not in MMBox, delete entry from selection
+ iSelection->Delete( i );
+ }
+ }
+ }
+ }
+ else
+ {
+ // take out an entry that could not be accessed
+ iSelection->Delete( i );
+ }
+ }
+
+ // delete from mmbox is wanted and the notifications are stored in mmbox
+ // Check duplicates, if the parent is in mmbox folder.
+
+ // If duplicate is found, check if the duplicate is free.
+ // If the duplicate is free, mark the duplicate as "deleting operation going on".
+ // If duplicate is not free, drop the original notification from iSelection.
+
+ for ( TInt j = iSelection->Count()-1; j >= 0; j-- )
+ {
+ if ( iServerEntry->SetEntry( iSelection->At( j ) ) == KErrNone )
+ {
+ // if original notification cannot be accessed there is no way
+ // to check the notification
+ tEntry = iServerEntry->Entry();
+
+ if ( tEntry.Parent() == iMmsSettings->MMBoxFolder() )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- check if duplicate is found" ) );
+ #endif
+ // parent is mmbox folder.
+ CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
+ CleanupStack::PushL( mmsHeaders );
+ CMsvStore* store = iServerEntry->ReadStoreL();
+ CleanupStack::PushL( store );
+ mmsHeaders->RestoreL( *store );
+ CleanupStack::PopAndDestroy( store );
+ store = NULL;
+
+ TMsvId duplicate = KMsvNullIndexEntryId;
+ FindDuplicateNotificationL( KMsvGlobalInBoxIndexEntryIdValue,
+ *mmsHeaders, duplicate );
+
+ if ( duplicate != KMsvNullIndexEntryId )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- duplicate found" ) );
+ #endif
+ if ( iServerEntry->SetEntry( duplicate ) == KErrNone )
+ {
+ // Mark duplicate, if it is free for a new operation
+ TMsvEntry dupEntry = iServerEntry->Entry();
+
+ if ( FreeNotification( dupEntry, KMmsOperationDelete ) )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- Marking duplicate" ) );
+ #endif
+ MarkNotificationOperationReserved( dupEntry, KMmsOperationDelete );
+
+ iServerEntry->ChangeEntry( dupEntry );
+
+ // Set duplicate as related entry to the original notification
+ if ( iServerEntry->SetEntry( iSelection->At( j ) ) == KErrNone )
+ {
+ tEntry = iServerEntry->Entry();
+ tEntry.SetReadOnly( EFalse );
+ iServerEntry->ChangeEntry( tEntry );
+
+ store = iServerEntry->EditStoreL();
+ CleanupStack::PushL( store );
+ mmsHeaders->RestoreL( *store );
+
+ mmsHeaders->SetRelatedEntry( duplicate );
+ mmsHeaders->StoreL( *store );
+ store->CommitL();
+ CleanupStack::PopAndDestroy( store );
+ store = NULL;
+ }
+ }
+ else
+ {
+ // duplicate is not free, drop the original from iSelection.
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- Duplicate is not free, drop the original notification from selection" ) );
+ #endif
+ iSelection->Delete( j );
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy( mmsHeaders );
+ }
+ }
+ }
+
+ // iSelection contains notifications that are deleted from mmbox
+ // Mark notifications as "deleting operation going on"
+
+ for ( TInt k = iSelection->Count()-1; k >= 0; k-- )
+ {
+ if ( iServerEntry->SetEntry( iSelection->At( k ) ) == KErrNone )
+ {
+ tEntry = iServerEntry->Entry();
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- reserve notif for deletion" ) );
+ #endif
+
+ // Mark all remaining notifications as operation-ongoing
+ // operation is from now on delete
+ MarkNotificationOperationReserved( tEntry, KMmsOperationDelete );
+
+ tEntry.SetReadOnly( EFalse );
+ iServerEntry->ChangeEntry( tEntry );
+ }
+ }
+ //
+ // If remote delete is required, creating PDU to be sent
+ //
+ if( ( iDeleteType != EMmsDeleteNotificationOnly ) &&
+ ( iSelection->Count() > 0 ) )
+ {
+#ifndef _NO_MMSS_LOGGING_
+TMmsLogger::Log( _L( "- creating PDU" ) );
+#endif
+ //
+ // Create headers structure
+ //
+ // iMmsRequestHeaders is a member that has been created in the constructor
+ // And Reset in the StartL function
+
+ // MessageType
+ iMmsRequestHeaders->SetMessageType( KMmsMessageTypeMBoxDeleteReq );
+
+ // TransactionId
+ TBufC8<KMMSMAXTIDLENGTH> tid;
+ tid.Des().NumUC( AllocateTID(), EHex );
+ iMmsRequestHeaders->SetTidL( tid );
+
+ //
+ // Content-Location array
+ // Loop through selection and put all content locations into array
+ //
+ CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
+ CleanupStack::PushL( mmsHeaders ); // ***
+ for( TInt i = iSelection->Count() - 1; i >= 0; i-- )
+ {
+ // Get entry
+ if ( iServerEntry->SetEntry( iSelection->At( i ) ) == KErrNone )
+ {
+ // Get read-only message store
+ CMsvStore* store = iServerEntry->ReadStoreL();
+ CleanupStack::PushL( store ); // ***
+ // Restore all parts of multimedia message
+ mmsHeaders->RestoreL( *store );
+
+ // Add array to headers
+ iMmsRequestHeaders->MMBoxMessageHeadersL().ContentLocationList()
+ .AppendL( mmsHeaders->ContentLocation() );
+ CleanupStack::PopAndDestroy( store );
+ }
+ }
+ CleanupStack::PopAndDestroy( mmsHeaders );
+
+ //
+ // Encode the PDU
+ //
+ iEncoder->EncodeHeadersL( *iMmsRequestHeaders, *iEncodeBuffer );
+ }
+
+ iServerEntry->SetEntry( KMsvNullIndexEntryId );
+ FallThrough();
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::ConnectToIAPL
+//
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::ConnectToIAPL()
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("CMmsDeleteOperation::ConnectToIAPL") );
+ #endif
+
+ if( iDeleteType == EMmsDeleteNotificationOnly || iSelection->Count() == 0 )
+ {
+ FallThrough();
+ }
+ else
+ {
+ CMmsBaseOperation::ConnectToIAPL();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::InitializeSessionL
+//
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::InitializeSessionL()
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("CMmsDeleteOperation::InitializeSessionL") );
+ #endif
+
+ if( iDeleteType == EMmsDeleteNotificationOnly || iSelection->Count() == 0 )
+ {
+ FallThrough();
+ }
+ else
+ {
+ CMmsBaseOperation::InitializeSessionL();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::SubmitTransactionL
+//
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::SubmitTransactionL()
+ {
+#ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("CMmsDeleteOperation::SubmitTransactionL"));
+#endif
+ //
+ // Maybe networking not needed at all
+ //
+ if( iDeleteType == EMmsDeleteNotificationOnly || iSelection->Count() == 0 )
+ {
+ FallThrough();
+ return;
+ }
+
+ // This check is needed only when running tests in local mode
+ // if length of URI is 0, Symbian code will panic
+ if ( !iUri )
+ {
+ iError = KMmsErrorNoURI1;
+ }
+ else if ( iUri->Des().Length() == 0 )
+ {
+ iError = KMmsErrorNoURI1;
+ }
+ else
+ {
+ // keep LINT happy
+ }
+
+ //
+ // Networking is needed. Is connection open.
+ //
+ if ( !iConnected )
+ {
+ if ( iError == KErrNone )
+ {
+ iError = KErrCouldNotConnect;
+ }
+ }
+
+ //
+ // If something has gone wrong, just fall through
+ //
+ if ( iError != KErrNone )
+ {
+ FallThrough();
+ return;
+ }
+
+ //
+ // Send
+ //
+ iMmsSession->SendMessageL(
+ iUri->Des(),
+ *iEncodeBuffer,
+ *iEncoder,
+ *iDecoder,
+ iStatus );
+ SetActive();
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::DecodeResponseL()
+//
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::DecodeResponseL()
+ {
+#ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "CMmsDeleteOperation::DecodeResponseL()" ) );
+#endif
+
+ if( iDeleteType != EMmsDeleteNotificationOnly && iSelection->Count() > 0 )
+ {
+ // iError is checked in base class method.
+ CMmsBaseOperation::DecodeResponseL();
+ }
+ else
+ {
+ FallThrough();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::UpdateEntryStatusL
+//
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::UpdateEntryStatusL()
+ {
+#ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "CMmsDeleteOperation::UpdateEntryStatusL()" ) );
+ TMmsLogger::Log( _L( "- Number of ids in iSelection: %d" ), iSelection->Count() );
+#endif
+
+ if( iDeleteType == EMmsDeleteNotificationOnly || iSelection->Count() == 0 )
+ {
+ FallThrough();
+ return;
+ }
+
+ //
+ // If error has occurred and there is nothing received from the network,
+ // just correcting the flags in the notification entries as they were before.
+ //
+ if( iError != KErrNone )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- error has occurred" ) );
+ #endif
+ MarkSelectionAsFailed();
+ FallThrough();
+ return;
+ }
+ //
+ // Following is the the default behaviour: no errors, response received
+ //
+ else
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- no errors" ) );
+ #endif
+
+ //
+ // Get delete result array from response
+ //
+ const RPointerArray<CMmsDeleteResultArray>& resultArray
+ = iResponse->DeleteResultArray();
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- resultarray length: %d" ), iResponse->DeleteResultArray().Count() );
+ #endif
+
+ //
+ // Make overall check for the response before checking each entry separately
+ // First, messagetype
+ //
+ if( iResponse->MessageType() != KMmsMessageTypeMBoxDeleteConf )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- ERROR: Response has wrong message type!" ) );
+ #endif
+ MarkSelectionAsFailed();
+ FallThrough();
+ return;
+ }
+ // Second, if result array contains status Unsupported-Message with no
+ // related Content-Location, the transaction is interpreted as failed.
+ for( TInt j = 0; j < resultArray.Count(); j++ )
+ {
+ if( resultArray[j]->ContentLocation().Length() == 0 &&
+ resultArray[j]->ResponseStatus() == KMmsErrorStatusUnsupportedMessage )
+ {
+ // If array contains item that has no Content-Location,
+ // something is wrong
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- Response contains response-status with no corresponding ContentLocation!" ) );
+ TMmsLogger::Log( _L( " Interpreting this as delete failure." ) );
+ #endif
+ MarkSelectionAsFailed();
+ FallThrough();
+ return;
+ }
+ }
+
+ //
+ // Moving from response level checks into entry level checks...
+ //
+ // Loop through iSelection to separate failed and successful ones
+ // (contains notifications that were sent to network)
+ //
+ CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
+ CleanupStack::PushL( mmsHeaders );
+ for( TInt i = iSelection->Count(); i > 0; i-- )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- looping in iSelection[%d]" ), i-1 );
+ #endif
+ // Get Content-location of this notification
+ if ( iServerEntry->SetEntry( iSelection->At( i-1 ) ) == KErrNone )
+ {
+ CMsvStore* store = iServerEntry->ReadStoreL();
+ CleanupStack::PushL( store );
+ mmsHeaders->RestoreL( *store );
+ CleanupStack::PopAndDestroy( store );
+ store = NULL;
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- store read" ) );
+ #endif
+ TPtrC8 pContentLocation = mmsHeaders->ContentLocation();
+ TMsvId duplicate = mmsHeaders->RelatedEntry();
+
+ //
+ // Search for the same content-location from response PDU
+ // (if it is found, it's mmbox delete has failed)
+ //
+ TBool bMmboxDeleteSucceeded = ETrue;
+ for ( TInt j = 0; j < resultArray.Count(); j++ )
+ {
+ // Check match
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- looping in resultArray[%d]" ), j );
+ #endif
+ if( resultArray[j]->ContentLocation().Compare( pContentLocation ) == 0 )
+ {
+ // Get response status that will be investigated next
+ TInt32 responseStatus = resultArray[j]->ResponseStatus();
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- Match found. X-Mms-Response-Status == %d" ), responseStatus );
+ #endif
+ // Found a match, now check the reason
+ if( responseStatus != KMmsStatusOk &&
+ responseStatus != KMmsErrorMessageNotFound && // this should not be used by the server
+ responseStatus != KMmsErrorPermanentMessageNotFound )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- delete did not succeed for this notif" ) );
+ #endif
+ // This entry failed, removing it from iSelection
+ iSelection->Delete( i-1 );
+ bMmboxDeleteSucceeded = EFalse;
+
+ // Notification will not be deleted any longer regardless of iDeleteType
+ // Correcting the notification entry
+ // StoredInMMBox flag value not changed.
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- clearing entry flags" ) );
+ #endif
+
+ // if the original notification is in mmbox folder and a duplicate is found,
+ // mark the status of the duplicate notification too.
+
+ if ( duplicate != KMsvNullIndexEntryId &&
+ iServerEntry->Entry().Parent() == iMmsSettings->MMBoxFolder() )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L(
+ "- duplicate exists and original notification is in mmbox folder" )
+ );
+ #endif
+ // Clear related entry from the original notification
+ // and mark the duplicate as failed
+ TRAP_IGNORE( MarkDuplicateL(
+ EMmsNotificationOperationFailed, *iServerEntry ) );
+ }
+
+ // Mark original notification. iServerEntry still points to it
+ TMsvEntry tEntry = iServerEntry->Entry();
+ MarkNotificationOperationFailed( tEntry );
+ tEntry.SetReadOnly( ETrue );
+ iServerEntry->ChangeEntry( tEntry );
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- original marked failed" ) );
+ #endif
+ }
+ }
+ } // inner for loop (resultArray)
+
+ // Has the current entry been deleted from mmbox...
+ if( bMmboxDeleteSucceeded )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- this notification was deleted from mmbox" ) );
+ #endif
+
+ if ( iServerEntry->SetEntry( iSelection->At( i-1 ) ) == KErrNone )
+ {
+ // if notification is in inbox, check if a duplicate exits in mmbox folder
+ if ( iServerEntry->Entry().Parent() == KMsvGlobalInBoxIndexEntryIdValue )
+ {
+ TMsvId mmboxFolder = iMmsSettings->MMBoxFolder();
+ if ( mmboxFolder != KMsvNullIndexEntryId )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- original notification is in inbox" ) );
+ TMmsLogger::Log( _L( "- finding duplicate from mmbox inbox" ) );
+ #endif
+ FindDuplicateNotificationL( mmboxFolder, *mmsHeaders, duplicate );
+ }
+ }
+
+ // if duplicate exits, mark it as "deleted successfully from mmbox"
+ if ( duplicate != KMsvNullIndexEntryId )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- duplicate exists" ) );
+ #endif
+
+ // iServerEntry should still be pointing to the original notification
+
+ // Clear related entry from the original notification
+ // and mark the duplicate as "deleted from mmbox"
+ TRAP_IGNORE( MarkDuplicateL( EMmsDeletedFromMmbox, *iServerEntry ) )
+ }
+
+ // Should notification also be deleted...
+ if( iDeleteType == EMmsDeleteBoth )
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- about to delete notif entry" ) );
+ #endif
+ DeleteNotificationEntryL();
+ }
+ else // deletetype not equal to delete-both
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- clearing notif flags" ) );
+ #endif
+ TMsvEntry tEntry = iServerEntry->Entry();
+ tEntry.iMtmData2 &= ~KMmsStoredInMMBox; // not-stored-in-mmbox
+ tEntry.iMtmData2 &= ~KMmsNewOperationForbidden; // operations allowed
+ tEntry.iMtmData2 &= ~KMmsOperationOngoing; // not ongoing
+ tEntry.iMtmData2 |= KMmsOperationFinished; // finished
+ tEntry.iMtmData2 &= ~KMmsOperationResult; // OK
+ tEntry.SetReadOnly( ETrue );
+ iServerEntry->ChangeEntry( tEntry );
+ }
+ }
+ }
+ }
+ } // outer for loop (iSelection)
+ CleanupStack::PopAndDestroy( mmsHeaders );
+ }
+ iServerEntry->SetEntry( KMsvNullIndexEntryId );
+ FallThrough();
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::DeleteNotificationEntryL
+//
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::DeleteNotificationEntryL()
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "CMmsDeleteOperation::DeleteNotificationEntryL()" ) );
+ #endif
+ // Get indexentry
+ TMsvEntry tEntry = iServerEntry->Entry();
+ TInt error = iServerEntry->SetEntry( tEntry.Parent());
+ if ( error == KErrNone )
+ {
+ // Can delete entry only if setting entry to parent was successful
+ iServerEntry->DeleteEntry( tEntry.Id() );
+ }
+ iServerEntry->SetEntry( KMsvNullIndexEntryId );
+ }
+
+// ---------------------------------------------------------
+// CMmsDeleteOperation::MarkSelectionAsFailed
+//
+// ---------------------------------------------------------
+//
+void CMmsDeleteOperation::MarkSelectionAsFailed()
+ {
+ #ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "CMmsDeleteOperation::MarkSelectionAsFailed()" ) );
+ #endif
+
+ // Loop through iSelection
+ for( TInt i = iSelection->Count(); i > 0; i-- )
+ {
+ TInt error = KErrNone;
+ error = iServerEntry->SetEntry( iSelection->At( i-1 ) );
+ if ( error == KErrNone )
+ {
+ // If notification in iSelection is in mmbox folder, mark the
+ // possible duplicate notification in inbox too.
+ if ( iServerEntry->Entry().Parent() == iMmsSettings->MMBoxFolder() )
+ {
+#ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L( "- check possible duplicate" ) );
+#endif
+ TRAP ( error, MarkDuplicateL( EMmsNotificationOperationFailed, *iServerEntry ) );
+#ifndef _NO_MMSS_LOGGING_
+ TMmsLogger::Log( _L("Trap failed: error %d "), error );
+#endif
+ }
+
+ // Mark the original notification in selection
+ // MarkDuplicateL does not mess up the original context of iServerEntry
+ TMsvEntry tEntry = iServerEntry->Entry();
+ MarkNotificationOperationFailed( tEntry );
+ tEntry.SetReadOnly( ETrue );
+ error = iServerEntry->ChangeEntry( tEntry );
+#ifndef _NO_MMSS_LOGGING_
+ if( error != KErrNone )
+ {
+ TMmsLogger::Log( _L( "ERROR: ChangeEntry() failed" ) );
+ }
+ else
+ {
+ TMmsLogger::Log( _L( "- selection[%d] flags are cleared" ), i );
+ }
+#endif
+ }
+ }
+ iServerEntry->SetEntry( KMsvNullIndexEntryId );
+
+ }
+
+// ================= OTHER EXPORTED FUNCTIONS ==============
+
+// End of File