--- /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<RDbDatabase*>(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<TIdentityId>& 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<TPluginId>& 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<TPluginId>(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;
+ }