diff -r cd501b96611d -r ece3df019add authenticationservices/authenticationserver/source/server/authdb.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/authenticationservices/authenticationserver/source/server/authdb.cpp Tue Nov 24 09:06:03 2009 +0200 @@ -0,0 +1,937 @@ +/* +* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: +* CAuthDb Authentication server data store implementation +* +*/ + + +/** + @file +*/ + +#include "authserver_impl.h" + +using namespace AuthServer; + +// The number of decimal digits needed to represent a 32 bit unsigned integer +const TInt KUint32Digits = 10; + +// -------- DB helper functions -------- + + +static void RollbackDb(TAny* aPtr) +/** + Implements the TCleanupOperation prototype. This + function is used to rollback a database transaction + if a leave occurs before it is committed. + + @param aPtr Pointer to RDbDatabase object + to roll back. + @see CleanupRollbackPushL + */ + { + RDbDatabase* db = static_cast(aPtr); + if (db->InTransaction()) + db->Rollback(); + } + + +inline void CleanupRollbackPushL(RDbDatabase& aDb) +/** + Puts the supplied database on the cleanup stack. + The database is rolled back if a leave occurs. + + If a leave does not occur then the supplied database + should be committed. Do not call CleanupStack::PopAndDestroy + to delete this object. + + @param aDb Database to roll back if + a leave occurs. + */ + { + CleanupStack::PushL(TCleanupItem(RollbackDb, &aDb)); + } + + +static void StartTransactionLC(RDbDatabase& aDb) +/** + Helper function starts a database transaction and + puts a rollback cleanup item on the cleanup stack. + + @param aDb Database to start transaction on. + @see CommitTransactionLD + */ + { + User::LeaveIfError(aDb.Begin()); + CleanupRollbackPushL(aDb); + } + + +static void CommitTransactionLD(RDbDatabase& aDb) +/** + Complements StartTransactionLC by removing the + the rollback cleanup item from the cleanup stack + and committing the database. + + @see StartTransactionLC + */ + { + CleanupStack::Pop(&aDb); + User::LeaveIfError(aDb.Commit()); + } + + +// -------- factory functions -------- + + +CAuthDb2* CAuthDb2::NewL(RFs& aFs) +/** + Factory function allocates a new instance of CAuthDb. + The database file is created if it does not already exist. + + @return New instance of CAuthDb. + */ + { + CAuthDb2* self = CAuthDb2::NewLC(aFs); + CleanupStack::Pop(self); + return self; + } + + +CAuthDb2* CAuthDb2::NewLC(RFs& aFs) +/** + Factory function allocates new instance of CAuthDb2, + putting it on the cleanup stack. The database file + is created if it does not already exist. + + @return New instance of CAuthDb. + */ + { + CAuthDb2* self = new(ELeave) CAuthDb2; + CleanupStack::PushL(self); + self->ConstructL(aFs); + return self; + } + + +void CAuthDb2::ConstructL(RFs& aFs) +/** + This second-phase constructor opens the + database file, creating it if it does not + already exist. + */ + { + TInt r; + TFileName dbName(KDbName); + dbName[0] = RFs::GetSystemDriveChar(); + + r = OpenDbFileL(aFs, dbName); + + if (r == KErrNone) + { + if (! iAuthDbFile.IsDamaged() || iAuthDbFile.Recover() == KErrNone) + return; + } + + User::LeaveIfError(iAuthDbFile.Replace(aFs, dbName)); + iIsDbOpen = ETrue; + StartTransactionLC(iAuthDbFile); + + // These commands are stored as narrow instead of wide + // text to save c. 500 bytes in decompressed exe size. + // The non-XIP EXE size is almost the same because DEFLATE + // is used on the ELF file. + + static const TText8*const cmds[] = + { + _S8("CREATE TABLE Identities (idName COUNTER, IdentityId UNSIGNED INTEGER NOT NULL, Description VARCHAR(255) NOT NULL)"), + _S8("CREATE UNIQUE INDEX idIndex ON Identities (idName)"), + _S8("CREATE UNIQUE INDEX identityIdx ON Identities (IdentityId DESC)"), + _S8("CREATE TABLE Prefs (PluginType UNSIGNED INTEGER NOT NULL, PluginId UNSIGNED INTEGER NOT NULL)"), + _S8("CREATE UNIQUE INDEX typeIdx ON Prefs (PluginType ASC)"), + _S8("CREATE TABLE TrainedPlugins (IdentityId UNSIGNED INTEGER NOT NULL, PluginId UNSIGNED INTEGER NOT NULL, TransientKey LONG VARBINARY NOT NULL)"), + _S8("CREATE UNIQUE INDEX identityPluginIdx ON TrainedPlugins (IdentityId DESC, PluginId ASC)") + }; + + const TInt elemCount = sizeof(cmds) / sizeof(cmds[0]); + TBuf<140> cmd; + for (TInt i = 0; i < elemCount; ++i) + { + TPtrC8 cmd8(cmds[i]); + cmd.Copy(cmd8); + User::LeaveIfError(iAuthDbFile.Execute(cmd)); + } + + CommitTransactionLD(iAuthDbFile); + } + + +CAuthDb2::~CAuthDb2() +/** + Close the database file used by this object. + */ + { + CloseDbFile(); + } + +TInt CAuthDb2::OpenDbFileL(RFs& aFs, const TFileName& aDbName) + { + + TInt r(0); + if(!iIsDbOpen) + { + r = iAuthDbFile.Open(aFs, aDbName); + if(KErrNone == r) + { + iIsDbOpen = ETrue; + } + else if (KErrNotFound != r) + { + User::Leave(r); + } + } + return r; + } + +void CAuthDb2::CloseDbFile() + { + if(iIsDbOpen) + { + RollbackDb(&iAuthDbFile); + if(iAuthDbFile.IsDamaged()) + { + iAuthDbFile.Recover(); + } + iAuthDbFile.Close(); + iIsDbOpen = EFalse; + } + } + +// -------- identities -------- + + +void CAuthDb2::AddIdentityWithTrainedPluginL( + TIdentityId aIdentityId, const TDesC& aDesc, + const CTransientKeyInfo& aTransKeyInfo) +/** + Adds an identity and trains a plugin for it in a single + atomic operation. + + @param aIdentityId New identity. + @param aDesc Identity's description. This must + have no more than KMaxDescLen characters. + @param aTransKeyInfo A transient key which trains this identity + for a plugin. + @leave KErrAuthServIdentityAlreadyExists The supplied identity + is already in the database. + */ + { + StartTransactionLC(iAuthDbFile); + + AddIdentityL(aIdentityId, aDesc); + + SetTrainedPluginL(aIdentityId, aTransKeyInfo.PluginId(), aTransKeyInfo); + + CommitTransactionLD(iAuthDbFile); + } + + +void CAuthDb2::AddIdentityL(TIdentityId aIdentityId, const TDesC& aDesc) +/** + Add the supplied identity to the database. + + @param aIdentityId New identity. + @param aDesc Identity's description. This must + have no more than KMaxDescLen characters. + @leave KErrAuthServDescTooLong The supplied description is more than + 255 characters. + @leave KErrAuthServIdentityAlreadyExists The supplied identity + is already in the database. + */ + { + if (aDesc.Length() > KMaxDescLen) + User::Leave(KErrAuthServDescTooLong); + + RDbTable table; + + // EUpdatable instead of EInsertOnly so can navigate to any + // existing row. + if (FindIdentityLC(table, RDbView::EUpdatable, aIdentityId)) + User::Leave(KErrAuthServIdentityAlreadyExists); + + table.InsertL(); // start automatic transaction + table.SetColL(KIdentitiesIdentityIdCol, aIdentityId); + table.SetColL(KIdentitiesDescCol, aDesc); + table.PutL(); // end automatic transaction + + CleanupStack::PopAndDestroy(&table); + } + + +void CAuthDb2::RemoveIdentityL(TIdentityId aIdentityId) +/** + Remove the supplied identity from the auth server's database. + Any trained entries for the supplied identity are also removed. + All updates to the database happen within a single transaction. + + @param aIdentityId Identity to remove from database; + @leave KErrAuthServIdentityNotFound The supplied identity could + not be found in the database. + */ + { + StartTransactionLC(iAuthDbFile); + + RDbTable table; + FindExistingIdentityLC(table, RDbView::EUpdatable, aIdentityId); + table.DeleteL(); + CleanupStack::PopAndDestroy(&table); + + // remove each training record for this identity + _LIT(KDelTrainFmt, "DELETE FROM TrainedPlugins WHERE IdentityId=%u"); + TBuf<(46 - 2) + 10> bufCmd; + bufCmd.Format(KDelTrainFmt, aIdentityId); + iAuthDbFile.Execute(bufCmd); + + CommitTransactionLD(iAuthDbFile); + } + + +TInt CAuthDb2::NumIdentitiesL() + /** + Retrieve the number of identities in the database. + @return the number of identities in the database. + */ + { + TInt result = 0; + RDbTable table; + OpenTableLC(table, KIdentitiesTableName, RDbRowSet::EReadOnly, KIdentitiesIndex); + result = table.CountL(); + CleanupStack::PopAndDestroy(&table); + return result; + } + +void CAuthDb2::IdentitiesL(RArray& aResults) +/** + Populate the supplied array with the currently + registered identities. + + @param aResults On success this array is populated + with the currently registered identities. + Any items which were in the array when + this function is called are removed. On + failure this array is emptied so the caller + does not have to place it on the cleanup stack. + */ + { + aResults.Reset(); + CleanupClosePushL(aResults); + + RDbTable table; + OpenTableLC(table, KIdentitiesTableName, RDbRowSet::EReadOnly, KIdIndexNum); + while (table.NextL()) + { + table.GetL(); + aResults.AppendL(table.ColUint32(KIdentitiesIdentityIdCol)); + } + + CleanupStack::PopAndDestroy(&table); + CleanupStack::Pop(&aResults); + } + +void CAuthDb2::IdentitiesWithDescriptionL(RIdAndStringArray& aList) +/** + Populate the supplied array with the currently + registered identities and descriptions. + + @param aList On success this array is populated + with the currently registered identities. + Any items which were in the array when + this function is called are removed. On + failure this array is emptied so the caller + does not have to place it on the cleanup stack. + */ + { + aList.Reset(); + CleanupClosePushL(aList); + + RDbTable table; + OpenTableLC(table, KIdentitiesTableName, RDbRowSet::EReadOnly, KIdentitiesIndex); + while (table.NextL()) + { + table.GetL(); + CIdAndString* id = + CIdAndString::NewLC(table.ColUint32(KIdentitiesIdentityIdCol), + table.ColDes(KIdentitiesDescCol)); + aList.AppendL(id); + CleanupStack::Pop(id); + } + + CleanupStack::PopAndDestroy(&table); + CleanupStack::Pop(&aList); + } + +HBufC* CAuthDb2::DescriptionL(TIdentityId aIdentityId) +/** + Allocate a descriptor containing the supplied identity's + description. + + @param aIdentityId Identity whose description is returned. + @return Newly-allocated descriptor containing the + identity's description. The client must + free this object. + @leave KErrAuthServIdentityNotFound The supplied identity could + not be found in the database. + */ + { + RDbTable table; + FindExistingIdentityLC(table, RDbView::EReadOnly, aIdentityId); + + table.GetL(); + HBufC* retDesc = table.ColDes(KIdentitiesDescCol).AllocL(); + + CleanupStack::PopAndDestroy(&table); + return retDesc; + } + + + +void CAuthDb2::SetDescriptionL(TIdentityId aIdentityId, const TDesC& aDesc) +/** + Update an identity's description. + + @param aIdentityId Identity to update. + @param aDesc New description text. This must have + no more than KMaxDescLen characters. + @leave KErrAuthServIdentityNotFound The supplied identity could + not be found in the database. + */ + { + if (aDesc.Length() > KMaxDescLen) + User::Leave(KErrAuthServDescTooLong); + + RDbTable table; + FindExistingIdentityLC(table, RDbView::EUpdatable, aIdentityId); + + table.UpdateL(); // start automatic transaction + table.SetColL(KIdentitiesDescCol, aDesc); + table.PutL(); // end automatic transaction + + CleanupStack::PopAndDestroy(&table); + } + + +void CAuthDb2::FindExistingIdentityLC( + RDbTable& aTable, RDbRowSet::TAccess aAccess, TIdentityId aIdentityId) +/** + Find the supplied identity and navigate to it. + On success, the table handle is on the cleanup stack. + + @param aTable Caller's table handle. + @param aAccess Mode in which to open the handle. + @param aIdentityId Identity to navigate to. + @leave KErrAuthServIdentityNotFound The supplied identity could + not be found. + */ + { + TBool found = FindIdentityLC(aTable, aAccess, aIdentityId); + if (! found) + User::Leave(KErrAuthServIdentityNotFound); + } + + +TBool CAuthDb2::FindIdentityLC(RDbTable& aTable, RDbRowSet::TAccess aAccess, TIdentityId aIdentityId) +/** + Navigate to the supplied identity in the Identities table. + On success, the table handle is on the cleanup stack. + + @param aTable Caller's table handle. + @param aAccess Mode in which to open the table. + @param aIdentityId Identity to navigate to. + @return Zero if could not find identity in table; + Non-zero otherwise. + */ + { + TBool found = OpenTableAndNavigateLC( + aTable, KIdentitiesTableName, aAccess, KIdentitiesIndex, aIdentityId); + + return found; + } + + +// -------- plugins -------- + +TInt CAuthDb2::NumTrainedPluginsL(TIdentityId aId) +/** + Retrieve the number of trained plugins for the specified id. + + @param aId the identity for whom to retrieve the number of trained plugins. + @return the number of trained plugins for the specified id. + */ + { + _LIT(KGetTrainedFmt, "SELECT IdentityId FROM TrainedPlugins WHERE IdentityId=%u"); + TBuf<(57 - 2) + 10> bufCmd; + bufCmd.Format(KGetTrainedFmt, aId); + + TDbQuery q(bufCmd); + RDbView viewTp; + CleanupClosePushL(viewTp); + User::LeaveIfError(viewTp.Prepare(iAuthDbFile, q)); + User::LeaveIfError(viewTp.EvaluateAll()); + TInt trainedCount = viewTp.CountL(); + CleanupStack::PopAndDestroy(&viewTp); + + return trainedCount; + } + +/** + Returns list of plugins that are trained for the given identity + + @param aIdentityId The identity for whom to retrieve the list of trained plugins. + @param aTrainedPlugins The array to fill the returned plugin ids. +*/ +void CAuthDb2::TrainedPluginsListL(TIdentityId aIdentityId, RArray& aTrainedPlugins) + { + _LIT(KGetTrainedFmt, "SELECT PluginId FROM TrainedPlugins WHERE IdentityId=%u"); + RBuf queryBuf; + CleanupClosePushL(queryBuf); + queryBuf.CreateL(KGetTrainedFmt().Length() + KUint32Digits); + queryBuf.Format(KGetTrainedFmt, aIdentityId); + + TDbQuery query(queryBuf); + RDbView viewTp; + CleanupClosePushL(viewTp); + User::LeaveIfError(viewTp.Prepare(iAuthDbFile, query)); + User::LeaveIfError(viewTp.EvaluateAll()); + + if (viewTp.FirstL()) + { + do + { + viewTp.GetL(); + aTrainedPlugins.AppendL(viewTp.ColUint32(1)); + } + while (viewTp.NextL()); + } + CleanupStack::PopAndDestroy(2, &queryBuf); // viewTp + } + +TAuthTrainingStatus CAuthDb2::PluginStatusL(TPluginId aPluginId) +/** + Return the supplied plugin's training status. + + EAuthUntrained No identities have been trained for this plugin. + EAuthTrained Some (but not all) identities have been trained for this plugin + EAuthFullyTrained All identities have been trained for this plugin. + + @param aPluginId Plugin whose status should be retrieved. + @return The plugin's training status. + */ + { + // get number of identities trained for this plugin + + // This involves filtering all trainings for this plugin + // from the TrainedPlugins table. For small numbers of users + // it is simpler to do this; for large numbers of users + // (registered identities) it may be better to maintain another + // table which matches each plugin against its training count. + + _LIT(KGetTrainedFmt, "SELECT IdentityId FROM TrainedPlugins WHERE PluginId=%u"); + TBuf<(55 - 2) + 10> bufCmd; + bufCmd.Format(KGetTrainedFmt, aPluginId); + + TDbQuery q(bufCmd); + RDbView viewTp; + CleanupClosePushL(viewTp); + User::LeaveIfError(viewTp.Prepare(iAuthDbFile, q)); + User::LeaveIfError(viewTp.EvaluateAll()); + TInt trainCount = viewTp.CountL(); + CleanupStack::PopAndDestroy(&viewTp); + + if (trainCount == 0) + return EAuthUntrained; + + // get total number of identities in the database + RDbTable tableId; + OpenTableLC(tableId, KIdentitiesTableName, RDbRowSet::EReadOnly, KIdentitiesIndex); + TInt idCount = tableId.CountL(); + CleanupStack::PopAndDestroy(&tableId); + + return (trainCount < idCount) ? EAuthTrained : EAuthFullyTrained; + } + + +// -------- preferences -------- + + +void CAuthDb2::SetPreferredPluginL(TAuthPluginType aPluginType, TPluginId aPluginId) +/** + Set the preferred plugin for the supplied plugin type. + + If the type already has a preferred plugin type, its entry is + updated. Otherwise, a new entry is created. + + @param aPluginType Type of plugin to associate with a specific + plugin ID. + @param aPluginId Specific plugin to use for the plugin type. + */ + { + RDbTable table; + + // start automatic transaction + if (FindPrefLC(table, RDbRowSet::EUpdatable, aPluginType)) + table.UpdateL(); + else + table.InsertL(); + + table.SetColL(KPrefsTypeCol, (TUint) aPluginType); + table.SetColL(KPrefsIdCol, (TUint) aPluginId); + table.PutL(); // end automatic transaction + + CleanupStack::PopAndDestroy(&table); + } + + +void CAuthDb2::ClearPreferredPluginL(TAuthPluginType aPluginType) +/** + Remove and preferred plugin ID for the supplied plugin type. + + If the supplied plugin type does not have a preferred plugin + then the database is not modified. + + @param aPluginType Type of plugin to remove from the + Prefs table. + */ + { + RDbTable table; + if (FindPrefLC(table, RDbRowSet::EUpdatable, aPluginType)) + table.DeleteL(); + + CleanupStack::PopAndDestroy(&table); + } + + +TPluginId CAuthDb2::PreferredPluginL(TAuthPluginType aPluginType) +/** + Retrieve the preferred plugin for the supplied plugin type. + If the plugin type does not have a preferred plugin this function + returns KUnknownPluginId. + + @param aPluginType Plugin type to find preferred plugin for. + @return Preferred plugin for aPluginType. This is + KUnknownPluginId if the type does not + have a preferred plugin. + */ + { + TPluginId pluginId; + + RDbTable table; + if (! FindPrefLC(table, RDbRowSet::EReadOnly, aPluginType)) + pluginId = KUnknownPluginId; + else + { + table.GetL(); + pluginId = static_cast(table.ColUint(KPrefsIdCol)); + } + + CleanupStack::PopAndDestroy(&table); + return pluginId; + } + + +TBool CAuthDb2::FindPrefLC(RDbTable& aTable, RDbRowSet::TAccess aAccess, TAuthPluginType aPluginType) +/** + Open the Prefs table and navigate to the supplied plugin type. + On success the table handle is placed on the cleanup stack. + + @param aTable Table handle to open. On success this + is placed on the cleanup stack. + @param aAccess Mode in which the table should be opened. + @param aPluginType Plugin type to navigate to. + @return Zero if could not find plugin type; + Non-zero otherwise. + */ + { + return OpenTableAndNavigateLC(aTable, KPrefsTableName, aAccess, KPrefsTypeIndex, aPluginType); + } + + +// -------- trained plugins -------- + + +void CAuthDb2::SetTrainedPluginL( + TIdentityId aIdentityId, TPluginId aPluginId, const CTransientKeyInfo& aTransKeyInfo) +/** + Sets the transient key for the supplied identity, plugin pair. + + If the identity has already been trained for this plugin + then the existing record is replaced. + + @param aIdentityId Identity to update. + @param aPluginId Plugin to associate with identity. + @param aTransKeyInfo The salt and encrypted protection key + for this identity / plugin pair. + @leave KErrAuthServIdentityNotFound The supplied identity has + not been registered. + */ + { + RDbTable table; + + TBool update = FindTrainedPluginLC(table, RDbRowSet::EUpdatable, aIdentityId, aPluginId); + + // start automatic transaction + if (update) + { + table.UpdateL(); + } + else + { + CheckIdentityRegisteredL(aIdentityId); + table.InsertL(); + } + + table.SetColL(KTpIdentityIdCol, (TUint) aIdentityId); + table.SetColL(KTpPluginIdCol, (TUint) aPluginId); + + RDbColWriteStream dbcws; + dbcws.OpenLC(table, KTpTransientKeyCol); + aTransKeyInfo.ExternalizeL(dbcws); + dbcws.CommitL(); + CleanupStack::PopAndDestroy(&dbcws); + table.PutL(); + + CleanupStack::PopAndDestroy(&table); + } + + +void CAuthDb2::RemoveTrainedPluginL(TIdentityId aIdentityId, TPluginId aPluginId) +/** + Remove the transient key info (i.e. the encrypted protection key + and its salt) for the supplied identity, plugin pair. + + @param aIdentityId Identity which should be trained for + the supplied plugin. + @param aPluginId Plugin which should be trained for the + supplied identity. + @leave KErrAuthServTrainingNotFound Attempted to remove an + identity, plugin pair which was not in the + trained plugins table. + */ + { + RDbTable table; + TBool found = FindTrainedPluginLC(table, RDbRowSet::EUpdatable, aIdentityId, aPluginId); + + if (! found) + User::Leave(KErrAuthServTrainingNotFound); + + table.DeleteL(); + CleanupStack::PopAndDestroy(&table); + } + + +CTransientKeyInfo* CAuthDb2::KeyInfoL(TIdentityId aIdentity, TPluginId aPluginId) +/** + Retrieve the transient key associated with the supplied identity, + plugin pair. + + @param aIdentity Identity to search for. + @param aPluginId Plugin which should be registered + with the supplied identity. + @return Transient key info, including encrypted + protection key, associated with identity, + plugin pair. + @leave KErrAuthServTrainingNotFound There was no transient key + information for the supplied identity, + plugin pair. + */ + { + RDbTable table; + TBool found = FindTrainedPluginLC(table, RDbRowSet::EReadOnly, aIdentity, aPluginId); + if (! found) + User::Leave(KErrAuthServTrainingNotFound); + + table.GetL(); + RDbColReadStream dbcrs; + dbcrs.OpenLC(table, KTpTransientKeyCol); + CTransientKeyInfo* keyInfo = CTransientKeyInfo::NewL(dbcrs); + + CleanupStack::PopAndDestroy(2, &table); // dbcrs, table + return keyInfo; + } + + +TBool CAuthDb2::FindTrainedPluginLC( + RDbTable& aTable, RDbRowSet::TAccess aAccess, + TIdentityId aIdentityId, TPluginId aPluginId) +/** + Helper function for SetTrainedPluginL and ClearTrainedPluginL. + This function opens the TrainedPlugins table and navigates to + the supplied identity, plugin pair if they are present. + + @param aTable Table handle to open. + @param aAccess Mode in which to open the table. + @param aIdentityId Identity to navigate to. + @param aPluginId Plugin to navigate to. + @return Zero if could not navigate to the + identity, plugin ID pair; non-zero + otherwise. + */ + { + OpenTableLC(aTable, KTpTableName, aAccess, KTpIndex); + + TDbSeekMultiKey<2> dbsmk; + dbsmk.Add((TUint) aIdentityId); + dbsmk.Add((TUint) aPluginId); + return aTable.SeekL(dbsmk); + } + + +// -------- helper functions -------- + + +TBool CAuthDb2::OpenTableAndNavigateLC( + RDbTable& aTable, const TDesC& aTableName, RDbRowSet::TAccess aAccess, + const TDesC& aIndexName, TUint aKey) +/** + Open the described table and navigate to the identified row. + + @param aTable Caller's table handle. On success + this is placed on the cleanup stack. + @param aTableName Table to open in auth db. + @param aAccess Mode to open table in. + @param aIndexName Index to use for navigating. + @param aKey Key to find in database. + @return Zero if could not find row in table; + Non-zero otherwise. + */ + { + OpenTableLC(aTable, aTableName, aAccess, aIndexName); + + TDbSeekKey seekKey((TUint)aKey); // from TUint32 + return aTable.SeekL(seekKey); + } + + +void CAuthDb2::OpenTableLC( + RDbTable& aTable, const TDesC& aTableName, + RDbRowSet::TAccess aAccess, const TDesC& aIndexName) +/** + Open the named table in the supplied access mode, + and use the index on it. + + @param aTable Caller's table handle. On success + this is placed on the cleanup stack. + @param aTableName Table to open in the authentication db. + @param aAccess Mode to open table in. + @param aIndexName Index to activate on table. + */ + { + CleanupClosePushL(aTable); + User::LeaveIfError(aTable.Open(iAuthDbFile, aTableName, aAccess)); + + if (aAccess != RDbRowSet::EInsertOnly) + { + User::LeaveIfError(aTable.SetIndex(aIndexName)); + } + } + + +void CAuthDb2::CheckIdentityRegisteredL(TUint aIdentityId) +/** + Checks if the supplied identity has been registered with + the database. If not, it leaves with KErrAuthServIdentityNotFound. + + This function is used to validate arguments to other functions. + + @param aIdentityId Identity to search for. + @leave KErrAuthServIdentityNotFound The supplied identity has not + been registered. + */ + { + CheckItemRegisteredL( + KIdentitiesTableName, KIdentitiesIndex, + aIdentityId, KErrAuthServIdentityNotFound); + } + + +void CAuthDb2::CheckItemRegisteredL( + const TDesC& aTableName, const TDesC& aIndexName, + TUint aValue, TInt aNotFoundError) +/** + Helper function for CheckIdentityRegisteredL. + + @param aTableName Name of table to search. + @param aIndexName Name of index to use on table. + @param aValue Key value to search for. + @param aNotFoundError If the key value cannot be found + ` then leave with this value. + */ + { + RDbTable table; + if (! OpenTableAndNavigateLC(table, aTableName, RDbRowSet::EReadOnly, aIndexName, aValue)) + User::Leave(aNotFoundError); + CleanupStack::PopAndDestroy(&table); + } + + +// -------- compaction -------- + + +const TInt KBlockSize = 512; +const TInt KBlockMask = KBlockSize - 1; + + +void CAuthDb2::CompactIfRequired() +/** + Compacts the database file if compacting it would + recover at least one 512 byte block. + + This function does not report any error status + but, if the database is damaged, ConstructL will + attempt to repair it. + */ + { + TInt r = iAuthDbFile.UpdateStats(); + + if (r == KErrNone) + { + RDbDatabase::TSize sz = iAuthDbFile.Size(); + + // approx used bytes - sz.iUsage is a percentage + TInt usedBytes = sz.iUsage * 100; + if ((usedBytes & ~KBlockMask) < (sz.iSize & ~KBlockMask)) + /* ignore */ iAuthDbFile.Compact(); + } + } + +TIdentityId CAuthDb2::DefaultIdentityL() +/** + Return the default identity which is the first identity + in the table when indexed based on the order of insertion. +*/ + { + TIdentityId identity(0); + RDbTable table; + OpenTableLC(table, KIdentitiesTableName, RDbRowSet::EReadOnly, KIdIndexNum); + + //Position the cursor on the first row and retrieve the Identity. + if (table.FirstL()) + { + table.GetL(); + identity = table.ColUint32(KIdentitiesIdentityIdCol); + } + + CleanupStack::PopAndDestroy(&table); + return identity; + }