mmsengine/mmsserver/src/mmsdeleteoperation.cpp
changeset 31 ebfee66fde93
child 47 5b14749788d7
child 52 12db4185673b
equal deleted inserted replaced
30:6a20128ce557 31:ebfee66fde93
       
     1 /*
       
     2 * Copyright (c) 2004-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *     State machine for sending a delete request to network
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 #include    <apparc.h>
       
    23 #include    <msventry.h>
       
    24 #include    <msvids.h>
       
    25 #include    <logcli.h>
       
    26 #include    <commdb.h>
       
    27 #include    <in_sock.h>
       
    28 #include    <commdbconnpref.h>
       
    29 #include    <AknGlobalNote.h>
       
    30 
       
    31 // the rest are local includes, needed always
       
    32 #include    "mmsconst.h"
       
    33 #include    "mmsdeleteoperation.h"
       
    34 #include    "mmssession.h"
       
    35 #include    "mmssettings.h"
       
    36 #include    "mmsservercommon.h"
       
    37 #include    "mmsheaders.h"
       
    38 #include    "mmsmmboxmessageheaders.h"
       
    39 #include    "mmsencode.h"
       
    40 #include    "mmsdecode.h"
       
    41 #include    "mmsscheduledentry.h"
       
    42 #include    "mmsgenutils.h"
       
    43 #include    "mmserrors.h"
       
    44 #include    "mmsserverentry.h"
       
    45 #include    "mmsconninit.h"
       
    46 
       
    47 // EXTERNAL DATA STRUCTURES
       
    48 
       
    49 // EXTERNAL FUNCTION PROTOTYPES  
       
    50 extern void gPanic( TMmsPanic aPanic );
       
    51 
       
    52 // CONSTANTS
       
    53 
       
    54 // MACROS
       
    55 
       
    56 // LOCAL CONSTANTS AND MACROS
       
    57 
       
    58 // MODULE DATA STRUCTURES
       
    59 
       
    60 // LOCAL FUNCTION PROTOTYPES
       
    61 
       
    62 // ==================== LOCAL FUNCTIONS ====================
       
    63 
       
    64 // ================= MEMBER FUNCTIONS =======================
       
    65 
       
    66 // ---------------------------------------------------------
       
    67 // CMmsDeleteOperation::CMmsDeleteOperation
       
    68 //
       
    69 // ---------------------------------------------------------
       
    70 //
       
    71 CMmsDeleteOperation::CMmsDeleteOperation( RFs& aFs ):
       
    72     CMmsBaseOperation( aFs )
       
    73     {
       
    74     //
       
    75     // members that get initial value 0, need not be initialized here
       
    76     //
       
    77     }
       
    78 
       
    79 // ---------------------------------------------------------
       
    80 // CMmsDeleteOperation::ConstructL
       
    81 //
       
    82 // ---------------------------------------------------------
       
    83 //
       
    84 void CMmsDeleteOperation::ConstructL( CMmsSettings* aMmsSettings )
       
    85     {
       
    86     CMmsBaseOperation::ConstructL( aMmsSettings );
       
    87     iMmsRequestHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
       
    88     CActiveScheduler::Add( this );
       
    89     }
       
    90 
       
    91 // ---------------------------------------------------------
       
    92 // CMmsDeleteOperation::NewL
       
    93 //
       
    94 // ---------------------------------------------------------
       
    95 //
       
    96 CMmsDeleteOperation* CMmsDeleteOperation::NewL( RFs& aFs, CMmsSettings* aMmsSettings )
       
    97     {
       
    98     CMmsDeleteOperation* self = new ( ELeave ) CMmsDeleteOperation( aFs );
       
    99     CleanupStack::PushL( self );
       
   100     self->ConstructL( aMmsSettings );
       
   101     CleanupStack::Pop( self );
       
   102     return self;
       
   103     }
       
   104 
       
   105     
       
   106 // ---------------------------------------------------------
       
   107 // CMmsDeleteOperation::~CMmsDeleteOperation
       
   108 //
       
   109 // ---------------------------------------------------------
       
   110 //
       
   111 CMmsDeleteOperation::~CMmsDeleteOperation()
       
   112     {
       
   113     Cancel();
       
   114     delete iMmsRequestHeaders;
       
   115     }
       
   116 
       
   117 // ---------------------------------------------------------
       
   118 // CMmsDeleteOperation::DoCancel
       
   119 //
       
   120 // ---------------------------------------------------------
       
   121 //
       
   122 void CMmsDeleteOperation::DoCancel()
       
   123     {
       
   124     #ifndef _NO_MMSS_LOGGING_
       
   125     TMmsLogger::Log( _L("CMmsDeleteOperation::DoCancel") );
       
   126     #endif
       
   127     CMmsBaseOperation::DoCancel();
       
   128 
       
   129     // Clear possible flags
       
   130     for( TInt i = iSelection->Count()-1; i >= 0; i-- )
       
   131         {
       
   132         // original entry
       
   133         if ( iServerEntry->SetEntry( iSelection->At( i ) ) == KErrNone )
       
   134             {
       
   135             TMsvEntry tEntry = iServerEntry->Entry();
       
   136             TMsvId parent = tEntry.Parent();
       
   137             // If notification in iSelection is in mmbox folder, mark the
       
   138             // possible duplicate notification in inbox too. 
       
   139             if ( parent == iMmsSettings->MMBoxFolder() )
       
   140                 { 
       
   141     #ifndef _NO_MMSS_LOGGING_
       
   142                 TMmsLogger::Log( _L("possible duplicates has to be checked") );
       
   143     #endif            
       
   144                 TInt error = KErrNone;
       
   145                 TRAP ( error, MarkDuplicateL( EMmsNotificationOperationFailed, *iServerEntry ) );
       
   146     #ifndef _NO_MMSS_LOGGING_
       
   147                 TMmsLogger::Log( _L("Trap failed: error %d "), error );
       
   148     #endif
       
   149                 }
       
   150             
       
   151             // reload to make sure any changes are included
       
   152             // (there should be no changes)
       
   153             tEntry = iServerEntry->Entry();
       
   154             MarkNotificationOperationFailed( tEntry );
       
   155             
       
   156             // put to read only state after duplicates have been marked
       
   157             // because MarkDuplicateL may want to edit link to related entry
       
   158             tEntry.SetReadOnly( ETrue );
       
   159             iServerEntry->ChangeEntry( tEntry );        
       
   160 
       
   161             }
       
   162         }
       
   163     }
       
   164 
       
   165 // ---------------------------------------------------------
       
   166 // CMmsDeleteOperation::StartL
       
   167 //
       
   168 // ---------------------------------------------------------
       
   169 //
       
   170 void CMmsDeleteOperation::StartL(
       
   171     TMmsDeleteOperationType aDeleteType,
       
   172     CMsvEntrySelection& aSelection,
       
   173     CMsvServerEntry& aServerEntry,
       
   174     TMsvId aService,
       
   175     TRequestStatus& aStatus )
       
   176     {
       
   177     iDeleteType = aDeleteType;
       
   178     #ifndef _NO_MMSS_LOGGING_
       
   179     TMmsLogger::Log( _L("CMmsDeleteOperation::StartL") );
       
   180     if( iDeleteType == EMmsDeleteNotificationOnly ) TMmsLogger::Log( _L("- EMmsDeleteNotificationOnly") );
       
   181     if( iDeleteType == EMmsDeleteMMBoxOnly ) TMmsLogger::Log( _L("- EMmsDeleteMMBoxOnly") );
       
   182     if( iDeleteType == EMmsDeleteBoth ) TMmsLogger::Log( _L("- EMmsDeleteBoth") );
       
   183     #endif
       
   184     // Make sure the version number is correctly set
       
   185     CMmsBaseOperation::StartL( aSelection, aServerEntry, aService, aStatus );
       
   186     iMmsRequestHeaders->Reset();
       
   187 
       
   188     //
       
   189     // Delete operation does not work as regular operations:
       
   190     //
       
   191     // iFailed list is emptied because retries are not used for delete
       
   192     iFailed->Reset();
       
   193     // iCurrentMessageNo makes no sense in case of delete
       
   194     iCurrentMessageNo = 0;
       
   195     }
       
   196 
       
   197 // ---------------------------------------------------------
       
   198 // CMmsDeleteOperation::StartL
       
   199 // This just overrides the base class version.
       
   200 // ---------------------------------------------------------
       
   201 //
       
   202 void CMmsDeleteOperation::StartL(
       
   203     CMsvEntrySelection&,
       
   204     CMsvServerEntry&,
       
   205     TMsvId,
       
   206     TRequestStatus& )
       
   207     {
       
   208     User::Leave( KErrNotSupported );
       
   209     }
       
   210 
       
   211 // ---------------------------------------------------------
       
   212 // CMmsDeleteOperation::EncodePDUL
       
   213 //
       
   214 // ---------------------------------------------------------
       
   215 //
       
   216 void CMmsDeleteOperation::EncodePDUL()
       
   217     {
       
   218     #ifndef _NO_MMSS_LOGGING_
       
   219     TMmsLogger::Log( _L("CMmsDeleteOperation::EncodePDU") );
       
   220     #endif
       
   221     TInt err = KErrNone;  // used to trap errors that are not propagated further
       
   222    
       
   223     // Go through iSelection and make various checks   
       
   224     TMsvEntry tEntry;
       
   225     for( TInt i = iSelection->Count()-1; i >= 0; i-- )
       
   226         {
       
   227         if ( iServerEntry->SetEntry( iSelection->At( i ) ) == KErrNone )
       
   228             {
       
   229             tEntry = iServerEntry->Entry();
       
   230 
       
   231             // Check that selection contains only "idle" notifications
       
   232             if( ( tEntry.iMtm != KUidMsgMMSNotification ) ||
       
   233                 ( tEntry.iMtm == KUidMsgMMSNotification && 
       
   234                 tEntry.iMtmData2 & KMmsNewOperationForbidden ) )
       
   235                 {
       
   236                 // Take out all non-notifications and notifications that have some operation ongoing
       
   237     #ifndef _NO_MMSS_LOGGING_
       
   238     TMmsLogger::Log( _L( "- notif not idle, skipping" ) );
       
   239     #endif
       
   240                 iSelection->Delete( i );
       
   241                 }
       
   242             else
       
   243                 {
       
   244                 // If only local delete requested, delete the entry
       
   245                 if( iDeleteType == EMmsDeleteNotificationOnly )
       
   246                     {
       
   247     #ifndef _NO_MMSS_LOGGING_
       
   248     TMmsLogger::Log( _L( "- just deleting the notif entry" ) );
       
   249     #endif
       
   250                     TRAP( err, DeleteNotificationEntryL() );
       
   251     #ifndef _NO_MMSS_LOGGING_
       
   252                     if( err != KErrNone )
       
   253                         {
       
   254                         TMmsLogger::Log( _L( "- ERROR: DeleteNotificationEntryL left" ) );
       
   255                         }
       
   256     #endif
       
   257                     iSelection->Delete( i );
       
   258                     }
       
   259                 else // EMmsDeleteMMBoxOnly OR EMmsDeleteBoth
       
   260                     {
       
   261     #ifndef _NO_MMSS_LOGGING_
       
   262     TMmsLogger::Log( _L( "- mmbox deletion wanted" ) );
       
   263     #endif
       
   264                     // Is there a message in MMBox.
       
   265                     if( !(tEntry.iMtmData2 & KMmsStoredInMMBox ) )
       
   266                         {
       
   267                         // No need to care about possible duplicate notification. 
       
   268     #ifndef _NO_MMSS_LOGGING_
       
   269     TMmsLogger::Log( _L( "- accordig to mmbox flag, message is not in mmbox" ) );
       
   270     #endif
       
   271                         // If both requested, but no message in MMBox,
       
   272                         // just delete the notification.
       
   273                         if( iDeleteType == EMmsDeleteBoth )
       
   274                             {                        
       
   275     #ifndef _NO_MMSS_LOGGING_
       
   276     TMmsLogger::Log( _L( "- local deletion requested, performing it" ) );
       
   277     #endif
       
   278                             TRAP( err, DeleteNotificationEntryL() );
       
   279     #ifndef _NO_MMSS_LOGGING_
       
   280                             if( err != KErrNone )
       
   281                                 {
       
   282                                 TMmsLogger::Log( _L( "- ERROR: DeleteNotificationEntryL left" ) );
       
   283                                 }
       
   284     #endif
       
   285                             }
       
   286                         else // iDeleteType == EMmsDeleteMMBoxOnly
       
   287                             {
       
   288     #ifndef _NO_MMSS_LOGGING_
       
   289     TMmsLogger::Log( _L( "- can not delete from mmbox, clearing entry flags" ) );
       
   290     #endif
       
   291                             MarkNotificationOperationFailed( tEntry );
       
   292                             tEntry.SetReadOnly( ETrue );
       
   293                             iServerEntry->ChangeEntry( tEntry );
       
   294                             }
       
   295                         // As message not in MMBox, delete entry from selection
       
   296                         iSelection->Delete( i );
       
   297                         }
       
   298                     }
       
   299                 }
       
   300             }
       
   301         else
       
   302             {
       
   303             // take out an entry that could not be accessed
       
   304             iSelection->Delete( i );
       
   305             }
       
   306         }
       
   307 
       
   308     // delete from mmbox is wanted and the notifications are stored in mmbox
       
   309     // Check duplicates, if the parent is in mmbox folder.
       
   310     
       
   311     // If duplicate is found, check if the duplicate is free. 
       
   312     // If the duplicate is free, mark the duplicate as "deleting operation going on". 
       
   313     // If duplicate is not free, drop the original notification from iSelection.
       
   314 
       
   315     for ( TInt j = iSelection->Count()-1; j >= 0; j-- )
       
   316         {
       
   317         if ( iServerEntry->SetEntry( iSelection->At( j ) ) == KErrNone ) 
       
   318             {
       
   319             // if original notification cannot be accessed there is no way
       
   320             // to check the notification
       
   321             tEntry = iServerEntry->Entry();
       
   322 
       
   323             if ( tEntry.Parent() == iMmsSettings->MMBoxFolder() )
       
   324                 {
       
   325     #ifndef _NO_MMSS_LOGGING_
       
   326     TMmsLogger::Log( _L( "- check if duplicate is found" ) );
       
   327     #endif
       
   328                 // parent is mmbox folder.
       
   329                 CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
       
   330                 CleanupStack::PushL( mmsHeaders ); 
       
   331                 CMsvStore* store = iServerEntry->ReadStoreL();
       
   332                 CleanupStack::PushL( store );           
       
   333                 mmsHeaders->RestoreL( *store );
       
   334                 CleanupStack::PopAndDestroy( store );
       
   335                 store = NULL;
       
   336 
       
   337                 TMsvId duplicate = KMsvNullIndexEntryId;
       
   338                 FindDuplicateNotificationL( KMsvGlobalInBoxIndexEntryIdValue,
       
   339                     *mmsHeaders, duplicate );
       
   340                     
       
   341                 if ( duplicate != KMsvNullIndexEntryId )
       
   342                     {
       
   343     #ifndef _NO_MMSS_LOGGING_
       
   344     TMmsLogger::Log( _L( "- duplicate found" ) );
       
   345     #endif
       
   346                     if ( iServerEntry->SetEntry( duplicate ) == KErrNone )
       
   347                         {
       
   348                         // Mark duplicate, if it is free for a new operation
       
   349                         TMsvEntry dupEntry = iServerEntry->Entry();
       
   350 
       
   351                         if ( FreeNotification( dupEntry, KMmsOperationDelete ) )
       
   352                             {
       
   353     #ifndef _NO_MMSS_LOGGING_
       
   354                             TMmsLogger::Log( _L( "- Marking duplicate" ) );
       
   355     #endif
       
   356                             MarkNotificationOperationReserved( dupEntry, KMmsOperationDelete );
       
   357                         
       
   358                             iServerEntry->ChangeEntry( dupEntry );
       
   359 
       
   360                             // Set duplicate as related entry to the original notification
       
   361                             if ( iServerEntry->SetEntry( iSelection->At( j ) ) == KErrNone )
       
   362                                 {
       
   363                                 tEntry = iServerEntry->Entry();
       
   364                                 tEntry.SetReadOnly( EFalse );
       
   365                                 iServerEntry->ChangeEntry( tEntry );
       
   366 
       
   367                                 store = iServerEntry->EditStoreL();
       
   368                                 CleanupStack::PushL( store );
       
   369                                 mmsHeaders->RestoreL( *store );
       
   370 
       
   371                                 mmsHeaders->SetRelatedEntry( duplicate );
       
   372                                 mmsHeaders->StoreL( *store );
       
   373                                 store->CommitL();
       
   374                                 CleanupStack::PopAndDestroy( store );
       
   375                                 store = NULL;
       
   376                                 }
       
   377                             }
       
   378                         else
       
   379                             {
       
   380                             // duplicate is not free, drop the original from iSelection. 
       
   381     #ifndef _NO_MMSS_LOGGING_
       
   382     TMmsLogger::Log( _L( "- Duplicate is not free, drop the original notification from selection" ) );
       
   383     #endif
       
   384                             iSelection->Delete( j );
       
   385                             }
       
   386                         }
       
   387                     }
       
   388                 CleanupStack::PopAndDestroy( mmsHeaders );
       
   389                 }
       
   390             }
       
   391         }
       
   392     
       
   393     // iSelection contains notifications that are deleted from mmbox
       
   394     // Mark notifications as "deleting operation going on"
       
   395 
       
   396     for ( TInt k = iSelection->Count()-1; k >= 0; k--  )
       
   397         {
       
   398         if ( iServerEntry->SetEntry( iSelection->At( k ) ) == KErrNone )
       
   399             {
       
   400             tEntry = iServerEntry->Entry();
       
   401     #ifndef _NO_MMSS_LOGGING_
       
   402             TMmsLogger::Log( _L( "- reserve notif for deletion" ) );
       
   403     #endif
       
   404 
       
   405             // Mark all remaining notifications as operation-ongoing
       
   406             // operation is from now on delete
       
   407             MarkNotificationOperationReserved( tEntry, KMmsOperationDelete );
       
   408             
       
   409             tEntry.SetReadOnly( EFalse );   
       
   410             iServerEntry->ChangeEntry( tEntry );
       
   411             }
       
   412         }
       
   413     // 
       
   414     // If remote delete is required, creating PDU to be sent
       
   415     //
       
   416     if( ( iDeleteType != EMmsDeleteNotificationOnly ) && 
       
   417         ( iSelection->Count() > 0 ) )
       
   418         {
       
   419 #ifndef _NO_MMSS_LOGGING_
       
   420 TMmsLogger::Log( _L( "- creating PDU" ) );
       
   421 #endif
       
   422         //
       
   423         // Create headers structure
       
   424         //
       
   425         // iMmsRequestHeaders is a member that has been created in the constructor
       
   426         // And Reset in the StartL function
       
   427 
       
   428         // MessageType
       
   429         iMmsRequestHeaders->SetMessageType( KMmsMessageTypeMBoxDeleteReq );
       
   430 
       
   431         // TransactionId
       
   432         TBufC8<KMMSMAXTIDLENGTH> tid;
       
   433         tid.Des().NumUC( AllocateTID(), EHex );
       
   434         iMmsRequestHeaders->SetTidL( tid );
       
   435 
       
   436         //
       
   437         // Content-Location array
       
   438         // Loop through selection and put all content locations into array
       
   439         //
       
   440         CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
       
   441         CleanupStack::PushL( mmsHeaders ); // ***
       
   442         for( TInt i = iSelection->Count() - 1; i >= 0; i-- )
       
   443             {
       
   444             // Get entry
       
   445             if ( iServerEntry->SetEntry( iSelection->At( i ) ) == KErrNone )
       
   446                 {
       
   447                 // Get read-only message store
       
   448                 CMsvStore* store = iServerEntry->ReadStoreL();
       
   449                 CleanupStack::PushL( store ); // ***
       
   450                 // Restore all parts of multimedia message
       
   451                 mmsHeaders->RestoreL( *store );
       
   452 
       
   453                 // Add array to headers
       
   454                 iMmsRequestHeaders->MMBoxMessageHeadersL().ContentLocationList()
       
   455                     .AppendL( mmsHeaders->ContentLocation() );
       
   456                 CleanupStack::PopAndDestroy( store );
       
   457                 }
       
   458             }
       
   459         CleanupStack::PopAndDestroy( mmsHeaders );
       
   460 
       
   461         //
       
   462         // Encode the PDU
       
   463         //
       
   464         iEncoder->EncodeHeadersL( *iMmsRequestHeaders, *iEncodeBuffer );
       
   465         }
       
   466 
       
   467     iServerEntry->SetEntry( KMsvNullIndexEntryId );
       
   468     FallThrough();
       
   469     }
       
   470 
       
   471 // ---------------------------------------------------------
       
   472 // CMmsDeleteOperation::ConnectToIAPL
       
   473 //
       
   474 // ---------------------------------------------------------
       
   475 //
       
   476 void CMmsDeleteOperation::ConnectToIAPL()
       
   477     {
       
   478     #ifndef _NO_MMSS_LOGGING_
       
   479     TMmsLogger::Log( _L("CMmsDeleteOperation::ConnectToIAPL") );
       
   480     #endif
       
   481 
       
   482     if( iDeleteType == EMmsDeleteNotificationOnly || iSelection->Count() == 0 )
       
   483         {
       
   484         FallThrough();
       
   485         }
       
   486     else 
       
   487         {
       
   488         CMmsBaseOperation::ConnectToIAPL();
       
   489         }
       
   490     }
       
   491 
       
   492 // ---------------------------------------------------------
       
   493 // CMmsDeleteOperation::InitializeSessionL
       
   494 //
       
   495 // ---------------------------------------------------------
       
   496 //
       
   497 void CMmsDeleteOperation::InitializeSessionL()
       
   498     {
       
   499     #ifndef _NO_MMSS_LOGGING_
       
   500     TMmsLogger::Log( _L("CMmsDeleteOperation::InitializeSessionL") );
       
   501     #endif
       
   502 
       
   503     if( iDeleteType == EMmsDeleteNotificationOnly || iSelection->Count() == 0 )
       
   504         {
       
   505         FallThrough();
       
   506         }
       
   507     else 
       
   508         {
       
   509         CMmsBaseOperation::InitializeSessionL();
       
   510         }
       
   511     }
       
   512 
       
   513 // ---------------------------------------------------------
       
   514 // CMmsDeleteOperation::SubmitTransactionL
       
   515 //
       
   516 // ---------------------------------------------------------
       
   517 //
       
   518 void CMmsDeleteOperation::SubmitTransactionL()
       
   519     {
       
   520 #ifndef _NO_MMSS_LOGGING_
       
   521     TMmsLogger::Log( _L("CMmsDeleteOperation::SubmitTransactionL"));
       
   522 #endif
       
   523     //
       
   524     // Maybe networking not needed at all
       
   525     // 
       
   526     if( iDeleteType == EMmsDeleteNotificationOnly || iSelection->Count() == 0 )
       
   527         {
       
   528         FallThrough();
       
   529         return;
       
   530         }
       
   531         
       
   532     // This check is needed only when running tests in local mode
       
   533     // if length of URI is 0, Symbian code will panic    
       
   534     if ( !iUri )
       
   535         {
       
   536         iError = KMmsErrorNoURI1;
       
   537         }
       
   538     else if ( iUri->Des().Length() == 0 )
       
   539         {
       
   540         iError = KMmsErrorNoURI1;
       
   541         }
       
   542     else
       
   543         {
       
   544         // keep LINT happy
       
   545         }
       
   546 
       
   547     //
       
   548     // Networking is needed. Is connection open.
       
   549     //
       
   550     if ( !iConnected )
       
   551         {
       
   552         if ( iError == KErrNone )
       
   553             {
       
   554             iError = KErrCouldNotConnect;
       
   555             }
       
   556         }
       
   557         
       
   558     //
       
   559     // If something has gone wrong, just fall through
       
   560     // 
       
   561     if ( iError != KErrNone )
       
   562         {
       
   563         FallThrough();
       
   564         return;
       
   565         }
       
   566 
       
   567     //
       
   568     // Send
       
   569     //
       
   570     iMmsSession->SendMessageL(
       
   571         iUri->Des(),
       
   572         *iEncodeBuffer,
       
   573         *iEncoder,
       
   574         *iDecoder,
       
   575         iStatus );
       
   576     SetActive();
       
   577     }
       
   578 
       
   579 // ---------------------------------------------------------
       
   580 // CMmsDeleteOperation::DecodeResponseL()
       
   581 //
       
   582 // ---------------------------------------------------------
       
   583 //
       
   584 void CMmsDeleteOperation::DecodeResponseL()
       
   585     {
       
   586 #ifndef _NO_MMSS_LOGGING_
       
   587     TMmsLogger::Log( _L( "CMmsDeleteOperation::DecodeResponseL()" ) );
       
   588 #endif
       
   589 
       
   590     if( iDeleteType != EMmsDeleteNotificationOnly && iSelection->Count() > 0 )
       
   591         {
       
   592         // iError is checked in base class method.
       
   593         CMmsBaseOperation::DecodeResponseL();
       
   594         }
       
   595     else
       
   596         {
       
   597         FallThrough();
       
   598         }
       
   599     }
       
   600 
       
   601 // ---------------------------------------------------------
       
   602 // CMmsDeleteOperation::UpdateEntryStatusL
       
   603 //
       
   604 // ---------------------------------------------------------
       
   605 //
       
   606 void CMmsDeleteOperation::UpdateEntryStatusL()
       
   607     {
       
   608 #ifndef _NO_MMSS_LOGGING_
       
   609     TMmsLogger::Log( _L( "CMmsDeleteOperation::UpdateEntryStatusL()" ) );
       
   610     TMmsLogger::Log( _L( "- Number of ids in iSelection: %d" ), iSelection->Count() );
       
   611 #endif
       
   612 
       
   613     if( iDeleteType == EMmsDeleteNotificationOnly || iSelection->Count() == 0 )
       
   614         {
       
   615         FallThrough();
       
   616         return;
       
   617         }
       
   618                 
       
   619     //
       
   620     // If error has occurred and there is nothing received from the network,
       
   621     // just correcting the flags in the notification entries as they were before.
       
   622     //
       
   623     if( iError != KErrNone )
       
   624         {
       
   625         #ifndef _NO_MMSS_LOGGING_
       
   626         TMmsLogger::Log( _L( "- error has occurred" ) );
       
   627         #endif
       
   628         MarkSelectionAsFailed();
       
   629         FallThrough();
       
   630         return;
       
   631         }
       
   632     //
       
   633     // Following is the the default behaviour: no errors, response received
       
   634     //
       
   635     else
       
   636         {
       
   637         #ifndef _NO_MMSS_LOGGING_
       
   638         TMmsLogger::Log( _L( "- no errors" ) );
       
   639         #endif
       
   640 
       
   641         //
       
   642         // Get delete result array from response
       
   643         //
       
   644         const RPointerArray<CMmsDeleteResultArray>& resultArray
       
   645             = iResponse->DeleteResultArray();
       
   646         #ifndef _NO_MMSS_LOGGING_
       
   647         TMmsLogger::Log( _L( "- resultarray length: %d" ), iResponse->DeleteResultArray().Count() );
       
   648         #endif
       
   649 
       
   650         //
       
   651         // Make overall check for the response before checking each entry separately
       
   652         // First, messagetype
       
   653         //
       
   654         if( iResponse->MessageType() != KMmsMessageTypeMBoxDeleteConf )
       
   655             {
       
   656             #ifndef _NO_MMSS_LOGGING_
       
   657             TMmsLogger::Log( _L( "- ERROR: Response has wrong message type!" ) );
       
   658             #endif
       
   659             MarkSelectionAsFailed();
       
   660             FallThrough();
       
   661             return;
       
   662             }
       
   663         // Second, if result array contains status Unsupported-Message with no
       
   664         // related Content-Location, the transaction is interpreted as failed.
       
   665         for( TInt j = 0; j < resultArray.Count(); j++ )
       
   666             {
       
   667             if( resultArray[j]->ContentLocation().Length() == 0 && 
       
   668                 resultArray[j]->ResponseStatus() == KMmsErrorStatusUnsupportedMessage )
       
   669                 {
       
   670                 // If array contains item that has no Content-Location,
       
   671                 // something is wrong
       
   672                 #ifndef _NO_MMSS_LOGGING_
       
   673                 TMmsLogger::Log( _L( "- Response contains response-status with no corresponding ContentLocation!" ) );
       
   674                 TMmsLogger::Log( _L( "  Interpreting this as delete failure." ) );
       
   675                 #endif
       
   676                 MarkSelectionAsFailed();
       
   677                 FallThrough();
       
   678                 return;
       
   679                 }
       
   680             }
       
   681 
       
   682         //
       
   683         // Moving from response level checks into entry level checks...
       
   684         //
       
   685         // Loop through iSelection to separate failed and successful ones
       
   686         // (contains notifications that were sent to network)
       
   687         //
       
   688         CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
       
   689         CleanupStack::PushL( mmsHeaders );
       
   690         for( TInt i = iSelection->Count(); i > 0; i-- )
       
   691             {
       
   692             #ifndef _NO_MMSS_LOGGING_
       
   693             TMmsLogger::Log( _L( "- looping in iSelection[%d]" ), i-1 );
       
   694             #endif
       
   695             // Get Content-location of this notification
       
   696             if ( iServerEntry->SetEntry( iSelection->At( i-1 ) ) == KErrNone )
       
   697                 {
       
   698                 CMsvStore* store = iServerEntry->ReadStoreL();
       
   699                 CleanupStack::PushL( store );
       
   700                 mmsHeaders->RestoreL( *store );
       
   701                 CleanupStack::PopAndDestroy( store );
       
   702                 store = NULL;
       
   703                 #ifndef _NO_MMSS_LOGGING_
       
   704                 TMmsLogger::Log( _L( "- store read" ) );
       
   705                 #endif            
       
   706                 TPtrC8 pContentLocation = mmsHeaders->ContentLocation();
       
   707                 TMsvId duplicate = mmsHeaders->RelatedEntry();
       
   708 
       
   709                 //
       
   710                 // Search for the same content-location from response PDU
       
   711                 // (if it is found, it's mmbox delete has failed)
       
   712                 //
       
   713                 TBool bMmboxDeleteSucceeded = ETrue;
       
   714                 for ( TInt j = 0; j < resultArray.Count(); j++ )
       
   715                     {
       
   716                     // Check match
       
   717                     #ifndef _NO_MMSS_LOGGING_
       
   718                     TMmsLogger::Log( _L( "- looping in resultArray[%d]" ), j );
       
   719                     #endif
       
   720                     if( resultArray[j]->ContentLocation().Compare( pContentLocation ) == 0 )
       
   721                         {
       
   722                         // Get response status that will be investigated next
       
   723                         TInt32 responseStatus = resultArray[j]->ResponseStatus();
       
   724                         #ifndef _NO_MMSS_LOGGING_
       
   725                         TMmsLogger::Log( _L( "- Match found. X-Mms-Response-Status == %d" ), responseStatus );
       
   726                         #endif
       
   727                         // Found a match, now check the reason
       
   728                         if( responseStatus != KMmsStatusOk &&
       
   729                             responseStatus != KMmsErrorMessageNotFound && // this should not be used by the server
       
   730                             responseStatus != KMmsErrorPermanentMessageNotFound )
       
   731                             {
       
   732                             #ifndef _NO_MMSS_LOGGING_
       
   733                             TMmsLogger::Log( _L( "- delete did not succeed for this notif" ) );
       
   734                             #endif
       
   735                             // This entry failed, removing it from iSelection
       
   736                             iSelection->Delete( i-1 );
       
   737                             bMmboxDeleteSucceeded = EFalse;
       
   738 
       
   739                             // Notification will not be deleted any longer regardless of iDeleteType
       
   740                             // Correcting the notification entry
       
   741                             // StoredInMMBox flag value not changed.
       
   742                             #ifndef _NO_MMSS_LOGGING_
       
   743                             TMmsLogger::Log( _L( "- clearing entry flags" ) );
       
   744                             #endif
       
   745 
       
   746                             // if the original notification is in mmbox folder and a duplicate is found,
       
   747                             // mark the status of the duplicate notification too. 
       
   748 
       
   749                             if ( duplicate != KMsvNullIndexEntryId &&
       
   750                                 iServerEntry->Entry().Parent() == iMmsSettings->MMBoxFolder() )
       
   751                                 {
       
   752                                 #ifndef _NO_MMSS_LOGGING_
       
   753                                 TMmsLogger::Log( _L(
       
   754                                     "- duplicate exists and original notification is in mmbox folder" )
       
   755                                     );
       
   756                                 #endif
       
   757                                 // Clear related entry from the original notification
       
   758                                 // and mark the duplicate as failed
       
   759                                 TRAP_IGNORE( MarkDuplicateL(
       
   760                                     EMmsNotificationOperationFailed, *iServerEntry ) );
       
   761                                 }
       
   762 
       
   763                             // Mark original notification. iServerEntry still points to it
       
   764                             TMsvEntry tEntry = iServerEntry->Entry();
       
   765                             MarkNotificationOperationFailed( tEntry );
       
   766                             tEntry.SetReadOnly( ETrue );
       
   767                             iServerEntry->ChangeEntry( tEntry );
       
   768                             #ifndef _NO_MMSS_LOGGING_
       
   769                             TMmsLogger::Log( _L( "- original marked failed" ) );
       
   770                             #endif
       
   771                             }
       
   772                         }
       
   773                     } // inner for loop (resultArray)
       
   774 
       
   775                 // Has the current entry been deleted from mmbox...
       
   776                 if( bMmboxDeleteSucceeded )
       
   777                     {
       
   778                     #ifndef _NO_MMSS_LOGGING_
       
   779                     TMmsLogger::Log( _L( "- this notification was deleted from mmbox" ) );
       
   780                     #endif
       
   781                     
       
   782                     if ( iServerEntry->SetEntry( iSelection->At( i-1 ) ) == KErrNone )
       
   783                         {
       
   784                         // if notification is in inbox, check if a duplicate exits in mmbox folder
       
   785                         if ( iServerEntry->Entry().Parent() == KMsvGlobalInBoxIndexEntryIdValue )
       
   786                             {
       
   787                             TMsvId mmboxFolder = iMmsSettings->MMBoxFolder();
       
   788                             if ( mmboxFolder != KMsvNullIndexEntryId )
       
   789                                 {
       
   790                                 #ifndef _NO_MMSS_LOGGING_
       
   791                                 TMmsLogger::Log( _L( "- original notification is in inbox" ) );
       
   792                                 TMmsLogger::Log( _L( "- finding duplicate from mmbox inbox" ) );
       
   793                                 #endif
       
   794                                 FindDuplicateNotificationL( mmboxFolder, *mmsHeaders, duplicate );
       
   795                                 }
       
   796                             }
       
   797                         
       
   798                         // if duplicate exits, mark it as "deleted successfully from mmbox"
       
   799                         if ( duplicate != KMsvNullIndexEntryId )
       
   800                             {
       
   801                             #ifndef _NO_MMSS_LOGGING_
       
   802                             TMmsLogger::Log( _L( "- duplicate exists" ) );
       
   803                             #endif
       
   804                             
       
   805                             // iServerEntry should still be pointing to the original notification
       
   806                             
       
   807                             // Clear related entry from the original notification
       
   808                             // and mark the duplicate as "deleted from mmbox"
       
   809                             TRAP_IGNORE( MarkDuplicateL( EMmsDeletedFromMmbox, *iServerEntry ) )
       
   810                             }
       
   811 
       
   812                         // Should notification also be deleted...
       
   813                         if( iDeleteType == EMmsDeleteBoth )
       
   814                             {
       
   815                             #ifndef _NO_MMSS_LOGGING_
       
   816                             TMmsLogger::Log( _L( "- about to delete notif entry" ) );
       
   817                             #endif
       
   818                             DeleteNotificationEntryL();
       
   819                             }
       
   820                         else // deletetype not equal to delete-both
       
   821                             {
       
   822                             #ifndef _NO_MMSS_LOGGING_
       
   823                             TMmsLogger::Log( _L( "- clearing notif flags" ) );
       
   824                             #endif
       
   825                             TMsvEntry tEntry = iServerEntry->Entry();
       
   826                             tEntry.iMtmData2 &= ~KMmsStoredInMMBox;         // not-stored-in-mmbox
       
   827                             tEntry.iMtmData2 &= ~KMmsNewOperationForbidden; // operations allowed
       
   828                             tEntry.iMtmData2 &= ~KMmsOperationOngoing;      // not ongoing
       
   829                             tEntry.iMtmData2 |= KMmsOperationFinished;      // finished
       
   830                             tEntry.iMtmData2 &= ~KMmsOperationResult;       // OK
       
   831                             tEntry.SetReadOnly( ETrue );
       
   832                             iServerEntry->ChangeEntry( tEntry );
       
   833                             }
       
   834                         }
       
   835                     }
       
   836                 }
       
   837             } // outer for loop (iSelection)
       
   838         CleanupStack::PopAndDestroy( mmsHeaders );
       
   839         }
       
   840     iServerEntry->SetEntry( KMsvNullIndexEntryId );
       
   841     FallThrough();    
       
   842     }
       
   843 
       
   844 // ---------------------------------------------------------
       
   845 // CMmsDeleteOperation::DeleteNotificationEntryL
       
   846 //
       
   847 // ---------------------------------------------------------
       
   848 //
       
   849 void CMmsDeleteOperation::DeleteNotificationEntryL()
       
   850     {
       
   851     #ifndef _NO_MMSS_LOGGING_
       
   852     TMmsLogger::Log( _L( "CMmsDeleteOperation::DeleteNotificationEntryL()" ) );
       
   853     #endif
       
   854     // Get indexentry
       
   855     TMsvEntry tEntry = iServerEntry->Entry(); 
       
   856     TInt error = iServerEntry->SetEntry( tEntry.Parent());
       
   857     if ( error == KErrNone )
       
   858         {
       
   859         // Can delete entry only if setting entry to parent was successful
       
   860         iServerEntry->DeleteEntry( tEntry.Id() );        
       
   861         }
       
   862     iServerEntry->SetEntry( KMsvNullIndexEntryId );
       
   863     }
       
   864 
       
   865 // ---------------------------------------------------------
       
   866 // CMmsDeleteOperation::MarkSelectionAsFailed
       
   867 //
       
   868 // ---------------------------------------------------------
       
   869 //
       
   870 void CMmsDeleteOperation::MarkSelectionAsFailed()
       
   871     {
       
   872     #ifndef _NO_MMSS_LOGGING_
       
   873     TMmsLogger::Log( _L( "CMmsDeleteOperation::MarkSelectionAsFailed()" ) );
       
   874     #endif
       
   875 
       
   876     // Loop through iSelection
       
   877     for( TInt i = iSelection->Count(); i > 0; i-- )
       
   878         {
       
   879         TInt error = KErrNone;
       
   880         error = iServerEntry->SetEntry( iSelection->At( i-1 ) );
       
   881         if ( error == KErrNone )
       
   882             {
       
   883             // If notification in iSelection is in mmbox folder, mark the
       
   884             // possible duplicate notification in inbox too. 
       
   885             if ( iServerEntry->Entry().Parent() == iMmsSettings->MMBoxFolder() )
       
   886                 {
       
   887 #ifndef _NO_MMSS_LOGGING_
       
   888                 TMmsLogger::Log( _L( "- check possible duplicate" ) );
       
   889 #endif
       
   890                 TRAP ( error, MarkDuplicateL( EMmsNotificationOperationFailed, *iServerEntry ) );
       
   891 #ifndef _NO_MMSS_LOGGING_
       
   892                 TMmsLogger::Log( _L("Trap failed: error %d "), error );
       
   893 #endif
       
   894                 }
       
   895 
       
   896             // Mark the original notification in selection
       
   897             // MarkDuplicateL does not mess up the original context of iServerEntry
       
   898             TMsvEntry tEntry = iServerEntry->Entry();
       
   899             MarkNotificationOperationFailed( tEntry );
       
   900             tEntry.SetReadOnly( ETrue );
       
   901             error = iServerEntry->ChangeEntry( tEntry );
       
   902 #ifndef _NO_MMSS_LOGGING_
       
   903             if( error != KErrNone )
       
   904                 {
       
   905                 TMmsLogger::Log( _L( "ERROR: ChangeEntry() failed" ) );
       
   906                 }
       
   907             else
       
   908                 {
       
   909                 TMmsLogger::Log( _L( "- selection[%d] flags are cleared" ), i );
       
   910                 }
       
   911 #endif
       
   912             }
       
   913         }
       
   914     iServerEntry->SetEntry( KMsvNullIndexEntryId );
       
   915 
       
   916     }
       
   917 
       
   918 // ================= OTHER EXPORTED FUNCTIONS ==============
       
   919 
       
   920 //  End of File