os/security/authorisation/userpromptservice/database/source/upsdb.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2007-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 * Implements a read-only interface for UPS Database.
    16 *
    17 */
    18 
    19 
    20 /**
    21  @file
    22  @internalTechnology
    23  @released
    24 */
    25 
    26 #include "upsdbw.h"
    27 #include "upscommon.h"
    28 
    29 using namespace UserPromptService;
    30 
    31 
    32 //
    33 //CDecisionView
    34 //
    35 
    36 CDecisionView::CDecisionView():CActive(EPriorityStandard)
    37 /**
    38 	Constructor for decision view object.
    39  */
    40 	{
    41 	CActiveScheduler::Add(this);	
    42 	}
    43 
    44 
    45 
    46 CDecisionView::~CDecisionView()
    47 /**
    48 	Destructor for the decision view object.
    49  */
    50 	{
    51 	iDbView.Close();
    52 	delete iColSet;
    53 	Deque();
    54 	}
    55 
    56 
    57 EXPORT_C CDecisionView* CDecisionView::NewLC()
    58 /**
    59 	Creates a decision view object. The function leaves, if creation of the view object fails.
    60 	
    61 	@return A pointer to the newly allocated view object, if creation is successful.
    62 	        The pointer is also put onto the cleanup stack.
    63  */
    64 	{
    65 	CDecisionView* self = new(ELeave) CDecisionView();
    66 	CleanupStack::PushL(self);
    67 	return self;
    68 	}
    69 
    70 
    71 void CDecisionView::DoCancel()
    72 //From CActive
    73 	{
    74 	iDbView.Cancel();
    75 	if (iClientStatus)
    76 		{
    77 		User::RequestComplete(iClientStatus, KErrCancel);
    78 		}	
    79 	}
    80 
    81 
    82 TInt CDecisionView::RunError(TInt aError)
    83 //From CActive
    84 	{
    85 	if (iClientStatus)
    86 		{
    87 		User::RequestComplete(iClientStatus, aError);
    88 		}
    89 	return KErrNone;
    90 	}
    91 
    92 
    93 void CDecisionView::RunL() 
    94 //From CActive
    95 	{
    96 	TInt status = iStatus.Int();
    97 	User::LeaveIfError(status);
    98 	
    99 	if(status > 0)
   100 		{
   101 		iDbView.Evaluate(iStatus);
   102 		SetActive();
   103 		}
   104 	else
   105 		{
   106 		User::RequestComplete(iClientStatus,status);
   107 		}
   108 	}
   109 	
   110 		
   111 EXPORT_C void CDecisionView::EvaluateView(TRequestStatus& aStatus)
   112 /**
   113 	Performs all steps of the view evaluation, returning immediately and 
   114 	signalling when all steps are complete. 
   115 	
   116 	@param aStatus The request status used to contain completion information for the function.
   117 	               On completion, the status value should be interpreted as follows: 
   118 	               0, evaluation is complete.< 0, an error code.
   119  */
   120 	{
   121 	__ASSERT_ALWAYS(!IsActive(), User::Panic(KDecisionViewPanic,KErrInUse));	
   122 	
   123 	aStatus = KRequestPending;
   124 	iClientStatus = &aStatus;	
   125 	
   126 	iDbView.Evaluate(iStatus);
   127 	
   128 	SetActive();
   129 	
   130 	}
   131 
   132 
   133 CDecisionRecord* CDecisionView::GenerateRecordL(RDbRowSet& aRowSet, CDbColSet* aColSet)
   134 /**
   135 	Retrieves all decision record fileds from the given rowset and generates
   136 	a decision record from these information.
   137 	
   138 	@param aRowSet A database rowset object.
   139 	@param aColSet A database column set object.
   140 	
   141 	@return The newly,created decision record if it is successful; otherwise, leaves.
   142  */
   143 	{
   144 	TSecureId clientSid(aRowSet.ColUint32(aColSet->ColNo(KColClientSid))); 			 //Client Secure Id
   145 	TSecureId serverId = TSecureId(aRowSet.ColUint32(aColSet->ColNo(KColServerSid))); //Service Secure Id
   146 	TUid evaluatorId = TUid::Uid(aRowSet.ColUint32(aColSet->ColNo(KColEvaluatorId))); //Evaluator Uid
   147 	TUid serviceId = TUid::Uid(aRowSet.ColUint32(aColSet->ColNo(KColServiceId)));	 //Service Uid
   148 	TPtrC8 fingerprint = aRowSet.ColDes8(aColSet->ColNo(KColFingerprint));			 //Fingerprint
   149 	TPtrC8 clientEntity = aRowSet.ColDes8(aColSet->ColNo(KColClientEntity));			 //Client Entity
   150 	TInt8 result = aRowSet.ColInt8(aColSet->ColNo(KColResult));						 //Result
   151 	TUint16 ver = aRowSet.ColUint16(aColSet->ColNo(KColMajorPolicyVersion));			 //Major Policy Version
   152 	TUint32 recordId =  aRowSet.ColUint32(aColSet->ColNo(KColRecordId));				 //Unique Record ID
   153 	TUint32 evaluatorInfo = aRowSet.ColUint32(aColSet->ColNo(KColEvaluatorInfo));     //EvaluatorInfo
   154 		
   155 	//a stream is used to read long columns
   156 	TDbColNo col = aColSet->ColNo(KColDescription);
   157 	TInt len = aRowSet.ColLength(col);
   158 		
   159 	RBuf description;
   160 	CleanupClosePushL(description);
   161 	description.CreateL(len);
   162 		
   163 	RDbColReadStream str;
   164 	str.OpenLC(aRowSet,col);
   165 	str.ReadL(description,len);
   166 	str.Close();
   167 	CleanupStack::PopAndDestroy(&str);
   168 		
   169 	CDecisionRecord *retval = CDecisionRecord::NewL(clientSid,evaluatorId,serviceId,serverId,fingerprint,
   170 								 clientEntity,description,result,ver,evaluatorInfo,recordId);
   171 	
   172 	CleanupStack::PopAndDestroy(&description);
   173 	return retval;
   174 	}
   175 	
   176 		
   177 EXPORT_C CDecisionRecord* CDecisionView::NextDecisionL()
   178 /** 
   179 	Moves the cursor to the next row in the view object and returns the current decision row.
   180  	If there are no more rows, the cursor is positioned to the end of the view object.
   181  	
   182  	@return 0, If the cursor is positioned at the end of the view. Otherwise, current record. 
   183  */
   184 	{
   185 	CDecisionRecord *record(0);
   186 	
   187 	if(iDbView.NextL())
   188 		{
   189 		iDbView.GetL();
   190 		record = GenerateRecordL(iDbView,iColSet);
   191 		}	
   192 	else
   193 		{
   194 		iDbView.Close();
   195 		}
   196 		
   197 	return record;
   198 	}
   199 
   200 
   201 //
   202 //CDecisionDb
   203 //
   204 
   205 
   206 CDecisionDb::CDecisionDb()
   207 /**
   208 	Constructor for read-only decision database object
   209  */
   210 	{
   211 	
   212 	}
   213 
   214 
   215 CDecisionDb::~CDecisionDb()
   216 /**
   217 	Destructor for read-only decision database object
   218  */
   219 	{
   220 	
   221 	}
   222 
   223 const TDesC* CDecisionDb::GetComparisonOperator(const TUint32& aFlag) const
   224 /**
   225 	Finds and returns the correspondent comparision operator string.
   226 	
   227 	@param aFlag 
   228  */
   229 	{
   230 	UserPromptService::TComparisonOp op = static_cast<UserPromptService::TComparisonOp>(aFlag & 0xFFFF0000);
   231 	switch (op)
   232 		{
   233 		case UserPromptService::EEqual:
   234 			{
   235 			return &KSQLQueryEqual;
   236 			}
   237 		case UserPromptService::ENotEqual:
   238 			{
   239 			return &KSQLQueryNotEqual;
   240 			}
   241 		case UserPromptService::ELessThan:
   242 			{
   243 			return &KSQLQueryLessThan;
   244 			}
   245 		case UserPromptService::EGreaterThan:
   246 			{
   247 			return &KSQLQueryGreaterThan;
   248 			}
   249 		case UserPromptService::ELessThanOrEqual:
   250 			{
   251 			return &KSQLQueryLessThanOrEqual;
   252 			}
   253 		case UserPromptService::EGreaterThanOrEqual:
   254 			{
   255 			return &KSQLQueryGreaterThanOrEqual;
   256 			}
   257 		}
   258 	return &KSQLQueryEqual;
   259 	}
   260 
   261 
   262 void CDecisionDb::CreateSqlStatementLC(CDecisionFilter& aFilter, RBuf& aSql)
   263 /**
   264 	Creates an sql statement from a given filter.
   265 
   266     @param aFilter A filter object used to create the SQL statement.
   267     @param aSql    The newly created SQL statement.
   268  */
   269 	{
   270 	//Estimate the maximum required buffer (maxLen) to save the sql statement.
   271 	//KSQLQueryBase must be in the statement at least.
   272 	TInt maxLen = KBaseSQLLength;
   273 	
   274 	//Get the bits belonging to ID values (ClientSid,EvaluatorId,ServiceId,ServerSid)
   275 	TUint32 combinedFlags = (aFilter.iSetFlag[KPosClientSid] | aFilter.iSetFlag[KPosEvaluatorId]   |
   276 						 	 aFilter.iSetFlag[KPosServiceId] | aFilter.iSetFlag[KPosServerSid]     |
   277 						 	 aFilter.iSetFlag[KPosFingerprint] | aFilter.iSetFlag[KPosClientEntity]|
   278 						 	 aFilter.iSetFlag[KPosMajorPolicyVersion] | aFilter.iSetFlag[KPosRecordId] |
   279 						 	 aFilter.iSetFlag[KPosDescription] | aFilter.iSetFlag[KPosResult] | 
   280 						 	 aFilter.iSetFlag[KPosEvaluatorInfo]);
   281 						 	
   282 	TUint16 flag = combinedFlags & 0x000006CF;
   283 	//Count how many bits are set, and add KMaxIntCondition for each set bit
   284 	while(flag != 0)
   285 		{
   286 		flag &= (flag-1);
   287 		maxLen += KMaxIntCondition;
   288 		}
   289 	//Get the bits belonging to string values (Fingerprint and ClientEntity)
   290 	flag = combinedFlags & 0x00000130;
   291 	//Count how many bits are set, and add KMaxStringCondition length for each set bit
   292 	while(flag != 0)
   293 		{
   294 		flag &= (flag-1);
   295 		maxLen += KMaxStringCondition;
   296 		}
   297 	
   298 	//Allocate the estimated number of bytes for the sql statement
   299 	aSql.CreateL(maxLen);
   300 	aSql.CleanupClosePushL();
   301 	//First copy the basic SQL statement
   302 	aSql.AppendFormat(KSQLQueryBase,&KDecisionTable);
   303 	
   304 	//If the filter is empty, there is no condition to add to the sql statement.
   305 	//So, simply return the base sql statement. In this case, all rows of
   306 	//the decision table are listed.
   307 	if(maxLen == KBaseSQLLength)
   308 		{
   309 		return;	
   310 		}
   311 	
   312 	//Filter is not empty, add 'WHERE' key word into the statement	
   313 	aSql.Append(KSQLQueryWhere);
   314 		
   315 	TBool multiple = EFalse;
   316 	//Append server SID if exists in the filter
   317 	AppendQueryInteger(aFilter.iServerSid.iId, aSql, multiple, aFilter.iSetFlag[KPosServerSid], KSetServerSid, KColServerSid);
   318 	//Append service UID if exists in the filter
   319 	AppendQueryInteger(aFilter.iServiceId.iUid, aSql, multiple, aFilter.iSetFlag[KPosServiceId], KSetServiceId, KColServiceId);
   320 	//Append client SID if exists in the filter
   321 	AppendQueryInteger(aFilter.iClientSid.iId, aSql, multiple, aFilter.iSetFlag[KPosClientSid], KSetClientSid, KColClientSid);		
   322 	//Append evaluator UID if exists in the filter
   323 	AppendQueryInteger(aFilter.iEvaluatorId.iUid, aSql, multiple, aFilter.iSetFlag[KPosEvaluatorId], KSetEvaluatorId, KColEvaluatorId);				
   324 	//Append major policy version if exists in the filter
   325 	AppendQueryInteger(aFilter.iMajorPolicyVersion, aSql, multiple, aFilter.iSetFlag[KPosMajorPolicyVersion], KSetMajorPolicyVersion, KColMajorPolicyVersion);
   326 	//Append record id if exists in the filter
   327 	AppendQueryInteger(aFilter.iRecordId, aSql, multiple, aFilter.iSetFlag[KPosRecordId], KSetRecordId, KColRecordId);		
   328 	//Append result if exists in the filter
   329 	AppendQueryInteger(aFilter.iResult, aSql, multiple, aFilter.iSetFlag[KPosResult], KSetResult, KColResult);		
   330 	//Append evaluator info if exists in the filter
   331 	AppendQueryInteger(aFilter.iEvaluatorInfo, aSql, multiple, aFilter.iSetFlag[KPosEvaluatorInfo], KSetEvaluatorInfo, KColEvaluatorInfo);		
   332 	//Append description if exists in the filter
   333 	AppendQueryStringL(*aFilter.iDescription, aSql, multiple, aFilter.iSetFlag[KPosDescription], KSetDescription, KColDescription);
   334 	
   335 	//Append fingerprint if exists in the filter	
   336 	//Convert 8-bit value to 16-bit
   337 	if(aFilter.iFingerprint)
   338 		{
   339 		HBufC* fp = HBufC::NewLC(aFilter.iFingerprint->Length());
   340 		TPtr ptrFp(fp->Des());
   341 		ptrFp.Copy(*aFilter.iFingerprint);
   342 	
   343 		AppendQueryStringL(*fp, aSql, multiple, aFilter.iSetFlag[KPosFingerprint], KSetFingerprint, KColFingerprint);
   344 		CleanupStack::PopAndDestroy(fp);
   345 		}
   346 	
   347 	//Append client entity if exists in the filter
   348 	//Convert 8-bit value to 16-bit 
   349 	if(aFilter.iClientEntity)
   350 		{
   351 		HBufC* ce = HBufC::NewLC(aFilter.iClientEntity->Length());
   352 		TPtr ptrCe(ce->Des());
   353 		ptrCe.Copy(*aFilter.iClientEntity);
   354 		
   355 		AppendQueryStringL(*ce, aSql, multiple, aFilter.iSetFlag[KPosClientEntity], KSetClientEntity, KColClientEntity);		
   356 		CleanupStack::PopAndDestroy(ce);
   357 		}
   358 	}
   359 
   360 
   361 void CDecisionDb::AppendQueryInteger(const TUint32& aValue, TDes& aSql, TBool& aMultiple, const TUint32& aFlag, const TUint32& aSetCol, const TDesC& aColName)
   362 /**
   363 	Appends an integer-based query key field to an SQL query string.
   364 	
   365 	@param aValue 	 The integer value which will be added to the query.
   366 	@param aSql   	 The SQL query string.
   367 	@param aMultiple EFalse, if there is only one query key in the query string. Otherwise, ETrue.
   368 	@param aFlag 	 The flag value corresponding to the query key.
   369 	@param aSetCol 	 A constant value indicating whether or not a specific column is set. 
   370 	@param aColName  The column name of the query key.
   371  */
   372 	{
   373 	if(aFlag & aSetCol)
   374 		{
   375 		if(aMultiple)
   376 			{
   377 			aSql.Append(KSQLQueryAnd);
   378 			}
   379 		else
   380 			{
   381 			aMultiple=ETrue;
   382 			}
   383 			
   384 		aSql.Append(aColName);
   385 		aSql.AppendFormat(KSQLQueryString,GetComparisonOperator(aFlag));	
   386 		aSql.AppendFormat(KSQLQueryConditionInt,aValue);
   387 		}
   388 	}
   389 	
   390 
   391 void CDecisionDb::AppendQueryStringL(const TDesC& aValue, TDes& aSql, TBool& aMultiple, const TUint32& aFlag, const TUint32& aSetCol, const TDesC& aColName)
   392 /**
   393 	Appends an string query key to an SQL query string.
   394 	
   395 	@param aValue 	 The string value which will be added to the query.
   396 	@param aSql   	 The SQL query string.
   397 	@param aMultiple EFalse, if there is only one query key in the query string. Otherwise, ETrue.
   398 	@param aFlag 	 The flag value corresponding to the query key.
   399 	@param aSetCol 	 A constant value indicating whether or not a specific column is set. 
   400 	@param aColName  The column name of the query key.
   401  */
   402 	{
   403 	if(aFlag & aSetCol)
   404 		{
   405 		if(aMultiple)
   406 			{
   407 			aSql.Append(KSQLQueryAnd);
   408 			}
   409 		else
   410 			{
   411 			aMultiple=ETrue;
   412 			}
   413 		
   414 		aSql.Append(aColName);
   415 		
   416 		if(aValue.Length() != 0)
   417 			{
   418 			//Scan for single quote
   419 			RBuf dbValue;
   420 			DoubleSingleQuotesL(aValue, dbValue);
   421 			dbValue.CleanupClosePushL();
   422 						
   423 			aSql.AppendFormat(KSQLQueryString,GetComparisonOperator(aFlag));	
   424 			aSql.AppendFormat(KSQLQueryConditionString,&dbValue);
   425 			
   426 			CleanupStack::PopAndDestroy(&dbValue);
   427 			}
   428 		else
   429 			{
   430 			aSql.Append(KSQLQueryNull);
   431 			}
   432 		}
   433 	}
   434 
   435 	
   436 void CDecisionDb::DoubleSingleQuotesL(const TDesC& aSource, RBuf& aDestination)
   437 /**
   438 	Copies a source descriptor into a destination descriptor. If a single quote
   439 	character is found an extra single quote is copied to the destination.
   440 	Because, it is not possible to search for a string in SQL with single quote (').
   441 	
   442 	@param aSource      A source descriptor.
   443 	@param aDestination A destination descriptor.
   444  */
   445 	{
   446 	_LIT(KSingleQuote,"'");
   447 
   448 	aDestination.Close();
   449 	
   450 	if(aSource.FindF(KSingleQuote) > KErrNotFound)
   451 		{
   452 		const TUint16 KSingleQuoteHex = 0x27;
   453 		TInt len = aSource.Length();
   454 		
   455 		//Define a temporary buffer and set its maximum size to twice of the original (if it contained all quotes!)
   456 		RBuf temp;
   457 		temp.CreateL(len*2);
   458 		CleanupClosePushL(temp);
   459 		
   460 		const TUint16 *ptrSrc = aSource.Ptr();
   461 		TUint16 *ptrDes = (TUint16 *)temp.Ptr();
   462 		TInt srcIndex=0;
   463 		TInt desIndex=0;
   464 		
   465 		for(srcIndex=0; srcIndex<len; ++srcIndex,++desIndex)
   466 			{
   467 			ptrDes[desIndex]	= ptrSrc[srcIndex];
   468 			if(ptrSrc[srcIndex] == KSingleQuoteHex) //is single quote?
   469 				{
   470 				ptrDes[++desIndex] = ptrSrc[srcIndex];//add extra single quote
   471 				}
   472 			}
   473 			
   474 		//Set the actual length	
   475 		temp.SetLength(desIndex);
   476 		//Copy temp into destination. destination's maximum length is the same as the length of temp
   477 		aDestination.CreateL(temp);
   478 		CleanupStack::PopAndDestroy(&temp);
   479 		}
   480 	else
   481 		{
   482 		//there is no single quote, just copy it
   483 		aDestination.CreateL(aSource);
   484 		}
   485 	}
   486 		
   487 		
   488 EXPORT_C CDecisionView *CDecisionDb::CreateViewL(CDecisionFilter& aFilter)
   489 /**
   490 	Generates an SQL view rowset to the decision table by using a filter.
   491 	The view rowset contains a set of rows which depend on the filter.
   492 	  
   493 	@param aFilter 		 A filter object to query the decision database
   494 	@param aDecisionView A decision view object containing handle to the newly created SQL view rowset.
   495  */		
   496 	{
   497 	RBuf sqlStatement;
   498 	CreateSqlStatementLC(aFilter, sqlStatement);
   499 	
   500 	CDecisionView *dbView = CDecisionView::NewLC();
   501 		
   502 	User::LeaveIfError(dbView->iDbView.Prepare(iDatabase,TDbQuery(sqlStatement),TDbWindow::EUnlimited));
   503 		
   504 	dbView->iColSet = dbView->iDbView.ColSetL();	
   505 		
   506 	CleanupStack::Pop(dbView);
   507 	CleanupStack::PopAndDestroy(&sqlStatement); //sqlStatement
   508 	
   509 	return dbView;
   510 	}
   511