authenticationservices/authenticationserver/source/server/authdb.cpp
changeset 19 ece3df019add
equal deleted inserted replaced
17:cd501b96611d 19:ece3df019add
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * CAuthDb Authentication server data store implementation
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 /**
       
    21  @file 
       
    22 */
       
    23 
       
    24 #include "authserver_impl.h"
       
    25 
       
    26 using namespace AuthServer;
       
    27 
       
    28 // The number of decimal digits needed to represent a 32 bit unsigned integer
       
    29 const TInt KUint32Digits = 10;
       
    30 
       
    31 // -------- DB helper functions --------
       
    32 
       
    33 
       
    34 static void RollbackDb(TAny* aPtr)
       
    35 /**
       
    36 	Implements the TCleanupOperation prototype.  This
       
    37 	function is used to rollback a database transaction
       
    38 	if a leave occurs before it is committed.
       
    39 	
       
    40 	@param	aPtr			Pointer to RDbDatabase object
       
    41 							to roll back.
       
    42 	@see CleanupRollbackPushL
       
    43  */
       
    44 	{
       
    45 	RDbDatabase* db = static_cast<RDbDatabase*>(aPtr);
       
    46 	if (db->InTransaction())
       
    47 		db->Rollback();
       
    48 	}
       
    49 
       
    50 
       
    51 inline void CleanupRollbackPushL(RDbDatabase& aDb)
       
    52 /**
       
    53 	Puts the supplied database on the cleanup stack.
       
    54 	The database is rolled back if a leave occurs.
       
    55 	
       
    56 	If a leave does not occur then the supplied database
       
    57 	should be committed.  Do not call CleanupStack::PopAndDestroy
       
    58 	to delete this object.
       
    59 	
       
    60 	@param	aDb				Database to roll back if
       
    61 							a leave occurs.
       
    62  */
       
    63 	{
       
    64 	CleanupStack::PushL(TCleanupItem(RollbackDb, &aDb));
       
    65 	}
       
    66 
       
    67 
       
    68 static void StartTransactionLC(RDbDatabase& aDb)
       
    69 /**
       
    70 	Helper function starts a database transaction and
       
    71 	puts a rollback cleanup item on the cleanup stack.
       
    72 	
       
    73 	@param	aDb				Database to start transaction on.
       
    74 	@see CommitTransactionLD
       
    75  */
       
    76 	{
       
    77 	User::LeaveIfError(aDb.Begin());
       
    78 	CleanupRollbackPushL(aDb);
       
    79 	}
       
    80 
       
    81 
       
    82 static void CommitTransactionLD(RDbDatabase& aDb)
       
    83 /**
       
    84 	Complements StartTransactionLC by removing the
       
    85 	the rollback cleanup item from the cleanup stack
       
    86 	and committing the database.
       
    87 	
       
    88 	@see StartTransactionLC
       
    89  */
       
    90 	{
       
    91 	CleanupStack::Pop(&aDb);
       
    92 	User::LeaveIfError(aDb.Commit());
       
    93 	}
       
    94 
       
    95 
       
    96 // -------- factory functions --------
       
    97 
       
    98 
       
    99 CAuthDb2* CAuthDb2::NewL(RFs& aFs)
       
   100 /**
       
   101 	Factory function allocates a new instance of CAuthDb.
       
   102 	The database file is created if it does not already exist.
       
   103 	
       
   104 	@return					New instance of CAuthDb.
       
   105  */
       
   106 	{
       
   107 	CAuthDb2* self = CAuthDb2::NewLC(aFs);
       
   108 	CleanupStack::Pop(self);
       
   109 	return self;
       
   110 	}
       
   111 
       
   112 
       
   113 CAuthDb2* CAuthDb2::NewLC(RFs& aFs)
       
   114 /**
       
   115 	Factory function allocates new instance of CAuthDb2,
       
   116 	putting it on the cleanup stack.  The database file
       
   117 	is created if it does not already exist.
       
   118 	
       
   119 	@return					New instance of CAuthDb.
       
   120  */
       
   121 	{
       
   122 	CAuthDb2* self = new(ELeave) CAuthDb2;
       
   123 	CleanupStack::PushL(self);
       
   124 	self->ConstructL(aFs);
       
   125 	return self;
       
   126 	}
       
   127 
       
   128 
       
   129 void CAuthDb2::ConstructL(RFs& aFs)
       
   130 /**
       
   131 	This second-phase constructor opens the
       
   132 	database file, creating it if it does not
       
   133 	already exist.
       
   134  */
       
   135 	{
       
   136 	TInt r;
       
   137 	TFileName dbName(KDbName);
       
   138 	dbName[0] = RFs::GetSystemDriveChar();
       
   139 
       
   140 	r = OpenDbFileL(aFs, dbName);
       
   141 	
       
   142 	if (r == KErrNone)
       
   143 		{
       
   144 		if (! iAuthDbFile.IsDamaged() || iAuthDbFile.Recover() == KErrNone)
       
   145 			return;
       
   146 		}
       
   147 	
       
   148 	User::LeaveIfError(iAuthDbFile.Replace(aFs, dbName));
       
   149 	iIsDbOpen = ETrue;
       
   150 	StartTransactionLC(iAuthDbFile);
       
   151 	
       
   152 	// These commands are stored as narrow instead of wide
       
   153 	// text to save c. 500 bytes in decompressed exe size.
       
   154 	// The non-XIP EXE size is almost the same because DEFLATE
       
   155 	// is used on the ELF file.
       
   156 	
       
   157 	static const TText8*const cmds[] =
       
   158 		{
       
   159 		_S8("CREATE TABLE Identities (idName COUNTER, IdentityId UNSIGNED INTEGER NOT NULL, Description VARCHAR(255) NOT NULL)"),
       
   160 		_S8("CREATE UNIQUE INDEX idIndex ON Identities (idName)"),
       
   161 		_S8("CREATE UNIQUE INDEX identityIdx ON Identities (IdentityId DESC)"),
       
   162 		_S8("CREATE TABLE Prefs (PluginType UNSIGNED INTEGER NOT NULL, PluginId UNSIGNED INTEGER NOT NULL)"),
       
   163 		_S8("CREATE UNIQUE INDEX typeIdx ON Prefs (PluginType ASC)"),
       
   164 		_S8("CREATE TABLE TrainedPlugins (IdentityId UNSIGNED INTEGER NOT NULL, PluginId UNSIGNED INTEGER NOT NULL, TransientKey LONG VARBINARY NOT NULL)"),
       
   165 		_S8("CREATE UNIQUE INDEX identityPluginIdx ON TrainedPlugins (IdentityId DESC, PluginId ASC)")
       
   166 		};
       
   167 	
       
   168 	const TInt elemCount = sizeof(cmds) / sizeof(cmds[0]);
       
   169 	TBuf<140> cmd;
       
   170 	for (TInt i = 0; i < elemCount; ++i)
       
   171 		{
       
   172 		TPtrC8 cmd8(cmds[i]);
       
   173 		cmd.Copy(cmd8);
       
   174 		User::LeaveIfError(iAuthDbFile.Execute(cmd));
       
   175 		}
       
   176 
       
   177 	CommitTransactionLD(iAuthDbFile);
       
   178 	}
       
   179 
       
   180 
       
   181 CAuthDb2::~CAuthDb2()
       
   182 /**
       
   183 	Close the database file used by this object.
       
   184  */
       
   185 	{
       
   186 	CloseDbFile();
       
   187 	}
       
   188 
       
   189 TInt CAuthDb2::OpenDbFileL(RFs& aFs, const TFileName& aDbName)
       
   190 	{
       
   191 	
       
   192 	TInt r(0);
       
   193 	if(!iIsDbOpen)
       
   194 		{
       
   195 		r = iAuthDbFile.Open(aFs, aDbName);
       
   196 		if(KErrNone == r)
       
   197 			{
       
   198 			iIsDbOpen = ETrue;
       
   199 			}
       
   200 		else if (KErrNotFound != r)
       
   201 			{
       
   202 			User::Leave(r);
       
   203 			}
       
   204 		}
       
   205 	return r;
       
   206 	}
       
   207 
       
   208 void CAuthDb2::CloseDbFile()
       
   209 	{
       
   210 	if(iIsDbOpen)
       
   211 		{
       
   212 		RollbackDb(&iAuthDbFile);
       
   213 		if(iAuthDbFile.IsDamaged())
       
   214 			{
       
   215 			iAuthDbFile.Recover();
       
   216 			}
       
   217 		iAuthDbFile.Close();
       
   218 		iIsDbOpen = EFalse;
       
   219 		}
       
   220 	}
       
   221 
       
   222 // -------- identities --------
       
   223 
       
   224 
       
   225 void CAuthDb2::AddIdentityWithTrainedPluginL(
       
   226 	TIdentityId aIdentityId, const TDesC& aDesc,
       
   227 	const CTransientKeyInfo& aTransKeyInfo)
       
   228 /**
       
   229 	Adds an identity and trains a plugin for it in a single
       
   230 	atomic operation.
       
   231 	
       
   232 	@param	aIdentityId		New identity.
       
   233 	@param	aDesc			Identity's description.  This must
       
   234 							have no more than KMaxDescLen characters.
       
   235 	@param	aTransKeyInfo	A transient key which trains this identity
       
   236 							for a plugin.
       
   237 	@leave	KErrAuthServIdentityAlreadyExists  The supplied identity
       
   238 							is already in the database.
       
   239  */
       
   240 	{
       
   241 	StartTransactionLC(iAuthDbFile);
       
   242 	
       
   243 	AddIdentityL(aIdentityId, aDesc);
       
   244 	
       
   245 	SetTrainedPluginL(aIdentityId, aTransKeyInfo.PluginId(), aTransKeyInfo);
       
   246 	
       
   247 	CommitTransactionLD(iAuthDbFile);
       
   248 	}
       
   249 
       
   250 
       
   251 void CAuthDb2::AddIdentityL(TIdentityId aIdentityId, const TDesC& aDesc)
       
   252 /**
       
   253 	Add the supplied identity to the database.
       
   254 	
       
   255 	@param	aIdentityId		New identity.
       
   256 	@param	aDesc			Identity's description.  This must
       
   257 							have no more than KMaxDescLen characters.
       
   258 	@leave	KErrAuthServDescTooLong The supplied description is more than
       
   259 							255 characters.
       
   260 	@leave	KErrAuthServIdentityAlreadyExists  The supplied identity
       
   261 							is already in the database.
       
   262  */
       
   263 	{
       
   264 	if (aDesc.Length() > KMaxDescLen)
       
   265 		User::Leave(KErrAuthServDescTooLong);
       
   266 
       
   267 	RDbTable table;
       
   268 	
       
   269 	// EUpdatable instead of EInsertOnly so can navigate to any
       
   270 	// existing row.
       
   271 	if (FindIdentityLC(table, RDbView::EUpdatable, aIdentityId))
       
   272 		User::Leave(KErrAuthServIdentityAlreadyExists);
       
   273 	
       
   274 	table.InsertL();		// start automatic transaction
       
   275 	table.SetColL(KIdentitiesIdentityIdCol, aIdentityId);
       
   276 	table.SetColL(KIdentitiesDescCol, aDesc);
       
   277 	table.PutL();			// end automatic transaction
       
   278 	
       
   279 	CleanupStack::PopAndDestroy(&table);
       
   280 	}
       
   281 
       
   282 
       
   283 void CAuthDb2::RemoveIdentityL(TIdentityId aIdentityId)
       
   284 /**
       
   285 	Remove the supplied identity from the auth server's database.
       
   286 	Any trained entries for the supplied identity are also removed.
       
   287 	All updates to the database happen within a single transaction.
       
   288 
       
   289 	@param	aIdentityId		Identity to remove from database;
       
   290 	@leave	KErrAuthServIdentityNotFound The supplied identity could
       
   291 							not be found in the database.
       
   292  */
       
   293 	{
       
   294 	StartTransactionLC(iAuthDbFile);
       
   295 	
       
   296 	RDbTable table;
       
   297 	FindExistingIdentityLC(table, RDbView::EUpdatable, aIdentityId);
       
   298 	table.DeleteL();
       
   299 	CleanupStack::PopAndDestroy(&table);
       
   300 
       
   301 	// remove each training record for this identity
       
   302 	_LIT(KDelTrainFmt, "DELETE FROM TrainedPlugins WHERE IdentityId=%u");
       
   303 	TBuf<(46 - 2) + 10> bufCmd;
       
   304 	bufCmd.Format(KDelTrainFmt, aIdentityId);
       
   305 	iAuthDbFile.Execute(bufCmd);
       
   306 	
       
   307 	CommitTransactionLD(iAuthDbFile);
       
   308 	}
       
   309 
       
   310 
       
   311 TInt CAuthDb2::NumIdentitiesL() 
       
   312  /**
       
   313 	Retrieve the number of identities in the database.
       
   314 	@return the number of identities in the database.
       
   315   */
       
   316 	{
       
   317 	TInt result = 0;
       
   318 	RDbTable table;
       
   319 	OpenTableLC(table, KIdentitiesTableName, RDbRowSet::EReadOnly, KIdentitiesIndex);
       
   320 	result = table.CountL();
       
   321 	CleanupStack::PopAndDestroy(&table);
       
   322 	return result;
       
   323 	}
       
   324   
       
   325 void CAuthDb2::IdentitiesL(RArray<TIdentityId>& aResults)
       
   326 /**
       
   327 	Populate the supplied array with the currently
       
   328 	registered identities.
       
   329 	
       
   330 	@param	aResults		On success this array is populated
       
   331 							with the currently registered identities.
       
   332 							Any items which were in the array when
       
   333 							this function is called are removed.  On
       
   334 							failure this array is emptied so the caller
       
   335 							does not have to place it on the cleanup stack.
       
   336  */
       
   337 	{
       
   338 	aResults.Reset();
       
   339 	CleanupClosePushL(aResults);
       
   340 	
       
   341 	RDbTable table;
       
   342 	OpenTableLC(table, KIdentitiesTableName, RDbRowSet::EReadOnly, KIdIndexNum);
       
   343 	while (table.NextL())
       
   344 		{
       
   345 		table.GetL();
       
   346 		aResults.AppendL(table.ColUint32(KIdentitiesIdentityIdCol));
       
   347 		}
       
   348 	
       
   349 	CleanupStack::PopAndDestroy(&table);
       
   350 	CleanupStack::Pop(&aResults);
       
   351 	}
       
   352 
       
   353 void CAuthDb2::IdentitiesWithDescriptionL(RIdAndStringArray& aList)
       
   354 /**
       
   355 	Populate the supplied array with the currently
       
   356 	registered identities and descriptions.
       
   357 	
       
   358 	@param	aList   		On success this array is populated
       
   359 							with the currently registered identities.
       
   360 							Any items which were in the array when
       
   361 							this function is called are removed.  On
       
   362 							failure this array is emptied so the caller
       
   363 							does not have to place it on the cleanup stack.
       
   364  */
       
   365 	{
       
   366 	aList.Reset();
       
   367 	CleanupClosePushL(aList);
       
   368 	
       
   369 	RDbTable table;
       
   370 	OpenTableLC(table, KIdentitiesTableName, RDbRowSet::EReadOnly, KIdentitiesIndex);
       
   371 	while (table.NextL())
       
   372 		{
       
   373 		table.GetL();
       
   374 		CIdAndString* id =
       
   375 		  CIdAndString::NewLC(table.ColUint32(KIdentitiesIdentityIdCol),
       
   376 							  table.ColDes(KIdentitiesDescCol));
       
   377 		aList.AppendL(id);
       
   378 		CleanupStack::Pop(id);
       
   379 		}
       
   380 	
       
   381 	CleanupStack::PopAndDestroy(&table);
       
   382 	CleanupStack::Pop(&aList);
       
   383 	}
       
   384 
       
   385 HBufC* CAuthDb2::DescriptionL(TIdentityId aIdentityId)
       
   386 /**
       
   387 	Allocate a descriptor containing the supplied identity's
       
   388 	description.
       
   389 	
       
   390 	@param	aIdentityId		Identity whose description is returned.
       
   391 	@return					Newly-allocated descriptor containing the
       
   392 							identity's description.  The client must
       
   393 							free this object.
       
   394 	@leave	KErrAuthServIdentityNotFound The supplied identity could
       
   395 							not be found in the database.
       
   396  */
       
   397 	{
       
   398 	RDbTable table;
       
   399 	FindExistingIdentityLC(table, RDbView::EReadOnly, aIdentityId);
       
   400 	
       
   401 	table.GetL();
       
   402 	HBufC* retDesc = table.ColDes(KIdentitiesDescCol).AllocL();
       
   403 	
       
   404 	CleanupStack::PopAndDestroy(&table);
       
   405 	return retDesc;
       
   406 	}
       
   407 
       
   408 
       
   409 
       
   410 void CAuthDb2::SetDescriptionL(TIdentityId aIdentityId, const TDesC& aDesc)
       
   411 /**
       
   412 	Update an identity's description.
       
   413 	
       
   414 	@param	aIdentityId		Identity to update.
       
   415 	@param	aDesc			New description text.  This must have
       
   416 							no more than KMaxDescLen characters.
       
   417 	@leave	KErrAuthServIdentityNotFound The supplied identity could
       
   418 							not be found in the database.
       
   419  */
       
   420 	{
       
   421 	if (aDesc.Length() > KMaxDescLen)
       
   422 		User::Leave(KErrAuthServDescTooLong);
       
   423 	
       
   424 	RDbTable table;
       
   425 	FindExistingIdentityLC(table, RDbView::EUpdatable, aIdentityId);
       
   426 	
       
   427 	table.UpdateL();			// start automatic transaction
       
   428 	table.SetColL(KIdentitiesDescCol, aDesc);
       
   429 	table.PutL();				// end automatic transaction
       
   430 	
       
   431 	CleanupStack::PopAndDestroy(&table);
       
   432 	}
       
   433 
       
   434 
       
   435 void CAuthDb2::FindExistingIdentityLC(
       
   436 	RDbTable& aTable, RDbRowSet::TAccess aAccess, TIdentityId aIdentityId)
       
   437 /**
       
   438 	Find the supplied identity and navigate to it.
       
   439 	On success, the table handle is on the cleanup stack.
       
   440 	
       
   441 	@param	aTable			Caller's table handle.
       
   442 	@param	aAccess			Mode in which to open the handle.
       
   443 	@param	aIdentityId		Identity to navigate to.
       
   444 	@leave	KErrAuthServIdentityNotFound The supplied identity could
       
   445 							not be found.
       
   446  */
       
   447 	{
       
   448 	TBool found = FindIdentityLC(aTable, aAccess, aIdentityId);
       
   449 	if (! found)
       
   450 		User::Leave(KErrAuthServIdentityNotFound);
       
   451 	}
       
   452 
       
   453 
       
   454 TBool CAuthDb2::FindIdentityLC(RDbTable& aTable, RDbRowSet::TAccess aAccess, TIdentityId aIdentityId)
       
   455 /**
       
   456 	Navigate to the supplied identity in the Identities table.
       
   457 	On success, the table handle is on the cleanup stack.
       
   458 	
       
   459 	@param	aTable			Caller's table handle.
       
   460 	@param	aAccess			Mode in which to open the table.
       
   461 	@param	aIdentityId		Identity to navigate to.
       
   462 	@return					Zero if could not find identity in table;
       
   463 							Non-zero otherwise.
       
   464  */
       
   465 	{
       
   466 	TBool found = OpenTableAndNavigateLC(
       
   467 		aTable, KIdentitiesTableName, aAccess, KIdentitiesIndex, aIdentityId);
       
   468 
       
   469 	return found;
       
   470 	}
       
   471 
       
   472 
       
   473 // -------- plugins --------
       
   474 
       
   475 TInt CAuthDb2::NumTrainedPluginsL(TIdentityId aId)
       
   476 /**
       
   477     Retrieve the number of trained plugins for the specified id.
       
   478     
       
   479     @param aId the identity for whom to retrieve the number of trained plugins.
       
   480     @return the number of trained plugins for the specified id.
       
   481  */
       
   482 	{
       
   483 	_LIT(KGetTrainedFmt, "SELECT IdentityId FROM TrainedPlugins WHERE IdentityId=%u");
       
   484 	TBuf<(57 - 2) + 10> bufCmd;
       
   485 	bufCmd.Format(KGetTrainedFmt, aId);
       
   486 	
       
   487 	TDbQuery q(bufCmd);
       
   488 	RDbView viewTp;
       
   489 	CleanupClosePushL(viewTp);
       
   490 	User::LeaveIfError(viewTp.Prepare(iAuthDbFile, q));
       
   491 	User::LeaveIfError(viewTp.EvaluateAll());
       
   492 	TInt trainedCount = viewTp.CountL();
       
   493 	CleanupStack::PopAndDestroy(&viewTp);
       
   494 
       
   495 	return trainedCount;
       
   496 	}
       
   497 
       
   498 /**
       
   499 	Returns list of plugins that are trained for the given identity
       
   500 
       
   501 	@param	aIdentityId		The identity for whom to retrieve the list of trained plugins.
       
   502 	@param 	aTrainedPlugins	The array to fill the returned plugin ids.
       
   503 */
       
   504 void CAuthDb2::TrainedPluginsListL(TIdentityId aIdentityId, RArray<TPluginId>& aTrainedPlugins)
       
   505 	{
       
   506 	_LIT(KGetTrainedFmt, "SELECT PluginId FROM TrainedPlugins WHERE IdentityId=%u");
       
   507 	RBuf queryBuf;
       
   508 	CleanupClosePushL(queryBuf);
       
   509 	queryBuf.CreateL(KGetTrainedFmt().Length() + KUint32Digits);
       
   510 	queryBuf.Format(KGetTrainedFmt, aIdentityId);
       
   511 
       
   512 	TDbQuery query(queryBuf);
       
   513 	RDbView viewTp;
       
   514 	CleanupClosePushL(viewTp);
       
   515 	User::LeaveIfError(viewTp.Prepare(iAuthDbFile, query));
       
   516 	User::LeaveIfError(viewTp.EvaluateAll());
       
   517 
       
   518 	if (viewTp.FirstL())
       
   519 		{
       
   520 		do
       
   521 			{
       
   522 			viewTp.GetL();
       
   523 			aTrainedPlugins.AppendL(viewTp.ColUint32(1));
       
   524 			}
       
   525 		while (viewTp.NextL());
       
   526 		}
       
   527 	CleanupStack::PopAndDestroy(2, &queryBuf); // viewTp
       
   528 	}
       
   529 
       
   530 TAuthTrainingStatus CAuthDb2::PluginStatusL(TPluginId aPluginId)
       
   531 /**
       
   532 	Return the supplied plugin's training status.
       
   533 
       
   534 		EAuthUntrained			No identities have been trained for this plugin.
       
   535 		EAuthTrained			Some (but not all) identities have been trained for this plugin
       
   536 		EAuthFullyTrained		All identities have been trained for this plugin.
       
   537 	
       
   538 	@param	aPluginId		Plugin whose status should be retrieved.
       
   539 	@return					The plugin's training status.
       
   540  */
       
   541 	{
       
   542 	// get number of identities trained for this plugin
       
   543 	
       
   544 	// This involves filtering all trainings for this plugin
       
   545 	// from the TrainedPlugins table.  For small numbers of users
       
   546 	// it is simpler to do this; for large numbers of users
       
   547 	// (registered identities) it may be better to maintain another
       
   548 	// table which matches each plugin against its training count.
       
   549 
       
   550 	_LIT(KGetTrainedFmt, "SELECT IdentityId FROM TrainedPlugins WHERE PluginId=%u");
       
   551 	TBuf<(55 - 2) + 10> bufCmd;
       
   552 	bufCmd.Format(KGetTrainedFmt, aPluginId);
       
   553 	
       
   554 	TDbQuery q(bufCmd);
       
   555 	RDbView viewTp;
       
   556 	CleanupClosePushL(viewTp);
       
   557 	User::LeaveIfError(viewTp.Prepare(iAuthDbFile, q));
       
   558 	User::LeaveIfError(viewTp.EvaluateAll());
       
   559 	TInt trainCount = viewTp.CountL();
       
   560 	CleanupStack::PopAndDestroy(&viewTp);
       
   561 	
       
   562 	if (trainCount == 0)
       
   563 		return EAuthUntrained;
       
   564 
       
   565 	// get total number of identities in the database
       
   566 	RDbTable tableId;
       
   567 	OpenTableLC(tableId, KIdentitiesTableName, RDbRowSet::EReadOnly, KIdentitiesIndex);
       
   568 	TInt idCount = tableId.CountL();
       
   569 	CleanupStack::PopAndDestroy(&tableId);
       
   570 	
       
   571 	return (trainCount < idCount) ? EAuthTrained : EAuthFullyTrained;
       
   572 	}
       
   573 
       
   574 
       
   575 // -------- preferences --------
       
   576 
       
   577 
       
   578 void CAuthDb2::SetPreferredPluginL(TAuthPluginType aPluginType, TPluginId aPluginId)
       
   579 /**
       
   580 	Set the preferred plugin for the supplied plugin type.
       
   581 
       
   582 	If the type already has a preferred plugin type, its entry is
       
   583 	updated.  Otherwise, a new entry is created.
       
   584 
       
   585 	@param	aPluginType		Type of plugin to associate with a specific
       
   586 							plugin ID.
       
   587 	@param	aPluginId		Specific plugin to use for the plugin type.
       
   588  */
       
   589 	{
       
   590 	RDbTable table;
       
   591 
       
   592 	// start automatic transaction
       
   593 	if (FindPrefLC(table, RDbRowSet::EUpdatable, aPluginType))
       
   594 		table.UpdateL();
       
   595 	else
       
   596 		table.InsertL();
       
   597 	
       
   598 	table.SetColL(KPrefsTypeCol, (TUint) aPluginType);
       
   599 	table.SetColL(KPrefsIdCol, (TUint) aPluginId);
       
   600 	table.PutL();			// end automatic transaction
       
   601 
       
   602 	CleanupStack::PopAndDestroy(&table);
       
   603 	}
       
   604 
       
   605 
       
   606 void CAuthDb2::ClearPreferredPluginL(TAuthPluginType aPluginType)
       
   607 /**
       
   608 	Remove and preferred plugin ID for the supplied plugin type.
       
   609 	
       
   610 	If the supplied plugin type does not have a preferred plugin
       
   611 	then the database is not modified.
       
   612 
       
   613 	@param	aPluginType		Type of plugin to remove from the
       
   614 							Prefs table.
       
   615  */
       
   616 	{
       
   617 	RDbTable table;
       
   618 	if (FindPrefLC(table, RDbRowSet::EUpdatable, aPluginType))
       
   619 		table.DeleteL();
       
   620 
       
   621 	CleanupStack::PopAndDestroy(&table);
       
   622 	}
       
   623 
       
   624 
       
   625 TPluginId CAuthDb2::PreferredPluginL(TAuthPluginType aPluginType)
       
   626 /**
       
   627 	Retrieve the preferred plugin for the supplied plugin type.
       
   628 	If the plugin type does not have a preferred plugin this function
       
   629 	returns KUnknownPluginId.
       
   630 
       
   631 	@param	aPluginType		Plugin type to find preferred plugin for.
       
   632 	@return					Preferred plugin for aPluginType.  This is
       
   633 							KUnknownPluginId if the type does not
       
   634 							have a preferred plugin.
       
   635  */
       
   636 	{
       
   637 	TPluginId pluginId;
       
   638 
       
   639 	RDbTable table;
       
   640 	if (! FindPrefLC(table, RDbRowSet::EReadOnly, aPluginType))
       
   641 		pluginId = KUnknownPluginId;
       
   642 	else
       
   643 		{
       
   644 		table.GetL();
       
   645 		pluginId = static_cast<TPluginId>(table.ColUint(KPrefsIdCol));
       
   646 		}
       
   647 
       
   648 	CleanupStack::PopAndDestroy(&table);
       
   649 	return pluginId;
       
   650 	}
       
   651 
       
   652 
       
   653 TBool CAuthDb2::FindPrefLC(RDbTable& aTable, RDbRowSet::TAccess aAccess, TAuthPluginType aPluginType)
       
   654 /**
       
   655 	Open the Prefs table and navigate to the supplied plugin type.
       
   656 	On success the table handle is placed on the cleanup stack.
       
   657 
       
   658 	@param	aTable			Table handle to open.  On success this
       
   659 							is placed on the cleanup stack.
       
   660 	@param	aAccess			Mode in which the table should be opened.
       
   661 	@param	aPluginType		Plugin type to navigate to.
       
   662 	@return					Zero if could not find plugin type;
       
   663 							Non-zero otherwise.
       
   664  */
       
   665 	{
       
   666 	return OpenTableAndNavigateLC(aTable, KPrefsTableName, aAccess, KPrefsTypeIndex, aPluginType);
       
   667 	}
       
   668 
       
   669 
       
   670 // -------- trained plugins --------
       
   671 
       
   672 
       
   673 void CAuthDb2::SetTrainedPluginL(
       
   674 	TIdentityId aIdentityId, TPluginId aPluginId, const CTransientKeyInfo& aTransKeyInfo)
       
   675 /**
       
   676 	Sets the transient key for the supplied identity, plugin pair.
       
   677 
       
   678 	If the identity has already been trained for this plugin
       
   679 	then the existing record is replaced.
       
   680 
       
   681 	@param	aIdentityId		Identity to update.
       
   682 	@param	aPluginId		Plugin to associate with identity.
       
   683 	@param	aTransKeyInfo	The salt and encrypted protection key
       
   684 							for this identity / plugin pair.
       
   685 	@leave	KErrAuthServIdentityNotFound The supplied identity has
       
   686 							not been registered.
       
   687  */
       
   688 	{
       
   689 	RDbTable table;
       
   690 
       
   691 	TBool update = FindTrainedPluginLC(table, RDbRowSet::EUpdatable, aIdentityId, aPluginId);
       
   692 	
       
   693 	// start automatic transaction
       
   694 	if (update)
       
   695 		{
       
   696 		table.UpdateL();
       
   697 		}
       
   698 	else
       
   699 		{
       
   700 		CheckIdentityRegisteredL(aIdentityId);
       
   701 		table.InsertL();
       
   702 		}
       
   703 
       
   704 	table.SetColL(KTpIdentityIdCol, (TUint) aIdentityId);
       
   705 	table.SetColL(KTpPluginIdCol, (TUint) aPluginId);
       
   706 	
       
   707 	RDbColWriteStream dbcws;
       
   708 	dbcws.OpenLC(table, KTpTransientKeyCol);
       
   709 	aTransKeyInfo.ExternalizeL(dbcws);
       
   710 	dbcws.CommitL();
       
   711 	CleanupStack::PopAndDestroy(&dbcws);
       
   712 	table.PutL();
       
   713 	
       
   714 	CleanupStack::PopAndDestroy(&table);
       
   715 	}
       
   716 
       
   717 
       
   718 void CAuthDb2::RemoveTrainedPluginL(TIdentityId aIdentityId, TPluginId aPluginId)
       
   719 /**
       
   720 	Remove the transient key info (i.e. the encrypted protection key
       
   721 	and its salt) for the supplied identity, plugin pair.
       
   722 
       
   723 	@param	aIdentityId		Identity which should be trained for
       
   724 							the supplied plugin.
       
   725 	@param	aPluginId		Plugin which should be trained for the
       
   726 							supplied identity.
       
   727 	@leave	KErrAuthServTrainingNotFound Attempted to remove an
       
   728 							identity, plugin pair which was not in the
       
   729 							trained plugins table.
       
   730  */
       
   731 	{
       
   732 	RDbTable table;
       
   733 	TBool found = FindTrainedPluginLC(table, RDbRowSet::EUpdatable, aIdentityId, aPluginId);
       
   734 
       
   735 	if (! found)
       
   736 		User::Leave(KErrAuthServTrainingNotFound);
       
   737 
       
   738 	table.DeleteL();
       
   739 	CleanupStack::PopAndDestroy(&table);
       
   740 	}
       
   741 
       
   742 
       
   743 CTransientKeyInfo* CAuthDb2::KeyInfoL(TIdentityId aIdentity, TPluginId aPluginId)
       
   744 /**
       
   745 	Retrieve the transient key associated with the supplied identity,
       
   746 	plugin pair.
       
   747 
       
   748 	@param	aIdentity		Identity to search for.
       
   749 	@param	aPluginId		Plugin which should be registered
       
   750 							with the supplied identity.
       
   751 	@return					Transient key info, including encrypted
       
   752 							protection key, associated with identity,
       
   753 							plugin pair.
       
   754 	@leave KErrAuthServTrainingNotFound There was no transient key
       
   755 							information for the supplied identity,
       
   756 							plugin pair.
       
   757  */
       
   758 	{
       
   759 	RDbTable table;
       
   760 	TBool found = FindTrainedPluginLC(table, RDbRowSet::EReadOnly, aIdentity, aPluginId);
       
   761 	if (! found)
       
   762 		User::Leave(KErrAuthServTrainingNotFound);
       
   763 
       
   764 	table.GetL();
       
   765 	RDbColReadStream dbcrs;
       
   766 	dbcrs.OpenLC(table, KTpTransientKeyCol);
       
   767 	CTransientKeyInfo* keyInfo = CTransientKeyInfo::NewL(dbcrs);
       
   768 
       
   769 	CleanupStack::PopAndDestroy(2, &table);		// dbcrs, table
       
   770 	return keyInfo;
       
   771 	}
       
   772 
       
   773 
       
   774 TBool CAuthDb2::FindTrainedPluginLC(
       
   775 	RDbTable& aTable, RDbRowSet::TAccess aAccess,
       
   776 	TIdentityId aIdentityId, TPluginId aPluginId)
       
   777 /**
       
   778 	Helper function for SetTrainedPluginL and ClearTrainedPluginL.
       
   779 	This function opens the TrainedPlugins table and navigates to
       
   780 	the supplied identity, plugin pair if they are present.
       
   781 
       
   782 	@param	aTable			Table handle to open.
       
   783 	@param	aAccess			Mode in which to open the table.
       
   784 	@param	aIdentityId		Identity to navigate to.
       
   785 	@param	aPluginId		Plugin to navigate to.
       
   786 	@return					Zero if could not navigate to the
       
   787 							identity, plugin ID pair; non-zero
       
   788 							otherwise.
       
   789  */
       
   790 	{
       
   791 	OpenTableLC(aTable, KTpTableName, aAccess, KTpIndex);
       
   792 
       
   793 	TDbSeekMultiKey<2> dbsmk;
       
   794 	dbsmk.Add((TUint) aIdentityId);
       
   795 	dbsmk.Add((TUint) aPluginId);
       
   796 	return aTable.SeekL(dbsmk);
       
   797 	}
       
   798 
       
   799 
       
   800 // -------- helper functions --------
       
   801 
       
   802 
       
   803 TBool CAuthDb2::OpenTableAndNavigateLC(
       
   804 	RDbTable& aTable, const TDesC& aTableName, RDbRowSet::TAccess aAccess,
       
   805 	const TDesC& aIndexName, TUint aKey)
       
   806 /**
       
   807 	Open the described table and navigate to the identified row.
       
   808 
       
   809 	@param	aTable			Caller's table handle.  On success
       
   810 							this is placed on the cleanup stack.
       
   811 	@param	aTableName		Table to open in auth db.
       
   812 	@param	aAccess			Mode to open table in.
       
   813 	@param	aIndexName		Index to use for navigating.
       
   814 	@param	aKey			Key to find in database.
       
   815 	@return					Zero if could not find row in table;
       
   816 							Non-zero otherwise.
       
   817  */
       
   818 	{
       
   819 	OpenTableLC(aTable, aTableName, aAccess, aIndexName);
       
   820 
       
   821 	TDbSeekKey seekKey((TUint)aKey);	// from TUint32
       
   822 	return aTable.SeekL(seekKey);
       
   823 	}
       
   824 
       
   825 
       
   826 void CAuthDb2::OpenTableLC(
       
   827 	RDbTable& aTable, const TDesC& aTableName,
       
   828 	RDbRowSet::TAccess aAccess, const TDesC& aIndexName)
       
   829 /**
       
   830 	Open the named table in the supplied access mode,
       
   831 	and use the index on it.
       
   832 
       
   833 	@param	aTable			Caller's table handle.  On success
       
   834 							this is placed on the cleanup stack.
       
   835 	@param	aTableName		Table to open in the authentication db.
       
   836 	@param	aAccess			Mode to open table in.
       
   837 	@param	aIndexName		Index to activate on table.
       
   838  */
       
   839 	{
       
   840 	CleanupClosePushL(aTable);
       
   841 	User::LeaveIfError(aTable.Open(iAuthDbFile, aTableName, aAccess));
       
   842 
       
   843 	if (aAccess != RDbRowSet::EInsertOnly)
       
   844 		{
       
   845 		User::LeaveIfError(aTable.SetIndex(aIndexName));
       
   846 		}
       
   847 	}
       
   848 
       
   849 
       
   850 void CAuthDb2::CheckIdentityRegisteredL(TUint aIdentityId)
       
   851 /**
       
   852 	Checks if the supplied identity has been registered with
       
   853 	the database.  If not, it leaves with KErrAuthServIdentityNotFound.
       
   854 	
       
   855 	This function is used to validate arguments to other functions.
       
   856 	
       
   857 	@param	aIdentityId		Identity to search for.
       
   858 	@leave	KErrAuthServIdentityNotFound The supplied identity has not
       
   859 							been registered.
       
   860  */
       
   861 	{
       
   862 	CheckItemRegisteredL(
       
   863 		KIdentitiesTableName, KIdentitiesIndex,
       
   864 		aIdentityId, KErrAuthServIdentityNotFound);
       
   865 	}
       
   866 
       
   867 
       
   868 void CAuthDb2::CheckItemRegisteredL(
       
   869 	const TDesC& aTableName, const TDesC& aIndexName,
       
   870 	TUint aValue, TInt aNotFoundError)
       
   871 /**
       
   872 	Helper function for CheckIdentityRegisteredL.
       
   873 	
       
   874 	@param	aTableName		Name of table to search.
       
   875 	@param	aIndexName		Name of index to use on table.
       
   876 	@param	aValue			Key value to search for.
       
   877 	@param	aNotFoundError	If the key value cannot be found
       
   878 		`					then leave with this value.
       
   879  */
       
   880  	{
       
   881 	RDbTable table;
       
   882 	if (! OpenTableAndNavigateLC(table, aTableName, RDbRowSet::EReadOnly, aIndexName, aValue))
       
   883 		User::Leave(aNotFoundError);
       
   884 	CleanupStack::PopAndDestroy(&table);
       
   885  	}
       
   886 
       
   887 
       
   888 // -------- compaction --------
       
   889 
       
   890 
       
   891 const TInt KBlockSize = 512;
       
   892 const TInt KBlockMask = KBlockSize - 1;
       
   893 
       
   894 
       
   895 void CAuthDb2::CompactIfRequired()
       
   896 /**
       
   897 	Compacts the database file if compacting it would
       
   898 	recover at least one 512 byte block.
       
   899 	
       
   900 	This function does not report any error status
       
   901 	but, if the database is damaged, ConstructL will
       
   902 	attempt to repair it.
       
   903  */
       
   904 	{
       
   905 	TInt r = iAuthDbFile.UpdateStats();
       
   906 	
       
   907 	if (r == KErrNone)
       
   908 		{
       
   909 		RDbDatabase::TSize sz = iAuthDbFile.Size();
       
   910 		
       
   911 		// approx used bytes - sz.iUsage is a percentage
       
   912 		TInt usedBytes = sz.iUsage * 100;
       
   913 		if ((usedBytes & ~KBlockMask) < (sz.iSize & ~KBlockMask))
       
   914 			/* ignore */ iAuthDbFile.Compact();
       
   915 		}
       
   916 	}
       
   917 
       
   918 TIdentityId CAuthDb2::DefaultIdentityL()
       
   919 /**
       
   920  	Return the default identity which is the first identity
       
   921  	in the table when indexed based on the order of insertion.
       
   922 */
       
   923 	{
       
   924 	TIdentityId identity(0);
       
   925 	RDbTable table;	
       
   926 	OpenTableLC(table, KIdentitiesTableName, RDbRowSet::EReadOnly, KIdIndexNum);
       
   927 	
       
   928 	//Position the cursor on the first row and retrieve the Identity.
       
   929 	if (table.FirstL())
       
   930 		{
       
   931 		table.GetL();
       
   932 		identity = table.ColUint32(KIdentitiesIdentityIdCol);
       
   933 		}	
       
   934 		
       
   935 	CleanupStack::PopAndDestroy(&table);
       
   936 	return identity;
       
   937 	}