1 /* |
|
2 * Copyright (c) 2002 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 the License "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: Implementation of CSIContentHandler. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 |
|
22 #include "CSIContentHandler.h" |
|
23 #include "PushMtmUtil.h" |
|
24 #include "PushMtmSettings.h" |
|
25 #include "PushMtmLog.h" |
|
26 #include "PushMtmUiDef.h" |
|
27 #include "StringResourceReader.h" |
|
28 #include "PushContentHandlerPanic.h" |
|
29 #include "si_dict.h" |
|
30 #include "PushContentHandlerUtils.h" |
|
31 #include <push/CSIPushMsgEntry.h> |
|
32 #include <msvids.h> |
|
33 #include <PushMtmUi.rsg> |
|
34 #include <nw_dom_node.h> |
|
35 #include <nw_dom_document.h> |
|
36 #include <nw_dom_element.h> |
|
37 #include <nw_dom_text.h> |
|
38 #include <nw_wbxml_dictionary.h> |
|
39 #include <THttpFields.h> |
|
40 |
|
41 // CONSTANTS |
|
42 |
|
43 // si attributes / elements |
|
44 _LIT8( KSi, "si" ); |
|
45 _LIT8( KIndication, "indication" ); |
|
46 _LIT8( KHrefAttrib, "href" ); |
|
47 _LIT8( KSiIdAttrib, "si-id" ); |
|
48 _LIT8( KCreatedAttrib, "created" ); |
|
49 _LIT8( KExpiresAttrib, "si-expires" ); |
|
50 _LIT8( KActionAttrib, "action" ); |
|
51 |
|
52 // action attribute literals |
|
53 _LIT8( KDeleteAction, "delete" ); |
|
54 _LIT8( KSignalNone, "signal-none" ); |
|
55 _LIT8( KSignalLow, "signal-low" ); |
|
56 _LIT8( KSignalMedium, "signal-medium" ); |
|
57 _LIT8( KSignalHigh, "signal-high" ); |
|
58 |
|
59 _LIT( KSiTextContentType, "text/vnd.wap.si" ); |
|
60 |
|
61 const TInt KValidMaxEncodedDateTimeSize = 7; |
|
62 const TInt KValidUTCLength = 20; // YYYY-MM-DDTHH:MM:SSZ |
|
63 const TInt KValidUTCNumericals = 14; |
|
64 const TInt KValidUTCYearBlockLength = 4; |
|
65 const TInt KValidUTCOtherBlockLength = 2; |
|
66 const TUint8 KAsciiZeroCharCode = 0x30; |
|
67 |
|
68 const TInt KValidTTimeMonthStart = 4; |
|
69 const TInt KValidTTimeDayStart = 6; |
|
70 const TInt KValidTTimeHourStart = 8; |
|
71 const TInt KValidTTimeMinuteStart = 10; |
|
72 const TInt KValidTTimeSecondStart = 12; |
|
73 const TInt KValidTTimeBlockLength = 2; |
|
74 |
|
75 const TInt KValidTTimeLength = 14; // YYYYMMDDHHMMSS |
|
76 |
|
77 const TInt KNoOfDictArrays = 1; |
|
78 |
|
79 _LIT( KCharMinus, "-" ); |
|
80 _LIT( KCharT, "T" ); |
|
81 _LIT( KCharColon, ":" ); |
|
82 _LIT( KCharZ, "Z" ); |
|
83 |
|
84 /// Conversion buffer size. |
|
85 LOCAL_D const TInt KPushConversionBufferSize = 256; |
|
86 /// Zero width non-breaking space character. |
|
87 LOCAL_D const TUint16 KPushZeroWidthNbsp = 0xfeff; |
|
88 |
|
89 // ================= MEMBER FUNCTIONS ======================= |
|
90 |
|
91 // --------------------------------------------------------- |
|
92 // CSIContentHandler::NewL |
|
93 // --------------------------------------------------------- |
|
94 // |
|
95 CSIContentHandler* CSIContentHandler::NewL() |
|
96 { |
|
97 PUSHLOG_ENTERFN("CSIContentHandler::NewL") |
|
98 |
|
99 CSIContentHandler* self = new (ELeave) CSIContentHandler; |
|
100 CleanupStack::PushL( self ); |
|
101 self->ConstructL(); |
|
102 CleanupStack::Pop( self ); |
|
103 |
|
104 PUSHLOG_LEAVEFN("CSIContentHandler::NewL") |
|
105 return self; |
|
106 } |
|
107 |
|
108 // --------------------------------------------------------- |
|
109 // CSIContentHandler::~CSIContentHandler |
|
110 // --------------------------------------------------------- |
|
111 // |
|
112 CSIContentHandler::~CSIContentHandler() |
|
113 { |
|
114 PUSHLOG_ENTERFN("CSIContentHandler::~CSIContentHandler") |
|
115 |
|
116 Cancel(); |
|
117 delete iHrefBuf; |
|
118 delete iSiIdBuf; |
|
119 delete iData; |
|
120 delete iCharacterSetConverter; |
|
121 iCharacterSetConverter = NULL; |
|
122 delete iCharacterSetsAvailable; |
|
123 iCharacterSetsAvailable = NULL; |
|
124 |
|
125 PUSHLOG_LEAVEFN("CSIContentHandler::~CSIContentHandler") |
|
126 } |
|
127 |
|
128 // --------------------------------------------------------- |
|
129 // CSIContentHandler::CSIContentHandler |
|
130 // --------------------------------------------------------- |
|
131 // |
|
132 CSIContentHandler::CSIContentHandler() |
|
133 : CPushContentHandlerBase(), |
|
134 iSavedMsgId( KMsvNullIndexEntryId ), |
|
135 iPushMsgAction( KErrNotFound ), |
|
136 iExpiresTime( Time::NullTTime() ), |
|
137 iCreatedTime( Time::NullTTime() ) |
|
138 { |
|
139 } |
|
140 |
|
141 // --------------------------------------------------------- |
|
142 // CSIContentHandler::ConstructL |
|
143 // --------------------------------------------------------- |
|
144 // |
|
145 void CSIContentHandler::ConstructL() |
|
146 { |
|
147 PUSHLOG_ENTERFN("CSIContentHandler::ConstructL") |
|
148 |
|
149 CPushContentHandlerBase::ConstructL(); |
|
150 // Added to Active Scheduler. |
|
151 |
|
152 PUSHLOG_LEAVEFN("CSIContentHandler::ConstructL") |
|
153 } |
|
154 |
|
155 // --------------------------------------------------------- |
|
156 // CSIContentHandler::CollectGarbageL |
|
157 // --------------------------------------------------------- |
|
158 // |
|
159 void CSIContentHandler::CollectGarbageL() |
|
160 { |
|
161 PUSHLOG_ENTERFN("CSIContentHandler::CollectGarbageL") |
|
162 |
|
163 DoCollectGarbageL(); |
|
164 |
|
165 //Ready. |
|
166 iState = EFilteringAndParsing; |
|
167 IdleComplete(); |
|
168 |
|
169 PUSHLOG_LEAVEFN("CSIContentHandler::CollectGarbageL") |
|
170 } |
|
171 |
|
172 // --------------------------------------------------------- |
|
173 // CSIContentHandler::ParsePushMsgL |
|
174 // Note that cXML parser dosn't do any validation! |
|
175 // --------------------------------------------------------- |
|
176 // |
|
177 void CSIContentHandler::ParsePushMsgL() |
|
178 { |
|
179 PUSHLOG_ENTERFN("CSIContentHandler::ParsePushMsgL") |
|
180 |
|
181 TPtrC8 bodyPtr; |
|
182 iMessage->GetMessageBody( bodyPtr ); |
|
183 // If there is no body in the message leave with an error |
|
184 if ( bodyPtr.Size() == 0 ) |
|
185 { |
|
186 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: Empty body") |
|
187 User::Leave( KErrCorrupt ); |
|
188 } |
|
189 |
|
190 // Get content type. It will tell us wheather the msg body is encoded or |
|
191 // textual. |
|
192 TPtrC contentType; |
|
193 iMessage->GetContentType( contentType ); |
|
194 PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: HTTP header - Content type <%S>",&contentType); |
|
195 |
|
196 /* |
|
197 TPtrC8 encodingPtr; |
|
198 TBool encodingFound = iMessage->GetHeaderField |
|
199 ( EHttpContentEncoding, encodingPtr ); |
|
200 #ifdef __TEST_LOG__ |
|
201 TBuf<64> encodingBuf; |
|
202 encodingBuf.Copy( encodingPtr ); |
|
203 PUSHLOG_WRITE_FORMAT(" HTTP header - Content encoding <%S>",&encodingBuf); |
|
204 #endif // __TEST_LOG__ |
|
205 */ |
|
206 |
|
207 // Add SI dictionary. |
|
208 NW_WBXML_Dictionary_t* dictArray[ KNoOfDictArrays ] = |
|
209 { (NW_WBXML_Dictionary_t*)&NW_SI_WBXMLDictionary }; |
|
210 |
|
211 NW_Status_t stat = NW_STAT_SUCCESS; |
|
212 |
|
213 RWbxmlDictionary wbxmlDict; |
|
214 wbxmlDict.InitializeL( KNoOfDictArrays, dictArray ); |
|
215 CleanupClosePushL<RWbxmlDictionary>( wbxmlDict ); |
|
216 |
|
217 NW_TinyDom_Handle_t domHandle; |
|
218 NW_Byte* buffer = (NW_Byte*)bodyPtr.Ptr(); |
|
219 NW_Int32 length = (NW_Int32)bodyPtr.Size(); |
|
220 // Let's use the content type now. |
|
221 NW_Bool encoded = ( contentType.CompareF( KSiTextContentType ) == 0 ) ? |
|
222 NW_FALSE : NW_TRUE; |
|
223 // SI public identifier. |
|
224 NW_Uint32 publicID = NW_SI_PublicId; |
|
225 NW_Bool extTNotStringTable = NW_FALSE; |
|
226 NW_DOM_NodeType_t type = 0; |
|
227 /********************************** |
|
228 * Root of DOM |
|
229 ***********************************/ |
|
230 CDocumentTreeOwner* docTreeOwner = new (ELeave) CDocumentTreeOwner; |
|
231 CleanupStack::PushL( docTreeOwner ); |
|
232 NW_DOM_DocumentNode_t* domNode = NW_DOM_DocumentNode_BuildTree |
|
233 ( |
|
234 &domHandle, |
|
235 buffer, |
|
236 length, |
|
237 encoded, |
|
238 publicID, |
|
239 extTNotStringTable |
|
240 ); |
|
241 if (!domNode) |
|
242 { |
|
243 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: domNode is Null") |
|
244 } |
|
245 User::LeaveIfNull( domNode ); |
|
246 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: domNode is not Null") // to be deleted |
|
247 // Let domNode be on the Cleanup Stack. |
|
248 docTreeOwner->SetDocTree( domNode ); |
|
249 |
|
250 // It must be a document node. |
|
251 type = NW_DOM_Node_getNodeType( domNode ); |
|
252 if ( type != NW_DOM_DOCUMENT_NODE ) |
|
253 { |
|
254 PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: Not Document node <%d>",type) |
|
255 User::Leave( KErrArgument ); |
|
256 } |
|
257 |
|
258 // Get character encoding (NW_Uint32) |
|
259 iCharEncoding = NW_DOM_DocumentNode_getCharacterEncoding( domNode ); |
|
260 PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: Doc char encoding <%x>",iCharEncoding) |
|
261 |
|
262 /********************************** |
|
263 * ELEMENT si |
|
264 ***********************************/ |
|
265 // Get the first element of the document that must be an si. |
|
266 // first make sure if there any children in the dom tree, otherwise we will PANIC(in NW_DOM_DocumentNode_getDocumentElement) and crash WatcherMainThread. |
|
267 TBool domNodeHasChildNodes = EFalse; |
|
268 domNodeHasChildNodes = NW_DOM_Node_hasChildNodes( domNode ); |
|
269 PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: check if Dom tree has <SI> node <%d>", domNodeHasChildNodes) |
|
270 if (!domNodeHasChildNodes) |
|
271 { |
|
272 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: No SI element present in the dom tree. Message corrupted.") |
|
273 User::Leave( KErrCorrupt ); |
|
274 } |
|
275 |
|
276 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: before calling getDocumentElement") |
|
277 NW_DOM_ElementNode_t* siElement = |
|
278 NW_DOM_DocumentNode_getDocumentElement( domNode ); |
|
279 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: after calling getDocumentElement") |
|
280 if (!siElement) |
|
281 { |
|
282 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: siElement is Null") |
|
283 } |
|
284 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: siElement is not Null, before leaving") |
|
285 User::LeaveIfNull( siElement ); |
|
286 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: siElement is not Null, after leaving if siElement is null") |
|
287 |
|
288 type = NW_DOM_Node_getNodeType( siElement ); |
|
289 |
|
290 CStringOwner* stringOwner = new (ELeave) CStringOwner; |
|
291 CleanupStack::PushL( stringOwner ); |
|
292 |
|
293 NW_String_t* name = NW_String_new(); |
|
294 User::LeaveIfNull( name ); |
|
295 // Let name be on the Cleanup Stack. |
|
296 stringOwner->SetString( name ); |
|
297 stat = NW_DOM_Node_getNodeName( siElement, name ); |
|
298 User::LeaveIfError( NwxStatusToErrCode( stat ) ); |
|
299 NW_Byte* nameBuf = NW_String_getStorage( name ); |
|
300 NW_Uint16 nameLen = NW_String_getCharCount( name, iCharEncoding ); |
|
301 TPtrC8 namePtr( nameBuf, nameLen ); |
|
302 |
|
303 // Now comes the validity check. |
|
304 if ( type != NW_DOM_ELEMENT_NODE || namePtr.CompareF( KSi ) != 0 ) |
|
305 { |
|
306 PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: Not si element node <%d>",type) |
|
307 User::Leave( KErrArgument ); |
|
308 } |
|
309 |
|
310 CleanupStack::PopAndDestroy( stringOwner ); // stringOwner |
|
311 |
|
312 /********************************** |
|
313 * ELEMENT indication |
|
314 ***********************************/ |
|
315 if ( NW_DOM_Node_hasChildNodes( siElement ) ) |
|
316 { |
|
317 NW_DOM_Node_t* node = NW_DOM_Node_getFirstChild( siElement ); |
|
318 if (!node) |
|
319 { |
|
320 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: no si child nodes!") |
|
321 } |
|
322 User::LeaveIfNull( node ); |
|
323 |
|
324 // Find the indication element. |
|
325 TBool indicationFound = EFalse; |
|
326 do { |
|
327 type = NW_DOM_Node_getNodeType( node ); |
|
328 |
|
329 CStringOwner* stringOwner = new (ELeave) CStringOwner; |
|
330 CleanupStack::PushL( stringOwner ); |
|
331 |
|
332 NW_String_t* name = NW_String_new(); |
|
333 User::LeaveIfNull( name ); |
|
334 stringOwner->SetString( name ); |
|
335 stat = NW_DOM_Node_getNodeName( node, name ); |
|
336 PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: getNodeName ErrCode: %d", NwxStatusToErrCode( stat )) |
|
337 User::LeaveIfError( NwxStatusToErrCode( stat ) ); |
|
338 NW_Byte* nameBuf = NW_String_getStorage( name ); |
|
339 NW_Uint16 nameLen = NW_String_getCharCount( name, |
|
340 iCharEncoding ); |
|
341 TPtrC8 namePtr( nameBuf, nameLen ); |
|
342 |
|
343 if ( type == NW_DOM_ELEMENT_NODE && |
|
344 namePtr.CompareF( KIndication ) == 0 ) |
|
345 { |
|
346 // We found the indication element. Parse it. |
|
347 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: indication under si found.") |
|
348 indicationFound = ETrue; |
|
349 NW_DOM_ElementNode_t* indicationElement = |
|
350 REINTERPRET_CAST( NW_DOM_ElementNode_t*, node ); |
|
351 ParseIndicationL( *indicationElement ); |
|
352 } |
|
353 |
|
354 CleanupStack::PopAndDestroy( stringOwner ); // stringOwner |
|
355 |
|
356 if ( !indicationFound ) |
|
357 { |
|
358 // Iterate next. |
|
359 node = NW_DOM_Node_getNextSibling( node ); |
|
360 if ( !node ) |
|
361 { |
|
362 PUSHLOG_WRITE("CSIContentHandler::ParsePushMsgL: No more sibling.") |
|
363 break; |
|
364 } |
|
365 } |
|
366 |
|
367 } while ( !indicationFound ); |
|
368 } |
|
369 |
|
370 // Cleanup. |
|
371 CleanupStack::PopAndDestroy( 2, &wbxmlDict ); // docTreeOwner, wbxmlDict |
|
372 |
|
373 if ( !ActionFlag() ) |
|
374 { |
|
375 // default if no action explicitly stated |
|
376 iPushMsgAction = CSIPushMsgEntry::ESIPushMsgSignalMedium; |
|
377 SetActionFlag( ETrue ); |
|
378 PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParsePushMsgL: Defaulting to ActionFlag: %d",iPushMsgAction) |
|
379 } |
|
380 |
|
381 iState = EProcessing; |
|
382 IdleComplete(); |
|
383 |
|
384 PUSHLOG_LEAVEFN("CSIContentHandler::ParsePushMsgL") |
|
385 } |
|
386 |
|
387 // --------------------------------------------------------- |
|
388 // CSIContentHandler::ParseIndicationL |
|
389 // --------------------------------------------------------- |
|
390 // |
|
391 void CSIContentHandler::ParseIndicationL( NW_DOM_ElementNode_t& aIndication ) |
|
392 { |
|
393 PUSHLOG_ENTERFN("CSIContentHandler::ParseIndicationL") |
|
394 |
|
395 NW_Status_t stat = NW_STAT_SUCCESS; |
|
396 NW_DOM_NodeType_t type = 0; |
|
397 |
|
398 if ( NW_DOM_ElementNode_hasAttributes( &aIndication ) ) |
|
399 { |
|
400 NW_DOM_AttributeListIterator_t attrIter; |
|
401 stat = NW_DOM_ElementNode_getAttributeListIterator |
|
402 ( &aIndication, &attrIter ); |
|
403 PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParseIndicationL: getAttribListIter ErrCode: %d", NwxStatusToErrCode( stat )) |
|
404 User::LeaveIfError( NwxStatusToErrCode( stat ) ); |
|
405 |
|
406 NW_DOM_AttributeHandle_t attrHandle; |
|
407 while ( NW_DOM_AttributeListIterator_getNextAttribute |
|
408 ( &attrIter, &attrHandle ) == NW_STAT_WBXML_ITERATE_MORE ) |
|
409 { |
|
410 ParseIndAttributeL( attrHandle ); |
|
411 } |
|
412 } |
|
413 |
|
414 /********************************** |
|
415 * PCDATA of ELEMENT indication |
|
416 ***********************************/ |
|
417 if ( NW_DOM_Node_hasChildNodes( &aIndication ) ) |
|
418 { |
|
419 NW_DOM_TextNode_t* textNode = |
|
420 NW_DOM_Node_getFirstChild( &aIndication ); |
|
421 User::LeaveIfNull( textNode ); |
|
422 |
|
423 type = NW_DOM_Node_getNodeType( textNode ); |
|
424 if ( type != NW_DOM_TEXT_NODE ) |
|
425 { |
|
426 PUSHLOG_WRITE_FORMAT("CSIContentHandler::ParseIndicationL: Not text node <%d>",type) |
|
427 User::Leave( KErrArgument ); |
|
428 } |
|
429 |
|
430 ParseTextL( *textNode ); |
|
431 } |
|
432 |
|
433 PUSHLOG_LEAVEFN("CSIContentHandler::ParseIndicationL") |
|
434 } |
|
435 |
|
436 // --------------------------------------------------------- |
|
437 // CSIContentHandler::ParseIndAttributeL |
|
438 // --------------------------------------------------------- |
|
439 // |
|
440 void CSIContentHandler::ParseIndAttributeL( NW_DOM_AttributeHandle_t& |
|
441 aAttrHandle ) |
|
442 { |
|
443 PUSHLOG_ENTERFN("CSIContentHandler::ParseIndAttributeL") |
|
444 |
|
445 NW_Status_t stat = NW_STAT_SUCCESS; |
|
446 |
|
447 CStringOwner* stringOwner = new (ELeave) CStringOwner; |
|
448 CleanupStack::PushL( stringOwner ); |
|
449 |
|
450 NW_String_t* attrName = NW_String_new(); |
|
451 User::LeaveIfNull( attrName ); |
|
452 stringOwner->SetString( attrName ); |
|
453 |
|
454 // Get the name of the attribute. |
|
455 stat = NW_DOM_AttributeHandle_getName( &aAttrHandle, attrName ); |
|
456 User::LeaveIfError( NwxStatusToErrCode( stat ) ); |
|
457 NW_Byte* attrNameBuf = NW_String_getStorage( attrName ); |
|
458 NW_Uint16 attrNameLen = NW_String_getCharCount( attrName, iCharEncoding ); |
|
459 TPtrC8 attrNamePtr( attrNameBuf, attrNameLen ); |
|
460 |
|
461 if ( attrNamePtr.CompareF( KCreatedAttrib ) == 0 ) |
|
462 { |
|
463 if ( CreatedFlag() ) |
|
464 { |
|
465 PUSHLOG_WRITE(" created redefinition") |
|
466 User::Leave( KErrCorrupt ); |
|
467 } |
|
468 else |
|
469 { |
|
470 TBool gotDate = AttributeToTTimeL( aAttrHandle, iCreatedTime ); |
|
471 SetCreatedFlag( gotDate ); |
|
472 PUSHLOG_WRITE_FORMAT(" iCreatedTime set %d",gotDate?1:0) |
|
473 } |
|
474 } |
|
475 else if ( attrNamePtr.CompareF( KHrefAttrib ) == 0 ) |
|
476 { |
|
477 if ( HrefFlag() ) |
|
478 { |
|
479 PUSHLOG_WRITE(" href redefinition") |
|
480 User::Leave( KErrCorrupt ); |
|
481 } |
|
482 else |
|
483 { |
|
484 CStringOwner* stringOwner = new (ELeave) CStringOwner; |
|
485 CleanupStack::PushL( stringOwner ); |
|
486 |
|
487 NW_String_t* val = NW_String_new(); |
|
488 User::LeaveIfNull( val ); |
|
489 stringOwner->SetString( val ); |
|
490 stat = NW_DOM_AttributeHandle_getValue( &aAttrHandle, val ); |
|
491 if ( stat != NW_STAT_DOM_NO_STRING_RETURNED ) |
|
492 { |
|
493 User::LeaveIfError( NwxStatusToErrCode( stat ) ); |
|
494 NW_Byte* storage = NW_String_getStorage( val ); |
|
495 NW_Uint16 length = NW_String_getCharCount( val, |
|
496 iCharEncoding ); |
|
497 if ( length == 0 ) |
|
498 { |
|
499 // Zero length href attribute is considered as missing. |
|
500 PUSHLOG_WRITE(" Zero length HrefFlag"); |
|
501 } |
|
502 else |
|
503 { |
|
504 TPtrC8 hrefPtr( storage, length ); |
|
505 HBufC* tempHrefBuf = HBufC::NewMaxL( length ); |
|
506 // No leavable after it!!! until... |
|
507 tempHrefBuf->Des().Copy( hrefPtr ); |
|
508 iHrefBuf = tempHrefBuf; // ...until here. |
|
509 SetHrefFlag( ETrue ); |
|
510 PUSHLOG_WRITE_FORMAT(" HrefFlag set <%S>",iHrefBuf); |
|
511 } |
|
512 } |
|
513 |
|
514 CleanupStack::PopAndDestroy( stringOwner ); // stringOwner |
|
515 } |
|
516 } |
|
517 else if ( attrNamePtr.CompareF( KExpiresAttrib ) == 0 ) |
|
518 { |
|
519 if ( ExpiresFlag() ) |
|
520 { |
|
521 PUSHLOG_WRITE(" expires redefinition") |
|
522 User::Leave( KErrCorrupt ); |
|
523 } |
|
524 else |
|
525 { |
|
526 TBool gotDate = AttributeToTTimeL( aAttrHandle, iExpiresTime ); |
|
527 SetExpiresFlag( gotDate ); |
|
528 PUSHLOG_WRITE_FORMAT(" iExpiresTime set %d",gotDate?1:0) |
|
529 } |
|
530 } |
|
531 else if ( attrNamePtr.CompareF( KSiIdAttrib ) == 0 ) |
|
532 { |
|
533 if ( SiIdFlag() ) |
|
534 { |
|
535 PUSHLOG_WRITE(" si-id redefinition") |
|
536 User::Leave( KErrCorrupt ); |
|
537 } |
|
538 else |
|
539 { |
|
540 // It is expected to be String. |
|
541 CStringOwner* stringOwner = new (ELeave) CStringOwner; |
|
542 CleanupStack::PushL( stringOwner ); |
|
543 |
|
544 NW_String_t* val = NW_String_new(); |
|
545 User::LeaveIfNull( val ); |
|
546 stringOwner->SetString( val ); |
|
547 stat = NW_DOM_AttributeHandle_getValue( &aAttrHandle, val ); |
|
548 User::LeaveIfError( NwxStatusToErrCode( stat ) ); |
|
549 NW_Byte* storage = NW_String_getStorage( val ); |
|
550 NW_Uint16 length = NW_String_getCharCount( val, iCharEncoding ); |
|
551 TPtrC8 siidPtr( storage, length ); |
|
552 |
|
553 iSiIdBuf = HBufC::NewMaxL( siidPtr.Length() ); |
|
554 iSiIdBuf->Des().Copy( siidPtr ); |
|
555 SetSiIdFlag( ETrue ); |
|
556 PUSHLOG_WRITE_FORMAT(" SiIdFlag set <%S>",iSiIdBuf) |
|
557 |
|
558 CleanupStack::PopAndDestroy( stringOwner ); // stringOwner |
|
559 } |
|
560 } |
|
561 else if ( attrNamePtr.CompareF( KActionAttrib ) == 0 ) |
|
562 { |
|
563 if ( ActionFlag() ) |
|
564 { |
|
565 PUSHLOG_WRITE(" action redefinition") |
|
566 User::Leave( KErrCorrupt ); |
|
567 } |
|
568 else |
|
569 { |
|
570 // It is expected to be String. |
|
571 CStringOwner* stringOwner = new (ELeave) CStringOwner; |
|
572 CleanupStack::PushL( stringOwner ); |
|
573 |
|
574 NW_String_t* val = NW_String_new(); |
|
575 User::LeaveIfNull( val ); |
|
576 stringOwner->SetString( val ); |
|
577 stat = NW_DOM_AttributeHandle_getValue( &aAttrHandle, val ); |
|
578 User::LeaveIfError( NwxStatusToErrCode( stat ) ); |
|
579 NW_Byte* storage = NW_String_getStorage( val ); |
|
580 NW_Uint16 length = NW_String_getCharCount( val, iCharEncoding ); |
|
581 TPtrC8 actionPtr( storage, length ); |
|
582 |
|
583 iPushMsgAction = ConvertActionString( actionPtr ); |
|
584 SetActionFlag( ETrue ); |
|
585 PUSHLOG_WRITE_FORMAT(" ActionFlag: %d",iPushMsgAction) |
|
586 |
|
587 CleanupStack::PopAndDestroy( stringOwner ); // stringOwner |
|
588 } |
|
589 } |
|
590 else |
|
591 { |
|
592 __ASSERT_DEBUG( EFalse, |
|
593 ContHandPanic( EPushContHandPanUnexpSiToken ) ); |
|
594 } |
|
595 |
|
596 CleanupStack::PopAndDestroy( stringOwner ); // stringOwner |
|
597 |
|
598 PUSHLOG_LEAVEFN("CSIContentHandler::ParseIndAttributeL") |
|
599 } |
|
600 |
|
601 // --------------------------------------------------------- |
|
602 // CSIContentHandler::ParseTextL |
|
603 // --------------------------------------------------------- |
|
604 // |
|
605 void CSIContentHandler::ParseTextL( NW_DOM_TextNode_t& aTextNode ) |
|
606 { |
|
607 PUSHLOG_ENTERFN("CSIContentHandler::ParseTextL") |
|
608 |
|
609 if ( DataFlag() ) |
|
610 { |
|
611 PUSHLOG_WRITE(" Data flag already set.") |
|
612 } |
|
613 else |
|
614 { |
|
615 CStringOwner* stringOwner = new (ELeave) CStringOwner; |
|
616 CleanupStack::PushL( stringOwner ); |
|
617 |
|
618 NW_String_t* data = NW_String_new(); |
|
619 User::LeaveIfNull( data ); |
|
620 stringOwner->SetString( data ); |
|
621 NW_Status_t stat = NW_STAT_SUCCESS; |
|
622 stat = NW_DOM_TextNode_getData( &aTextNode, data ); |
|
623 User::LeaveIfError( NwxStatusToErrCode( stat ) ); |
|
624 |
|
625 HBufC16* ucs2buffer = ConvertToUnicodeL( *data, iCharEncoding ); |
|
626 // Be careful: ucs2buffer is not on the CleanupStack! |
|
627 __ASSERT_DEBUG( ucs2buffer != 0, ContHandPanic( EPushContHandPanNullUcs2Buf ) ); |
|
628 |
|
629 TPtrC16 ucs2ptrC( *ucs2buffer ); |
|
630 if ( ucs2ptrC.Length() == 0 ) |
|
631 { |
|
632 // Zero length data is considered as nothing. |
|
633 PUSHLOG_WRITE(" Zero length Data"); |
|
634 } |
|
635 else |
|
636 { |
|
637 PUSHLOG_WRITE_FORMAT(" Data: <%S>",&ucs2ptrC); |
|
638 |
|
639 #ifdef __TEST_LOG__ |
|
640 // Write out each unicode character identifier |
|
641 TInt length = ucs2ptrC.Length(); |
|
642 for (TInt logI=0;logI<length;logI++) |
|
643 { |
|
644 TBuf16<1> currChar; |
|
645 currChar.Copy( ucs2ptrC.Mid( logI, /*aLength*/1 ) ); |
|
646 PUSHLOG_WRITE_FORMAT2(" 0x%x %S",currChar[0],&currChar); |
|
647 } |
|
648 #endif // __TEST_LOG__ |
|
649 |
|
650 iData = ucs2buffer; // Ownership transferred. |
|
651 ucs2buffer = NULL; |
|
652 SetDataFlag( ETrue ); |
|
653 } |
|
654 |
|
655 CleanupStack::PopAndDestroy( stringOwner ); |
|
656 } |
|
657 |
|
658 PUSHLOG_LEAVEFN("CSIContentHandler::ParseTextL") |
|
659 } |
|
660 |
|
661 // --------------------------------------------------------- |
|
662 // CSIContentHandler::ConvertToUnicodeL |
|
663 // --------------------------------------------------------- |
|
664 // |
|
665 HBufC16* CSIContentHandler::ConvertToUnicodeL( const TDesC8& aSrc, TUint aCharSetId ) |
|
666 { |
|
667 PUSHLOG_ENTERFN("CSIContentHandler::ConvertToUnicodeL"); |
|
668 |
|
669 __ASSERT_DEBUG( aCharSetId != 0, ContHandPanic( EPushContHandPanNullCharSetId ) ); |
|
670 |
|
671 InitialiseCharacterSetConverterL(); |
|
672 |
|
673 HBufC16* ucs2buffer = NULL; // The return value. |
|
674 TBool resultOnStack = EFalse; |
|
675 |
|
676 #ifdef __TEST_LOG__ |
|
677 // Write out the original 8-bit buffer |
|
678 TInt origiLength = aSrc.Length(); |
|
679 for (TInt origiLogI=0;origiLogI<origiLength;origiLogI++) |
|
680 { |
|
681 TBuf16<1> currChar; // Only 16-bit buffer can be written out. |
|
682 currChar.Copy( aSrc.Mid( origiLogI, /*aLength*/1 ) ); |
|
683 PUSHLOG_WRITE_FORMAT2(" 0x%x %S",currChar[0],&currChar); |
|
684 } |
|
685 #endif // __TEST_LOG__ |
|
686 |
|
687 // Result |
|
688 HBufC16* buffer = HBufC16::NewLC( KPushConversionBufferSize ); |
|
689 PUSHLOG_WRITE(" buffer allocated"); |
|
690 TPtr16 ptr( buffer->Des() ); |
|
691 |
|
692 // Prepare conversion for the given charset ID. |
|
693 RFs& fs = iMsvSession->FileSession(); |
|
694 iCharacterSetConverter->PrepareToConvertToOrFromL |
|
695 ( aCharSetId, *iCharacterSetsAvailable, fs ); |
|
696 PUSHLOG_WRITE(" PrepareToConvertToOrFromL OK"); |
|
697 |
|
698 TInt state = 0; |
|
699 TInt remaining = iCharacterSetConverter->ConvertToUnicode( ptr, aSrc, state ); |
|
700 PUSHLOG_WRITE_FORMAT(" remaining: %d",remaining); |
|
701 while ( remaining >= 0 ) |
|
702 { |
|
703 if ( ucs2buffer == NULL ) |
|
704 { |
|
705 ucs2buffer = HBufC::NewLC( ptr.Length() ); |
|
706 resultOnStack = ETrue; |
|
707 } |
|
708 else |
|
709 { |
|
710 __ASSERT_DEBUG( resultOnStack, |
|
711 ContHandPanic( EPushContHandPanSiResNotOnStack ) ); |
|
712 // This may change the address of ucs2buffer so we need to put |
|
713 // it on the cleanup stack again!! |
|
714 ucs2buffer = ucs2buffer->ReAllocL |
|
715 ( ucs2buffer->Length() + ptr.Length() ); |
|
716 CleanupStack::Pop(); // old ucs2buffer |
|
717 CleanupStack::PushL( ucs2buffer ); // possibly new copy |
|
718 PUSHLOG_WRITE(" ucs2buffer reallocated"); |
|
719 } |
|
720 TPtr16 ucs2ptr( ucs2buffer->Des() ); |
|
721 ucs2ptr.Append( ptr ); |
|
722 if ( remaining > 0 ) |
|
723 { |
|
724 // Try to convert all remaining characters. |
|
725 ptr.Zero(); |
|
726 remaining = iCharacterSetConverter->ConvertToUnicode |
|
727 ( ptr, aSrc.Right( remaining ), state ); |
|
728 PUSHLOG_WRITE_FORMAT(" remaining: %d",remaining); |
|
729 } |
|
730 else |
|
731 { |
|
732 PUSHLOG_WRITE(" break"); |
|
733 break; |
|
734 } |
|
735 } |
|
736 |
|
737 if ( resultOnStack ) |
|
738 { |
|
739 CleanupStack::Pop(); // ucs2buffer |
|
740 resultOnStack = EFalse; |
|
741 } |
|
742 |
|
743 // ucs2buffer is not on the CleanupStack! |
|
744 |
|
745 CleanupStack::PopAndDestroy( buffer ); // buffer |
|
746 |
|
747 if ( ucs2buffer == NULL ) |
|
748 { |
|
749 PUSHLOG_WRITE(" NULL ucs2buffer - allocating an empty buf"); |
|
750 ucs2buffer = KNullDesC().AllocL(); |
|
751 } |
|
752 else |
|
753 { |
|
754 // Check if first character is a Zero-width nbsp. |
|
755 TPtrC16 ucs2ptrC( *ucs2buffer ); |
|
756 if ( ucs2ptrC.Length() >= 1 && ucs2ptrC[0] == KPushZeroWidthNbsp ) |
|
757 { |
|
758 // First character is a Zero-width NBSP. This character is used as |
|
759 // BOM in some encodings and should not be present at this point. |
|
760 // But we are tolerant and remove it. |
|
761 // (Not expecting big-endianness here.) |
|
762 HBufC16* temp = ucs2buffer; |
|
763 CleanupStack::PushL( temp ); |
|
764 ucs2buffer = ucs2ptrC.Mid( 1 ).AllocL(); |
|
765 CleanupStack::PopAndDestroy( temp ); // temp |
|
766 PUSHLOG_WRITE(" BOM removed"); |
|
767 } |
|
768 else |
|
769 { |
|
770 PUSHLOG_WRITE(" No BOM"); |
|
771 } |
|
772 } |
|
773 |
|
774 |
|
775 PUSHLOG_LEAVEFN("CSIContentHandler::ConvertToUnicodeL"); |
|
776 return ucs2buffer; |
|
777 } |
|
778 |
|
779 // --------------------------------------------------------- |
|
780 // CSIContentHandler::ConvertToUnicodeL |
|
781 // --------------------------------------------------------- |
|
782 // |
|
783 HBufC16* CSIContentHandler::ConvertToUnicodeL |
|
784 ( NW_String_t& aString, NW_Uint32 aCharEncoding ) |
|
785 { |
|
786 PUSHLOG_ENTERFN("CSIContentHandler::ConvertToUnicodeL"); |
|
787 |
|
788 /* As cXmlLibrary does, we support only the following charsets: |
|
789 #define HTTP_iso_10646_ucs_2 0x03E8 |
|
790 #define HTTP_iso_8859_1 0x04 |
|
791 #define HTTP_us_ascii 0x03 |
|
792 #define HTTP_utf_8 0x6A |
|
793 #define HTTP_utf_16 1015 |
|
794 */ |
|
795 TUint id = 0; |
|
796 if ( aCharEncoding == HTTP_iso_10646_ucs_2 ) |
|
797 { |
|
798 id = KCharacterSetIdentifierUcs2; |
|
799 PUSHLOG_WRITE(" KCharacterSetIdentifierUcs2") |
|
800 } |
|
801 else if ( aCharEncoding == HTTP_iso_8859_1 ) |
|
802 { |
|
803 id = KCharacterSetIdentifierIso88591; |
|
804 PUSHLOG_WRITE(" KCharacterSetIdentifierIso88591") |
|
805 } |
|
806 else if ( aCharEncoding == HTTP_us_ascii ) |
|
807 { |
|
808 id = KCharacterSetIdentifierAscii; |
|
809 PUSHLOG_WRITE(" KCharacterSetIdentifierAscii") |
|
810 } |
|
811 else if ( aCharEncoding == HTTP_utf_8 ) |
|
812 { |
|
813 id = KCharacterSetIdentifierUtf8; |
|
814 PUSHLOG_WRITE(" KCharacterSetIdentifierUtf8") |
|
815 } |
|
816 else if ( aCharEncoding == HTTP_utf_16 ) // No such in CharConv.h |
|
817 { |
|
818 id = KCharacterSetIdentifierUcs2; |
|
819 PUSHLOG_WRITE(" KCharacterSetIdentifierUcs2") |
|
820 } |
|
821 else |
|
822 { |
|
823 id = KCharacterSetIdentifierUtf8; // Defaulting to UTF-8 |
|
824 PUSHLOG_WRITE(" DEFAULTING to KCharacterSetIdentifierUtf8"); |
|
825 } |
|
826 |
|
827 PUSHLOG_WRITE_FORMAT(" id: 0x%x",id); |
|
828 __ASSERT_DEBUG( id != 0, ContHandPanic( EPushContHandPanNullCharSetId ) ); |
|
829 |
|
830 // Source |
|
831 PUSHLOG_WRITE_FORMAT(" Storage: 0x%x",NW_String_getStorage(&aString)); |
|
832 PUSHLOG_WRITE_FORMAT(" Byte count: %d",NW_String_getByteCount(&aString)-1); |
|
833 |
|
834 // We will use NW_String_getByteCount(&aString)-1 as size, because |
|
835 // NW_String_getByteCount(&aString) includes NULL terminator. |
|
836 const TPtrC8 src( NW_String_getStorage(&aString), |
|
837 NW_String_getByteCount(&aString)-1 ); |
|
838 HBufC16* ucs2buffer = ConvertToUnicodeL( src, id ); |
|
839 |
|
840 PUSHLOG_LEAVEFN("CSIContentHandler::ConvertToUnicodeL"); |
|
841 return ucs2buffer; |
|
842 } |
|
843 |
|
844 // --------------------------------------------------------- |
|
845 // CSIContentHandler::InitialiseCharacterSetConverterL |
|
846 // --------------------------------------------------------- |
|
847 // |
|
848 void CSIContentHandler::InitialiseCharacterSetConverterL() |
|
849 { |
|
850 PUSHLOG_ENTERFN("CSIContentHandler::InitialiseCharacterSetConverterL") |
|
851 |
|
852 iCharacterSetConverter = CCnvCharacterSetConverter::NewL(); |
|
853 |
|
854 RFs& fs = iMsvSession->FileSession(); |
|
855 iCharacterSetsAvailable = |
|
856 CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL( fs ); |
|
857 |
|
858 PUSHLOG_LEAVEFN("CSIContentHandler::InitialiseCharacterSetConverterL") |
|
859 } |
|
860 |
|
861 // --------------------------------------------------------- |
|
862 // CSIContentHandler::ConvertActionString |
|
863 // --------------------------------------------------------- |
|
864 // |
|
865 TUint CSIContentHandler::ConvertActionString |
|
866 ( const TDesC8& aActionString ) const |
|
867 { |
|
868 const TInt KMatchFound = 0; |
|
869 |
|
870 // set to default signal value (to rid ourselves of build warning) |
|
871 TUint actionValue = CSIPushMsgEntry::ESIPushMsgSignalMedium; |
|
872 |
|
873 if ( aActionString.Compare( KDeleteAction ) == KMatchFound ) |
|
874 { |
|
875 actionValue = CSIPushMsgEntry::ESIPushMsgDelete; |
|
876 } |
|
877 else if ( aActionString.Compare( KSignalNone ) == KMatchFound ) |
|
878 { |
|
879 actionValue = CSIPushMsgEntry::ESIPushMsgSignalNone; |
|
880 } |
|
881 else if ( aActionString.Compare( KSignalLow ) == KMatchFound ) |
|
882 { |
|
883 actionValue = CSIPushMsgEntry::ESIPushMsgSignalLow; |
|
884 } |
|
885 else if ( aActionString.Compare( KSignalMedium ) == KMatchFound ) |
|
886 { |
|
887 actionValue = CSIPushMsgEntry::ESIPushMsgSignalMedium; |
|
888 } |
|
889 else if ( aActionString.Compare( KSignalHigh ) == KMatchFound ) |
|
890 { |
|
891 actionValue = CSIPushMsgEntry::ESIPushMsgSignalHigh; |
|
892 } |
|
893 |
|
894 return actionValue; |
|
895 } |
|
896 |
|
897 // --------------------------------------------------------- |
|
898 // CSIContentHandler::SetSIPushMsgEntryFieldsL |
|
899 // --------------------------------------------------------- |
|
900 // |
|
901 void CSIContentHandler::SetSIPushMsgEntryFieldsL( CSIPushMsgEntry& |
|
902 aSIPushMsgEntry ) |
|
903 { |
|
904 PUSHLOG_ENTERFN("CSIContentHandler::SetSIPushMsgEntryFieldsL") |
|
905 |
|
906 if ( SiIdFlag() || HrefFlag() ) |
|
907 { |
|
908 if ( SiIdFlag() && ( HrefFlag() == EFalse ) ) |
|
909 { |
|
910 // Message has only si-id but no href. |
|
911 aSIPushMsgEntry.SetIdL( *iSiIdBuf ); |
|
912 } |
|
913 else if ( HrefFlag() && ( SiIdFlag() == EFalse ) ) |
|
914 { |
|
915 // If message has no si-id but does have a href, use href as si-id. |
|
916 aSIPushMsgEntry.SetIdL( *iHrefBuf ); |
|
917 aSIPushMsgEntry.SetUrlL( *iHrefBuf ); |
|
918 } |
|
919 else |
|
920 { |
|
921 // Use si-id and href as is. |
|
922 aSIPushMsgEntry.SetIdL( *iSiIdBuf ); |
|
923 aSIPushMsgEntry.SetUrlL( *iHrefBuf ); |
|
924 } |
|
925 } |
|
926 |
|
927 __ASSERT_DEBUG( ActionFlag(), |
|
928 ContHandPanic( EPushContHandPanUnspecSiAction ) ); |
|
929 if ( ActionFlag() ) |
|
930 { |
|
931 aSIPushMsgEntry.SetAction( iPushMsgAction ); |
|
932 } |
|
933 else // default if no action explicitly stated |
|
934 { |
|
935 aSIPushMsgEntry.SetAction( CSIPushMsgEntry::ESIPushMsgSignalMedium ); |
|
936 } |
|
937 |
|
938 // uses default null time value if no explicit date set in message |
|
939 aSIPushMsgEntry.SetCreated( iCreatedTime ); |
|
940 aSIPushMsgEntry.SetExpires( iExpiresTime ); |
|
941 |
|
942 // PCDATA (text) from message |
|
943 if ( DataFlag() ) |
|
944 { |
|
945 aSIPushMsgEntry.SetTextL( *iData ); |
|
946 } |
|
947 |
|
948 TPtrC8 msgHeaderPtr; |
|
949 iMessage->GetHeader( msgHeaderPtr ); |
|
950 aSIPushMsgEntry.SetHeaderL( msgHeaderPtr ); |
|
951 |
|
952 // Get server address. |
|
953 TPtrC8 srvAddress; |
|
954 if ( iMessage->GetServerAddress( srvAddress ) ) |
|
955 { |
|
956 aSIPushMsgEntry.SetFromL( srvAddress ); |
|
957 } |
|
958 |
|
959 // First line in Inbox: TMsvEntry::iDetails. |
|
960 if ( srvAddress.Length() == 0 ) |
|
961 { |
|
962 // Read from resource. |
|
963 HBufC* details = |
|
964 iStrRscReader->AllocReadResourceLC( R_PUSHMISC_UNK_SENDER ); |
|
965 aSIPushMsgEntry.SetMsgDetailsL( *details ); |
|
966 CleanupStack::PopAndDestroy( details ); |
|
967 } |
|
968 else |
|
969 { |
|
970 // Convert the "From" information to the format required by the UI |
|
971 // spec and then decode it. |
|
972 HBufC* details = iWapPushUtils->ConvertDetailsL( srvAddress ); |
|
973 CleanupStack::PushL( details ); |
|
974 HBufC* convertedFrom = |
|
975 CPushMtmUtil::ConvertUriToDisplayFormL( *details ); |
|
976 CleanupStack::PushL( convertedFrom ); |
|
977 // |
|
978 aSIPushMsgEntry.SetMsgDetailsL( *convertedFrom ); |
|
979 // |
|
980 CleanupStack::PopAndDestroy( 2, details ); // convertedFrom, details |
|
981 } |
|
982 |
|
983 // Second line in Inbox: TMsvEntry::iDescription. |
|
984 if ( DataFlag() ) |
|
985 { |
|
986 // Display SI message. |
|
987 aSIPushMsgEntry.SetMsgDescriptionL( *iData ); |
|
988 } |
|
989 else |
|
990 { |
|
991 // Display URL. |
|
992 __ASSERT_DEBUG( HrefFlag(), |
|
993 ContHandPanic( EPushContHandPanUnspecSiHref ) ); |
|
994 const TPtrC url = aSIPushMsgEntry.Url(); |
|
995 HBufC* convertedUrl = CPushMtmUtil::ConvertUriToDisplayFormL( url ); |
|
996 CleanupStack::PushL( convertedUrl ); |
|
997 // |
|
998 aSIPushMsgEntry.SetMsgDescriptionL( *convertedUrl ); |
|
999 // |
|
1000 CleanupStack::PopAndDestroy( convertedUrl ); // convertedUrl |
|
1001 } |
|
1002 |
|
1003 // ******** Push MTM specific processing ********* |
|
1004 |
|
1005 /* |
|
1006 * Unfortunately in CPushMsgEntryBase there is no such functionality |
|
1007 * with which we can reach TMsvEntry as non-const, but we have to |
|
1008 * modify the entry's iMtmData2 member somehow. We can do it |
|
1009 * with either casting or with modifying and saving the entry |
|
1010 * manually after it has been saved by CSIPushMsgEntry. The latter |
|
1011 * solution is more expensive so we choose the first. |
|
1012 */ |
|
1013 TMsvEntry& tEntry = CONST_CAST( TMsvEntry&, aSIPushMsgEntry.Entry() ); |
|
1014 if ( HrefFlag() ) |
|
1015 { |
|
1016 CPushMtmUtil::SetAttrs( tEntry, EPushMtmAttrHasHref ); |
|
1017 } |
|
1018 else |
|
1019 { |
|
1020 CPushMtmUtil::ResetAttrs( tEntry, EPushMtmAttrHasHref ); |
|
1021 } |
|
1022 |
|
1023 // *** Set the entry to unread and new state. *** |
|
1024 |
|
1025 tEntry.SetNew( ETrue ); |
|
1026 tEntry.SetUnread( ETrue ); |
|
1027 |
|
1028 PUSHLOG_LEAVEFN("CSIContentHandler::SetSIPushMsgEntryFieldsL") |
|
1029 } |
|
1030 |
|
1031 // --------------------------------------------------------- |
|
1032 // CSIContentHandler::ProcessingPushMsgEntryL |
|
1033 // --------------------------------------------------------- |
|
1034 // |
|
1035 void CSIContentHandler::ProcessingPushMsgEntryL() |
|
1036 { |
|
1037 PUSHLOG_ENTERFN("CSIContentHandler::ProcessingPushMsgEntryL") |
|
1038 |
|
1039 TBool deletePushMsg( EFalse ); |
|
1040 |
|
1041 __ASSERT_DEBUG( ActionFlag(), |
|
1042 ContHandPanic( EPushContHandPanUnspecSiAction ) ); |
|
1043 |
|
1044 // S60 requirement: if both the href and the message is empty then |
|
1045 // delete the msg. |
|
1046 if ( HrefFlag() == EFalse && DataFlag() == EFalse ) |
|
1047 { |
|
1048 deletePushMsg = ETrue; |
|
1049 } |
|
1050 |
|
1051 // Expiration. |
|
1052 if ( !deletePushMsg && ExpiresFlag() ) |
|
1053 { |
|
1054 TTime today; |
|
1055 today.UniversalTime(); |
|
1056 #ifdef __TEST_LOG__ |
|
1057 _LIT( KDateFormat, "%E%D%X%N%Y %1 %2 %3" ); |
|
1058 _LIT( KTimeFormat, "%-B%:0%J%:1%T%:2%S%:3%+B" ); |
|
1059 TBuf<32> dateHolder; |
|
1060 TBuf<32> timeHolder; |
|
1061 today.FormatL( dateHolder, KDateFormat ); |
|
1062 today.FormatL( timeHolder, KTimeFormat ); |
|
1063 PUSHLOG_WRITE_FORMAT(" now date: <%S>",&dateHolder) |
|
1064 PUSHLOG_WRITE_FORMAT(" now time: <%S>",&timeHolder) |
|
1065 iExpiresTime.FormatL( dateHolder, KDateFormat ); |
|
1066 iExpiresTime.FormatL( timeHolder, KTimeFormat ); |
|
1067 PUSHLOG_WRITE_FORMAT(" exp date: <%S>",&dateHolder) |
|
1068 PUSHLOG_WRITE_FORMAT(" exp time: <%S>",&timeHolder) |
|
1069 #endif // __TEST_LOG__ |
|
1070 // check if message has expiry date before today's date |
|
1071 if ( iExpiresTime < today ) |
|
1072 { |
|
1073 PUSHLOG_WRITE("CSIContentHandler already expired") |
|
1074 deletePushMsg = ETrue; |
|
1075 } |
|
1076 } |
|
1077 |
|
1078 // An SI with the action attribute set to “delete” MUST have an |
|
1079 // explicitly assigned value for si-id. |
|
1080 if ( !deletePushMsg && ActionFlag() ) |
|
1081 { |
|
1082 if ( iPushMsgAction == CSIPushMsgEntry::ESIPushMsgDelete ) |
|
1083 { |
|
1084 if ( !SiIdFlag() || ( SiIdFlag() && iSiIdBuf->Length() == 0 ) ) |
|
1085 { |
|
1086 deletePushMsg = ETrue; |
|
1087 } |
|
1088 } |
|
1089 } |
|
1090 |
|
1091 // Handling out of order delivery & Replacement. |
|
1092 TMsvId matchingEntryId = KMsvNullIndexEntryId; |
|
1093 |
|
1094 if ( !deletePushMsg && ( SiIdFlag() || HrefFlag() ) && CreatedFlag() ) |
|
1095 { |
|
1096 deletePushMsg = HandleMsgOrderReceptionL( matchingEntryId ); |
|
1097 } |
|
1098 |
|
1099 if ( !deletePushMsg && ActionFlag() ) |
|
1100 { |
|
1101 // SI with action=signal-none must not be presented to the end-user. |
|
1102 // Note. In S60 signal-none behaves the same as delete: the |
|
1103 // message is discarded after processing it! |
|
1104 if ( iPushMsgAction == CSIPushMsgEntry::ESIPushMsgSignalNone ) |
|
1105 { |
|
1106 deletePushMsg = ETrue; |
|
1107 } |
|
1108 // SI with action=delete must also be discarded. |
|
1109 else if ( iPushMsgAction == CSIPushMsgEntry::ESIPushMsgDelete ) |
|
1110 { |
|
1111 deletePushMsg = ETrue; |
|
1112 } |
|
1113 } |
|
1114 |
|
1115 // Store message if not marked for deletion. |
|
1116 if ( !deletePushMsg ) |
|
1117 { |
|
1118 StoreSIMessageL( matchingEntryId ); |
|
1119 } |
|
1120 else |
|
1121 { |
|
1122 // The new entry must be discarded. |
|
1123 // Delete the corresponding matching entry, too. |
|
1124 if ( matchingEntryId != KMsvNullIndexEntryId ) |
|
1125 { |
|
1126 iWapPushUtils->DeleteEntryL( matchingEntryId ); |
|
1127 } |
|
1128 } |
|
1129 |
|
1130 iState = EDone; |
|
1131 IdleComplete(); |
|
1132 |
|
1133 PUSHLOG_LEAVEFN("CSIContentHandler::ProcessingPushMsgEntryL") |
|
1134 } |
|
1135 |
|
1136 // --------------------------------------------------------- |
|
1137 // CSIContentHandler::StoreSIMessageL |
|
1138 // --------------------------------------------------------- |
|
1139 // |
|
1140 void CSIContentHandler::StoreSIMessageL( TMsvId aMatchingEntryId ) |
|
1141 { |
|
1142 PUSHLOG_ENTERFN("CSIContentHandler::StoreSIMessageL") |
|
1143 |
|
1144 CSIPushMsgEntry* siEntry = CSIPushMsgEntry::NewL(); |
|
1145 CleanupStack::PushL( siEntry ); |
|
1146 |
|
1147 if ( aMatchingEntryId != KMsvNullIndexEntryId ) |
|
1148 { |
|
1149 PUSHLOG_WRITE("Matching SI found"); |
|
1150 //Delete this old entry |
|
1151 iWapPushUtils->DeleteEntryL( aMatchingEntryId ); |
|
1152 } |
|
1153 |
|
1154 SetSIPushMsgEntryFieldsL( *siEntry ); |
|
1155 iSavedMsgId = siEntry->SaveL( *iMsvSession, KMsvGlobalInBoxIndexEntryId ); |
|
1156 |
|
1157 #ifdef __TEST_LOG__ |
|
1158 _LIT( KDateFormat, "%E%D%X%N%Y %1 %2 %3" ); |
|
1159 _LIT( KTimeFormat, "%-B%:0%J%:1%T%:2%S%:3%+B" ); |
|
1160 TBuf<32> dateHolder; |
|
1161 TBuf<32> timeHolder; |
|
1162 TTime recDateTime = siEntry->ReceivedDate(); |
|
1163 recDateTime.FormatL( dateHolder, KDateFormat ); |
|
1164 recDateTime.FormatL( timeHolder, KTimeFormat ); |
|
1165 PUSHLOG_WRITE_FORMAT(" rec date: <%S>",&dateHolder) |
|
1166 PUSHLOG_WRITE_FORMAT(" rec time: <%S>",&timeHolder) |
|
1167 #endif // __TEST_LOG__ |
|
1168 |
|
1169 CleanupStack::PopAndDestroy( siEntry ); // siEntry |
|
1170 |
|
1171 PUSHLOG_LEAVEFN("CSIContentHandler::StoreSIMessageL") |
|
1172 } |
|
1173 |
|
1174 // --------------------------------------------------------- |
|
1175 // CSIContentHandler::HandleMsgOrderReceptionL |
|
1176 // --------------------------------------------------------- |
|
1177 // |
|
1178 TBool CSIContentHandler::HandleMsgOrderReceptionL( TMsvId& aMatchingEntryId ) |
|
1179 { |
|
1180 PUSHLOG_ENTERFN("CSIContentHandler::HandleMsgOrderReceptionL") |
|
1181 |
|
1182 __ASSERT_DEBUG( ( SiIdFlag() || HrefFlag() ), |
|
1183 ContHandPanic( EPushContHandPanNoSiIdOrHrefAttr ) ); |
|
1184 __ASSERT_DEBUG( CreatedFlag(), |
|
1185 ContHandPanic( EPushContHandPanNoCreatedAttr ) ); |
|
1186 |
|
1187 CMsvEntrySelection* matchingIdList = NULL; |
|
1188 TBool discardPushMsg( EFalse ); |
|
1189 |
|
1190 // Get list of matching stored SI messages. |
|
1191 if ( SiIdFlag() && iSiIdBuf->Length() != 0 ) |
|
1192 { |
|
1193 matchingIdList = iWapPushUtils->FindSiIdLC( *iSiIdBuf ); |
|
1194 } |
|
1195 else // HrefFlag() |
|
1196 { |
|
1197 // Use href as si-id. |
|
1198 matchingIdList = iWapPushUtils->FindSiIdLC( *iHrefBuf ); |
|
1199 } |
|
1200 const TInt matchingListCount( matchingIdList->Count() ); |
|
1201 // Note that the count can be greater than 1. |
|
1202 |
|
1203 PUSHLOG_WRITE_FORMAT("CSIContentHandler Count: %d",matchingListCount) |
|
1204 |
|
1205 if ( 0 < matchingListCount && CreatedFlag() ) |
|
1206 { |
|
1207 CSIPushMsgEntry* siEntry = CSIPushMsgEntry::NewL(); |
|
1208 CleanupStack::PushL( siEntry ); |
|
1209 |
|
1210 // Delete older stored messages and/or mark current message for |
|
1211 // deletion if same date or older than stored messages |
|
1212 TBool foundOneToBeReplaced = EFalse; |
|
1213 for ( TInt count = 0; count < matchingListCount; ++count ) |
|
1214 { |
|
1215 TMsvId matchingSiMsgEntryId( matchingIdList->At(count) ); |
|
1216 |
|
1217 siEntry->RetrieveL( *iMsvSession, matchingSiMsgEntryId ); |
|
1218 |
|
1219 // Skip date comparisons if creation date not valid - |
|
1220 // SI without created attribute never gets replaced. |
|
1221 TTime existingSiCreatedTime( siEntry->Created() ); |
|
1222 |
|
1223 if ( existingSiCreatedTime == Time::NullTTime() ) |
|
1224 { |
|
1225 // continue; |
|
1226 } |
|
1227 else |
|
1228 { |
|
1229 __ASSERT_DEBUG( !foundOneToBeReplaced, |
|
1230 ContHandPanic( EPushContHandPanTooManySi ) ); |
|
1231 if ( foundOneToBeReplaced ) |
|
1232 { |
|
1233 PUSHLOG_WRITE(" Already found one") |
|
1234 // Only one SI has to be found. |
|
1235 // If the program runs into it, then make a |
|
1236 // garbage collection to ensure consistency and |
|
1237 // remove other messages found. |
|
1238 iWapPushUtils->DeleteEntryL( matchingSiMsgEntryId ); |
|
1239 // After the 'for' only one SI is allowed that has created |
|
1240 // attribute. |
|
1241 } |
|
1242 else |
|
1243 { |
|
1244 foundOneToBeReplaced = ETrue; // A match was found. |
|
1245 // Check if received SI is newer than existing stored Si |
|
1246 // (out of order). |
|
1247 if ( iCreatedTime > existingSiCreatedTime ) |
|
1248 { |
|
1249 PUSHLOG_WRITE(" Replacing...") |
|
1250 // The new SI replaces the existing. |
|
1251 aMatchingEntryId = matchingSiMsgEntryId; |
|
1252 discardPushMsg = EFalse; |
|
1253 } |
|
1254 else if ( iCreatedTime <= existingSiCreatedTime ) |
|
1255 { |
|
1256 PUSHLOG_WRITE(" Discarding...") |
|
1257 // Received SI is older than existing stored Si. |
|
1258 discardPushMsg = ETrue; |
|
1259 } |
|
1260 } |
|
1261 } |
|
1262 } |
|
1263 |
|
1264 CleanupStack::PopAndDestroy( siEntry ); // siEntry |
|
1265 } |
|
1266 |
|
1267 CleanupStack::PopAndDestroy( matchingIdList ); // matchingIdList |
|
1268 |
|
1269 PUSHLOG_LEAVEFN("CSIContentHandler::HandleMsgOrderReceptionL") |
|
1270 return discardPushMsg; |
|
1271 } |
|
1272 |
|
1273 // --------------------------------------------------------- |
|
1274 // CSIContentHandler::ConvertDateTimeL |
|
1275 // --------------------------------------------------------- |
|
1276 // |
|
1277 TBool CSIContentHandler::ConvertDateTimeL( const TDesC& aDateTime, |
|
1278 TTime& aConvertedDate ) const |
|
1279 { |
|
1280 PUSHLOG_ENTERFN("CSIContentHandler::ConvertDateTimeL") |
|
1281 |
|
1282 TTime convertedTime = Time::NullTTime(); |
|
1283 TBool convertedOK = EFalse; |
|
1284 |
|
1285 // check supplied descriptor is the correct length |
|
1286 if ( aDateTime.Length() != KValidUTCLength ) |
|
1287 { |
|
1288 PUSHLOG_WRITE_FORMAT(" invalid UTC length <%d>",aDateTime.Length()) |
|
1289 User::Leave( KErrCorrupt ); |
|
1290 } |
|
1291 else |
|
1292 { |
|
1293 TBuf<KValidUTCLength> str = aDateTime; |
|
1294 PUSHLOG_WRITE_FORMAT(" datetime str: <%S>",&str) |
|
1295 if ( !IsValidUTCTime( str ) ) |
|
1296 { |
|
1297 // The UTC time is invalid. |
|
1298 PUSHLOG_WRITE(" invalid UTC time") |
|
1299 User::Leave( KErrCorrupt ); |
|
1300 } |
|
1301 else |
|
1302 { |
|
1303 // Now 'str' is in format YYYYMMDD:HHMMSS |
|
1304 // Adjust UTC time to zero offset TTime. Only month and day |
|
1305 // is effected. |
|
1306 const TInt KFirstMonthChar = KValidTTimeMonthStart; |
|
1307 const TInt KSecondMonthChar = KFirstMonthChar + 1; |
|
1308 const TInt KFirstDayChar = KValidTTimeDayStart; |
|
1309 const TInt KSecondDayChar = KFirstDayChar + 1; |
|
1310 // Month. |
|
1311 // check for special case of month = 10 which becomes 09 |
|
1312 if ( str[KFirstMonthChar] == '1' && str[KSecondMonthChar] == '0' ) |
|
1313 { |
|
1314 str[KFirstMonthChar] = '0'; |
|
1315 str[KSecondMonthChar] = '9'; |
|
1316 } |
|
1317 else |
|
1318 { |
|
1319 // month value is either 11, 12 or less than 10, ie 1 - 9. |
|
1320 // reduce day by one, eg 11 becomes 10, 12 becomes 11, 09 becomes 08 |
|
1321 str[KSecondMonthChar]--; |
|
1322 } |
|
1323 |
|
1324 // Day. |
|
1325 // check for special cases 10, 20, 30 |
|
1326 if ( str[KSecondDayChar] == '0' ) |
|
1327 { |
|
1328 // reduce day by 1, ie 10 becomes 09, 20 becomes 19 ... |
|
1329 str[KSecondDayChar] = '9'; |
|
1330 str[KFirstDayChar]--; |
|
1331 } |
|
1332 else |
|
1333 { |
|
1334 // day value is between 1 and 9 so reduce day by one |
|
1335 // eg 29 becomes 28, 11 bcomes 10, 31 becomes 30 |
|
1336 str[KSecondDayChar]--; |
|
1337 } |
|
1338 |
|
1339 // string is now syntaxically correct, but Set() will return an |
|
1340 // error if it's semantically incorrect. |
|
1341 User::LeaveIfError( convertedTime.Set( str ) ); |
|
1342 convertedOK = ETrue; |
|
1343 } |
|
1344 } |
|
1345 |
|
1346 PUSHLOG_LEAVEFN("CSIContentHandler::ConvertDateTimeL") |
|
1347 aConvertedDate = convertedTime; |
|
1348 return convertedOK; |
|
1349 } |
|
1350 |
|
1351 // --------------------------------------------------------- |
|
1352 // CSIContentHandler::ConvertOpaqueToUtcL |
|
1353 // --------------------------------------------------------- |
|
1354 // |
|
1355 HBufC* CSIContentHandler::ConvertOpaqueToUtcL( const TDesC8& aOpaque ) const |
|
1356 { |
|
1357 PUSHLOG_ENTERFN("CSIContentHandler::ConvertOpaqueToUtcL") |
|
1358 |
|
1359 const TInt opaqueSize = aOpaque.Size(); |
|
1360 if ( KValidMaxEncodedDateTimeSize < opaqueSize ) |
|
1361 { |
|
1362 PUSHLOG_WRITE_FORMAT(" Bad OPAQUE size: <%d>",opaqueSize) |
|
1363 User::Leave( KErrCorrupt ); |
|
1364 } |
|
1365 |
|
1366 HBufC* converted = HBufC::NewMaxLC( KValidUTCLength ); |
|
1367 TPtr convertedPtr = converted->Des(); |
|
1368 convertedPtr.SetLength( 0 ); // Reset. |
|
1369 |
|
1370 // Split up each opaque byte to two bytes. |
|
1371 TUint8 byte( 0x00 ); |
|
1372 TUint8 high( 0x00 ); |
|
1373 TUint8 low( 0x00 ); |
|
1374 TInt i = 0; |
|
1375 for ( i = 0; i < opaqueSize; ++i ) |
|
1376 { |
|
1377 byte = aOpaque[i]; |
|
1378 high = (TUint8)( (byte & 0xF0) >> 4 ); |
|
1379 low = (TUint8)( byte & 0x0F ); |
|
1380 // Check high and low if they are in the range [0-9]. |
|
1381 if ( 9 < high || 9 < low ) |
|
1382 { |
|
1383 PUSHLOG_WRITE_FORMAT2(" Overflow: <%d, %d>",high,low) |
|
1384 User::Leave( KErrOverflow ); |
|
1385 } |
|
1386 convertedPtr.Append( TChar(KAsciiZeroCharCode + high) ); |
|
1387 convertedPtr.Append( TChar(KAsciiZeroCharCode + low) ); |
|
1388 } |
|
1389 |
|
1390 // A valid UTC %Datetime contains 14 numerical characters and 6 |
|
1391 // non-numerical: “1999-04-30T06:40:00Z”. |
|
1392 // So fill the remaining bytes with zeros. |
|
1393 for ( i = convertedPtr.Length(); i < KValidUTCNumericals; ++i ) |
|
1394 { |
|
1395 convertedPtr.Append( TChar('0') ); |
|
1396 } |
|
1397 |
|
1398 // Insert the necessary non-numerical boundary characters. |
|
1399 i = 0; |
|
1400 // Skip year and insert '-'. (Don't forget to increase i with 1 each time!) |
|
1401 i += KValidUTCYearBlockLength; |
|
1402 convertedPtr.Insert( i++, KCharMinus ); |
|
1403 // Skip month and insert '-'. |
|
1404 i += KValidUTCOtherBlockLength; |
|
1405 convertedPtr.Insert( i++, KCharMinus ); |
|
1406 // Skip day and insert 'T'. |
|
1407 i += KValidUTCOtherBlockLength; |
|
1408 convertedPtr.Insert( i++, KCharT ); |
|
1409 // Skip hour and insert ':'. |
|
1410 i += KValidUTCOtherBlockLength; |
|
1411 convertedPtr.Insert( i++, KCharColon ); |
|
1412 // Skip minute and insert ':'. |
|
1413 i += KValidUTCOtherBlockLength; |
|
1414 convertedPtr.Insert( i++, KCharColon ); |
|
1415 // Skip second and insert 'Z'. |
|
1416 i += KValidUTCOtherBlockLength; |
|
1417 convertedPtr.Insert( i++, KCharZ ); |
|
1418 |
|
1419 CleanupStack::Pop( converted ); // converted |
|
1420 PUSHLOG_LEAVEFN("CSIContentHandler::ConvertOpaqueToUtcL") |
|
1421 return converted; |
|
1422 } |
|
1423 |
|
1424 // --------------------------------------------------------- |
|
1425 // CSIContentHandler::IsValidUTCTime |
|
1426 // --------------------------------------------------------- |
|
1427 // |
|
1428 TBool CSIContentHandler::IsValidUTCTime( TDes& aDateTime ) const |
|
1429 { |
|
1430 PUSHLOG_ENTERFN("CSIContentHandler::IsValidUTCTime") |
|
1431 |
|
1432 TBool isValid( ETrue ); // Return value. |
|
1433 |
|
1434 // Now aDateTime has to be in format YYYY-MM-DDTHH:MM:SSZ |
|
1435 |
|
1436 // check supplied descriptor is the correct length |
|
1437 if ( aDateTime.Length() != KValidUTCLength ) |
|
1438 { |
|
1439 PUSHLOG_WRITE_FORMAT(" invalid UTC length <%d>",aDateTime.Length()) |
|
1440 isValid = EFalse; |
|
1441 } |
|
1442 else |
|
1443 { |
|
1444 // strip out formatting characters |
|
1445 TInt formatCharPos = 4; |
|
1446 aDateTime.Delete( formatCharPos, 1 ); |
|
1447 // now move through two characters at a time and remove other chars |
|
1448 // to just leave digits |
|
1449 const TInt KRemainingFormatChars = 5; |
|
1450 TInt i( 0 ); |
|
1451 for ( i = 0; i < KRemainingFormatChars; ++i ) |
|
1452 { |
|
1453 formatCharPos += 2; |
|
1454 aDateTime.Delete( formatCharPos, 1 ); |
|
1455 } |
|
1456 |
|
1457 // Now aDateTime has to be in format YYYYMMDDHHMMSS |
|
1458 |
|
1459 __ASSERT_DEBUG( aDateTime.Length() == KValidTTimeLength, |
|
1460 ContHandPanic( EPushContHandPanBadTTimeLength ) ); |
|
1461 |
|
1462 // now have UTC string stripped of format characters - check remaining |
|
1463 // characters are all digits - YYYYMMDDHHMMSS |
|
1464 TChar ch; |
|
1465 for ( i = 0; i < KValidTTimeLength; ++i ) |
|
1466 { |
|
1467 ch = aDateTime[i]; |
|
1468 if ( ch.IsDigit() == EFalse ) |
|
1469 { |
|
1470 PUSHLOG_WRITE_FORMAT(" not digit <%d>",i) |
|
1471 isValid = EFalse; |
|
1472 } |
|
1473 } |
|
1474 |
|
1475 if ( isValid ) |
|
1476 { |
|
1477 /* |
|
1478 In YYYYMMDDHHMMSS |
|
1479 YYYY = 4 digit year ("0000" ... "9999") |
|
1480 MM = 2 digit month ("01"=January, "02"=February ... "12"=December) |
|
1481 DD = 2 digit day ("01", "02" ... "31") |
|
1482 HH = 2 digit hour, 24-hour timekeeping system ("00" ... "23") |
|
1483 MM = 2 digit minute ("00" ... "59") |
|
1484 SS = 2 digit second ("00" ... "59") |
|
1485 */ |
|
1486 TInt err; |
|
1487 TUint val; |
|
1488 // Do not check year. There are no restrictions. |
|
1489 // Check month. |
|
1490 TLex parser( aDateTime.Mid( KValidTTimeMonthStart, |
|
1491 KValidTTimeBlockLength ) ); |
|
1492 err = parser.Val( val, EDecimal ); |
|
1493 if ( err ) |
|
1494 { |
|
1495 isValid = EFalse; |
|
1496 PUSHLOG_WRITE_FORMAT(" parser err: <%d>",err) |
|
1497 } |
|
1498 else |
|
1499 { |
|
1500 PUSHLOG_WRITE_FORMAT(" month: <%d>",val) |
|
1501 if ( val < 1 || 12 < val ) |
|
1502 { |
|
1503 isValid = EFalse; |
|
1504 } |
|
1505 } |
|
1506 // Check day. |
|
1507 if ( isValid ) |
|
1508 { |
|
1509 parser = aDateTime.Mid( KValidTTimeDayStart, |
|
1510 KValidTTimeBlockLength ); |
|
1511 err = parser.Val( val, EDecimal ); |
|
1512 if ( err ) |
|
1513 { |
|
1514 isValid = EFalse; |
|
1515 PUSHLOG_WRITE_FORMAT(" parser err: <%d>",err) |
|
1516 } |
|
1517 else |
|
1518 { |
|
1519 PUSHLOG_WRITE_FORMAT(" day: <%d>",val) |
|
1520 if ( val < 1 || 31 < val ) |
|
1521 { |
|
1522 isValid = EFalse; |
|
1523 } |
|
1524 } |
|
1525 } |
|
1526 // Check hour. |
|
1527 if ( isValid ) |
|
1528 { |
|
1529 parser = aDateTime.Mid( KValidTTimeHourStart, |
|
1530 KValidTTimeBlockLength ); |
|
1531 err = parser.Val( val, EDecimal ); |
|
1532 if ( err ) |
|
1533 { |
|
1534 isValid = EFalse; |
|
1535 PUSHLOG_WRITE_FORMAT(" parser err: <%d>",err) |
|
1536 } |
|
1537 else |
|
1538 { |
|
1539 PUSHLOG_WRITE_FORMAT(" hour: <%d>",val) |
|
1540 if ( 23 < val ) |
|
1541 { |
|
1542 isValid = EFalse; |
|
1543 } |
|
1544 } |
|
1545 } |
|
1546 // Check minute. |
|
1547 if ( isValid ) |
|
1548 { |
|
1549 parser = aDateTime.Mid( KValidTTimeMinuteStart, |
|
1550 KValidTTimeBlockLength ); |
|
1551 err = parser.Val( val, EDecimal ); |
|
1552 if ( err ) |
|
1553 { |
|
1554 isValid = EFalse; |
|
1555 PUSHLOG_WRITE_FORMAT(" parser err: <%d>",err) |
|
1556 } |
|
1557 else |
|
1558 { |
|
1559 PUSHLOG_WRITE_FORMAT(" min: <%d>",val) |
|
1560 if ( 59 < val ) |
|
1561 { |
|
1562 isValid = EFalse; |
|
1563 } |
|
1564 } |
|
1565 } |
|
1566 // Check second. |
|
1567 if ( isValid ) |
|
1568 { |
|
1569 parser = aDateTime.Mid( KValidTTimeSecondStart, |
|
1570 KValidTTimeBlockLength ); |
|
1571 err = parser.Val( val, EDecimal ); |
|
1572 if ( err ) |
|
1573 { |
|
1574 isValid = EFalse; |
|
1575 PUSHLOG_WRITE_FORMAT(" parser err: <%d>",err) |
|
1576 } |
|
1577 else |
|
1578 { |
|
1579 PUSHLOG_WRITE_FORMAT(" sec: <%d>",val) |
|
1580 if ( 59 < val ) |
|
1581 { |
|
1582 isValid = EFalse; |
|
1583 } |
|
1584 } |
|
1585 } |
|
1586 |
|
1587 // insert colon seperating date from time |
|
1588 const TInt KColonPosition = 8; |
|
1589 aDateTime.Insert( KColonPosition, KCharColon ); |
|
1590 |
|
1591 // Now aDateTime has to be in format YYYYMMDD:HHMMSS |
|
1592 } |
|
1593 } |
|
1594 |
|
1595 PUSHLOG_LEAVEFN("CSIContentHandler::IsValidUTCTime") |
|
1596 return isValid; // aDateTime contains a modified buffer. |
|
1597 } |
|
1598 |
|
1599 // --------------------------------------------------------- |
|
1600 // CSIContentHandler::AttributeToTTimeL |
|
1601 // --------------------------------------------------------- |
|
1602 // |
|
1603 TBool CSIContentHandler::AttributeToTTimeL |
|
1604 ( NW_DOM_AttributeHandle_t& aAttrHandle, |
|
1605 TTime& aConvertedDate ) const |
|
1606 { |
|
1607 PUSHLOG_ENTERFN("CSIContentHandler::AttributeToTTimeL") |
|
1608 |
|
1609 TBool gotDate = EFalse; |
|
1610 NW_Status_t stat = NW_STAT_SUCCESS; |
|
1611 NW_DOM_AttrVal_t attrVal; |
|
1612 |
|
1613 // It is expected to be String or Opaque. |
|
1614 // It may be Opaque, to which we will need a NW_DOM_AttrVal_t structure. |
|
1615 stat = NW_DOM_AttributeHandle_getNextVal( &aAttrHandle, &attrVal ); |
|
1616 |
|
1617 if ( stat != NW_STAT_WBXML_ITERATE_MORE ) |
|
1618 { |
|
1619 User::LeaveIfError( NwxStatusToErrCode( stat ) ); |
|
1620 } |
|
1621 else |
|
1622 { |
|
1623 NW_Uint16 valType = NW_DOM_AttrVal_getType( &attrVal ); |
|
1624 |
|
1625 if ( valType == NW_DOM_ATTR_VAL_STRING ) |
|
1626 { |
|
1627 CStringOwner* stringOwner = new (ELeave) CStringOwner; |
|
1628 CleanupStack::PushL( stringOwner ); |
|
1629 |
|
1630 NW_String_t* val = NW_String_new(); |
|
1631 User::LeaveIfNull( val ); |
|
1632 stringOwner->SetString( val ); |
|
1633 // |
|
1634 stat = NW_DOM_AttrVal_toString( &attrVal, val, iCharEncoding ); |
|
1635 User::LeaveIfError( NwxStatusToErrCode( stat ) ); |
|
1636 NW_Byte* storage = NW_String_getStorage( val ); |
|
1637 NW_Uint16 length = NW_String_getCharCount( val, iCharEncoding ); |
|
1638 TPtrC8 dataPtr( storage, length ); |
|
1639 HBufC* dataBuf = HBufC::NewMaxLC( dataPtr.Length() ); |
|
1640 dataBuf->Des().Copy( dataPtr ); |
|
1641 gotDate = ConvertDateTimeL( *dataBuf, aConvertedDate ); |
|
1642 |
|
1643 CleanupStack::PopAndDestroy( 2, stringOwner ); // dataBuf, |
|
1644 // stringOwner |
|
1645 } |
|
1646 else if ( valType == NW_DOM_ATTR_VAL_OPAQUE ) |
|
1647 { |
|
1648 NW_Uint32 len = 0; |
|
1649 NW_Byte* data = NW_DOM_AttrVal_getOpaque( &attrVal, &len ); |
|
1650 User::LeaveIfNull( data ); |
|
1651 TPtrC8 dataPtr( data, len ); |
|
1652 |
|
1653 HBufC* dateTime = ConvertOpaqueToUtcL( dataPtr ); |
|
1654 CleanupStack::PushL( dateTime ); |
|
1655 gotDate = ConvertDateTimeL( *dateTime, aConvertedDate ); |
|
1656 CleanupStack::PopAndDestroy( dateTime ); // dateTime |
|
1657 } |
|
1658 else |
|
1659 { |
|
1660 User::Leave( KErrNotSupported ); |
|
1661 } |
|
1662 } |
|
1663 |
|
1664 PUSHLOG_LEAVEFN("CSIContentHandler::AttributeToTTimeL") |
|
1665 return gotDate; // aConvertedDate contains the result. |
|
1666 } |
|
1667 |
|
1668 // --------------------------------------------------------- |
|
1669 // CSIContentHandler::HandleMessageL |
|
1670 // --------------------------------------------------------- |
|
1671 // |
|
1672 void CSIContentHandler::HandleMessageL( CPushMessage* aPushMsg, |
|
1673 TRequestStatus& aStatus ) |
|
1674 { |
|
1675 PUSHLOG_ENTERFN("CSIContentHandler::HandleMessageL") |
|
1676 |
|
1677 __ASSERT_DEBUG( aPushMsg != NULL, |
|
1678 ContHandPanic( EPushContHandPanMsgNull ) ); |
|
1679 |
|
1680 #ifdef __TEST_LOG__ |
|
1681 TPtrC8 bodyPtr; |
|
1682 aPushMsg->GetMessageBody( bodyPtr ); |
|
1683 PUSHLOG_HEXDUMP( bodyPtr ) |
|
1684 #endif // __TEST_LOG__ |
|
1685 |
|
1686 iMessage = aPushMsg; |
|
1687 iAcknowledge = ETrue; |
|
1688 SetConfirmationStatus( aStatus ); |
|
1689 |
|
1690 iState = EGarbageCollecting; |
|
1691 IdleComplete(); |
|
1692 |
|
1693 PUSHLOG_LEAVEFN("CSIContentHandler::HandleMessageL") |
|
1694 } |
|
1695 |
|
1696 // --------------------------------------------------------- |
|
1697 // CSIContentHandler::HandleMessageL |
|
1698 // --------------------------------------------------------- |
|
1699 // |
|
1700 void CSIContentHandler::HandleMessageL( CPushMessage* aPushMsg ) |
|
1701 { |
|
1702 PUSHLOG_ENTERFN("CSIContentHandler::HandleMessageL") |
|
1703 |
|
1704 __ASSERT_DEBUG( aPushMsg != NULL, |
|
1705 ContHandPanic( EPushContHandPanMsgNull ) ); |
|
1706 |
|
1707 #ifdef __TEST_LOG__ |
|
1708 TPtrC8 bodyPtr; |
|
1709 aPushMsg->GetMessageBody( bodyPtr ); |
|
1710 PUSHLOG_HEXDUMP( bodyPtr ) |
|
1711 #endif // __TEST_LOG__ |
|
1712 |
|
1713 iAcknowledge = EFalse; |
|
1714 iMessage = aPushMsg; |
|
1715 |
|
1716 iState = EGarbageCollecting; |
|
1717 IdleComplete(); |
|
1718 |
|
1719 PUSHLOG_LEAVEFN("CSIContentHandler::HandleMessageL") |
|
1720 } |
|
1721 |
|
1722 // --------------------------------------------------------- |
|
1723 // CSIContentHandler::CancelHandleMessage |
|
1724 // --------------------------------------------------------- |
|
1725 // |
|
1726 void CSIContentHandler::CancelHandleMessage() |
|
1727 { |
|
1728 PUSHLOG_ENTERFN("CSIContentHandler::CancelHandleMessage") |
|
1729 Cancel(); |
|
1730 PUSHLOG_LEAVEFN("CSIContentHandler::CancelHandleMessage") |
|
1731 } |
|
1732 |
|
1733 // --------------------------------------------------------- |
|
1734 // CSIContentHandler::CPushHandlerBase_Reserved1 |
|
1735 // --------------------------------------------------------- |
|
1736 // |
|
1737 void CSIContentHandler::CPushHandlerBase_Reserved1() |
|
1738 { |
|
1739 } |
|
1740 |
|
1741 // --------------------------------------------------------- |
|
1742 // CSIContentHandler::CPushHandlerBase_Reserved2 |
|
1743 // --------------------------------------------------------- |
|
1744 // |
|
1745 void CSIContentHandler::CPushHandlerBase_Reserved2() |
|
1746 { |
|
1747 } |
|
1748 |
|
1749 // --------------------------------------------------------- |
|
1750 // CSIContentHandler::DoCancel |
|
1751 // --------------------------------------------------------- |
|
1752 // |
|
1753 void CSIContentHandler::DoCancel() |
|
1754 { |
|
1755 PUSHLOG_ENTERFN("CSIContentHandler::DoCancel") |
|
1756 Complete( KErrCancel ); |
|
1757 PUSHLOG_LEAVEFN("CSIContentHandler::DoCancel") |
|
1758 } |
|
1759 |
|
1760 // --------------------------------------------------------- |
|
1761 // CSIContentHandler::RunL |
|
1762 // --------------------------------------------------------- |
|
1763 // |
|
1764 void CSIContentHandler::RunL() |
|
1765 { |
|
1766 // Handle errors in RunError(). |
|
1767 PUSHLOG_WRITE_FORMAT("iStatus.Int(): %d",iStatus.Int()) |
|
1768 User::LeaveIfError( iStatus.Int() ); |
|
1769 |
|
1770 // use active state machine routine to manage activites: |
|
1771 switch ( iState ) |
|
1772 { |
|
1773 case EGarbageCollecting: |
|
1774 { |
|
1775 CollectGarbageL(); |
|
1776 break; |
|
1777 } |
|
1778 case EFilteringAndParsing: |
|
1779 { |
|
1780 if ( !FilterPushMsgL() ) |
|
1781 { |
|
1782 // It did not pass the filter. Done. |
|
1783 iState = EDone; |
|
1784 IdleComplete(); |
|
1785 } |
|
1786 else |
|
1787 { |
|
1788 // Continue. |
|
1789 TInt ret = KErrNone; |
|
1790 PUSHLOG_WRITE("CSIContentHandler::RunL : before trapping parsing.") |
|
1791 TRAP(ret, ParsePushMsgL()); |
|
1792 PUSHLOG_WRITE_FORMAT("CSIContentHandler::RunL : after trapping parsing. ret = %d", ret) |
|
1793 if ( ret != KErrNone) |
|
1794 { |
|
1795 PUSHLOG_WRITE("CSIContentHandler::RunL : Parsing failed. discarding message.") |
|
1796 iState = EDone; |
|
1797 IdleComplete(); |
|
1798 } |
|
1799 } |
|
1800 break; |
|
1801 } |
|
1802 case EProcessing: |
|
1803 { |
|
1804 ProcessingPushMsgEntryL(); |
|
1805 break; |
|
1806 } |
|
1807 case EDone: |
|
1808 { |
|
1809 PUSHLOG_WRITE("CSIContentHandler EDone") |
|
1810 Complete( KErrNone ); |
|
1811 break; |
|
1812 } |
|
1813 default: |
|
1814 { |
|
1815 // JIC. |
|
1816 PUSHLOG_WRITE("CSIContentHandler default Done") |
|
1817 Complete( KErrNone ); |
|
1818 break; |
|
1819 } |
|
1820 } |
|
1821 } |
|
1822 |
|
1823 // --------------------------------------------------------- |
|
1824 // CSIContentHandler::RunError |
|
1825 // --------------------------------------------------------- |
|
1826 // |
|
1827 TInt CSIContentHandler::RunError( TInt aError ) |
|
1828 { |
|
1829 PUSHLOG_WRITE_FORMAT("CSIContentHandler::RunError: %d",aError) |
|
1830 |
|
1831 iState = EDone; |
|
1832 Complete( aError ); |
|
1833 return KErrNone; |
|
1834 } |
|
1835 |
|