1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/authorisation/userpromptservice/database/source/upsdb.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,511 @@
1.4 +/*
1.5 +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +* Implements a read-only interface for UPS Database.
1.19 +*
1.20 +*/
1.21 +
1.22 +
1.23 +/**
1.24 + @file
1.25 + @internalTechnology
1.26 + @released
1.27 +*/
1.28 +
1.29 +#include "upsdbw.h"
1.30 +#include "upscommon.h"
1.31 +
1.32 +using namespace UserPromptService;
1.33 +
1.34 +
1.35 +//
1.36 +//CDecisionView
1.37 +//
1.38 +
1.39 +CDecisionView::CDecisionView():CActive(EPriorityStandard)
1.40 +/**
1.41 + Constructor for decision view object.
1.42 + */
1.43 + {
1.44 + CActiveScheduler::Add(this);
1.45 + }
1.46 +
1.47 +
1.48 +
1.49 +CDecisionView::~CDecisionView()
1.50 +/**
1.51 + Destructor for the decision view object.
1.52 + */
1.53 + {
1.54 + iDbView.Close();
1.55 + delete iColSet;
1.56 + Deque();
1.57 + }
1.58 +
1.59 +
1.60 +EXPORT_C CDecisionView* CDecisionView::NewLC()
1.61 +/**
1.62 + Creates a decision view object. The function leaves, if creation of the view object fails.
1.63 +
1.64 + @return A pointer to the newly allocated view object, if creation is successful.
1.65 + The pointer is also put onto the cleanup stack.
1.66 + */
1.67 + {
1.68 + CDecisionView* self = new(ELeave) CDecisionView();
1.69 + CleanupStack::PushL(self);
1.70 + return self;
1.71 + }
1.72 +
1.73 +
1.74 +void CDecisionView::DoCancel()
1.75 +//From CActive
1.76 + {
1.77 + iDbView.Cancel();
1.78 + if (iClientStatus)
1.79 + {
1.80 + User::RequestComplete(iClientStatus, KErrCancel);
1.81 + }
1.82 + }
1.83 +
1.84 +
1.85 +TInt CDecisionView::RunError(TInt aError)
1.86 +//From CActive
1.87 + {
1.88 + if (iClientStatus)
1.89 + {
1.90 + User::RequestComplete(iClientStatus, aError);
1.91 + }
1.92 + return KErrNone;
1.93 + }
1.94 +
1.95 +
1.96 +void CDecisionView::RunL()
1.97 +//From CActive
1.98 + {
1.99 + TInt status = iStatus.Int();
1.100 + User::LeaveIfError(status);
1.101 +
1.102 + if(status > 0)
1.103 + {
1.104 + iDbView.Evaluate(iStatus);
1.105 + SetActive();
1.106 + }
1.107 + else
1.108 + {
1.109 + User::RequestComplete(iClientStatus,status);
1.110 + }
1.111 + }
1.112 +
1.113 +
1.114 +EXPORT_C void CDecisionView::EvaluateView(TRequestStatus& aStatus)
1.115 +/**
1.116 + Performs all steps of the view evaluation, returning immediately and
1.117 + signalling when all steps are complete.
1.118 +
1.119 + @param aStatus The request status used to contain completion information for the function.
1.120 + On completion, the status value should be interpreted as follows:
1.121 + 0, evaluation is complete.< 0, an error code.
1.122 + */
1.123 + {
1.124 + __ASSERT_ALWAYS(!IsActive(), User::Panic(KDecisionViewPanic,KErrInUse));
1.125 +
1.126 + aStatus = KRequestPending;
1.127 + iClientStatus = &aStatus;
1.128 +
1.129 + iDbView.Evaluate(iStatus);
1.130 +
1.131 + SetActive();
1.132 +
1.133 + }
1.134 +
1.135 +
1.136 +CDecisionRecord* CDecisionView::GenerateRecordL(RDbRowSet& aRowSet, CDbColSet* aColSet)
1.137 +/**
1.138 + Retrieves all decision record fileds from the given rowset and generates
1.139 + a decision record from these information.
1.140 +
1.141 + @param aRowSet A database rowset object.
1.142 + @param aColSet A database column set object.
1.143 +
1.144 + @return The newly,created decision record if it is successful; otherwise, leaves.
1.145 + */
1.146 + {
1.147 + TSecureId clientSid(aRowSet.ColUint32(aColSet->ColNo(KColClientSid))); //Client Secure Id
1.148 + TSecureId serverId = TSecureId(aRowSet.ColUint32(aColSet->ColNo(KColServerSid))); //Service Secure Id
1.149 + TUid evaluatorId = TUid::Uid(aRowSet.ColUint32(aColSet->ColNo(KColEvaluatorId))); //Evaluator Uid
1.150 + TUid serviceId = TUid::Uid(aRowSet.ColUint32(aColSet->ColNo(KColServiceId))); //Service Uid
1.151 + TPtrC8 fingerprint = aRowSet.ColDes8(aColSet->ColNo(KColFingerprint)); //Fingerprint
1.152 + TPtrC8 clientEntity = aRowSet.ColDes8(aColSet->ColNo(KColClientEntity)); //Client Entity
1.153 + TInt8 result = aRowSet.ColInt8(aColSet->ColNo(KColResult)); //Result
1.154 + TUint16 ver = aRowSet.ColUint16(aColSet->ColNo(KColMajorPolicyVersion)); //Major Policy Version
1.155 + TUint32 recordId = aRowSet.ColUint32(aColSet->ColNo(KColRecordId)); //Unique Record ID
1.156 + TUint32 evaluatorInfo = aRowSet.ColUint32(aColSet->ColNo(KColEvaluatorInfo)); //EvaluatorInfo
1.157 +
1.158 + //a stream is used to read long columns
1.159 + TDbColNo col = aColSet->ColNo(KColDescription);
1.160 + TInt len = aRowSet.ColLength(col);
1.161 +
1.162 + RBuf description;
1.163 + CleanupClosePushL(description);
1.164 + description.CreateL(len);
1.165 +
1.166 + RDbColReadStream str;
1.167 + str.OpenLC(aRowSet,col);
1.168 + str.ReadL(description,len);
1.169 + str.Close();
1.170 + CleanupStack::PopAndDestroy(&str);
1.171 +
1.172 + CDecisionRecord *retval = CDecisionRecord::NewL(clientSid,evaluatorId,serviceId,serverId,fingerprint,
1.173 + clientEntity,description,result,ver,evaluatorInfo,recordId);
1.174 +
1.175 + CleanupStack::PopAndDestroy(&description);
1.176 + return retval;
1.177 + }
1.178 +
1.179 +
1.180 +EXPORT_C CDecisionRecord* CDecisionView::NextDecisionL()
1.181 +/**
1.182 + Moves the cursor to the next row in the view object and returns the current decision row.
1.183 + If there are no more rows, the cursor is positioned to the end of the view object.
1.184 +
1.185 + @return 0, If the cursor is positioned at the end of the view. Otherwise, current record.
1.186 + */
1.187 + {
1.188 + CDecisionRecord *record(0);
1.189 +
1.190 + if(iDbView.NextL())
1.191 + {
1.192 + iDbView.GetL();
1.193 + record = GenerateRecordL(iDbView,iColSet);
1.194 + }
1.195 + else
1.196 + {
1.197 + iDbView.Close();
1.198 + }
1.199 +
1.200 + return record;
1.201 + }
1.202 +
1.203 +
1.204 +//
1.205 +//CDecisionDb
1.206 +//
1.207 +
1.208 +
1.209 +CDecisionDb::CDecisionDb()
1.210 +/**
1.211 + Constructor for read-only decision database object
1.212 + */
1.213 + {
1.214 +
1.215 + }
1.216 +
1.217 +
1.218 +CDecisionDb::~CDecisionDb()
1.219 +/**
1.220 + Destructor for read-only decision database object
1.221 + */
1.222 + {
1.223 +
1.224 + }
1.225 +
1.226 +const TDesC* CDecisionDb::GetComparisonOperator(const TUint32& aFlag) const
1.227 +/**
1.228 + Finds and returns the correspondent comparision operator string.
1.229 +
1.230 + @param aFlag
1.231 + */
1.232 + {
1.233 + UserPromptService::TComparisonOp op = static_cast<UserPromptService::TComparisonOp>(aFlag & 0xFFFF0000);
1.234 + switch (op)
1.235 + {
1.236 + case UserPromptService::EEqual:
1.237 + {
1.238 + return &KSQLQueryEqual;
1.239 + }
1.240 + case UserPromptService::ENotEqual:
1.241 + {
1.242 + return &KSQLQueryNotEqual;
1.243 + }
1.244 + case UserPromptService::ELessThan:
1.245 + {
1.246 + return &KSQLQueryLessThan;
1.247 + }
1.248 + case UserPromptService::EGreaterThan:
1.249 + {
1.250 + return &KSQLQueryGreaterThan;
1.251 + }
1.252 + case UserPromptService::ELessThanOrEqual:
1.253 + {
1.254 + return &KSQLQueryLessThanOrEqual;
1.255 + }
1.256 + case UserPromptService::EGreaterThanOrEqual:
1.257 + {
1.258 + return &KSQLQueryGreaterThanOrEqual;
1.259 + }
1.260 + }
1.261 + return &KSQLQueryEqual;
1.262 + }
1.263 +
1.264 +
1.265 +void CDecisionDb::CreateSqlStatementLC(CDecisionFilter& aFilter, RBuf& aSql)
1.266 +/**
1.267 + Creates an sql statement from a given filter.
1.268 +
1.269 + @param aFilter A filter object used to create the SQL statement.
1.270 + @param aSql The newly created SQL statement.
1.271 + */
1.272 + {
1.273 + //Estimate the maximum required buffer (maxLen) to save the sql statement.
1.274 + //KSQLQueryBase must be in the statement at least.
1.275 + TInt maxLen = KBaseSQLLength;
1.276 +
1.277 + //Get the bits belonging to ID values (ClientSid,EvaluatorId,ServiceId,ServerSid)
1.278 + TUint32 combinedFlags = (aFilter.iSetFlag[KPosClientSid] | aFilter.iSetFlag[KPosEvaluatorId] |
1.279 + aFilter.iSetFlag[KPosServiceId] | aFilter.iSetFlag[KPosServerSid] |
1.280 + aFilter.iSetFlag[KPosFingerprint] | aFilter.iSetFlag[KPosClientEntity]|
1.281 + aFilter.iSetFlag[KPosMajorPolicyVersion] | aFilter.iSetFlag[KPosRecordId] |
1.282 + aFilter.iSetFlag[KPosDescription] | aFilter.iSetFlag[KPosResult] |
1.283 + aFilter.iSetFlag[KPosEvaluatorInfo]);
1.284 +
1.285 + TUint16 flag = combinedFlags & 0x000006CF;
1.286 + //Count how many bits are set, and add KMaxIntCondition for each set bit
1.287 + while(flag != 0)
1.288 + {
1.289 + flag &= (flag-1);
1.290 + maxLen += KMaxIntCondition;
1.291 + }
1.292 + //Get the bits belonging to string values (Fingerprint and ClientEntity)
1.293 + flag = combinedFlags & 0x00000130;
1.294 + //Count how many bits are set, and add KMaxStringCondition length for each set bit
1.295 + while(flag != 0)
1.296 + {
1.297 + flag &= (flag-1);
1.298 + maxLen += KMaxStringCondition;
1.299 + }
1.300 +
1.301 + //Allocate the estimated number of bytes for the sql statement
1.302 + aSql.CreateL(maxLen);
1.303 + aSql.CleanupClosePushL();
1.304 + //First copy the basic SQL statement
1.305 + aSql.AppendFormat(KSQLQueryBase,&KDecisionTable);
1.306 +
1.307 + //If the filter is empty, there is no condition to add to the sql statement.
1.308 + //So, simply return the base sql statement. In this case, all rows of
1.309 + //the decision table are listed.
1.310 + if(maxLen == KBaseSQLLength)
1.311 + {
1.312 + return;
1.313 + }
1.314 +
1.315 + //Filter is not empty, add 'WHERE' key word into the statement
1.316 + aSql.Append(KSQLQueryWhere);
1.317 +
1.318 + TBool multiple = EFalse;
1.319 + //Append server SID if exists in the filter
1.320 + AppendQueryInteger(aFilter.iServerSid.iId, aSql, multiple, aFilter.iSetFlag[KPosServerSid], KSetServerSid, KColServerSid);
1.321 + //Append service UID if exists in the filter
1.322 + AppendQueryInteger(aFilter.iServiceId.iUid, aSql, multiple, aFilter.iSetFlag[KPosServiceId], KSetServiceId, KColServiceId);
1.323 + //Append client SID if exists in the filter
1.324 + AppendQueryInteger(aFilter.iClientSid.iId, aSql, multiple, aFilter.iSetFlag[KPosClientSid], KSetClientSid, KColClientSid);
1.325 + //Append evaluator UID if exists in the filter
1.326 + AppendQueryInteger(aFilter.iEvaluatorId.iUid, aSql, multiple, aFilter.iSetFlag[KPosEvaluatorId], KSetEvaluatorId, KColEvaluatorId);
1.327 + //Append major policy version if exists in the filter
1.328 + AppendQueryInteger(aFilter.iMajorPolicyVersion, aSql, multiple, aFilter.iSetFlag[KPosMajorPolicyVersion], KSetMajorPolicyVersion, KColMajorPolicyVersion);
1.329 + //Append record id if exists in the filter
1.330 + AppendQueryInteger(aFilter.iRecordId, aSql, multiple, aFilter.iSetFlag[KPosRecordId], KSetRecordId, KColRecordId);
1.331 + //Append result if exists in the filter
1.332 + AppendQueryInteger(aFilter.iResult, aSql, multiple, aFilter.iSetFlag[KPosResult], KSetResult, KColResult);
1.333 + //Append evaluator info if exists in the filter
1.334 + AppendQueryInteger(aFilter.iEvaluatorInfo, aSql, multiple, aFilter.iSetFlag[KPosEvaluatorInfo], KSetEvaluatorInfo, KColEvaluatorInfo);
1.335 + //Append description if exists in the filter
1.336 + AppendQueryStringL(*aFilter.iDescription, aSql, multiple, aFilter.iSetFlag[KPosDescription], KSetDescription, KColDescription);
1.337 +
1.338 + //Append fingerprint if exists in the filter
1.339 + //Convert 8-bit value to 16-bit
1.340 + if(aFilter.iFingerprint)
1.341 + {
1.342 + HBufC* fp = HBufC::NewLC(aFilter.iFingerprint->Length());
1.343 + TPtr ptrFp(fp->Des());
1.344 + ptrFp.Copy(*aFilter.iFingerprint);
1.345 +
1.346 + AppendQueryStringL(*fp, aSql, multiple, aFilter.iSetFlag[KPosFingerprint], KSetFingerprint, KColFingerprint);
1.347 + CleanupStack::PopAndDestroy(fp);
1.348 + }
1.349 +
1.350 + //Append client entity if exists in the filter
1.351 + //Convert 8-bit value to 16-bit
1.352 + if(aFilter.iClientEntity)
1.353 + {
1.354 + HBufC* ce = HBufC::NewLC(aFilter.iClientEntity->Length());
1.355 + TPtr ptrCe(ce->Des());
1.356 + ptrCe.Copy(*aFilter.iClientEntity);
1.357 +
1.358 + AppendQueryStringL(*ce, aSql, multiple, aFilter.iSetFlag[KPosClientEntity], KSetClientEntity, KColClientEntity);
1.359 + CleanupStack::PopAndDestroy(ce);
1.360 + }
1.361 + }
1.362 +
1.363 +
1.364 +void CDecisionDb::AppendQueryInteger(const TUint32& aValue, TDes& aSql, TBool& aMultiple, const TUint32& aFlag, const TUint32& aSetCol, const TDesC& aColName)
1.365 +/**
1.366 + Appends an integer-based query key field to an SQL query string.
1.367 +
1.368 + @param aValue The integer value which will be added to the query.
1.369 + @param aSql The SQL query string.
1.370 + @param aMultiple EFalse, if there is only one query key in the query string. Otherwise, ETrue.
1.371 + @param aFlag The flag value corresponding to the query key.
1.372 + @param aSetCol A constant value indicating whether or not a specific column is set.
1.373 + @param aColName The column name of the query key.
1.374 + */
1.375 + {
1.376 + if(aFlag & aSetCol)
1.377 + {
1.378 + if(aMultiple)
1.379 + {
1.380 + aSql.Append(KSQLQueryAnd);
1.381 + }
1.382 + else
1.383 + {
1.384 + aMultiple=ETrue;
1.385 + }
1.386 +
1.387 + aSql.Append(aColName);
1.388 + aSql.AppendFormat(KSQLQueryString,GetComparisonOperator(aFlag));
1.389 + aSql.AppendFormat(KSQLQueryConditionInt,aValue);
1.390 + }
1.391 + }
1.392 +
1.393 +
1.394 +void CDecisionDb::AppendQueryStringL(const TDesC& aValue, TDes& aSql, TBool& aMultiple, const TUint32& aFlag, const TUint32& aSetCol, const TDesC& aColName)
1.395 +/**
1.396 + Appends an string query key to an SQL query string.
1.397 +
1.398 + @param aValue The string value which will be added to the query.
1.399 + @param aSql The SQL query string.
1.400 + @param aMultiple EFalse, if there is only one query key in the query string. Otherwise, ETrue.
1.401 + @param aFlag The flag value corresponding to the query key.
1.402 + @param aSetCol A constant value indicating whether or not a specific column is set.
1.403 + @param aColName The column name of the query key.
1.404 + */
1.405 + {
1.406 + if(aFlag & aSetCol)
1.407 + {
1.408 + if(aMultiple)
1.409 + {
1.410 + aSql.Append(KSQLQueryAnd);
1.411 + }
1.412 + else
1.413 + {
1.414 + aMultiple=ETrue;
1.415 + }
1.416 +
1.417 + aSql.Append(aColName);
1.418 +
1.419 + if(aValue.Length() != 0)
1.420 + {
1.421 + //Scan for single quote
1.422 + RBuf dbValue;
1.423 + DoubleSingleQuotesL(aValue, dbValue);
1.424 + dbValue.CleanupClosePushL();
1.425 +
1.426 + aSql.AppendFormat(KSQLQueryString,GetComparisonOperator(aFlag));
1.427 + aSql.AppendFormat(KSQLQueryConditionString,&dbValue);
1.428 +
1.429 + CleanupStack::PopAndDestroy(&dbValue);
1.430 + }
1.431 + else
1.432 + {
1.433 + aSql.Append(KSQLQueryNull);
1.434 + }
1.435 + }
1.436 + }
1.437 +
1.438 +
1.439 +void CDecisionDb::DoubleSingleQuotesL(const TDesC& aSource, RBuf& aDestination)
1.440 +/**
1.441 + Copies a source descriptor into a destination descriptor. If a single quote
1.442 + character is found an extra single quote is copied to the destination.
1.443 + Because, it is not possible to search for a string in SQL with single quote (').
1.444 +
1.445 + @param aSource A source descriptor.
1.446 + @param aDestination A destination descriptor.
1.447 + */
1.448 + {
1.449 + _LIT(KSingleQuote,"'");
1.450 +
1.451 + aDestination.Close();
1.452 +
1.453 + if(aSource.FindF(KSingleQuote) > KErrNotFound)
1.454 + {
1.455 + const TUint16 KSingleQuoteHex = 0x27;
1.456 + TInt len = aSource.Length();
1.457 +
1.458 + //Define a temporary buffer and set its maximum size to twice of the original (if it contained all quotes!)
1.459 + RBuf temp;
1.460 + temp.CreateL(len*2);
1.461 + CleanupClosePushL(temp);
1.462 +
1.463 + const TUint16 *ptrSrc = aSource.Ptr();
1.464 + TUint16 *ptrDes = (TUint16 *)temp.Ptr();
1.465 + TInt srcIndex=0;
1.466 + TInt desIndex=0;
1.467 +
1.468 + for(srcIndex=0; srcIndex<len; ++srcIndex,++desIndex)
1.469 + {
1.470 + ptrDes[desIndex] = ptrSrc[srcIndex];
1.471 + if(ptrSrc[srcIndex] == KSingleQuoteHex) //is single quote?
1.472 + {
1.473 + ptrDes[++desIndex] = ptrSrc[srcIndex];//add extra single quote
1.474 + }
1.475 + }
1.476 +
1.477 + //Set the actual length
1.478 + temp.SetLength(desIndex);
1.479 + //Copy temp into destination. destination's maximum length is the same as the length of temp
1.480 + aDestination.CreateL(temp);
1.481 + CleanupStack::PopAndDestroy(&temp);
1.482 + }
1.483 + else
1.484 + {
1.485 + //there is no single quote, just copy it
1.486 + aDestination.CreateL(aSource);
1.487 + }
1.488 + }
1.489 +
1.490 +
1.491 +EXPORT_C CDecisionView *CDecisionDb::CreateViewL(CDecisionFilter& aFilter)
1.492 +/**
1.493 + Generates an SQL view rowset to the decision table by using a filter.
1.494 + The view rowset contains a set of rows which depend on the filter.
1.495 +
1.496 + @param aFilter A filter object to query the decision database
1.497 + @param aDecisionView A decision view object containing handle to the newly created SQL view rowset.
1.498 + */
1.499 + {
1.500 + RBuf sqlStatement;
1.501 + CreateSqlStatementLC(aFilter, sqlStatement);
1.502 +
1.503 + CDecisionView *dbView = CDecisionView::NewLC();
1.504 +
1.505 + User::LeaveIfError(dbView->iDbView.Prepare(iDatabase,TDbQuery(sqlStatement),TDbWindow::EUnlimited));
1.506 +
1.507 + dbView->iColSet = dbView->iDbView.ColSetL();
1.508 +
1.509 + CleanupStack::Pop(dbView);
1.510 + CleanupStack::PopAndDestroy(&sqlStatement); //sqlStatement
1.511 +
1.512 + return dbView;
1.513 + }
1.514 +