|
1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 // Local includes |
|
17 // |
|
18 #include "CSIContentHandler.h" |
|
19 |
|
20 // System includes |
|
21 // |
|
22 #include <push/sislpushmsgutils.h> |
|
23 #include <push/csipushmsgentry.h> |
|
24 #include <escapeutils.h> |
|
25 #include <msvids.h> |
|
26 #include <inetprottextutils.h> |
|
27 |
|
28 // SI string tables. |
|
29 #include "sitagstable.h" |
|
30 #include "siattributetable.h" |
|
31 #include "siattributevaluetable.h" |
|
32 |
|
33 |
|
34 const TInt KValidUTCLength = 20; |
|
35 |
|
36 |
|
37 #if defined(_DEBUG) |
|
38 _LIT(KErrPushMsgNull, "NULL CPushMessage"); |
|
39 #endif |
|
40 |
|
41 // Constants |
|
42 _LIT(KReserved, "Reserved"); |
|
43 |
|
44 void CSIContentHandler::CPushHandlerBase_Reserved1() |
|
45 { |
|
46 User::Panic(KReserved, KErrNotSupported); |
|
47 } |
|
48 |
|
49 void CSIContentHandler::CPushHandlerBase_Reserved2() |
|
50 { |
|
51 User::Panic(KReserved, KErrNotSupported); |
|
52 } |
|
53 |
|
54 /** |
|
55 * The SL Content handler private constructor. |
|
56 * Index number : ESIContentHandlerIndex |
|
57 */ |
|
58 CSIContentHandler::CSIContentHandler() |
|
59 : CContentHandlerBase(), iPushMsgAction(KErrNotFound), iExpiresTime(Time::NullTTime()), iCreatedTime(Time::NullTTime()), iValidDate(ETrue) |
|
60 { |
|
61 } |
|
62 |
|
63 /** |
|
64 * This will complete initialization of the object |
|
65 */ |
|
66 void CSIContentHandler::ConstructL() |
|
67 { |
|
68 iWapPushUtils = CSISLPushMsgUtils::NewL(); |
|
69 CActiveScheduler::Add(this); |
|
70 } |
|
71 |
|
72 /** |
|
73 * Static Factory Construction |
|
74 * |
|
75 * Version of NewL which leaves nothing |
|
76 * on the cleanup stack |
|
77 */ |
|
78 CSIContentHandler* CSIContentHandler::NewL() |
|
79 { |
|
80 CSIContentHandler* self = new(ELeave) CSIContentHandler; |
|
81 CleanupStack::PushL(self); |
|
82 self->ConstructL(); |
|
83 CleanupStack::Pop(self); |
|
84 return self; |
|
85 } |
|
86 |
|
87 /** |
|
88 * Default d'tor |
|
89 */ |
|
90 CSIContentHandler::~CSIContentHandler() |
|
91 { |
|
92 __LOG_PTR_DEBUG("CSIContentHandler:: Destructor Called"); |
|
93 delete iHrefBuf; |
|
94 delete iSiIdBuf; |
|
95 delete iData; |
|
96 delete iWapPushUtils; |
|
97 } |
|
98 |
|
99 /** |
|
100 * HandleMessage Async. Version |
|
101 * Takes ownership of Push Message and sets self active to continue |
|
102 * processing message. |
|
103 * @param aPushMsg |
|
104 * CPushMessage to process |
|
105 * @param aStatus |
|
106 * request status variable for use in asynchronous operations |
|
107 */ |
|
108 void CSIContentHandler::HandleMessageL(CPushMessage* aPushMsg, TRequestStatus& aStatus) |
|
109 { |
|
110 __LOG_PTR_DEBUG("CSIContentHandler:: HandleMessage Async Func. Called"); |
|
111 __ASSERT_DEBUG( aPushMsg != NULL, User::Panic(KErrPushMsgNull, KErrNone)); |
|
112 |
|
113 iMessage = aPushMsg; |
|
114 iAcknowledge = ETrue; |
|
115 SetConfirmationStatus(aStatus); |
|
116 |
|
117 iState= EParsing; |
|
118 IdleComplete(); |
|
119 } |
|
120 |
|
121 /** |
|
122 * HandleMessage Sync. Version |
|
123 * Takes ownership of Push Message and sets self active to continue |
|
124 * processing message. |
|
125 * |
|
126 * Initial State: Set data members then go to the next state |
|
127 * @param aPushMsg |
|
128 * CPushMessage to process |
|
129 */ |
|
130 void CSIContentHandler::HandleMessageL(CPushMessage* aPushMsg) |
|
131 { |
|
132 __LOG_PTR_DEBUG("CSIContentHandler:: HandleMessage Sync Func. Called"); |
|
133 __ASSERT_DEBUG( aPushMsg != NULL, User::Panic(KErrPushMsgNull, KErrNone)); |
|
134 |
|
135 iAcknowledge = EFalse; |
|
136 iMessage = aPushMsg; |
|
137 |
|
138 iState =EParsing; |
|
139 IdleComplete(); |
|
140 } |
|
141 |
|
142 /** |
|
143 * Parse the SI message from XML to its component parts which are held |
|
144 * in the document tree. This tree is then examined and the attributes |
|
145 * read and recorded for later reference. Once parsed the parser and tree |
|
146 * are deleted as no longer required. |
|
147 * @leave KErrNotFound |
|
148 * indicates general processing error and to abandon processing |
|
149 * @leave KErrCorrupt |
|
150 * there is no body in the message |
|
151 * @leave TDesC::AllocL |
|
152 |
|
153 */ |
|
154 void CSIContentHandler::ParsePushMsgL() |
|
155 { |
|
156 __LOG_PTR_DEBUG("CSIContentHandler:: ParsePushMsgL. Called"); |
|
157 |
|
158 CMessageParser* myParser = CMessageParser::NewL ( *iMessage, |
|
159 *this, |
|
160 &sitagstable::Table, |
|
161 &siattributetable::Table, |
|
162 &siattributevaluetable::Table ); |
|
163 CleanupStack::PushL ( myParser ); |
|
164 |
|
165 myParser->ParseMessageL (); |
|
166 |
|
167 User::LeaveIfError ( myParser->LastError() ); |
|
168 |
|
169 CleanupStack::PopAndDestroy ( myParser ); |
|
170 |
|
171 if (iData) |
|
172 { |
|
173 ( iData->Des() ).TrimLeft (); |
|
174 ( iData->Des() ).TrimRight (); |
|
175 } |
|
176 iState = EProcessing; |
|
177 IdleComplete(); |
|
178 } |
|
179 |
|
180 // Return value NULL indicates failed conversion! |
|
181 // Ownership of the resulting string is passed up to caller. |
|
182 HBufC16* CSIContentHandler::FormatDateStringL(const TDesC& aData) |
|
183 { |
|
184 const TInt KDateTimePart = 7; |
|
185 enum TDateTimeParts {EYearTop, EYearBot, EMon, EDay, EHour, EMin, ESec}; |
|
186 TInt dateData[KDateTimePart]; |
|
187 |
|
188 for (TInt i = 0; i < KDateTimePart; i++) |
|
189 dateData[i] = 0; |
|
190 |
|
191 TInt offSet = 0; |
|
192 TInt dataLen = aData.Length(); |
|
193 |
|
194 |
|
195 while (offSet < KDateTimePart && dataLen > 0) |
|
196 { |
|
197 dateData[offSet] = aData[offSet]; |
|
198 offSet++; |
|
199 dataLen--; |
|
200 } |
|
201 |
|
202 _LIT(KDateFormat,"%2x%02x-%02x-%02xT%02x:%02x:%02xZ"); |
|
203 const TInt KDateFormatLen = 20; |
|
204 |
|
205 TBuf16<KDateFormatLen> dateBuf; |
|
206 dateBuf.Format(KDateFormat, dateData[EYearTop], |
|
207 dateData[EYearBot], |
|
208 dateData[EMon], |
|
209 dateData[EDay], |
|
210 dateData[EHour], |
|
211 dateData[EMin], |
|
212 dateData[ESec]); |
|
213 return( dateBuf.AllocL() ); |
|
214 } |
|
215 |
|
216 |
|
217 /** |
|
218 * Convert UTC date time into native TTime format. Method can not leave |
|
219 * and traps any leaves from ValidateUTCTimeL. |
|
220 * @param aDateTime |
|
221 * the UTC string representing the date and time |
|
222 * @param aConvertedDate |
|
223 * member date variable passed in to accept converted UTC date as TTime varaible |
|
224 * @return TBool |
|
225 * indicates if conversion successful (ETrue) or conversion failed (EFalse) |
|
226 */ |
|
227 TBool CSIContentHandler::ConvertDateTimeL(const TDesC& aDateTime, TTime &aConvertedDate) |
|
228 { |
|
229 TTime convertedTime = Time::NullTTime(); |
|
230 TBool convertedOK = EFalse; |
|
231 |
|
232 HBufC* dateTime = NULL; |
|
233 if (aDateTime.Length() == KValidUTCLength) //check supplied descriptor is the correct length |
|
234 { |
|
235 dateTime = aDateTime.AllocLC (); |
|
236 } |
|
237 else |
|
238 { |
|
239 // Convert to UTC string |
|
240 dateTime = FormatDateStringL ( aDateTime ); |
|
241 CleanupStack::PushL ( dateTime ); |
|
242 } |
|
243 |
|
244 TBuf<20> str = dateTime->Des(); |
|
245 if (IsValidUTCTime(str)) |
|
246 { |
|
247 // adjust UTC time to zero offset TTime |
|
248 const TInt KFirstMonthChar = 4; |
|
249 const TInt KSecondMonthChar = KFirstMonthChar + 1; |
|
250 const TInt KFirstDayChar = 6; |
|
251 const TInt KSecondDayChar = KFirstDayChar + 1; |
|
252 // check for special case of month = 10 which becomes 09 |
|
253 if (str[KFirstMonthChar]=='1' && str[KSecondMonthChar] == '0') |
|
254 { |
|
255 str[KFirstMonthChar]='0'; |
|
256 str[KSecondMonthChar]='9'; |
|
257 } |
|
258 else |
|
259 // month value is either 11, 12 or less than 10, ie 1 - 9. |
|
260 // reduce day by one, eg 11 becomes 10, 12 becomes 11, 09 becomes 08 |
|
261 str[KSecondMonthChar]-- ; |
|
262 |
|
263 // check for special cases 10, 20, 30 |
|
264 if (str[KSecondDayChar] == '0') |
|
265 { |
|
266 // reduce day by 1, ie 10 becomes 09, 20 becomes 19 ... |
|
267 str[KSecondDayChar] = '9'; |
|
268 str[KFirstDayChar]--; |
|
269 } |
|
270 else |
|
271 // day value is between 1 and 9 so reduce day by one |
|
272 // eg 29 becomes 28, 11 bcomes 10, 31 becomes 30 |
|
273 str[KSecondDayChar]--; |
|
274 |
|
275 // string is now syntaxically correct and year will be not be negative |
|
276 // so no errors will occur here and will now have a valid TTime |
|
277 convertedTime.Set(str); |
|
278 convertedOK = ETrue; |
|
279 } |
|
280 |
|
281 aConvertedDate = convertedTime; |
|
282 CleanupStack::PopAndDestroy ( dateTime ); |
|
283 if(!convertedOK) |
|
284 { |
|
285 iValidDate = EFalse; |
|
286 } |
|
287 return convertedOK; |
|
288 } |
|
289 |
|
290 /** |
|
291 * Check given UTC time string conforms to expected format: |
|
292 * YYYY-MM-DDTHH:MM:SSZ and strip out formatting characters |
|
293 * then validate the remaining characters are all digits. |
|
294 * If validated then add TTime formating character so final |
|
295 * string returned will be of the format YYYYMMDD:HHMMSS. |
|
296 * @param aDateTime |
|
297 * UTC string which is validated and returned |
|
298 * @return boolean |
|
299 * indicates if given date is valid (ETrue) |
|
300 * or not (EFalse) |
|
301 */ |
|
302 TBool CSIContentHandler::IsValidUTCTime(TDes& aDateTime) |
|
303 { |
|
304 // strip out formatting characters |
|
305 TInt formatCharPos = 4; |
|
306 aDateTime.Delete(formatCharPos, 1); |
|
307 // now move through two characters at a time and remove other chars |
|
308 // to just leave digits |
|
309 TInt KRemainingFormatChars = 5; |
|
310 for (TInt i = 0 ; i < KRemainingFormatChars; i++) |
|
311 { |
|
312 formatCharPos += 2; |
|
313 aDateTime.Delete(formatCharPos, 1); |
|
314 } |
|
315 |
|
316 // check string now the right TTime length |
|
317 const TInt KValidTTimeLength = 14; |
|
318 if (aDateTime.Length() != KValidTTimeLength) |
|
319 return EFalse; |
|
320 |
|
321 // now have UTC string stripped of format characters - check remaining characters are |
|
322 // all digits - YYYYMMDDHHMMSS |
|
323 TChar ch; |
|
324 for (TInt x = 0; x < KValidTTimeLength; x++) |
|
325 { |
|
326 ch = aDateTime[x]; |
|
327 if (ch.IsDigit() == EFalse) |
|
328 return EFalse; |
|
329 } |
|
330 |
|
331 TInt err = ValidateDateTime( aDateTime ); |
|
332 if(!err) |
|
333 return EFalse; |
|
334 |
|
335 // insert colon seperating date from time |
|
336 _LIT(colon, ":"); |
|
337 const TInt KColonPosition = 8; |
|
338 aDateTime.Insert(KColonPosition, colon); |
|
339 return ETrue; |
|
340 } |
|
341 |
|
342 /** |
|
343 * Validate date and time to check whether date and time values lie |
|
344 * within the valid range |
|
345 * @param aDateTime |
|
346 * UTC string which is validated |
|
347 * @return boolean |
|
348 * indicates if given date and time is valid (ETrue) |
|
349 * or not (EFalse) |
|
350 */ |
|
351 TBool CSIContentHandler::ValidateDateTime(TDes& aDateTime) |
|
352 { |
|
353 TPtrC ptr(aDateTime); |
|
354 TPtrC yr; |
|
355 yr.Set(ptr.Left(4)); |
|
356 TInt yearInt; |
|
357 InetProtTextUtils::ConvertDescriptorToInt(yr,yearInt); |
|
358 |
|
359 TPtrC month; |
|
360 month.Set(ptr.Mid(4)); |
|
361 TPtrC mon; |
|
362 mon.Set(month.Left(2)); |
|
363 TInt monthInt; |
|
364 InetProtTextUtils::ConvertDescriptorToInt(mon,monthInt); |
|
365 |
|
366 TPtrC day; |
|
367 day.Set(month.Mid(2)); |
|
368 TPtrC dy; |
|
369 dy.Set(day.Left(2)); |
|
370 TInt dayInt; |
|
371 InetProtTextUtils::ConvertDescriptorToInt(dy,dayInt); |
|
372 |
|
373 TPtrC hour; |
|
374 hour.Set(day.Mid(2)); |
|
375 TPtrC hr; |
|
376 hr.Set(hour.Left(2)); |
|
377 TInt hourInt; |
|
378 InetProtTextUtils::ConvertDescriptorToInt(hr,hourInt); |
|
379 |
|
380 TPtrC minute; |
|
381 minute.Set(hour.Mid(2)); |
|
382 TPtrC min; |
|
383 min.Set(minute.Left(2)); |
|
384 TInt minInt; |
|
385 InetProtTextUtils::ConvertDescriptorToInt(min,minInt); |
|
386 |
|
387 TPtrC second; |
|
388 second.Set(minute.Mid(2)); |
|
389 TPtrC sec; |
|
390 sec.Set(second.Left(2)); |
|
391 TInt secInt; |
|
392 InetProtTextUtils::ConvertDescriptorToInt(sec,secInt); |
|
393 |
|
394 |
|
395 if ( monthInt == 1 || monthInt == 3 || monthInt == 5 || monthInt == 7 |
|
396 || monthInt == 8 || monthInt == 10 || monthInt == 12) |
|
397 { |
|
398 if (!(dayInt <= 31)) |
|
399 return EFalse; |
|
400 } |
|
401 else if (monthInt == 04 || monthInt == 06 || monthInt == 9 || monthInt == 11) |
|
402 { |
|
403 if (!(dayInt <= 30)) |
|
404 return EFalse; |
|
405 } |
|
406 else if (monthInt == 02) |
|
407 { |
|
408 if (Time::IsLeapYear(yearInt)) |
|
409 { |
|
410 if (!(dayInt <= 29)) |
|
411 return EFalse; |
|
412 } |
|
413 else if (!(dayInt <= 28)) |
|
414 return EFalse; |
|
415 } |
|
416 else |
|
417 { |
|
418 return EFalse; |
|
419 } |
|
420 |
|
421 if ( !(hourInt <= 23 && minInt <= 59 && secInt <= 59)) |
|
422 return EFalse; |
|
423 |
|
424 return ETrue; |
|
425 } |
|
426 |
|
427 /** |
|
428 * Convert the action string to a representative numeric value to facilitate |
|
429 * storing the message in the wap push utils. |
|
430 * @param aActionString |
|
431 * the attribute value indicating the action level eg 'signal-high' |
|
432 * @return TUint |
|
433 * a value representing the action type (as defined in PushEntry.h) |
|
434 */ |
|
435 TUint CSIContentHandler::ConvertActionString(const RString& aActionString) |
|
436 { |
|
437 // set to default signal value (to rid ourselves of build warning) |
|
438 TUint actionValue = CSIPushMsgEntry::ESIPushMsgSignalMedium; |
|
439 switch ( aActionString.Index ( siattributevaluetable::Table ) ) |
|
440 { |
|
441 case siattributevaluetable::EAction1: |
|
442 actionValue = CSIPushMsgEntry::ESIPushMsgSignalNone; |
|
443 break; |
|
444 case siattributevaluetable::EAction2: |
|
445 actionValue = CSIPushMsgEntry::ESIPushMsgSignalLow; |
|
446 break; |
|
447 case siattributevaluetable::EAction3: |
|
448 actionValue = CSIPushMsgEntry::ESIPushMsgSignalMedium; |
|
449 break; |
|
450 case siattributevaluetable::EAction4: |
|
451 actionValue = CSIPushMsgEntry::ESIPushMsgSignalHigh; |
|
452 break; |
|
453 case siattributevaluetable::EAction5: |
|
454 actionValue = CSIPushMsgEntry::ESIPushMsgDelete; |
|
455 break; |
|
456 default: |
|
457 User::Invariant (); |
|
458 } |
|
459 return actionValue; |
|
460 } |
|
461 |
|
462 /** |
|
463 * Handles message reception and processes the received message following |
|
464 * the flow of actions detailed in 7.2 Reception |
|
465 * [WAP Service Indication 08-Nov-1999] |
|
466 * 1. check if received message is expired |
|
467 * 2. if received message is an older version of stored SI, |
|
468 * or is the same age - discard received message |
|
469 * 3. if message is more recent version than stored SI - delete stored SI |
|
470 * 4. if message actioned to delete, and has Si Id set, then delete it |
|
471 * and any stored messages with same id |
|
472 * finally if received message not set to deleted or discarded - store it |
|
473 */ |
|
474 void CSIContentHandler::ProcessingPushMsgEntryL() |
|
475 { |
|
476 __LOG_PTR_DEBUG("CSIContentHandler:: ProcessingPushMsgEntryL. called"); |
|
477 TBool deletePushMsg = EFalse; |
|
478 |
|
479 // 1. Expiration |
|
480 TTime today; |
|
481 today.UniversalTime(); |
|
482 // check if message has expiry date before today's date |
|
483 if (ExpiresFlag() && iExpiresTime < today) |
|
484 { |
|
485 deletePushMsg = ETrue; |
|
486 __LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: Expired msg (1)"); |
|
487 } |
|
488 |
|
489 // 2. handling out of order delivery & |
|
490 // 3. replacement |
|
491 else if (SiIdFlag() || HrefFlag()) |
|
492 deletePushMsg = HandleMsgOrderReceptionL(); |
|
493 |
|
494 // 4. deletion |
|
495 if (!deletePushMsg && ActionFlag()) |
|
496 { |
|
497 // check if action = delete and SiId value is set before can delete |
|
498 if ((iPushMsgAction == CSIPushMsgEntry::ESIPushMsgDelete) && (SiIdFlag())) |
|
499 { |
|
500 __LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: delete msg (4)"); |
|
501 |
|
502 // delete msg and any matching messages (with same si-id) |
|
503 __LOG_PTR_DEBUG("CWapPushMsgUtils: FindSiIdLC called"); |
|
504 CMsvEntrySelection* matchingIdList = iWapPushUtils->FindSiIdLC(*iSiIdBuf); |
|
505 TInt matchingListCount = matchingIdList->Count(); |
|
506 for (TInt count = 0; count < matchingListCount; count++) |
|
507 { |
|
508 TMsvId matchingSiMsgEntryId = matchingIdList->At(count); |
|
509 if (matchingSiMsgEntryId) |
|
510 { |
|
511 __LOG_PTR_DEBUG("CWapPushMsgUtils: DeleteEntryNowL called"); |
|
512 iWapPushUtils->DeleteEntryNowL(matchingSiMsgEntryId); |
|
513 } |
|
514 } |
|
515 CleanupStack::PopAndDestroy(); // matchingIdList |
|
516 deletePushMsg = ETrue; |
|
517 } |
|
518 } |
|
519 |
|
520 // store message if not marked for deletion and date/time is valid |
|
521 if (!deletePushMsg && iValidDate) |
|
522 StoreSIMessageL(); |
|
523 // Reset the flag to ETrue for next message |
|
524 iValidDate = ETrue; |
|
525 |
|
526 iState = EDone; |
|
527 IdleComplete(); |
|
528 } |
|
529 |
|
530 /** |
|
531 * Check received SI message against existing stored messages |
|
532 * with the same si-id and update the message(s) according to |
|
533 * the creation date (if specified). |
|
534 * @return TBool |
|
535 * ETrue - Received SI message older than stored match(es) |
|
536 * and should be marked for deletion |
|
537 * EFalse - Receieved SI message to be retained as newer |
|
538 * therefore do not delete it |
|
539 */ |
|
540 TBool CSIContentHandler::HandleMsgOrderReceptionL() |
|
541 { |
|
542 CMsvEntrySelection* matchingIdList; |
|
543 TBool discardPushMsg = EFalse; |
|
544 |
|
545 __LOG_PTR_DEBUG("CSISLPushMsgUtils: FindSiIdLC called"); |
|
546 // get list of matching stored SI messages |
|
547 if (SiIdFlag()) |
|
548 matchingIdList = iWapPushUtils->FindSiIdLC(*iSiIdBuf); |
|
549 else |
|
550 matchingIdList = iWapPushUtils->FindSiIdLC(*iHrefBuf); |
|
551 |
|
552 // check we have a creation date specified before checking against list of matches |
|
553 if (matchingIdList->Count() && CreatedFlag()) |
|
554 { |
|
555 CSIPushMsgEntry* siEntry=GetSiEntryL(); |
|
556 CleanupStack::PushL(siEntry); |
|
557 |
|
558 // delete older stored messages and/or mark current message for deletion |
|
559 // if same date or older than stored messages |
|
560 TInt matchingListCount = matchingIdList->Count(); |
|
561 for (TInt count = 0; count < matchingListCount; count++) |
|
562 { |
|
563 TMsvId matchingSiMsgEntryId = matchingIdList->At(count); |
|
564 |
|
565 __LOG_PTR_DEBUG("CSIPushMsgEntry: RetrieveL called"); |
|
566 siEntry->RetrieveL(iWapPushUtils->Session(), matchingSiMsgEntryId); |
|
567 |
|
568 // skip date comparisons if creation date not valid |
|
569 TTime existingSiCreatedTime = siEntry->Created(); |
|
570 if (existingSiCreatedTime == Time::NullTTime()) |
|
571 continue; |
|
572 //check if received SI is newer than existing stored Si (out of order) |
|
573 if (iCreatedTime > existingSiCreatedTime) |
|
574 { |
|
575 __LOG_PTR_DEBUG("CWapPushMsgUtils: DeleteEntryNowL called"); |
|
576 iWapPushUtils->DeleteEntryNowL(matchingSiMsgEntryId); |
|
577 __LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: delete stored msg (3)"); |
|
578 } |
|
579 else if (iCreatedTime <= existingSiCreatedTime) |
|
580 // received SI older than existing stored Si (replacement) |
|
581 discardPushMsg = ETrue; |
|
582 } |
|
583 CleanupStack::PopAndDestroy(siEntry); |
|
584 } |
|
585 |
|
586 CleanupStack::PopAndDestroy(matchingIdList); |
|
587 |
|
588 if (discardPushMsg) |
|
589 { |
|
590 __LOG_PTR_DEBUG("CSIContentHandler: ProcessingPushMsgEntryL: discard msg (2)"); |
|
591 } |
|
592 return discardPushMsg; |
|
593 } |
|
594 |
|
595 |
|
596 /** |
|
597 * Save push message in message store. |
|
598 * Creates link to message service provided by wap push utils |
|
599 * and uses this and the associated push entry class to save |
|
600 * the push message. |
|
601 */ |
|
602 void CSIContentHandler::StoreSIMessageL() |
|
603 { |
|
604 __LOG_PTR_DEBUG("CSIContentHandler:: StoreSiMessageL. called"); |
|
605 |
|
606 CSIPushMsgEntry* siEntry=GetSiEntryL(); |
|
607 CleanupStack::PushL(siEntry); |
|
608 SetSIPushMsgEntryFieldsL(*siEntry); |
|
609 |
|
610 TMsvId folderId; |
|
611 iWapPushUtils->GetPushMsgFolderIdL(folderId); |
|
612 |
|
613 __LOG_PTR_DEBUG("CSIPushMsgEntry::SaveL called"); |
|
614 siEntry->SaveL(iWapPushUtils->Session(), folderId); |
|
615 |
|
616 CleanupStack::PopAndDestroy(siEntry); |
|
617 } |
|
618 |
|
619 |
|
620 CSIPushMsgEntry* CSIContentHandler::GetSiEntryL() |
|
621 { |
|
622 TBool isInt; |
|
623 TPtrC8 appURI; |
|
624 TInt appID=0; |
|
625 iMessage->GetAppIdL(appURI, appID, isInt); |
|
626 CSIPushMsgEntry* siEntry=NULL; |
|
627 if (isInt) |
|
628 { |
|
629 siEntry = CSIPushMsgEntry::NewL(appID); |
|
630 } |
|
631 else |
|
632 { |
|
633 siEntry = CSIPushMsgEntry::NewL(appURI); |
|
634 } |
|
635 return siEntry; |
|
636 } |
|
637 |
|
638 /** |
|
639 * Create SI entry fields prior to storing message. The saving of |
|
640 * certain push message attributes will be set to defaults if |
|
641 * information missing to facilitate message searching, storing |
|
642 * and retrieval. |
|
643 * @param siEntry |
|
644 * entry represents message format to use when storing it |
|
645 */ |
|
646 void CSIContentHandler::SetSIPushMsgEntryFieldsL(CSIPushMsgEntry& aSIPushMsgEntry) |
|
647 { |
|
648 // if message has no si-id but does have a href - use href as si-id and |
|
649 // if message has a si-id but no href use si-id for href |
|
650 |
|
651 if (SiIdFlag() || HrefFlag()) |
|
652 { |
|
653 if (SiIdFlag() && (HrefFlag() == EFalse)) |
|
654 { |
|
655 aSIPushMsgEntry.SetIdL(*iSiIdBuf); |
|
656 aSIPushMsgEntry.SetUrlL(*iSiIdBuf); |
|
657 } |
|
658 else if (HrefFlag() && (SiIdFlag() == EFalse)) |
|
659 { |
|
660 aSIPushMsgEntry.SetIdL(*iHrefBuf); |
|
661 aSIPushMsgEntry.SetUrlL(*iHrefBuf); |
|
662 } |
|
663 else |
|
664 { |
|
665 aSIPushMsgEntry.SetIdL(*iSiIdBuf); |
|
666 aSIPushMsgEntry.SetUrlL(*iHrefBuf); |
|
667 } |
|
668 } |
|
669 |
|
670 if (ActionFlag()) |
|
671 aSIPushMsgEntry.SetAction(iPushMsgAction); |
|
672 else // default if no action explicitly stated |
|
673 aSIPushMsgEntry.SetAction(CSIPushMsgEntry::ESIPushMsgSignalMedium); |
|
674 |
|
675 // uses default null time value if no explicit date set in message |
|
676 aSIPushMsgEntry.SetCreated(iCreatedTime); |
|
677 aSIPushMsgEntry.SetExpires(iExpiresTime); |
|
678 |
|
679 // PCDATA (text) from message |
|
680 if (DataFlag()) |
|
681 aSIPushMsgEntry.SetTextL(*iData); |
|
682 |
|
683 TPtrC8 msgHeaderPtr; |
|
684 iMessage->GetHeader(msgHeaderPtr); |
|
685 aSIPushMsgEntry.SetHeaderL(msgHeaderPtr); |
|
686 |
|
687 TPtrC8 from; |
|
688 if (!iMessage->GetBinaryHeaderField(EHttpFrom, from) && |
|
689 !iMessage->GetBinaryHeaderField(EHttpXWapInitiatorURI, from) && |
|
690 !iMessage->GetBinaryHeaderField(EHttpContentLocation, from) ) |
|
691 { |
|
692 from.Set(KNullDesC8); |
|
693 } |
|
694 aSIPushMsgEntry.SetFromL(from); |
|
695 |
|
696 if(iMessage->MessageAllowed()) |
|
697 { |
|
698 aSIPushMsgEntry.SetTrusted(ETrue); |
|
699 } |
|
700 else |
|
701 { |
|
702 aSIPushMsgEntry.SetTrusted(EFalse); |
|
703 } |
|
704 |
|
705 TPtrC8 serverAddress8; |
|
706 iMessage->GetServerAddress(serverAddress8); |
|
707 aSIPushMsgEntry.SetMsgOriginUriL(serverAddress8); |
|
708 } |
|
709 |
|
710 /** |
|
711 * Same functionality as DoCancel() |
|
712 */ |
|
713 void CSIContentHandler::CancelHandleMessage() |
|
714 { |
|
715 __LOG_PTR_DEBUG("CSIContentHandler:: CancelHandleMessage called"); |
|
716 Complete(KErrCancel); |
|
717 } |
|
718 |
|
719 /** |
|
720 * Cancels the handling of the message and revokes the active status |
|
721 * of the handler |
|
722 */ |
|
723 void CSIContentHandler::DoCancel() |
|
724 { |
|
725 __LOG_PTR_DEBUG("CSIContentHandler:: DoCancel Called"); |
|
726 Complete(KErrCancel); |
|
727 } |
|
728 |
|
729 /** |
|
730 * Step through the various representative states for handling a message |
|
731 * 1. validate the message by parsing it against the relevant DTD |
|
732 * 2. process the message in accordance with the Reception rules |
|
733 * 3. finish up |
|
734 */ |
|
735 void CSIContentHandler::RunL() |
|
736 { |
|
737 __LOG_PTR_DEBUG("CSIContentHandler:: RunL Called"); |
|
738 // use active state machine routine to manage activites: |
|
739 switch (iState) |
|
740 { |
|
741 case EParsing : |
|
742 ParsePushMsgL(); |
|
743 break; |
|
744 case EProcessing: |
|
745 ProcessingPushMsgEntryL(); |
|
746 break; |
|
747 case EDone: |
|
748 Complete(KErrNone); |
|
749 break; |
|
750 default: |
|
751 break; |
|
752 } |
|
753 } |
|
754 |
|
755 /** |
|
756 * CPluginActiveBase methods |
|
757 */ |
|
758 TInt CSIContentHandler::RunError(TInt aError) |
|
759 { |
|
760 __LOG_PTR_DEBUG("CSIContentHandler:: RunError Called"); |
|
761 iState=EDone; |
|
762 Complete(aError); |
|
763 return KErrNone; |
|
764 } |
|
765 |
|
766 void CSIContentHandler::HandleElementL ( const RString& aTag, const RString& aAttributeName, const RString& aAttributeValue ) |
|
767 { |
|
768 __LOG_PTR_DEBUG( "CSIContentHandler:: HandleElementL Called" ); |
|
769 |
|
770 const TDesC8& tag = aTag.DesC(); |
|
771 iIndicationTagFound = EFalse; |
|
772 |
|
773 if ( aTag.Index ( sitagstable::Table ) == sitagstable::EIndication ) |
|
774 { |
|
775 iIndicationTagFound = ETrue; |
|
776 } |
|
777 |
|
778 TBool gotDate = EFalse; |
|
779 HBufC* des16 = EscapeUtils::ConvertToUnicodeFromUtf8L ( aAttributeValue.DesC() ); |
|
780 CleanupStack::PushL ( des16 ); |
|
781 |
|
782 switch ( aAttributeName.Index ( siattributetable::Table ) ) |
|
783 { |
|
784 case siattributetable::EAction1: |
|
785 case siattributetable::EAction2: |
|
786 case siattributetable::EAction3: |
|
787 case siattributetable::EAction4: |
|
788 case siattributetable::EAction5: |
|
789 iPushMsgAction = ConvertActionString( aAttributeValue ); |
|
790 SetActionFlag(ETrue); |
|
791 break; |
|
792 |
|
793 case siattributetable::ECreated: |
|
794 gotDate = ConvertDateTimeL ( *des16, iCreatedTime ); |
|
795 SetCreatedFlag(gotDate); |
|
796 break; |
|
797 |
|
798 case siattributetable::EHref: |
|
799 delete iHrefBuf; |
|
800 iHrefBuf = NULL; |
|
801 |
|
802 iHrefBuf = ( des16->Des() ).AllocL (); |
|
803 SetHrefFlag(ETrue); |
|
804 break; |
|
805 |
|
806 case siattributetable::ESiExpires: |
|
807 gotDate = ConvertDateTimeL ( *des16, iExpiresTime ); |
|
808 SetExpiresFlag(gotDate); |
|
809 break; |
|
810 |
|
811 case siattributetable::ESiId: |
|
812 delete iSiIdBuf; |
|
813 iSiIdBuf = NULL; |
|
814 |
|
815 iSiIdBuf = ( des16->Des() ).AllocL (); |
|
816 SetSiIdFlag(ETrue); |
|
817 break; |
|
818 |
|
819 case siattributetable::EClass: |
|
820 break; |
|
821 |
|
822 default: |
|
823 // Shouldn't come here. |
|
824 User::Invariant (); |
|
825 } |
|
826 |
|
827 CleanupStack::PopAndDestroy ( des16 ); |
|
828 } |
|
829 |
|
830 void CSIContentHandler::HandleContentL ( const TDesC8& aBytes ) |
|
831 { |
|
832 // We do handle content only if it is in indication tag. |
|
833 // else we reject the content. |
|
834 if ( !iIndicationTagFound ) |
|
835 { |
|
836 return; |
|
837 } |
|
838 if ( iData ) |
|
839 { |
|
840 HBufC* des16 = EscapeUtils::ConvertToUnicodeFromUtf8L ( aBytes ); |
|
841 CleanupStack::PushL ( des16 ); |
|
842 |
|
843 TInt newDataLength = des16->Length (); |
|
844 TInt existingDataLength = iData->Length (); |
|
845 |
|
846 if ( ( newDataLength + existingDataLength ) > existingDataLength ) |
|
847 { |
|
848 iData = iData->ReAllocL ( newDataLength + existingDataLength ); |
|
849 } |
|
850 |
|
851 (iData->Des()).Append( *des16 ); |
|
852 |
|
853 CleanupStack::PopAndDestroy ( des16 ); |
|
854 } |
|
855 else |
|
856 { |
|
857 iData = EscapeUtils::ConvertToUnicodeFromUtf8L ( aBytes ); |
|
858 } |
|
859 SetDataFlag ( ETrue ); |
|
860 } |
|
861 |