| 31 |      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  
 |