authenticationservices/authenticationserver/test/tAuthSvr/src/tpinauthpluginupgrade.cpp
changeset 29 ece3df019add
equal deleted inserted replaced
19:cd501b96611d 29:ece3df019add
       
     1 /*
       
     2 * Copyright (c) 2008-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 * dummy dll upgrade implementation.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include <f32file.h>
       
    21 
       
    22 #include "tPinAuthPlugin.h"
       
    23 #include <e32svr.h>
       
    24 
       
    25 #ifndef __INIPARSER_H__
       
    26 	#include <cinidata.h>
       
    27 #endif // __INIPARSER_H__
       
    28 
       
    29 _LIT(KPluginUpgradeNamePin, "Pin1-Upgrade");
       
    30 
       
    31 CTPinAuthPlugin::~CTPinAuthPlugin()
       
    32 	{
       
    33 	delete iClientMessage;
       
    34 	}
       
    35 
       
    36 CTPinAuthPlugin::CTPinAuthPlugin()
       
    37 	{}
       
    38 		
       
    39 void CTPinAuthPlugin::ConstructL()
       
    40 	{
       
    41 	iName.Set(KPluginUpgradeNamePin);
       
    42 	iDescription.Set(KPluginDescriptionPin);
       
    43 	iMinEntropy = KEntropyPin;
       
    44 	iFalsePositiveRate = KFalsePosPin;
       
    45   	iFalseNegativeRate = KFalseNegPin;
       
    46   	iClientMessage = HBufC::NewL(2048);
       
    47 	ReloadAllFromIniFile();
       
    48 	}
       
    49 	
       
    50 /**
       
    51   Sets information like iActiveState and iSupportsDefaultData from 
       
    52   the TEF ini file to the individual plugin database files
       
    53 */	
       
    54 void CTPinAuthPlugin::ReloadAllFromIniFile()
       
    55 	{
       
    56 	// Set the file to be read, based on the Id of the plugin
       
    57 	
       
    58 	_LIT(KFileText, "\\tAuth\\tAuthSvr\\testdata\\Pin");
       
    59 	_LIT(KFileSuffix, "Db.ini");					
       
    60 	_LIT(KFormatFileName,"%S%x%S");
       
    61 	
       
    62 	TDriveUnit sysDrive (RFs::GetSystemDrive());
       
    63 	TBuf<64> fileText(sysDrive.Name());
       
    64 	fileText.Append(KFileText);
       
    65 	iFileToRead.Format(KFormatFileName,&fileText, Id(), &KFileSuffix);
       
    66 
       
    67 	//Read data from file to get initialisation information
       
    68 	
       
    69 	// Open and read in INI file
       
    70 	// Default path to look for INI file is in 'c:\system\data' 
       
    71 	// on target filesystem
       
    72 	
       
    73 	CIniData* file=NULL;
       
    74 	TRAPD(r,file=CIniData::NewL(iFileToRead));
       
    75 	
       
    76 	//Put file on the cleanupstack if anything else in this function is going to leave, but nothing does.	
       
    77 	
       
    78 	if(r!=KErrNone)
       
    79 		{
       
    80 		RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
       
    81 		}
       
    82 	
       
    83 	else
       
    84 		{
       
    85 		// Look for a key under a named section, retrieve text value	
       
    86 		TPtrC result;		
       
    87 		TBool ret;	//return value from FindVar functions
       
    88 		ret=file->FindVar(_L("SectionOne"),_L("iSupportsDefaultData"),result);
       
    89 		if(!ret)
       
    90 			{
       
    91 			RDebug::Print(_L("Key or section not found. iSupportsDefaultData default value used."));
       
    92 			iSupportsDefaultData = ETrue;	// Default value
       
    93 			}
       
    94 		else
       
    95 			{
       
    96 			_LIT(KFalse,"false");
       
    97 			// Create a lower case copy of the data that is read from the file
       
    98 			TBuf<10> resultLowerCase;			
       
    99 			resultLowerCase.Copy(result);
       
   100 			resultLowerCase.LowerCase();
       
   101 			iSupportsDefaultData = (resultLowerCase.FindF(KFalse) == KErrNotFound);
       
   102 			}
       
   103 		// Set the active state of the plugin depending on the contents of the 
       
   104 		// corresponding file, which has been set as a member variable
       
   105 		ret =file->FindVar(_L("SectionOne"),_L("activeState"),result);
       
   106 		if(!ret)
       
   107 			{
       
   108 			RDebug::Print(_L("Key or section not found. iActiveState default value of ETRUE used."));			
       
   109 			iActiveState = ETrue;	// Default value
       
   110 			}
       
   111 		else
       
   112 			{
       
   113 			_LIT(KFalse,"false");
       
   114 			// Create a lower case copy of the data that is read from the file
       
   115 			TBuf<10> resultLowerCase;			
       
   116 			resultLowerCase.Copy(result);
       
   117 			resultLowerCase.LowerCase();
       
   118 			
       
   119 			// If the string 'false' was not found, we set the value to 'true' -the default value
       
   120 			iActiveState = (resultLowerCase.FindF(KFalse) == KErrNotFound);
       
   121 			}
       
   122 		TRAPD(r,file->WriteToFileL());
       
   123 		
       
   124 		if (KErrNone != r)
       
   125 			{
       
   126 			RDebug::Print(_L("Error occurred while writing to the file."));
       
   127 			TBuf<84> initInfoFile(sysDrive.Name());
       
   128 			initInfoFile.Append(KInitInfoFile);
       
   129 			RDebug::Print(_L("Filename = %S, KeyName = iSupportsDefaultData,"), &initInfoFile);
       
   130 			RDebug::Print(_L("value = %S."), &result);
       
   131 			}
       
   132 		delete file;
       
   133 		TRAP(r,file=CIniData::NewL(KAuthSvrPolicyFile));
       
   134 		TPtrC displayMessage;
       
   135 		ret=file->FindVar(_L("SectionOne"),_L("DisplayMessage"),displayMessage);
       
   136 		if(displayMessage.Length() == 0)   //Value = 0
       
   137 			{
       
   138 			RDebug::Print(_L("DisplayMessage not passed."));
       
   139 			iClientMessage = iClientMessage->ReAllocL(0);	// Default value
       
   140 			TPtr ptr(iClientMessage->Des());
       
   141 			ptr = KNullDesC();
       
   142 			ret=file->SetValue(_L("SectionOne"),_L("DisplayMessage"),displayMessage);
       
   143 			TRAP(r,file->WriteToFileL());
       
   144 			}
       
   145 		else
       
   146 			{
       
   147 			iClientMessage = iClientMessage->ReAllocL(displayMessage.Length());
       
   148 			TPtr ptr(iClientMessage->Des());
       
   149 			ptr = displayMessage;
       
   150 			ret=file->SetValue(_L("SectionOne"),_L("DisplayMessage"),displayMessage);
       
   151 			TRAP(r,file->WriteToFileL());
       
   152 			}
       
   153 		delete file;
       
   154 		}
       
   155 			
       
   156 	}
       
   157 
       
   158 void CTPinAuthPlugin::ReloadActiveStateFromIniFile() const
       
   159 	{
       
   160 	// Set the file to be read, based on the Id of the plugin
       
   161 	
       
   162 	_LIT(KFileText, "\\tAuth\\tAuthSvr\\testdata\\Pin");
       
   163 	_LIT(KFileSuffix, "Db.ini");
       
   164 	
       
   165 	_LIT(KFormatFileName,"%S%x%S");
       
   166 	
       
   167 	TDriveUnit sysDrive (RFs::GetSystemDrive());
       
   168 	TBuf<64> fileText(sysDrive.Name());
       
   169 	fileText.Append(KFileText);
       
   170 	iFileToRead.Format(KFormatFileName,&fileText, Id(), &KFileSuffix);
       
   171 
       
   172 	//Read data from file to get initialisation information
       
   173 	
       
   174 	// Open and read in INI file
       
   175 	// Default path to look for INI file is in 'c:\system\data' 
       
   176 	// on target filesystem
       
   177 	
       
   178 	CIniData* file=NULL;
       
   179 	TRAPD(r,file=CIniData::NewL(iFileToRead));
       
   180 	
       
   181 	//Put file on the cleanupstack if anything else in this function is going to leave, but nothing does.	
       
   182 	
       
   183 	if(r!=KErrNone)
       
   184 		{
       
   185 		RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
       
   186 		}
       
   187 	
       
   188 	else
       
   189 		{
       
   190 		// Look for a key under a named section, retrieve text value	
       
   191 		TPtrC result;		
       
   192 		TBool ret=EFalse;	//return value from FindVar functions
       
   193 
       
   194 		// Set the active state of the plugin depending on the contents of the 
       
   195 		// corresponding file, which has been set as a member variable
       
   196 		ret =file->FindVar(_L("SectionOne"),_L("activeState"),result);
       
   197 		if(!ret)
       
   198 			{
       
   199 			RDebug::Print(_L("Key or section not found. iActiveState default value of ETRUE used."));			
       
   200 			iActiveState = ETrue;	// Default value
       
   201 			}
       
   202 		else
       
   203 			{
       
   204 			_LIT(KFalse,"false");
       
   205 			// Create a lower case copy of the data that is read from the file
       
   206 			TBuf<10> resultLowerCase;
       
   207 			resultLowerCase.Copy(result);
       
   208 			resultLowerCase.LowerCase();
       
   209 			if (resultLowerCase.FindF(KFalse) == KErrNotFound) 
       
   210 				iActiveState = ETrue;	// The string 'false' was not found, so we set the value to 'true' -the default value
       
   211 			else
       
   212 				iActiveState = EFalse;
       
   213 			}
       
   214 		TRAPD(r,file->WriteToFileL());
       
   215 		
       
   216 		if (KErrNone != r)
       
   217 			{
       
   218 			RDebug::Print(_L("Error occurred while writing to the file."));
       
   219 			TBuf<84> initInfoFile(sysDrive.Name());
       
   220 			initInfoFile.Append(KInitInfoFile);
       
   221 			RDebug::Print(_L("Filename = %S, KeyName = activeState,"), &initInfoFile);
       
   222 			RDebug::Print(_L("value = %S."), &result);
       
   223 			}
       
   224 		delete file;
       
   225 		}
       
   226 	}
       
   227 
       
   228 
       
   229 	
       
   230 //Implement CAuthPluginInterface definitions
       
   231 
       
   232 /**
       
   233  Normally, this would ask the user to input a 4-digit pin and then compare it to 
       
   234  the values that this plugin has been trained with. The result should be the 
       
   235  user that this PIN corresponds to.
       
   236  'aResult' should be the 'hash' of the stored PIN (which corresponds to the freshly entered PIN)
       
   237  but in this case, it's returned as it was 'unhashed'.
       
   238 */
       
   239 
       
   240 void CTPinAuthPlugin::Identify(TIdentityId& aId, const TDesC& aClientMessage,
       
   241 							   HBufC8*& aResult, TRequestStatus& aRequest)
       
   242 	{
       
   243 	ASSERT(IsActive());
       
   244 	
       
   245 	// We are simulating user input by reading from a file
       
   246 	// (The data contained in this file has been freshly written by the 'client part in TestExecute')
       
   247 	
       
   248 	if(aClientMessage != *ClientMessage())
       
   249 		{
       
   250 		TRequestStatus* status  = &aRequest;
       
   251 		User::RequestComplete(status, KErrGeneral);
       
   252 		RDebug::Print(_L("Display String Mismatch !!! ABORTING WITH KERRGENERAL"));
       
   253 		return;	
       
   254 		}
       
   255 	else
       
   256 		{
       
   257 		RDebug::Print(_L("Display String at the plugin matches the string sent !! "));
       
   258 		}
       
   259 	aRequest = KRequestPending;
       
   260 		
       
   261 	TBuf8<32> userInput;
       
   262 	TRAPD(result1, IdReadUserInput(userInput));	//Get the data from the AuthSvrPolicy.ini file
       
   263 	if (KErrNone != result1)
       
   264 		{
       
   265 		aRequest = result1;
       
   266 		}
       
   267 	else
       
   268 		{
       
   269 		// No errors, carry on					
       
   270 		//Convert the 8-bit string to a 16-bit string for printing in RDebug
       
   271 		HBufC* buf = 0;
       
   272 		buf = HBufC::New(32);
       
   273 		buf->Des().Copy(userInput);
       
   274 		_LIT(KMsgDebug1,"Identifying Userinput read from file = %S");    		
       
   275 		RDebug::Print(KMsgDebug1, buf);
       
   276 		delete buf;	//Memory cleanup. This string was only needed for the above Print function
       
   277 			
       
   278 		// Possibly, to allow for the cancellation or quitting, allow that to be the input string
       
   279 		_LIT8(KCancelText, "Cancel");	
       
   280 		_LIT8(KQuitText, "Quit");	
       
   281 		if (userInput == KCancelText)
       
   282 			{
       
   283 			TRequestStatus* status  = &aRequest;
       
   284 			User::RequestComplete(status, KErrAuthServPluginCancelled);
       
   285 			//aResult will not be updated, as specified
       
   286 			}
       
   287 		else if (userInput == KQuitText)
       
   288 			{
       
   289 			TRequestStatus* status  = &aRequest;
       
   290 			User::RequestComplete(status, KErrAuthServPluginQuit);
       
   291 			//aResult will not be updated, as specified
       
   292 			}
       
   293 		else
       
   294 			{
       
   295 			//compare with the known set of inputs and see if this is one of them.	
       
   296 			TInt result2 = CheckForStringPresence(aId, userInput, aRequest);
       
   297 			if (KErrNone == result2)	//The above function did not leave
       
   298 				{
       
   299 				//See if the string was found.
       
   300 				TInt length = userInput.Length();
       
   301 				
       
   302 				aResult = HBufC8::New(length);	
       
   303 				aResult->Des().Format(_L8("%S"), &userInput);
       
   304 				
       
   305 				RDebug::Printf("aResult has been updated. aResult = %S, userInput = %S", 
       
   306 									aResult, &userInput);
       
   307 				TRequestStatus* status  = &aRequest;
       
   308 				User::RequestComplete(status, result2);
       
   309 			
       
   310 				//Note: aRequest has been updated by the CheckForStringPresence function				
       
   311 				}
       
   312 			else if (KErrNotFound == result2)
       
   313 				{
       
   314 				RDebug::Printf("The data that the user input was not found (recognized)"
       
   315 								"Error = %d", result2);
       
   316 				
       
   317 				TRequestStatus* status  = &aRequest;
       
   318 				aId = KUnknownIdentity;
       
   319 				User::RequestComplete(status, KErrNone);
       
   320 				}			
       
   321 			else
       
   322 				{
       
   323 				//Caters for file access errors etc
       
   324 				RDebug::Printf("Error occurred while checking for the presence of the string"
       
   325 								"in the list. Error = %d", result2);
       
   326 				
       
   327 				TRequestStatus* status  = &aRequest;
       
   328 				aId = KUnknownIdentity;
       
   329 				User::RequestComplete(status, KErrNone);
       
   330 				}
       
   331 			}
       
   332 			//End of 'else' where the user did not cancel or quit the 'identify' process
       
   333 		}		
       
   334 	}
       
   335 	
       
   336 void CTPinAuthPlugin::Cancel()
       
   337 	{		
       
   338 	}
       
   339 
       
   340 void CTPinAuthPlugin::Train(TIdentityId aId, HBufC8*& aResult, TRequestStatus& aRequest)
       
   341 	{
       
   342 	
       
   343 	//Accept user input and update the list of inputs along with IDs.
       
   344 	
       
   345 ASSERT(IsActive());
       
   346 	
       
   347 	aRequest = KRequestPending;
       
   348 	//TInt result = KErrNone;
       
   349 	
       
   350 	TBuf8<32> userInput;
       
   351 	TRAPD(result1, TrainReadUserInput(userInput));
       
   352 	if (KErrNone != result1)
       
   353 		{
       
   354 		_LIT(KMsgDebug2,"Training Userinput read Error: result = %d");    
       
   355 		RDebug::Print(KMsgDebug2, result1);
       
   356 		}
       
   357 	else
       
   358 		{
       
   359 		// No errors, carry on		
       
   360 		//Convert the 8-bit string to a 16-bit string for printing in RDebug
       
   361 		HBufC* buf = 0;
       
   362 		buf = HBufC::New(32);
       
   363 		buf->Des().Copy(userInput);
       
   364 		_LIT(KMsgDebug3, "Training Userinput read from file = %S");
       
   365 		RDebug::Print(KMsgDebug3, buf);
       
   366 		delete buf;	//Memory cleanup. This string was only needed for the above Print function			
       
   367 		
       
   368 		// To allow for the cancellation or quitting, allow that to be the input string
       
   369 		TRequestStatus aRequest2 = KRequestPending;
       
   370 		_LIT8(KCancelText, "Cancel");
       
   371 		_LIT8(KQuitText, "Quit");
       
   372 		userInput.Trim();		
       
   373 		if (userInput.CompareF(KCancelText) == 0)
       
   374 			{ aRequest2 = KErrAuthServPluginCancelled; }		
       
   375 		else if (userInput.CompareF(KQuitText) == 0)
       
   376 			{ aRequest2 = KErrAuthServPluginQuit; }
       
   377 		else
       
   378 			{
       
   379 			//compare with the present set of inputs and see if this is one of them.
       
   380 			// update this list with this new user input, tagged to the aId
       
   381 			TRAPD(result2, CheckForNewStringPresenceL(aId, userInput, aRequest2));			
       
   382 			if (KErrNone != result2)
       
   383 				{
       
   384 				_LIT(KMsgDebug4, "Training Userinput read Error: results = %d");    
       
   385 				RDebug::Print(KMsgDebug4, result2);
       
   386 				}
       
   387 			else if(KErrNone == aRequest2.Int())
       
   388 				{
       
   389 				// No errors, update aResult.
       
   390 				// First allocate space for it since this variable will always be a 
       
   391 				// null pointer coming into this function
       
   392 				
       
   393 				aResult = HBufC8::New(userInput.Size());									
       
   394 				*aResult = userInput;
       
   395 				aRequest2 = KErrNone;
       
   396 				}			
       
   397 			else
       
   398 				{
       
   399 				_LIT(KMsgDebug5, "Error occurred during training. aRequest.Int() = %d");
       
   400 				RDebug::Print(KMsgDebug5, aRequest2.Int());
       
   401 				//aResult is not updated, nor is aId				
       
   402 				}
       
   403 			}
       
   404 		// Complete the asynchronous function
       
   405 		TRequestStatus* status  = &aRequest;
       
   406 		User::RequestComplete(status, aRequest2.Int());
       
   407 		}
       
   408 	}
       
   409 
       
   410 TBool CTPinAuthPlugin::IsActive () const
       
   411 	{
       
   412 	// There is never any user intervention required
       
   413 	//return true;
       
   414 	// As a future development note, this value may be read from a file (or a section in a file)
       
   415 	
       
   416 	ReloadActiveStateFromIniFile();
       
   417 	return iActiveState;
       
   418 	}
       
   419 	
       
   420 TInt CTPinAuthPlugin::Forget(TIdentityId aId)
       
   421 	{
       
   422 	// Open the list of userInputs that have been stored by this plugin
       
   423 	// Then find the one that corresponds to this id
       
   424 	// Then remove this string from the list and return the correct status value
       
   425 	
       
   426 	//Open the file
       
   427 	TRAPD(result3, FindStringAndRemoveL(aId));
       
   428 	return result3;
       
   429 			
       
   430 	}
       
   431 	
       
   432 TInt CTPinAuthPlugin::DefaultData(TIdentityId aId, HBufC8*& aOutputBuf)
       
   433 	{
       
   434 	
       
   435 	// This implementation of the PIN plugin does support default data.
       
   436 	// There will be cases where i don't want this available. Hence the addition of a 
       
   437 	// new class member iSupportsDefaultData
       
   438 	ReloadAllFromIniFile();
       
   439 	
       
   440 	TInt result = KErrNotSupported;
       
   441 	TRequestStatus aRequest2 = KRequestPending;
       
   442 	
       
   443 	if (iSupportsDefaultData)	//Class member initialised in the constructor
       
   444 		{
       
   445 		TBufC8<16> defaultBuf(KDefaultData);
       
   446 		//compare with the present set of inputs and see if this is one of them.
       
   447 		// update this list with this new user input, tagged to the aId
       
   448 		TRAPD(result2, CheckForNewStringPresenceL(aId, defaultBuf, aRequest2));			
       
   449 		if (KErrNone != result2)
       
   450 			{
       
   451 			_LIT(KMsgDebug4, "Training Userinput read Error: results = %d");    
       
   452 			RDebug::Print(KMsgDebug4, result2);
       
   453 			}
       
   454 		else if(KErrNone == aRequest2.Int())
       
   455 			{
       
   456 			// No errors, update aOutputBuf.
       
   457 			// First allocate space for it since this variable will always be a 
       
   458 			// null pointer coming into this function				
       
   459 			
       
   460 			TRAPD(resAlloc, (aOutputBuf = HBufC8::NewL(KDefaultData().Size())) );
       
   461 			if (KErrNone != resAlloc)
       
   462 				{
       
   463 				_LIT(KMsgAllocFailed2,"Failed to allocate memory for updating aOutputBuf");
       
   464 				RDebug::Print(KMsgAllocFailed2);
       
   465 				result = resAlloc;
       
   466 				}
       
   467 			else
       
   468 				{
       
   469 				*aOutputBuf = KDefaultData;
       
   470 				result = KErrNone;				
       
   471 				}
       
   472 			}			
       
   473 		else
       
   474 			{
       
   475 			_LIT(KMsgDebug5, "Error occurred during training. aRequest2.Int() = %d");
       
   476 			RDebug::Print(KMsgDebug5, aRequest2.Int());
       
   477 			//aOutputBuf is not updated, nor is aId				
       
   478 			}
       
   479 		}
       
   480 		
       
   481 	return result;	
       
   482 	}
       
   483 
       
   484 TInt CTPinAuthPlugin::Reset(TIdentityId/* aId*/, const TDesC&/* aRegistrationData*/, HBufC8*&/* aResult*/)
       
   485 	{
       
   486 	return KErrNotSupported;
       
   487 	}
       
   488 
       
   489 //--------------------------------------------------------------------------------
       
   490 
       
   491 /**
       
   492  Utility method to capture the data that the user has input 
       
   493  (in the form of data stored in a file)
       
   494 */
       
   495 TInt CTPinAuthPlugin::IdReadUserInput(TBuf8<32>& aInputValue)
       
   496 	{
       
   497 
       
   498 	TInt retValue;
       
   499 	CIniData* file=NULL;
       
   500 	TRAPD(r,file=CIniData::NewL(iFileToRead));
       
   501 	if(r!=KErrNone)
       
   502 		{
       
   503 		RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
       
   504 		retValue = r;
       
   505 		}
       
   506 	
       
   507 	else
       
   508 		{
       
   509 		// Look for a key under a named section, retrieve text value	
       
   510 		TPtrC result;		
       
   511 		TBool ret=EFalse;	//return value from FindVar functions
       
   512 		
       
   513 		ret=file->FindVar(_L("SectionOne"),_L("IdEnteredPinValue"),result);
       
   514 		if(!ret)
       
   515 			{
       
   516 			RDebug::Print(_L("Unable to find the key in the file %S. IdEnteredPinValue is not known, 9999 used. Error = %d"), &iFileToRead, ret);
       
   517 			_LIT8(KEnteredPinValueErr, "9999");
       
   518 			aInputValue = KEnteredPinValueErr;	// Default value
       
   519 			retValue = KErrNotFound;						
       
   520 			}
       
   521 		else
       
   522 			{
       
   523 			//Later,include a check to ensure that only digits were entered
       
   524 			aInputValue.Copy(result);
       
   525 			aInputValue.Trim();			
       
   526 			retValue = KErrNone;	//Not necessary
       
   527 			}
       
   528 		delete file;	//memory cleanup
       
   529 		}
       
   530 	
       
   531 	return retValue;
       
   532 	}
       
   533 
       
   534 TInt CTPinAuthPlugin::TrainReadUserInput(TBuf8<32>& aInputValue)
       
   535 	{
       
   536 
       
   537 	TInt retValue;
       
   538 	CIniData* file=NULL;
       
   539 	TRAPD(r,file=CIniData::NewL(iFileToRead));
       
   540 	if(r!=KErrNone)
       
   541 		{
       
   542 		RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
       
   543 		retValue = r;
       
   544 		}
       
   545 	
       
   546 	else
       
   547 		{
       
   548 		// Look for a key under a named section, retrieve text value	
       
   549 		TPtrC result;		
       
   550 		TBool ret=EFalse;	//return value from FindVar functions
       
   551 		
       
   552 		ret=file->FindVar(_L("SectionOne"),_L("TrainEnteredPinValue"),result);
       
   553 		if(!ret)
       
   554 			{
       
   555 			RDebug::Print(_L("Unable to find the key in the file %S. TrainEnteredPinValue is not known, 9999 used. Error = %d"), &iFileToRead, ret);
       
   556 			_LIT8(KEnteredPinValueErr, "9999");
       
   557 			aInputValue = KEnteredPinValueErr;	// Default value
       
   558 			retValue = KErrNotFound;						
       
   559 			}
       
   560 		else
       
   561 			{
       
   562    			aInputValue.Copy(result);
       
   563 			aInputValue.Trim();
       
   564 			retValue = KErrNone;	//Not necessary
       
   565 			}
       
   566 		delete file;	//memory cleanup
       
   567 		}
       
   568 	
       
   569 	return retValue;
       
   570 	}
       
   571 
       
   572 /**
       
   573  Utility method to compare the data that the user has input 
       
   574  with all the data that has been stored for users 
       
   575  Called by Identify()
       
   576  @return - success or failure value
       
   577 */
       
   578 TInt CTPinAuthPlugin::CheckForStringPresence(TIdentityId& aId, TBuf8<32> aInputValue, TRequestStatus& aRequestValue)
       
   579 	{
       
   580 
       
   581 	TInt retValue = KErrNone;	
       
   582 	// First format the aInputValue string so that it starts with a ':' and ends with a ','.
       
   583 	_LIT8(KFormatValue2, ":%S,");
       
   584 	TBuf8<32> aInputValue2;
       
   585 	aInputValue2.Format(KFormatValue2, &aInputValue);
       
   586 
       
   587 	//Convert the 8-bit string to a 16-bit string for printing in RDebug
       
   588 	HBufC* buf = 0;
       
   589 	buf = HBufC::New(32);
       
   590 	buf->Des().Copy(aInputValue);		
       
   591 	RDebug::Print(_L("Formatted string: %S"), buf);
       
   592 	delete buf;	//Memory cleanup. This string was only needed for the above Print function
       
   593 
       
   594 	TBuf8<500> pinFileContents1, pinFileContents2;
       
   595 	// Read the contents of the file that contains all the ID/PIN combinations
       
   596 
       
   597 	CIniData* file=NULL;
       
   598 	TRAPD(r,file=CIniData::NewL(iFileToRead));
       
   599 	if(r!=KErrNone)
       
   600 		{
       
   601 		RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
       
   602 		retValue = r;
       
   603 		}	
       
   604 	else
       
   605 		{
       
   606 		// Look for a key under a named section, retrieve text value	
       
   607 		TPtrC result;		
       
   608 		TBool ret=EFalse;	//return value from FindVar functions
       
   609 		
       
   610 		ret=file->FindVar(_L("SectionOne"),_L("Identity&PinValues"),result);
       
   611 		if(!ret)
       
   612 			{
       
   613 			RDebug::Print(_L("Unable to find the Identity&PinValues key in the file %S."), &iFileToRead);
       
   614 			retValue = KErrNotFound;
       
   615 			aRequestValue =KErrNotFound;
       
   616 			}
       
   617 		else
       
   618 			{
       
   619 			pinFileContents1.Copy(result);	
       
   620 			
       
   621 			TInt searchResult;
       
   622 			searchResult = pinFileContents1.Find(aInputValue2);
       
   623 			
       
   624 			if (KErrNotFound == searchResult)
       
   625 				{
       
   626 				RDebug::Print(_L("Userinput not found in the pinFile %S. Identification error"), &iFileToRead);
       
   627 				aRequestValue= KErrAuthServIdentityNotFound;
       
   628 				retValue  = searchResult;
       
   629 				}
       
   630 			else if (searchResult)	// a positive value
       
   631 				{				
       
   632 				// Now find the userID by searching back through the string for the "," marker				
       
   633 				pinFileContents2 = pinFileContents1.Left(searchResult);
       
   634 				TInt userIdStartPos = pinFileContents2.LocateReverse(',');
       
   635 								 
       
   636 				//Extract this userId for use by the calling function
       
   637 				TBuf8<50> p1 = pinFileContents2.Right(searchResult - userIdStartPos - 1);
       
   638 				TLex8 input (p1);
       
   639 				TRadix aRadix = EDecimal;
       
   640 				input.Val(aId, aRadix);
       
   641 				RDebug::Print(_L("UserId that is stored = %u"), aId);
       
   642 				aRequestValue = KErrNone;
       
   643 				retValue = KErrNone;
       
   644 				}				
       
   645 			else
       
   646 				{
       
   647 				RDebug::Print(_L("Unexpected error in the 'Find' function. Searchresult = %d"), searchResult);
       
   648 				aRequestValue = searchResult;
       
   649 				retValue = searchResult;				
       
   650 				}//End check for key&section search in file				
       
   651 			}//End check for safe file access
       
   652 		delete file;
       
   653 		}
       
   654 	
       
   655 	return retValue;
       
   656 	}
       
   657 
       
   658 /**
       
   659  Utility method to compare the data that the user has input 
       
   660  with all the data that has been stored for users 
       
   661  Used to find out if the input is unique. 
       
   662  -since KIdAmbiguous is no longer used, KIdCancel will be returned if the input is non-unique
       
   663  Called by Train() and DefaultData()
       
   664 */
       
   665 TInt CTPinAuthPlugin::CheckForNewStringPresenceL(TIdentityId aId, TBuf8<32> aInputValue, TRequestStatus& aRequestValue)
       
   666 	{	
       
   667 	TBuf8<500> pinFileContents, pinFileContents2;
       
   668 	TInt retValue = KErrNone;
       
   669 
       
   670 	CIniData* file=NULL;
       
   671 	TRAPD(r,file=CIniData::NewL(iFileToRead));
       
   672 		
       
   673 	if(r!=KErrNone)
       
   674 		{
       
   675 		RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
       
   676 		return r;
       
   677 		}	
       
   678 	
       
   679 	// Look for a key under a named section, retrieve text value	
       
   680 	TPtrC result;		
       
   681 	TBool ret=EFalse;	//return value from FindVar functions
       
   682 	aRequestValue = KErrAuthServIdentityNotFound;	//Initialisation		
       
   683 			
       
   684 	ret=file->FindVar(KPluginIniSection, KPinDbTag,result);
       
   685 	if(!ret)
       
   686 		{
       
   687 		RDebug::Print(_L("Unable to find the %S key in the file %S."), &KPinDbTag, &iFileToRead);
       
   688 		delete file;
       
   689 		return KErrNotFound;			
       
   690 		}
       
   691 	
       
   692 	//Copy the data from the named section in the file, and see if any previous user has used this input string
       
   693 	pinFileContents.Copy(result);			
       
   694 	
       
   695 	TInt searchResultPin;
       
   696 	TBuf8<50> searchStringPin;
       
   697 	_LIT8(KFormat3, ":%S,");
       
   698 	searchStringPin.Format(KFormat3, &aInputValue);
       
   699 	searchResultPin = pinFileContents.Find(searchStringPin);
       
   700 				
       
   701 	if (KErrNotFound == searchResultPin)
       
   702 		{				
       
   703 		//check that the identity is unique, if so, update the Db 
       
   704 		// with the new Id-PIN pair, as is done already
       
   705 		// else update the PIN only, ie training data for that identity
       
   706 		TInt searchResultId;
       
   707 		TBuf8<50> searchStringId;
       
   708 		_LIT8(KFormat4, ",%u:");
       
   709 		searchStringId.Format(KFormat4, aId);
       
   710 		
       
   711 		searchResultId = pinFileContents.Find(searchStringId);
       
   712 		
       
   713 		TDriveUnit sysDrive (RFs::GetSystemDrive());
       
   714 		TBuf<80> policyFile;
       
   715 		if (KErrNotFound == searchResultId)
       
   716 			{									
       
   717 			// Add this entry to the file
       
   718 			// This is a simple system, expecting a format as below:
       
   719 			// ",aId:inputPin,aId:inputPin,aId:inputPin,"				
       
   720 			
       
   721 			_LIT8(KFormat2, "%S%u:%S,");
       
   722 			if (pinFileContents.Size() == 0)
       
   723 				{
       
   724 				pinFileContents.Append(',');	//Initialisation
       
   725 				}
       
   726 			pinFileContents2.Format(KFormat2, &pinFileContents, aId, &aInputValue);				
       
   727 										
       
   728 			//For the purpose of writing the data to a file, i'll create a 16-bit version of pinFileContents
       
   729 			TInt ret2 = 0;
       
   730 			HBufC* buf = 0;
       
   731 			buf = HBufC::NewL(pinFileContents2.Length());
       
   732 			buf->Des().Copy(pinFileContents2);												
       
   733 			ret2 = file->SetValue(_L("SectionOne"),_L("Identity&PinValues"), *buf);
       
   734 			
       
   735 			TRAPD(r,file->WriteToFileL());
       
   736 			
       
   737 						
       
   738 			if (KErrNone != r)
       
   739 				{
       
   740 				policyFile.Copy(sysDrive.Name());
       
   741 				policyFile.Append(KPolicyFile);
       
   742 				RDebug::Print(_L("Error occurred while writing to the file. Filename = %S, KeyName = AllUserID&PinValues, value = %S."), &policyFile, buf);
       
   743 				}
       
   744 			delete buf;		//Memory cleanup. This string was only needed for the above Print function
       
   745 			
       
   746 			if(KErrNone == ret2)
       
   747 				{				
       
   748 				aRequestValue = KErrNone;
       
   749 				
       
   750 				//Update the global database
       
   751 				AddToGlobalDb(aId, aInputValue);
       
   752 				}
       
   753 			else
       
   754 				{
       
   755 				RDebug::Print(_L("Error occurred while writing data to file. Error = %d"), ret2);					
       
   756 				aRequestValue = ret2;
       
   757 				}
       
   758 			
       
   759 			}
       
   760 
       
   761 		else
       
   762 			{
       
   763 			//The Identity has already been trained with this plugin, 
       
   764 			// update the PIN (training data)
       
   765 			
       
   766 			//extract the string to the right of the end of the aId
       
   767 			pinFileContents2 = pinFileContents.Mid(searchResultId + searchStringId.Size());
       
   768 			
       
   769 			//Find the end of the PIN (Training data)
       
   770 			_LIT8(KPinEndMarker, ",");
       
   771 			TBufC8<5> bufPinEndMarker(KPinEndMarker);					
       
   772 			TInt pinEndPos = pinFileContents2.Find(bufPinEndMarker);
       
   773 			
       
   774 			//Replace this with the new PIN
       
   775 			pinFileContents.Replace((searchResultId + searchStringId.Size()),
       
   776 									 pinEndPos, aInputValue);	
       
   777 			
       
   778 			//For the purpose of writing the data to a file, i'll create a 16-bit version of pinFileContents
       
   779 			TInt ret2 = 0;
       
   780 			HBufC* buf = 0;
       
   781 			buf = HBufC::NewL(pinFileContents.Length());
       
   782 			buf->Des().Copy(pinFileContents);
       
   783 								
       
   784 			ret2 = file->SetValue(_L("SectionOne"),_L("Identity&PinValues"), *buf);
       
   785 			
       
   786 			TRAPD(r,file->WriteToFileL());
       
   787 			
       
   788 			if (KErrNone != r)
       
   789 				{
       
   790 				policyFile.Copy(sysDrive.Name());
       
   791 				policyFile.Append(KPolicyFile);
       
   792 				RDebug::Print(_L("Error occurred while writing to the file. Filename = %S, KeyName = AllUserID&PinValues, value = %S."), &policyFile, buf);
       
   793 				}
       
   794 			delete buf;		//Memory cleanup. This string was only needed for the above Print function
       
   795 			
       
   796 			if(KErrNone ==ret2)
       
   797 				{				
       
   798 				aRequestValue = KErrNone;
       
   799 				
       
   800 				//Update the global database
       
   801 				AddToGlobalDb(aId, aInputValue);
       
   802 				}
       
   803 			else
       
   804 				{
       
   805 				RDebug::Print(_L("Error occurred while writing data to file. Error = %d"), ret2);					
       
   806 				aRequestValue = ret2;
       
   807 				}
       
   808 			}
       
   809 		delete file;
       
   810 		return ret;
       
   811 		}
       
   812 	if (searchResultPin)	// a positive value
       
   813 		{
       
   814 		// A user has already tried to train this plugin using the given data.
       
   815 		// The pinFileContents are not updated, to avoid duplication
       
   816 		
       
   817 		aRequestValue = KErrAuthServPluginCancelled;
       
   818 		delete file;
       
   819 		return searchResultPin;
       
   820 		}	
       
   821 	
       
   822 	RDebug::Print(_L("Unexpected error in the 'Find' function. SearchresultPin = %d"), searchResultPin);
       
   823 	retValue = searchResultPin;
       
   824 
       
   825 	delete file;
       
   826 		
       
   827 	return retValue;
       
   828 	}
       
   829 
       
   830 	
       
   831 /**
       
   832  Utility function to remove the training data that is associated with a given Id
       
   833  Called by the Forget function
       
   834  @return - KIdSuccess, KIdUnknown or some error code  
       
   835  */ 
       
   836 TInt CTPinAuthPlugin::FindStringAndRemoveL (TIdentityId aId)
       
   837 	{
       
   838 	TBuf8<500> pinFileContents, pinFileContents2;
       
   839 	TInt retValue = KErrAuthServNoSuchIdentity;		//init
       
   840 	CIniData* file=NULL;
       
   841 	//First read the list of userId and PIN combinations from a file
       
   842 	TRAPD(r,file=CIniData::NewL(iFileToRead));
       
   843 	if(r!=KErrNone)
       
   844 		{
       
   845 		RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
       
   846 		retValue = r;
       
   847 		}	
       
   848 	else
       
   849 		{
       
   850 		// Look for a key under a named section, retrieve text value	
       
   851 		TPtrC result;		
       
   852 		TBool ret=EFalse;	//return value from FindVar functions
       
   853 				
       
   854 		ret=file->FindVar(KPluginIniSection, KPinDbTag,result);
       
   855 		if(!ret)
       
   856 			{
       
   857 			RDebug::Print(_L("Config error: Unable to find the %S key in the file %S."), &KPinDbTag, &iFileToRead);
       
   858 			retValue = KErrNotFound;						
       
   859 			}
       
   860 		else
       
   861 			{
       
   862 			//Copy the data from the named section in the file, and see if any previous user has used this input string
       
   863 			pinFileContents.Copy(result);				
       
   864 			
       
   865 			//Format the searchstring as defined in the file so that it starts with a ',' and ends with a ':'.
       
   866 			_LIT8(KFormatValue3, ",%u:");			
       
   867 			
       
   868 			TBuf8<32> searchString;
       
   869 			searchString.Format(KFormatValue3, aId);
       
   870 
       
   871 			//For the purpose of printing the data to a file, i'll create a 16-bit version of pinFileContents
       
   872 			HBufC* buf = 0;
       
   873 			buf = HBufC::NewL(searchString.Length());
       
   874 			buf->Des().Copy(searchString);
       
   875 			RDebug::Print(_L("Formatted searchString used in 'FindStringAndRemove(): %S"), buf);
       
   876 			delete buf;
       
   877 
       
   878 			TInt userIdStartPos;	//The offset of the searchString within pinFileContents
       
   879 									//i.e the position of the '.' just before the identityId
       
   880 			userIdStartPos = pinFileContents.Find(searchString);
       
   881 			if (KErrNotFound == userIdStartPos)
       
   882 				{
       
   883 				RDebug::Print(_L("FindStringAndRemoveL: The specified ID was not found in the pinFile"));
       
   884 				retValue = KErrAuthServNoSuchIdentity;	//KIdUnknown;
       
   885 				}
       
   886 			else
       
   887 				{
       
   888 				
       
   889 				//Find where the string (including PIN) ends
       
   890 				TLex8 aLex = TLex8(pinFileContents);
       
   891 				TInt length(0);
       
   892 				aLex.Inc(userIdStartPos+1);
       
   893 				while(aLex.Peek() != ',') 
       
   894 					{
       
   895 					aLex.Inc();
       
   896 					length++;
       
   897 					}
       
   898 								
       
   899 				//remove the found (total) string from the list (including the starting ',')
       
   900 				pinFileContents.Delete(userIdStartPos,length+1);
       
   901 				
       
   902 				//Update the file
       
   903 				//For the purpose of writing the data to a file, i'll create a 16-bit version of pinFileContents
       
   904 				TInt ret2 = 0;
       
   905 				HBufC* buf;
       
   906 				buf = HBufC::NewL(pinFileContents.Length());	
       
   907 				buf->Des().Copy(pinFileContents);
       
   908 								
       
   909 				ret2 = file->SetValue(KPluginIniSection, KPinDbTag, *buf);
       
   910 				
       
   911 				TRAPD(r,file->WriteToFileL());
       
   912 				TDriveUnit sysDrive (RFs::GetSystemDrive());
       
   913 				TBuf<2> sysDriveName (sysDrive.Name());
       
   914 				TBuf<84> policyFile;
       
   915 								
       
   916 				if (KErrNone != r)
       
   917 					{
       
   918 					policyFile.Copy(sysDriveName);
       
   919 					policyFile.Append(KPolicyFile);
       
   920 					RDebug::Print(_L("Error occurred while writing to the file. Filename = %S, KeyName = AllUserID&PinValues, value = %S."), &policyFile, buf);
       
   921 					}
       
   922 				delete buf;		//Memory cleanup. This string was only needed for the above Print function
       
   923 				
       
   924 				if (KErrNone !=ret2)
       
   925 					{
       
   926 					policyFile .Copy(sysDriveName);
       
   927 					policyFile.Append(KAuthSvrPolicyFile);
       
   928 					RDebug::Print(_L("Error occurred in WriteToFileL(). Error = %d. Filename= %S"), ret2, &policyFile);
       
   929 					retValue = ret2;
       
   930 					}
       
   931 				else
       
   932 					{
       
   933 					retValue = KErrNone;		
       
   934 					}				
       
   935 				}			
       
   936 			}//End check for key&section search in file
       
   937 		delete file;
       
   938 		}//End check for safe file access
       
   939 	
       
   940 	return retValue;
       
   941 	}
       
   942 
       
   943 
       
   944 /**
       
   945  Utility function to Update the Global Db with the training data 
       
   946  that is associated with a given Id. The update will not happen if 
       
   947  the identity is already present in this list, i.e. it's been pu in 
       
   948  by another plugin
       
   949  Called by the CheckForNewStringPresence function
       
   950  @return - KErrNone, or some error code
       
   951 */
       
   952 TInt CTPinAuthPlugin::AddToGlobalDb (TIdentityId aId, TBuf8<32> aInputValue)
       
   953 	{
       
   954 	
       
   955 	TBuf8<500> totalDbFileContents, totalDbFileContents2;
       
   956 	TInt retValue = KErrNone;
       
   957 	CIniData* file=NULL;
       
   958 	
       
   959 	TDriveUnit sysDrive (RFs::GetSystemDrive());
       
   960 	TDriveName sysDriveName (sysDrive.Name());
       
   961 	TBuf<128> authSvrPolicyFile(sysDriveName);
       
   962 	authSvrPolicyFile.Append(KAuthSvrPolicyFile);
       
   963 	
       
   964 	TRAPD(r,file=CIniData::NewL(authSvrPolicyFile));	
       
   965 	if(r!=KErrNone)
       
   966 		{
       
   967 		RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &authSvrPolicyFile);
       
   968 		retValue = r;
       
   969 		}	
       
   970 	else
       
   971 		{
       
   972 		// Look for a key under a named section, retrieve text value	
       
   973 		TPtrC result;		
       
   974 		TBool ret=EFalse;	//return value from FindVar functions		
       
   975 				
       
   976 		ret=file->FindVar(KPluginIniSection, KTotalDbTag,result);
       
   977 		if(!ret)
       
   978 			{
       
   979 			RDebug::Print(_L("Unable to find the %S key in the file %S."), &KTotalDbTag, &authSvrPolicyFile);
       
   980 			retValue = KErrNotFound;		
       
   981 			}
       
   982 		else
       
   983 			{
       
   984 			//Copy the data from the named section in the file, and see if any previous user has used this input string
       
   985 			totalDbFileContents.Copy(result);
       
   986 			TBuf8<20> aidString;
       
   987 			aidString.Num(aId, EDecimal);			
       
   988 			TInt searchResult;			
       
   989 			searchResult = totalDbFileContents.Find(aidString);
       
   990 			
       
   991 			if (KErrNotFound == searchResult)
       
   992 				{
       
   993 				// Add this entry to the file
       
   994 				// This is a simple system, expecting a format as below:
       
   995 				// ",aId:inputPin,aId:inputPin,aId:inputPin,"				
       
   996 				_LIT8(KFormat2, "%S%u:%S,");
       
   997 				if (totalDbFileContents.Size() == 0)
       
   998 					{					
       
   999 					totalDbFileContents.Append(',');	//Initialisation
       
  1000 					}
       
  1001 				totalDbFileContents2.Format(KFormat2, &totalDbFileContents, aId, &aInputValue);				
       
  1002 					
       
  1003 				//For the purpose of writing the data to a file, i'll create a 16-bit version of pinFileContents
       
  1004 				TInt ret2 = 0;
       
  1005 				HBufC* buf = 0;
       
  1006 				buf = HBufC::New(totalDbFileContents2.Length());
       
  1007 				buf->Des().Copy(totalDbFileContents2);								
       
  1008 				ret2 = file->SetValue(KPluginIniSection, KTotalDbTag, *buf);
       
  1009 				
       
  1010 				TRAPD(r,file->WriteToFileL());
       
  1011 									
       
  1012 				if (KErrNone != r)
       
  1013 					{
       
  1014 					TBuf<80> policyFile(sysDriveName);
       
  1015 					policyFile.Append(KPolicyFile);
       
  1016 					RDebug::Print(_L("Error occurred while writing to the file. Filename = %S, KeyName = AllUserID&PinValues, value = %S."), &policyFile, buf);
       
  1017 					}
       
  1018 				delete buf;		//Memory cleanup. This string was only needed for the above Print function
       
  1019 				
       
  1020 				if (KErrNone !=ret2)
       
  1021 					{
       
  1022 					RDebug::Print(_L("Error occurred in SetValue(). Error = %d. Filename= %S"), ret2, &authSvrPolicyFile);
       
  1023 					retValue = ret2;
       
  1024 					}
       
  1025 				}
       
  1026 			else
       
  1027 				{
       
  1028 				// A user has already tried to train this plugin using the given data.
       
  1029 				// The pinFileContents are not updated, to avoid duplication				
       
  1030 				retValue = KErrNone;													
       
  1031 				}//End aidString search in the totalDbFileContents string (Find())
       
  1032 			}//End check for key&section search in file (FindVar())
       
  1033 			delete file;
       
  1034 		}//End check for safe file access
       
  1035 	return retValue;
       
  1036 	}
       
  1037 const HBufC* CTPinAuthPlugin::ClientMessage()
       
  1038 	{
       
  1039 	return iClientMessage;
       
  1040 	}
       
  1041 
       
  1042 const TPtrC& CTPinAuthPlugin::Name() const
       
  1043   {
       
  1044   return iName;
       
  1045   }
       
  1046 const TPtrC& CTPinAuthPlugin::Description() const
       
  1047   {
       
  1048   return iDescription;
       
  1049   }
       
  1050 AuthServer::TAuthPluginType CTPinAuthPlugin::Type() const 
       
  1051   {
       
  1052   return iType;
       
  1053   }
       
  1054 
       
  1055 AuthServer::TEntropy CTPinAuthPlugin::MinEntropy() const
       
  1056   {
       
  1057   return iMinEntropy;
       
  1058   }
       
  1059 
       
  1060 AuthServer::TPercentage CTPinAuthPlugin::FalsePositiveRate() const
       
  1061   {
       
  1062   return iFalsePositiveRate;
       
  1063   }
       
  1064 
       
  1065 AuthServer::TPercentage CTPinAuthPlugin::FalseNegativeRate() const
       
  1066   {
       
  1067   return iFalseNegativeRate;
       
  1068   }