|
1 /* |
|
2 * Copyright (c) 2006 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 "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 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <eikenv.h> |
|
20 #include <f32file.h> |
|
21 #include <bautils.h> |
|
22 #include <s32mem.h> |
|
23 |
|
24 #include "ncdpurchasehistorydbimpl.h" |
|
25 #include "ncdpurchasedownloadinfo.h" |
|
26 #include "ncdpurchaseinstallinfo.h" |
|
27 #include "ncdpurchasehistoryfilter.h" |
|
28 #include "ncdnodefunctionids.h" |
|
29 #include "catalogssession.h" |
|
30 #include "catalogsbasemessage.h" |
|
31 #include "catalogsbigdes.h" |
|
32 #include "catalogsconstants.h" |
|
33 #include "catalogsutils.h" |
|
34 #include "ncdutils.h" |
|
35 |
|
36 #include "catalogsdebug.h" |
|
37 |
|
38 // Create a purchases table. |
|
39 // This column order is always used when inserting data or in queries. |
|
40 // Column numbering is stored in CNcdPurchaseHistoryDb::PurchaseColumns. |
|
41 _LIT( KSqlCreatePurchasesTable, "\ |
|
42 CREATE TABLE purchases ( \ |
|
43 purchase_id COUNTER,\ |
|
44 event_id UNSIGNED INTEGER,\ |
|
45 client_uid INTEGER,\ |
|
46 namespace LONG VARCHAR,\ |
|
47 entity_id LONG VARCHAR,\ |
|
48 item_name LONG VARCHAR,\ |
|
49 item_purpose UNSIGNED INTEGER,\ |
|
50 catalog_name LONG VARCHAR,\ |
|
51 download_info LONG VARBINARY,\ |
|
52 purchase_option_id LONG VARCHAR,\ |
|
53 purchase_option_name LONG VARCHAR,\ |
|
54 purchase_option_price LONG VARCHAR,\ |
|
55 final_price LONG VARCHAR,\ |
|
56 payment_method_name LONG VARCHAR,\ |
|
57 purchase_time BIGINT,\ |
|
58 downloaded_files LONG VARBINARY,\ |
|
59 file_install_infos LONG VARBINARY,\ |
|
60 icon LONG VARBINARY,\ |
|
61 downloadaccesspoint LONG VARCHAR,\ |
|
62 description LONG VARCHAR,\ |
|
63 version LONG VARCHAR,\ |
|
64 server_uri LONG VARCHAR,\ |
|
65 item_type INTEGER, \ |
|
66 total_content_size INTEGER, \ |
|
67 origin_node_id LONG VARCHAR, \ |
|
68 last_operation_time BIGINT, \ |
|
69 last_operation_error_code INTEGER, \ |
|
70 has_icon INTEGER, \ |
|
71 attributes LONG VARBINARY )" ); |
|
72 |
|
73 |
|
74 // Create a event counter table. |
|
75 _LIT( KSqlCreateEventCounterTable, |
|
76 "CREATE TABLE event_counter_table ( event_counter UNSIGNED INTEGER )" ); |
|
77 |
|
78 // Event counter column number. |
|
79 const TInt KEventCounterColumnNumber = 1; |
|
80 |
|
81 |
|
82 // Select purchases. |
|
83 _LIT( KSqlPurchasesStart, |
|
84 "SELECT purchase_id FROM purchases WHERE event_id >= " ); |
|
85 _LIT( KSqlPurchasesNamespace, " AND namespace = '" ); |
|
86 _LIT( KSqlPurchasesEntityId, " AND entity_id = '" ); |
|
87 _LIT( KSqlPurchasesClientUid, " AND ( client_uid = " ); |
|
88 _LIT( KSqlPurchasesOrClientUid, " OR client_uid = " ); |
|
89 _LIT( KSqlPurchasesEndClientUid, " )" ); |
|
90 _LIT( KSqlPurchasesEnd, "'" ); |
|
91 _LIT( KSqlPurchasesOrderNewestFirst, " ORDER BY event_id DESC" ); |
|
92 _LIT( KSqlPurchasesOrderOldestFirst, " ORDER BY event_id ASC" ); |
|
93 |
|
94 // Select purchase to be updated. |
|
95 _LIT( KSqlPurchaseUpdateStart, |
|
96 "SELECT * FROM purchases WHERE client_uid = " ); |
|
97 _LIT( KSqlPurchasesUpdateNamespace, " AND namespace = '" ); |
|
98 _LIT( KSqlPurchasesUpdateEntityId, "' AND entity_id = '" ); |
|
99 _LIT( KSqlPurchasesUpdatePurchaseTime, "' AND purchase_time = " ); |
|
100 _LIT( KSqlPurchasesUpdateEnd, "" ); |
|
101 |
|
102 // Select purchase. |
|
103 _LIT( KSqlPurchaseByPurchaseIdStart, |
|
104 "SELECT * FROM purchases WHERE purchase_id = " ); |
|
105 _LIT( KSqlPurchaseByPurchaseIdEnd, "" ); |
|
106 |
|
107 // Select all purchases. |
|
108 _LIT( KSqlPurchasesAllNone, "SELECT * FROM purchases" ); |
|
109 |
|
110 // Delete specified purchase event. |
|
111 _LIT( KSqlPurchasesDeleteStart, |
|
112 "DELETE FROM purchases WHERE purchase_id = " ); |
|
113 _LIT( KSqlPurchasesDeleteEnd, "" ); |
|
114 |
|
115 |
|
116 // Select current event count. |
|
117 _LIT( KSqlCurrentEventCount, |
|
118 "SELECT event_counter FROM event_counter_table" ); |
|
119 |
|
120 // Delete event count from event count table. |
|
121 _LIT( KSqlEventCountDelete, "DELETE FROM event_counter_table" ); |
|
122 |
|
123 // "-2147483648" |
|
124 const TInt KMaxLengthOfInt = 11; |
|
125 |
|
126 // "-9223372036854775808" |
|
127 const TInt KMaxLengthOfTint64 = 20; |
|
128 |
|
129 static void AppendWithQuotesDuplicatedL( |
|
130 CCatalogsBigDes* aOutput, |
|
131 const TDesC& aInput ) |
|
132 { |
|
133 _LIT( KQuote, "'" ); |
|
134 |
|
135 if ( aOutput == NULL || &aInput == NULL ) |
|
136 { |
|
137 return; |
|
138 } |
|
139 |
|
140 TPtrC in = aInput.Mid( 0 ); |
|
141 while ( in.Length() > 0 ) |
|
142 { |
|
143 TInt i = in.Locate( '\'' ); |
|
144 if ( i == KErrNotFound ) |
|
145 { |
|
146 // Quote not found, all done |
|
147 aOutput->AppendL( in ); |
|
148 return; |
|
149 } |
|
150 aOutput->AppendL( in.Mid( 0, i + 1 ) ); |
|
151 // Append extra quote |
|
152 aOutput->AppendL( KQuote ); |
|
153 if ( i + 1 < in.Length() ) |
|
154 { |
|
155 // Get end part of the input descriptor |
|
156 in.Set( in.Mid( i + 1 ) ); |
|
157 } |
|
158 else |
|
159 { |
|
160 // End of the input descriptor reached |
|
161 return; |
|
162 } |
|
163 |
|
164 } |
|
165 } |
|
166 |
|
167 static HBufC* ReadLongTextColumnL( RDbRowSet aView, TDbColNo aCol ) |
|
168 { |
|
169 TInt length = aView.ColLength( aCol ); |
|
170 if ( length == 0 ) |
|
171 { |
|
172 return KNullDesC().Alloc(); |
|
173 } |
|
174 RDbColReadStream readStream; |
|
175 readStream.OpenLC( aView, aCol ); |
|
176 HBufC* result = HBufC::NewLC( length ); |
|
177 TPtr resultPtr = result->Des(); |
|
178 readStream.ReadL( resultPtr, length ); |
|
179 readStream.Close(); |
|
180 CleanupStack::Pop( result ); |
|
181 CleanupStack::Pop(); //readStream |
|
182 return result; |
|
183 } |
|
184 |
|
185 static void WriteLongTextColumnL( |
|
186 RDbRowSet aView, |
|
187 TDbColNo aCol, |
|
188 const TDesC& aValue ) |
|
189 { |
|
190 RDbColWriteStream writeStream; |
|
191 writeStream.OpenLC( aView, aCol ); |
|
192 if ( &aValue ) |
|
193 { |
|
194 writeStream.WriteL( aValue ); |
|
195 } |
|
196 else |
|
197 { |
|
198 writeStream.WriteL( KNullDesC ); |
|
199 } |
|
200 writeStream.Close(); |
|
201 CleanupStack::Pop( &writeStream ); |
|
202 } |
|
203 |
|
204 static HBufC8* ReadLongTextColumn8L( RDbRowSet aView, TDbColNo aCol ) |
|
205 { |
|
206 TInt length = aView.ColLength( aCol ); |
|
207 if ( length == 0 ) |
|
208 { |
|
209 return KNullDesC8().Alloc(); |
|
210 } |
|
211 RDbColReadStream readStream; |
|
212 readStream.OpenLC( aView, aCol ); |
|
213 HBufC8* result = HBufC8::NewLC( length ); |
|
214 TPtr8 resultPtr = result->Des(); |
|
215 readStream.ReadL( resultPtr, length ); |
|
216 readStream.Close(); |
|
217 CleanupStack::Pop( result ); |
|
218 CleanupStack::Pop(); //readStream |
|
219 return result; |
|
220 } |
|
221 |
|
222 static void WriteLongTextColumn8L( |
|
223 RDbRowSet aView, |
|
224 TDbColNo aCol, |
|
225 const TDesC8& aValue ) |
|
226 { |
|
227 RDbColWriteStream writeStream; |
|
228 writeStream.OpenLC( aView, aCol ); |
|
229 if ( &aValue ) |
|
230 { |
|
231 writeStream.WriteL( aValue ); |
|
232 } |
|
233 else |
|
234 { |
|
235 writeStream.WriteL( KNullDesC8 ); |
|
236 } |
|
237 writeStream.Close(); |
|
238 CleanupStack::Pop( &writeStream ); |
|
239 } |
|
240 |
|
241 |
|
242 CNcdPurchaseHistoryDb* CNcdPurchaseHistoryDb::NewL( |
|
243 const TDesC& aDbFilename ) |
|
244 { |
|
245 CNcdPurchaseHistoryDb* self = NewLC( aDbFilename ); |
|
246 CleanupStack::Pop( self ); |
|
247 return self; |
|
248 } |
|
249 |
|
250 CNcdPurchaseHistoryDb* CNcdPurchaseHistoryDb::NewLC( |
|
251 const TDesC& aDbFilename ) |
|
252 { |
|
253 CNcdPurchaseHistoryDb* self = |
|
254 new ( ELeave ) CNcdPurchaseHistoryDb(); |
|
255 CleanupClosePushL( *self ); |
|
256 self->ConstructL( aDbFilename ); |
|
257 return self; |
|
258 } |
|
259 |
|
260 CNcdPurchaseHistoryDb::~CNcdPurchaseHistoryDb() |
|
261 { |
|
262 iDatabase.Close(); |
|
263 delete iDbFilename; |
|
264 iFs.Close(); |
|
265 } |
|
266 |
|
267 void CNcdPurchaseHistoryDb::ReceiveMessage( |
|
268 MCatalogsBaseMessage* aMessage, |
|
269 TInt aFunctionNumber ) |
|
270 { |
|
271 DLTRACEIN(("")); |
|
272 |
|
273 DASSERT( aMessage ); |
|
274 |
|
275 // Now, we can be sure that rest of the time iMessage exists. |
|
276 // This member variable is set for the CounterPartLost function. |
|
277 iMessage = aMessage; |
|
278 |
|
279 TInt trapError( KErrNone ); |
|
280 |
|
281 switch( aFunctionNumber ) |
|
282 { |
|
283 case NcdNodeFunctionIds::ENcdPurchaseHistorySavePurchase: |
|
284 DLTRACE(("Insert purchase event")); |
|
285 TRAP( trapError, SavePurchaseRequestL( *aMessage ) ); |
|
286 break; |
|
287 |
|
288 case NcdNodeFunctionIds::ENcdPurchaseHistorySavePurchaseWithOldIcon: |
|
289 DLTRACE(("Insert purchase event with old icon")); |
|
290 TRAP( trapError, SavePurchaseRequestL( *aMessage, EFalse ) ); |
|
291 break; |
|
292 |
|
293 case NcdNodeFunctionIds::ENcdPurchaseHistoryRemovePurchase: |
|
294 DLTRACE(("Remove purchase")); |
|
295 TRAP( trapError, RemovePurchaseRequestL( *aMessage ) ); |
|
296 break; |
|
297 |
|
298 case NcdNodeFunctionIds::ENcdPurchaseHistoryGetPurchaseIds: |
|
299 DLTRACE(("Get purchase IDs")); |
|
300 TRAP( trapError, GetPurchaseIdsRequestL( *aMessage ) ); |
|
301 break; |
|
302 |
|
303 case NcdNodeFunctionIds::ENcdPurchaseHistoryGetPurchase: |
|
304 DLTRACE(("Get purchase")); |
|
305 TRAP( trapError, GetPurchaseRequestL( *aMessage, ETrue ) ); |
|
306 break; |
|
307 |
|
308 case NcdNodeFunctionIds::ENcdPurchaseHistoryGetPurchaseNoIcon: |
|
309 DLTRACE(("Get purchase")); |
|
310 TRAP( trapError, GetPurchaseRequestL( *aMessage, EFalse ) ); |
|
311 break; |
|
312 |
|
313 case NcdNodeFunctionIds::ENcdPurchaseHistoryEventCount: |
|
314 DLTRACE(("Get purchase event count")); |
|
315 TRAP( trapError, EventCountRequestL( *aMessage ) ); |
|
316 break; |
|
317 |
|
318 case NcdNodeFunctionIds::ENcdRelease: |
|
319 DLTRACE(("Release purchase history")); |
|
320 ReleaseRequest( *aMessage ); |
|
321 break; |
|
322 |
|
323 default: |
|
324 break; |
|
325 } |
|
326 |
|
327 if ( trapError != KErrNone ) |
|
328 { |
|
329 // Because something went wrong the complete has not been |
|
330 // yet called for the message. |
|
331 // So, inform the client about the error. |
|
332 DLTRACE(("ERROR, Complete and release %d", trapError)); |
|
333 |
|
334 aMessage->CompleteAndRelease( trapError ); |
|
335 } |
|
336 |
|
337 // Because the message should not be used after this, set it NULL. |
|
338 // So, CounterPartLost function will know that no messages are |
|
339 // waiting the response at the moment. |
|
340 iMessage = NULL; |
|
341 |
|
342 DLTRACEOUT(("")); |
|
343 } |
|
344 |
|
345 void CNcdPurchaseHistoryDb::CounterPartLost( |
|
346 const MCatalogsSession& aSession ) |
|
347 { |
|
348 // This function may be called whenever -- when the message is waiting |
|
349 // response or when the message does not exist. |
|
350 // iMessage may be NULL here, because in the end of the |
|
351 // ReceiveMessage it is set to NULL. The life time of the message |
|
352 // ends shortly after CompleteAndRelease is called. |
|
353 if ( iMessage != NULL ) |
|
354 { |
|
355 iMessage->CounterPartLost( aSession ); |
|
356 } |
|
357 } |
|
358 |
|
359 void CNcdPurchaseHistoryDb::ConstructL( const TDesC& aDbFilename ) |
|
360 { |
|
361 if ( aDbFilename == KNullDesC ) |
|
362 { |
|
363 User::Leave( KErrBadName ); |
|
364 } |
|
365 |
|
366 User::LeaveIfError( iFs.Connect() ); |
|
367 |
|
368 // Set database name. |
|
369 iDbFilename = aDbFilename.AllocL(); |
|
370 BaflUtils::EnsurePathExistsL( iFs, *iDbFilename ); |
|
371 TInt err = iDatabase.Open( iFs, *iDbFilename ); |
|
372 |
|
373 if ( err == KErrNotFound || err == KErrCorrupt ) |
|
374 { |
|
375 // Delete existing database file. This should happen only if |
|
376 // database file is corrupted. Ignoring errors as database file |
|
377 // may not be present. |
|
378 BaflUtils::DeleteFile( iFs, *iDbFilename ); |
|
379 |
|
380 // See if the database can be found from another drive |
|
381 TFindFile finder( iFs ); |
|
382 CDir* dir = NULL; |
|
383 |
|
384 err = finder.FindWildByDir( *iDbFilename, KNullDesC, dir ); |
|
385 |
|
386 if ( err == KErrNone ) |
|
387 { |
|
388 // Move old database to correct folder and try to open it |
|
389 CleanupStack::PushL( dir ); |
|
390 CFileMan* fileman = CFileMan::NewL( iFs ); |
|
391 CleanupStack::PushL( fileman ); |
|
392 User::LeaveIfError( fileman->Move( finder.File(), |
|
393 *iDbFilename, |
|
394 CFileMan::EOverWrite ) ); |
|
395 CleanupStack::PopAndDestroy( fileman ); |
|
396 CleanupStack::PopAndDestroy( dir ); |
|
397 |
|
398 // NOTE: Error ignored. If folder contains files, |
|
399 // it will not be deleted. |
|
400 iFs.RmDir( finder.File() ); |
|
401 |
|
402 err = iDatabase.Open( iFs, *iDbFilename ); |
|
403 if ( err == KErrNotFound || err == KErrCorrupt ) |
|
404 { |
|
405 BaflUtils::DeleteFile( iFs, *iDbFilename ); |
|
406 // Trying to create the database |
|
407 User::LeaveIfError( iDatabase.Create( iFs, *iDbFilename ) ); |
|
408 User::LeaveIfError( |
|
409 iDatabase.Execute( KSqlCreatePurchasesTable ) ); |
|
410 User::LeaveIfError( |
|
411 iDatabase.Execute( KSqlCreateEventCounterTable ) ); |
|
412 } |
|
413 else if ( err != KErrNone ) |
|
414 { |
|
415 User::Leave( err ); |
|
416 } |
|
417 } |
|
418 else |
|
419 { |
|
420 // Trying to create the database |
|
421 User::LeaveIfError( iDatabase.Create( iFs, *iDbFilename ) ); |
|
422 User::LeaveIfError( |
|
423 iDatabase.Execute( KSqlCreatePurchasesTable ) ); |
|
424 User::LeaveIfError( |
|
425 iDatabase.Execute( KSqlCreateEventCounterTable ) ); |
|
426 } |
|
427 } |
|
428 else if ( err != KErrNone ) |
|
429 { |
|
430 User::Leave( err ); |
|
431 } |
|
432 |
|
433 if ( iDatabase.IsDamaged() ) |
|
434 { |
|
435 // Database has been partly damaged. Try to recover it. |
|
436 iDatabase.Recover(); |
|
437 } |
|
438 } |
|
439 |
|
440 CNcdPurchaseHistoryDb::CNcdPurchaseHistoryDb() |
|
441 : CCatalogsCommunicable() |
|
442 { |
|
443 } |
|
444 |
|
445 void CNcdPurchaseHistoryDb::SavePurchaseL( |
|
446 CNcdPurchaseDetails& aPurchase, |
|
447 TBool aSaveIcon ) |
|
448 { |
|
449 DLTRACEIN(("")); |
|
450 // Ensure that purchase history handling bugs in PCD! don't crash the client :) |
|
451 ValidatePurchaseDetailsL( aPurchase ); |
|
452 |
|
453 CCatalogsBigDes* sqlStatement = CCatalogsBigDes::NewLC(); |
|
454 |
|
455 sqlStatement->AppendL( KSqlPurchaseUpdateStart ); |
|
456 TBuf<KMaxLengthOfInt> intBuf; |
|
457 intBuf.Num( aPurchase.ClientUid().iUid ); |
|
458 sqlStatement->AppendL( intBuf ); |
|
459 sqlStatement->AppendL( KSqlPurchasesUpdateNamespace ); |
|
460 AppendWithQuotesDuplicatedL( sqlStatement, aPurchase.Namespace() ); |
|
461 sqlStatement->AppendL( KSqlPurchasesUpdateEntityId ); |
|
462 AppendWithQuotesDuplicatedL( sqlStatement, aPurchase.EntityId() ); |
|
463 sqlStatement->AppendL( KSqlPurchasesUpdatePurchaseTime ); |
|
464 TBuf<KMaxLengthOfTint64> bigIntBuf; |
|
465 bigIntBuf.Num( aPurchase.PurchaseTime().Int64() ); |
|
466 sqlStatement->AppendL( bigIntBuf ); |
|
467 sqlStatement->AppendL( KSqlPurchasesUpdateEnd ); |
|
468 |
|
469 TUint newEventCount = EventCountL() + 1; |
|
470 |
|
471 RDbView view; |
|
472 CleanupClosePushL( view ); |
|
473 |
|
474 HBufC* sqlStatementBuf = sqlStatement->DesLC(); |
|
475 User::LeaveIfError( |
|
476 view.Prepare( iDatabase, TDbQuery( *sqlStatementBuf ) ) ); |
|
477 CleanupStack::PopAndDestroy( sqlStatementBuf ); |
|
478 |
|
479 User::LeaveIfError( view.EvaluateAll() ); |
|
480 view.FirstL(); |
|
481 |
|
482 if ( view.AtRow() ) |
|
483 { |
|
484 UpdatePurchaseL( view, aPurchase, newEventCount, aSaveIcon ); |
|
485 } |
|
486 else |
|
487 { |
|
488 view.Close(); |
|
489 NewPurchaseL( aPurchase, newEventCount ); |
|
490 } |
|
491 |
|
492 // Set new purchase count |
|
493 SetEventCountL( newEventCount ); |
|
494 |
|
495 CleanupStack::PopAndDestroy( &view ); |
|
496 CleanupStack::PopAndDestroy( sqlStatement ); |
|
497 DLTRACEOUT(("")); |
|
498 } |
|
499 |
|
500 void CNcdPurchaseHistoryDb::RemovePurchaseL( TUint aPurchaseId ) |
|
501 { |
|
502 if ( ! PurchaseExistsL( aPurchaseId ) ) |
|
503 { |
|
504 // Purchase didn't exist in the database. |
|
505 User::Leave( KErrNotFound ); |
|
506 } |
|
507 |
|
508 TInt maxLength = KSqlPurchasesDeleteStart().Length() + KMaxLengthOfInt |
|
509 + KSqlPurchasesDeleteEnd().Length(); |
|
510 |
|
511 HBufC* sqlStatement = HBufC::NewLC( maxLength ); |
|
512 TPtr statementPtr( sqlStatement->Des() ); |
|
513 |
|
514 statementPtr.Copy( KSqlPurchasesDeleteStart ); |
|
515 statementPtr.AppendNum( aPurchaseId ); |
|
516 statementPtr.Append( KSqlPurchasesDeleteEnd ); |
|
517 |
|
518 // Remove purchase from the database using event ID. |
|
519 User::LeaveIfError( iDatabase.Execute( *sqlStatement ) ); |
|
520 // Remove all unnecessary data from the database. |
|
521 User::LeaveIfError( iDatabase.Compact() ); |
|
522 |
|
523 CleanupStack::PopAndDestroy( sqlStatement ); |
|
524 } |
|
525 |
|
526 RArray<TUint> CNcdPurchaseHistoryDb::PurchaseIdsL( |
|
527 const CNcdPurchaseHistoryFilter& aFilter, |
|
528 const TSortingOrder aSortingOrder ) |
|
529 { |
|
530 CCatalogsBigDes* sqlStatement = CCatalogsBigDes::NewLC(); |
|
531 |
|
532 // Construct the SQL query. |
|
533 sqlStatement->AppendL( KSqlPurchasesStart ); |
|
534 TBuf<KMaxLengthOfInt> eventId; |
|
535 eventId.Num( aFilter.EventId() ); |
|
536 sqlStatement->AppendL( eventId ); |
|
537 |
|
538 if ( aFilter.Namespace().Compare( KNullDesC ) != 0 ) |
|
539 { |
|
540 sqlStatement->AppendL( KSqlPurchasesNamespace ); |
|
541 AppendWithQuotesDuplicatedL( sqlStatement, aFilter.Namespace() ); |
|
542 sqlStatement->AppendL( KSqlPurchasesEnd ); |
|
543 } |
|
544 |
|
545 if ( aFilter.EntityId().Compare( KNullDesC ) != 0 ) |
|
546 { |
|
547 sqlStatement->AppendL( KSqlPurchasesEntityId ); |
|
548 AppendWithQuotesDuplicatedL( sqlStatement, aFilter.EntityId() ); |
|
549 sqlStatement->AppendL( KSqlPurchasesEnd ); |
|
550 } |
|
551 |
|
552 if ( aFilter.ClientUids().Count() > 0 ) |
|
553 { |
|
554 TArray< TUid > uids = aFilter.ClientUids(); |
|
555 TInt count = uids.Count(); |
|
556 sqlStatement->AppendL( KSqlPurchasesClientUid ); |
|
557 for ( TInt i = 0; i < count; i++ ) |
|
558 { |
|
559 TBuf<KMaxLengthOfInt> clientUid; |
|
560 clientUid.Num( uids[i].iUid ); |
|
561 sqlStatement->AppendL( clientUid ); |
|
562 if ( i + 1 < count ) |
|
563 { |
|
564 // More UIDs in the filter. |
|
565 sqlStatement->AppendL( KSqlPurchasesOrClientUid ); |
|
566 } |
|
567 } |
|
568 sqlStatement->AppendL( KSqlPurchasesEndClientUid ); |
|
569 } |
|
570 |
|
571 switch ( aSortingOrder ) |
|
572 { |
|
573 case CNcdPurchaseHistoryDb::ENewestFirst: |
|
574 sqlStatement->AppendL( KSqlPurchasesOrderNewestFirst ); |
|
575 break; |
|
576 case CNcdPurchaseHistoryDb::EOldestFirst: |
|
577 sqlStatement->AppendL( KSqlPurchasesOrderOldestFirst ); |
|
578 break; |
|
579 case CNcdPurchaseHistoryDb::ENone: |
|
580 default: |
|
581 break; |
|
582 } |
|
583 |
|
584 RDbView view; |
|
585 CleanupClosePushL( view ); |
|
586 |
|
587 HBufC* sqlStatementBuf = sqlStatement->DesLC(); |
|
588 User::LeaveIfError( |
|
589 view.Prepare( iDatabase, TDbQuery( *sqlStatementBuf ) ) ); |
|
590 CleanupStack::PopAndDestroy( sqlStatementBuf ); |
|
591 |
|
592 User::LeaveIfError( view.EvaluateAll() ); |
|
593 view.FirstL(); |
|
594 |
|
595 RArray<TUint> purchaseIds; |
|
596 CleanupClosePushL( purchaseIds ); |
|
597 |
|
598 while( view.AtRow() ) |
|
599 { |
|
600 view.GetL(); |
|
601 purchaseIds.Append( |
|
602 view.ColUint32( CNcdPurchaseHistoryDb::EPurchaseId ) ); |
|
603 view.NextL(); |
|
604 } |
|
605 |
|
606 CleanupStack::Pop( &purchaseIds ); |
|
607 CleanupStack::PopAndDestroy( &view ); |
|
608 CleanupStack::PopAndDestroy( sqlStatement ); |
|
609 |
|
610 return purchaseIds; |
|
611 } |
|
612 |
|
613 CNcdPurchaseDetails* CNcdPurchaseHistoryDb::PurchaseL( |
|
614 TUint aPurchaseId, |
|
615 TBool aLoadIcon ) |
|
616 { |
|
617 TInt maxLength = KSqlPurchaseByPurchaseIdStart().Length() |
|
618 + KMaxLengthOfInt |
|
619 + KSqlPurchaseByPurchaseIdEnd().Length(); |
|
620 |
|
621 HBufC* sqlStatement = HBufC::NewLC( maxLength ); |
|
622 TPtr statementPtr( sqlStatement->Des() ); |
|
623 |
|
624 statementPtr.Copy( KSqlPurchaseByPurchaseIdStart ); |
|
625 statementPtr.AppendNum( aPurchaseId ); |
|
626 statementPtr.Append( KSqlPurchaseByPurchaseIdEnd ); |
|
627 |
|
628 RDbView view; |
|
629 CleanupClosePushL( view ); |
|
630 |
|
631 User::LeaveIfError( |
|
632 view.Prepare( iDatabase, TDbQuery( *sqlStatement ) ) ); |
|
633 |
|
634 User::LeaveIfError( view.EvaluateAll() ); |
|
635 view.FirstL(); |
|
636 |
|
637 CNcdPurchaseDetails* details = NULL; |
|
638 |
|
639 if ( view.AtRow() ) |
|
640 { |
|
641 view.GetL(); |
|
642 |
|
643 details = CNcdPurchaseDetails::NewLC(); |
|
644 |
|
645 details->SetClientUid( TUid::Uid( view.ColInt32( EClientUid ) ) ); |
|
646 details->SetNamespace( ReadLongTextColumnL( view, ENamespace ) ); |
|
647 details->SetEntityId( ReadLongTextColumnL( view, EEntityId ) ); |
|
648 details->SetItemName( ReadLongTextColumnL( view, EItemName ) ); |
|
649 details->SetItemPurpose( view.ColUint32( EItemPurpose ) ); |
|
650 details->SetCatalogSourceName( |
|
651 ReadLongTextColumnL( view, ECatalogName ) ); |
|
652 |
|
653 // Get download info buffer from database |
|
654 HBufC8* downloadBuf = ReadLongTextColumn8L( view, EDownloadInfo ); |
|
655 CleanupStack::PushL( downloadBuf ); |
|
656 |
|
657 if ( downloadBuf->Length() > 0 ) |
|
658 { |
|
659 // There is some data. |
|
660 RDesReadStream readStream( *downloadBuf ); |
|
661 CleanupClosePushL( readStream ); |
|
662 |
|
663 // Get count of download infos. |
|
664 TInt count = readStream.ReadInt32L(); |
|
665 for ( TInt i = 0; i < count; i++ ) |
|
666 { |
|
667 // Internalize download infos from the buffer. |
|
668 |
|
669 CNcdPurchaseDownloadInfo* info = |
|
670 CNcdPurchaseDownloadInfo::NewLC(); |
|
671 |
|
672 info->InternalizeL( readStream ); |
|
673 details->AddDownloadInfoL( info ); |
|
674 |
|
675 CleanupStack::Pop( info ); |
|
676 } |
|
677 |
|
678 CleanupStack::PopAndDestroy( &readStream ); |
|
679 } |
|
680 |
|
681 CleanupStack::PopAndDestroy( downloadBuf ); |
|
682 |
|
683 details->SetPurchaseOptionId( |
|
684 ReadLongTextColumnL( view, EPurchaseOptionId ) ); |
|
685 details->SetPurchaseOptionName( |
|
686 ReadLongTextColumnL( view, EPurchaseOptionName ) ); |
|
687 details->SetPurchaseOptionPrice( |
|
688 ReadLongTextColumnL( view, EPurchaseOptionPrice ) ); |
|
689 details->SetFinalPrice( ReadLongTextColumnL( view, EFinalPrice ) ); |
|
690 details->SetPaymentMethodName( |
|
691 ReadLongTextColumnL( view, EPaymentMethodName ) ); |
|
692 details->SetPurchaseTime( view.ColInt64( EPurchaseTime ) ); |
|
693 |
|
694 HBufC8* filesBuf = ReadLongTextColumn8L( view, EDownloadedFiles ); |
|
695 CleanupStack::PushL( filesBuf ); |
|
696 CDesCArray* downloadedFiles = |
|
697 new (ELeave) CDesCArrayFlat( KListGranularity ); |
|
698 CleanupStack::PushL( downloadedFiles ); |
|
699 |
|
700 if ( filesBuf->Length() > 0 ) |
|
701 { |
|
702 // There is some data. |
|
703 RDesReadStream readStream( *filesBuf ); |
|
704 CleanupClosePushL( readStream ); |
|
705 |
|
706 TInt filesCount = readStream.ReadInt32L(); |
|
707 for ( TInt i = 0; i < filesCount; i++ ) |
|
708 { |
|
709 HBufC* buf = NULL; |
|
710 InternalizeDesL( buf, readStream ); |
|
711 CleanupStack::PushL( buf ); |
|
712 downloadedFiles->AppendL( *buf ); |
|
713 CleanupStack::PopAndDestroy( buf ); |
|
714 } |
|
715 |
|
716 CleanupStack::PopAndDestroy( &readStream ); |
|
717 } |
|
718 |
|
719 details->SetDownloadedFiles( downloadedFiles ); |
|
720 CleanupStack::Pop( downloadedFiles ); |
|
721 CleanupStack::PopAndDestroy( filesBuf ); |
|
722 |
|
723 // Get install info buffer from database |
|
724 HBufC8* installBuf = ReadLongTextColumn8L( view, EFileInstallInfos ); |
|
725 CleanupStack::PushL( installBuf ); |
|
726 |
|
727 if ( installBuf->Length() > 0 ) |
|
728 { |
|
729 // There is some data. |
|
730 RDesReadStream readStream( *installBuf ); |
|
731 CleanupClosePushL( readStream ); |
|
732 |
|
733 // Get count of install infos. |
|
734 TInt count = readStream.ReadInt32L(); |
|
735 for ( TInt i = 0; i < count; i++ ) |
|
736 { |
|
737 // Internalize install infos from the buffer. |
|
738 |
|
739 CNcdPurchaseInstallInfo* info = |
|
740 CNcdPurchaseInstallInfo::NewLC(); |
|
741 |
|
742 info->InternalizeL( readStream ); |
|
743 details->AddInstallInfoL( info ); |
|
744 |
|
745 CleanupStack::Pop( info ); |
|
746 } |
|
747 |
|
748 CleanupStack::PopAndDestroy( &readStream ); |
|
749 } |
|
750 |
|
751 CleanupStack::PopAndDestroy( installBuf ); |
|
752 |
|
753 if ( aLoadIcon ) |
|
754 { |
|
755 DLTRACE(("Loading icon from the purchase history")); |
|
756 details->SetIcon( ReadLongTextColumn8L( view, EIcon ) ); |
|
757 } |
|
758 details->SetDownloadAccessPoint( ReadLongTextColumnL( view, EDownloadAccessPoint ) ); |
|
759 details->SetDescription( ReadLongTextColumnL( view, EDescription ) ); |
|
760 details->SetVersion( ReadLongTextColumnL( view, EVersion ) ); |
|
761 details->SetServerUri( ReadLongTextColumnL( view, EServerUri ) ); |
|
762 details->SetItemType( (MNcdPurchaseDetails::TItemType)view.ColInt32( EItemType ) ); |
|
763 details->SetTotalContentSize( view.ColInt32( ETotalContentSize ) ); |
|
764 details->SetOriginNodeId( ReadLongTextColumnL( view, EOriginNodeId ) ); |
|
765 details->SetLastOperationTime( view.ColInt64( ELastOperationTime ) ); |
|
766 details->SetLastOperationErrorCode( view.ColInt32( ELastOperationErrorCode ) ); |
|
767 details->SetHasIcon( view.ColInt32( EHasIcon ) ); |
|
768 |
|
769 // Get attributes buffer from database |
|
770 HBufC8* attributesBuf = ReadLongTextColumn8L( view, EAttributes ); |
|
771 CleanupStack::PushL( attributesBuf ); |
|
772 |
|
773 if ( attributesBuf->Length() > 0 ) |
|
774 { |
|
775 // There is some data. |
|
776 RDesReadStream readStream( *attributesBuf ); |
|
777 CleanupClosePushL( readStream ); |
|
778 details->InternalizeAttributesL( readStream ); |
|
779 CleanupStack::PopAndDestroy( &readStream ); |
|
780 } |
|
781 |
|
782 CleanupStack::PopAndDestroy( attributesBuf ); |
|
783 } |
|
784 |
|
785 if ( ! details ) |
|
786 { |
|
787 User::Leave( KErrNotFound ); |
|
788 } |
|
789 |
|
790 // Ensure that purchase history handling bugs in PCD! don't crash the client :) |
|
791 ValidatePurchaseDetailsL( *details ); |
|
792 |
|
793 CleanupStack::Pop( details ); |
|
794 CleanupStack::PopAndDestroy( &view ); |
|
795 CleanupStack::PopAndDestroy( sqlStatement ); |
|
796 |
|
797 return details; |
|
798 } |
|
799 |
|
800 TUint CNcdPurchaseHistoryDb::EventCountL() |
|
801 { |
|
802 TUint eventCount = 0; |
|
803 |
|
804 RDbView view; |
|
805 CleanupClosePushL( view ); |
|
806 |
|
807 User::LeaveIfError( view.Prepare( |
|
808 iDatabase, |
|
809 TDbQuery( KSqlCurrentEventCount ), |
|
810 RDbView::EReadOnly ) ); |
|
811 |
|
812 view.EvaluateAll(); |
|
813 view.FirstL(); |
|
814 |
|
815 if ( view.AtRow() ) |
|
816 { |
|
817 view.GetL(); |
|
818 eventCount = view.ColUint32( KEventCounterColumnNumber ); |
|
819 } |
|
820 |
|
821 CleanupStack::PopAndDestroy( &view ); |
|
822 |
|
823 return eventCount; |
|
824 } |
|
825 |
|
826 void CNcdPurchaseHistoryDb::SavePurchaseRequestL( MCatalogsBaseMessage& aMessage, |
|
827 TBool aSaveIcon ) |
|
828 { |
|
829 TInt inputLength = aMessage.InputLength(); |
|
830 User::LeaveIfError( inputLength ); |
|
831 |
|
832 HBufC8* message = HBufC8::NewLC( inputLength ); |
|
833 TPtr8 ptr = message->Des(); |
|
834 User::LeaveIfError( aMessage.ReadInput( ptr ) ); |
|
835 |
|
836 CNcdPurchaseDetails* details = CNcdPurchaseDetails::NewLC(); |
|
837 |
|
838 RDesReadStream stream( *message ); |
|
839 CleanupClosePushL( stream ); |
|
840 |
|
841 details->InternalizeL( stream ); |
|
842 |
|
843 CleanupStack::PopAndDestroy( &stream ); |
|
844 |
|
845 SavePurchaseL( *details, aSaveIcon ); |
|
846 |
|
847 CleanupStack::PopAndDestroy( details ); |
|
848 CleanupStack::PopAndDestroy( message ); |
|
849 |
|
850 aMessage.CompleteAndRelease( KErrNone ); |
|
851 } |
|
852 |
|
853 void CNcdPurchaseHistoryDb::RemovePurchaseRequestL( MCatalogsBaseMessage& aMessage ) |
|
854 { |
|
855 TInt inputLength = aMessage.InputLength(); |
|
856 User::LeaveIfError( inputLength ); |
|
857 |
|
858 HBufC8* message = HBufC8::NewLC( inputLength ); |
|
859 TPtr8 ptr = message->Des(); |
|
860 User::LeaveIfError( aMessage.ReadInput( ptr ) ); |
|
861 |
|
862 TUint purchaseId = Des8ToUint( *message ); |
|
863 |
|
864 CleanupStack::PopAndDestroy( message ); |
|
865 |
|
866 RemovePurchaseL( purchaseId ); |
|
867 |
|
868 aMessage.CompleteAndRelease( KErrNone ); |
|
869 } |
|
870 |
|
871 void CNcdPurchaseHistoryDb::GetPurchaseIdsRequestL( MCatalogsBaseMessage& aMessage ) |
|
872 { |
|
873 TInt inputLength = aMessage.InputLength(); |
|
874 User::LeaveIfError( inputLength ); |
|
875 |
|
876 HBufC8* message = HBufC8::NewLC( inputLength ); |
|
877 TPtr8 ptr = message->Des(); |
|
878 User::LeaveIfError( aMessage.ReadInput( ptr ) ); |
|
879 |
|
880 CNcdPurchaseHistoryFilter* filter = CNcdPurchaseHistoryFilter::NewLC(); |
|
881 |
|
882 RDesReadStream stream( *message ); |
|
883 CleanupClosePushL( stream ); |
|
884 |
|
885 filter->InternalizeL( stream ); |
|
886 |
|
887 CleanupStack::PopAndDestroy( &stream ); |
|
888 |
|
889 RArray<TUint> purchaseIds = PurchaseIdsL( *filter, ENewestFirst ); |
|
890 |
|
891 CleanupStack::PopAndDestroy( filter ); |
|
892 CleanupStack::PopAndDestroy( message ); |
|
893 |
|
894 CleanupClosePushL( purchaseIds ); |
|
895 |
|
896 TUint count = purchaseIds.Count(); |
|
897 |
|
898 message = HBufC8::NewLC( ( count + 1 ) * sizeof(TUint) ); |
|
899 |
|
900 HBufC8* temp = UintToDes8LC( count ); |
|
901 message->Des().Copy( *temp ); |
|
902 CleanupStack::PopAndDestroy( temp ); |
|
903 |
|
904 for ( TInt i = 0; i < count; i++ ) |
|
905 { |
|
906 temp = UintToDes8LC( purchaseIds[i] ); |
|
907 message->Des().Append( *temp ); |
|
908 CleanupStack::PopAndDestroy( temp ); |
|
909 } |
|
910 |
|
911 aMessage.CompleteAndReleaseL( *message, KErrNone ); |
|
912 |
|
913 CleanupStack::PopAndDestroy( message ); |
|
914 |
|
915 CleanupStack::PopAndDestroy( &purchaseIds ); |
|
916 } |
|
917 |
|
918 void CNcdPurchaseHistoryDb::GetPurchaseRequestL( |
|
919 MCatalogsBaseMessage& aMessage, |
|
920 TBool aLoadIcon ) |
|
921 { |
|
922 DLTRACEIN(("aLoadIcon: %d", aLoadIcon)); |
|
923 TInt inputLength = aMessage.InputLength(); |
|
924 User::LeaveIfError( inputLength ); |
|
925 |
|
926 HBufC8* message = HBufC8::NewLC( inputLength ); |
|
927 TPtr8 ptr = message->Des(); |
|
928 User::LeaveIfError( aMessage.ReadInput( ptr ) ); |
|
929 |
|
930 TUint purchaseId = Des8ToUint( *message ); |
|
931 |
|
932 CleanupStack::PopAndDestroy( message ); |
|
933 |
|
934 CNcdPurchaseDetails* details = PurchaseL( purchaseId, aLoadIcon ); |
|
935 if ( details ) |
|
936 { |
|
937 CleanupStack::PushL( details ); |
|
938 |
|
939 CBufBase* buf = CBufFlat::NewL( KBufExpandSize ); |
|
940 CleanupStack::PushL( buf ); |
|
941 |
|
942 RBufWriteStream stream( *buf ); |
|
943 CleanupClosePushL( stream ); |
|
944 |
|
945 details->ExternalizeL( stream ); |
|
946 |
|
947 CleanupStack::PopAndDestroy( &stream ); |
|
948 |
|
949 aMessage.CompleteAndReleaseL( buf->Ptr( 0 ), KErrNone ); |
|
950 |
|
951 CleanupStack::PopAndDestroy( buf ); |
|
952 CleanupStack::PopAndDestroy( details ); |
|
953 } |
|
954 else |
|
955 { |
|
956 aMessage.CompleteAndRelease( KErrNotFound ); |
|
957 } |
|
958 } |
|
959 |
|
960 void CNcdPurchaseHistoryDb::EventCountRequestL( MCatalogsBaseMessage& aMessage ) |
|
961 { |
|
962 TUint count = EventCountL(); |
|
963 |
|
964 HBufC8* message = UintToDes8LC( count ); |
|
965 |
|
966 aMessage.CompleteAndReleaseL( *message, KErrNone ); |
|
967 |
|
968 CleanupStack::PopAndDestroy( message ); |
|
969 } |
|
970 |
|
971 void CNcdPurchaseHistoryDb::ReleaseRequest( MCatalogsBaseMessage& aMessage ) |
|
972 { |
|
973 DLTRACEIN(("")); |
|
974 |
|
975 // Decrease the reference count for this object. |
|
976 // When the reference count reaches zero, this object will be destroyed |
|
977 // and removed from the session. |
|
978 MCatalogsSession& requestSession( aMessage.Session() ); |
|
979 TInt handle( aMessage.Handle() ); |
|
980 |
|
981 // Send complete information back to proxy. |
|
982 aMessage.CompleteAndRelease( KErrNone ); |
|
983 |
|
984 // Remove this object from the session. |
|
985 requestSession.RemoveObject( handle ); |
|
986 |
|
987 DLTRACEOUT(("")); |
|
988 } |
|
989 |
|
990 void CNcdPurchaseHistoryDb::NewPurchaseL( |
|
991 CNcdPurchaseDetails& aPurchase, |
|
992 TUint aNewEventCount ) |
|
993 { |
|
994 // Construct database view. |
|
995 RDbView view; |
|
996 CleanupClosePushL( view ); |
|
997 User::LeaveIfError( view.Prepare( |
|
998 iDatabase, |
|
999 TDbQuery( KSqlPurchasesAllNone ), |
|
1000 RDbView::EInsertOnly ) ); |
|
1001 view.InsertL(); |
|
1002 |
|
1003 // Set initial value for EHasIcon here. This is needed because in SetPurchaseViewL |
|
1004 // the flag is never unset after being set to true. The reason for this is that |
|
1005 // the flag is unkwnown to PCD! Adapter and when it syncs PH data with the engine |
|
1006 // it cannot set the flag correctly. Therefore the flag is always kept as true |
|
1007 // regardless of what PCD! Adapter sends in the sync. This is correct because |
|
1008 // once set, the icon data is never removed from the purchase detail entry. |
|
1009 view.SetColL( EHasIcon, EFalse ); |
|
1010 |
|
1011 SetPurchaseViewL( view, aPurchase, aNewEventCount, ETrue ); |
|
1012 |
|
1013 |
|
1014 // Insert purchase into the database |
|
1015 view.PutL(); |
|
1016 view.Close(); |
|
1017 CleanupStack::PopAndDestroy( &view ); |
|
1018 } |
|
1019 |
|
1020 |
|
1021 void CNcdPurchaseHistoryDb::UpdatePurchaseL( |
|
1022 RDbRowSet& aView, |
|
1023 CNcdPurchaseDetails& aPurchase, |
|
1024 TUint aNewEventCount, |
|
1025 TBool aSaveIcon ) |
|
1026 { |
|
1027 aView.UpdateL(); |
|
1028 |
|
1029 SetPurchaseViewL( aView, aPurchase, aNewEventCount, aSaveIcon ); |
|
1030 |
|
1031 // Update purchase details. |
|
1032 aView.PutL(); |
|
1033 } |
|
1034 |
|
1035 |
|
1036 void CNcdPurchaseHistoryDb::SetPurchaseViewL( |
|
1037 RDbRowSet& aView, |
|
1038 CNcdPurchaseDetails& aPurchase, |
|
1039 TUint aNewEventCount, |
|
1040 TBool aSaveIcon ) |
|
1041 { |
|
1042 aView.SetColL( EEventId, aNewEventCount ); |
|
1043 aView.SetColL( EClientUid, aPurchase.ClientUid().iUid ); |
|
1044 WriteLongTextColumnL( aView, ENamespace, aPurchase.Namespace() ); |
|
1045 WriteLongTextColumnL( aView, EEntityId, aPurchase.EntityId() ); |
|
1046 WriteLongTextColumnL( aView, EItemName, aPurchase.ItemName() ); |
|
1047 aView.SetColL( EItemPurpose, aPurchase.ItemPurpose() ); |
|
1048 WriteLongTextColumnL( |
|
1049 aView, |
|
1050 ECatalogName, |
|
1051 aPurchase.CatalogSourceName() ); |
|
1052 |
|
1053 CBufBase* downloadBuf = CBufFlat::NewL( KBufExpandSize ); |
|
1054 CleanupStack::PushL( downloadBuf ); |
|
1055 |
|
1056 RBufWriteStream downloadStream( *downloadBuf ); |
|
1057 CleanupClosePushL( downloadStream ); |
|
1058 |
|
1059 TInt downloadCount = aPurchase.DownloadInfoCount(); |
|
1060 downloadStream.WriteInt32L( downloadCount ); |
|
1061 for ( TInt i = 0; i < downloadCount; i++ ) |
|
1062 { |
|
1063 // Download information present. |
|
1064 |
|
1065 CNcdPurchaseDownloadInfo& info = aPurchase.DownloadInfo( i ); |
|
1066 info.ExternalizeL( downloadStream ); |
|
1067 } |
|
1068 |
|
1069 CleanupStack::PopAndDestroy( &downloadStream ); |
|
1070 TPtr8 downloadPtr = downloadBuf->Ptr( 0 ); |
|
1071 WriteLongTextColumn8L( aView, EDownloadInfo, downloadPtr ); |
|
1072 CleanupStack::PopAndDestroy( downloadBuf ); |
|
1073 |
|
1074 WriteLongTextColumnL( aView, EPurchaseOptionId, aPurchase.PurchaseOptionId() ); |
|
1075 WriteLongTextColumnL( aView, EPurchaseOptionName, aPurchase.PurchaseOptionName() ); |
|
1076 WriteLongTextColumnL( aView, EPurchaseOptionPrice, aPurchase.PurchaseOptionPrice() ); |
|
1077 WriteLongTextColumnL( aView, EFinalPrice, aPurchase.FinalPrice() ); |
|
1078 WriteLongTextColumnL( aView, EPaymentMethodName, aPurchase.PaymentMethodName() ); |
|
1079 aView.SetColL( EPurchaseTime, aPurchase.PurchaseTime().Int64() ); |
|
1080 |
|
1081 const MDesCArray& downloadedFiles = aPurchase.DownloadedFiles(); |
|
1082 |
|
1083 CBufBase* filesBuf = CBufFlat::NewL( KBufExpandSize ); |
|
1084 CleanupStack::PushL( filesBuf ); |
|
1085 |
|
1086 RBufWriteStream filesStream( *filesBuf ); |
|
1087 CleanupClosePushL( filesStream ); |
|
1088 |
|
1089 TInt filesCount = downloadedFiles.MdcaCount(); |
|
1090 filesStream.WriteInt32L( filesCount ); |
|
1091 for ( TInt i = 0; i < filesCount; i++ ) |
|
1092 { |
|
1093 // Downloaded files present. |
|
1094 |
|
1095 ExternalizeDesL( downloadedFiles.MdcaPoint( i ), filesStream ); |
|
1096 } |
|
1097 |
|
1098 CleanupStack::PopAndDestroy( &filesStream ); |
|
1099 TPtr8 filesPtr = filesBuf->Ptr( 0 ); |
|
1100 WriteLongTextColumn8L( aView, EDownloadedFiles, filesPtr ); |
|
1101 CleanupStack::PopAndDestroy( filesBuf ); |
|
1102 |
|
1103 CBufBase* installBuf = CBufFlat::NewL( KBufExpandSize ); |
|
1104 CleanupStack::PushL( installBuf ); |
|
1105 |
|
1106 RBufWriteStream installStream( *installBuf ); |
|
1107 CleanupClosePushL( installStream ); |
|
1108 |
|
1109 TInt installCount = aPurchase.InstallInfoCount(); |
|
1110 installStream.WriteInt32L( installCount ); |
|
1111 for ( TInt i = 0; i < installCount; i++ ) |
|
1112 { |
|
1113 // Install information present. |
|
1114 |
|
1115 CNcdPurchaseInstallInfo& info = aPurchase.InstallInfo( i ); |
|
1116 info.ExternalizeL( installStream ); |
|
1117 } |
|
1118 |
|
1119 CleanupStack::PopAndDestroy( &installStream ); |
|
1120 TPtr8 installPtr = installBuf->Ptr( 0 ); |
|
1121 WriteLongTextColumn8L( aView, EFileInstallInfos, installPtr ); |
|
1122 CleanupStack::PopAndDestroy( installBuf ); |
|
1123 |
|
1124 if ( aSaveIcon ) |
|
1125 { |
|
1126 DLTRACE(("Saving the icon to purchase history")); |
|
1127 WriteLongTextColumn8L( aView, EIcon, aPurchase.Icon() ); |
|
1128 } |
|
1129 WriteLongTextColumnL( |
|
1130 aView, |
|
1131 EDownloadAccessPoint, |
|
1132 aPurchase.DownloadAccessPoint() ); |
|
1133 WriteLongTextColumnL( aView, EDescription, aPurchase.Description() ); |
|
1134 WriteLongTextColumnL( aView, EVersion, aPurchase.Version() ); |
|
1135 WriteLongTextColumnL( aView, EServerUri, aPurchase.ServerUri() ); |
|
1136 aView.SetColL( EItemType, aPurchase.ItemType() ); |
|
1137 aView.SetColL( ETotalContentSize, aPurchase.TotalContentSize() ); |
|
1138 WriteLongTextColumnL( aView, EOriginNodeId, aPurchase.OriginNodeId() ); |
|
1139 aView.SetColL( ELastOperationTime, aPurchase.LastOperationTime().Int64() ); |
|
1140 aView.SetColL( ELastOperationErrorCode, aPurchase.LastOperationErrorCode() ); |
|
1141 |
|
1142 if( aPurchase.HasIcon() ) |
|
1143 { |
|
1144 // HasIcon flag can be set but never unset. |
|
1145 aView.SetColL( EHasIcon, ETrue ); |
|
1146 } |
|
1147 |
|
1148 // Externalize attributes |
|
1149 RCatalogsBufferWriter attributeWriter; |
|
1150 attributeWriter.OpenLC(); |
|
1151 aPurchase.ExternalizeAttributesL( attributeWriter() ); |
|
1152 WriteLongTextColumn8L( aView, EAttributes, attributeWriter.PtrL() ); |
|
1153 CleanupStack::PopAndDestroy( &attributeWriter ); |
|
1154 |
|
1155 } |
|
1156 |
|
1157 void CNcdPurchaseHistoryDb::SetEventCountL( TUint aEventCount ) |
|
1158 { |
|
1159 // Remove old event count from the database. |
|
1160 User::LeaveIfError( iDatabase.Execute( KSqlEventCountDelete ) ); |
|
1161 |
|
1162 // Construct database view. |
|
1163 RDbView view; |
|
1164 User::LeaveIfError( view.Prepare( |
|
1165 iDatabase, |
|
1166 TDbQuery( KSqlCurrentEventCount ), |
|
1167 RDbView::EInsertOnly ) ); |
|
1168 view.InsertL(); |
|
1169 |
|
1170 view.SetColL( KEventCounterColumnNumber, aEventCount ); |
|
1171 |
|
1172 // Insert event count into the database |
|
1173 view.PutL(); |
|
1174 view.Close(); |
|
1175 |
|
1176 // Remove all unnecessary data from the database. |
|
1177 User::LeaveIfError( iDatabase.Compact() ); |
|
1178 } |
|
1179 |
|
1180 TBool CNcdPurchaseHistoryDb::PurchaseExistsL( TUint aPurchaseId ) |
|
1181 { |
|
1182 TInt maxLength = KSqlPurchaseByPurchaseIdStart().Length() |
|
1183 + KMaxLengthOfInt |
|
1184 + KSqlPurchaseByPurchaseIdEnd().Length(); |
|
1185 |
|
1186 HBufC* sqlStatement = HBufC::NewLC( maxLength ); |
|
1187 TPtr statementPtr( sqlStatement->Des() ); |
|
1188 |
|
1189 statementPtr.Copy( KSqlPurchaseByPurchaseIdStart ); |
|
1190 statementPtr.AppendNum( aPurchaseId ); |
|
1191 statementPtr.Append( KSqlPurchaseByPurchaseIdEnd ); |
|
1192 |
|
1193 RDbView view; |
|
1194 CleanupClosePushL( view ); |
|
1195 |
|
1196 User::LeaveIfError( |
|
1197 view.Prepare( iDatabase, TDbQuery( *sqlStatement ) ) ); |
|
1198 |
|
1199 User::LeaveIfError( view.EvaluateAll() ); |
|
1200 view.FirstL(); |
|
1201 |
|
1202 TBool exists = EFalse; |
|
1203 |
|
1204 if ( view.AtRow() ) |
|
1205 { |
|
1206 exists = ETrue; |
|
1207 } |
|
1208 |
|
1209 CleanupStack::PopAndDestroy( &view ); |
|
1210 CleanupStack::PopAndDestroy( sqlStatement ); |
|
1211 |
|
1212 return exists; |
|
1213 } |
|
1214 |
|
1215 |
|
1216 void CNcdPurchaseHistoryDb::ValidatePurchaseDetailsL( |
|
1217 CNcdPurchaseDetails& aDetails ) |
|
1218 { |
|
1219 DLTRACEIN(("")); |
|
1220 |
|
1221 TInt dlInfoCount = aDetails.DownloadInfoCount(); |
|
1222 |
|
1223 // Add/remove filepaths so that there's as many filepaths as there are |
|
1224 // download infos. Download infos determine the real count because they |
|
1225 // are received from the protocol |
|
1226 TInt filePathDiff = dlInfoCount - aDetails.DownloadedFiles().MdcaCount(); |
|
1227 if ( filePathDiff > 0 ) |
|
1228 { |
|
1229 DLTRACE(("Adding %d empty filepaths", filePathDiff )); |
|
1230 while ( filePathDiff-- ) |
|
1231 { |
|
1232 aDetails.AddDownloadedFileL( KNullDesC() ); |
|
1233 } |
|
1234 } |
|
1235 else if ( filePathDiff < 0 ) // This shouldn't really ever happen |
|
1236 { |
|
1237 DLTRACE(("Removing %d filepaths", -filePathDiff )); |
|
1238 // Start from the end |
|
1239 TInt index = aDetails.DownloadedFiles().MdcaCount() - 1; |
|
1240 |
|
1241 filePathDiff = index + filePathDiff; |
|
1242 for ( ; index > filePathDiff; index-- ) |
|
1243 { |
|
1244 aDetails.RemoveDownloadedFile( index ); |
|
1245 } |
|
1246 } |
|
1247 |
|
1248 // install info count must be <= download info count |
|
1249 TInt installDiff = dlInfoCount - aDetails.InstallInfoCount(); |
|
1250 if ( installDiff < 0 ) // This shouldn't really ever happen |
|
1251 { |
|
1252 DLTRACE(("Removing %d install infos", -installDiff )); |
|
1253 // Start from the end |
|
1254 TInt index = aDetails.InstallInfoCount() - 1; |
|
1255 |
|
1256 installDiff = index + installDiff; |
|
1257 for ( ; index > installDiff; index-- ) |
|
1258 { |
|
1259 aDetails.RemoveInstallInfo( index ); |
|
1260 } |
|
1261 } |
|
1262 } |
|
1263 |