|
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 "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: CWPWbxmlParser parses WBXML data using builder design pattern |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include <stdlib.h> // included for free() |
|
21 #include "MWPBuilder.h" |
|
22 #include "CWPWbxmlParser.h" |
|
23 #include "OMAProvisioningDictionary.h" |
|
24 #include "ProvisioningDebug.h" |
|
25 #include <nw_cXML_Parser.h> |
|
26 |
|
27 // EXTERNAL DATA STRUCTURES |
|
28 extern "C" NW_WBXML_Dictionary_t NW_omawapprovisioning_WBXMLDictionary; |
|
29 |
|
30 // CONSTANTS |
|
31 const NW_Uint16 KParseError = 0xffff; |
|
32 const NW_Uint16 KParseStatusOk = 0; |
|
33 const TUint KWapProvisioningDocToken = 0x05; |
|
34 const TUint KCharacteristicToken = 0x06; |
|
35 const NW_Uint16 KTokenValueMask = 0xff; |
|
36 //const TUint16 KTokenPageMask = 0xff00; // Commented to remove warning in armv5 |
|
37 const TUint KAttribValMin = 128; |
|
38 const TUint KParmNameToken = 0x05; |
|
39 const TUint KCharTypeToken = 0x50; |
|
40 const TUint KParmStartValueToken = 0x06; |
|
41 const TUint KParmToken = 0x07; |
|
42 const TUint KFromTag = 0x0201; |
|
43 //const TUint KMaxBandwidthTag = 0x0202; // Commented to remove warning in armv5 |
|
44 //const TUint KMaxUdpPortTag = 0x0203; // Commented to remove warning in armv5 |
|
45 //const TUint KMinUdpPortTag = 0x0204; // Commented to remove warning in armv5 |
|
46 //const NW_Int32 publicID = 0x0b; // Commented to remove warning in armv5 |
|
47 const TUint KDictionaryCount = 1; |
|
48 const TInt KHeaderLength = 4; |
|
49 // binary values of the clashing names in different code pages |
|
50 //const TInt KDuplicateTagTable[]={ 0x06,0x07 }; |
|
51 const TInt KDuplicateCharacteristicTable[]={ 0x53,0x58 }; |
|
52 const TInt KDuplicateParmAttributeStartTable[]={ 0x07, 0x14, 0x1C, |
|
53 0x22, 0x23, 0x24 }; |
|
54 //const TInt KDuplicateAddrtypeValueTable[]={ 0x86, 0x87, 0x88 }; // Commented to remove warning in armv5 |
|
55 |
|
56 _LIT(KFromStr,"FROM"); |
|
57 //_LIT(KMaxBandwidthStr,"MAX-BANDWIDTH"); // Commented to remove warning in armv5 |
|
58 //_LIT(KMaxUdpPortStr,"MAX-UDP-PORT"); // Commented to remove warning in armv5 |
|
59 //_LIT(KMinUdpPortStr,"MIN-UDP-PORT"); // Commented to remove warning in armv5 |
|
60 |
|
61 // ============================ MEMBER FUNCTIONS =============================== |
|
62 |
|
63 |
|
64 // ----------------------------------------------------------------------------- |
|
65 // CWPNameValuePair::CWPNameValuePair |
|
66 // C++ default constructor. |
|
67 // ----------------------------------------------------------------------------- |
|
68 // |
|
69 CWPNameValuePair::CWPNameValuePair() |
|
70 { |
|
71 } |
|
72 |
|
73 // ----------------------------------------------------------------------------- |
|
74 // CWPNameValuePair::~CWPNameValuePair |
|
75 // Destructor |
|
76 // ----------------------------------------------------------------------------- |
|
77 // |
|
78 CWPNameValuePair::~CWPNameValuePair() |
|
79 { |
|
80 delete iValue; |
|
81 } |
|
82 |
|
83 // --------------------------------------------------------- |
|
84 // CWPStringPair::SetValue |
|
85 // --------------------------------------------------------- |
|
86 // |
|
87 void CWPNameValuePair::SetValue( HBufC* aValue ) |
|
88 { |
|
89 delete iValue; |
|
90 iValue = aValue; |
|
91 } |
|
92 |
|
93 const TDesC& CWPNameValuePair::Value() const |
|
94 { |
|
95 if ( iValue ) |
|
96 { |
|
97 return *iValue; |
|
98 } |
|
99 else |
|
100 { |
|
101 return KNullDesC; |
|
102 } |
|
103 } |
|
104 |
|
105 // ============================ MEMBER FUNCTIONS =============================== |
|
106 |
|
107 // ----------------------------------------------------------------------------- |
|
108 // CWPWbxmlParser::CWPWbxmlParser |
|
109 // C++ default constructor can NOT contain any code, that |
|
110 // might leave. |
|
111 // ----------------------------------------------------------------------------- |
|
112 // |
|
113 CWPWbxmlParser::CWPWbxmlParser() |
|
114 { |
|
115 } |
|
116 |
|
117 // ----------------------------------------------------------------------------- |
|
118 // CWPWbxmlParser::ConstructL |
|
119 // Symbian 2nd phase constructor can leave. |
|
120 // ----------------------------------------------------------------------------- |
|
121 // |
|
122 void CWPWbxmlParser::ConstructL() |
|
123 { |
|
124 |
|
125 iDocNode = NULL; |
|
126 // A dictionary containing OMA provisioning WBXML tokens: |
|
127 iDictionary[0] = &NW_omawapprovisioning_WBXMLDictionary; |
|
128 TInt err = NW_WBXML_Dictionary_initialize ( KDictionaryCount, iDictionary ); |
|
129 switch( err ) |
|
130 { |
|
131 case NW_STAT_OUT_OF_MEMORY: |
|
132 { |
|
133 User::Leave( KErrNoMemory ); |
|
134 break; |
|
135 } |
|
136 case NW_STAT_FAILURE: |
|
137 { |
|
138 User::Leave( KErrGeneral ); |
|
139 break; |
|
140 } |
|
141 default: |
|
142 break; |
|
143 } |
|
144 |
|
145 } |
|
146 |
|
147 // ----------------------------------------------------------------------------- |
|
148 // CWPWbxmlParser::NewL |
|
149 // Two-phased constructor. |
|
150 // ----------------------------------------------------------------------------- |
|
151 // |
|
152 EXPORT_C CWPWbxmlParser* CWPWbxmlParser::NewL() |
|
153 { |
|
154 CWPWbxmlParser* self = new( ELeave ) CWPWbxmlParser; |
|
155 CleanupStack::PushL(self); |
|
156 self->ConstructL(); |
|
157 CleanupStack::Pop(self); |
|
158 return self; |
|
159 } |
|
160 |
|
161 // Destructor |
|
162 CWPWbxmlParser::~CWPWbxmlParser() |
|
163 { |
|
164 delete iParameterName; |
|
165 NW_WBXML_Dictionary_destroy(); // deletes iDictionary |
|
166 } |
|
167 |
|
168 void CWPWbxmlParser::Cleanup( TAny *aPtr ) |
|
169 { |
|
170 NW_TinyDom_ParserDelete( STATIC_CAST( Parser_t* , aPtr ) ); |
|
171 } |
|
172 |
|
173 |
|
174 // ----------------------------------------------------------------------------- |
|
175 // CWPWbxmlParser::ParseL |
|
176 // Two-phased constructor. |
|
177 // ----------------------------------------------------------------------------- |
|
178 // |
|
179 EXPORT_C void CWPWbxmlParser::ParseL( const TDesC8& aDocument, |
|
180 MWPBuilder& aRoot ) |
|
181 { |
|
182 NW_TinyDom_Handle_t handle; |
|
183 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseL begin" ) ); |
|
184 |
|
185 NW_Int32 bufferLength( aDocument.Size() ); |
|
186 if( bufferLength <= KHeaderLength ) |
|
187 { |
|
188 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseL leaving" ) ); |
|
189 User::Leave( KErrCorrupt ); |
|
190 } |
|
191 NW_Byte* buffer = CONST_CAST( NW_Byte*, aDocument.Ptr() ); |
|
192 // create a tree from a wbxml buffer |
|
193 iDocNode = NW_DOM_DocumentNode_BuildWBXMLTree(&handle, |
|
194 buffer, |
|
195 bufferLength, |
|
196 NW_FALSE, |
|
197 NW_FALSE); |
|
198 |
|
199 if( !iDocNode ) |
|
200 { |
|
201 User::Leave( KErrCorrupt ); |
|
202 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseL error branch" ) ); |
|
203 } |
|
204 else |
|
205 { |
|
206 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseL okey branch" ) ); |
|
207 |
|
208 CleanupStack::PushL( TCleanupItem( Cleanup, &handle ) ) ; |
|
209 // traverse tree and build data into engine |
|
210 ParseDocumentL( iDocNode, aRoot ) ; |
|
211 CleanupStack::PopAndDestroy(); // via handle |
|
212 } |
|
213 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseL end" ) ); |
|
214 } |
|
215 |
|
216 |
|
217 // ----------------------------------------------------------------------------- |
|
218 // CWPWbxmlParser::ParseDocumentL |
|
219 // Parses DOM document |
|
220 // ----------------------------------------------------------------------------- |
|
221 // |
|
222 NW_Uint16 CWPWbxmlParser::ParseDocumentL( NW_DOM_DocumentNode_t *aDocument, |
|
223 MWPBuilder& aRoot ) |
|
224 { |
|
225 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseDocumentL begin" ) ); |
|
226 NW_Uint32 encoding( NW_DOM_DocumentNode_getCharacterEncoding( aDocument ) ); |
|
227 NW_DOM_ElementNode_t* elem = |
|
228 NW_DOM_DocumentNode_getDocumentElement( aDocument ); |
|
229 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseDocumentL end" ) ); |
|
230 return ParseNodeL( elem, encoding, aRoot ); |
|
231 } |
|
232 |
|
233 // ----------------------------------------------------------------------------- |
|
234 // CWPWbxmlParser::ParseNode |
|
235 // Parses DOM tree Node recursively |
|
236 // ----------------------------------------------------------------------------- |
|
237 // |
|
238 NW_Uint16 CWPWbxmlParser::ParseNodeL( NW_DOM_Node_t* aNode, NW_Uint32 aEncoding, |
|
239 MWPBuilder& aRoot) |
|
240 { |
|
241 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParesNodeL begin" ) ); |
|
242 NW_DOM_Node_t* node = aNode; |
|
243 if( !node ) |
|
244 { |
|
245 User::Leave( KErrGeneral ); |
|
246 } |
|
247 else |
|
248 { |
|
249 NW_Uint32 type = NW_DOM_Node_getNodeType( aNode ); |
|
250 if ( type != NW_DOM_ELEMENT_NODE ) |
|
251 { |
|
252 User::Leave( KErrGeneral ); |
|
253 } |
|
254 } |
|
255 NW_Uint16 errCode( KParseStatusOk ); |
|
256 // traverse tree by simulating a stack |
|
257 while( node ) |
|
258 { |
|
259 ParseElementL( node, aEncoding, aRoot ); |
|
260 if( NW_DOM_Node_hasChildNodes( node ) ) |
|
261 { |
|
262 node = NW_DOM_Node_getFirstChild( node ); |
|
263 } |
|
264 else // leaf reached, find parent level |
|
265 { |
|
266 while( NW_DOM_Node_getNextSibling( node ) == NULL && node != aNode ) |
|
267 { |
|
268 NW_Uint32 tagToken = NW_DOM_ElementNode_getTagToken( node ); |
|
269 if( tagToken == KCharacteristicToken ) |
|
270 { |
|
271 aRoot.EndCharacteristicL(); |
|
272 } |
|
273 |
|
274 if(tagToken==0) |
|
275 User::Leave(KErrCorrupt); |
|
276 node = NW_DOM_Node_getParentNode( node ); |
|
277 } |
|
278 // always end leaf characteristic |
|
279 NW_Uint32 tagToken = NW_DOM_ElementNode_getTagToken( node ); |
|
280 if( tagToken == KCharacteristicToken ) |
|
281 { |
|
282 aRoot.EndCharacteristicL(); |
|
283 } |
|
284 node = NW_DOM_Node_getNextSibling( node ); |
|
285 } // end leaf |
|
286 } // end outer while |
|
287 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseNodeL end" ) ); |
|
288 return errCode; |
|
289 } |
|
290 |
|
291 // ----------------------------------------------------------------------------- |
|
292 // CWPWbxmlParser::ParseElement |
|
293 // Parses DOM tree element into Engine data model using builder pattern. |
|
294 // ----------------------------------------------------------------------------- |
|
295 // |
|
296 void CWPWbxmlParser::ParseElementL( NW_DOM_ElementNode_t* aElement, |
|
297 NW_Uint32 aEncoding, MWPBuilder& aRoot ) |
|
298 { |
|
299 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseElementL begin" ) ); |
|
300 NW_Uint32 token = NW_DOM_ElementNode_getTagToken( aElement ); |
|
301 NW_Uint16 parmNameToken( 0 ); |
|
302 NW_TinyTree_t* tiny_tree = NW_TinyTree_Node_findTree( aElement ) ; |
|
303 NW_TinyDom_getParser( tiny_tree ); |
|
304 if ( NW_DOM_ElementNode_hasAttributes( aElement ) ) |
|
305 { |
|
306 NW_DOM_AttributeListIterator_t listIter; |
|
307 NW_Status_t status = |
|
308 NW_DOM_ElementNode_getAttributeListIterator( aElement, &listIter ); |
|
309 if( status != NW_STAT_SUCCESS ) |
|
310 { |
|
311 User::Leave( KErrCorrupt ); |
|
312 } |
|
313 TBool isFirstPart( ETrue ); // only one iteration |
|
314 TBool isLastPartProcessed( EFalse ); |
|
315 TBool unknownNameFound( EFalse ); |
|
316 NW_DOM_AttributeHandle_t attrHandle; |
|
317 while ( NW_DOM_AttributeListIterator_getNextAttribute( &listIter, |
|
318 &attrHandle ) |
|
319 == NW_STAT_WBXML_ITERATE_MORE ) |
|
320 { |
|
321 CWPNameValuePair* pair = new( ELeave ) CWPNameValuePair(); |
|
322 CleanupStack::PushL( pair ); |
|
323 NW_Uint16 attribToken( KParseError ); |
|
324 attribToken = ParseAttributeL( &attrHandle, |
|
325 aEncoding, |
|
326 *pair ); |
|
327 |
|
328 if( attribToken == KParseError ) |
|
329 { |
|
330 // syntactically invalid attribute |
|
331 User::Leave( KErrCorrupt ); |
|
332 } |
|
333 |
|
334 // extract code page from token |
|
335 NW_Uint16 codePage( |
|
336 STATIC_CAST( NW_Uint16, ( ( attribToken >> 8 ) & KTokenValueMask |
|
337 ) ) ); |
|
338 NW_Uint16 extractedValue ( |
|
339 STATIC_CAST( NW_Uint16, ( attribToken & KTokenValueMask ) |
|
340 ) ); |
|
341 // process attributes based on current element token |
|
342 switch( token ) |
|
343 { |
|
344 case KWapProvisioningDocToken: |
|
345 { |
|
346 FLOG( _L( "[ProvisioningParser] ParseElementL: prov doc found" ) ); |
|
347 break; // start of document |
|
348 } |
|
349 case KCharacteristicToken: |
|
350 { |
|
351 FLOG( _L( "[ProvisioningParser] characteristic token found" ) ); |
|
352 // check if the name clashes with a name in code page zero |
|
353 if ( attribToken == KCharTypeToken && pair ) |
|
354 { |
|
355 aRoot.StartCharacteristicL( pair->Value() ); |
|
356 } |
|
357 else { |
|
358 if( codePage != 0 ) |
|
359 { |
|
360 TInt numElements( STATIC_CAST( TInt, ( |
|
361 sizeof ( KDuplicateCharacteristicTable ) / |
|
362 sizeof ( KDuplicateCharacteristicTable[0] ) ) ) ); |
|
363 for( TInt i( 0 ); i < numElements; i++ ) |
|
364 { |
|
365 if ( extractedValue == |
|
366 KDuplicateCharacteristicTable[i] ) |
|
367 { |
|
368 attribToken = extractedValue; |
|
369 FTRACE(RDebug::Print(_L("[ProvisioningParser] characteristic: id %d"), extractedValue)); |
|
370 break; // end for |
|
371 } |
|
372 } |
|
373 } // end codepage not 0 |
|
374 aRoot.StartCharacteristicL( attribToken ); |
|
375 } |
|
376 break; |
|
377 } |
|
378 // Note: parameters are constructed in two phases: |
|
379 // 1. the attribute value prefix token of the parm is stored |
|
380 // 2. the value of the attribute is read and stored |
|
381 // with the prefix. |
|
382 case KParmToken: |
|
383 { |
|
384 FLOG( _L( "[ProvisioningParser] parameter token found" ) ); |
|
385 // process the first part of the parameter attribute |
|
386 if( isFirstPart && attribToken > 0 && |
|
387 extractedValue < KAttribValMin ) |
|
388 { |
|
389 if( extractedValue == KParmNameToken && pair ) |
|
390 { |
|
391 if( pair->Value().Compare( KFromStr ) ==0 ) |
|
392 { |
|
393 parmNameToken = KFromTag; |
|
394 } |
|
395 |
|
396 // unknown parameter name. |
|
397 else |
|
398 { |
|
399 unknownNameFound = ETrue; |
|
400 delete iParameterName; |
|
401 iParameterName = NULL; |
|
402 iParameterName = (pair->Value()).AllocL(); |
|
403 } |
|
404 } |
|
405 // set parameter name token for storing it in step 2. |
|
406 else |
|
407 { |
|
408 parmNameToken = attribToken; |
|
409 } |
|
410 FTRACE(RDebug::Print(_L("[ProvisioningParser] parameter id %d"), parmNameToken)); |
|
411 |
|
412 // check if the name clashes with a name in code page 0 |
|
413 if( codePage != 0 ) |
|
414 { |
|
415 TInt numElements( STATIC_CAST( TInt, ( |
|
416 sizeof ( KDuplicateParmAttributeStartTable ) / |
|
417 sizeof ( KDuplicateParmAttributeStartTable[0] )) |
|
418 )); |
|
419 for( TInt i(0); i < numElements ; i++ ) |
|
420 { |
|
421 if ( extractedValue == |
|
422 KDuplicateParmAttributeStartTable[i] ) |
|
423 { |
|
424 parmNameToken = extractedValue; |
|
425 break; // end for |
|
426 } |
|
427 } |
|
428 } // end codepage not 0 |
|
429 isFirstPart = EFalse; |
|
430 break; |
|
431 } |
|
432 // process the second part of the attribute (value) |
|
433 else if(!isFirstPart && (extractedValue == KParmStartValueToken |
|
434 || extractedValue >= KAttribValMin ) ) |
|
435 { |
|
436 if( !unknownNameFound ) |
|
437 { |
|
438 aRoot.ParameterL( parmNameToken, pair->Value() ); |
|
439 } |
|
440 else if ( unknownNameFound ) |
|
441 { |
|
442 aRoot.ParameterL( *iParameterName , pair->Value() ); |
|
443 delete iParameterName; |
|
444 iParameterName = NULL; |
|
445 } |
|
446 isLastPartProcessed=ETrue; |
|
447 } |
|
448 break; |
|
449 } |
|
450 default: // error no corresponding element exists |
|
451 { |
|
452 break; |
|
453 } |
|
454 } // end switch |
|
455 CleanupStack::PopAndDestroy(); // pair |
|
456 } // end while |
|
457 // if this parameter consisted of only one attribute, then |
|
458 // store it |
|
459 if( parmNameToken && !isLastPartProcessed ) |
|
460 { |
|
461 aRoot.ParameterL( parmNameToken, KNullDesC ); |
|
462 } |
|
463 else if( iParameterName && !isLastPartProcessed ) |
|
464 { |
|
465 aRoot.ParameterL( *iParameterName, KNullDesC ); |
|
466 delete iParameterName; |
|
467 iParameterName = NULL; |
|
468 } |
|
469 |
|
470 } |
|
471 |
|
472 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseElementL end" ) ); |
|
473 // end if has attributes. |
|
474 } |
|
475 |
|
476 // ----------------------------------------------------------------------------- |
|
477 // CWPWbxmlParser::ParseAttribute |
|
478 // Constructs HBufCs containing attribute name and value |
|
479 // ----------------------------------------------------------------------------- |
|
480 // |
|
481 NW_Uint16 CWPWbxmlParser::ParseAttributeL( NW_DOM_AttributeHandle_t* aAttrHandle, |
|
482 NW_Uint32 aEncoding, |
|
483 CWPNameValuePair& aPair ) |
|
484 { |
|
485 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseAttributeL begin" ) ); |
|
486 NW_Uint16 getStatus( KParseError ); |
|
487 // All tokenised attributes must begin with a single attribute start token |
|
488 // and may be followed by zero or more attribute value, string, entity, |
|
489 // opaque, or extension tokens. |
|
490 // 1. process attribute name |
|
491 TUint16 token( NW_DOM_AttributeHandle_getToken( aAttrHandle ) ); |
|
492 // 2. process attribute value (only one allowed) |
|
493 NW_String_t strValue; |
|
494 NW_Status_t status = NW_DOM_AttributeHandle_getValue( aAttrHandle, &strValue ); |
|
495 if( status == NW_STAT_SUCCESS ) |
|
496 { |
|
497 getStatus = KParseStatusOk; |
|
498 } |
|
499 aPair.SetValue( ProcessAttributePartL( &strValue, aEncoding, getStatus ) ); |
|
500 |
|
501 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ParseAttributeL end" ) ); |
|
502 return token; |
|
503 } |
|
504 // ----------------------------------------------------------------------------- |
|
505 // CWPWbxmlParser::ProcessAttributePartL |
|
506 // Constructs HBufCs containing attribute name and value |
|
507 // ----------------------------------------------------------------------------- |
|
508 // |
|
509 HBufC* CWPWbxmlParser::ProcessAttributePartL( NW_String_t* aString, |
|
510 NW_Uint32 aEncoding, |
|
511 NW_Uint16 aStatus ) |
|
512 { |
|
513 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ProcessAttributePartL begin" ) ); |
|
514 |
|
515 NW_Ucs2 *ucs2Value = NULL; |
|
516 HBufC* attribute = NULL; |
|
517 if ( aStatus == KParseStatusOk ) |
|
518 { |
|
519 NW_String_stringToUCS2Char( aString, aEncoding, &ucs2Value ); |
|
520 if ( !ucs2Value ) |
|
521 { |
|
522 NW_String_deleteStorage( aString ); |
|
523 //User::Leave( KErrCorrupt ); |
|
524 attribute = HBufC::NewL(1); |
|
525 TPtr aptr(attribute->Des()); |
|
526 aptr.Append(_L("")); |
|
527 return attribute; |
|
528 } |
|
529 TPtrC attribValuePtr( ucs2Value ); |
|
530 attribute = attribValuePtr.Alloc(); |
|
531 if( !attribute ) // mem alloc failed |
|
532 { |
|
533 free( ucs2Value ); |
|
534 NW_String_deleteStorage( aString ); |
|
535 User::Leave( KErrNoMemory ); |
|
536 } |
|
537 } |
|
538 else |
|
539 { |
|
540 NW_String_deleteStorage( aString ); |
|
541 User::Leave( KErrCorrupt ); |
|
542 } |
|
543 // clean attribute value |
|
544 free( ucs2Value ); |
|
545 NW_String_deleteStorage( aString ); |
|
546 |
|
547 FLOG( _L( "[ProvisioningParser] CWPWbxmlParser::ProcessAttributePartL end" ) ); |
|
548 return attribute; |
|
549 } |
|
550 |
|
551 // End of File |