emailservices/emailstore/message_store/server/src/ContainerStoreContainersTable.cpp
/*
* 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 containers table implementation.
*
*/
// ========
// INCLUDES
// ========
#include <s32mem.h> // for descriptor read/write streams
#include "ContainerStoreContainersTable.h"
#include "ContainerStoreDefs.h"
#include "ContainerStoreEncryption.h"
#include "ContainerStoreUtils.h"
#include "PropertiesSerializer.h"
#include "MessageStoreClientServer.h"
// =========
// CONSTANTS
// =========
_LIT( KSelect, "SELECT " );
_LIT( KComma, "," );
_LIT( KFrom, " FROM " );
_LIT( KWhere, " WHERE " );
_LIT( KAnd, " AND " );
_LIT( KEqualTo, "=" );
_LIT( KGreaterThanOrEqualTo, ">=" );
_LIT( KLessThanOrEqualTo, "<=" );
_LIT( KOrderBy, " ORDER BY ");
_LIT( KAsc, " ASC" );
// ======================
// METHOD IMPLEMENTATIONS
// ======================
// ==========================================================================
// FUNCTION: OpenL
// ==========================================================================
CContainerStoreContainersTable* CContainerStoreContainersTable::OpenL( CContainerStoreUtils& aUtils,
MCustomBehaviorProvider& aCustomBehaviorProvider,
TUint aCountsLength,
CContainerStoreEncryption& aEncryption )
{
CContainerStoreContainersTable* self = new(ELeave) CContainerStoreContainersTable( aUtils, aCustomBehaviorProvider, aCountsLength, aEncryption );
CleanupStack::PushL( self );
self->OpenTableL();
CleanupStack::Pop( self );
return self;
} // end OpenL
// ==========================================================================
// FUNCTION: CreateL
// ==========================================================================
CContainerStoreContainersTable* CContainerStoreContainersTable::CreateL( CContainerStoreUtils& aUtils,
MCustomBehaviorProvider& aCustomBehaviorProvider,
TUint aCountsLength,
CContainerStoreEncryption& aEncryption )
{
CContainerStoreContainersTable* self = new(ELeave) CContainerStoreContainersTable( aUtils, aCustomBehaviorProvider, aCountsLength, aEncryption );
CleanupStack::PushL( self );
self->CreateTableL();
CleanupStack::Pop( self );
return self;
} // end CreateL
// ==========================================================================
// FUNCTION: Constructor
// ==========================================================================
CContainerStoreContainersTable::CContainerStoreContainersTable( CContainerStoreUtils& aUtils,
MCustomBehaviorProvider& aCustomBehaviorProvider,
TUint aCountsLength,
CContainerStoreEncryption& aEncryption ) :
CContainerStoreTable( aUtils ),
iCustomBehaviorProvider( aCustomBehaviorProvider ),
iCountsLength( aCountsLength ),
iEncryption( aEncryption )
{
__LOG_CONSTRUCT( "msg", "CContainerStoreContainersTable" )
} // end constructor
// ==========================================================================
// FUNCTION: Destructor
// ==========================================================================
CContainerStoreContainersTable::~CContainerStoreContainersTable()
{
iUtils.CloseTable( iTable );
__LOG_DESTRUCT
} // end destructor
// ==========================================================================
// FUNCTION: HierarchyL
// ==========================================================================
void CContainerStoreContainersTable::HierarchyL( TContainerId aId,
RArray<TContainerId>& aHierarchy )
{
__LOG_ENTER_SUPPRESS( "HierarchyL" )
aHierarchy.Reset();
TBool done = EFalse;
TContainerId currentId = aId;
if( !iTable.SeekL( currentId ) )
{
__LOG_WRITE_ERROR( "container not found" )
User::Leave( KErrNotFound );
} // end if
// Set a bookmark at the original container, for a quick return.
TDbBookmark bookmark = iTable.Bookmark();
aHierarchy.Append( currentId );
// Build the hierarchy of the container.
while( !done )
{
iTable.GetL();
TContainerId parentId = iTable.ColUint32( iParentIdColNum );
switch( parentId )
{
case KContainerInvalidId:
// Stop when the container has no parent container.
done = ETrue;
break;
case KUncommittedContainers:
// Stop when the container is uncommitted.
aHierarchy.Append( KUncommittedContainers );
done = ETrue;
break;
case KToBeDeletedContainers:
// If the container is the To Be Deleted hierarchy then treat this as a "not found" case.
__LOG_WRITE_ERROR( "container is in to be deleted hierarchy" )
User::Leave( KErrNotFound );
break;
default:
// Add the parent to the hierarchy.
aHierarchy.Append( parentId );
// Traverse to the parent entry.
if( !iTable.SeekL( parentId ) )
{
// This should not happen. If it has, there are orphaned records in the database.
__LOG_WRITE8_FORMAT1_ERROR( "orphaned container found %i", parentId )
User::Leave( KErrNotFound );
} // end if
break;
} // end case
} // end while
// Go back to the original container.
iTable.GotoL( bookmark );
} // end HierarchyL
// ==========================================================================
// FUNCTION: SeekL
// ==========================================================================
void CContainerStoreContainersTable::SeekL( TContainerId aId,
RArray<TContainerId>& aHierarchy )
{
HierarchyL( aId, aHierarchy );
} // end SeekL
// ==========================================================================
// FUNCTION: SeekL
// ==========================================================================
void CContainerStoreContainersTable::SeekL( TContainerId aId )
{
__LOG_ENTER_SUPPRESS( "SeekL" )
if( !iTable.SeekL( aId ) )
{
__LOG_WRITE_ERROR( "container not found" )
User::Leave( KErrNotFound );
} // end if
iTable.GetL();
} // end SeekL
// ==========================================================================
// FUNCTION: SeekL
// ==========================================================================
void CContainerStoreContainersTable::SeekL( TContainerId aId,
TContainerId& aParentId )
{
SeekL( aId );
iTable.GetL();
aParentId = iTable.ColUint32( iParentIdColNum );
} // end SeekL
// ==========================================================================
// FUNCTION: FindL
// ==========================================================================
TContainerId CContainerStoreContainersTable::FindL( const TDesC& aSqlQuery )
{
__LOG_ENTER_SUPPRESS( "FindL" )
__LOG_WRITE_FORMAT1_DEBUG3( "query=%S", &aSqlQuery )
TContainerId returnValue;
iTable.FirstL();
if( iTable.FindL( RDbRowSet::EForwards, aSqlQuery ) == KErrNotFound )
{
__LOG_WRITE_INFO( "No match found" )
returnValue = KContainerInvalidId;
}
else
{
iTable.GetL();
returnValue = iTable.ColUint32( iIdColNum );
} // end if
return returnValue;
} // end FindL
// ==========================================================================
// FUNCTION: GotoL
// ==========================================================================
TContainerId CContainerStoreContainersTable::GotoL( TDbBookmark aBookmark )
{
iTable.GotoL( aBookmark );
iTable.GetL();
return iTable.ColUint32( iIdColNum );
} // end GotoL
// ==========================================================================
// FUNCTION: Bookmark
// ==========================================================================
TDbBookmark CContainerStoreContainersTable::Bookmark()
{
return iTable.Bookmark();
} // end Bookmark
// ==========================================================================
// FUNCTION: ParentId
// ==========================================================================
TContainerId CContainerStoreContainersTable::ParentId()
{
return iTable.ColUint32( iParentIdColNum );
} // end ParentId
// ==========================================================================
// FUNCTION: OpenTableL
// ==========================================================================
void CContainerStoreContainersTable::OpenTableL()
{
__LOG_ENTER( "OpenTableL" )
iUtils.OpenTableL( iTable, KContainersTableName );
// Get the column numbers for the containers table.
CDbColSet* colSet = iTable.ColSetL();
CleanupStack::PushL( colSet );
iIdColNum = colSet->ColNo( KContainersTableIdCol );
iParentIdColNum = colSet->ColNo( KContainersTableParentIdCol );
iChildrenCountsColNum = colSet->ColNo( KContainersTableChildrenCountsCol );
iChildrenCountColNum = colSet->ColNo( KContainersTableChildrenCountCol );
iPropertiesColNum = colSet->ColNo( KContainersTablePropertiesCol );
iQuickPropertiesColNum = colSet->ColNo( KContainersTableQuickPropertiesCol );
iCountsColNum = colSet->ColNo( KContainersTableCountsCol );
iIsRowEncryptedColNum = colSet->ColNo( KContainersTableIsRowEncryptedCol );
CleanupStack::PopAndDestroy( colSet );
// Set the table's index to the ID index.
User::LeaveIfError( iTable.SetIndex( KContainersTableIdIndex ) );
__LOG_EXIT
} // end OpenTableL
// ==========================================================================
// FUNCTION: CreateTableL
// ==========================================================================
void CContainerStoreContainersTable::CreateTableL()
{
__LOG_ENTER( "CreateContainersTableL" )
// Create table columns
CDbColSet* colSet = CDbColSet::NewLC();
TDbCol idCol( KContainersTableIdCol, EDbColUint32 );
colSet->AddL( idCol );
TDbCol parentIdCol( KContainersTableParentIdCol, EDbColUint32 );
colSet->AddL( parentIdCol );
TDbCol childrenCountCol( KContainersTableChildrenCountCol, EDbColUint16 );
colSet->AddL( childrenCountCol );
TDbCol childrenCountsCol( KContainersTableChildrenCountsCol, EDbColBinary, iCountsLength );
colSet->AddL( childrenCountsCol );
TDbCol propertiesCol( KContainersTablePropertiesCol, EDbColLongBinary );
colSet->AddL( propertiesCol );
TDbCol quickPropertiesCol( KContainersTableQuickPropertiesCol, EDbColLongBinary );
colSet->AddL( quickPropertiesCol );
TDbCol countsCol( KContainersTableCountsCol, EDbColBinary, iCountsLength );
colSet->AddL( countsCol );
TDbCol isEncryptedCol( KContainersTableIsRowEncryptedCol, EDbColUint8 );
colSet->AddL( isEncryptedCol );
// Create table.
iUtils.CreateTableL( KContainersTableName, *colSet );
CleanupStack::PopAndDestroy( colSet );
// Create table index.
CreateIndexL( KContainersTableName, KContainersTableIdIndex, KContainersTableIdCol );
OpenTableL();
__LOG_EXIT
} // end CreateTableL
// ==========================================================================
// FUNCTION: WritePropertiesColumnL
// ==========================================================================
void CContainerStoreContainersTable::WritePropertiesColumnL( const TDesC8& aProperties )
{
__LOG_ENTER_SUPPRESS( "WritePropertiesColumnL" )
if( aProperties.Length() > 0 )
{
if ( IsEncrypted() )
{
EncryptAndWritePropertiesColumnL( aProperties );
}
else
{
WriteUnencryptedPropertiesColumnL( aProperties );
}
}
else
{
iTable.SetColNullL( iPropertiesColNum );
} // end if
} // end WritePropertiesColumnL
// ==========================================================================
// FUNCTION: ReadPropertiesColumnL
// ==========================================================================
void CContainerStoreContainersTable::ReadPropertiesColumnL( RBuf8& aProperties )
{
__LOG_ENTER_SUPPRESS( "ReadPropertiesColumnL" )
if ( IsEncrypted() )
{
ReadAndDescrptPropertiesColumnL( aProperties );
}
else
{
ReadUnencryptedPropertiesColumnL( aProperties );
}
} // end ReadPropertiesColumnL
// ==========================================================================
// FUNCTION: CreateContainerL
// ==========================================================================
void CContainerStoreContainersTable::CreateContainerL( TContainerId aId,
TContainerId aParentId,
const TDesC8& aProperties,
RBuf8& aQuickProperties )
{
__LOG_ENTER_SUPPRESS( "CreateContainerL" )
RBuf8 countsBuf;
CleanupClosePushL( countsBuf );
countsBuf.CreateL( iCountsLength );
iCustomBehaviorProvider.InitializeCounts( countsBuf );
// Insert an entry in the folders table.
iTable.LastL();
InsertRowLC();
iTable.SetColL( iIdColNum, aId );
iTable.SetColL( iParentIdColNum, aParentId );
iTable.SetColL( iChildrenCountColNum, 0 );
iTable.SetColL( iChildrenCountsColNum, countsBuf );
iTable.SetColL( iIsRowEncryptedColNum, static_cast<TUint8>( iEncryption.IsEncryptionOn() ) );
WritePropertiesColumnL( aProperties );
// Add the type bits to the assigned ID.
TUint type = aId & KContainerTypeMask;
UpdateQuickPropertiesAndCountsL( type, aProperties, aQuickProperties, countsBuf );
_LIT( KMyCounts, "myCounts" );
iCustomBehaviorProvider.LogCounts( KMyCounts, countsBuf );
PutRowUpdatesL();
if( aParentId != KUncommittedContainers && aParentId != KContainerInvalidId )
{
SeekL( aParentId );
IncrementParentCountsL( countsBuf );
} // end if
CleanupStack::PopAndDestroy( &countsBuf );
} // end CreateContainerL
// ==========================================================================
// FUNCTION: IncrementParentCountsL
// ==========================================================================
void CContainerStoreContainersTable::IncrementParentCountsL( const TDesC8& aCountsDelta )
{
__LOG_ENTER_SUPPRESS( "IncrementParentCountsL" )
PrepareRowForUpdateLC();
// Read old values.
TUint16 childrenCount = iTable.ColUint16( iChildrenCountColNum );
RBuf8 countsBuf;
CleanupClosePushL( countsBuf );
countsBuf.CreateL( iTable.ColDes8( iChildrenCountsColNum ) );
_LIT( KOldChildrenCounts, "oldChildrenCounts" );
iCustomBehaviorProvider.LogCounts( KOldChildrenCounts, countsBuf );
// Update values.
childrenCount++;
iCustomBehaviorProvider.IncrementParentCounts( countsBuf, aCountsDelta );
_LIT( KNewChildrenCounts, "newChildrenCounts" );
iCustomBehaviorProvider.LogCounts( KNewChildrenCounts, countsBuf );
// Write new values to database.
iTable.SetColL( iChildrenCountColNum, childrenCount );
iTable.SetColL( iChildrenCountsColNum, countsBuf );
CleanupStack::PopAndDestroy( &countsBuf );
PutRowUpdatesL();
} // end IncrementParentCountsL
// ==========================================================================
// FUNCTION: DecrementParentCountsL
// ==========================================================================
void CContainerStoreContainersTable::DecrementParentCountsL( const TDesC8& aCountsDelta )
{
__LOG_ENTER_SUPPRESS( "DecrementParentCountsL" )
PrepareRowForUpdateLC();
// Read old values.
TUint16 childrenCount = iTable.ColUint16( iChildrenCountColNum );
RBuf8 countsBuf;
CleanupClosePushL( countsBuf );
countsBuf.CreateL( iTable.ColDes8( iChildrenCountsColNum ) );
_LIT( KOldChildrenCounts, "oldChildrenCounts" );
iCustomBehaviorProvider.LogCounts( KOldChildrenCounts, countsBuf );
// Update values.
childrenCount--;
iCustomBehaviorProvider.DecrementParentCounts( countsBuf, aCountsDelta );
_LIT( KNewChildrenCounts, "newChildrenCounts" );
iCustomBehaviorProvider.LogCounts( KNewChildrenCounts, countsBuf );
// Write new values to database.
iTable.SetColL( iChildrenCountColNum, childrenCount );
iTable.SetColL( iChildrenCountsColNum, countsBuf );
CleanupStack::PopAndDestroy( &countsBuf );
PutRowUpdatesL();
} // end DecrementParentCountsL
// ==========================================================================
// FUNCTION: UpdateQuickPropertiesAndCountsL
// ==========================================================================
void CContainerStoreContainersTable::UpdateQuickPropertiesAndCountsL( TContainerId aType,
const TDesC8& aProperties,
RBuf8& aQuickProperties,
TDes8& aCounts )
{
__LOG_ENTER_SUPPRESS( "UpdateQuickPropertiesAndCountsL" )
aQuickProperties.SetLength( 0 );
iCustomBehaviorProvider.QuickPropertiesAndCountsL( aType,
aProperties,
aQuickProperties,
aCounts );
__LOG_WRITE8_FORMAT1_INFO( "aQuickProperties.Length()=%i", aQuickProperties.Length() )
if( aQuickProperties.Length() > 0 )
{
// The quick properties are not encrypted.
iUtils.WriteLongColumnL( iTable,
iQuickPropertiesColNum,
aQuickProperties );
}
else
{
// Clear the quick properties column.
iTable.SetColNullL( iQuickPropertiesColNum );
} // end if
_LIT( KMyCounts, "myCounts" );
iCustomBehaviorProvider.LogCounts( KMyCounts, aCounts );
iTable.SetColL( iCountsColNum, aCounts );
} // end UpdateQuickPropertiesAndCountsL
// ==========================================================================
// FUNCTION: DeleteL
// ==========================================================================
void CContainerStoreContainersTable::DeleteL()
{
iTable.DeleteL();
// This function is only called for objects that are already in the "to be deleted" folder hierarchy.
// There is no need to update the parent container since the parent container is also part of the
// "to be deleted" hierarchy.
} // end DeleteL
// ==========================================================================
// FUNCTION: MarkAsDeleteRetryL
// ==========================================================================
void CContainerStoreContainersTable::MarkAsDeleteRetryL()
{
PrepareRowForUpdateLC();
iTable.SetColL( iParentIdColNum, KToRetryDeleteContainers );
PutRowUpdatesL();
} // end MarkAsDeleteRetryL
// ==========================================================================
// FUNCTION: MarkForDeleteL
// ==========================================================================
void CContainerStoreContainersTable::MarkForDeleteL()
{
PrepareRowForUpdateLC();
iTable.SetColL( iParentIdColNum, KToBeDeletedContainers );
PutRowUpdatesL();
} // end MarkForDeleteL
// ==========================================================================
// FUNCTION: MoveL
// ==========================================================================
void CContainerStoreContainersTable::MoveL( TContainerId aNewParentId, TDes8& aTotalCountsDelta )
{
__LOG_ENTER( "MoveL" )
// Update the entry's parent ID.
TContainerId oldParentId = iTable.ColUint32( iParentIdColNum );
TUint length = iTable.ColLength( iQuickPropertiesColNum );
PrepareRowForUpdateLC();
iTable.SetColL( iParentIdColNum, aNewParentId );
PutRowUpdatesL();
RBuf8 myDescendentCounts;
CleanupClosePushL( myDescendentCounts );
myDescendentCounts.Create( iTable.ColLength( iChildrenCountsColNum ) );
ChildrenCountsL( myDescendentCounts, ETrue );
RBuf8 myCounts;
CleanupClosePushL( myCounts );
myCounts.CreateL( iTable.ColDes8( iCountsColNum ) );
_LIT( KMyCounts, "myCounts" );
iCustomBehaviorProvider.LogCounts( KMyCounts, myCounts );
iCustomBehaviorProvider.InitializeCounts( aTotalCountsDelta );
// Increment the new parent container's child counts.
if( aNewParentId != KToBeDeletedContainers )
{
SeekL( aNewParentId );
IncrementParentCountsL( myCounts );
}
else
{
// The item is being deleted. Decrement the total counts.
iCustomBehaviorProvider.DecrementParentCounts( aTotalCountsDelta, myCounts );
iCustomBehaviorProvider.DecrementParentCounts( aTotalCountsDelta, myDescendentCounts );
} // end if
// Decrement the old parent container's child counts.
if( oldParentId != KUncommittedContainers )
{
SeekL( oldParentId );
DecrementParentCountsL( myCounts );
}
else
{
// The item is being committed. Increment the total counts.
iCustomBehaviorProvider.IncrementParentCounts( aTotalCountsDelta, myCounts );
iCustomBehaviorProvider.IncrementParentCounts( aTotalCountsDelta, myDescendentCounts );
} // end if
_LIT( KaTotalCountsDelta, "aTotalCountsDelta" );
iCustomBehaviorProvider.LogCounts( KaTotalCountsDelta, aTotalCountsDelta );
CleanupStack::PopAndDestroy( &myCounts );
CleanupStack::PopAndDestroy( &myDescendentCounts );
__LOG_EXIT
} // end MoveL
// ==========================================================================
// FUNCTION: CopyL
// ==========================================================================
void CContainerStoreContainersTable::CopyL( TContainerId aNewId, TContainerId aDestinationId, RBuf8& aQuickProperties )
{
__LOG_ENTER( "Copy" )
// Copy properties.
RBuf8 propertiesBuf;
CleanupClosePushL( propertiesBuf );
ReadPropertiesColumnL( propertiesBuf );
CreateContainerL( aNewId, aDestinationId, propertiesBuf, aQuickProperties );
CleanupStack::PopAndDestroy( &propertiesBuf );
__LOG_EXIT
} // end CopyL
// ==========================================================================
// FUNCTION: ChildrenCountsL
// ==========================================================================
void CContainerStoreContainersTable::ChildrenCountsL( TDes8& aCounts, TBool aRecursive )
{
if ( !aRecursive )
{
aCounts.Copy( iTable.ColDes8( iChildrenCountsColNum ) );
}
else
{
RBuf8 totalCounts;
CleanupClosePushL( totalCounts );
RBuf8 childrenCounts;
CleanupClosePushL( childrenCounts );
TContainerId id = iTable.ColUint32( iIdColNum );
totalCounts.CreateL( iTable.ColLength( iCountsColNum ) );
iCustomBehaviorProvider.InitializeCounts( totalCounts );
childrenCounts.CreateL( iTable.ColDes8(iChildrenCountsColNum) );
iCustomBehaviorProvider.IncrementParentCounts( totalCounts, childrenCounts );
TDbBookmark bookmark = iTable.Bookmark();
RArray<TContainerId> childrens;
CleanupClosePushL( childrens );
ListChildrenL( childrens, id, EMsgStoreFolderBits, ETrue );
for ( int i = 0 ; i < childrens.Count() ; i++ )
{
iTable.SeekL( childrens[i] );
iTable.GetL();
childrenCounts.Copy( iTable.ColDes8(iChildrenCountsColNum) );
iCustomBehaviorProvider.IncrementParentCounts( totalCounts, childrenCounts );
}
aCounts.Copy( totalCounts );
iTable.GotoL( bookmark );
CleanupStack::PopAndDestroy( &childrens );
CleanupStack::PopAndDestroy( &childrenCounts );
CleanupStack::PopAndDestroy( &totalCounts );
}
} // end ChildrenCountsL
// ==========================================================================
// FUNCTION: UpdatePropertiesL
// ==========================================================================
void CContainerStoreContainersTable::UpdatePropertiesL( const TDesC8& aProperties,
RBuf8& aQuickProperties,
TDes8& aTotalCountsDelta,
TContainerId& aRealParentId )
{
__LOG_ENTER_SUPPRESS( "UpdatePropertiesL" )
RBuf8 newCountsBuf;
CleanupClosePushL( newCountsBuf );
RBuf8 oldCountsBuf;
CleanupClosePushL( oldCountsBuf );
PrepareRowForUpdateLC();
// Read the parent ID of the row.
aRealParentId = iTable.ColUint32( iParentIdColNum );
// Get the old counts.
oldCountsBuf.CreateL( iTable.ColDes8( iCountsColNum ) );
_LIT( KoldmyCountBuf, "old(my)CountBuf" );
iCustomBehaviorProvider.LogCounts( KoldmyCountBuf, oldCountsBuf );
// Update the properties column.
WritePropertiesColumnL( aProperties );
// Update the quick properties and counts columns.
TContainerId id = iTable.ColUint32( iIdColNum );
TContainerId type = (id & KContainerTypeMask);
newCountsBuf.CreateL( iCountsLength );
UpdateQuickPropertiesAndCountsL( type, aProperties, aQuickProperties, newCountsBuf );
_LIT(KnewmyCountBuf, "new(my)CountBuf" );
iCustomBehaviorProvider.LogCounts( KnewmyCountBuf, newCountsBuf );
PutRowUpdatesL();
// The total counts delta is the new counts minus the old counts.
aTotalCountsDelta.Copy( newCountsBuf );
iCustomBehaviorProvider.DecrementParentCounts( aTotalCountsDelta, oldCountsBuf );
_LIT( KaTotalCountsDelta, "aTotalCountsDelta" );
iCustomBehaviorProvider.LogCounts( KaTotalCountsDelta, aTotalCountsDelta );
if( aRealParentId != KUncommittedContainers )
{
SeekL( aRealParentId );
// Decrement the parent row's counts by the old count values.
DecrementParentCountsL( oldCountsBuf );
// Increment the parent row's counts by the new count values.
IncrementParentCountsL( newCountsBuf );
} // end if
CleanupStack::PopAndDestroy( &oldCountsBuf );
CleanupStack::PopAndDestroy( &newCountsBuf );
} // end UpdatePropertiesL
// ==========================================================================
// FUNCTION: UpdatePropertyL
// ==========================================================================
void CContainerStoreContainersTable::UpdatePropertyL( const TDesC8& aName,
TUint8 aType,
const TDesC8& aValue,
RBuf8& aQuickProperties,
TDes8& aTotalCountsDelta,
TContainerId& aRealParentId )
{
__LOG_ENTER_SUPPRESS( "UpdatePropertyL" )
RBuf8 propertiesBuf;
CleanupClosePushL( propertiesBuf );
ReadPropertiesColumnL( propertiesBuf );
// Look for an existing occurrence of the property.
TPropertiesSerializer serializer( propertiesBuf );
TBool found = serializer.Find( aName );
if( found )
{
// Property already exists. Replace the value length and value.
serializer.UpdateValueL( aValue );
}
else
{
// Add the property.
serializer.AddPropertyL( aName, aType, aValue );
} // end if
UpdatePropertiesL( propertiesBuf, aQuickProperties, aTotalCountsDelta, aRealParentId );
CleanupStack::PopAndDestroy( &propertiesBuf );
} // end UpdatePropertyL
// ==========================================================================
// FUNCTION: PropertiesL
// ==========================================================================
void CContainerStoreContainersTable::PropertiesL( RBuf8& aProperties )
{
ReadPropertiesColumnL( aProperties );
} // end PropertiesL
// ==========================================================================
// FUNCTION: PropertiesSizeL
// ==========================================================================
TUint CContainerStoreContainersTable::PropertiesSizeL( TContainerId aId )
{
SeekL( aId );
return iTable.ColLength( iPropertiesColNum );
} // end PropertiesSizeL
// ==========================================================================
// FUNCTION: QuickPropertiesL
// ==========================================================================
void CContainerStoreContainersTable::QuickPropertiesL( RBuf8& aQuickProperties )
{
// Quick properties are not encrypted
iUtils.ReadLongColumnL( iTable, iQuickPropertiesColNum, aQuickProperties );
} // end PropertiesL
// ==========================================================================
// FUNCTION: ListChildrenL
// ==========================================================================
void CContainerStoreContainersTable::ListChildrenL( RArray<TContainerId>& aChildren, TContainerId aId, TContainerId aType, TBool aRecursive )
{
__LOG_ENTER_SUPPRESS( "ListChildrenL" )
aChildren.Reset();
const TUint bufSsize = 200;
TBuf<bufSsize> queryString;
queryString.Copy( KSelect );
queryString.Append( KContainersTableIdCol );
// Only need the children count if this is a recursive search.
if( aRecursive )
{
queryString.Append( KComma );
queryString.Append( KContainersTableChildrenCountCol );
} // end if
queryString.Append( KFrom );
queryString.Append( KContainersTableName );
queryString.Append( KWhere );
// If the requested type isn't "any", then narrow down the query.
if( aType != KContainerTypeAny )
{
const TContainerId lowestId = aType;
const TContainerId highestId = (aType | ~KContainerTypeMask );
queryString.Append( KContainersTableIdCol );
queryString.Append( KGreaterThanOrEqualTo );
queryString.AppendNum( lowestId );
queryString.Append( KAnd );
queryString.Append( KContainersTableIdCol );
queryString.Append( KLessThanOrEqualTo );
queryString.AppendNum( highestId );
queryString.Append( KAnd );
} // end if
queryString.Append( KContainersTableParentIdCol );
queryString.Append( KEqualTo );
TInt queryLengthWithoutId = queryString.Length();
RDbView view;
CleanupClosePushL( view );
const TUint granularity = 25;
RArray<TContainerId> toBeSearched( granularity );
CleanupClosePushL( toBeSearched );
toBeSearched.Append( aId );
const TInt idColNum = 1;
const TInt childrenCountColNum = 2;
while( toBeSearched.Count() > 0 )
{
// Update the query to query the next ID to be searched.
queryString.SetLength( queryLengthWithoutId );
queryString.AppendNum( toBeSearched[0] );
toBeSearched.Remove( 0 );
if ( aType == EMsgStorePartBits )
{
//must sort the message parts by containerId in ascending order
// to preserve the same order as they are created
queryString.Append( KOrderBy );
queryString.Append( KContainersTableIdCol );
queryString.Append( KAsc );
__LOG_WRITE_INFO("Using order by in query");
}
iUtils.PopulateViewL( view, queryString );
TBool found = view.FirstL();
// Add the IDs in the view to the children array.
while( found )
{
view.GetL();
TUint32 cid = view.ColUint32( idColNum );
__LOG_WRITE_FORMAT1_INFO("Id=%x", cid);
aChildren.Append( cid );
// Search the container for children if this a recursive search and the child count is
// greater than 0.
if( aRecursive && ( view.ColUint32( childrenCountColNum ) > 0 ) )
{
toBeSearched.Append( view.ColUint32( idColNum ) );
} // end if
found = view.NextL();
} // end while
// Most close old view before preparing new one, otherwise a memory leak occurs.
view.Close();
} // end while
CleanupStack::PopAndDestroy( &toBeSearched );
CleanupStack::PopAndDestroy( &view );
} // end ListChildrenL
// ==========================================================================
// FUNCTION: EncryptFirstL
// ==========================================================================
TBool CContainerStoreContainersTable::EncryptFirstL( TDbBookmark& aNextRow )
{
__LOG_ENTER_SUPPRESS("EncryptFirstL")
TBool found = iUtils.FindFirstEncryptedOrUnencryptedL( iTable, KContainersTableIsRowEncryptedCol, EFalse, aNextRow );
return found;
}
// ==========================================================================
// FUNCTION: EncryptNextL
// ==========================================================================
TBool CContainerStoreContainersTable::EncryptNextL( TDbBookmark& aNextRow, TContainerId& aEncryptedContainerId )
{
__LOG_ENTER_SUPPRESS("EncryptNextL")
TBool hasMore = EFalse;
TContainerId id = KContainerInvalidId;
TRAPD( err, id = GotoL( aNextRow ) );
if ( err == KErrNotFound )
{
hasMore = EncryptFirstL( aNextRow );
}
else if ( err != KErrNone )
{
User::Leave( err );
}
else
{
if ( !IsEncrypted() )
{
RBuf8 propertyBuf;
CleanupClosePushL( propertyBuf );
//read the unencrypted properties and write the enctypted properties back
ReadUnencryptedPropertiesColumnL( propertyBuf );
PrepareRowForUpdateLC();
EncryptAndWritePropertiesColumnL( propertyBuf );
//update the encrypted flag
SetEncryptedL( ETrue );
PutRowUpdatesL();
CleanupStack::PopAndDestroy( &propertyBuf );
//set the encryptedConteinerId so that the caller can encrypt its content
aEncryptedContainerId = id;
}
hasMore = iTable.NextL();
if ( hasMore )
{
__LOG_WRITE_INFO("hasMore is TRUE")
aNextRow = iTable.Bookmark();
}
}
return hasMore;
}
// ==========================================================================
// FUNCTION: DecryptFirstL
// ==========================================================================
TBool CContainerStoreContainersTable::DecryptFirstL( TDbBookmark& aNextRow )
{
__LOG_ENTER("DecryptFirstL")
TBool found = iUtils.FindFirstEncryptedOrUnencryptedL( iTable, KContainersTableIsRowEncryptedCol, ETrue, aNextRow );
__LOG_EXIT
return found;
}
// ==========================================================================
// FUNCTION: DecryptNextL
// ==========================================================================
TBool CContainerStoreContainersTable::DecryptNextL( TDbBookmark& aNextRow, TContainerId& aDecryptedContainerId )
{
__LOG_ENTER_SUPPRESS("DecryptNextL")
TBool hasMore = EFalse;
TContainerId id = KContainerInvalidId;
TRAPD( err, id = GotoL( aNextRow ) );
if ( err == KErrNotFound )
{
hasMore = DecryptFirstL( aNextRow );
}
else if ( err != KErrNone )
{
User::Leave( err );
}
else
{
if ( IsEncrypted() )
{
RBuf8 propertyBuf;
CleanupClosePushL( propertyBuf );
//the row is currentlly encryptted
//read the encrypted properties and write the unenctypted properties back
ReadAndDescrptPropertiesColumnL( propertyBuf );
PrepareRowForUpdateLC();
WriteUnencryptedPropertiesColumnL( propertyBuf );
//update the encrypted flag
SetEncryptedL( EFalse );
PutRowUpdatesL();
CleanupStack::PopAndDestroy( &propertyBuf );
//set the aDecryptedContainerId so that the caller can decrypt its content
aDecryptedContainerId = id;
}
hasMore = iTable.NextL();
if ( hasMore )
{
__LOG_WRITE_INFO("hasMore is TRUE")
aNextRow = iTable.Bookmark();
}
}
return hasMore;
}
// ==========================================================================
// FUNCTION: ReadAndDescrptPropertiesColumnL
// ==========================================================================
void CContainerStoreContainersTable::ReadAndDescrptPropertiesColumnL( RBuf8& aProperties )
{
__LOG_ENTER_SUPPRESS( "ReadPropertiesColumnL" )
RBuf8 encryptedBuffer;
CleanupClosePushL( encryptedBuffer );
iUtils.ReadLongColumnL( iTable, iPropertiesColNum, encryptedBuffer );
if( aProperties.Length() < encryptedBuffer.Length() )
{
aProperties.ReAllocL( encryptedBuffer.Length() );
} // end if
if( encryptedBuffer.Length() > 0 )
{
iEncryption.DecryptL( encryptedBuffer, aProperties );
iEncryption.RemovePaddingL( aProperties );
} // end if
CleanupStack::PopAndDestroy( &encryptedBuffer );
}
// ==========================================================================
// FUNCTION: EncryptAndWritePropertiesColumnL
// ==========================================================================
void CContainerStoreContainersTable::EncryptAndWritePropertiesColumnL( const TDesC8& aProperties )
{
__LOG_ENTER_SUPPRESS( "EncryptAndWritePropertiesColumnL" )
if ( aProperties.Length() > 0 )
{
RBuf8 encryptedBuffer;
encryptedBuffer.CreateL( aProperties.Length() + iEncryption.BlockSizeL() );
CleanupClosePushL( encryptedBuffer );
RBuf8 paddedBuffer;
paddedBuffer.CreateL( aProperties.Length() + iEncryption.BlockSizeL() );
CleanupClosePushL( paddedBuffer );
paddedBuffer.Copy( aProperties );
iEncryption.AddPaddingL( paddedBuffer, iEncryption.BlockSizeL() );
iEncryption.EncryptL( paddedBuffer, encryptedBuffer );
CleanupStack::PopAndDestroy( &paddedBuffer );
iUtils.WriteLongColumnL( iTable, iPropertiesColNum, encryptedBuffer );
CleanupStack::PopAndDestroy( &encryptedBuffer );
}
else
{
iTable.SetColNullL( iPropertiesColNum );
}
}
// ==========================================================================
// FUNCTION: ReadUnencryptedPropertiesColumnL
// ==========================================================================
void CContainerStoreContainersTable::ReadUnencryptedPropertiesColumnL( RBuf8& aProperties )
{
iUtils.ReadLongColumnL( iTable, iPropertiesColNum, aProperties );
}
// ==========================================================================
// FUNCTION: WriteUnencryptedPropertiesColumnL
// ==========================================================================
void CContainerStoreContainersTable::WriteUnencryptedPropertiesColumnL( const TDesC8& aProperties )
{
iUtils.WriteLongColumnL( iTable, iPropertiesColNum, aProperties );
}
// ==========================================================================
// FUNCTION: IsEncrypted
// ==========================================================================
TBool CContainerStoreContainersTable::IsEncrypted()
{
TBool isEncrypted = static_cast<TBool>( iTable.ColUint8( iIsRowEncryptedColNum ) );
return isEncrypted;
}
// ==========================================================================
// FUNCTION: SetEncryptedL
// ==========================================================================
void CContainerStoreContainersTable::SetEncryptedL( TBool aIsEncrypted )
{
iTable.SetColL( iIsRowEncryptedColNum, static_cast<TUint8>(aIsEncrypted) );
}