|         |      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 entrys. 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 entrys. 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 entrys. 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 entrys. 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 entrys. 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 entrys. 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 entrys. 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                 //lenght  | 
|         |    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 entrys. 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   |