omads/omadsextensions/adapters/mms/src/mmsdatastore.cpp
changeset 40 b63e67867dcd
child 42 1eb2293b4d77
equal deleted inserted replaced
39:9905f7d46607 40:b63e67867dcd
       
     1 /*
       
     2 * Copyright (c) 2005-2009 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:  Part of SyncML Data Synchronization Plug In Adapter
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32base.h>
       
    20 #include <msvstd.h>
       
    21 #include <msvapi.h>
       
    22 #include <msvids.h>
       
    23 #include <mtclreg.h> 
       
    24 #include <mmsconst.h>
       
    25 #include <centralrepository.h>
       
    26 #include <mmscodecclient.h>
       
    27 #include <sysutil.h>
       
    28 #include <MmsEngineInternalCRKeys.h>
       
    29 
       
    30 #include "mmsdatastore.h"
       
    31 #include "omadsfolderobject.h"
       
    32 #include "mmsadaptermsvapi.h"
       
    33 #include "mmsdataproviderdefs.h"
       
    34 #include "logger.h"
       
    35 
       
    36 _LIT8( KMmsMimeType, "application/vnd.wap.mms-message" );
       
    37 _LIT8( KMmsMimeVersion, "1.2" );
       
    38 _LIT8( KFolderMimeType, "application/vnd.omads-folder+xml" );
       
    39 _LIT8( KFolderMimeVersion, "1.2" );
       
    40 
       
    41 const TInt KDataBufferSize = 1024;
       
    42 const TUint KMMS_Flag_Read = 0x01;
       
    43 
       
    44 // -----------------------------------------------------------------------------
       
    45 // CMmsDataStore::CMmsDataStore
       
    46 // C++ default constructor can NOT contain any code, that might leave.
       
    47 // -----------------------------------------------------------------------------
       
    48 CMmsDataStore::CMmsDataStore():
       
    49     iHasHistory(EFalse),
       
    50     iDataBaseOpened(EFalse),
       
    51     iKey(TKeyArrayFix(_FOFF(TSnapshotItem, ItemId()), ECmpTInt))
       
    52     { 
       
    53     }
       
    54   
       
    55 // -----------------------------------------------------------------------------
       
    56 // CMmsDataStore::ConstructL
       
    57 // Symbian 2nd phase constructor, can leave.
       
    58 // -----------------------------------------------------------------------------
       
    59 void CMmsDataStore::ConstructL(CMsvSession &aMsvSession)
       
    60     {
       
    61     LOGGER_ENTERFN("CMmsDataStore::ConstructL");
       
    62     
       
    63     iMsvSession = &aMsvSession;
       
    64     
       
    65     // Waiter object to be used with CodecClient
       
    66     iMsvWait = CMsvOperationActiveSchedulerWait::NewLC();
       
    67     CleanupStack::Pop( iMsvWait );
       
    68     iCodecClient = CMmsCodecClient::NewL( *iMsvSession );
       
    69     iMsvApi = CMmsAdapterMsvApi::NewL( *iMsvSession );
       
    70     
       
    71     // Item UID sets, used to transfer change info
       
    72     iNewItems = new (ELeave) CNSmlDataItemUidSet;
       
    73     iDeletedItems = new (ELeave) CNSmlDataItemUidSet;
       
    74     iUpdatedItems = new (ELeave) CNSmlDataItemUidSet;
       
    75     iMovedItems = new (ELeave) CNSmlDataItemUidSet;
       
    76     iSoftDeletedItems = new (ELeave) CNSmlDataItemUidSet;
       
    77     
       
    78     iFolderObjectParser = COMADSFolderObject::NewL();
       
    79     
       
    80     LOGGER_LEAVEFN("CMmsDataStore::ConstructL");
       
    81     }
       
    82 
       
    83 // -----------------------------------------------------------------------------
       
    84 // CMmsDataStore::NewL
       
    85 // Two-phased constructor.
       
    86 // -----------------------------------------------------------------------------
       
    87 CMmsDataStore* CMmsDataStore::NewL( CMsvSession &aMsvSession)
       
    88     {
       
    89     CMmsDataStore* self = new (ELeave) CMmsDataStore;
       
    90     
       
    91     CleanupStack::PushL( self );
       
    92     self->ConstructL( aMsvSession );
       
    93     CleanupStack::Pop( self );
       
    94 
       
    95     return self;    
       
    96     }
       
    97 
       
    98     
       
    99 // -----------------------------------------------------------------------------
       
   100 // CMmsDataStore::~CMmsDataStore
       
   101 // Destructor
       
   102 // -----------------------------------------------------------------------------
       
   103 CMmsDataStore::~CMmsDataStore()
       
   104     {
       
   105     LOGGER_ENTERFN("CMmsDataStore::~CMmsDataStore()");
       
   106     
       
   107     delete iDataBuffer;
       
   108     
       
   109     delete iChangeFinder;
       
   110     delete iFolderObjectParser;
       
   111     
       
   112     delete iNewItems;
       
   113     delete iDeletedItems;
       
   114     delete iUpdatedItems;
       
   115     delete iMovedItems;
       
   116     delete iSoftDeletedItems;
       
   117  
       
   118     delete iMsvApi;
       
   119     delete iCodecClient;
       
   120     delete iMsvWait;
       
   121             
       
   122     LOGGER_LEAVEFN("CMmsDataStore::~CMmsDataStore()");
       
   123     }
       
   124 
       
   125 // -----------------------------------------------------------------------------
       
   126 // CMmsDataStore::DoOpenL
       
   127 // Opens database. This operation is performed SYNCHRONOUSLY
       
   128 // -----------------------------------------------------------------------------
       
   129 void CMmsDataStore::DoOpenL( const TDesC& /*aStoreName*/,
       
   130     MSmlSyncRelationship& aContext, TRequestStatus& aStatus )
       
   131     {
       
   132     LOGGER_ENTERFN("CMmsDataStore::DoOpenL");
       
   133     
       
   134     iCallerStatus = &aStatus;
       
   135     *iCallerStatus = KRequestPending;
       
   136     
       
   137     if ( iDataBaseOpened )
       
   138         {
       
   139         User::RequestComplete( iCallerStatus, KErrInUse );
       
   140         LOGGER_WRITE("CMmsDataStore::DoOpenL failed with KErrInUse.");
       
   141         return;
       
   142         }
       
   143     
       
   144     *iContext = aContext;
       
   145 
       
   146     // Create ChangeFinder object
       
   147     if ( iChangeFinder )
       
   148         {
       
   149         delete iChangeFinder;
       
   150         iChangeFinder = NULL;
       
   151         }
       
   152     iChangeFinder = CChangeFinder::NewL( aContext, iKey, iHasHistory, KMmsDataProviderImplUid );
       
   153     
       
   154     // Set current snapshot, this will be compared against the old one   
       
   155     RegisterSnapshotL();
       
   156     
       
   157     iDataBaseOpened = ETrue;
       
   158     iCurrentState = EMmsOpenAndWaiting;
       
   159     User::RequestComplete( iCallerStatus, KErrNone );   
       
   160     
       
   161     LOGGER_LEAVEFN("CMmsDataStore::DoOpenL");
       
   162     }
       
   163 
       
   164 // -----------------------------------------------------------------------------
       
   165 // CMmsDataStore::DoCancelRequest
       
   166 // Not supported, does nothing.
       
   167 // -----------------------------------------------------------------------------
       
   168 void CMmsDataStore::DoCancelRequest()
       
   169     {
       
   170     LOGGER_ENTERFN("CMmsDataStore::DoCancelRequestL");
       
   171     LOGGER_LEAVEFN("CMmsDataStore::DoCancelRequestL");
       
   172     }
       
   173 
       
   174 // -----------------------------------------------------------------------------
       
   175 // CMmsDataStore::DoStoreName
       
   176 // Returns the name of the DataStore
       
   177 // -----------------------------------------------------------------------------
       
   178 const TDesC& CMmsDataStore::DoStoreName() const
       
   179     {
       
   180     LOGGER_ENTERFN("CMmsDataStore::DoStoreName");
       
   181     
       
   182     if ( iDataBaseOpened )
       
   183         {
       
   184         LOGGER_LEAVEFN( "CMmsDataStore::DoStoreName" );
       
   185         LOGGER_WRITE_1( "Database name: %S", &KNSmlDefaultLocalDbName );
       
   186         return KNSmlDefaultLocalDbName;
       
   187         }
       
   188 
       
   189     LOGGER_LEAVEFN( "CMmsDataStore::DoStoreName" );
       
   190     return KNullDesC;
       
   191     }
       
   192 
       
   193 // -----------------------------------------------------------------------------
       
   194 // CMmsDataStore::DoBeginTransactionL
       
   195 // Transactions are not supported.
       
   196 // -----------------------------------------------------------------------------
       
   197 void CMmsDataStore::DoBeginTransactionL()
       
   198     {
       
   199     LOGGER_ENTERFN("CMmsDataStore::DoBeginTransactionL");
       
   200     LOGGER_WRITE( "CMmsDataStore::DoBeginTransactionL leaved with KErrNotSupported." );
       
   201     User::Leave( KErrNotSupported );
       
   202     }
       
   203 
       
   204 // -----------------------------------------------------------------------------
       
   205 // CMmsDataStore::DoCommitTransactionL
       
   206 // Transactions are not supported.
       
   207 // -----------------------------------------------------------------------------
       
   208 void CMmsDataStore::DoCommitTransactionL( TRequestStatus& aStatus )
       
   209     {
       
   210     LOGGER_ENTERFN( "CMmsDataStore::DoCommitTransactionL" ); 
       
   211     LOGGER_WRITE( "CMmsDataStore::DoCommitTransactionL failed with KErrNotSupported." );
       
   212     
       
   213     iCallerStatus = &aStatus;
       
   214     User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   215     }
       
   216 
       
   217 // -----------------------------------------------------------------------------
       
   218 // CMmsDataStore::DoRevertTransaction
       
   219 // Transactions are not supported.
       
   220 // -----------------------------------------------------------------------------
       
   221 void CMmsDataStore::DoRevertTransaction( TRequestStatus& aStatus )
       
   222     {
       
   223     LOGGER_ENTERFN( "CMmsDataStore::DoRevertTransaction" ); 
       
   224     iCallerStatus = &aStatus;
       
   225     User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   226     LOGGER_LEAVEFN( "CMmsDataStore::DoRevertTransaction" );
       
   227     }
       
   228 
       
   229 // -----------------------------------------------------------------------------
       
   230 // CMmsDataStore::DoBeginBatchL
       
   231 // Batching is not supported.
       
   232 // -----------------------------------------------------------------------------
       
   233 void CMmsDataStore::DoBeginBatchL()
       
   234     {
       
   235     LOGGER_ENTERFN( "CMmsDataStore::DoBeginBatchL" );
       
   236     LOGGER_WRITE( "CMmsDataStore::DoBeginBatchL leaved with KErrNotSupported." );
       
   237     User::Leave( KErrNotSupported );    
       
   238     }
       
   239 
       
   240 // -----------------------------------------------------------------------------
       
   241 // CMmsDataStore::DoCommitBatchL
       
   242 // Batching is not supported
       
   243 // -----------------------------------------------------------------------------
       
   244 //
       
   245 void CMmsDataStore::DoCommitBatchL( RArray<TInt>& /*aResultArray*/, TRequestStatus& aStatus )
       
   246     {
       
   247     LOGGER_ENTERFN( "CMmsDataStore::DoCommitBatchL" );  
       
   248     LOGGER_WRITE( "CMmsDataStore::DoCommitBatchL failed with KErrNotSupported" );
       
   249     iCallerStatus = &aStatus;
       
   250     User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   251     }
       
   252 
       
   253 // -----------------------------------------------------------------------------
       
   254 // CMmsDataStore::DoCancelBatch
       
   255 // Batching is not supported
       
   256 // -----------------------------------------------------------------------------
       
   257 void CMmsDataStore::DoCancelBatch()
       
   258     {
       
   259     LOGGER_ENTERFN( "CMmsDataStore::DoCancelBatch" );
       
   260     LOGGER_LEAVEFN( "CMmsDataStore::DoCancelBatch" );
       
   261     }
       
   262 
       
   263 // -----------------------------------------------------------------------------
       
   264 // CMmsDataStore::DoSetRemoteStoreFormatL
       
   265 // Not supported
       
   266 // -----------------------------------------------------------------------------
       
   267 //
       
   268 void CMmsDataStore::DoSetRemoteStoreFormatL( const CSmlDataStoreFormat& /*aServerDataStoreFormat*/ )
       
   269     {
       
   270     LOGGER_ENTERFN("CMmsDataStore::DoSetRemoteStoreFormatL");
       
   271     LOGGER_LEAVEFN("CMmsDataStore::DoSetRemoteStoreFormatL");
       
   272     }
       
   273 
       
   274 // -----------------------------------------------------------------------------
       
   275 // CMmsDataStore::DoSetRemoteMaxObjectSize
       
   276 // Not supported
       
   277 // -----------------------------------------------------------------------------
       
   278 void CMmsDataStore::DoSetRemoteMaxObjectSize( TInt /*aServerMaxObjectSize*/ )
       
   279     {
       
   280     LOGGER_ENTERFN("CMmsDataStore::DoSetRemoteMaxObjectSize");
       
   281     LOGGER_LEAVEFN("CMmsDataStore::DoSetRemoteMaxObjectSize");
       
   282     }
       
   283 
       
   284 // -----------------------------------------------------------------------------
       
   285 // CMmsDataStore::DoMaxObjectSize
       
   286 // Reads the maximum MMS Message size from the central repository
       
   287 // -----------------------------------------------------------------------------
       
   288 TInt CMmsDataStore::DoMaxObjectSize() const
       
   289     {
       
   290     LOGGER_ENTERFN( "CMmsDataStore::DoMaxObjectSize" );
       
   291     
       
   292     CRepository* repository( NULL );
       
   293     TInt error( KErrNone );
       
   294     TInt maxSendSize( 0 );
       
   295     
       
   296     // Create central repository instance
       
   297     TRAP( error, repository = CRepository::NewL( KCRUidMmsEngine ) );  
       
   298     if ( error == KErrNone )
       
   299         {
       
   300         // Obtain the size from the central repository.
       
   301         // In the case of error we'll set the value to zero ("anything goes").
       
   302         error = repository->Get( KMmsEngineMaximumSendSize, maxSendSize );
       
   303         if ( error != KErrNone )
       
   304             {
       
   305             maxSendSize = 0;
       
   306             }
       
   307         
       
   308         delete repository;
       
   309         }
       
   310     else
       
   311         {
       
   312         LOGGER_WRITE_1( "CRepository::NewL leaved with %d", error );
       
   313         }       
       
   314         
       
   315     LOGGER_LEAVEFN( "CMmsDataStore::DoMaxObjectSize" );
       
   316     return maxSendSize;
       
   317     }
       
   318 
       
   319 // -----------------------------------------------------------------------------
       
   320 // CMmsDataStore::DoOpenItemL
       
   321 // Opens item in the DataStore, reads it (either completely or partially) 
       
   322 // to the temporary buffer where it can be later read to the remote database.
       
   323 // -----------------------------------------------------------------------------
       
   324 void CMmsDataStore::DoOpenItemL( TSmlDbItemUid aUid, TBool& aFieldChange, 
       
   325     TInt& aSize, TSmlDbItemUid& aParent, TDes8& aMimeType, 
       
   326     TDes8& aMimeVer, TRequestStatus& aStatus )
       
   327     {
       
   328     LOGGER_ENTERFN( "CMmsDataStore::DoOpenItemL" );
       
   329 
       
   330     LOGGER_WRITE_1( "Opening item %d.", aUid );
       
   331     
       
   332     // Store these for later use
       
   333     iCallerStatus = &aStatus;
       
   334     *iCallerStatus = KRequestPending;
       
   335     
       
   336     // Check that we're in a proper state
       
   337     if ( iCurrentState != EMmsOpenAndWaiting )
       
   338         {
       
   339         LOGGER_WRITE_1( "CMmsDataStore::DoOpenItemL, invalid state %d.", iCurrentState );
       
   340         User::RequestComplete( iCallerStatus, KErrNotReady );
       
   341         return;
       
   342         }
       
   343         
       
   344     TBool userFolderFound( EFalse );
       
   345     TTime timeStamp;
       
   346     TPtrC folderName;
       
   347     userFolderFound = iMsvApi->FindUserFolderL( aUid, folderName, timeStamp );
       
   348     
       
   349     if ( userFolderFound )
       
   350         {
       
   351         // Allocate new buffer
       
   352         SAFEDELETE( iDataBuffer );
       
   353         iDataBuffer = CBufFlat::NewL( KDataBufferSize );
       
   354         
       
   355         iFolderObjectParser->SetName( folderName );
       
   356         iFolderObjectParser->SetCreatedDate( timeStamp.DateTime() );
       
   357         iFolderObjectParser->SetModifiedDate( timeStamp.DateTime() );
       
   358         iFolderObjectParser->ExportFolderXmlL( *iDataBuffer ); 
       
   359        
       
   360         iParentId = KMsvMyFoldersEntryIdValue;
       
   361         
       
   362         iCurrentState = EFolderOpen;
       
   363         iReadPosition = 0;
       
   364         
       
   365         aSize = iDataBuffer->Size();
       
   366         }
       
   367     else // Open MMS message
       
   368         {
       
   369         TInt error( KErrNone );
       
   370         
       
   371         CMsvEntry* entry( NULL );
       
   372         TRAP( error, entry = iMsvSession->GetEntryL(aUid) );
       
   373         if ( error != KErrNone )
       
   374             {
       
   375             User::RequestComplete( iCallerStatus, KErrNotFound ); 
       
   376             LOGGER_WRITE_1("iMsvSession->GetEntryL failed with %d.", error);
       
   377             return;
       
   378             }
       
   379         
       
   380         TMsvEntry messageEntry = entry->Entry();
       
   381         SAFEDELETE( entry );
       
   382     
       
   383         iCurrentId = aUid;
       
   384         iParentId = messageEntry.Parent();
       
   385         iReadCounter = 0;
       
   386     
       
   387         // Check whether we need to send the whole item
       
   388         if ( iChangeFinder->UpdatePartialL( aUid ) )
       
   389             {
       
   390             LOGGER_WRITE("EMmsItemOpenFieldUpdate");
       
   391             aSize = 1;
       
   392             iCurrentState = EMmsItemOpenFieldUpdate;
       
   393             }
       
   394         else    
       
   395             {
       
   396             // Read the whole item from the message store to the buffer
       
   397             TUint32 flags( 0 );
       
   398             TRAP( error, iCodecClient->InitializeChunkedRetrievingL(
       
   399                 iCurrentId,
       
   400                 iParentId,
       
   401                 flags,
       
   402                 iUnread,
       
   403                 aSize,
       
   404                 iMsvWait->iStatus) );
       
   405             
       
   406             if ( error != KErrNone ) 
       
   407                 {
       
   408                 User::RequestComplete( iCallerStatus, error );
       
   409                 LOGGER_WRITE_1("iCodecClient->InitializeChunkedRetrievingL failed with %d.", error); 
       
   410                 return;         
       
   411                 }
       
   412             
       
   413             // Wait until the message has been processed
       
   414             iMsvWait->Start();
       
   415             
       
   416             if ( iMsvWait->iStatus != KErrNone )
       
   417                 {
       
   418                 User::RequestComplete( iCallerStatus, iMsvWait->iStatus.Int() );
       
   419                 LOGGER_WRITE_1( "iCodecClient->InitializeChunkedRetrievingL failed with %d",
       
   420                     iMsvWait->iStatus.Int() ); 
       
   421                 return;
       
   422                 }
       
   423             LOGGER_WRITE_1("iUnread: %d", (TInt)iUnread);
       
   424             aSize++; // Status byte will be added also, reserve one additional byte for that.
       
   425             iCurrentState = EMmsItemOpen;
       
   426             }
       
   427         } // Open MMS message
       
   428     
       
   429     aParent = iParentId;
       
   430     
       
   431     aFieldChange = iCurrentState == EMmsItemOpenFieldUpdate ? ETrue : EFalse;
       
   432     
       
   433     if ( iCurrentState == EFolderOpen ) // Message folder
       
   434         {
       
   435         TInt targetLength = KFolderMimeType().Length();
       
   436         if ( aMimeType.MaxLength() < targetLength )
       
   437             {
       
   438             targetLength = aMimeType.MaxLength();
       
   439             }
       
   440         aMimeType.Copy( KFolderMimeType().Ptr(), targetLength );
       
   441 
       
   442         // Set mime version (do not exceed the allocated buffer)
       
   443         targetLength = KFolderMimeVersion().Length();
       
   444         if ( aMimeVer.MaxLength() < targetLength )
       
   445             {
       
   446             targetLength = aMimeVer.MaxLength();
       
   447             }
       
   448         aMimeVer.Copy( KFolderMimeVersion().Ptr(), targetLength );
       
   449         }
       
   450     else // EMmsMessage
       
   451         {   
       
   452         TInt targetLength = KMmsMimeType().Length();
       
   453         if ( aMimeType.MaxLength() < targetLength )
       
   454             {
       
   455             targetLength = aMimeType.MaxLength();
       
   456             }
       
   457         aMimeType.Copy( KMmsMimeType().Ptr(), targetLength );
       
   458 
       
   459         // Set mime version (do not exceed the allocated buffer)
       
   460         targetLength = KMmsMimeVersion().Length();
       
   461         if ( aMimeVer.MaxLength() < targetLength )
       
   462             {
       
   463             targetLength = aMimeVer.MaxLength();
       
   464             }
       
   465         aMimeVer.Copy( KMmsMimeVersion().Ptr(), targetLength );
       
   466         }
       
   467     
       
   468     LOGGER_WRITE_1("aSize: %d", aSize);
       
   469     
       
   470     // Signal we're complete
       
   471     User::RequestComplete( iCallerStatus, KErrNone ); 
       
   472 
       
   473     LOGGER_LEAVEFN("CMmsDataStore::DoOpenItemL");
       
   474     }
       
   475 
       
   476 // -----------------------------------------------------------------------------
       
   477 // CMmsDataStore::DoCreateItemL
       
   478 // Create new item to the message store.
       
   479 // Return the id number of the newly created item
       
   480 // -----------------------------------------------------------------------------
       
   481 void CMmsDataStore::DoCreateItemL( TSmlDbItemUid& aUid, TInt aSize, TSmlDbItemUid aParent, 
       
   482     const TDesC8& aMimeType, const TDesC8& /*aMimeVer*/, TRequestStatus& aStatus )
       
   483     {
       
   484     LOGGER_ENTERFN( "CMmsDataStore::DoCreateItemL" );
       
   485     LOGGER_WRITE_1( "Parent folder: %d.", aParent );
       
   486     
       
   487     // Store some variables for further use
       
   488     iCallerStatus = &aStatus;
       
   489     *iCallerStatus = KRequestPending;
       
   490     
       
   491     // Ensure that we're in proper state
       
   492     if ( iCurrentState != EMmsOpenAndWaiting )
       
   493         {
       
   494         LOGGER_WRITE_1( "Invalid state %d.", iCurrentState );
       
   495         }
       
   496         
       
   497     TBool createFolder( EFalse );
       
   498     LOG( aMimeType );
       
   499     if ( aMimeType.Compare( KFolderMimeType() ) == 0 )  
       
   500         {
       
   501         createFolder = ETrue;
       
   502         }
       
   503     else if ( aMimeType.Compare( KMmsMimeType() ) != 0 )
       
   504         {
       
   505         User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   506         LOGGER_WRITE("Bad MIME type");
       
   507         return;
       
   508         }
       
   509     
       
   510     // Ensure that we've got enough disk space for the item
       
   511     if ( iCodecClient->DiskSpaceBelowCriticalLevelL( aSize ) )
       
   512         {
       
   513         User::RequestComplete( iCallerStatus, KErrDiskFull );
       
   514         LOGGER_WRITE( "Disk full" );
       
   515         return;
       
   516         }
       
   517         
       
   518     if( createFolder )
       
   519         {
       
   520         if ( aParent != KMsvMyFoldersEntryIdValue )
       
   521             {
       
   522             User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   523             LOGGER_WRITE( "Bad parent folder" );
       
   524             return;
       
   525             }
       
   526         SAFEDELETE( iDataBuffer );
       
   527         iDataBuffer = CBufFlat::NewL( KDataBufferSize );
       
   528         iCurrentState = EFolderCreating;
       
   529         iCreatedUid = &aUid;
       
   530         iWrittenDataLength = 0;
       
   531         }
       
   532     else
       
   533         {
       
   534         // There is some problems on chunked data adding, so get all data to internal buffer
       
   535         iCreatedUid = &aUid;
       
   536         iCurrentState = EMmsItemCreating;
       
   537         iWriteCounter = 0;
       
   538         iWrittenDataLength = 0;
       
   539         if ( iDataBuffer )
       
   540             {
       
   541             iDataBuffer->ResizeL( aSize );
       
   542             }
       
   543         else
       
   544             {
       
   545             iDataBuffer = CBufFlat::NewL( KDataBufferSize );
       
   546             iDataBuffer->ResizeL( aSize );
       
   547             }
       
   548         }
       
   549         
       
   550     iParentId = aParent; 
       
   551     
       
   552     // Signal we're complete
       
   553     User::RequestComplete( iCallerStatus, KErrNone );
       
   554     
       
   555     LOGGER_LEAVEFN("CMmsDataStore::DoCreateItemL");
       
   556     }
       
   557 
       
   558 // -----------------------------------------------------------------------------
       
   559 // CMmsDataStore::DoReplaceItemL
       
   560 // Begin the replace operation, ensure that the item really exists
       
   561 // -----------------------------------------------------------------------------
       
   562 void CMmsDataStore::DoReplaceItemL( TSmlDbItemUid aUid, TInt aSize, TSmlDbItemUid aParent, 
       
   563     TBool /*aFieldChange*/, TRequestStatus& aStatus )
       
   564     {
       
   565     LOGGER_ENTERFN("CMmsDataStore::DoReplaceItemL");
       
   566     LOGGER_WRITE_1("Replacing item %d.", aUid);
       
   567     LOGGER_WRITE_1("Parent folder: %d.", aParent);
       
   568     
       
   569     // Store some variables for further use
       
   570     iCallerStatus = &aStatus;
       
   571     *iCallerStatus = KRequestPending;
       
   572     
       
   573     // Ensure proper state
       
   574     if ( iCurrentState != EMmsOpenAndWaiting )
       
   575         {
       
   576         LOGGER_WRITE_1("Invalid state %d.", iCurrentState);
       
   577         }
       
   578 
       
   579     // Ensure that we've got enough disk space for the item
       
   580     if ( iCodecClient->DiskSpaceBelowCriticalLevelL( aSize ) )
       
   581         {
       
   582         User::RequestComplete( iCallerStatus, KErrDiskFull );
       
   583         LOGGER_WRITE("Disk full");
       
   584         return;
       
   585         }
       
   586              
       
   587     // Find entry
       
   588     CMsvEntry* entry(NULL);
       
   589     TRAPD( err, entry = iMsvSession->GetEntryL( aUid ) );
       
   590     if ( err != KErrNone )
       
   591         {
       
   592         User::RequestComplete( iCallerStatus, KErrNotFound );
       
   593         LOGGER_WRITE_1("CMsvSession::GetEntryL failed with %d.", err)
       
   594         return;
       
   595         }
       
   596 
       
   597     TMsvEntry tEntry = entry->Entry();
       
   598     delete entry;
       
   599     
       
   600     // Check entry type
       
   601     TBool updateFolder(EFalse);
       
   602     if ( tEntry.iType == KUidMsvFolderEntry )
       
   603         {
       
   604         updateFolder = ETrue;
       
   605         LOGGER_WRITE("Type: folder");
       
   606         }
       
   607         
       
   608    if ( ( updateFolder && aParent != KMsvMyFoldersEntryIdValue )
       
   609         || ( !updateFolder && !iMsvApi->ValidFolderL( aParent )
       
   610         || ( aParent != tEntry.Parent() ) ) )
       
   611         {
       
   612         User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   613         LOGGER_WRITE_1("Bad parent folder, message entry parent is %d", tEntry.Parent());
       
   614         return;    
       
   615         }           
       
   616     
       
   617     // Store these for further use
       
   618     iParentId = aParent;
       
   619     iCurrentId = aUid;
       
   620     
       
   621     if ( updateFolder )
       
   622         {
       
   623         SAFEDELETE( iDataBuffer );
       
   624         iDataBuffer = CBufFlat::NewL( KDataBufferSize );
       
   625         iCurrentState = EFolderUpdating;
       
   626         iWrittenDataLength = 0;
       
   627         }
       
   628     else
       
   629         {
       
   630         iCurrentState = EMmsItemUpdating;
       
   631         iWriteCounter = 0;
       
   632         iWrittenDataLength = 0;
       
   633         if ( iDataBuffer )
       
   634             {
       
   635             iDataBuffer->ResizeL( aSize );
       
   636             }
       
   637         else
       
   638             {
       
   639             iDataBuffer = CBufFlat::NewL( KDataBufferSize );
       
   640             iDataBuffer->ResizeL( aSize );
       
   641             }
       
   642         }
       
   643     
       
   644     // Signal we're complete
       
   645     User::RequestComplete( iCallerStatus, KErrNone );
       
   646 
       
   647     LOGGER_LEAVEFN("CMmsDataStore::DoReplaceItemL");
       
   648     }
       
   649 
       
   650 // -----------------------------------------------------------------------------
       
   651 // CMmsDataStore::DoReadItemL
       
   652 // Read specified amount of data from the temporary buffer
       
   653 // -----------------------------------------------------------------------------
       
   654 void CMmsDataStore::DoReadItemL( TDes8& aBuffer )
       
   655     {
       
   656     LOGGER_ENTERFN("CMmsDataStore::DoReadItemL");
       
   657     
       
   658     if ( iCurrentState == EFolderOpen )
       
   659         {   
       
   660         // This is how much we've got left in the buffer
       
   661         TInt left = iDataBuffer->Size() - iReadPosition;
       
   662     
       
   663         // Make sure that there's something to read
       
   664         if ( left > 0 )
       
   665             {
       
   666             // This is how much there's space in the destination buffer
       
   667             TInt destSize = aBuffer.MaxSize();
       
   668 
       
   669             // This is how much we can read
       
   670             TInt toRead = destSize < left ? destSize : left;
       
   671 
       
   672             // Read the data from the buffer, then update the position
       
   673             iDataBuffer->Read( iReadPosition, aBuffer, toRead );
       
   674             iReadPosition += toRead;
       
   675             }
       
   676         else
       
   677             {
       
   678             LOGGER_WRITE("All data read");
       
   679             User::Leave( KErrEof );
       
   680             }
       
   681         }
       
   682     
       
   683     else if ( iCurrentState == EMmsItemOpenFieldUpdate )
       
   684         {
       
   685         if ( iReadCounter++ == 0 )
       
   686             {
       
   687             TUint8 status = ResolveStatusBits( iUnread );
       
   688             LOGGER_WRITE_1("WriteStatusBits: %d", status);
       
   689             aBuffer.Append( &status, 1 );
       
   690             }
       
   691         else
       
   692             {
       
   693             LOGGER_WRITE("Field update done");
       
   694             User::Leave( KErrEof );             
       
   695             }   
       
   696         }
       
   697         
       
   698     else if ( iCurrentState == EMmsItemOpen )
       
   699         {
       
   700         if ( iReadCounter++ == 0 )
       
   701             {
       
   702             TUint8 status = ResolveStatusBits( iUnread );
       
   703             LOGGER_WRITE_1("WriteStatusBits: %d", status);
       
   704             aBuffer.Append( &status, 1 );
       
   705             iReadPosition = 0;
       
   706             iLastDataChunk = EFalse;
       
   707             iReadAllData = EFalse;
       
   708             }
       
   709         else if ( iReadAllData )
       
   710             {
       
   711             User::Leave( KErrEof );
       
   712             }
       
   713             
       
   714         TInt error = ReadDataRecursively( aBuffer );
       
   715         if ( error != KErrNone )
       
   716             {
       
   717             User::Leave( error );
       
   718             }           
       
   719         }
       
   720     
       
   721     else
       
   722         {
       
   723         LOGGER_WRITE_1("CMmsDataStore::DoReadItemL: bad state %d", iCurrentState);
       
   724         User::Leave( KErrNotReady );
       
   725         }   
       
   726 
       
   727     LOGGER_LEAVEFN("CMmsDataStore::DoReadItemL");   
       
   728     }
       
   729 
       
   730 // -----------------------------------------------------------------------------
       
   731 // CMmsDataStore::DoWriteItemL
       
   732 // Write specified amount of data to the temporary buffer
       
   733 // -----------------------------------------------------------------------------
       
   734 void CMmsDataStore::DoWriteItemL( const TDesC8& aData )
       
   735     {
       
   736     LOGGER_ENTERFN("CMmsDataStore::DoWriteItemL");
       
   737     LOGGER_WRITE_1("%d",iWriteCounter);
       
   738     
       
   739     TInt dataLength = aData.Length();
       
   740     LOGGER_WRITE_1("Data length: %d", dataLength);
       
   741     
       
   742     if ( !( dataLength > 0 ) ) // Should never happen...
       
   743         {
       
   744         LOGGER_WRITE("Error: no data");
       
   745         User::Leave( KErrArgument );
       
   746         }
       
   747 
       
   748     if ( iCodecClient->DiskSpaceBelowCriticalLevelL( dataLength ) )
       
   749         {
       
   750         LOGGER_WRITE("Error: disk full");
       
   751         User::Leave( KErrDiskFull );
       
   752         }
       
   753         
       
   754     TInt error( KErrNone );
       
   755     
       
   756     if ( iCurrentState == EFolderCreating || iCurrentState == EFolderUpdating )
       
   757         {
       
   758         // Add data to buffer
       
   759         iDataBuffer->InsertL( iWrittenDataLength, aData );
       
   760         iWrittenDataLength += aData.Size();
       
   761         }
       
   762       
       
   763     else if ( iCurrentState == EMmsItemCreating )
       
   764         {
       
   765         if ( iWriteCounter++ == 0 )
       
   766             {
       
   767             iUnread = aData[0] & KMMS_Flag_Read ? EFalse : ETrue;
       
   768             if ( dataLength > 1 )
       
   769                 {
       
   770                 TPtrC8 data = aData.Mid(1);
       
   771                 iDataBuffer->Write( iWrittenDataLength, data );
       
   772                 iWrittenDataLength += data.Length();
       
   773                 }
       
   774             }
       
   775         else
       
   776             {
       
   777             TPtrC8 data = aData.Mid(0);
       
   778             iDataBuffer->Write( iWrittenDataLength, data );
       
   779             iWrittenDataLength += dataLength;
       
   780             }    
       
   781         }
       
   782         
       
   783     else if ( iCurrentState == EMmsItemUpdating )
       
   784         {
       
   785         if ( iWriteCounter++ == 0 )
       
   786             {
       
   787             iUnread = aData[0] & KMMS_Flag_Read ? EFalse : ETrue;
       
   788             if ( dataLength > 1 )
       
   789                 {
       
   790                 TPtrC8 data = aData.Mid(1);
       
   791                 iDataBuffer->Write( iWrittenDataLength, data );
       
   792                 iWrittenDataLength += data.Length();
       
   793                 }
       
   794             else // just status update
       
   795                 {
       
   796                 UpdateMmsStatusL( iCurrentId, iUnread );
       
   797                 LOGGER_WRITE_1("Message status updated, iUnread: %d", iUnread);
       
   798                 }    
       
   799             }
       
   800         else
       
   801             {
       
   802             TPtrC8 data = aData.Mid(0);    
       
   803             iDataBuffer->Write( iWrittenDataLength, data );
       
   804             iWrittenDataLength += dataLength;
       
   805             }    
       
   806         }
       
   807         
       
   808     else
       
   809         {
       
   810         LOGGER_WRITE_1("Wrong state %d", iCurrentState);
       
   811         User::Leave( KErrNotReady );
       
   812         }
       
   813         
       
   814     if ( error != KErrNone )
       
   815         {
       
   816         LOGGER_WRITE_1("iCodecClient->NextDataPart() failed with %d", error);
       
   817         User::Leave( error );
       
   818         }  
       
   819 
       
   820     LOGGER_LEAVEFN("CMmsDataStore::DoWriteItemL");  
       
   821     }
       
   822 
       
   823 // -----------------------------------------------------------------------------
       
   824 // CMmsDataStore::DoCommitItemL
       
   825 // Commits item from temporary buffer to the message store
       
   826 // -----------------------------------------------------------------------------
       
   827 void CMmsDataStore::DoCommitItemL( TRequestStatus& aStatus )
       
   828     {
       
   829     LOGGER_ENTERFN("CMmsDataStore::DoCommitItemL");
       
   830     
       
   831     // Store some variables
       
   832     iCallerStatus = &aStatus;
       
   833     *iCallerStatus = KRequestPending;
       
   834     
       
   835     TInt error(KErrNone);
       
   836     
       
   837     if ( iCurrentState == EFolderCreating || iCurrentState == EFolderUpdating )
       
   838         {
       
   839         error = iFolderObjectParser->ImportFolderXml( iDataBuffer->Ptr(0) );
       
   840         if ( error != KErrNone )
       
   841             {
       
   842             User::RequestComplete( iCallerStatus, error );
       
   843             LOGGER_WRITE_1("ImportFolderXml failed with %d", error);
       
   844             return;
       
   845             }
       
   846          
       
   847          const TDesC& name = iFolderObjectParser->GetName();
       
   848          if ( name.Length() <= 0 )
       
   849             {
       
   850             User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   851             LOGGER_WRITE("Folder name is empty");
       
   852             return;
       
   853             }
       
   854             
       
   855          if ( iCurrentState == EFolderCreating )
       
   856             {
       
   857             TMsvId id;
       
   858             error = iMsvApi->AddUserFolderL( id, name );
       
   859             if ( error == KErrNone )
       
   860                 {
       
   861                 *iCreatedUid = id;
       
   862                 iCurrentId = id;
       
   863                 }
       
   864             else
       
   865                 {
       
   866                 LOGGER_WRITE_1("iMsvApi->AddFolderL failed with %d", error);
       
   867                 }    
       
   868             }
       
   869          else
       
   870             {
       
   871             error = iMsvApi->UpdateUserFolderL( iCurrentId, name );
       
   872             if ( error != KErrNone )
       
   873                 {
       
   874                 LOGGER_WRITE_1("iMsvApi->UpdateFolderL failed with %d", error);
       
   875                 }
       
   876             }
       
   877         }
       
   878     else if ( iCurrentState == EMmsItemCreating )
       
   879         {
       
   880         LOGGER_WRITE("Create MMS item");
       
   881         TMsvId newId(0);
       
   882         TUint32 flags(0);
       
   883         
       
   884         error = iCodecClient->CreateNewMessageEntryL( iParentId, newId );
       
   885         if ( !error )
       
   886             {
       
   887             iCodecClient->AddMML( *iDataBuffer, iParentId, flags, iUnread, newId, iMsvWait->iStatus );
       
   888             // Wait until the message has been processed
       
   889             iMsvWait->Start();
       
   890             error = iMsvWait->iStatus.Int();
       
   891             LOGGER_WRITE_1("error: %d", error);
       
   892             LOGGER_WRITE_1("AddMML newId: %d", newId);
       
   893             *iCreatedUid = newId;
       
   894             iCurrentId = newId;
       
   895             }
       
   896         }
       
   897     else if ( iCurrentState == EMmsItemUpdating )
       
   898         {
       
   899         if ( iWrittenDataLength > 0 ) // if no data then just field update
       
   900             {
       
   901             TUint32 flags(0);
       
   902             iCodecClient->ReplaceMML( iCurrentId, *iDataBuffer, flags, iUnread, iMsvWait->iStatus );
       
   903             iMsvWait->Start();
       
   904             error = iMsvWait->iStatus.Int();
       
   905             }
       
   906         else
       
   907             {
       
   908             UpdateMmsStatusL( iCurrentId, iUnread );   
       
   909             }
       
   910         }
       
   911     else
       
   912         {
       
   913         User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   914         LOGGER_WRITE_1("Bad state: %d", iCurrentState);
       
   915         return;
       
   916         }
       
   917     
       
   918     delete iDataBuffer;
       
   919     iDataBuffer = NULL;
       
   920     
       
   921     if ( error == KErrNone ) // Update Change Finder
       
   922         {
       
   923         TMsvId service;
       
   924         TMsvEntry msgEntry;
       
   925         
       
   926         // Inform ChangeFinder of added item
       
   927         TSnapshotItem snapshotItem( iCurrentId, iParentId, iUnread );
       
   928         error = iMsvSession->GetEntry( iCurrentId, service, msgEntry );
       
   929         
       
   930         if ( error == KErrNone )
       
   931             {
       
   932             snapshotItem.SetLastChangedDate( msgEntry.iDate );
       
   933             if ( iCurrentState == EFolderCreating || iCurrentState == EFolderUpdating )
       
   934                 {
       
   935                 snapshotItem.SetFolderNameL( msgEntry.iDetails );
       
   936                 }
       
   937             
       
   938             if ( iCurrentState == EFolderCreating || iCurrentState == EMmsItemCreating )
       
   939                 {
       
   940                 iChangeFinder->ItemAddedL( snapshotItem );
       
   941                 }
       
   942             else
       
   943                 {
       
   944                 iChangeFinder->ItemUpdatedL( snapshotItem );
       
   945                 }
       
   946             }
       
   947         else
       
   948             {
       
   949             LOGGER_WRITE_1( "CMsvSession::GetEntry failed with %d", error );
       
   950             }
       
   951         }
       
   952     
       
   953     // Send message if parent folder is Outbox
       
   954     if ( iParentId == KMsvGlobalOutBoxIndexEntryId &&
       
   955         iCurrentState == EMmsItemCreating &&
       
   956         error == KErrNone )
       
   957         {
       
   958         LOGGER_WRITE("Sending message...");
       
   959         iCodecClient->SendMML( iCurrentId, iMsvWait->iStatus );
       
   960         iMsvWait->Start();
       
   961         error = iMsvWait->iStatus.Int();
       
   962         }
       
   963     
       
   964     LOGGER_WRITE_1("error: %d", error);
       
   965     // We'll be waiting for next event, signal we're done
       
   966     iCurrentState = EMmsOpenAndWaiting;
       
   967     User::RequestComplete( iCallerStatus, error );
       
   968     
       
   969     LOGGER_LEAVEFN("CMmsDataStore::DoCommitItemL");
       
   970     }
       
   971 
       
   972 // -----------------------------------------------------------------------------
       
   973 // CMmsDataStore::DoCloseItem
       
   974 // Closes open item in the data store
       
   975 // -----------------------------------------------------------------------------
       
   976 void CMmsDataStore::DoCloseItem()
       
   977     {
       
   978     LOGGER_ENTERFN("CMmsDataStore::DoCloseItem");
       
   979     SAFEDELETE(iDataBuffer);
       
   980     if ( iCurrentState == EFolderOpen )
       
   981         {
       
   982         iCurrentState = EMmsOpenAndWaiting;
       
   983         }
       
   984     else if ( iCurrentState == EMmsItemOpen )
       
   985         {
       
   986         iCodecClient->ReleaseData();
       
   987         iCurrentState = EMmsOpenAndWaiting; 
       
   988         }
       
   989     else if ( iCurrentState == EMmsItemOpenFieldUpdate )
       
   990         {
       
   991         iCurrentState = EMmsOpenAndWaiting;
       
   992         }
       
   993     else 
       
   994         {
       
   995         LOGGER_WRITE_1("Invalid state %d.", iCurrentState);
       
   996         }
       
   997     
       
   998     LOGGER_LEAVEFN("CMmsDataStore::DoCloseItem");
       
   999     }
       
  1000 
       
  1001 // -----------------------------------------------------------------------------
       
  1002 // CMmsDataStore::DoMoveItemL
       
  1003 // Moves item from one folder to another in the message store
       
  1004 // -----------------------------------------------------------------------------
       
  1005 void CMmsDataStore::DoMoveItemL( TSmlDbItemUid aUid,
       
  1006     TSmlDbItemUid aNewParent, TRequestStatus& aStatus )
       
  1007     {
       
  1008     LOGGER_ENTERFN("CMmsDataStore::DoMoveItemL");
       
  1009     
       
  1010     LOGGER_WRITE_1("Moving item %d.", aUid);
       
  1011     
       
  1012     // Store some variables for further use
       
  1013     iCallerStatus = &aStatus;
       
  1014     *iCallerStatus = KRequestPending;
       
  1015 
       
  1016     // Check that we're in proper state
       
  1017     if ( iCurrentState != EMmsOpenAndWaiting ) 
       
  1018         {
       
  1019         LOGGER_WRITE_1("CMmsDataStore::DoMoveItemL, invalid state %d.", iCurrentState);
       
  1020         }
       
  1021 
       
  1022     // Ensure that we have this item in the message store   
       
  1023     if ( !MmsItemExists( aUid ) )
       
  1024         {
       
  1025         User::RequestComplete( iCallerStatus, KErrNotSupported ); 
       
  1026         LOGGER_WRITE("MMS item not found");
       
  1027         return;
       
  1028         }
       
  1029     
       
  1030     iCodecClient->MoveMML( aUid, aNewParent, iMsvWait->iStatus );
       
  1031     iMsvWait->Start();  
       
  1032     
       
  1033     // Inform ChangeFinder of the moved item
       
  1034     TMsvId service;
       
  1035     TMsvEntry msgEntry;
       
  1036     User::LeaveIfError( iMsvSession->GetEntry( aUid, service, msgEntry ) );
       
  1037     TBool unread = msgEntry.Unread();
       
  1038     TSnapshotItem snapshotItem( aUid, aNewParent, unread );
       
  1039     iChangeFinder->ItemMovedL( snapshotItem );
       
  1040 
       
  1041     // Signal we're done
       
  1042     User::RequestComplete( iCallerStatus, KErrNone );
       
  1043     
       
  1044     LOGGER_LEAVEFN("CMmsDataStore::DoMoveItemL");
       
  1045     }
       
  1046 
       
  1047 // -----------------------------------------------------------------------------
       
  1048 // CMmsDataStore::DoDeleteItemL
       
  1049 // Removes item from the message store
       
  1050 // -----------------------------------------------------------------------------
       
  1051 void CMmsDataStore::DoDeleteItemL( TSmlDbItemUid aUid, TRequestStatus& aStatus  )
       
  1052     {
       
  1053     LOGGER_ENTERFN("CMmsDataStore::DoDeleteItemL");
       
  1054     LOGGER_WRITE_1("Deleting item %d.", aUid);
       
  1055     
       
  1056     // Store some variables for further use
       
  1057     iCallerStatus = &aStatus;
       
  1058     *iCallerStatus = KRequestPending;
       
  1059     
       
  1060     TInt error(KErrNone);
       
  1061     
       
  1062     // Check that we're in proper state
       
  1063     if ( iCurrentState != EMmsOpenAndWaiting ) 
       
  1064         {
       
  1065         LOGGER_WRITE_1("CMmsDataStore::DoDeleteItemL, invalid state %d.", iCurrentState);        
       
  1066         }
       
  1067         
       
  1068     // Check if this is a user folder
       
  1069     if ( iMsvApi->FindUserFolderL( aUid ) )
       
  1070         {
       
  1071         LOGGER_WRITE("Folder");
       
  1072         error = DeleteAllMessagesInFolderL( aUid );
       
  1073         if ( error != KErrNone )
       
  1074             {
       
  1075             User::RequestComplete( iCallerStatus, error );    
       
  1076             LOGGER_WRITE_1("Deleting MMS messages in folder failed with %d", error); 
       
  1077             return;
       
  1078             }
       
  1079         error = iMsvApi->DeleteUserFolderL(aUid);  
       
  1080         if ( error != KErrNone )
       
  1081             {
       
  1082             // Note: folder is not deleted if contains other message items (like MMS)
       
  1083             // In this case DeleteUserFolderL returns KErrInUse.    
       
  1084             LOGGER_WRITE_1("Deleting folder failed with %d", error); 
       
  1085             }       
       
  1086         }
       
  1087     else if ( MmsItemExists( aUid ) )
       
  1088         {
       
  1089         // Tell CodecClient to delete this message
       
  1090         error = iCodecClient->DeleteMM( aUid );
       
  1091         if ( error != KErrNone )
       
  1092             {
       
  1093             User::RequestComplete( iCallerStatus, error );    
       
  1094             LOGGER_WRITE_1("CMmsCodecClient::DeleteMM failed with %d", error);   
       
  1095             return;
       
  1096             }
       
  1097         // Inform ChangeFinder of the removed item
       
  1098         iChangeFinder->ItemDeletedL( aUid );
       
  1099         }
       
  1100     else
       
  1101         {
       
  1102         User::RequestComplete( iCallerStatus, KErrNotFound ); 
       
  1103         LOGGER_WRITE_1("Item %d is not folder or MMS message", aUid);
       
  1104         return;
       
  1105         }
       
  1106     
       
  1107     LOGGER_WRITE_1("complete error: %d", error);
       
  1108     // Signal we're done
       
  1109     User::RequestComplete( iCallerStatus, error );
       
  1110     LOGGER_LEAVEFN("CMmsDataStore::DoDeleteItemL");
       
  1111     }
       
  1112 
       
  1113 // -----------------------------------------------------------------------------
       
  1114 // CMmsDataStore::DoSoftDeleteItemL
       
  1115 // Soft delete isn't supported.
       
  1116 // -----------------------------------------------------------------------------
       
  1117 void CMmsDataStore::DoSoftDeleteItemL( TSmlDbItemUid /*aUid*/, TRequestStatus& aStatus )
       
  1118     {
       
  1119     LOGGER_ENTERFN("CMmsDataStore::DoSoftDeleteItemL"); 
       
  1120     
       
  1121     // Store some variables for further use
       
  1122     iCallerStatus = &aStatus;
       
  1123     *iCallerStatus = KRequestPending;
       
  1124 
       
  1125     // Signal we're done
       
  1126     User::RequestComplete( iCallerStatus, KErrNotSupported );
       
  1127     
       
  1128     LOGGER_LEAVEFN("CMmsDataStore::DoSoftDeleteItemL");
       
  1129     }
       
  1130 
       
  1131 // -----------------------------------------------------------------------------
       
  1132 // CMmsDataStore::DoDeleteAllItemsL
       
  1133 // Deletes all items in the standard folders of message store
       
  1134 // -----------------------------------------------------------------------------
       
  1135 void CMmsDataStore::DoDeleteAllItemsL( TRequestStatus& aStatus )
       
  1136     {
       
  1137     LOGGER_ENTERFN("CMmsDataStore::DoDeleteAllItemsL");
       
  1138     
       
  1139     // Store some variables for further use 
       
  1140     iCallerStatus = &aStatus;
       
  1141     *iCallerStatus = KRequestPending;
       
  1142     
       
  1143    // Check that we're in proper state
       
  1144     if ( iCurrentState != EMmsOpenAndWaiting ) 
       
  1145         {
       
  1146         LOGGER_WRITE_1("CMmsDataStore::DoDeleteAllItemsL, invalid state %d.", iCurrentState);
       
  1147         }
       
  1148         
       
  1149     TInt error(KErrNone);
       
  1150     TInt result(KErrNone);      
       
  1151     
       
  1152     // Delete all messages in the standard folders (except outbox)
       
  1153     error = DeleteAllMessagesInFolderL( KMsvGlobalInBoxIndexEntryId );
       
  1154     if ( error != KErrNone )
       
  1155         {
       
  1156         result = error;
       
  1157         }
       
  1158        
       
  1159     error = DeleteAllMessagesInFolderL( KMsvDraftEntryId );
       
  1160     if ( error != KErrNone )
       
  1161         {
       
  1162         result = error;
       
  1163         }   
       
  1164     
       
  1165     error = DeleteAllMessagesInFolderL( KMsvSentEntryId );
       
  1166     if ( error != KErrNone )
       
  1167         {
       
  1168         result = error;
       
  1169         }
       
  1170         
       
  1171     error = CleanUserFoldersL();
       
  1172     if ( error != KErrNone )
       
  1173         {
       
  1174         result = error;
       
  1175         }
       
  1176             
       
  1177     iChangeFinder->ResetL();
       
  1178     
       
  1179     User::RequestComplete( iCallerStatus, result );
       
  1180     
       
  1181     LOGGER_LEAVEFN("CMmsDataStore::DoDeleteAllItemsL");
       
  1182     }
       
  1183 
       
  1184 // -----------------------------------------------------------------------------
       
  1185 // CMmsDataStore::DeleteAllMessagesInFolderL
       
  1186 // Deletes all items in the specified folder in message store
       
  1187 // -----------------------------------------------------------------------------
       
  1188 TInt CMmsDataStore::DeleteAllMessagesInFolderL( TMsvId aId )
       
  1189     {
       
  1190     LOGGER_ENTERFN("CMmsDataStore::DeleteAllMessagesInFolderL");
       
  1191     LOGGER_WRITE_1("Folder: %d", aId);
       
  1192     
       
  1193     TInt error(KErrNone);
       
  1194     
       
  1195     // Get the root folder
       
  1196     CMsvEntry* msvEntry = iMsvSession->GetEntryL(aId);
       
  1197     CleanupStack::PushL(msvEntry);
       
  1198     
       
  1199     // Find all of it's childs
       
  1200     CMsvEntrySelection* messages = msvEntry->ChildrenWithTypeL(KUidMsvMessageEntry);
       
  1201     CleanupStack::PopAndDestroy(msvEntry);
       
  1202     CleanupStack::PushL(messages);
       
  1203         
       
  1204     TMsvId service;
       
  1205     TMsvEntry msg;
       
  1206     TMsvId id;
       
  1207     
       
  1208     // We are only interested of the MM content
       
  1209     for ( TInt index=0; index < messages->Count(); index++ )
       
  1210         {
       
  1211         id = messages->At( index );
       
  1212         LOGGER_WRITE_1("Message item %d:", id);
       
  1213         
       
  1214         error = iMsvSession->GetEntry( id, service, msg );
       
  1215         if ( error != KErrNone )
       
  1216             {
       
  1217             LOGGER_WRITE_1("GetEntry failed with %d", error);
       
  1218             break;
       
  1219             }
       
  1220         
       
  1221         if ( msg.iMtm == KUidMsgTypeMultimedia )
       
  1222             {
       
  1223             error = iCodecClient->DeleteMM( id );
       
  1224             if ( error != KErrNone )
       
  1225                 {
       
  1226                 LOGGER_WRITE_1("DeleteMM failed with %d", error);
       
  1227                 break;
       
  1228                 }
       
  1229             // Update Change Finder
       
  1230             iChangeFinder->ItemDeletedL( id );
       
  1231             LOGGER_WRITE("MMS message deleted");    
       
  1232             }
       
  1233         }
       
  1234     CleanupStack::PopAndDestroy(messages); 
       
  1235     
       
  1236     LOGGER_LEAVEFN("CMmsDataStore::DeleteAllMessagesInFolderL");
       
  1237 
       
  1238     return error;
       
  1239     }
       
  1240 
       
  1241 
       
  1242 // -----------------------------------------------------------------------------
       
  1243 // CMmsDataStore::DoHasSyncHistory
       
  1244 // This method returns ETrue if Data Store has history information. 
       
  1245 // Slow-sync will be used if Data Store does not have history information.
       
  1246 // -----------------------------------------------------------------------------
       
  1247 TBool CMmsDataStore::DoHasSyncHistory() const
       
  1248     {
       
  1249     LOGGER_ENTERFN("CMmsDataStore::DoHasSyncHistory");
       
  1250     LOGGER_LEAVEFN("CMmsDataStore::DoHasSyncHistory");      
       
  1251         
       
  1252     // iHasHistory is initialized in DoOpenL method
       
  1253     return iHasHistory;
       
  1254     }
       
  1255 
       
  1256 // -----------------------------------------------------------------------------
       
  1257 // CMmsDataStore::DoAddedItems
       
  1258 // This method returns UIDs of added items. Those items are added after previous
       
  1259 // synchronization with current synchronization relationship. 
       
  1260 // -----------------------------------------------------------------------------
       
  1261 const MSmlDataItemUidSet& CMmsDataStore::DoAddedItems() const
       
  1262     {
       
  1263     LOGGER_ENTERFN("CMmsDataStore::DoAddedItems");  
       
  1264     
       
  1265     // Ensure that we're in a proper state
       
  1266     if ( iCurrentState != EMmsOpenAndWaiting )
       
  1267         {
       
  1268         LOGGER_WRITE_1("CMmsDataStore::DoAddedItems, invalid state %d.", iCurrentState);
       
  1269         }
       
  1270     
       
  1271     TInt error(KErrNone);
       
  1272 
       
  1273     // Clear new-items array
       
  1274     iNewItems->Reset();
       
  1275 
       
  1276     // Set current snapshot, this will be compared against the old one      
       
  1277     // Search for new items
       
  1278     TRAP( error, iChangeFinder->FindNewItemsL(*iNewItems) )
       
  1279     if ( error != KErrNone )
       
  1280         {
       
  1281         LOGGER_WRITE_1("CMmsDataStore::DoAddedItems, iChangeFinder->FindNewItemsL leaved with %d.", error);
       
  1282         }
       
  1283     
       
  1284     LOGGER_WRITE_1("New item count: %d.", iNewItems->ItemCount());
       
  1285     LOGGER_LEAVEFN("CMmsDataStore::DoAddedItems");      
       
  1286     
       
  1287     return *iNewItems;
       
  1288     }
       
  1289 
       
  1290 // -----------------------------------------------------------------------------
       
  1291 // CMmsDataStore::DoDeletedItems
       
  1292 //
       
  1293 // -----------------------------------------------------------------------------
       
  1294 const MSmlDataItemUidSet& CMmsDataStore::DoDeletedItems() const
       
  1295     {
       
  1296     LOGGER_ENTERFN("CMmsDataStore::DoDeletedItemsL");   
       
  1297     
       
  1298     // Ensure that we're in a proper state
       
  1299     if ( iCurrentState != EMmsOpenAndWaiting )
       
  1300         {
       
  1301         LOGGER_WRITE_1("CMmsDataStore::DoDeletedItems, invalid state %d.", iCurrentState);
       
  1302         }
       
  1303     
       
  1304     TInt error(KErrNone);
       
  1305     
       
  1306     // Clear deleted-items array
       
  1307     iDeletedItems->Reset();
       
  1308     
       
  1309     // Search for deleted items
       
  1310     TRAP( error, iChangeFinder->FindDeletedItemsL( *iDeletedItems ) );
       
  1311     if ( error != KErrNone )
       
  1312         {
       
  1313         LOGGER_WRITE_1("CMmsDataStore::DoDeletedItems, iChangeFinder->FindDeletedItemsL leaved with %d.", error);
       
  1314         }           
       
  1315     
       
  1316     LOGGER_WRITE_1("Deleted item count: %d.", iDeletedItems->ItemCount());
       
  1317     LOGGER_LEAVEFN("CMmsDataStore::DoDeletedItemsL");
       
  1318     return *iDeletedItems;
       
  1319     }
       
  1320 
       
  1321 // -----------------------------------------------------------------------------
       
  1322 // CMmsDataStore::DoSoftDeletedItems
       
  1323 // Not directly supported, equals to "hard" delete
       
  1324 // -----------------------------------------------------------------------------
       
  1325 const MSmlDataItemUidSet& CMmsDataStore::DoSoftDeletedItems() const
       
  1326     {
       
  1327     LOGGER_ENTERFN("CMmsDataStore::DoSoftDeletedItems");
       
  1328     LOGGER_LEAVEFN("CMmsDataStore::DoSoftDeletedItems");
       
  1329 
       
  1330     iSoftDeletedItems->Reset();
       
  1331     return *iSoftDeletedItems;
       
  1332     }
       
  1333 
       
  1334 // -----------------------------------------------------------------------------
       
  1335 // CMmsDataStore::DoModifiedItems
       
  1336 // Finds all modified items in the data store
       
  1337 // -----------------------------------------------------------------------------
       
  1338 const MSmlDataItemUidSet& CMmsDataStore::DoModifiedItems() const
       
  1339     {
       
  1340     LOGGER_ENTERFN("CMmsDataStore::DoModifiedItems");   
       
  1341     
       
  1342     // Ensure that we're in a proper state
       
  1343     if ( iCurrentState != EMmsOpenAndWaiting )
       
  1344         {
       
  1345         LOGGER_WRITE_1("CMmsDataStore::DoModifiedItems, invalid state %d.", iCurrentState);
       
  1346         }
       
  1347     
       
  1348     TInt error(KErrNone);
       
  1349     
       
  1350     // Clear updated-items array
       
  1351     iUpdatedItems->Reset();
       
  1352     
       
  1353     // Search for updated items
       
  1354     TRAP( error, iChangeFinder->FindChangedItemsL( *iUpdatedItems ) )
       
  1355     if ( error != KErrNone )
       
  1356         {
       
  1357         LOGGER_WRITE_1("CMmsDataStore::DoModifiedItems, iChangeFinder->FindChangedItemsL leaved with %d.", error);
       
  1358         }
       
  1359     
       
  1360     LOGGER_WRITE_1("Modified item count: %d.", iUpdatedItems->ItemCount());
       
  1361     LOGGER_LEAVEFN("CMmsDataStore::DoModifiedItems");       
       
  1362     return *iUpdatedItems;
       
  1363     }
       
  1364 
       
  1365 // -----------------------------------------------------------------------------
       
  1366 // CMmsDataStore::DoMovedItems
       
  1367 // Finds all moved items in the data store
       
  1368 // -----------------------------------------------------------------------------
       
  1369 const MSmlDataItemUidSet& CMmsDataStore::DoMovedItems() const
       
  1370     {
       
  1371     LOGGER_ENTERFN("CMmsDataStore::DoMovedItems");  
       
  1372     
       
  1373     // Ensure that we're in a proper state
       
  1374     if ( iCurrentState != EMmsOpenAndWaiting )
       
  1375         {
       
  1376         LOGGER_WRITE_1("CMmsDataStore::DoMovedItems, invalid state %d.", iCurrentState);
       
  1377         }
       
  1378     
       
  1379     TInt error(KErrNone);
       
  1380     
       
  1381     // Clear moved-items array
       
  1382     iMovedItems->Reset();
       
  1383     
       
  1384     // Search for moved items
       
  1385     TRAP( error, iChangeFinder->FindMovedItemsL( *iMovedItems ) );
       
  1386     if ( error != KErrNone )
       
  1387         {
       
  1388         LOGGER_WRITE_1("CMmsDataStore::DoMovedItems, iChangeFinder->FindMovedItemsL leaved with %d.", error);
       
  1389         }
       
  1390     
       
  1391     LOGGER_WRITE_1("Moved item count: %d.", iMovedItems->ItemCount());
       
  1392     LOGGER_LEAVEFN("CMmsDataStore::DoMovedItems");
       
  1393     return *iMovedItems;    
       
  1394     }
       
  1395 
       
  1396 // -----------------------------------------------------------------------------
       
  1397 // CMmsDataStore::DoResetChangeInfoL
       
  1398 // Resets change history in the data store. All content is considered
       
  1399 // new in the data store point of view.
       
  1400 // -----------------------------------------------------------------------------
       
  1401 void CMmsDataStore::DoResetChangeInfoL( TRequestStatus& aStatus )
       
  1402     {
       
  1403     LOGGER_ENTERFN("CMmsDataStore::DoResetChangeInfoL");    
       
  1404     
       
  1405     iCallerStatus = &aStatus;
       
  1406     *iCallerStatus = KRequestPending;
       
  1407     
       
  1408     // Check that we're in proper state
       
  1409     if ( iCurrentState != EMmsOpenAndWaiting ) 
       
  1410         {
       
  1411         LOGGER_WRITE_1("CMmsDataStore::DoResetChangeInfoL, invalid state %d.", iCurrentState);
       
  1412         }   
       
  1413             
       
  1414     // Reset change info in ChangeFinder
       
  1415     iChangeFinder->ResetL();
       
  1416     iHasHistory = EFalse;
       
  1417     
       
  1418     // Signal we're done
       
  1419     User::RequestComplete( iCallerStatus, KErrNone ); 
       
  1420     
       
  1421     LOGGER_LEAVEFN("CMmsDataStore::DoResetChangeInfoL");
       
  1422     }
       
  1423         
       
  1424 // -----------------------------------------------------------------------------
       
  1425 // CMmsDataStore::DoCommitChangeInfoL
       
  1426 // Commits change info. These items are no longer reported, when change
       
  1427 // information is being queried.
       
  1428 // -----------------------------------------------------------------------------
       
  1429 void CMmsDataStore::DoCommitChangeInfoL( TRequestStatus& aStatus, const MSmlDataItemUidSet& aItems )
       
  1430     {
       
  1431     LOGGER_ENTERFN("CMmsDataStore::DoCommitChangeInfoL");
       
  1432     
       
  1433     iCallerStatus = &aStatus;
       
  1434     *iCallerStatus = KRequestPending;
       
  1435     
       
  1436     // Ensure that we're in a proper state
       
  1437     if ( iCurrentState != EMmsOpenAndWaiting ) 
       
  1438         {
       
  1439         LOGGER_WRITE_1("CMmsDataStore::DoCommitChangeInfoL, invalid state %d.", iCurrentState);
       
  1440         }
       
  1441 
       
  1442     // Notify ChangeFinder
       
  1443     iChangeFinder->CommitChangesL(aItems);
       
  1444     iHasHistory = ETrue;
       
  1445         
       
  1446     // Signal we're done
       
  1447     User::RequestComplete(iCallerStatus, KErrNone);
       
  1448         
       
  1449     LOGGER_LEAVEFN("CMmsDataStore::DoCommitChangeInfoL");
       
  1450     }
       
  1451         
       
  1452     
       
  1453 // -----------------------------------------------------------------------------
       
  1454 // CMmsDataStore::DoCommitChangeInfoL
       
  1455 // Commits change info. There is no more nothing to report when change
       
  1456 // information is being queried. 
       
  1457 // -----------------------------------------------------------------------------
       
  1458 void CMmsDataStore::DoCommitChangeInfoL(TRequestStatus& aStatus)
       
  1459     {
       
  1460     LOGGER_ENTERFN("CMmsDataStore::DoCommitChangeInfoL");
       
  1461     
       
  1462     iCallerStatus = &aStatus;
       
  1463     *iCallerStatus = KRequestPending;
       
  1464     
       
  1465     // Ensure that we're in a proper state
       
  1466     if ( iCurrentState != EMmsOpenAndWaiting ) 
       
  1467         {
       
  1468         LOGGER_WRITE_1("CMmsDataStore::DoCommitChangeInfoL, invalid state %d.", iCurrentState);
       
  1469         }
       
  1470     
       
  1471     // Notify ChangeFinder
       
  1472     iChangeFinder->CommitChangesL();
       
  1473     iHasHistory = ETrue;
       
  1474         
       
  1475     // Signal we're done
       
  1476     User::RequestComplete( iCallerStatus, KErrNone );
       
  1477     
       
  1478     LOGGER_LEAVEFN("CMmsDataStore::DoCommitChangeInfoL");
       
  1479     }
       
  1480         
       
  1481 
       
  1482 // -----------------------------------------------------------------------------
       
  1483 // CMmsDataStore::RegisterSnapshotL
       
  1484 // Sets Changefinder to compare against current message store content
       
  1485 // -----------------------------------------------------------------------------
       
  1486 void CMmsDataStore::RegisterSnapshotL() const
       
  1487     {
       
  1488     CSnapshotArray* snapshot = new (ELeave) CSnapshotArray( KSnapshotGranularity );
       
  1489     CleanupStack::PushL(snapshot);
       
  1490     
       
  1491     // Use only standard folders (except outbox)
       
  1492     RegisterFolderL(snapshot, KMsvGlobalInBoxIndexEntryId);
       
  1493     RegisterFolderL(snapshot, KMsvDraftEntryId);
       
  1494     RegisterFolderL(snapshot, KMsvSentEntryId);
       
  1495     RegisterFolderL(snapshot, KMsvGlobalOutBoxIndexEntryId);    
       
  1496     RegisterUserFoldersL(snapshot);
       
  1497     
       
  1498     // Set new snapshot to compare against
       
  1499     iChangeFinder->SetNewSnapshot(snapshot);
       
  1500 
       
  1501     // Changefinder takes ownership of the snapshot
       
  1502     CleanupStack::Pop(snapshot);
       
  1503     }
       
  1504 
       
  1505 // -----------------------------------------------------------------------------
       
  1506 // CMmsDataStore::RegisterFolderL
       
  1507 // Adds a single folder into the snapshot array
       
  1508 // -----------------------------------------------------------------------------
       
  1509 TInt CMmsDataStore::RegisterFolderL(CSnapshotArray* aSnapshot, const TMsvId& aId) const
       
  1510     {
       
  1511     // Get the root folder
       
  1512     CMsvEntry* msvEntry = iMsvSession->GetEntryL(aId);
       
  1513     CleanupStack::PushL( msvEntry );
       
  1514     
       
  1515     // Find all of it's childs
       
  1516     CMsvEntrySelection* messages = msvEntry->ChildrenWithTypeL( KUidMsvMessageEntry );
       
  1517     CleanupStack::PopAndDestroy( msvEntry );
       
  1518     CleanupStack::PushL( messages );
       
  1519     
       
  1520     TMsvId id;
       
  1521     TMsvEntry msg;
       
  1522     
       
  1523     // We are only interested of the MM content
       
  1524     for ( TInt index=0; index<messages->Count(); index++ )
       
  1525         {
       
  1526         TInt result = iMsvSession->GetEntry( messages->At( index ), id, msg );
       
  1527         User::LeaveIfError( result );
       
  1528         
       
  1529         // We're only interested about the multimedia content
       
  1530         if ( msg.iMtm == KUidMsgTypeMultimedia )
       
  1531             {
       
  1532             // Create snapshot item
       
  1533             TKeyArrayFix key(iKey);
       
  1534             TSnapshotItem item( (TUint) msg.Id() );
       
  1535             
       
  1536             item.SetLastChangedDate( msg.iDate );
       
  1537             item.SetParentId( msg.Parent() );
       
  1538             item.SetUnread( msg.Unread() ? ETrue : EFalse );
       
  1539             
       
  1540             // Add to snapshot
       
  1541             aSnapshot->InsertIsqL( item, key );
       
  1542             }
       
  1543         }
       
  1544 
       
  1545     CleanupStack::PopAndDestroy( messages );
       
  1546     return KErrNone;
       
  1547     }
       
  1548     
       
  1549 // -----------------------------------------------------------------------------
       
  1550 // CMmsDataStore::MmsItemExists
       
  1551 // Returns ETrue if MMS item exists in the message store, otherwise EFalse
       
  1552 // -----------------------------------------------------------------------------    
       
  1553 TBool CMmsDataStore::MmsItemExists( TMsvId aUid )
       
  1554     {
       
  1555     CMsvEntry* entry(NULL);
       
  1556     
       
  1557     // Try to open this item
       
  1558     TRAPD( error, entry = iMsvSession->GetEntryL( aUid ) );
       
  1559     if ( error != KErrNone )
       
  1560         {
       
  1561         return EFalse;
       
  1562         }
       
  1563         
       
  1564     TMsvEntry tEntry = entry->Entry();
       
  1565     TBool result(EFalse);
       
  1566     
       
  1567     if ( tEntry.iType == KUidMsvMessageEntry && tEntry.iMtm == KUidMsgTypeMultimedia )
       
  1568         {
       
  1569         result = ETrue;
       
  1570         }
       
  1571     
       
  1572     delete entry;
       
  1573     
       
  1574     return result;
       
  1575     }
       
  1576     
       
  1577 // -----------------------------------------------------------------------------
       
  1578 // CMmsDataStore::ResolveStatusBits
       
  1579 // Creates status bit field according to TMsvEntry parameter
       
  1580 // -----------------------------------------------------------------------------
       
  1581 TUint8 CMmsDataStore::ResolveStatusBits(TBool aUnread)
       
  1582     {
       
  1583     // Reset the status byte, then find the correct flags
       
  1584     TUint8 data(0);
       
  1585     
       
  1586     // Set status according to the Read/Unread information iCurrentEntry   
       
  1587     if ( aUnread )
       
  1588         {
       
  1589         // Status unset
       
  1590         data &= (~KMMS_Flag_Read);
       
  1591         }
       
  1592     else
       
  1593         { 
       
  1594         // Status set
       
  1595         data |= KMMS_Flag_Read;
       
  1596         }
       
  1597     
       
  1598     return data;
       
  1599     }   
       
  1600     
       
  1601 // -----------------------------------------------------------------------------
       
  1602 // CMmsDataStore::ReadDataRecursively
       
  1603 // Write specified amount of data to the temporary buffer
       
  1604 // -----------------------------------------------------------------------------    
       
  1605 TInt CMmsDataStore::ReadDataRecursively( TDes8& aBuffer )
       
  1606     {
       
  1607     LOGGER_ENTERFN("CMmsDataStore::ReadDataRecursively");
       
  1608     
       
  1609     TInt error(KErrNone);
       
  1610     
       
  1611     TInt freeBuffer = aBuffer.MaxLength() - aBuffer.Length();
       
  1612     
       
  1613     if ( freeBuffer == 0 )
       
  1614         {
       
  1615         LOGGER_WRITE("Destination buffer filled.");
       
  1616         return KErrNone;
       
  1617         }
       
  1618     
       
  1619     if ( iReadPosition == 0 )
       
  1620         {
       
  1621         if ( iLastDataChunk )
       
  1622             {
       
  1623             LOGGER_WRITE("All MMS data read");
       
  1624             iReadAllData = ETrue;
       
  1625             return KErrNone;
       
  1626             }
       
  1627         else
       
  1628             {
       
  1629             error = iCodecClient->GetNextDataPart( iReadDataChunk, iLastDataChunk );
       
  1630             if ( error != KErrNone )
       
  1631                 {
       
  1632                 LOGGER_WRITE_1("iCodecClient->GetNextDataPart failed with %d", error);
       
  1633                 return error;
       
  1634                 }
       
  1635             else
       
  1636                 {
       
  1637                 LOGGER_WRITE_1("iCodecClient->GetNextDataPart succeeded, length %d", iReadDataChunk.Length());
       
  1638                 }   
       
  1639             }   
       
  1640         }
       
  1641         
       
  1642     TInt left = iReadDataChunk.Length() - iReadPosition;    
       
  1643     
       
  1644     if ( freeBuffer < left )
       
  1645         {
       
  1646         TPtrC8 data = iReadDataChunk.Mid(iReadPosition, freeBuffer);
       
  1647         aBuffer.Append(data);
       
  1648         iReadPosition += freeBuffer;
       
  1649         return KErrNone; 
       
  1650         }
       
  1651     else
       
  1652         {
       
  1653         if ( left > 0 )
       
  1654             {
       
  1655             TPtrC8 data = iReadDataChunk.Mid(iReadPosition, left);
       
  1656             aBuffer.Append(data);
       
  1657             }
       
  1658         error = iCodecClient->ReleaseData();
       
  1659         if ( error != KErrNone )
       
  1660             {
       
  1661             return error;
       
  1662             }
       
  1663         iReadPosition = 0;
       
  1664         return ReadDataRecursively( aBuffer );
       
  1665         }           
       
  1666     }   
       
  1667     
       
  1668 // -----------------------------------------------------------------------------
       
  1669 // CMmsDataStore::UpdateMmsStatusL
       
  1670 // Updates MMS message status
       
  1671 // -----------------------------------------------------------------------------
       
  1672 void CMmsDataStore::UpdateMmsStatusL( TMsvId aId, TBool aUnread )
       
  1673     {
       
  1674     CMsvEntry* msvEntry = iMsvSession->GetEntryL( aId );
       
  1675     const TMsvEntry& oldEntry = msvEntry->Entry();
       
  1676     
       
  1677     TMsvEntry newEntry( oldEntry );
       
  1678     newEntry.SetUnread( aUnread );
       
  1679     
       
  1680     CleanupStack::PushL( msvEntry );
       
  1681     msvEntry->ChangeL( newEntry );
       
  1682     CleanupStack::PopAndDestroy( msvEntry );   
       
  1683     }
       
  1684     
       
  1685 // -----------------------------------------------------------------------------
       
  1686 // CMmsDataStore::RegisterUserFoldersL
       
  1687 // Adds user folder messages into the snapshot array
       
  1688 // -----------------------------------------------------------------------------
       
  1689 TInt CMmsDataStore::RegisterUserFoldersL( CSnapshotArray* aSnapshot ) const
       
  1690     {
       
  1691     LOGGER_ENTERFN("CMmsDataStore::RegisterUserFoldersL");     
       
  1692     
       
  1693     // Get the folder   
       
  1694     CMsvEntry* msvEntry = iMsvSession->GetEntryL( KMsvMyFoldersEntryIdValue );
       
  1695     CleanupStack::PushL(msvEntry);
       
  1696     
       
  1697     // Find all of it's childs
       
  1698     CMsvEntrySelection* folders = msvEntry->ChildrenWithTypeL( KUidMsvFolderEntry );
       
  1699     CleanupStack::PopAndDestroy( msvEntry ); 
       
  1700     CleanupStack::PushL( folders );
       
  1701 
       
  1702     for ( TInt index = 0; index < folders->Count(); index++ )
       
  1703         {
       
  1704         TMsvId folderId = folders->At(index);
       
  1705         
       
  1706         if ( folderId != KMsvMyFoldersTemplatesFolderId )
       
  1707             {
       
  1708             TMsvId service;
       
  1709             TMsvEntry folderEntry;
       
  1710             TInt result = iMsvSession->GetEntry( folderId, service, folderEntry );
       
  1711             User::LeaveIfError( result );
       
  1712             
       
  1713             TKeyArrayFix key(iKey);
       
  1714             TBool unread(EFalse);
       
  1715             TSnapshotItem item( (TUint) folderId, folderEntry.Parent(), unread );
       
  1716             item.SetLastChangedDate( folderEntry.iDate );
       
  1717             item.SetFolderNameL( folderEntry.iDetails );
       
  1718             
       
  1719             aSnapshot->InsertIsqL( item, key );
       
  1720             
       
  1721             RegisterFolderL( aSnapshot, folderId );
       
  1722             }
       
  1723         }
       
  1724     
       
  1725     CleanupStack::PopAndDestroy( folders );
       
  1726     
       
  1727     // Register also MMS messages directly under My Folders
       
  1728     RegisterFolderL( aSnapshot, KMsvMyFoldersEntryIdValue );
       
  1729     
       
  1730     LOGGER_LEAVEFN("CMmsDataStore::RegisterUserFoldersL");     
       
  1731     
       
  1732     return KErrNone;
       
  1733     }
       
  1734 
       
  1735 // -----------------------------------------------------------------------------
       
  1736 // CMmsDataStore::CleanUserFoldersL
       
  1737 // Cleans all user folders from MMS messages
       
  1738 // -----------------------------------------------------------------------------
       
  1739 TInt CMmsDataStore::CleanUserFoldersL() 
       
  1740     {
       
  1741     LOGGER_ENTERFN("CMmsDataStore::CleanUserFoldersL");      
       
  1742     
       
  1743     // Get the folder   
       
  1744     CMsvEntry* msvEntry = iMsvSession->GetEntryL( KMsvMyFoldersEntryIdValue );
       
  1745     CleanupStack::PushL(msvEntry);
       
  1746     
       
  1747     // Find all of it's childs
       
  1748     CMsvEntrySelection* folders = msvEntry->ChildrenWithTypeL( KUidMsvFolderEntry );
       
  1749     CleanupStack::PopAndDestroy( msvEntry ); 
       
  1750     CleanupStack::PushL( folders );
       
  1751     
       
  1752     TInt error(KErrNone);
       
  1753     TInt result(KErrNone);
       
  1754 
       
  1755     for ( TInt index = 0; index < folders->Count(); index++ )
       
  1756         {
       
  1757         TMsvId folderId = folders->At(index);
       
  1758         
       
  1759         if ( folderId != KMsvMyFoldersTemplatesFolderId )
       
  1760             {
       
  1761             error = DeleteAllMessagesInFolderL(folderId);
       
  1762             if ( error != KErrNone )
       
  1763                 {
       
  1764                 LOGGER_WRITE_1("Deleting messages in folder failed with %d", error); 
       
  1765                 result = error;
       
  1766                 }
       
  1767             error = iMsvApi->DeleteUserFolderL( folderId );
       
  1768             if ( error != KErrNone && error != KErrInUse )
       
  1769                 {
       
  1770                 // Note: folder is not deleted if contains other message items (like MMS)
       
  1771                 // In this case DeleteUserFolderL returns KErrInUse.
       
  1772                 LOGGER_WRITE_1("iMsvApi->DeleteUserFolderL failed with %d", error);
       
  1773                 result = error;
       
  1774                 }
       
  1775             }
       
  1776         }
       
  1777     
       
  1778     CleanupStack::PopAndDestroy( folders );
       
  1779     
       
  1780     // Delete all messages directly under My Folders
       
  1781     DeleteAllMessagesInFolderL( KMsvMyFoldersEntryIdValue );
       
  1782     
       
  1783     LOGGER_LEAVEFN("CSmsDataStore::CleanUserFoldersL");
       
  1784     
       
  1785     return result;       
       
  1786     }
       
  1787