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