diff -r 880bdb445c5c -r c0e7917aa107 authenticationservices/authenticationserver/test/reftestplugin/pinplugin/pinplugindb.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/authenticationservices/authenticationserver/test/reftestplugin/pinplugin/pinplugindb.cpp Sat Dec 05 21:41:51 2009 +0000 @@ -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(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()); + } + + + +