diff -r 675a964f4eb5 -r 35751d3474b7 authorisation/userpromptservice/database/source/upsdb.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/authorisation/userpromptservice/database/source/upsdb.cpp Thu Sep 10 14:01:51 2009 +0300 @@ -0,0 +1,511 @@ +/* +* Copyright (c) 2007-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: +* Implements a read-only interface for UPS Database. +* +*/ + + +/** + @file + @internalTechnology + @prototype +*/ + +#include "upsdbw.h" +#include "upscommon.h" + +using namespace UserPromptService; + + +// +//CDecisionView +// + +CDecisionView::CDecisionView():CActive(EPriorityStandard) +/** + Constructor for decision view object. + */ + { + CActiveScheduler::Add(this); + } + + + +CDecisionView::~CDecisionView() +/** + Destructor for the decision view object. + */ + { + iDbView.Close(); + delete iColSet; + Deque(); + } + + +EXPORT_C CDecisionView* CDecisionView::NewLC() +/** + Creates a decision view object. The function leaves, if creation of the view object fails. + + @return A pointer to the newly allocated view object, if creation is successful. + The pointer is also put onto the cleanup stack. + */ + { + CDecisionView* self = new(ELeave) CDecisionView(); + CleanupStack::PushL(self); + return self; + } + + +void CDecisionView::DoCancel() +//From CActive + { + iDbView.Cancel(); + if (iClientStatus) + { + User::RequestComplete(iClientStatus, KErrCancel); + } + } + + +TInt CDecisionView::RunError(TInt aError) +//From CActive + { + if (iClientStatus) + { + User::RequestComplete(iClientStatus, aError); + } + return KErrNone; + } + + +void CDecisionView::RunL() +//From CActive + { + TInt status = iStatus.Int(); + User::LeaveIfError(status); + + if(status > 0) + { + iDbView.Evaluate(iStatus); + SetActive(); + } + else + { + User::RequestComplete(iClientStatus,status); + } + } + + +EXPORT_C void CDecisionView::EvaluateView(TRequestStatus& aStatus) +/** + Performs all steps of the view evaluation, returning immediately and + signalling when all steps are complete. + + @param aStatus The request status used to contain completion information for the function. + On completion, the status value should be interpreted as follows: + 0, evaluation is complete.< 0, an error code. + */ + { + __ASSERT_ALWAYS(!IsActive(), User::Panic(KDecisionViewPanic,KErrInUse)); + + aStatus = KRequestPending; + iClientStatus = &aStatus; + + iDbView.Evaluate(iStatus); + + SetActive(); + + } + + +CDecisionRecord* CDecisionView::GenerateRecordL(RDbRowSet& aRowSet, CDbColSet* aColSet) +/** + Retrieves all decision record fileds from the given rowset and generates + a decision record from these information. + + @param aRowSet A database rowset object. + @param aColSet A database column set object. + + @return The newly,created decision record if it is successful; otherwise, leaves. + */ + { + TSecureId clientSid(aRowSet.ColUint32(aColSet->ColNo(KColClientSid))); //Client Secure Id + TSecureId serverId = TSecureId(aRowSet.ColUint32(aColSet->ColNo(KColServerSid))); //Service Secure Id + TUid evaluatorId = TUid::Uid(aRowSet.ColUint32(aColSet->ColNo(KColEvaluatorId))); //Evaluator Uid + TUid serviceId = TUid::Uid(aRowSet.ColUint32(aColSet->ColNo(KColServiceId))); //Service Uid + TPtrC8 fingerprint = aRowSet.ColDes8(aColSet->ColNo(KColFingerprint)); //Fingerprint + TPtrC8 clientEntity = aRowSet.ColDes8(aColSet->ColNo(KColClientEntity)); //Client Entity + TInt8 result = aRowSet.ColInt8(aColSet->ColNo(KColResult)); //Result + TUint16 ver = aRowSet.ColUint16(aColSet->ColNo(KColMajorPolicyVersion)); //Major Policy Version + TUint32 recordId = aRowSet.ColUint32(aColSet->ColNo(KColRecordId)); //Unique Record ID + TUint32 evaluatorInfo = aRowSet.ColUint32(aColSet->ColNo(KColEvaluatorInfo)); //EvaluatorInfo + + //a stream is used to read long columns + TDbColNo col = aColSet->ColNo(KColDescription); + TInt len = aRowSet.ColLength(col); + + RBuf description; + CleanupClosePushL(description); + description.CreateL(len); + + RDbColReadStream str; + str.OpenLC(aRowSet,col); + str.ReadL(description,len); + str.Close(); + CleanupStack::PopAndDestroy(&str); + + CDecisionRecord *retval = CDecisionRecord::NewL(clientSid,evaluatorId,serviceId,serverId,fingerprint, + clientEntity,description,result,ver,evaluatorInfo,recordId); + + CleanupStack::PopAndDestroy(&description); + return retval; + } + + +EXPORT_C CDecisionRecord* CDecisionView::NextDecisionL() +/** + Moves the cursor to the next row in the view object and returns the current decision row. + If there are no more rows, the cursor is positioned to the end of the view object. + + @return 0, If the cursor is positioned at the end of the view. Otherwise, current record. + */ + { + CDecisionRecord *record(0); + + if(iDbView.NextL()) + { + iDbView.GetL(); + record = GenerateRecordL(iDbView,iColSet); + } + else + { + iDbView.Close(); + } + + return record; + } + + +// +//CDecisionDb +// + + +CDecisionDb::CDecisionDb() +/** + Constructor for read-only decision database object + */ + { + + } + + +CDecisionDb::~CDecisionDb() +/** + Destructor for read-only decision database object + */ + { + + } + +const TDesC* CDecisionDb::GetComparisonOperator(const TUint32& aFlag) const +/** + Finds and returns the correspondent comparision operator string. + + @param aFlag + */ + { + UserPromptService::TComparisonOp op = static_cast(aFlag & 0xFFFF0000); + switch (op) + { + case UserPromptService::EEqual: + { + return &KSQLQueryEqual; + } + case UserPromptService::ENotEqual: + { + return &KSQLQueryNotEqual; + } + case UserPromptService::ELessThan: + { + return &KSQLQueryLessThan; + } + case UserPromptService::EGreaterThan: + { + return &KSQLQueryGreaterThan; + } + case UserPromptService::ELessThanOrEqual: + { + return &KSQLQueryLessThanOrEqual; + } + case UserPromptService::EGreaterThanOrEqual: + { + return &KSQLQueryGreaterThanOrEqual; + } + } + return &KSQLQueryEqual; + } + + +void CDecisionDb::CreateSqlStatementLC(CDecisionFilter& aFilter, RBuf& aSql) +/** + Creates an sql statement from a given filter. + + @param aFilter A filter object used to create the SQL statement. + @param aSql The newly created SQL statement. + */ + { + //Estimate the maximum required buffer (maxLen) to save the sql statement. + //KSQLQueryBase must be in the statement at least. + TInt maxLen = KBaseSQLLength; + + //Get the bits belonging to ID values (ClientSid,EvaluatorId,ServiceId,ServerSid) + TUint32 combinedFlags = (aFilter.iSetFlag[KPosClientSid] | aFilter.iSetFlag[KPosEvaluatorId] | + aFilter.iSetFlag[KPosServiceId] | aFilter.iSetFlag[KPosServerSid] | + aFilter.iSetFlag[KPosFingerprint] | aFilter.iSetFlag[KPosClientEntity]| + aFilter.iSetFlag[KPosMajorPolicyVersion] | aFilter.iSetFlag[KPosRecordId] | + aFilter.iSetFlag[KPosDescription] | aFilter.iSetFlag[KPosResult] | + aFilter.iSetFlag[KPosEvaluatorInfo]); + + TUint16 flag = combinedFlags & 0x000006CF; + //Count how many bits are set, and add KMaxIntCondition for each set bit + while(flag != 0) + { + flag &= (flag-1); + maxLen += KMaxIntCondition; + } + //Get the bits belonging to string values (Fingerprint and ClientEntity) + flag = combinedFlags & 0x00000130; + //Count how many bits are set, and add KMaxStringCondition length for each set bit + while(flag != 0) + { + flag &= (flag-1); + maxLen += KMaxStringCondition; + } + + //Allocate the estimated number of bytes for the sql statement + aSql.CreateL(maxLen); + aSql.CleanupClosePushL(); + //First copy the basic SQL statement + aSql.AppendFormat(KSQLQueryBase,&KDecisionTable); + + //If the filter is empty, there is no condition to add to the sql statement. + //So, simply return the base sql statement. In this case, all rows of + //the decision table are listed. + if(maxLen == KBaseSQLLength) + { + return; + } + + //Filter is not empty, add 'WHERE' key word into the statement + aSql.Append(KSQLQueryWhere); + + TBool multiple = EFalse; + //Append server SID if exists in the filter + AppendQueryInteger(aFilter.iServerSid.iId, aSql, multiple, aFilter.iSetFlag[KPosServerSid], KSetServerSid, KColServerSid); + //Append service UID if exists in the filter + AppendQueryInteger(aFilter.iServiceId.iUid, aSql, multiple, aFilter.iSetFlag[KPosServiceId], KSetServiceId, KColServiceId); + //Append client SID if exists in the filter + AppendQueryInteger(aFilter.iClientSid.iId, aSql, multiple, aFilter.iSetFlag[KPosClientSid], KSetClientSid, KColClientSid); + //Append evaluator UID if exists in the filter + AppendQueryInteger(aFilter.iEvaluatorId.iUid, aSql, multiple, aFilter.iSetFlag[KPosEvaluatorId], KSetEvaluatorId, KColEvaluatorId); + //Append major policy version if exists in the filter + AppendQueryInteger(aFilter.iMajorPolicyVersion, aSql, multiple, aFilter.iSetFlag[KPosMajorPolicyVersion], KSetMajorPolicyVersion, KColMajorPolicyVersion); + //Append record id if exists in the filter + AppendQueryInteger(aFilter.iRecordId, aSql, multiple, aFilter.iSetFlag[KPosRecordId], KSetRecordId, KColRecordId); + //Append result if exists in the filter + AppendQueryInteger(aFilter.iResult, aSql, multiple, aFilter.iSetFlag[KPosResult], KSetResult, KColResult); + //Append evaluator info if exists in the filter + AppendQueryInteger(aFilter.iEvaluatorInfo, aSql, multiple, aFilter.iSetFlag[KPosEvaluatorInfo], KSetEvaluatorInfo, KColEvaluatorInfo); + //Append description if exists in the filter + AppendQueryStringL(*aFilter.iDescription, aSql, multiple, aFilter.iSetFlag[KPosDescription], KSetDescription, KColDescription); + + //Append fingerprint if exists in the filter + //Convert 8-bit value to 16-bit + if(aFilter.iFingerprint) + { + HBufC* fp = HBufC::NewLC(aFilter.iFingerprint->Length()); + TPtr ptrFp(fp->Des()); + ptrFp.Copy(*aFilter.iFingerprint); + + AppendQueryStringL(*fp, aSql, multiple, aFilter.iSetFlag[KPosFingerprint], KSetFingerprint, KColFingerprint); + CleanupStack::PopAndDestroy(fp); + } + + //Append client entity if exists in the filter + //Convert 8-bit value to 16-bit + if(aFilter.iClientEntity) + { + HBufC* ce = HBufC::NewLC(aFilter.iClientEntity->Length()); + TPtr ptrCe(ce->Des()); + ptrCe.Copy(*aFilter.iClientEntity); + + AppendQueryStringL(*ce, aSql, multiple, aFilter.iSetFlag[KPosClientEntity], KSetClientEntity, KColClientEntity); + CleanupStack::PopAndDestroy(ce); + } + } + + +void CDecisionDb::AppendQueryInteger(const TUint32& aValue, TDes& aSql, TBool& aMultiple, const TUint32& aFlag, const TUint32& aSetCol, const TDesC& aColName) +/** + Appends an integer-based query key field to an SQL query string. + + @param aValue The integer value which will be added to the query. + @param aSql The SQL query string. + @param aMultiple EFalse, if there is only one query key in the query string. Otherwise, ETrue. + @param aFlag The flag value corresponding to the query key. + @param aSetCol A constant value indicating whether or not a specific column is set. + @param aColName The column name of the query key. + */ + { + if(aFlag & aSetCol) + { + if(aMultiple) + { + aSql.Append(KSQLQueryAnd); + } + else + { + aMultiple=ETrue; + } + + aSql.Append(aColName); + aSql.AppendFormat(KSQLQueryString,GetComparisonOperator(aFlag)); + aSql.AppendFormat(KSQLQueryConditionInt,aValue); + } + } + + +void CDecisionDb::AppendQueryStringL(const TDesC& aValue, TDes& aSql, TBool& aMultiple, const TUint32& aFlag, const TUint32& aSetCol, const TDesC& aColName) +/** + Appends an string query key to an SQL query string. + + @param aValue The string value which will be added to the query. + @param aSql The SQL query string. + @param aMultiple EFalse, if there is only one query key in the query string. Otherwise, ETrue. + @param aFlag The flag value corresponding to the query key. + @param aSetCol A constant value indicating whether or not a specific column is set. + @param aColName The column name of the query key. + */ + { + if(aFlag & aSetCol) + { + if(aMultiple) + { + aSql.Append(KSQLQueryAnd); + } + else + { + aMultiple=ETrue; + } + + aSql.Append(aColName); + + if(aValue.Length() != 0) + { + //Scan for single quote + RBuf dbValue; + DoubleSingleQuotesL(aValue, dbValue); + dbValue.CleanupClosePushL(); + + aSql.AppendFormat(KSQLQueryString,GetComparisonOperator(aFlag)); + aSql.AppendFormat(KSQLQueryConditionString,&dbValue); + + CleanupStack::PopAndDestroy(&dbValue); + } + else + { + aSql.Append(KSQLQueryNull); + } + } + } + + +void CDecisionDb::DoubleSingleQuotesL(const TDesC& aSource, RBuf& aDestination) +/** + Copies a source descriptor into a destination descriptor. If a single quote + character is found an extra single quote is copied to the destination. + Because, it is not possible to search for a string in SQL with single quote ('). + + @param aSource A source descriptor. + @param aDestination A destination descriptor. + */ + { + _LIT(KSingleQuote,"'"); + + aDestination.Close(); + + if(aSource.FindF(KSingleQuote) > KErrNotFound) + { + const TUint16 KSingleQuoteHex = 0x27; + TInt len = aSource.Length(); + + //Define a temporary buffer and set its maximum size to twice of the original (if it contained all quotes!) + RBuf temp; + temp.CreateL(len*2); + CleanupClosePushL(temp); + + const TUint16 *ptrSrc = aSource.Ptr(); + TUint16 *ptrDes = (TUint16 *)temp.Ptr(); + TInt srcIndex=0; + TInt desIndex=0; + + for(srcIndex=0; srcIndexiDbView.Prepare(iDatabase,TDbQuery(sqlStatement),TDbWindow::EUnlimited)); + + dbView->iColSet = dbView->iDbView.ColSetL(); + + CleanupStack::Pop(dbView); + CleanupStack::PopAndDestroy(&sqlStatement); //sqlStatement + + return dbView; + } +