mmsengine/mmscodecclient/src/mmscodecclient.cpp
changeset 31 ebfee66fde93
child 47 5b14749788d7
equal deleted inserted replaced
30:6a20128ce557 31:ebfee66fde93
       
     1 /*
       
     2 * Copyright (c) 2003 - 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:   Provides access to message store.
       
    15 *
       
    16 */
       
    17 
       
    18  
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 #include "mmsheaders.h"
       
    23 #include "mmscodecclient.h"
       
    24 #include "mmsversion.h"
       
    25 #include "mmsmsventry.h" // for the TMmsMsvEntry
       
    26 #include "mmsgenutils.h"
       
    27 #include "mmssettings.h"
       
    28 #include "mmsdecode.h"
       
    29 #include "mmsencode.h"
       
    30 #include "mmscliententry.h"
       
    31 #include "mmsclient.h"
       
    32 #include "mmscodecclientlogger.h"
       
    33 
       
    34 #include    <mmsvattachmentmanager.h>
       
    35 #include    <mmsvattachmentmanagersync.h>
       
    36 #include    <mtclreg.h>     //CClientMtmRegistry
       
    37 #include    <msvapi.h>         // CMsvOperation 
       
    38 
       
    39  
       
    40 // EXTERNAL DATA STRUCTURES
       
    41 
       
    42 // EXTERNAL FUNCTION PROTOTYPES  
       
    43 
       
    44 // CONSTANTS
       
    45 
       
    46 // MACROS
       
    47 
       
    48 // LOCAL CONSTANTS AND MACROS
       
    49 
       
    50 const TInt  KMaxDetailsLength = 64;   // Copy max this many chars to TMsvEntry
       
    51                                       //::iDetails
       
    52 _LIT( KAddressSeparator, ";" );       //Separator used between addresses in 
       
    53                                       //TMsvEntry::iDetails
       
    54 
       
    55 const TInt KMmsCodecClientChunkSize = 10 * 1024; // 10k buffer - can be adjusted if needed
       
    56                                       
       
    57 // MODULE DATA STRUCTURES
       
    58 
       
    59 // LOCAL FUNCTION PROTOTYPES
       
    60 
       
    61 // FORWARD DECLARATIONS
       
    62 
       
    63 // ============================= LOCAL FUNCTIONS ===============================
       
    64 
       
    65 
       
    66 
       
    67 // ============================ MEMBER FUNCTIONS ===============================
       
    68 
       
    69 // -----------------------------------------------------------------------------
       
    70 // CMmsCodecClient::CMmsCodecClient
       
    71 // -----------------------------------------------------------------------------
       
    72 //
       
    73 CMmsCodecClient::CMmsCodecClient():CActive( EPriorityStandard ),
       
    74     iEntryBeingHandled ( KMsvNullIndexEntryId ),
       
    75     iFolder ( KMsvNullIndexEntryId ),
       
    76     iMmsVersion ( KMmsDefaultVersion ),
       
    77     iState ( EIdle )
       
    78     {     
       
    79     }
       
    80 
       
    81 // -----------------------------------------------------------------------------
       
    82 // CMmsCodecClient::ConstructL
       
    83 // -----------------------------------------------------------------------------
       
    84 //
       
    85 void CMmsCodecClient::ConstructL( CMsvSession& aMsvSession )
       
    86     {
       
    87     iMsvSession = &aMsvSession; 
       
    88     
       
    89     iFs = iMsvSession->FileSession();
       
    90     
       
    91     iClientEntry = iMsvSession->GetEntryL( KMsvRootIndexEntryId );   
       
    92         
       
    93     iMmsHeaders = CMmsHeaders::NewL( KMmsDefaultVersion );
       
    94 
       
    95     iDecoder = CMmsDecode::NewL( iFs );
       
    96     
       
    97     iEncoder = CMmsEncode::NewL( iFs );
       
    98 
       
    99     iClientMtmRegistry = CClientMtmRegistry::NewL( *iMsvSession );
       
   100     
       
   101     iMmsClient = (CMmsClientMtm *) iClientMtmRegistry->NewMtmL( 
       
   102         KUidMsgTypeMultimedia );
       
   103      
       
   104     iClientEntryWrapper = CMmsClientEntry::NewL( iFs, *iClientEntry, EFalse );
       
   105     
       
   106     CMmsSettings* settings = CMmsSettings::NewL();
       
   107     CleanupStack::PushL( settings );
       
   108     settings->LoadSettingsL();
       
   109     iMmsVersion = settings->MmsVersion();
       
   110     CleanupStack::PopAndDestroy( settings );
       
   111     
       
   112     CActiveScheduler::Add( this );
       
   113     }
       
   114 
       
   115 // -----------------------------------------------------------------------------
       
   116 // CMmsCodecClient::NewL
       
   117 // -----------------------------------------------------------------------------
       
   118 //
       
   119 EXPORT_C CMmsCodecClient* CMmsCodecClient::NewL( CMsvSession& aMsvSession )
       
   120     {
       
   121     CMmsCodecClient* self = new( ELeave ) CMmsCodecClient;
       
   122     
       
   123     CleanupStack::PushL( self );
       
   124     self->ConstructL( aMsvSession );
       
   125     CleanupStack::Pop( self );
       
   126 
       
   127     return self;
       
   128     }
       
   129 
       
   130 // -----------------------------------------------------------------------------    
       
   131 // Destructor
       
   132 // -----------------------------------------------------------------------------
       
   133 //
       
   134 CMmsCodecClient::~CMmsCodecClient()
       
   135     { 
       
   136     // from CActive
       
   137     Cancel();
       
   138     
       
   139     // If we come to destructor before all the member variables have been created,
       
   140     // iState == EIdle, and none of the cleanup operations are attempted (pointers
       
   141     // not used before they are created).
       
   142     // By the time iState is something else besides idle, all member pointers exist
       
   143     // already and can be used.
       
   144     
       
   145     // Cleanup after incomplete operation
       
   146     ResetChunkedMode();
       
   147     //Let's make sure that if entry has just been created
       
   148     //it is be deleted.
       
   149     // we also check if iClientEntryWrapper is not NULL,
       
   150     // but actually, if is null, iState is idle.
       
   151     if ( iClientEntryWrapper &&
       
   152         ( iState == EEntryCreated || iState == EChunkedAdd || iState == EChunkedReplace ) &&
       
   153         iEntryBeingHandled != KMsvNullIndexEntryId ) 
       
   154         {
       
   155         iClientEntryWrapper->DeleteEntry( iEntryBeingHandled ); 
       
   156         }
       
   157     
       
   158     delete iMmsHeaders;
       
   159     delete iDecoder;
       
   160     delete iEncoder;
       
   161     delete iClientEntryWrapper;
       
   162     delete iClientEntry; 
       
   163     delete iMmsClient;
       
   164     delete iClientMtmRegistry;
       
   165     delete iEncodeBuffer;
       
   166 
       
   167     }
       
   168 
       
   169 // -----------------------------------------------------------------------------
       
   170 // CMmsCodecClient::AddMML
       
   171 // This function is called after CreateNewMessageEntryL so the new created id
       
   172 // aMmId already exist.
       
   173 // -----------------------------------------------------------------------------
       
   174 //
       
   175 EXPORT_C void CMmsCodecClient::AddMML(
       
   176     CBufFlat& aMm,
       
   177     TMsvId aFolder,
       
   178     TUint32 aFlags,
       
   179     TBool aUnread,
       
   180     TMsvId& aMmId,
       
   181     TRequestStatus& aStatus )
       
   182     {
       
   183     iClientStatus = &aStatus;   
       
   184     iEntryBeingHandled = aMmId;
       
   185     iFolder = aFolder;
       
   186     iFlags = aFlags;
       
   187     iUnread = aUnread;
       
   188 
       
   189     //The entry must have just been created
       
   190     if ( iState != EEntryCreated )
       
   191         {
       
   192         ResetChunkedMode();
       
   193         iState = EIdle;
       
   194         *iClientStatus = KRequestPending;
       
   195         User::RequestComplete( iClientStatus, KErrArgument );
       
   196         return;
       
   197         }
       
   198     
       
   199     // Check if the buffer is empty
       
   200     if ( aMm.Size() == 0 )
       
   201         {
       
   202         // delete entry - if we go back to idle state, we can create new entry
       
   203         DeleteCurrentEntryL();
       
   204         iState = EIdle;
       
   205         *iClientStatus = KRequestPending;
       
   206         User::RequestComplete( iClientStatus, KErrArgument );
       
   207         return;
       
   208         }
       
   209          
       
   210     iClientEntryWrapper->SetCurrentEntry( iEntryBeingHandled );
       
   211     iDecoder->StartL( *iClientEntryWrapper, *iMmsHeaders, aMm, iStatus);
       
   212     *iClientStatus = KRequestPending;
       
   213     iState = EFinalizeDecodedMM;
       
   214     SetActive();   
       
   215     }
       
   216 
       
   217 // -----------------------------------------------------------------------------
       
   218 // CMmsCodecClient::DeleteMM
       
   219 // -----------------------------------------------------------------------------
       
   220 //
       
   221 EXPORT_C TInt CMmsCodecClient::DeleteMM(
       
   222     TMsvId aMmId )
       
   223     {
       
   224     //Let's first make sure that the client is not illegally trashing the 
       
   225     //message store with empty entries. Only the AddMML -function is allowed to 
       
   226     //be called after the new entry has been created.
       
   227     ResetChunkedMode();
       
   228     
       
   229     if ( iState == EEntryCreated ) 
       
   230         {
       
   231         iClientEntryWrapper->DeleteEntry( iEntryBeingHandled ); 
       
   232         iState = EIdle;  //No more new entry
       
   233         return KErrArgument;                      
       
   234         }   
       
   235     
       
   236     //The wrapper sets the entry to parent for us    
       
   237     return iClientEntryWrapper->DeleteEntry( aMmId ); 
       
   238     }
       
   239 
       
   240 // -----------------------------------------------------------------------------
       
   241 // CMmsCodecClient::RetrieveMML
       
   242 // -----------------------------------------------------------------------------
       
   243 //
       
   244 EXPORT_C void CMmsCodecClient::RetrieveMML(
       
   245     TMsvId aMmId,
       
   246     CBufFlat& aMM,
       
   247     TMsvId& aFolder,
       
   248     TUint32& aFlags,                   
       
   249     TBool& aUnread,
       
   250     TRequestStatus& aStatus )
       
   251     
       
   252     {
       
   253     iClientStatus = &aStatus;
       
   254     
       
   255     ResetChunkedMode();
       
   256     //Let's first make sure that the client is not illegally trashing the 
       
   257     //message store with empty entries. Only the AddMM -function is allowed to 
       
   258     //be called after the new entry has been created.
       
   259     if ( iState == EEntryCreated ) 
       
   260         {
       
   261         // delete entry
       
   262         DeleteCurrentEntryL();
       
   263         iState = EIdle;  //No more new entry
       
   264         *iClientStatus = KRequestPending;
       
   265         User::RequestComplete( iClientStatus, KErrArgument );                      
       
   266         return;
       
   267         }
       
   268         
       
   269     iEntryBeingHandled = aMmId;
       
   270     CBufFlat*   encodeBuffer = &aMM;
       
   271 
       
   272     iClientEntry->SetEntryL( aMmId ); 
       
   273     
       
   274     TMsvEntry tEntry = iClientEntry->Entry();
       
   275 
       
   276     // Get the flags of the entry.
       
   277     RetrieveFlags( tEntry, aFlags, aUnread );
       
   278     // Get the folder where the message is stored.
       
   279     aFolder = tEntry.Parent();
       
   280 
       
   281     tEntry.SetReadOnly( EFalse );
       
   282     iClientEntry->ChangeL( tEntry );
       
   283 
       
   284     // Prepare MMS headers for encoding.
       
   285     // Gets the message store for the current context with read access.
       
   286     CMsvStore* store = iClientEntry->ReadStoreL();
       
   287     CleanupStack::PushL( store );
       
   288     iMmsHeaders->RestoreL( *store );
       
   289 
       
   290     iMmsHeaders->SetMessageType( KMmsMessageTypeMSendReq );
       
   291 
       
   292     // Set MMS version if it is undefined
       
   293     if ( iMmsHeaders->MmsVersion() == 0 )
       
   294         {
       
   295         // Version not set
       
   296         iMmsHeaders->SetMmsVersion( iMmsVersion );
       
   297         }
       
   298 
       
   299     // Don't change the original message.
       
   300     CleanupStack::PopAndDestroy( store ); 
       
   301     
       
   302     // Encode the MMS.
       
   303     iClientEntryWrapper->SetCurrentEntry( aMmId );
       
   304     iEncoder->StartL( *iClientEntryWrapper, *iMmsHeaders, *encodeBuffer, iStatus );
       
   305     *iClientStatus = KRequestPending;
       
   306     iState = EFinalizeEncodedMM;
       
   307       
       
   308     SetActive();
       
   309     }
       
   310 
       
   311 // -----------------------------------------------------------------------------
       
   312 // CMmsCodecClient::SendMML
       
   313 // -----------------------------------------------------------------------------
       
   314 //
       
   315 
       
   316 EXPORT_C CMsvOperation* CMmsCodecClient::SendMML(
       
   317     TMsvId aMmId ,
       
   318     TRequestStatus& aStatus )
       
   319     {
       
   320     iClientStatus = &aStatus;
       
   321     ResetChunkedMode();
       
   322     //Let's first make sure that the client is not illegally trashing the 
       
   323     //message store with empty entries. Only the AddMM -function is allowed to 
       
   324     //be called after the new entry has been created.
       
   325     if ( iState == EEntryCreated ) 
       
   326         {
       
   327         // delete entry
       
   328         DeleteCurrentEntryL();   
       
   329         iState = EIdle;  //No more new entry
       
   330         *iClientStatus = KRequestPending;
       
   331         User::RequestComplete( iClientStatus, KErrArgument );                      
       
   332         return NULL;
       
   333         }
       
   334     
       
   335     iMmsClient->SwitchCurrentEntryL(aMmId);
       
   336     iMmsClient->LoadMessageL();
       
   337     CMsvOperation* op = NULL;   
       
   338     op = iMmsClient->SendL(iStatus);
       
   339     *iClientStatus = KRequestPending;
       
   340     iState = ESendMM;
       
   341     SetActive();   
       
   342     return op;
       
   343     }
       
   344 // -----------------------------------------------------------------------------
       
   345 // CMmsCodecClient::ReplaceMML
       
   346 // -----------------------------------------------------------------------------
       
   347 //
       
   348 
       
   349 EXPORT_C void CMmsCodecClient::ReplaceMML(
       
   350     TMsvId& aMmId, 
       
   351     CBufFlat& aMm,
       
   352     TUint32 aFlags,
       
   353     TBool aUnread,
       
   354     TRequestStatus& aStatus )
       
   355     {
       
   356     iClientStatus = &aStatus;
       
   357     ResetChunkedMode();
       
   358     //Let's first make sure that the client is not illegally trashing the 
       
   359     //message store with empty entries. Only the AddMM -function is allowed to 
       
   360     //be called after the new entry has been created.
       
   361     if ( iState == EEntryCreated ) 
       
   362         {
       
   363         // delete entry
       
   364         DeleteCurrentEntryL();   
       
   365         iState = EIdle;  //No more new entry
       
   366         *iClientStatus = KRequestPending;
       
   367         User::RequestComplete( iClientStatus, KErrArgument );                      
       
   368         return;
       
   369         }
       
   370     
       
   371     // Check if the aMm is empty. 
       
   372     if ( aMm.Size() == 0 )
       
   373         {
       
   374         iState = EIdle;
       
   375         *iClientStatus = KRequestPending;
       
   376         User::RequestComplete( iClientStatus, KErrArgument );
       
   377         return;
       
   378         }
       
   379 
       
   380     // Messages in outbox must not be replaced.
       
   381     if ( ParentOutbox( aMmId ) )
       
   382         {
       
   383         iState = EIdle;
       
   384         *iClientStatus = KRequestPending;
       
   385         User::RequestComplete( iClientStatus, KErrArgument );
       
   386         return;        
       
   387         }
       
   388 
       
   389     iFlags = aFlags;
       
   390     iUnread = aUnread;
       
   391      
       
   392     // Set the Entry as being handled
       
   393     iEntryBeingHandled = aMmId;
       
   394 
       
   395     iClientEntry->SetEntryL( iEntryBeingHandled );
       
   396     TMsvEntry tEntry = iClientEntry->Entry();
       
   397      
       
   398     tEntry.SetVisible( EFalse );
       
   399     tEntry.SetComplete( EFalse );
       
   400     tEntry.SetInPreparation( ETrue );
       
   401     tEntry.SetReadOnly( EFalse );
       
   402  
       
   403     iClientEntry->ChangeL( tEntry );
       
   404 
       
   405     // Remove the attachments of the Entry   
       
   406     CMsvStore* store = iClientEntry->EditStoreL();
       
   407     CleanupStack::PushL( store );
       
   408 
       
   409     MMsvAttachmentManager& attachMan = store->AttachmentManagerL();
       
   410     MMsvAttachmentManagerSync& attachManSynch = store->AttachmentManagerExtensionsL(); 
       
   411     
       
   412     TInt numOfAttach( attachMan.AttachmentCount() );
       
   413     TInt i(0);
       
   414     while ( i < numOfAttach )
       
   415         {
       
   416     	attachManSynch.RemoveAttachmentL( 0 );  //This is correct
       
   417         i++;
       
   418         }
       
   419     
       
   420 
       
   421     store->CommitL();
       
   422     CleanupStack::PopAndDestroy( store );
       
   423     
       
   424     iClientEntryWrapper->SetCurrentEntry( iEntryBeingHandled );
       
   425     iDecoder->StartL( *iClientEntryWrapper, *iMmsHeaders, aMm, iStatus);
       
   426     *iClientStatus = KRequestPending;
       
   427     iState = EFinalizeDecodedMM;
       
   428     SetActive(); 
       
   429     }
       
   430     
       
   431     
       
   432 // -----------------------------------------------------------------------------
       
   433 // CMmsCodecClient::MoveMML
       
   434 // This function is implemeted synchronously altought the interface looks like
       
   435 // asynchronous
       
   436 // -----------------------------------------------------------------------------
       
   437 //
       
   438 
       
   439 EXPORT_C void CMmsCodecClient::MoveMML( TMsvId aMmId, 
       
   440                                TMsvId aParentId, 
       
   441                                TRequestStatus& aStatus )
       
   442     {
       
   443     iClientStatus = &aStatus;
       
   444     ResetChunkedMode();
       
   445     //Let's first make sure that the client is not illegally trashing the 
       
   446     //message store with empty entries. Only the AddMM -function is allowed to 
       
   447     //be called after the new entry has been created.
       
   448     if ( iState == EEntryCreated ) 
       
   449         {
       
   450         // delete entry
       
   451         DeleteCurrentEntryL();
       
   452         iState = EIdle;  //No more new entry
       
   453          *iClientStatus = KRequestPending;
       
   454         User::RequestComplete( iClientStatus, KErrArgument );                    
       
   455         return;
       
   456         }
       
   457     
       
   458     iState = EIdle;  //Move is stateless operation
       
   459     if ( aParentId == KMsvGlobalOutBoxIndexEntryId )
       
   460         {
       
   461     	 *iClientStatus = KRequestPending;
       
   462         User::RequestComplete( iClientStatus, KErrArgument );                    
       
   463         return;
       
   464         }
       
   465     
       
   466     iClientEntry->SetEntryL( aMmId );
       
   467     
       
   468     TMsvEntry tEntry = iClientEntry->Entry();
       
   469     TMsvId parent = tEntry.Parent();
       
   470     
       
   471     
       
   472     // Can't move within same folder
       
   473     if ( parent == aParentId )
       
   474         {
       
   475         *iClientStatus = KRequestPending;
       
   476         User::RequestComplete( iClientStatus, KErrArgument );                    
       
   477         return;	
       
   478         }
       
   479     
       
   480     iClientEntry->SetEntryL( parent );
       
   481     
       
   482     iClientEntry -> MoveL( aMmId, aParentId );
       
   483     
       
   484     //Let's accept all kind of moves between standard folders except to outbox 
       
   485     //altought all of them are not accepted from the mms ui of the phone
       
   486     //Some flags in TMsvEntry must be set according to target folder.
       
   487     TMmsMsvEntry* mmsEntry = STATIC_CAST( TMmsMsvEntry*, &tEntry );
       
   488     
       
   489     if ( aParentId == KMsvGlobalInBoxIndexEntryId )
       
   490         {
       
   491         mmsEntry->SetMobileTerminated( ETrue );
       
   492         tEntry.SetReadOnly( ETrue );
       
   493         } 
       
   494     
       
   495     else if ( aParentId == KMsvSentEntryId )
       
   496         {
       
   497         mmsEntry->SetMobileTerminated( EFalse );  
       
   498         tEntry.SetReadOnly( ETrue );
       
   499         }
       
   500         
       
   501     else // ( aParentId == KMsvDraftEntryId )
       
   502         {
       
   503         mmsEntry->SetMobileTerminated( EFalse );   
       
   504         tEntry.SetReadOnly( EFalse );
       
   505         // Messages in drafts folders must be always editor oriented.
       
   506         tEntry.iMtmData1 &= (~KMmsMessageMobileTerminated);
       
   507         tEntry.iMtmData1 |= KMmsMessageEditorOriented; // editor oriented    
       
   508         }
       
   509 
       
   510     
       
   511     *iClientStatus = KRequestPending;
       
   512     User::RequestComplete( iClientStatus, KErrNone );              
       
   513     }    
       
   514 
       
   515 // -----------------------------------------------------------------------------
       
   516 // CMmsCodecClient::SetFlags 
       
   517 // -----------------------------------------------------------------------------
       
   518 //
       
   519 
       
   520 EXPORT_C TInt CMmsCodecClient::SetFlags(
       
   521     TMsvId aMmId,
       
   522     TUint32 aFlags,
       
   523     TBool aUnread )
       
   524     {
       
   525     TInt error( KErrNone );
       
   526     ResetChunkedMode();
       
   527     //Let's first make sure that the client is not illegally trashing the 
       
   528     //message store with empty entries. Only the AddMM -function is allowed to 
       
   529     //be called after the new entry has been created.
       
   530     if ( iState == EEntryCreated ) 
       
   531         {
       
   532         // delete entry, not allowed to leave
       
   533         if ( iEntryBeingHandled != KMsvNullIndexEntryId )
       
   534             {
       
   535             iClientEntryWrapper->DeleteEntry( iEntryBeingHandled ); 
       
   536             }
       
   537         iState = EIdle;  //No more new entry
       
   538         return KErrArgument;                      
       
   539         }
       
   540     // The flags of the message that are in Outbox must not be changed.
       
   541     if ( ParentOutbox( aMmId ) )
       
   542         {
       
   543         return KErrNotSupported;
       
   544         }
       
   545     iFlags = aFlags;
       
   546     iUnread = aUnread;
       
   547 
       
   548     TRAP ( error, 
       
   549         {
       
   550         iClientEntry->SetEntryL( aMmId );
       
   551         TMsvEntry tEntry = iClientEntry->Entry();
       
   552         SetFlagsToTMsvEntry( tEntry );
       
   553         iClientEntry->ChangeL( tEntry );
       
   554         } );
       
   555     
       
   556     return error;
       
   557     }
       
   558 
       
   559 // -----------------------------------------------------------------------------
       
   560 // CMmsCodecClient::SetFlagsToTMsvEntry 
       
   561 // -----------------------------------------------------------------------------
       
   562 //
       
   563 
       
   564 void CMmsCodecClient::SetFlagsToTMsvEntry(
       
   565     TMsvEntry& aEntry)
       
   566     {
       
   567     aEntry.SetUnread( iUnread );
       
   568     
       
   569     //We do not want the client to set all flags in TMsvEntry::iMtmData1
       
   570     //Only EMmsDrmCorruptedAttachment is allowed to be set.
       
   571     //Not even the KMmsMessageMobileTerminated / KMmsMessageEditorOriented
       
   572     //flags because those are always set in FinalizeDecodecL when the meassege
       
   573     //is created or replaced. Later there can not be changes.
       
   574     if ( iFlags & EMmsDrmCorruptedAttachment )
       
   575         {
       
   576     	aEntry.iMtmData1 |= EMmsDrmCorruptedAttachment;
       
   577         }
       
   578     else
       
   579         {
       
   580     	aEntry.iMtmData1 |= ~EMmsDrmCorruptedAttachment;
       
   581         }
       
   582     }
       
   583 
       
   584 // -----------------------------------------------------------------------------
       
   585 // CMmsCodecClient::DoCancel
       
   586 // -----------------------------------------------------------------------------
       
   587 //
       
   588 
       
   589 void CMmsCodecClient::DoCancel()
       
   590     {
       
   591     // Cancel all class members that are active objects
       
   592     iDecoder->Cancel();
       
   593     iEncoder->Cancel();
       
   594     User::RequestComplete( iClientStatus, KErrCancel );
       
   595     }
       
   596 
       
   597 // -----------------------------------------------------------------------------
       
   598 // CMmsCodecClient::RunL 
       
   599 // -----------------------------------------------------------------------------
       
   600 //
       
   601 
       
   602 void CMmsCodecClient::RunL( )
       
   603     {
       
   604     TInt error = KErrNone;
       
   605 
       
   606     if ( iState == EFinalizeDecodedMM )
       
   607         {
       
   608         if ( iStatus != KErrNone ) // Something failed when the message was decoded.
       
   609             {   
       
   610             // delete entry
       
   611             DeleteCurrentEntryL();
       
   612             iState = EIdle;
       
   613             User::RequestComplete( iClientStatus, KErrNotSupported );
       
   614             return;
       
   615             }
       
   616         else // Decode succeeded. Finalize the entry.
       
   617             {           
       
   618             TRAP ( error, FinalizeDecodedMML() );
       
   619             if ( error != KErrNone ) // Finalizing leaves
       
   620                 {
       
   621                 // delete entry
       
   622                 DeleteCurrentEntryL();
       
   623                 iState = EIdle;
       
   624                 User::RequestComplete( iClientStatus, KErrNotSupported );
       
   625                 return;               
       
   626                 }
       
   627             else  // Message is decoded and finalized correctly.
       
   628                 {        
       
   629                 iEntryBeingHandled = KMsvNullIndexEntryId;
       
   630                 iState = EIdle;                
       
   631                 User::RequestComplete( iClientStatus, KErrNone );
       
   632                 return;
       
   633                 }
       
   634             }
       
   635         }
       
   636     else if ( iState == EFinalizeEncodedMM )
       
   637         {
       
   638         if ( iStatus != KErrNone ) // Encoding failed.
       
   639             {
       
   640             iState = EIdle;
       
   641             User::RequestComplete( iClientStatus, KErrNotSupported );
       
   642             return;            
       
   643             }
       
   644         else // Encoding succeeded.
       
   645             {
       
   646             // The readonly flag has been set off in order to retrieve the message.
       
   647             // The read only flag has to be set on if the folder is not draft or outbox folder.
       
   648             iClientEntry->SetEntryL( iEntryBeingHandled );
       
   649             TMsvEntry tEntry = iClientEntry->Entry();
       
   650             TMsvId parent = tEntry.Parent();
       
   651 
       
   652             if ( parent != KMsvDraftEntryId &&
       
   653                  parent != KMsvGlobalOutBoxIndexEntryId )
       
   654                 {
       
   655                 tEntry.SetReadOnly( ETrue );           
       
   656                 iClientEntry->ChangeL( tEntry );
       
   657                 }
       
   658             else
       
   659                 {
       
   660                 tEntry.SetReadOnly( EFalse );           
       
   661                 iClientEntry->ChangeL( tEntry );
       
   662                 }
       
   663                 
       
   664             iEntryBeingHandled = KMsvNullIndexEntryId;
       
   665             iState = EIdle;
       
   666             
       
   667             User::RequestComplete( iClientStatus, KErrNone );
       
   668             return;
       
   669             }
       
   670         }
       
   671     
       
   672     else // ( iState == ESendMM )
       
   673         {
       
   674         iState = EIdle;
       
   675         User::RequestComplete( iClientStatus, iStatus.Int() );
       
   676         return;
       
   677         }   
       
   678     }
       
   679         
       
   680 
       
   681 // -----------------------------------------------------------------------------
       
   682 // CMmsCodecClient::RunError
       
   683 // -----------------------------------------------------------------------------
       
   684 //	
       
   685 TInt CMmsCodecClient::RunError( TInt aError )
       
   686 	{
       
   687 	iState = EIdle;
       
   688     User::RequestComplete( iClientStatus, aError );
       
   689 	return KErrNone;	
       
   690 	}
       
   691     
       
   692 // -----------------------------------------------------------------------------
       
   693 // CMmsCodecClient::CreateNewMessageEntry
       
   694 // -----------------------------------------------------------------------------
       
   695 //
       
   696 EXPORT_C TInt CMmsCodecClient::CreateNewMessageEntryL( TMsvId aFolder, TMsvId& aCreatedId )
       
   697     {
       
   698      
       
   699     // Create a message entry into the target folder.
       
   700     // The entry is invisible and in preparation until
       
   701     // the message is decoded and finalised successfully.
       
   702 
       
   703     // If the creation of the entry is successful, we
       
   704     // set our entry to point to the newly created entry
       
   705     // to get data content to it.
       
   706 
       
   707     ResetChunkedMode();
       
   708     //Let's first make sure that the client is not illegally trashing the 
       
   709     //message store with empty entries. Only the AddMM -function is allowed to be called
       
   710     //after the new entry has been created.
       
   711     if ( iState == EEntryCreated ) 
       
   712         {
       
   713         // delete entry
       
   714         DeleteCurrentEntryL();
       
   715         iState = EIdle;  //No more new entry
       
   716         return KErrArgument;                      
       
   717         }
       
   718     
       
   719     // set first default flags 
       
   720     TMsvEntry tEntry;
       
   721 
       
   722     // set all relevant flags in tMsvEntry
       
   723     tEntry.iType = KUidMsvMessageEntry;
       
   724     tEntry.iMtm = KUidMsgTypeMultimedia;
       
   725     tEntry.iServiceId = iMmsClient->DefaultServiceL();
       
   726     tEntry.SetNew( EFalse );
       
   727 
       
   728     tEntry.SetVisible( EFalse );
       
   729     tEntry.SetComplete( EFalse );
       
   730     tEntry.SetInPreparation( ETrue );
       
   731 
       
   732     // Query disk space:
       
   733     TInt error = iClientEntryWrapper->DiskSpaceBelowCriticalLevelL( KMmsIndexEntryExtra );
       
   734     if ( error != KErrNone )
       
   735         {
       
   736         return error; // KErrDiskFull
       
   737         }
       
   738 
       
   739     iClientEntry->SetEntryL( aFolder );
       
   740     iClientEntry->CreateL( tEntry );
       
   741     iEntryBeingHandled = tEntry.Id();
       
   742     aCreatedId = iEntryBeingHandled;
       
   743     iState = EEntryCreated;
       
   744     return KErrNone;
       
   745     }
       
   746 
       
   747 // -----------------------------------------------------------------------------
       
   748 // CMmsCodecClient::FinalizeDecodedMML 
       
   749 // -----------------------------------------------------------------------------
       
   750 //
       
   751 void CMmsCodecClient::FinalizeDecodedMML()
       
   752     { 
       
   753     iClientEntry->SetEntryL( iEntryBeingHandled );
       
   754     TMsvEntry tEntry = iClientEntry->Entry();
       
   755        
       
   756     //Resest the message class bits. There may be something in case of replace
       
   757     tEntry.iMtmData1 &= ~KMmsMessageClassMask;
       
   758     if ( iMmsHeaders->MessageClass() == EMmsClassAdvertisement )
       
   759         {
       
   760         tEntry.iMtmData1 |= KMmsMessageAdvertisement;
       
   761         }
       
   762     else if (iMmsHeaders->MessageClass() == EMmsClassInformational )
       
   763         {
       
   764         tEntry.iMtmData1 |= KMmsMessageInformational;
       
   765         }
       
   766     else
       
   767         {
       
   768         }
       
   769 
       
   770     tEntry.iDate.UniversalTime();
       
   771 
       
   772     if ( iMmsHeaders->ToRecipients().MdcaCount() +
       
   773         iMmsHeaders->CcRecipients().MdcaCount() +
       
   774         iMmsHeaders->BccRecipients().MdcaCount() > 1 )
       
   775         {
       
   776         tEntry.SetMultipleRecipients( ETrue );
       
   777         }
       
   778 
       
   779     SetFlagsToTMsvEntry( tEntry );
       
   780 
       
   781     // Certain flags has to be in a particular way
       
   782     TMsvId parent = tEntry.Parent();
       
   783     TMmsMsvEntry* mmsEntry = STATIC_CAST( TMmsMsvEntry*, &tEntry );
       
   784     TBuf<KMaxDetailsLength> detailsBuf; 
       
   785     if ( parent == KMsvGlobalInBoxIndexEntryId )
       
   786         {
       
   787         mmsEntry->SetMobileTerminated( ETrue );
       
   788         tEntry.SetReadOnly( ETrue );
       
   789         GenerateSenderL( detailsBuf );
       
   790         } 
       
   791     
       
   792     else if ( parent == KMsvSentEntryId )
       
   793         {
       
   794         mmsEntry->SetMobileTerminated( EFalse ); // not mobile terminated
       
   795         tEntry.SetReadOnly( ETrue );
       
   796         GenerateRecipientsL( detailsBuf );
       
   797         }
       
   798 
       
   799     else if ( parent == KMsvGlobalOutBoxIndexEntryId )
       
   800         {
       
   801         mmsEntry->SetMobileTerminated( EFalse ); // not mobile terminated
       
   802         mmsEntry->SetEditorOriented ( ETrue );
       
   803         tEntry.SetReadOnly( EFalse );
       
   804         tEntry.SetSendingState( KMsvSendStateUponRequest );
       
   805         GenerateRecipientsL( detailsBuf );       
       
   806         }
       
   807     else if ( parent == KMsvDraftEntryId )
       
   808         {
       
   809         mmsEntry->SetMobileTerminated( EFalse );  // not mobile terminated 
       
   810         tEntry.SetReadOnly( EFalse );
       
   811         // Messages in drafts folders must be always editor oriented.
       
   812         tEntry.iMtmData1 &= (~KMmsMessageMobileTerminated);
       
   813         tEntry.iMtmData1 |= KMmsMessageEditorOriented; // editor oriented
       
   814         GenerateRecipientsL( detailsBuf );    
       
   815         }
       
   816     else
       
   817         {
       
   818     	mmsEntry->SetMobileTerminated( ETrue );
       
   819         tEntry.SetReadOnly( ETrue );
       
   820         GenerateSenderL( detailsBuf );
       
   821  
       
   822         }
       
   823     tEntry.iDetails.Set( detailsBuf );
       
   824     tEntry.SetVisible( ETrue );
       
   825     tEntry.SetComplete( ETrue );
       
   826     tEntry.SetInPreparation( EFalse );
       
   827     iClientEntry->ChangeL( tEntry );        
       
   828     }
       
   829 
       
   830 
       
   831 // -----------------------------------------------------------------------------
       
   832 // CMmsCodecClient::GenerateRecipientsL
       
   833 // -----------------------------------------------------------------------------
       
   834 //
       
   835 void CMmsCodecClient::GenerateRecipientsL( TDes& aDetails )
       
   836     { 
       
   837     HBufC* alias = HBufC::NewL( KMaxDetailsLength );
       
   838     CleanupStack::PushL( alias );
       
   839     TPtr aliasPtr = alias->Des();
       
   840     const CDesCArray& addresses = iMmsHeaders->ToRecipients();
       
   841     TInt addrCnt = addresses.Count();
       
   842 
       
   843     TPtrC stringToAdd;
       
   844     for ( TInt i = 0; i < addrCnt; ++i)
       
   845         {      
       
   846         TPtrC address = TMmsGenUtils::PureAddress( addresses[i] );
       
   847 
       
   848         //GetAlias guarantees that the alias length is KMaxDetailsLength at max
       
   849         TMmsGenUtils::GetAlias(
       
   850             address,
       
   851             aliasPtr,
       
   852             KMaxDetailsLength,
       
   853             iFs );
       
   854         
       
   855         if ( aliasPtr.Length() > 0 )
       
   856         	{
       
   857     		//Alias found
       
   858             stringToAdd.Set( aliasPtr );
       
   859         	}
       
   860     	else
       
   861             {
       
   862         	//Fatal error or no alias found
       
   863             stringToAdd.Set( address );
       
   864             }
       
   865 
       
   866         
       
   867         if ( ( aDetails.Length() != 0 ) &&   // Not a first address
       
   868              ( aDetails.Length() 
       
   869                  + KAddressSeparator().Length() < KMaxDetailsLength ) )
       
   870             {
       
   871             // Add separator
       
   872             aDetails.Append( KAddressSeparator() );
       
   873             }
       
   874 
       
   875         if ( aDetails.Length() + stringToAdd.Length() < KMaxDetailsLength ) 
       
   876             {
       
   877             // whole string fits. Add it.
       
   878             aDetails.Append( stringToAdd );
       
   879             }
       
   880         else
       
   881             {
       
   882             // Only part of the string fits
       
   883             TInt charsToAdd = KMaxDetailsLength - aDetails.Length();
       
   884 
       
   885             if ( charsToAdd <= 0 )
       
   886                 {
       
   887                 // Cannot add any more chars 
       
   888                 break;
       
   889                 }
       
   890 
       
   891             if ( charsToAdd >= stringToAdd.Length() )
       
   892                 {
       
   893                 //Guarantee that charsToAdd is not larger that stringToAdd 
       
   894                 //length
       
   895                 charsToAdd = stringToAdd.Length();
       
   896                 }
       
   897 
       
   898             aDetails.Append( stringToAdd.Left( charsToAdd ) );
       
   899             break;
       
   900             }
       
   901         }
       
   902     CleanupStack::PopAndDestroy( alias ); 
       
   903     }
       
   904     
       
   905     
       
   906 // -----------------------------------------------------------------------------
       
   907 // CMmsCodecClient::GenerateSenderL
       
   908 // -----------------------------------------------------------------------------
       
   909 //
       
   910 void CMmsCodecClient::GenerateSenderL ( TDes& aDetails )
       
   911 {
       
   912     HBufC* alias = HBufC::NewL( KMaxDetailsLength );
       
   913     CleanupStack::PushL( alias );
       
   914     TPtr aliasPtr = alias->Des();   
       
   915             
       
   916     iMmsClient->SwitchCurrentEntryL(iEntryBeingHandled);
       
   917     iMmsClient->LoadMessageL();    
       
   918     const TPtrC senderAddress = iMmsClient->Sender();
       
   919   
       
   920     //GetAlias guarantees that the alias length is KMaxDetailsLength at max
       
   921     TMmsGenUtils::GetAlias(
       
   922         senderAddress,
       
   923         aliasPtr,
       
   924         KMaxDetailsLength,
       
   925         iFs );
       
   926         
       
   927     if ( aliasPtr.Length() == 0 )
       
   928         {
       
   929         //In theory the senderAddress may exceed the KMaxDetailsLength
       
   930         //but the following line will not crash.
       
   931         aDetails.Append( senderAddress.Left( KMaxDetailsLength ) );
       
   932         }
       
   933 
       
   934     else
       
   935     	{
       
   936         //Alias found
       
   937         aDetails.Append( aliasPtr.Left( KMaxDetailsLength ) );	
       
   938     	}
       
   939    	
       
   940     CleanupStack::PopAndDestroy( alias );  
       
   941 }
       
   942 
       
   943 // -----------------------------------------------------------------------------
       
   944 // CMmsCodecClient::RetrieveFlags
       
   945 // This function is used to construt flags for the user of the codec client.
       
   946 // The unread flag is a boolean variable and the other flags uses the structure
       
   947 // of the TMsvEntry::iMtmData1 but only few bit are provided.
       
   948 // -----------------------------------------------------------------------------
       
   949 //
       
   950 void CMmsCodecClient::RetrieveFlags(                                
       
   951     TMsvEntry aEntry,
       
   952     TUint32 &aFlags,
       
   953     TBool &aUnread )
       
   954     {       
       
   955     aUnread = aEntry.Unread();
       
   956     aFlags = 0; //Reset the bitfields
       
   957     
       
   958     if ( aEntry.iMtmData1 & EMmsDrmCorruptedAttachment )
       
   959         {    	
       
   960     	aFlags |= EMmsDrmCorruptedAttachment;
       
   961         }
       
   962 
       
   963     if ( aEntry.iMtmData1 & KMmsMessageMobileTerminated )
       
   964         {
       
   965         aFlags |= KMmsMessageMobileTerminated;
       
   966         }
       
   967     else //KMmsMessageEditorOriented 
       
   968         {
       
   969     	aFlags |= KMmsMessageEditorOriented;
       
   970         }
       
   971     }
       
   972 
       
   973 // -----------------------------------------------------------------------------
       
   974 // CMmsCodecClient:: ParentOutbox
       
   975 // -----------------------------------------------------------------------------
       
   976 //
       
   977 
       
   978 TBool CMmsCodecClient::ParentOutbox( TMsvId aMmId )
       
   979     {
       
   980 
       
   981     TInt error = KErrNone;
       
   982     error = iClientEntryWrapper->SetCurrentEntry( aMmId );
       
   983     if ( error == KErrNotFound ) // The entry does not exist.
       
   984         {
       
   985         return EFalse;
       
   986         }
       
   987     
       
   988     TMsvEntry tEntry = iClientEntry->Entry();
       
   989     TMsvId parent = tEntry.Parent();
       
   990     if ( parent == KMsvGlobalOutBoxIndexEntryId )
       
   991         {
       
   992         return ETrue;
       
   993         }
       
   994     return EFalse;
       
   995     }
       
   996 
       
   997 
       
   998 EXPORT_C TInt CMmsCodecClient::DiskSpaceBelowCriticalLevelL(TInt aSize)
       
   999 	{
       
  1000 	return( iClientEntryWrapper->DiskSpaceBelowCriticalLevelL( aSize ) );
       
  1001 	}
       
  1002 	
       
  1003 
       
  1004 // -----------------------------------------------------------------------------
       
  1005 // CMmsCodecClient::DeleteCurrentEntryL
       
  1006 // Reason for this function is that iClientEntryWrapper::DeleteEntry uses traps
       
  1007 // to prevent leave. This DeleteCurrentEntryL is used in leaving functions.
       
  1008 // -----------------------------------------------------------------------------
       
  1009 //
       
  1010 void CMmsCodecClient::DeleteCurrentEntryL()
       
  1011     {
       
  1012     if ( iEntryBeingHandled != KMsvNullIndexEntryId )
       
  1013         {
       
  1014         iClientEntry->SetEntryL( iEntryBeingHandled );
       
  1015         TMsvEntry tEntry = iClientEntry->Entry();
       
  1016         iClientEntry->SetEntryL( tEntry.Parent() );
       
  1017         iClientEntry->DeleteL( iEntryBeingHandled );
       
  1018         iEntryBeingHandled = KMsvNullIndexEntryId;	
       
  1019         }
       
  1020     }
       
  1021 
       
  1022 // -----------------------------------------------------------------------------
       
  1023 //
       
  1024 // -----------------------------------------------------------------------------
       
  1025 //
       
  1026 EXPORT_C void CMmsCodecClient::InitializeChunkedRetrievingL(
       
  1027     TMsvId aMessageId,
       
  1028     TMsvId& aFolder,
       
  1029     TUint32& aFlags,
       
  1030     TBool& aUnread,
       
  1031     TInt& aOverallDataSize,
       
  1032     TRequestStatus& aStatus )
       
  1033     {
       
  1034     iClientStatus = &aStatus;
       
  1035     
       
  1036     ResetChunkedMode();
       
  1037     if ( iState == EEntryCreated )
       
  1038         {
       
  1039         // delete entry
       
  1040         DeleteCurrentEntryL();
       
  1041         iState = EIdle;  //No more new entry
       
  1042         User::Leave( KErrArgument );
       
  1043         }
       
  1044         
       
  1045     iEntryBeingHandled = aMessageId;
       
  1046     
       
  1047     iLastChunk = EFalse;
       
  1048     if ( iEncodeBuffer )
       
  1049         {
       
  1050         // delete old data from buffer
       
  1051         iEncodeBuffer->ResizeL( 0 );    
       
  1052         }
       
  1053     else
       
  1054         {
       
  1055         // create new buffer
       
  1056         iEncodeBuffer = CBufFlat::NewL( 0x400 ); // expand in multiple kilos
       
  1057         }
       
  1058 
       
  1059     iClientEntry->SetEntryL( aMessageId ); 
       
  1060     
       
  1061     TMsvEntry tEntry = iClientEntry->Entry();
       
  1062 
       
  1063     // Get the flags of the entry.
       
  1064     RetrieveFlags( tEntry, aFlags, aUnread );
       
  1065     // Get the folder where the message is stored.
       
  1066     aFolder = tEntry.Parent();
       
  1067     tEntry.SetReadOnly( EFalse );
       
  1068     iClientEntry->ChangeL( tEntry );
       
  1069 
       
  1070     // Prepare MMS headers for encoding.
       
  1071     // Gets the message store for the current context with read access.
       
  1072     CMsvStore* store = iClientEntry->ReadStoreL();
       
  1073     CleanupStack::PushL( store );
       
  1074     iMmsHeaders->RestoreL( *store );
       
  1075 
       
  1076     iMmsHeaders->SetMessageType( KMmsMessageTypeMSendReq );
       
  1077 
       
  1078     // Set MMS version if it is undefined
       
  1079     if ( iMmsHeaders->MmsVersion() == 0 )
       
  1080         {
       
  1081         // Version not set
       
  1082         iMmsHeaders->SetMmsVersion( iMmsVersion );
       
  1083         }
       
  1084 
       
  1085     // we do not change anything on the disk.
       
  1086     CleanupStack::PopAndDestroy( store ); 
       
  1087     
       
  1088     // Encode the MMS.
       
  1089     iEncodeBuffer->ResizeL( KMmsCodecClientChunkSize );
       
  1090     
       
  1091     iClientEntryWrapper->SetCurrentEntry( aMessageId );
       
  1092 
       
  1093     // iEncoder sets client status to pending if the function does not leave
       
  1094     iEncoder->StartChunkedL( *iClientEntryWrapper, *iMmsHeaders, *iEncodeBuffer, *iClientStatus );
       
  1095     
       
  1096     iState = EChunkedRetrieve;
       
  1097     // iEncoder calculates the overall data size when encoding headers in StartChunkedL
       
  1098     aOverallDataSize = iEncoder->OverallDataSize();
       
  1099     
       
  1100     // CodecClient does not become active here.
       
  1101     // iEncoder completes client
       
  1102     
       
  1103     }
       
  1104 	
       
  1105 // -----------------------------------------------------------------------------
       
  1106 //
       
  1107 // -----------------------------------------------------------------------------
       
  1108 //
       
  1109 EXPORT_C TInt CMmsCodecClient::GetNextDataPart( TPtrC8& aDataPart, TBool& aLastDataChunk )
       
  1110     {
       
  1111     if ( iState != EChunkedRetrieve )
       
  1112         {
       
  1113         // called out of context
       
  1114         return KErrArgument;
       
  1115         }
       
  1116     
       
  1117     TInt error = KErrNone;
       
  1118     error = iEncoder->GetNextDataPart( aDataPart, iLastChunk );
       
  1119     aLastDataChunk = iLastChunk;
       
  1120     return error;
       
  1121     }
       
  1122 
       
  1123 	
       
  1124 // -----------------------------------------------------------------------------
       
  1125 //
       
  1126 // -----------------------------------------------------------------------------
       
  1127 //
       
  1128 EXPORT_C TInt CMmsCodecClient::ReleaseData()
       
  1129     {
       
  1130     if ( iState != EChunkedRetrieve )
       
  1131         {
       
  1132         // called out of context
       
  1133         return KErrArgument;
       
  1134         }
       
  1135     
       
  1136     TInt error = KErrNone;
       
  1137     error = iEncoder->ReleaseData();
       
  1138     if ( iLastChunk || error != KErrNone )
       
  1139         {
       
  1140         // Read only flag is restored and iState goes back to idle
       
  1141         ReleaseRetrievedEntry();
       
  1142         }
       
  1143     return error;    
       
  1144     }
       
  1145 
       
  1146 // -----------------------------------------------------------------------------
       
  1147 //
       
  1148 // -----------------------------------------------------------------------------
       
  1149 //
       
  1150 EXPORT_C void CMmsCodecClient::InitializeChunkedAddingL(
       
  1151     TMsvId aFolder,
       
  1152     TMsvId& aMessageId,
       
  1153     TUint32 aFlags,
       
  1154     TBool aUnread )
       
  1155     {
       
  1156     
       
  1157     ResetChunkedMode();
       
  1158     if ( iState == EEntryCreated )
       
  1159         {
       
  1160         // delete entry
       
  1161         DeleteCurrentEntryL();
       
  1162         iState = EIdle;  //No more new entry
       
  1163         User::Leave( KErrArgument );
       
  1164         }
       
  1165         
       
  1166     // all folders are valid    
       
  1167        
       
  1168     iEntryBeingHandled = aMessageId;
       
  1169     iFolder = aFolder;
       
  1170     iFlags = aFlags;
       
  1171     iUnread = aUnread;
       
  1172     
       
  1173     // create the entry that is going to receive data
       
  1174     
       
  1175     // set first default flags 
       
  1176     TMsvEntry tEntry;
       
  1177 
       
  1178     // set all relevant flags in tMsvEntry
       
  1179     tEntry.iType = KUidMsvMessageEntry;
       
  1180     tEntry.iMtm = KUidMsgTypeMultimedia;
       
  1181     tEntry.iServiceId = iMmsClient->DefaultServiceL();
       
  1182     tEntry.SetNew( EFalse );
       
  1183 
       
  1184     tEntry.SetVisible( EFalse );
       
  1185     tEntry.SetComplete( EFalse );
       
  1186     tEntry.SetInPreparation( ETrue );
       
  1187 
       
  1188     // Query disk space:
       
  1189     TInt error = iClientEntryWrapper->DiskSpaceBelowCriticalLevelL( KMmsIndexEntryExtra );
       
  1190     User::LeaveIfError( error );
       
  1191 
       
  1192     iClientEntry->SetEntryL( aFolder );
       
  1193     iClientEntry->CreateL( tEntry );
       
  1194     iEntryBeingHandled = tEntry.Id();
       
  1195     aMessageId = iEntryBeingHandled;
       
  1196     iState = EChunkedAdd;
       
  1197     
       
  1198     iPosition = 0;
       
  1199     if ( iEncodeBuffer )
       
  1200         {
       
  1201         // delete old data from buffer
       
  1202         iEncodeBuffer->ResizeL( 0 );    
       
  1203         }
       
  1204     else
       
  1205         {
       
  1206         // create new buffer
       
  1207         iEncodeBuffer = CBufFlat::NewL( 0x400 ); // expand in multiple kilos
       
  1208         }
       
  1209     
       
  1210     iClientEntryWrapper->SetCurrentEntry( iEntryBeingHandled );
       
  1211     iMmsHeaders->Reset();
       
  1212     
       
  1213     iDecoder->InitializeChunkedMode(
       
  1214         *iClientEntryWrapper,
       
  1215         *iMmsHeaders,
       
  1216         *iEncodeBuffer
       
  1217         );
       
  1218     }
       
  1219 
       
  1220 // -----------------------------------------------------------------------------
       
  1221 //
       
  1222 // -----------------------------------------------------------------------------
       
  1223 //
       
  1224 EXPORT_C void CMmsCodecClient::InitializeChunkedReplacingL(
       
  1225     TMsvId aMessageId,
       
  1226     TUint32 aFlags,
       
  1227     TBool aUnread )
       
  1228     {
       
  1229     
       
  1230     ResetChunkedMode();
       
  1231     //Let's first make sure that the client is not illegally trashing the 
       
  1232     //message store with empty entries. Only the AddMM -function is allowed to 
       
  1233     //be called after the new entry has been created.
       
  1234     if ( iState == EEntryCreated ) 
       
  1235         {
       
  1236         // delete entry
       
  1237         DeleteCurrentEntryL();   
       
  1238         iState = EIdle;  //No more new entry
       
  1239         User::Leave( KErrArgument );
       
  1240         }
       
  1241     
       
  1242     // Messages in outbox must not be replaced.
       
  1243     if ( ParentOutbox( aMessageId ) )
       
  1244         {
       
  1245         iState = EIdle;
       
  1246         User::Leave( KErrArgument );
       
  1247         }
       
  1248 
       
  1249     iFlags = aFlags;
       
  1250     iUnread = aUnread;
       
  1251      
       
  1252     // Set the Entry as being handled
       
  1253     iEntryBeingHandled = aMessageId;
       
  1254 
       
  1255     iClientEntry->SetEntryL( iEntryBeingHandled );
       
  1256     TMsvEntry tEntry = iClientEntry->Entry();
       
  1257      
       
  1258     tEntry.SetVisible( EFalse );
       
  1259     tEntry.SetComplete( EFalse );
       
  1260     tEntry.SetInPreparation( ETrue );
       
  1261     tEntry.SetReadOnly( EFalse );
       
  1262  
       
  1263     iClientEntry->ChangeL( tEntry );
       
  1264 
       
  1265     // Remove the attachments of the Entry   
       
  1266     CMsvStore* store = iClientEntry->EditStoreL();
       
  1267     CleanupStack::PushL( store );
       
  1268 
       
  1269     MMsvAttachmentManager& attachMan = store->AttachmentManagerL();
       
  1270     MMsvAttachmentManagerSync& attachManSynch = store->AttachmentManagerExtensionsL(); 
       
  1271     
       
  1272     TInt numOfAttach( attachMan.AttachmentCount() );
       
  1273     TInt i( 0 );
       
  1274     while ( i < numOfAttach )
       
  1275         {
       
  1276         // we keep deleting the first one 
       
  1277     	attachManSynch.RemoveAttachmentL( 0 );
       
  1278         i++;
       
  1279         }
       
  1280     
       
  1281     store->CommitL();
       
  1282     CleanupStack::PopAndDestroy( store );
       
  1283     
       
  1284     iState = EChunkedReplace;
       
  1285     
       
  1286     iPosition = 0;
       
  1287     if ( iEncodeBuffer )
       
  1288         {
       
  1289         // delete old data from buffer
       
  1290         iEncodeBuffer->ResizeL( 0 );    
       
  1291         }
       
  1292     else
       
  1293         {
       
  1294         // create new buffer
       
  1295         iEncodeBuffer = CBufFlat::NewL( 0x400 ); // expand in multiple kilos
       
  1296         }
       
  1297         
       
  1298     iClientEntryWrapper->SetCurrentEntry( iEntryBeingHandled );
       
  1299     iMmsHeaders->Reset();
       
  1300     
       
  1301     iDecoder->InitializeChunkedMode(
       
  1302         *iClientEntryWrapper,
       
  1303         *iMmsHeaders,
       
  1304         *iEncodeBuffer
       
  1305         );
       
  1306     }
       
  1307 
       
  1308 
       
  1309 // -----------------------------------------------------------------------------
       
  1310 //
       
  1311 // -----------------------------------------------------------------------------
       
  1312 //
       
  1313 EXPORT_C TInt CMmsCodecClient::NextDataPart(
       
  1314     TPtrC8& aDataPart,
       
  1315     TBool aLastDataChunk )
       
  1316     {
       
  1317     if ( iState != EChunkedAdd && iState != EChunkedReplace )
       
  1318         {
       
  1319         // called out of context
       
  1320         return KErrArgument;
       
  1321         }
       
  1322         
       
  1323     if ( iEntryBeingHandled == KMsvNullIndexEntryId )
       
  1324         {
       
  1325         // something has gone wrong earlier and entry has been deleted
       
  1326         // but the caller has ignored the error and tries to continue
       
  1327         return KErrNotFound;
       
  1328         }
       
  1329     
       
  1330     // This must work the same way as if the data were coming over
       
  1331     // HTTP transport...
       
  1332     TInt error = KErrNone;
       
  1333     TInt currentData = aDataPart.Length();
       
  1334     TRAP( error,
       
  1335         {
       
  1336         iEncodeBuffer->ResizeL( aDataPart.Length() + iPosition );
       
  1337         iEncodeBuffer->Write( iPosition, aDataPart, currentData );
       
  1338         }
       
  1339         );
       
  1340     // The data is now in our own buffer if memeory did not run out
       
  1341     
       
  1342     iPosition = 0;
       
  1343     
       
  1344     if ( error == KErrNone )
       
  1345         {
       
  1346         error = iDecoder->NextDataPart( *iEncodeBuffer, iPosition, aLastDataChunk );
       
  1347         }
       
  1348     
       
  1349     TInt amount = iEncodeBuffer->Size() - iPosition;
       
  1350     if ( iPosition != 0 )
       
  1351         {
       
  1352         // some data handled
       
  1353         iEncodeBuffer->Delete( 0, iPosition );
       
  1354         }
       
  1355     // This does not leave - we are reducing the size    
       
  1356     TRAP_IGNORE( iEncodeBuffer->ResizeL( amount ) );
       
  1357     iPosition = amount; // continue writing from here
       
  1358 
       
  1359     if ( error != KErrNone )
       
  1360         {
       
  1361         iDecoder->RelaseDataSink();
       
  1362         // delete entry, not allowed to leave
       
  1363         iClientEntryWrapper->DeleteEntry( iEntryBeingHandled ); 
       
  1364         iEntryBeingHandled = KMsvNullIndexEntryId;
       
  1365         iState = EIdle;
       
  1366         }
       
  1367         
       
  1368     if ( aLastDataChunk && error == KErrNone )
       
  1369         {
       
  1370         // The message is complete - finalize the entry
       
  1371         iDecoder->RelaseDataSink();
       
  1372         TRAP ( error, FinalizeDecodedMML() );
       
  1373         if ( error != KErrNone ) // Finalizing leaves
       
  1374             {
       
  1375             // delete entry, not allowed to leave
       
  1376             iClientEntryWrapper->DeleteEntry( iEntryBeingHandled ); 
       
  1377             }
       
  1378         iEntryBeingHandled = KMsvNullIndexEntryId;
       
  1379         iState = EIdle;
       
  1380         }
       
  1381     
       
  1382     return error;
       
  1383     }
       
  1384 
       
  1385 void CMmsCodecClient::ResetChunkedMode()
       
  1386     {
       
  1387     // If the previous operation has not completed correctly,
       
  1388     // do what cleanup we can and then allow operation to continue
       
  1389     switch ( iState )
       
  1390         {
       
  1391         case EChunkedRetrieve:
       
  1392             {
       
  1393             if ( iEntryBeingHandled != KMsvNullIndexEntryId )
       
  1394                 {
       
  1395                 // This also sets the iState back to idle
       
  1396                 ReleaseRetrievedEntry();
       
  1397                 }
       
  1398             break;
       
  1399             }
       
  1400         case EChunkedAdd:
       
  1401             {
       
  1402             iDecoder->RelaseDataSink();
       
  1403             if ( iEntryBeingHandled != KMsvNullIndexEntryId )
       
  1404                 {
       
  1405                 iClientEntryWrapper->DeleteEntry( iEntryBeingHandled ); 
       
  1406                 }
       
  1407             iState = EIdle;
       
  1408             break;
       
  1409             }
       
  1410         case EChunkedReplace:
       
  1411             {
       
  1412             iDecoder->RelaseDataSink();
       
  1413             // Delete entry. It could still be incomplete
       
  1414             if ( iEntryBeingHandled != KMsvNullIndexEntryId )
       
  1415                 {
       
  1416                 iClientEntryWrapper->DeleteEntry( iEntryBeingHandled ); 
       
  1417                 }
       
  1418             iState = EIdle;
       
  1419             break;
       
  1420             }
       
  1421         default:
       
  1422             {
       
  1423             break;
       
  1424             }
       
  1425         }
       
  1426     }
       
  1427 
       
  1428 void CMmsCodecClient::ReleaseRetrievedEntry()
       
  1429     {
       
  1430     // Restore read only flag if we turned it off
       
  1431     // If not able to access the entry, we cannot help it
       
  1432     if ( iEntryBeingHandled != KMsvNullIndexEntryId )
       
  1433         {
       
  1434         TRAP_IGNORE( 
       
  1435             {
       
  1436             iClientEntry->SetEntryL( iEntryBeingHandled );
       
  1437             TMsvEntry tEntry = iClientEntry->Entry();
       
  1438             TMsvId parent = tEntry.Parent();
       
  1439 
       
  1440             if ( parent != KMsvDraftEntryId &&
       
  1441                 parent != KMsvGlobalOutBoxIndexEntryId )
       
  1442                 {
       
  1443                 tEntry.SetReadOnly( ETrue );           
       
  1444                 // We do our best
       
  1445                 iClientEntry->ChangeL( tEntry );
       
  1446                 }
       
  1447             }
       
  1448             );
       
  1449         }
       
  1450     // Last chunk released or terminated by error - done with this entry
       
  1451     iEntryBeingHandled = KMsvNullIndexEntryId;
       
  1452     iState = EIdle;
       
  1453     }
       
  1454 
       
  1455 
       
  1456 // ========================== OTHER EXPORTED FUNCTIONS =========================
       
  1457 
       
  1458 //  End of File