emailservices/emailstore/message_store/server/src/ContainerStoreMRUAddressTable.cpp
changeset 0 8466d47a6819
child 51 d845db10c0d4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/emailstore/message_store/server/src/ContainerStoreMRUAddressTable.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,969 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Container store most recently used address table implementation.
+*
+*/
+
+
+
+// ========
+// INCLUDES
+// ========
+
+#include "ContainerStoreMRUAddressTable.h"
+#include "ContainerStoreDefs.h"
+#include "ContainerStoreUtils.h"
+#include "MessageStoreClientServer.h"
+#include "ContainerStoreEncryption.h"
+#include "ContainerStoreGeneralTable.h"
+#include "ContainerStoreAccountTable.h"
+
+// =========
+// CONSTANTS
+// =========
+
+_LIT( KSelectStar,     "SELECT *"         );
+_LIT( KFrom,            " FROM "          );
+_LIT( KWhere,          " WHERE "          );
+_LIT( KEquals,         " = "              );
+_LIT( KDelete,         "DELETE"           );
+
+// =======
+// CLASSES
+// =======
+// ======================================
+// CLASS: CMruAddress
+// ======================================
+// ======================
+// METHOD IMPLEMENTATIONS
+// ======================
+// ==========================================================================
+// FUNCTION: NewL
+// ==========================================================================
+CMruAddress* CMruAddress::NewL( TUint aMruNum, const TDesC& aEmailAddress, const TDesC& aDisplayName )
+    {
+    CMruAddress* self = new(ELeave) CMruAddress( aMruNum );
+    CleanupStack::PushL( self );
+    self->ConstructL( aEmailAddress, aDisplayName );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ==========================================================================
+// FUNCTION: CMruAddress
+// ==========================================================================
+CMruAddress::CMruAddress( TUint aMruNum )
+: iMruNum( aMruNum )
+    {
+    }
+     
+// ==========================================================================
+// FUNCTION: ConstructL
+// ==========================================================================
+void CMruAddress::ConstructL( const TDesC& aEmailAddress, const TDesC& aDisplayName )
+    {
+    iEmailAddress.Create( aEmailAddress );
+    iDisplayName.Create( aDisplayName );
+    }
+
+// ==========================================================================
+// FUNCTION: ~CMruAddress
+// ==========================================================================
+CMruAddress::~CMruAddress()
+    {
+    iDisplayName.Close();
+    iEmailAddress.Close();
+    }
+        
+// ==========================================================================
+// FUNCTION: SortByAddress
+// ==========================================================================
+TInt CMruAddress::SortByAddress(const CMruAddress& aFirst, const CMruAddress& aSecond)
+    {
+    TInt rc = aFirst.iEmailAddress.CompareF( aSecond.iEmailAddress );
+    if ( rc == 0 )
+        {
+        rc = aFirst.iDisplayName.CompareF( aSecond.iDisplayName );
+        }
+    return rc;
+    }
+        
+// ==========================================================================
+// FUNCTION: SortByMruDesc
+// ==========================================================================
+TInt CMruAddress::SortByMruDesc( const CMruAddress& aFirst, const CMruAddress& aSecond )
+    {
+    return aSecond.iMruNum < aFirst.iMruNum ? -1 : ( aSecond.iMruNum == aFirst.iMruNum ) ? 0 : 1;
+    }
+        
+// ======================================
+// CLASS: CMruAddressList
+// ======================================
+// ==========================================================================
+// FUNCTION: CMruAddressList
+// ==========================================================================
+CMruAddressList::CMruAddressList( TContainerId aMailboxId )
+: iMailboxId( aMailboxId )
+    {
+    }
+
+// ==========================================================================
+// FUNCTION: ~CMruAddressList
+// ==========================================================================
+CMruAddressList::~CMruAddressList()
+    {
+    iSortedByAddressArray.Reset();
+    iSortedByMruArray.ResetAndDestroy();
+    }
+
+// ==========================================================================
+// FUNCTION: FindAddress
+// ==========================================================================
+CMruAddress* CMruAddressList::FindAddress( CMruAddress* aMruAddress )
+    {
+    CMruAddress* result = NULL;
+    
+    //check if the address already exists
+    TInt index = iSortedByAddressArray.FindInOrder( aMruAddress, &CMruAddress::SortByAddress );
+    if ( index >= 0 )
+        {
+        result = iSortedByAddressArray[index];
+        }
+    
+    return result;
+    }
+        
+// ==========================================================================
+// FUNCTION: PromoteAddressL
+// ==========================================================================
+void CMruAddressList::PromoteAddressL( CMruAddress* aMruAddress, TUint aNewMruNum )
+    {
+    //check if the address already exists
+    TInt ndxAddr = iSortedByAddressArray.FindInOrder( aMruAddress, &CMruAddress::SortByAddress );
+    if ( ndxAddr >= 0 )
+        {
+        CMruAddress* toBePromoted = iSortedByAddressArray[ndxAddr];
+        //already exists, get the index to the MruArray too.
+        TInt ndxMru = iSortedByMruArray.FindInOrder( toBePromoted, &CMruAddress::SortByMruDesc );
+        if ( ndxMru < 0 )
+            {
+            User::Leave( KErrCorrupt );
+            }
+        
+        //get the one that needs to be promoted and remove it from its current position
+        iSortedByAddressArray.Remove( ndxAddr );
+        iSortedByMruArray.Remove( ndxMru );
+
+        //add the promoted back with new MruNum
+        AddAddress( toBePromoted, aNewMruNum );
+        }
+    else
+        {
+        User::Leave( KErrNotFound );
+        }
+    }
+     
+// ==========================================================================
+// FUNCTION: AddAddress
+// ==========================================================================
+void CMruAddressList::AddAddress( CMruAddress* aMruAddress )
+    {
+    iSortedByAddressArray.InsertInOrder( aMruAddress, &CMruAddress::SortByAddress );
+    iSortedByMruArray.InsertInOrder( aMruAddress, &CMruAddress::SortByMruDesc );
+    }
+
+// ==========================================================================
+// FUNCTION: AddAddress
+// ==========================================================================
+void CMruAddressList::AddAddress( CMruAddress* aMruAddress, TUint aNewMruNum )
+    {
+    aMruAddress->SetMruNum( aNewMruNum );
+    AddAddress( aMruAddress );
+    }
+
+// ==========================================================================
+// FUNCTION: GetL
+// ==========================================================================
+CMruAddress* CMruAddressList::GetL( TInt aIndex )
+    {
+    if ( aIndex >= iSortedByMruArray.Count() )
+        {
+        User::Leave( KErrArgument );
+        }
+    return iSortedByMruArray[aIndex];
+    }
+
+// ==========================================================================
+// FUNCTION: RemoveL
+//           This method only removes an object from the array, it does not 
+//           detroy the object
+// ==========================================================================
+void CMruAddressList::RemoveL( TInt aIndex )
+    {
+    if ( aIndex >= iSortedByMruArray.Count() )
+        {
+        User::Leave( KErrArgument );
+        }
+    CMruAddress* toBeRemoved = iSortedByMruArray[aIndex];
+    
+    TInt ndxAddr = iSortedByAddressArray.FindInOrder( toBeRemoved, &CMruAddress::SortByAddress );
+    if ( ndxAddr < 0 )
+        {
+        User::Leave( KErrCorrupt );
+        }
+    iSortedByMruArray.Remove( aIndex );
+    iSortedByAddressArray.Remove( ndxAddr );
+    }
+
+// ======================================
+// CLASS: CContainerStoreMruAddressTable
+// ======================================
+// ======================
+// METHOD IMPLEMENTATIONS
+// ======================
+
+// ==========================================================================
+// FUNCTION: OpenL
+// ==========================================================================
+CContainerStoreMruAddressTable* CContainerStoreMruAddressTable::OpenL( CContainerStoreUtils&        aUtils, 
+																       CContainerStoreEncryption&   aEncryption,
+                                                                       CContainerStoreGeneralTable& aGeneralTable,
+                                                                       CContainerStoreAccountTable& aAccountTable )
+	{
+    CContainerStoreMruAddressTable* self = new(ELeave) CContainerStoreMruAddressTable( aUtils, aEncryption, aGeneralTable, aAccountTable );
+	CleanupStack::PushL( self );
+	self->OpenTableL();
+	CleanupStack::Pop( self );
+	return self;
+	} // end OpenL
+
+// ==========================================================================
+// FUNCTION: CreateL
+// ==========================================================================
+CContainerStoreMruAddressTable* CContainerStoreMruAddressTable::CreateL( CContainerStoreUtils&        aUtils, 
+                                                                         CContainerStoreEncryption&   aEncryption,
+                                                                         CContainerStoreGeneralTable& aGeneralTable,
+                                                                         CContainerStoreAccountTable& aAccountTable )
+	{
+    CContainerStoreMruAddressTable* self = new(ELeave) CContainerStoreMruAddressTable( aUtils, aEncryption, aGeneralTable, aAccountTable );
+	CleanupStack::PushL( self );
+	self->CreateTableL();
+	CleanupStack::Pop( self );
+	return self;
+	} // end CreateL
+
+// ==========================================================================
+// FUNCTION: Constructor
+// ==========================================================================
+CContainerStoreMruAddressTable::CContainerStoreMruAddressTable( CContainerStoreUtils&        aUtils, 
+														        CContainerStoreEncryption&   aEncryption,
+                                                                CContainerStoreGeneralTable& aGeneralTable,
+                                                                CContainerStoreAccountTable& aAccountTable ) :
+    CContainerStoreTable( aUtils ), iEncryption(aEncryption), iGeneralTable( aGeneralTable ), iAccountTable( aAccountTable )
+	{
+	__LOG_CONSTRUCT( "msg", "CContainerStoreMruAddressTable" )
+	__LOG_CLOSE_BETWEEN_WRITES
+	} // end constructor
+
+// ==========================================================================
+// FUNCTION: Destructor
+// ==========================================================================
+CContainerStoreMruAddressTable::~CContainerStoreMruAddressTable()
+	{
+    iAddressLists.ResetAndDestroy();
+	iUtils.CloseTable( iTable );
+    iEncryptedBuffer.Close();
+    
+	__LOG_DESTRUCT	
+	} // end destructor
+	
+// ==========================================================================
+// FUNCTION: OpenTableL
+// ==========================================================================
+void CContainerStoreMruAddressTable::OpenTableL()
+	{
+	__LOG_ENTER( "OpenTableL" )
+
+	iUtils.OpenTableL( iTable, KMruAddressTableName );
+	
+	// Get the column numbers for the containers table.
+	CDbColSet* colSet = iTable.ColSetL();
+	CleanupStack::PushL( colSet );
+	
+    iMruNumColNum        = colSet->ColNo( KMruAddressTableMruNumCol );
+    iMailboxIdColNum     = colSet->ColNo( KMruAddressTableMailBoxIdCol );
+    iDisplayNameColNum   = colSet->ColNo( KMruAddressTableDisplayNameCol );
+    iEmailAddressColNum  = colSet->ColNo( KMruAddressTableEmailAddressCol );
+	iIsEncryptedColNum   = colSet->ColNo( KMruAddressTableIsEncryptedCol );
+	
+	CleanupStack::PopAndDestroy( colSet );
+
+	// Set the table's index to the ID index.
+	User::LeaveIfError( iTable.SetIndex( KMruAddressTableMruNumIndex ) );
+    
+	__LOG_EXIT	
+	} // end OpenTableL
+	
+// ==========================================================================
+// FUNCTION: CreateTableL
+// ==========================================================================
+void CContainerStoreMruAddressTable::CreateTableL()
+	{
+	__LOG_ENTER( "CreateTableL" )
+	
+	// Create table columns
+	
+	CDbColSet* colSet = CDbColSet::NewLC();
+	
+	TDbCol rowIdCol( KMruAddressTableMruNumCol, EDbColUint32 );
+	colSet->AddL( rowIdCol );	
+	
+    TDbCol mailBoxIdCol( KMruAddressTableMailBoxIdCol, EDbColUint32 );
+    colSet->AddL( mailBoxIdCol );   
+    
+	TDbCol displayNameCol( KMruAddressTableDisplayNameCol, EDbColLongBinary );
+	colSet->AddL( displayNameCol );	
+	
+    TDbCol emailAddressCol( KMruAddressTableEmailAddressCol, EDbColLongBinary );
+    colSet->AddL( emailAddressCol ); 
+	
+	TDbCol isEncryptedCol( KMruAddressTableIsEncryptedCol, EDbColUint8 );
+	colSet->AddL( isEncryptedCol );	
+		
+	// Create table.
+	iUtils.CreateTableL( KMruAddressTableName, *colSet );
+	
+	CleanupStack::PopAndDestroy( colSet );
+	
+	//create indexes on RowId and MailBox ID columns
+    CreateIndexL( KMruAddressTableName, KMruAddressTableMruNumIndex,    KMruAddressTableMruNumCol );
+    CreateIndexL( KMruAddressTableName, KMruAddressTableMailboxIdIndex, KMruAddressTableMailBoxIdCol );
+	
+	OpenTableL();
+			
+	__LOG_EXIT
+	} // end CreateTableL
+	
+
+// ==========================================================================
+// FUNCTION: SetMruAddressListL
+// ==========================================================================
+void CContainerStoreMruAddressTable::SetMruAddressListL( TContainerId                aMailboxId, 
+                                                         RPointerArray<CMruAddress>& aMruAddressArray ) 
+	{
+    __LOG_ENTER_SUPPRESS( "SetMruAddressListL" )
+    __LOG_WRITE8_FORMAT1_INFO( "mailbox=%x", aMailboxId )
+
+    InitializeIfNeededL();
+    
+	CMruAddressList& addressList = AddressListByMailboxIdL( aMailboxId );
+    
+    iUtils.BeginDatabaseTransactionLC();
+    
+	//Need to add the addresses in the reverse order 
+    //so that the first element in the input array has the highest MRU number
+    TInt count = aMruAddressArray.Count();
+    for ( TInt i = count - 1 ; i >= 0 ; i-- )
+        {
+        CMruAddress* curAddr = aMruAddressArray[i];
+        SetMruAddressL( addressList, curAddr );
+        
+        //remove the address from the array because it maybe added to the list already
+        aMruAddressArray.Remove(i);
+        
+        //After returning from SetMruAddressL, the curAddr can be either
+        // NULL - if the address is new and the object has been added to the MRU list, or
+        // Unchanged if the address already exists, and the existing object was "promoted"
+        // to the top of the MRU list
+        // In either case, we can delete the pointer
+        delete curAddr;
+        }
+    
+    //Persist the iCurMruNumber to General Table
+    iGeneralTable.SetCurMruNumberL( iCurMruNumber );
+    
+    iUtils.CommitDatabaseTransactionL();
+	}
+
+// ==========================================================================
+// FUNCTION: SetMaxMruCountL
+// ==========================================================================
+void CContainerStoreMruAddressTable::SetMaxMruCountL( TInt aMaxCount )
+    {
+    
+    InitializeIfNeededL();
+    
+    iMaxMruCount = aMaxCount;
+    
+    iUtils.BeginDatabaseTransactionLC();
+    
+    for ( TInt i = 0 ; i < iAddressLists.Count() ; i++ )
+        {
+        CMruAddressList* list = iAddressLists[i];
+        TInt count = list->Count();
+        while ( count  > aMaxCount )
+            {
+            CMruAddress* address = list->GetL(count - 1);
+            CleanupStack::PushL( address );
+            
+            //remove it from the list
+            list->RemoveL( count - 1 );
+            
+            //delete it from the table
+            DeleteAddressFromTableL( address->MruNum() );
+            
+            CleanupStack::PopAndDestroy( address );
+            count = list->Count();
+            }
+        }
+    iGeneralTable.SetMaxMruCountL( aMaxCount );
+    
+    iUtils.CommitDatabaseTransactionL();
+    }
+
+// ==========================================================================
+// FUNCTION: MruAddressListL
+// ==========================================================================
+const RPointerArray<CMruAddress>& CContainerStoreMruAddressTable::MruAddressListL( TContainerId aMailboxId )
+    {
+    __LOG_ENTER_SUPPRESS( "SetMruAddressListL" );
+    __LOG_WRITE8_FORMAT1_INFO( "mailbox=%x", aMailboxId );
+    
+    InitializeIfNeededL();
+    
+    CMruAddressList& addressList = AddressListByMailboxIdL( aMailboxId );
+    
+    return addressList.SortedByMruArray();
+    }
+
+// ==========================================================================
+// FUNCTION: AddMailBoxL
+// ==========================================================================
+void CContainerStoreMruAddressTable::AddMailboxL( TContainerId aMailboxId )
+    {
+    __LOG_ENTER( "AddMailboxL" )
+    
+    TRAPD( err, AddressListByMailboxIdL( aMailboxId ) );
+    if ( err != KErrNotFound )
+        {
+        User::Leave( KErrAlreadyExists );
+        }
+    
+    CMruAddressList* list = new(ELeave) CMruAddressList( aMailboxId );
+    iAddressLists.Append( list );
+    
+    __LOG_EXIT
+    }
+// ==========================================================================
+// FUNCTION: DeleteMailBoxL
+// ==========================================================================
+void CContainerStoreMruAddressTable::DeleteMailboxL( TContainerId aMailboxId )
+    {
+    __LOG_ENTER( "DeleteMailboxL" )
+    
+    //delete from the lists in memory
+    TBool found = EFalse;
+    TInt count = iAddressLists.Count();
+    for ( TInt i = 0 ; i < count ; i++ )
+        {
+        if ( iAddressLists[i]->MailboxId() == aMailboxId )
+            {
+            CMruAddressList* list = iAddressLists[i];
+            iAddressLists.Remove( i );
+            delete list;
+            break;
+            }
+        }
+    
+    if ( !found == NULL )
+        {
+        User::Leave( KErrNotFound );
+        }
+    
+    //delete from the table
+    const TUint bufSize = 100;
+    TBuf<bufSize> sqlString;
+    sqlString.Copy( KDelete );
+    sqlString.Append( KFrom );
+    sqlString.Append( KMruAddressTableName );
+    sqlString.Append( KWhere );
+    sqlString.Append( KMruAddressTableMailBoxIdCol );
+    sqlString.Append( KEquals );
+    sqlString.AppendNum( aMailboxId );
+    
+    __LOG_WRITE_FORMAT1_INFO("sqlString=%S", &sqlString );
+    
+    iUtils.Execute( sqlString );
+    
+    __LOG_EXIT
+    }
+
+
+// ==========================================================================
+// FUNCTION: SetMRUAddressL
+// ==========================================================================
+void CContainerStoreMruAddressTable::SetMruAddressL( CMruAddressList& aAddressList, CMruAddress*& aMruAddress )
+    {
+    __LOG_ENTER_SUPPRESS( "SetMruAddressL" )
+    __LOG_WRITE8_FORMAT2_INFO( "emailAddr=%S, dispName=%S", &aMruAddress->EmailAddress(), &aMruAddress->DisplayName() )
+    
+    ++iCurMruNumber;
+    
+    CMruAddress* existing = aAddressList.FindAddress( aMruAddress );
+    if ( !existing  )
+        {
+        aMruAddress->SetMruNum( iCurMruNumber );
+        AddAddressToTableL( aAddressList.MailboxId(), aMruAddress );
+        aAddressList.AddAddress( aMruAddress );
+        
+        //check for the MaxMruAddressCount
+        if ( aAddressList.SortedByMruArray().Count() > iMaxMruCount )
+            {
+            //we have exceeded the maximum size, delete the last one
+            CMruAddress* toBeRemoved = aAddressList.GetL( iMaxMruCount );
+            CleanupStack::PushL( toBeRemoved );
+            
+            aAddressList.RemoveL( iMaxMruCount );
+            DeleteAddressFromTableL( toBeRemoved->MruNum() );
+            
+            CleanupStack::PopAndDestroy( toBeRemoved );
+            }
+        //need to set aMruAddress to NULL because its memory has been added to addressList
+        //and we don't want the caller to free that memory
+        aMruAddress = NULL;
+        }
+    else
+        {
+        UpdateMruNumberInTableL( existing->MruNum(), iCurMruNumber );
+        aAddressList.PromoteAddressL( existing, iCurMruNumber );
+        //we did not use the aMruAddress, so leave it as is so that the caller can free it
+        }
+    }
+
+// ==========================================================================
+// FUNCTION: AddressListByMailboxIdL
+// ==========================================================================
+CMruAddressList& CContainerStoreMruAddressTable::AddressListByMailboxIdL( TContainerId aMailboxId )
+    {
+    CMruAddressList* list = NULL;
+    TInt count = iAddressLists.Count();
+    for ( TInt i = 0 ; i < count ; i++ )
+        {
+        if ( iAddressLists[i]->MailboxId() == aMailboxId )
+            {
+            list = iAddressLists[i];
+            break;
+            }
+        }
+    
+    if ( !list )
+        {
+        User::Leave( KErrNotFound );
+        }
+    
+    return *list;
+    }
+
+// ==========================================================================
+// FUNCTION: InitializeIfNeededL
+// ==========================================================================
+void CContainerStoreMruAddressTable::InitializeIfNeededL()
+    {
+    if ( !iEncryption.Authenticated() )
+        {
+        User::Leave(KErrNotReady);
+        }
+    
+    if ( iAddressLists.Count() == 0 )
+        {
+        iCurMruNumber = iGeneralTable.CurMruNumberL();
+        iMaxMruCount = iGeneralTable.MaxMruCountL();
+        
+        RArray<TContainerId> mailboxIds;
+        CleanupClosePushL( mailboxIds );
+        
+        iAccountTable.MailboxIdsL( mailboxIds );
+        
+        InitializeAddressListsL( mailboxIds );
+    
+        CleanupStack::PopAndDestroy( &mailboxIds );
+        }
+    }
+
+// ==========================================================================
+// FUNCTION: InitializeAddressListsL
+// ==========================================================================
+void CContainerStoreMruAddressTable::InitializeAddressListsL( RArray<TContainerId>& aMailboxIds )
+    {
+    __LOG_ENTER( "InitializeAddressListsL" )
+    
+    RBuf emailAddress;
+    CleanupClosePushL( emailAddress );
+    
+    RBuf displayName;
+    CleanupClosePushL( displayName );
+    
+    TInt count = aMailboxIds.Count();
+    for ( TInt i = 0 ; i < count ; i++ )
+        {
+        TContainerId mailboxId = aMailboxIds[i];
+        CMruAddressList* list = new(ELeave) CMruAddressList( mailboxId );
+        iAddressLists.Append( list );
+        
+        const TUint bufSize = 100;
+        TBuf<bufSize> sqlString;
+        sqlString.Copy( KSelectStar );
+        sqlString.Append( KFrom );
+        sqlString.Append( KMruAddressTableName );
+        sqlString.Append( KWhere );
+        sqlString.Append( KMruAddressTableMailBoxIdCol );
+        sqlString.Append( KEquals );
+        sqlString.AppendNum( mailboxId );
+        __LOG_WRITE_FORMAT1_INFO( "sqlString=%S", &sqlString )
+        
+        RDbView view;
+        CleanupClosePushL( view );
+        
+        iUtils.PopulateViewL( view, sqlString );
+        
+        for( TBool hasMore = view.FirstL() ; hasMore ; hasMore = view.NextL() )
+            {
+            view.GetL();
+            TUint mruNum = view.ColUint32( iMruNumColNum );
+            ReadStringFieldL( view, iEmailAddressColNum, emailAddress );
+            ReadStringFieldL( view, iDisplayNameColNum, displayName );
+            
+            CMruAddress* address = CMruAddress::NewL( mruNum, emailAddress, displayName );
+            list->AddAddress( address );
+            }
+        
+        CleanupStack::PopAndDestroy( &view );
+        //here
+        }
+    CleanupStack::PopAndDestroy( &displayName );
+    CleanupStack::PopAndDestroy( &emailAddress );
+    
+    __LOG_EXIT
+    }
+
+// ==========================================================================
+// FUNCTION: AddAddressToTableL
+// ==========================================================================
+void CContainerStoreMruAddressTable::AddAddressToTableL( TContainerId aMailboxId, CMruAddress* aMruAddress )
+    {
+    __LOG_ENTER_SUPPRESS("AddAddressToTableL")
+    __LOG_WRITE_FORMAT4_INFO("mbId=%x, mru=%u, email=%S, dispName=%S", 
+            aMailboxId, aMruAddress->MruNum(), &aMruAddress->EmailAddress(), &aMruAddress->DisplayName() )
+    
+    iTable.LastL();
+    
+    InsertRowLC();
+     
+    iTable.SetColL( iMruNumColNum,    aMruAddress->MruNum() );
+    iTable.SetColL( iMailboxIdColNum, aMailboxId );
+    
+    TBool isEncryptionOn = iEncryption.IsEncryptionOn();
+    
+    iTable.SetColL( iIsEncryptedColNum, static_cast<TUint8>( isEncryptionOn ) );
+    WriteStringFieldL( iEmailAddressColNum, aMruAddress->EmailAddress(), isEncryptionOn );
+    WriteStringFieldL( iDisplayNameColNum, aMruAddress->DisplayName(), isEncryptionOn );
+    
+    PutRowUpdatesL();
+    }
+
+// ==========================================================================
+// FUNCTION: UpdateMruNumberInTableL
+// ==========================================================================
+void CContainerStoreMruAddressTable::UpdateMruNumberInTableL( TUint aOldMruNum, TUint aNewMruNum )
+    {
+    __LOG_ENTER_SUPPRESS("UpdateMruNumberInTable")
+    __LOG_WRITE_FORMAT2_INFO("updating MRU %u to %u", aOldMruNum, aNewMruNum )
+    
+    iTable.SeekL( aOldMruNum );
+    
+    PrepareRowForUpdateLC();
+    
+    iTable.SetColL( iMruNumColNum, aNewMruNum );
+    
+    PutRowUpdatesL();
+    }
+
+// ==========================================================================
+// FUNCTION: DeleteAddressFromTableL
+// ==========================================================================
+void CContainerStoreMruAddressTable::DeleteAddressFromTableL( TUint aMruNum )
+    {
+    __LOG_ENTER_SUPPRESS( "DeleteAddressFromTable" )
+    
+    __LOG_WRITE8_FORMAT1_INFO( "aMruNum=%ld", aMruNum )
+    
+    SeekL( aMruNum );
+    iTable.DeleteL();
+    }
+
+// ==========================================================================
+// FUNCTION: ReadStringFieldL
+// ==========================================================================
+void CContainerStoreMruAddressTable::ReadStringFieldL( RDbRowSet& aRowSet, TInt aColumnNum, RBuf& aString )
+    {
+    __LOG_ENTER_SUPPRESS( "ReadStringFieldL" )
+    
+    aString.SetLength( 0 );
+    
+    iUtils.ReadLongColumnL( aRowSet, aColumnNum, iEncryptedBuffer );
+    
+    RBuf8 string8;
+    CleanupClosePushL( string8 );
+    string8.Create( iEncryptedBuffer.Length() );
+    
+    if( aString.Size() < iEncryptedBuffer.Length() )
+        {        
+        aString.ReAllocL( iEncryptedBuffer.Length() );
+        } // end if
+    
+    if ( IsEncrypted( aRowSet ) )
+        {
+        if( iEncryptedBuffer.Length() > 0 )
+            {        
+            iEncryption.DecryptL( iEncryptedBuffer, string8 );        
+            iEncryption.RemovePaddingL( string8 );
+            } // end if
+        }
+    else
+        {
+        string8.Copy( iEncryptedBuffer );
+        }
+    
+    const TUint16* valuePtr16 = reinterpret_cast<const TUint16*>( string8.Ptr() );
+    TPtrC16 string16;
+    string16.Set( valuePtr16, string8.Length() / 2 );
+    aString.Copy( string16 );
+    
+    CleanupStack::PopAndDestroy( &string8 );
+    
+    __LOG_WRITE_FORMAT2_DEBUG3( "col=%d, string=%S", aColumnNum, &aString )
+    }
+
+// ==========================================================================
+// FUNCTION: WriteStringFieldL
+// ==========================================================================
+void CContainerStoreMruAddressTable::WriteStringFieldL( TInt aColumnNum, const TDesC& aString, TBool aEncryptBeforeWrite )
+    {
+    
+    const TUint8* valuePtr8 = reinterpret_cast<const TUint8*>( aString.Ptr() );
+    TPtrC8 string8;
+    string8.Set( valuePtr8, aString.Length() * 2 );
+    
+    if ( aEncryptBeforeWrite && string8.Length() > 0 )
+        {
+        RBuf8 encryptedBuffer;
+        encryptedBuffer.CreateL( string8.Length() + iEncryption.BlockSizeL() );
+        CleanupClosePushL( encryptedBuffer );
+        
+        RBuf8 paddedBuffer;
+        paddedBuffer.CreateL( string8.Length() + iEncryption.BlockSizeL() );       
+        CleanupClosePushL( paddedBuffer );
+        
+        paddedBuffer.Copy( string8 );
+        iEncryption.AddPaddingL( paddedBuffer, iEncryption.BlockSizeL() );
+        
+        iEncryption.EncryptL( paddedBuffer, encryptedBuffer );
+        
+        CleanupStack::PopAndDestroy( &paddedBuffer );
+        
+        iUtils.WriteLongColumnL( iTable, aColumnNum, encryptedBuffer );
+        
+        CleanupStack::PopAndDestroy( &encryptedBuffer );
+        }
+    else
+        {
+        iUtils.WriteLongColumnL( iTable, aColumnNum, string8 );
+        }
+    }
+
+// ==========================================================================
+// FUNCTION: EncryptFirstL
+// ==========================================================================
+TBool CContainerStoreMruAddressTable::EncryptFirstL( TDbBookmark& aNextRow )
+    {
+    __LOG_ENTER( "EncryptFirstL" )
+    
+    TBool found = iUtils.FindFirstEncryptedOrUnencryptedL( iTable, KMruAddressTableIsEncryptedCol, EFalse, aNextRow );
+    
+    __LOG_EXIT
+    
+    return found;
+    }
+
+// ==========================================================================
+// FUNCTION: EncryptNextL
+// ==========================================================================
+TBool CContainerStoreMruAddressTable::EncryptNextL( TDbBookmark& aNextRow )
+    {
+    __LOG_ENTER( "EncryptNextL" )
+    
+    TBool hasMore = EFalse;
+    
+    TRAPD( err, iTable.GotoL( aNextRow ) );
+    if ( err == KErrNotFound )
+        {
+        hasMore = EncryptFirstL( aNextRow );
+        }
+    else if ( err != KErrNone )
+        {
+        User::Leave( err );        
+        }
+    else
+        {
+        iTable.GetL();
+        if ( !IsEncrypted( iTable ) )
+            {
+            RBuf stringBuf;
+            CleanupClosePushL( stringBuf );
+            
+            //read and encrypt the email address field
+            ReadStringFieldL( iTable, iEmailAddressColNum, stringBuf );
+            
+            PrepareRowForUpdateLC();
+            
+            WriteStringFieldL( iEmailAddressColNum, stringBuf, ETrue );  //encrypt before write
+            
+            //read and encrypt the displayName
+            ReadStringFieldL( iTable, iDisplayNameColNum, stringBuf );
+            
+            WriteStringFieldL( iDisplayNameColNum, stringBuf, ETrue );  //encrypt before write
+            
+            //update the isEncrypted column
+            SetEncryptedL( ETrue );
+            
+            PutRowUpdatesL();
+            
+            CleanupStack::PopAndDestroy( &stringBuf );
+            }
+        
+        hasMore = iTable.NextL();
+        if ( hasMore )
+            {
+            __LOG_WRITE_INFO("hasMore is TRUE")
+            aNextRow = iTable.Bookmark();
+            }
+        }
+
+    __LOG_EXIT
+    
+    return hasMore;
+    }
+
+// ==========================================================================
+// FUNCTION: DecryptFirstL
+// ==========================================================================
+TBool CContainerStoreMruAddressTable::DecryptFirstL( TDbBookmark& aNextRow )
+    {
+    __LOG_ENTER( "DecryptFirstL" )
+    
+    TBool found = iUtils.FindFirstEncryptedOrUnencryptedL( iTable, KMruAddressTableIsEncryptedCol, ETrue, aNextRow );
+    
+    __LOG_EXIT
+    
+    return found;
+    }
+
+// ==========================================================================
+// FUNCTION: DecryptNextL
+// ==========================================================================
+TBool CContainerStoreMruAddressTable::DecryptNextL( TDbBookmark& aNextRow )
+    {
+    __LOG_ENTER( "DecryptNextL" )
+    
+    TBool hasMore = EFalse;
+    
+    TRAPD( err, iTable.GotoL( aNextRow ) );
+    if ( err == KErrNotFound )
+        {
+        hasMore = DecryptFirstL( aNextRow );
+        }
+    else if ( err != KErrNone )
+        {
+        User::Leave( err );        
+        }
+    else
+        {
+        iTable.GetL();
+        if ( IsEncrypted( iTable) )
+            {
+            RBuf stringBuf;
+            CleanupClosePushL( stringBuf );
+
+            //decrypt and write the email address
+            ReadStringFieldL( iTable, iEmailAddressColNum, stringBuf );
+            
+            PrepareRowForUpdateLC();
+            
+            WriteStringFieldL( iEmailAddressColNum, stringBuf, EFalse );  //write unencrypted
+            
+            //decrypt and write the displayName
+            ReadStringFieldL( iTable, iDisplayNameColNum, stringBuf );
+            
+            WriteStringFieldL( iDisplayNameColNum, stringBuf, EFalse );  //write unencrypted
+            
+            //update the isEncrypted column
+            SetEncryptedL( EFalse );
+            
+            PutRowUpdatesL();
+            
+            CleanupStack::PopAndDestroy( &stringBuf );
+            }
+        
+        hasMore = iTable.NextL();
+        if ( hasMore )
+            {
+            __LOG_WRITE_INFO("hasMore is TRUE")
+            aNextRow = iTable.Bookmark();
+            }
+        }
+
+    __LOG_EXIT
+    
+    return hasMore;
+    }
+
+// ==========================================================================
+// FUNCTION: SeekL
+// ==========================================================================
+void CContainerStoreMruAddressTable::SeekL( TUint aMruNum )
+    {
+    __LOG_ENTER_SUPPRESS("SeekL")
+    if ( !iTable.SeekL( aMruNum ) )
+        {
+        __LOG_WRITE8_FORMAT1_ERROR( "RowId id %x not found", aMruNum )
+        User::Leave( KErrNotFound );
+        }
+    }
+
+// ==========================================================================
+// FUNCTION: IsEncrypted
+// ==========================================================================
+TBool CContainerStoreMruAddressTable::IsEncrypted( RDbRowSet& aRowSet )
+    {
+    return static_cast<TBool>( aRowSet.ColUint8( iIsEncryptedColNum ) );
+    }
+
+// ==========================================================================
+// FUNCTION: SetEncryptedL
+// ==========================================================================
+void CContainerStoreMruAddressTable::SetEncryptedL( TBool aIsEncrypted )
+    {
+    iTable.SetColL( iIsEncryptedColNum, static_cast<TUint8>(aIsEncrypted) );
+    }
+