authenticationservices/authenticationserver/test/reftestplugin/pinplugin/pinplugindb.cpp
changeset 29 ece3df019add
equal deleted inserted replaced
19:cd501b96611d 29:ece3df019add
       
     1 /*
       
     2 * Copyright (c) 2006-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 * CPinPluginDB pin plugin data store implementation
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 /**
       
    21  @file 
       
    22 */
       
    23 
       
    24 #include "pinplugindb.h"
       
    25 
       
    26 _LIT(KPluginStoreName, "plugin.store");
       
    27 _LIT(KFileDrive, "c:");
       
    28 
       
    29 using namespace AuthServer;
       
    30 
       
    31 CPinPluginDB* CPinPluginDB::NewL()
       
    32 	{
       
    33 	CPinPluginDB* self = CPinPluginDB::NewLC();
       
    34 	CleanupStack::Pop(self);
       
    35 	return self;
       
    36 	}
       
    37 
       
    38 CPinPluginDB* CPinPluginDB::NewLC()
       
    39 	{
       
    40 	CPinPluginDB* self = new(ELeave) CPinPluginDB();
       
    41 	CleanupStack::PushL(self);
       
    42 	self->ConstructL();
       
    43 	return self;
       
    44 	}
       
    45 	
       
    46 CPinPluginDB::CPinPluginDB() :
       
    47 	iRootStreamId(KNullStreamId),
       
    48 	iIdentityStreamId(KNullStreamId)
       
    49 	{
       
    50 	}
       
    51 
       
    52 CPinPluginDB::~CPinPluginDB()
       
    53 	{
       
    54 	if (iFileStore)
       
    55 		{
       
    56 		CompactStore();
       
    57 		delete iFileStore;
       
    58 		}
       
    59 
       
    60 	iFile.Close(); 
       
    61 	iFs.Close();
       
    62 
       
    63 	iId.Reset();
       
    64 	iId.Close();
       
    65 	iIdKeyHash.ResetAndDestroy();
       
    66 	iIdKeyHash.Close();
       
    67 	}
       
    68 	
       
    69 		
       
    70 void CPinPluginDB::ConstructL()
       
    71 	{
       
    72 	User::LeaveIfError(iFs.Connect());
       
    73 	
       
    74 	TFileName privatePath;
       
    75 	iFs.PrivatePath(privatePath);
       
    76 	iPluginDBName.Copy(KFileDrive);
       
    77 	iPluginDBName.Append(privatePath);
       
    78 	iPluginDBName.Append(KPluginStoreName);
       
    79 	OpenStoreL();
       
    80 	
       
    81 	ReadIdKeysFromStoreL();
       
    82 	}
       
    83 
       
    84 
       
    85 void CPinPluginDB::AddPinL(const TIdentityId& aId, const TDesC8& aIdentityKeyHash)
       
    86 	{
       
    87 	if(IdIndex(aId) == KErrNotFound && IsUniquePin(aIdentityKeyHash))
       
    88 		{
       
    89 		// Add the IdentityId to the array, rewrite the identitystream and 
       
    90 		// Only then commit the store
       
    91 		HBufC8* keyHash = aIdentityKeyHash.AllocLC();
       
    92 		TInt err = KErrNone;
       
    93 		iIdKeyHash.AppendL(keyHash);
       
    94 		err = iId.Append(aId);
       
    95 		if(err != KErrNone)
       
    96 			{
       
    97 			iIdKeyHash.Remove(iIdKeyHash.Count() - 1);
       
    98 			User::Leave(err);
       
    99 			}
       
   100 		TCleanupItem cleanupStore(RevertStore, iFileStore);
       
   101 		// write the idkeys to the store.
       
   102 		TRAP(err,
       
   103 			CleanupStack::PushL(cleanupStore);
       
   104 			WriteIdKeysToStoreL();
       
   105 			CleanupStack::Pop(iFileStore));
       
   106 
       
   107 		if (err != KErrNone)
       
   108 			{
       
   109 			iId.Remove(iId.Count() - 1);
       
   110 			iIdKeyHash.Remove(iIdKeyHash.Count() - 1);
       
   111 			User::Leave(err);
       
   112 			}
       
   113 		CleanupStack::Pop(keyHash); 
       
   114 		}
       
   115 	else
       
   116 		{
       
   117 		User::Leave(KErrAlreadyExists);
       
   118 		}
       
   119  	}
       
   120 
       
   121 void CPinPluginDB::UpdatePinL(const TIdentityId& aId, const TDesC8& aIdentityKeyHash)
       
   122 	{
       
   123 	if(IdIndex(aId) != KErrNotFound)
       
   124 		{
       
   125 		// Get the index of the existing id and key hash
       
   126 		TInt index = IdIndex(aId);
       
   127 		TInt err = KErrNone;
       
   128 		HBufC8* keyHash = aIdentityKeyHash.AllocLC();
       
   129 		// delete the old keyHash and store the new keyHash to the index
       
   130 		delete iIdKeyHash[index];
       
   131 		iIdKeyHash[index] = keyHash;
       
   132 
       
   133 		TCleanupItem cleanupStore(RevertStore, iFileStore);
       
   134 		// write the idkeys to the store.
       
   135 		TRAP(err ,
       
   136 			CleanupStack::PushL(cleanupStore);
       
   137 			WriteIdKeysToStoreL();
       
   138 			CleanupStack::Pop(iFileStore));
       
   139 		if (err!= KErrNone)
       
   140 			{
       
   141 			CleanupStack::Pop(keyHash);
       
   142 			ReadIdKeysFromStoreL();
       
   143 			User::Leave(err);
       
   144 			}
       
   145 		CleanupStack::Pop(keyHash);
       
   146 		}
       
   147 	else
       
   148 		{
       
   149 		User::Leave(KErrNotFound);
       
   150 		}
       
   151 	}
       
   152 	
       
   153 void CPinPluginDB::RemovePinL(const TIdentityId& aId)
       
   154 	{
       
   155 	if(IdIndex(aId) != KErrNotFound)
       
   156 		{
       
   157 		TInt err = KErrNone;
       
   158 		TInt index = IdIndex(aId);
       
   159 
       
   160 		// Delete the IdentityId from the array, rewrite the identitystream and 
       
   161 	   	// Only then commit the store
       
   162 		delete iIdKeyHash[index];
       
   163   		iIdKeyHash.Remove(index);
       
   164    		iId.Remove(index);
       
   165  
       
   166 		TCleanupItem cleanupStore(RevertStore, iFileStore);
       
   167 		// write the idkeys to the store.
       
   168 		TRAP(err, 
       
   169 			CleanupStack::PushL(cleanupStore);
       
   170 			WriteIdKeysToStoreL();
       
   171 			CleanupStack::Pop(iFileStore));
       
   172 		if(err != KErrNone)
       
   173 			{
       
   174 			ReadIdKeysFromStoreL();
       
   175    			User::Leave(err);
       
   176 			}
       
   177 		}
       
   178 	else
       
   179 		{
       
   180 		User::Leave(KErrNotFound);
       
   181 		}
       
   182 	}
       
   183 	
       
   184 TBool CPinPluginDB::IsUniquePin(const TDesC8& aIdentityKeyHash) const
       
   185 	{
       
   186 	//	Check each iIdKeyHash in the store to determine if aIdentityId already exists
       
   187 	TInt count = iIdKeyHash.Count();
       
   188 	TBool isUnique = ETrue;
       
   189 	for (TInt index = 0; index < count; ++index)
       
   190 		{
       
   191 		if (aIdentityKeyHash.CompareF(*iIdKeyHash[index]) == 0)
       
   192 			{
       
   193 			isUnique = EFalse;
       
   194 			break;
       
   195 			}
       
   196 		}
       
   197 	return isUnique;
       
   198 	}
       
   199 	
       
   200 TInt CPinPluginDB::IdIndex(const TIdentityId& aId) const
       
   201 	{
       
   202 	TInt count = iId.Count();
       
   203 	for (TInt index = 0; index < count; ++index)
       
   204 		{
       
   205 		if (aId == iId[index])
       
   206 			{
       
   207 			return index;
       
   208 			}
       
   209 		}
       
   210 	return KErrNotFound;
       
   211 	}
       
   212 	
       
   213 TIdentityId CPinPluginDB::IdFromPin(const TDesC8& aIdentityKeyHash) const
       
   214 	{
       
   215 	TInt count = iIdKeyHash.Count();
       
   216 	for (TInt index = 0; index < count; ++index)
       
   217 		{
       
   218 		if (aIdentityKeyHash.CompareF(*iIdKeyHash[index]) == 0)
       
   219 			{
       
   220 			return iId[index];
       
   221 			}
       
   222 		}
       
   223 	return KUnknownIdentity;
       
   224 	}
       
   225 	
       
   226 void CPinPluginDB::OpenStoreL()
       
   227 	{
       
   228 	//	Tries to Open a plugin store file on the private path of the process. 
       
   229 	//	If it cannot find one, create a file with permanent file store
       
   230 	//	it should initialise iFileStore unless it cannot
       
   231 	//	create the file/store/streams
       
   232 	
       
   233 	TRAPD(result, OpenStoreInFileL(iPluginDBName));
       
   234 
       
   235 	if (result == KErrNotFound || result == KErrPathNotFound) 
       
   236 		{		
       
   237 		// Not yet opened a valid store, either no file to be found, or no valid
       
   238 		// store in it.
       
   239 		CreateStoreInFileL(iPluginDBName);
       
   240 		}
       
   241 	else if (result != KErrNone)
       
   242 		{
       
   243 		// DB gets corrupted or File may be in use. Abort startup.
       
   244 		User::Leave(result);
       
   245 		}
       
   246 	}
       
   247 
       
   248 
       
   249 void CPinPluginDB::CreateStoreInFileL(const TDesC& aFile)
       
   250 	{
       
   251 	TInt r = iFs.MkDirAll(aFile);
       
   252 	if ((r!=KErrNone) && (r!=KErrAlreadyExists))
       
   253 		{
       
   254 		User::Leave(r);
       
   255 		}
       
   256 	
       
   257 	delete iFileStore;
       
   258 	iFileStore = NULL;
       
   259 
       
   260 	iFileStore = CPermanentFileStore::ReplaceL(iFs, aFile, EFileRead | EFileWrite | EFileStream | EFileShareExclusive);
       
   261 	iFileStore->SetTypeL(KPermanentFileStoreLayoutUid);
       
   262 
       
   263 	TCleanupItem cleanupStore(RevertStore, iFileStore);
       
   264 	CleanupStack::PushL(cleanupStore);
       
   265 	
       
   266 	// Create Identity stream - Currently no Identity created, and no IdentityKeyHash
       
   267 	RStoreWriteStream identityStream;
       
   268 	iIdentityStreamId = identityStream.CreateLC(*iFileStore);
       
   269 	identityStream.WriteUint32L(KNullStreamId.Value()); //contains the id of dataStream
       
   270 	identityStream.WriteUint32L(0); // Write IdentityId count of zero
       
   271 	identityStream.CommitL();
       
   272 	CleanupStack::PopAndDestroy(&identityStream);
       
   273 
       
   274 	// Create root stream - just contains id of Identity stream
       
   275 	RStoreWriteStream rootStream;
       
   276 	iRootStreamId = rootStream.CreateLC(*iFileStore);
       
   277 	iFileStore->SetRootL(iRootStreamId);
       
   278 	rootStream.WriteUint32L(iIdentityStreamId.Value());		
       
   279 	rootStream.CommitL();
       
   280 	CleanupStack::PopAndDestroy(&rootStream);
       
   281 	
       
   282 	iFileStore->CommitL();
       
   283 	CleanupStack::Pop(iFileStore); 
       
   284 	}
       
   285 
       
   286 void CPinPluginDB::OpenStoreInFileL(const TDesC& aFile)
       
   287 	{
       
   288 	// Make sure the file isn't write protected
       
   289 	User::LeaveIfError(iFs.SetAtt(aFile, 0, KEntryAttReadOnly));
       
   290 	
       
   291 	User::LeaveIfError(iFile.Open(iFs, aFile, EFileRead | EFileWrite | EFileStream | EFileShareExclusive));
       
   292 	
       
   293 	delete iFileStore;
       
   294 	iFileStore = NULL;
       
   295 
       
   296 	iFileStore = CPermanentFileStore::FromL(iFile);		
       
   297 
       
   298 	// Get the root StreamId
       
   299 	iRootStreamId = iFileStore->Root();
       
   300 	if (iRootStreamId == KNullStreamId)
       
   301 		{
       
   302 		User::Leave(KErrCorrupt);
       
   303 		}
       
   304 	
       
   305 	RStoreReadStream rootStream;
       
   306 	rootStream.OpenLC(*iFileStore, iRootStreamId);
       
   307 	iIdentityStreamId = (TStreamId)(rootStream.ReadUint32L());
       
   308 	CleanupStack::PopAndDestroy(&rootStream);
       
   309 	}
       
   310 
       
   311 // Rewrites the Identity stream (ie the array of IdentityId) to the store
       
   312 void CPinPluginDB::WriteIdKeysToStoreL()
       
   313 	{
       
   314 	TInt count = iId.Count();
       
   315 	TInt hashCount = iIdKeyHash.Count();
       
   316 	if (count != hashCount)
       
   317 		{
       
   318 		User::Leave(KErrCorrupt);
       
   319 		}
       
   320 	
       
   321 	TStreamId dataStreamId = KNullStreamId;
       
   322 	if (count > 0)
       
   323 		{
       
   324 		RStoreWriteStream dataStream;
       
   325 		dataStreamId = dataStream.CreateLC(*iFileStore);
       
   326 		//write the Identity Id key to a data stream
       
   327 		for (TInt index = 0; index < count; ++index)
       
   328 			{
       
   329 			dataStream.WriteUint32L(iId[index]);
       
   330 			dataStream.WriteUint32L((*iIdKeyHash[index]).Length());
       
   331 			dataStream.WriteL(*iIdKeyHash[index]);
       
   332 			}
       
   333 		dataStream.CommitL();
       
   334 		CleanupStack::PopAndDestroy(&dataStream); 	
       
   335 		}
       
   336 	RStoreReadStream readStream;
       
   337 	readStream.OpenLC(*iFileStore, iIdentityStreamId);
       
   338 	TStreamId oldDataStreamId = (TStreamId)(readStream.ReadInt32L());
       
   339 	CleanupStack::PopAndDestroy(&readStream);
       
   340 		
       
   341 	iFileStore->DeleteL(oldDataStreamId);
       
   342 	
       
   343 	RStoreWriteStream writeStream;
       
   344 	writeStream.OpenLC(*iFileStore, iIdentityStreamId);
       
   345 	writeStream.WriteUint32L(dataStreamId.Value());
       
   346 	writeStream.WriteInt32L(count);
       
   347 	writeStream.CommitL();
       
   348 	CleanupStack::PopAndDestroy(&writeStream); 	
       
   349 	iFileStore->CommitL();
       
   350 	CompactStore();
       
   351 	}
       
   352 	
       
   353 void CPinPluginDB::ReadIdKeysFromStoreL()
       
   354 	{
       
   355 	iId.Reset();
       
   356 	iIdKeyHash.ResetAndDestroy();
       
   357 	
       
   358 	RStoreReadStream readStream;
       
   359 	readStream.OpenLC(*iFileStore, iIdentityStreamId);
       
   360 	TStreamId dataStreamId = (TStreamId)(readStream.ReadInt32L());
       
   361 	TInt count = readStream.ReadInt32L();
       
   362 	CleanupStack::PopAndDestroy(&readStream);
       
   363 	
       
   364 	if (count > 0)
       
   365 		{
       
   366 		RStoreReadStream dataStream;
       
   367 		dataStream.OpenLC(*iFileStore, dataStreamId);
       
   368 		for (TInt index = 0; index < count; ++index)
       
   369 			{
       
   370 			TIdentityId identityId = (TIdentityId)(dataStream.ReadInt32L());
       
   371 			iId.AppendL(identityId);
       
   372 			TInt length = dataStream.ReadInt32L();
       
   373 			HBufC8* idKeyHash = HBufC8::NewMaxLC(length);
       
   374 			TPtr8 idKeyHashPtr = idKeyHash->Des();
       
   375 			dataStream.ReadL(idKeyHashPtr, length);
       
   376 			iIdKeyHash.AppendL(idKeyHash);
       
   377 			CleanupStack::Pop(idKeyHash);
       
   378 			}
       
   379 		CleanupStack::PopAndDestroy(&dataStream);
       
   380 		}
       
   381 	}
       
   382 
       
   383 void CPinPluginDB::RevertStore(TAny* aStore)
       
   384 	{
       
   385 	CPermanentFileStore* store = reinterpret_cast<CPermanentFileStore*>(aStore);
       
   386 	TRAP_IGNORE(store->RevertL());
       
   387 	// We're ignoring the leave code from this becuase there's no way we can
       
   388 	// handle this sensibly.  This shouldn't be a problem in practice - this
       
   389 	// will leave if for example the file store is on removable which is
       
   390 	// unexpectedly remove, and this is never the case for us.
       
   391 	}
       
   392 
       
   393 
       
   394 void CPinPluginDB::CompactStore()
       
   395 	{
       
   396 	ASSERT(iFileStore);
       
   397 	TRAP_IGNORE(iFileStore->ReclaimL(); iFileStore->CompactL());
       
   398 	}
       
   399 
       
   400 
       
   401 
       
   402