mmsengine/mmsserver/src/mmssendoperation.cpp
changeset 31 ebfee66fde93
child 47 5b14749788d7
child 52 12db4185673b
equal deleted inserted replaced
30:6a20128ce557 31:ebfee66fde93
       
     1 /*
       
     2 * Copyright (c) 2005-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 messages
       
    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 // LOCAL INCLUDE FILES
       
    32 #include    "mmsconst.h"
       
    33 #include    "mmssendoperation.h"
       
    34 #include    "mmssession.h"
       
    35 #include    "mmssettings.h"
       
    36 #include    "mmsservercommon.h"
       
    37 #include    "mmsheaders.h"
       
    38 #include    "mmsencode.h"
       
    39 #include    "mmsdecode.h"
       
    40 #include    "mmsscheduledentry.h"
       
    41 #include    "mmsgenutils.h"
       
    42 #include    "mmslog.h"
       
    43 #include    "mmserrors.h"
       
    44 #include    "mmsserverentry.h"
       
    45 #include    "mmsconninit.h"
       
    46 #include    "MmsServerDebugLogging.h"
       
    47 
       
    48 // EXTERNAL DATA STRUCTURES
       
    49 
       
    50 // EXTERNAL FUNCTION PROTOTYPES  
       
    51 extern void gPanic( TMmsPanic aPanic );
       
    52 
       
    53 // CONSTANTS
       
    54 
       
    55 // MACROS
       
    56 // LOCAL CONSTANTS AND MACROS
       
    57 // MODULE DATA STRUCTURES
       
    58 // LOCAL FUNCTION PROTOTYPES
       
    59 // ==================== LOCAL FUNCTIONS ====================
       
    60 // ================= MEMBER FUNCTIONS =======================
       
    61 
       
    62 // ---------------------------------------------------------
       
    63 // CMmsSendOperation
       
    64 // ---------------------------------------------------------
       
    65 //
       
    66 CMmsSendOperation::CMmsSendOperation( RFs& aFs ): CMmsBaseOperation( aFs )
       
    67     // members that get initial value 0, need not be initialized here
       
    68     {
       
    69     }
       
    70 
       
    71 // ---------------------------------------------------------
       
    72 // ConstructL
       
    73 // ---------------------------------------------------------
       
    74 //
       
    75 void CMmsSendOperation::ConstructL( CMmsSettings* aMmsSettings )
       
    76     {
       
    77     CMmsBaseOperation::ConstructL( aMmsSettings );
       
    78     iMmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() );
       
    79     // iSent is just a copy to retain old name for the time being.
       
    80     iSent = iSuccessful;
       
    81     User::LeaveIfError( iShareProtectedFileSession.Connect() );
       
    82     iShareProtectedFileSessionOpened = ETrue;
       
    83     User::LeaveIfError( iShareProtectedFileSession.ShareProtected() ); 
       
    84     CActiveScheduler::Add( this );
       
    85     }
       
    86 
       
    87 // ---------------------------------------------------------
       
    88 // NewL
       
    89 // ---------------------------------------------------------
       
    90 //
       
    91 CMmsSendOperation* CMmsSendOperation::NewL( RFs& aFs, CMmsSettings* aMmsSettings )
       
    92     {
       
    93     CMmsSendOperation* self = new ( ELeave ) CMmsSendOperation( aFs );
       
    94     CleanupStack::PushL( self );
       
    95     self->ConstructL( aMmsSettings );
       
    96     CleanupStack::Pop( self );
       
    97     return self;
       
    98     }
       
    99     
       
   100 // ---------------------------------------------------------
       
   101 // ~CMmsSendOperation
       
   102 // ---------------------------------------------------------
       
   103 //
       
   104 CMmsSendOperation::~CMmsSendOperation()
       
   105     {
       
   106     Cancel();
       
   107     
       
   108     if ( iShareProtectedFileSessionOpened )
       
   109         {
       
   110         iShareProtectedFileSession.Close();
       
   111         }
       
   112     
       
   113     // iSelection, iServerEntry, and iMmsSettings
       
   114     // are not deleted, because they belong to caller
       
   115 
       
   116     // iSent is not deleted because it is just a copy of iSuccessful
       
   117 
       
   118     delete iMmsHeaders;
       
   119     }
       
   120 
       
   121 // ---------------------------------------------------------
       
   122 // StartL
       
   123 // ---------------------------------------------------------
       
   124 //
       
   125 void CMmsSendOperation::StartL(
       
   126     CMsvEntrySelection& aSelection,
       
   127     CMsvServerEntry& aServerEntry,
       
   128     TMsvId aService,
       
   129     TRequestStatus& aStatus )
       
   130     {
       
   131     LOG(_L("CMmsSendOperation::StartL") );
       
   132     
       
   133     __ASSERT_DEBUG( iState==EMmsOperationIdle, gPanic( EMmsAlreadyBusy ) );
       
   134     CMmsBaseOperation::StartL( aSelection, aServerEntry, aService, aStatus );
       
   135     iMmsHeaders->Reset();
       
   136     }
       
   137 
       
   138 // ---------------------------------------------------------
       
   139 // EncodePDUL
       
   140 // ---------------------------------------------------------
       
   141 //
       
   142 void CMmsSendOperation::EncodePDUL()
       
   143     {
       
   144     LOG( _L("CMmsSendOperation::EncodePDUL") );
       
   145     
       
   146     CMsvStore* store = NULL;
       
   147     // In case of multiple entries, iError is reset here on every round
       
   148     // (because EncodePDUL starts the round)
       
   149     iError = iServerEntry->SetEntry( iSelection->At( iCurrentMessageNo - 1 ) );
       
   150 
       
   151     // If user tries to delete the entry before it has been sent,
       
   152     // it is first put to suspended state, and then deleted.
       
   153     // If entry is suspended -> message will not be sent
       
   154     if( iError == KErrNone )
       
   155         {
       
   156         if( iServerEntry->Entry().SendingState() == KMsvSendStateSuspended ||
       
   157             iServerEntry->Entry().Deleted() )
       
   158             {
       
   159             // All activity stopped with this entry
       
   160             iError = KErrNotFound;
       
   161 #ifndef _NO_MMSS_LOGGING_
       
   162             if( iServerEntry->Entry().SendingState() == KMsvSendStateSuspended )
       
   163                 {
       
   164                 LOG( _L("- message in suspended state") );
       
   165                 }
       
   166             if( iServerEntry->Entry().Deleted() )
       
   167                 {
       
   168                 LOG( _L("- message in deleted state") );
       
   169                 }
       
   170 #endif
       
   171             }
       
   172         }    
       
   173 #ifndef _NO_MMSS_LOGGING_
       
   174     else
       
   175         {
       
   176         LOG2( _L("- ERROR in SetEntry(): %d"), iError );
       
   177         }
       
   178 #endif
       
   179 
       
   180     // Check if message contains closed content that should not be sent
       
   181     // ContainsClosedContentL leaves only if memory runs out
       
   182     
       
   183     if ( iError == KErrNone )
       
   184         {
       
   185         iError = CheckClosedContentL( *iServerEntry, iShareProtectedFileSession );
       
   186         }
       
   187 
       
   188     // Attempt to delete the message after this point will come too late,
       
   189     // and the message will be sent
       
   190     if( iError == KErrNone )
       
   191         {
       
   192         TRAP( iError, store = iServerEntry->EditStoreL(); )
       
   193         }
       
   194     if( iError == KErrNone )
       
   195         {
       
   196         CleanupStack::PushL( store ); // ***
       
   197         }
       
   198         
       
   199     // If error encountered quit here.
       
   200     if( iError != KErrNone )
       
   201         {
       
   202         FallThrough();
       
   203         return;
       
   204         }
       
   205         
       
   206     // Restore the message in order to encode it into binary
       
   207     // if RestoreL leaves -> serious OOM condition -> cannot continue.
       
   208     iMmsHeaders->RestoreL( *store );
       
   209 
       
   210     // Adding TID. If found already (retrying..), using it.
       
   211     if ( iMmsHeaders->Tid().Length() == 0 )
       
   212         {
       
   213         TBufC8<KMMSMAXTIDLENGTH> tid;
       
   214         tid.Des().NumUC( AllocateTID(), EHex );
       
   215         iMmsHeaders->SetTidL( tid );
       
   216         }
       
   217         
       
   218     // Clear old response text in case the message has failed before
       
   219     iMmsHeaders->SetResponseTextL( TPtrC() );
       
   220 
       
   221     // Message type
       
   222     iMmsHeaders->SetMessageType( KMmsMessageTypeMSendReq );
       
   223 
       
   224     // MMS version that is used
       
   225     // Make sure we specify our current version even if the message
       
   226     // has been created elsewhere and brought in by sychronization etc.
       
   227     iMmsHeaders->SetMmsVersion( iMmsSettings->MmsVersion() );
       
   228 
       
   229     // Store the changed headers. 
       
   230     // No check for critical disk space level here, because only a 16-byte TID
       
   231     // was added.
       
   232     iMmsHeaders->StoreL( *store );
       
   233     store->CommitL();
       
   234 
       
   235     // Close the store now (otherwise attachments can not be read..)
       
   236     CleanupStack::PopAndDestroy( store );
       
   237 
       
   238 #ifndef _NO_MMSS_LOGGING_
       
   239     // calculate space needed and resize buffer
       
   240     const TMsvEntry& entry = iServerEntry->Entry();
       
   241     TInt size = entry.iSize;
       
   242     LOG2( _L("- message size about %d"), size );
       
   243 #endif
       
   244     
       
   245     // ... instead using entry wrapper class
       
   246     iError = iEntryWrapper->SetCurrentEntry( iSelection->At( iCurrentMessageNo - 1 ) );
       
   247     if( iError != KErrNone )
       
   248         {
       
   249         iServerEntry->SetEntry( KMsvNullIndexEntryId ); // not needed any more..
       
   250         FallThrough();
       
   251         }
       
   252     else
       
   253         {
       
   254         // The actual encoding is executed by mmsencode class
       
   255         iEncoder->StartChunkedL( *iEntryWrapper, *iMmsHeaders, *iEncodeBuffer, iStatus );
       
   256         // release the service entry to allow cancelling while conncetion is being opened
       
   257         iServerEntry->SetEntry( KMsvNullIndexEntryId );
       
   258         SetActive();
       
   259         }
       
   260     }
       
   261 
       
   262 // ---------------------------------------------------------
       
   263 // SubmitTransactionL
       
   264 // ---------------------------------------------------------
       
   265 //
       
   266 void CMmsSendOperation::SubmitTransactionL()
       
   267     {
       
   268     LOG( _L("CMmsSendOperation::SubmitTransactionL") );
       
   269     
       
   270     if ( iError != KErrNone )
       
   271         {
       
   272         FallThrough();
       
   273         return;
       
   274         }
       
   275 
       
   276     // "Sending" is either local or global.
       
   277     // Global is normal case, local is only for test purposes.
       
   278     if ( !iMmsSettings->LocalMode() )
       
   279         {
       
   280         LOG( _L("- global mode") );
       
   281         // The base class does HTTP POST to home page URI
       
   282         CMmsBaseOperation::SubmitTransactionL();
       
   283         }
       
   284     else
       
   285         {
       
   286         // No disk space checking here, because this is test code
       
   287         LOG( _L("- local mode") );
       
   288         TInt error = iServerEntry->SetEntry( iSelection->At( iCurrentMessageNo - 1 ) );
       
   289         if( error == KErrNone )
       
   290             {
       
   291             TMsvEntry entry = iServerEntry->Entry();
       
   292             if( iConnected )
       
   293                 {
       
   294                 entry.SetConnected( ETrue );
       
   295                 }
       
   296             entry.SetSendingState( KMsvSendStateSending );
       
   297             iServerEntry->ChangeEntry( entry );
       
   298             }
       
   299         iServerEntry->SetEntry( KMsvNullIndexEntryId );
       
   300 
       
   301         // sending uses the localmode OUT directory
       
   302         TFileName* fileName = new( ELeave ) TFileName;
       
   303         CleanupStack::PushL( fileName );
       
   304         fileName->Copy( iMmsSettings->LocalModeOut() );
       
   305         _LIT( KRelated, "m.mms");
       
   306         iParse.Set( *fileName, &KRelated, NULL );
       
   307         fileName->Copy( iParse.FullName() );
       
   308         User::LeaveIfError( CApaApplication::GenerateFileName( iFs, *fileName ) );
       
   309 
       
   310         RFile file;
       
   311         iError = file.Create( iFs, *fileName, EFileWrite | EFileShareExclusive );
       
   312         // for message id generation
       
   313         iParse.Set( *fileName, NULL, NULL );
       
   314         LOG2( _L("- local mode, file create status %d "), iError );
       
   315         TPtrC8 ptr /*= iEncodeBuffer->Ptr( 0 )*/;
       
   316         TBool isLastChunk = EFalse; 
       
   317         while ( iError == KErrNone && !isLastChunk )
       
   318             {
       
   319             MMmsCodecDataSupplier* dataSupplier = iEncoder;
       
   320             iError = dataSupplier->GetNextDataPart( ptr, isLastChunk );
       
   321             file.Write( ptr );
       
   322             file.Flush();
       
   323             iError = dataSupplier->ReleaseData();
       
   324             }
       
   325         
       
   326         // discard the contents
       
   327         iEncodeBuffer->Reset();
       
   328             
       
   329         // done - close files
       
   330         file.Close();
       
   331         CleanupStack::PopAndDestroy( fileName );
       
   332         fileName = NULL;
       
   333         FallThrough();
       
   334         }
       
   335     }
       
   336 
       
   337 // ---------------------------------------------------------
       
   338 // StoreResponseL()
       
   339 // ---------------------------------------------------------
       
   340 //
       
   341 void CMmsSendOperation::StoreResponseL()
       
   342     {
       
   343     LOG( _L("CMmsSendOperation::StoreResponseL") );
       
   344 
       
   345     // First we must analyze the response message to see if sending
       
   346     // was successful. In case we want to retry, we probably keep
       
   347     // our encoded message until we are either satisfied with the
       
   348     // result, or decide that it is hopeless.
       
   349 
       
   350     // The response from MMSC has been decoded earlier by the base class. 
       
   351     // Now the result must be saved - either the error code and text
       
   352     // or the message id depending if the sending was successful
       
   353 
       
   354     // The possible response message from MMSC is in iEncodeBuffer.
       
   355     // When we called the send transaction, the buffer contained
       
   356     // the encoded message. If the sending was successful, the
       
   357     // buffer contains the return message from MMSC
       
   358 
       
   359     // The transaction will not complete until a response has been
       
   360     // received from MMSC
       
   361 
       
   362     // 'error' tries to keep track of failures to access the entry
       
   363     // because of backup/restore or media unavailable
       
   364     TInt error = KErrNone; 
       
   365                            
       
   366     LOG2( _L("- iEncodeBuffer size %d "), iEncodeBuffer->Size() );
       
   367 
       
   368 #ifndef _NO_MMSS_LOGGING_
       
   369     // In logging version, unsuccessful attempts' responses are dumped into file
       
   370     if( iError != KErrNone && iEncodeBuffer->Size() > 0 )
       
   371         {
       
   372         TFileName fileName;
       
   373         fileName.Copy( KMmsDefaultLogDirectory );
       
   374         TUint att;
       
   375         if ( iFs.Att( fileName, att ) == KErrNone )
       
   376             {
       
   377             _LIT( KRelated, "SendResp.mms");
       
   378             // don't mess up iParse - it may contain local mode filename
       
   379             TParse parse;
       
   380             parse.Set( fileName, &KRelated, NULL );
       
   381             fileName = parse.FullName();
       
   382             error = CApaApplication::GenerateFileName( iFs, fileName );
       
   383             if ( error == KErrNone )
       
   384                 {
       
   385                 RFile file;
       
   386                 error = file.Create( iFs, fileName, EFileWrite | EFileShareExclusive );
       
   387                 // for message id generation
       
   388                 parse.Set( fileName, NULL, NULL );
       
   389 
       
   390                 if ( error == KErrNone )
       
   391                     {
       
   392                     // the data is supposed to be in the encode buffer
       
   393                     TPtr8 ptr = iEncodeBuffer->Ptr( 0 );
       
   394                     file.Write( ptr );
       
   395                     file.Flush();
       
   396                     }
       
   397 
       
   398                 // done - close files
       
   399                 file.Close();
       
   400                 }
       
   401             }
       
   402         error = KErrNone;
       
   403         }
       
   404 #endif
       
   405 
       
   406     // We must check the result, and mark the entry as failed
       
   407     // if the sending fails. Failed entries may be retried later.
       
   408 
       
   409     // The error should stay in iError
       
   410     // Above error was set if we failed to set iEntryWrapper to point to NULL entry
       
   411     // that should never fail, so our error should still be KErrNone
       
   412 
       
   413     error = iServerEntry->SetEntry( iSelection->At( iCurrentMessageNo - 1 ) );
       
   414     // if we could not access the entry we want, we are in really bad trouble.
       
   415     // We might be running backup/restore or the MMC might have been removed
       
   416 
       
   417     if( error == KErrNone )
       
   418         {
       
   419         // The actual send transaction should return a message ID
       
   420         // we should save its value
       
   421         CMsvStore* store = NULL;
       
   422         TRAP( error, {store = iServerEntry->EditStoreL();} )
       
   423 #ifndef _NO_MMSS_LOGGING_
       
   424         if ( error != KErrNone )
       
   425             {
       
   426             LOG2( _L("-ERROR getting edit store: %d"), error );
       
   427             }
       
   428 #endif
       
   429         // We add a couple of strings.
       
   430         // In any case, if we were successful, we are going to remove
       
   431         // the scheduling soon. That will free more disk space that
       
   432         // we take here. So we don't check here.
       
   433         // Besides, we need to update our entry, and if we cannot do it
       
   434         // we are in trouble.
       
   435         if( error == KErrNone )
       
   436             {
       
   437             LOG( _L("- update recipient scheduling data") );
       
   438             // Get the recipient scheduling info to be updated later.
       
   439             CleanupStack::PushL( store ); // ***
       
   440             CMmsScheduledEntry* mmsScheduledEntry =
       
   441                 CMmsScheduledEntry::NewL( iServerEntry->Entry() );
       
   442             CleanupStack::PushL( mmsScheduledEntry ); // ***
       
   443             mmsScheduledEntry->RestoreL( *store );
       
   444             UpdateRecipient( iError, *mmsScheduledEntry );
       
   445             if( iError == KErrNone || iResponse->ResponseText().Length() > 0 )
       
   446                 {
       
   447                 // We must add the message ID for delivery reports
       
   448                 // in local mode we use the generated filename
       
   449                 if ( iResponse->MessageId().Length() == 0 && iMmsSettings->LocalMode() )
       
   450                     {
       
   451                     HBufC8* id = HBufC8::NewL( KMaxFileName );
       
   452                     CleanupStack::PushL( id );
       
   453                     id->Des().Copy( iParse.NameAndExt() );
       
   454                     iResponse->SetMessageIdL( id->Des() );
       
   455                     CleanupStack::PopAndDestroy( id );
       
   456                     id = NULL;
       
   457                     }
       
   458 
       
   459                 iMmsHeaders->RestoreL( *store );
       
   460                 if( iError == KErrNone )
       
   461                     {
       
   462                     // message was successfully sent, store ID
       
   463                     iMmsHeaders->SetMessageIdL( iResponse->MessageId() );
       
   464                     // clear TID to prevent same TID from being used for two different messages.
       
   465                     // If a sent message is copied elsewhere and then resent, it is considered
       
   466                     // a different message.
       
   467                     iMmsHeaders->SetTidL( TPtrC8() );
       
   468                     }
       
   469                 if( iError != KErrNone )
       
   470                     {
       
   471                     iMmsHeaders->SetResponseTextL( iResponse->ResponseText() );
       
   472                     }
       
   473                 iMmsHeaders->StoreL( *store );
       
   474                 }
       
   475             // update entry fields to match scheduled entry
       
   476             // mainly this updates the recipient info (possible error)
       
   477             mmsScheduledEntry->StoreL( *store );
       
   478             store->CommitL();
       
   479             CleanupStack::PopAndDestroy( mmsScheduledEntry );
       
   480             CleanupStack::PopAndDestroy( store );
       
   481             }
       
   482 
       
   483         TMsvEntry entry = iServerEntry->Entry();
       
   484         entry.SetConnected( EFalse );
       
   485         entry.iError = iError;
       
   486 
       
   487         if( iError == KErrNone )
       
   488             {
       
   489             entry.SetReadOnly( EFalse );
       
   490             entry.SetFailed( EFalse );
       
   491             entry.SetSendingState( KMsvSendStateSent );
       
   492             }
       
   493         else
       
   494             {
       
   495             // We have a hopelessly failed message.
       
   496             // We mark it failed later, not yet
       
   497             entry.SetReadOnly( EFalse );
       
   498             }
       
   499 
       
   500         // We cannot set the entry to read only state here,
       
   501         // because we must still update the schedule.
       
   502         TInt tempError;
       
   503         tempError = iServerEntry->ChangeEntry( entry );
       
   504 #ifndef _NO_MMSS_LOGGING_
       
   505         if( tempError != KErrNone )
       
   506             {
       
   507             LOG2( _L("- ERROR in ChangeEntry: %d"), tempError );            
       
   508             }
       
   509 #endif
       
   510         // don't override error if already set
       
   511         if( error == KErrNone )
       
   512             {
       
   513             error = tempError;
       
   514             }
       
   515         }
       
   516 
       
   517     iServerEntry->SetEntry( KMsvNullIndexEntryId );
       
   518 
       
   519     // If the error is no longer KErrNone, there has been problems in updating
       
   520     // the message entry. Reason might be backup/restore or removal of MMC.
       
   521     // If the failure is due to backup/restore, we should try to wait for the
       
   522     // end of the operation and then retry from the start of this state.
       
   523 
       
   524     if( error <= (TInt) KMsvMediaUnavailable && error >= (TInt) KMsvIndexRestore )
       
   525         {
       
   526         LOG( _L("- must wait for backup end ") );
       
   527         TRequestStatus* status = &iStatus;
       
   528         iStatus = KRequestPending;
       
   529         SetActive();
       
   530         User::RequestComplete( status, error );
       
   531         return;
       
   532         }
       
   533     else if ( iError == KErrNone )
       
   534         {
       
   535         // The following will not fail
       
   536         iSuccessful->AppendL( ( *iFailed )[iCurrentMessageNo - 1] );
       
   537         iFailed->Delete( iCurrentMessageNo - 1 );
       
   538         LOG( _L("- Successful case: entry moved from iFailed to iSent selection") );
       
   539         }
       
   540     else
       
   541         {
       
   542         // keep LINT happy
       
   543         }
       
   544 
       
   545     // If we have updated our entry, the buffer can go
       
   546     iEncodeBuffer->Reset();
       
   547 
       
   548     FallThrough();        
       
   549     }
       
   550 
       
   551 // ---------------------------------------------------------
       
   552 // LogL
       
   553 // ---------------------------------------------------------
       
   554 //
       
   555 void CMmsSendOperation::LogL()
       
   556     {
       
   557     LOG( _L("CMmsSendOperation::LogL") );
       
   558     
       
   559     TInt error = iServerEntry->SetEntry( iSelection->At( iCurrentMessageNo - 1 ) );
       
   560     if ( error != KErrNone || iError != KErrNone ||
       
   561         ( iMmsHeaders->DeliveryReport() != EMmsYes  && iMmsHeaders->ReadReply() != EMmsYes ) )
       
   562         {
       
   563         // Can't access the entry or do not want logging, can't update log
       
   564         FallThrough();
       
   565         return;
       
   566         }
       
   567         
       
   568     TBool isActive = EFalse;    
       
   569     TRAP( error,
       
   570         {
       
   571         InitializeLoggingL();
       
   572     
       
   573         TMsvEntry entry = iServerEntry->Entry();
       
   574         // set event type and recipients to log event
       
   575         CommonLogEventInitializationL( *iMmsHeaders, entry );
       
   576         iServerEntry->SetEntry( KMsvNullIndexEntryId );
       
   577    
       
   578         iLogEvent->SetDataL( iMmsHeaders->MessageId() );
       
   579     
       
   580         // CMmsLog will set our status to KRequestPending
       
   581         iMmsLog->StartL( *iLogEvent, *iRemoteParties, iStatus );
       
   582         SetActive();
       
   583         isActive = ETrue;
       
   584         });
       
   585 
       
   586     // If logging has been successfully initialized, iMmsLog will complete us.
       
   587     // If something has gone wrong, we complete ourselves because we want to
       
   588     // continue finalization of the sending. We free our entry in any case
       
   589     
       
   590     iServerEntry->SetEntry( KMsvNullIndexEntryId );
       
   591     if ( !isActive )
       
   592         {
       
   593         FallThrough();
       
   594         return;
       
   595         }
       
   596     }
       
   597 
       
   598 // ---------------------------------------------------------
       
   599 // MoveEntryL
       
   600 // ---------------------------------------------------------
       
   601 //
       
   602 void CMmsSendOperation::MoveEntryL()
       
   603     {
       
   604     // Moving entry into Sent folder or deleting it depending on settings
       
   605     LOG( _L("CMmsSendOperation::MoveEntryL") );
       
   606     
       
   607     TInt error;
       
   608     error = iServerEntry->SetEntry( iSelection->At( iCurrentMessageNo - 1 ) );
       
   609     if( iError == KErrNone && error == KErrNone )
       
   610         {
       
   611         TMsvEntry entry = iServerEntry->Entry();
       
   612 
       
   613         if( iMmsSettings->MoveToSent() )
       
   614             {
       
   615 
       
   616             if ( iMmsHeaders->DeliveryReport() == KMmsYes)
       
   617                 {
       
   618                 LOG( _L("CMmsSendOperation: Delivery reports wanted") );
       
   619                 TInt recipientCount(0);
       
   620             	//Reset flags in mtmdata2
       
   621                 entry.iMtmData2 |= KMmsDeliveryStatusPending;
       
   622                 entry.iMtmData2 &= ~KMmsDeliveryStatusPartial;
       
   623                 entry.iMtmData2 &= ~KMmsDeliveryStatysFailed; 
       
   624                 entry.iMtmData2 &= ~KMmsDeliveryStatysDelivered; 
       
   625          
       
   626          
       
   627                 recipientCount = ( iMmsHeaders -> ToRecipients()).MdcaCount()
       
   628                     + (iMmsHeaders -> CcRecipients()).MdcaCount()
       
   629                     + (iMmsHeaders -> BccRecipients()).MdcaCount();
       
   630          
       
   631             
       
   632                entry.iMtmData3 |= recipientCount << KMmsSentItemTotalRecipientsShift;
       
   633                entry.iMtmData3 &= ~KMmsSentItemSuccessfullyDeliveredMask;
       
   634                entry.iMtmData3 &= ~KMmsSentItemFailedDeliveryMask; 
       
   635                 }
       
   636             else  //Reports not wanted
       
   637                 {
       
   638             	//Reset delivery status flags in mtmdata2
       
   639                 LOG( _L("CMmsSendOperation: Delivery reports not wanted") );
       
   640                 entry.iMtmData2 &= ~KMmsDeliveryStatusMask;
       
   641                 }
       
   642                 
       
   643             iServerEntry->ChangeEntry(entry);
       
   644                 
       
   645             // Move entry from Outbox to Sent Folder
       
   646             iError = iServerEntry->SetEntry( entry.Parent() );
       
   647             if ( iError == KErrNone )
       
   648                 {
       
   649                 iServerEntry->MoveEntryWithinService( entry.Id(), KMsvSentEntryIdValue );
       
   650                 LOG( _L("CMmsSendOperation::Moved to SENT") );           
       
   651                 }
       
   652             }
       
   653         else
       
   654             {
       
   655             // Move entry to Message Heaven
       
   656             iError = iServerEntry->SetEntry( entry.Parent() );
       
   657             if ( iError == KErrNone )
       
   658                 {
       
   659                 iServerEntry->DeleteEntry( entry.Id() );
       
   660                 }
       
   661             }
       
   662         }
       
   663     iServerEntry->SetEntry( KMsvNullIndexEntryId );
       
   664     FallThrough();
       
   665     }
       
   666 
       
   667 // ================= OTHER EXPORTED FUNCTIONS ==============
       
   668 
       
   669 //  End of File  
       
   670