authenticationservices/authenticationserver/test/reftestplugin/pinplugin/pinplugindb.cpp
branchRCL_3
changeset 61 641f389e9157
parent 29 ece3df019add
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticationservices/authenticationserver/test/reftestplugin/pinplugin/pinplugindb.cpp	Tue Aug 31 17:00:08 2010 +0300
@@ -0,0 +1,402 @@
+/*
+* Copyright (c) 2006-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: 
+* CPinPluginDB pin plugin data store implementation
+*
+*/
+
+
+/**
+ @file 
+*/
+
+#include "pinplugindb.h"
+
+_LIT(KPluginStoreName, "plugin.store");
+_LIT(KFileDrive, "c:");
+
+using namespace AuthServer;
+
+CPinPluginDB* CPinPluginDB::NewL()
+	{
+	CPinPluginDB* self = CPinPluginDB::NewLC();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CPinPluginDB* CPinPluginDB::NewLC()
+	{
+	CPinPluginDB* self = new(ELeave) CPinPluginDB();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+	
+CPinPluginDB::CPinPluginDB() :
+	iRootStreamId(KNullStreamId),
+	iIdentityStreamId(KNullStreamId)
+	{
+	}
+
+CPinPluginDB::~CPinPluginDB()
+	{
+	if (iFileStore)
+		{
+		CompactStore();
+		delete iFileStore;
+		}
+
+	iFile.Close(); 
+	iFs.Close();
+
+	iId.Reset();
+	iId.Close();
+	iIdKeyHash.ResetAndDestroy();
+	iIdKeyHash.Close();
+	}
+	
+		
+void CPinPluginDB::ConstructL()
+	{
+	User::LeaveIfError(iFs.Connect());
+	
+	TFileName privatePath;
+	iFs.PrivatePath(privatePath);
+	iPluginDBName.Copy(KFileDrive);
+	iPluginDBName.Append(privatePath);
+	iPluginDBName.Append(KPluginStoreName);
+	OpenStoreL();
+	
+	ReadIdKeysFromStoreL();
+	}
+
+
+void CPinPluginDB::AddPinL(const TIdentityId& aId, const TDesC8& aIdentityKeyHash)
+	{
+	if(IdIndex(aId) == KErrNotFound && IsUniquePin(aIdentityKeyHash))
+		{
+		// Add the IdentityId to the array, rewrite the identitystream and 
+		// Only then commit the store
+		HBufC8* keyHash = aIdentityKeyHash.AllocLC();
+		TInt err = KErrNone;
+		iIdKeyHash.AppendL(keyHash);
+		err = iId.Append(aId);
+		if(err != KErrNone)
+			{
+			iIdKeyHash.Remove(iIdKeyHash.Count() - 1);
+			User::Leave(err);
+			}
+		TCleanupItem cleanupStore(RevertStore, iFileStore);
+		// write the idkeys to the store.
+		TRAP(err,
+			CleanupStack::PushL(cleanupStore);
+			WriteIdKeysToStoreL();
+			CleanupStack::Pop(iFileStore));
+
+		if (err != KErrNone)
+			{
+			iId.Remove(iId.Count() - 1);
+			iIdKeyHash.Remove(iIdKeyHash.Count() - 1);
+			User::Leave(err);
+			}
+		CleanupStack::Pop(keyHash); 
+		}
+	else
+		{
+		User::Leave(KErrAlreadyExists);
+		}
+ 	}
+
+void CPinPluginDB::UpdatePinL(const TIdentityId& aId, const TDesC8& aIdentityKeyHash)
+	{
+	if(IdIndex(aId) != KErrNotFound)
+		{
+		// Get the index of the existing id and key hash
+		TInt index = IdIndex(aId);
+		TInt err = KErrNone;
+		HBufC8* keyHash = aIdentityKeyHash.AllocLC();
+		// delete the old keyHash and store the new keyHash to the index
+		delete iIdKeyHash[index];
+		iIdKeyHash[index] = keyHash;
+
+		TCleanupItem cleanupStore(RevertStore, iFileStore);
+		// write the idkeys to the store.
+		TRAP(err ,
+			CleanupStack::PushL(cleanupStore);
+			WriteIdKeysToStoreL();
+			CleanupStack::Pop(iFileStore));
+		if (err!= KErrNone)
+			{
+			CleanupStack::Pop(keyHash);
+			ReadIdKeysFromStoreL();
+			User::Leave(err);
+			}
+		CleanupStack::Pop(keyHash);
+		}
+	else
+		{
+		User::Leave(KErrNotFound);
+		}
+	}
+	
+void CPinPluginDB::RemovePinL(const TIdentityId& aId)
+	{
+	if(IdIndex(aId) != KErrNotFound)
+		{
+		TInt err = KErrNone;
+		TInt index = IdIndex(aId);
+
+		// Delete the IdentityId from the array, rewrite the identitystream and 
+	   	// Only then commit the store
+		delete iIdKeyHash[index];
+  		iIdKeyHash.Remove(index);
+   		iId.Remove(index);
+ 
+		TCleanupItem cleanupStore(RevertStore, iFileStore);
+		// write the idkeys to the store.
+		TRAP(err, 
+			CleanupStack::PushL(cleanupStore);
+			WriteIdKeysToStoreL();
+			CleanupStack::Pop(iFileStore));
+		if(err != KErrNone)
+			{
+			ReadIdKeysFromStoreL();
+   			User::Leave(err);
+			}
+		}
+	else
+		{
+		User::Leave(KErrNotFound);
+		}
+	}
+	
+TBool CPinPluginDB::IsUniquePin(const TDesC8& aIdentityKeyHash) const
+	{
+	//	Check each iIdKeyHash in the store to determine if aIdentityId already exists
+	TInt count = iIdKeyHash.Count();
+	TBool isUnique = ETrue;
+	for (TInt index = 0; index < count; ++index)
+		{
+		if (aIdentityKeyHash.CompareF(*iIdKeyHash[index]) == 0)
+			{
+			isUnique = EFalse;
+			break;
+			}
+		}
+	return isUnique;
+	}
+	
+TInt CPinPluginDB::IdIndex(const TIdentityId& aId) const
+	{
+	TInt count = iId.Count();
+	for (TInt index = 0; index < count; ++index)
+		{
+		if (aId == iId[index])
+			{
+			return index;
+			}
+		}
+	return KErrNotFound;
+	}
+	
+TIdentityId CPinPluginDB::IdFromPin(const TDesC8& aIdentityKeyHash) const
+	{
+	TInt count = iIdKeyHash.Count();
+	for (TInt index = 0; index < count; ++index)
+		{
+		if (aIdentityKeyHash.CompareF(*iIdKeyHash[index]) == 0)
+			{
+			return iId[index];
+			}
+		}
+	return KUnknownIdentity;
+	}
+	
+void CPinPluginDB::OpenStoreL()
+	{
+	//	Tries to Open a plugin store file on the private path of the process. 
+	//	If it cannot find one, create a file with permanent file store
+	//	it should initialise iFileStore unless it cannot
+	//	create the file/store/streams
+	
+	TRAPD(result, OpenStoreInFileL(iPluginDBName));
+
+	if (result == KErrNotFound || result == KErrPathNotFound) 
+		{		
+		// Not yet opened a valid store, either no file to be found, or no valid
+		// store in it.
+		CreateStoreInFileL(iPluginDBName);
+		}
+	else if (result != KErrNone)
+		{
+		// DB gets corrupted or File may be in use. Abort startup.
+		User::Leave(result);
+		}
+	}
+
+
+void CPinPluginDB::CreateStoreInFileL(const TDesC& aFile)
+	{
+	TInt r = iFs.MkDirAll(aFile);
+	if ((r!=KErrNone) && (r!=KErrAlreadyExists))
+		{
+		User::Leave(r);
+		}
+	
+	delete iFileStore;
+	iFileStore = NULL;
+
+	iFileStore = CPermanentFileStore::ReplaceL(iFs, aFile, EFileRead | EFileWrite | EFileStream | EFileShareExclusive);
+	iFileStore->SetTypeL(KPermanentFileStoreLayoutUid);
+
+	TCleanupItem cleanupStore(RevertStore, iFileStore);
+	CleanupStack::PushL(cleanupStore);
+	
+	// Create Identity stream - Currently no Identity created, and no IdentityKeyHash
+	RStoreWriteStream identityStream;
+	iIdentityStreamId = identityStream.CreateLC(*iFileStore);
+	identityStream.WriteUint32L(KNullStreamId.Value()); //contains the id of dataStream
+	identityStream.WriteUint32L(0); // Write IdentityId count of zero
+	identityStream.CommitL();
+	CleanupStack::PopAndDestroy(&identityStream);
+
+	// Create root stream - just contains id of Identity stream
+	RStoreWriteStream rootStream;
+	iRootStreamId = rootStream.CreateLC(*iFileStore);
+	iFileStore->SetRootL(iRootStreamId);
+	rootStream.WriteUint32L(iIdentityStreamId.Value());		
+	rootStream.CommitL();
+	CleanupStack::PopAndDestroy(&rootStream);
+	
+	iFileStore->CommitL();
+	CleanupStack::Pop(iFileStore); 
+	}
+
+void CPinPluginDB::OpenStoreInFileL(const TDesC& aFile)
+	{
+	// Make sure the file isn't write protected
+	User::LeaveIfError(iFs.SetAtt(aFile, 0, KEntryAttReadOnly));
+	
+	User::LeaveIfError(iFile.Open(iFs, aFile, EFileRead | EFileWrite | EFileStream | EFileShareExclusive));
+	
+	delete iFileStore;
+	iFileStore = NULL;
+
+	iFileStore = CPermanentFileStore::FromL(iFile);		
+
+	// Get the root StreamId
+	iRootStreamId = iFileStore->Root();
+	if (iRootStreamId == KNullStreamId)
+		{
+		User::Leave(KErrCorrupt);
+		}
+	
+	RStoreReadStream rootStream;
+	rootStream.OpenLC(*iFileStore, iRootStreamId);
+	iIdentityStreamId = (TStreamId)(rootStream.ReadUint32L());
+	CleanupStack::PopAndDestroy(&rootStream);
+	}
+
+// Rewrites the Identity stream (ie the array of IdentityId) to the store
+void CPinPluginDB::WriteIdKeysToStoreL()
+	{
+	TInt count = iId.Count();
+	TInt hashCount = iIdKeyHash.Count();
+	if (count != hashCount)
+		{
+		User::Leave(KErrCorrupt);
+		}
+	
+	TStreamId dataStreamId = KNullStreamId;
+	if (count > 0)
+		{
+		RStoreWriteStream dataStream;
+		dataStreamId = dataStream.CreateLC(*iFileStore);
+		//write the Identity Id key to a data stream
+		for (TInt index = 0; index < count; ++index)
+			{
+			dataStream.WriteUint32L(iId[index]);
+			dataStream.WriteUint32L((*iIdKeyHash[index]).Length());
+			dataStream.WriteL(*iIdKeyHash[index]);
+			}
+		dataStream.CommitL();
+		CleanupStack::PopAndDestroy(&dataStream); 	
+		}
+	RStoreReadStream readStream;
+	readStream.OpenLC(*iFileStore, iIdentityStreamId);
+	TStreamId oldDataStreamId = (TStreamId)(readStream.ReadInt32L());
+	CleanupStack::PopAndDestroy(&readStream);
+		
+	iFileStore->DeleteL(oldDataStreamId);
+	
+	RStoreWriteStream writeStream;
+	writeStream.OpenLC(*iFileStore, iIdentityStreamId);
+	writeStream.WriteUint32L(dataStreamId.Value());
+	writeStream.WriteInt32L(count);
+	writeStream.CommitL();
+	CleanupStack::PopAndDestroy(&writeStream); 	
+	iFileStore->CommitL();
+	CompactStore();
+	}
+	
+void CPinPluginDB::ReadIdKeysFromStoreL()
+	{
+	iId.Reset();
+	iIdKeyHash.ResetAndDestroy();
+	
+	RStoreReadStream readStream;
+	readStream.OpenLC(*iFileStore, iIdentityStreamId);
+	TStreamId dataStreamId = (TStreamId)(readStream.ReadInt32L());
+	TInt count = readStream.ReadInt32L();
+	CleanupStack::PopAndDestroy(&readStream);
+	
+	if (count > 0)
+		{
+		RStoreReadStream dataStream;
+		dataStream.OpenLC(*iFileStore, dataStreamId);
+		for (TInt index = 0; index < count; ++index)
+			{
+			TIdentityId identityId = (TIdentityId)(dataStream.ReadInt32L());
+			iId.AppendL(identityId);
+			TInt length = dataStream.ReadInt32L();
+			HBufC8* idKeyHash = HBufC8::NewMaxLC(length);
+			TPtr8 idKeyHashPtr = idKeyHash->Des();
+			dataStream.ReadL(idKeyHashPtr, length);
+			iIdKeyHash.AppendL(idKeyHash);
+			CleanupStack::Pop(idKeyHash);
+			}
+		CleanupStack::PopAndDestroy(&dataStream);
+		}
+	}
+
+void CPinPluginDB::RevertStore(TAny* aStore)
+	{
+	CPermanentFileStore* store = reinterpret_cast<CPermanentFileStore*>(aStore);
+	TRAP_IGNORE(store->RevertL());
+	// We're ignoring the leave code from this becuase there's no way we can
+	// handle this sensibly.  This shouldn't be a problem in practice - this
+	// will leave if for example the file store is on removable which is
+	// unexpectedly remove, and this is never the case for us.
+	}
+
+
+void CPinPluginDB::CompactStore()
+	{
+	ASSERT(iFileStore);
+	TRAP_IGNORE(iFileStore->ReclaimL(); iFileStore->CompactL());
+	}
+
+
+
+