|
1 /* |
|
2 * Copyright (c) 2008 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: XML SAX Parser for UPnP. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 // INCLUDE FILES |
|
24 // xml parser |
|
25 #include <xml/parser.h> |
|
26 #include <xml/parserfeature.h> |
|
27 #include <xml/matchdata.h> |
|
28 |
|
29 // upnp stack api |
|
30 #include <upnpstring.h> |
|
31 |
|
32 // upnpframework / xmlparser api |
|
33 #include "upnpxmlparserlite.h" |
|
34 #include "upnpobjectlite.h" |
|
35 |
|
36 // xmlparser internal |
|
37 #include "upnpobjectstacklite.h" |
|
38 |
|
39 |
|
40 _LIT( KComponentLogfile, "upnpxmlparser.txt"); |
|
41 #include "upnplog.h" |
|
42 |
|
43 _LIT8( KXmlMimeType, "text/xml" ); |
|
44 _LIT8( KLIB2XML, "libxml2" ); |
|
45 |
|
46 _LIT8( KContainer, "container" ); |
|
47 _LIT8( KItem, "item" ); |
|
48 _LIT8( KTitle, "title" ); |
|
49 _LIT8( KClass, "class" ); |
|
50 _LIT8( KId, "id" ); |
|
51 //_LIT8( KComma, ":" ); |
|
52 _LIT8( KDIDL, "DIDL-Lite" ); |
|
53 _LIT8( KDesc, "desc" ); |
|
54 _LIT8( KDlnaDoc, "X_DLNADOC" ); |
|
55 |
|
56 _LIT( KIndexContainer, "1" ); |
|
57 _LIT( KIndexAudio, "2" ); |
|
58 _LIT( KIndexVideo, "3" ); |
|
59 _LIT( KIndexImage, "4" ); |
|
60 _LIT( KIndexOther, "5" ); |
|
61 |
|
62 // -------------------------------------------------------------------------- |
|
63 // CUPnPXMLParserLite::CUPnPXMLParserLite() |
|
64 // See upnpxmlparser.h |
|
65 // -------------------------------------------------------------------------- |
|
66 CUPnPXMLParserLite::CUPnPXMLParserLite() |
|
67 { |
|
68 } |
|
69 |
|
70 // -------------------------------------------------------------------------- |
|
71 // CUPnPXMLParserLite::ConstructL |
|
72 // See upnpxmlparser.h |
|
73 // -------------------------------------------------------------------------- |
|
74 void CUPnPXMLParserLite::ConstructL() |
|
75 { |
|
76 __LOG( "CUPnPXMLParserLite::CostructL" ); |
|
77 iStack = CUPnPObjectStackLite::NewL(); |
|
78 } |
|
79 |
|
80 // -------------------------------------------------------------------------- |
|
81 // CUPnPXMLParserLite::NewL |
|
82 // See upnpxmlparser.h |
|
83 // -------------------------------------------------------------------------- |
|
84 EXPORT_C CUPnPXMLParserLite* CUPnPXMLParserLite::NewL() |
|
85 { |
|
86 CUPnPXMLParserLite* self = CUPnPXMLParserLite::NewLC(); |
|
87 CleanupStack::Pop( self ); |
|
88 return self; |
|
89 } |
|
90 |
|
91 |
|
92 // -------------------------------------------------------------------------- |
|
93 // CUPnPXMLParserLite::NewLC |
|
94 // See upnpxmlparser.h |
|
95 // -------------------------------------------------------------------------- |
|
96 EXPORT_C CUPnPXMLParserLite* CUPnPXMLParserLite::NewLC() |
|
97 { |
|
98 CUPnPXMLParserLite* self = new( ELeave ) CUPnPXMLParserLite(); |
|
99 CleanupStack::PushL( self ); |
|
100 self->ConstructL(); |
|
101 return self; |
|
102 } |
|
103 |
|
104 // -------------------------------------------------------------------------- |
|
105 // CUPnPXMLParserLite::~CUPnPXMLParserLite |
|
106 // See upnpxmlparser.h |
|
107 // -------------------------------------------------------------------------- |
|
108 CUPnPXMLParserLite::~CUPnPXMLParserLite() |
|
109 { |
|
110 __LOG( "CUPnPXMLParserLite::~CUPnPXMLParserLite" ); |
|
111 if ( iStack ) |
|
112 { |
|
113 iStack->ResetAndDestroy(); |
|
114 delete iStack; |
|
115 } |
|
116 |
|
117 delete iElementValue; |
|
118 delete iFormatString; |
|
119 delete iTitleBuf; |
|
120 } |
|
121 |
|
122 // -------------------------------------------------------------------------- |
|
123 // CUPnPXMLParserLite::ParseResultDataL |
|
124 // See upnpxmlparser.h |
|
125 // -------------------------------------------------------------------------- |
|
126 EXPORT_C void CUPnPXMLParserLite::ParseResultDataL( |
|
127 RPointerArray<CUpnpObjectLite>& aResultArray, const TDesC8& aData, |
|
128 const TDesC& aFormatString ) |
|
129 { |
|
130 __LOG( "CUPnPXMLParserLite::ParseResultDataL, begin" ); |
|
131 |
|
132 delete iFormatString; iFormatString = NULL; |
|
133 if( aFormatString != KNullDesC ) |
|
134 { |
|
135 iFormatString = aFormatString.AllocL(); |
|
136 } |
|
137 |
|
138 if ( !aData.Length() ) |
|
139 { |
|
140 User::Leave( KErrArgument ); |
|
141 } |
|
142 |
|
143 iResultRoot = &aResultArray; |
|
144 |
|
145 // Create parser |
|
146 CMatchData* matchData = CMatchData::NewLC(); |
|
147 matchData->SetMimeTypeL( KXmlMimeType ); |
|
148 matchData->SetVariantL( KLIB2XML ); |
|
149 CParser* parser = CParser::NewLC( *matchData, *this ); |
|
150 parser->EnableFeature( Xml::EReportNamespaceMapping ); |
|
151 |
|
152 Xml::ParseL( *parser, aData ); |
|
153 |
|
154 CleanupStack::PopAndDestroy( parser ); |
|
155 CleanupStack::PopAndDestroy( matchData ); |
|
156 |
|
157 iResultRoot = NULL; |
|
158 __LOG( "CUPnPXMLParserLite::ParseResultDataL, end" ); |
|
159 } |
|
160 |
|
161 // -------------------------------------------------------------------------- |
|
162 // CUPnPXMLParserLite::OnStartDocumentL |
|
163 // See upnpxmlparser.h |
|
164 // -------------------------------------------------------------------------- |
|
165 void CUPnPXMLParserLite::OnStartDocumentL( |
|
166 const RDocumentParameters& /*aDocParam*/, |
|
167 TInt /*aErrorCode*/ ) |
|
168 { |
|
169 // No implementation needed |
|
170 } |
|
171 |
|
172 // -------------------------------------------------------------------------- |
|
173 // CUPnPXMLParserLite::OnEndDocumentL |
|
174 // See upnpxmlparser.h |
|
175 // -------------------------------------------------------------------------- |
|
176 void CUPnPXMLParserLite::OnEndDocumentL( TInt /*aErrorCode*/ ) |
|
177 { |
|
178 // No implementation needed |
|
179 } |
|
180 |
|
181 // -------------------------------------------------------------------------- |
|
182 // CUPnPXMLParserLite::OnStartElementL |
|
183 // See upnpxmlparser.h |
|
184 // -------------------------------------------------------------------------- |
|
185 void CUPnPXMLParserLite::OnStartElementL( const RTagInfo& aElement, |
|
186 const RAttributeArray& aAttributes, |
|
187 TInt aErrorCode ) |
|
188 { |
|
189 __LOG1( "CUPnPXMLParserLite::OnStartElementL, error code: %d", aErrorCode ); |
|
190 if ( aErrorCode != KErrNone ) |
|
191 { |
|
192 return; |
|
193 } |
|
194 const TDesC8& desName = aElement.LocalName().DesC(); |
|
195 const TDesC8& prefix = aElement.Prefix().DesC(); |
|
196 |
|
197 // Delete content, since there may be some stuff between the elements |
|
198 // (comments, whitespace etc.) |
|
199 delete iElementValue; iElementValue = NULL; |
|
200 |
|
201 if ( !desName.CompareF( KContainer ) ) // Container element |
|
202 { |
|
203 CUpnpObjectLite* tmpContainer = CUpnpObjectLite::NewL(); |
|
204 CleanupStack::PushL( tmpContainer ); |
|
205 |
|
206 SetAttributesL( *tmpContainer, aAttributes ); |
|
207 //push into the stack, ownership is transferred |
|
208 iStack->PushL( tmpContainer ); |
|
209 |
|
210 CleanupStack::Pop( tmpContainer ); |
|
211 } |
|
212 else if ( !desName.CompareF( KItem ) ) // Item element |
|
213 { |
|
214 CUpnpObjectLite* tmpItem = CUpnpObjectLite::NewL(); |
|
215 CleanupStack::PushL( tmpItem ); |
|
216 |
|
217 SetAttributesL( *tmpItem, aAttributes ); |
|
218 //push into the stack, ownership is transferred |
|
219 iStack->PushL( tmpItem ); |
|
220 |
|
221 CleanupStack::Pop( tmpItem ); |
|
222 } |
|
223 else if( !desName.CompareF( KTitle ) ) // Title element |
|
224 { |
|
225 // check that we have item or container. cause leave if not |
|
226 if ( iStack->Count() == 0) |
|
227 { |
|
228 User::Leave( KErrArgument ); |
|
229 } |
|
230 // We should have an item or a container already! |
|
231 //__ASSERTD( iStack->Top(), __FILE__, __LINE__ ); |
|
232 iTitle = ETrue; |
|
233 } |
|
234 else if( !desName.CompareF( KClass ) ) // Object class element |
|
235 { |
|
236 // check that we have item or container. cause leave if not |
|
237 if ( iStack->Count() == 0) |
|
238 { |
|
239 User::Leave( KErrArgument ); |
|
240 } |
|
241 // We should have an item or a container already! |
|
242 //__ASSERTD( iStack->Top(), __FILE__, __LINE__ ); |
|
243 iObjectClass = ETrue; |
|
244 } |
|
245 // Ignore DIDL-Lite, desc and X_DLNADOC -elements (DLNA req) |
|
246 else if( desName.Compare( KDIDL ) == KErrNone || |
|
247 desName.Compare( KDesc ) == KErrNone || |
|
248 desName.Compare( KDlnaDoc ) == KErrNone |
|
249 ) |
|
250 { |
|
251 // Ignore |
|
252 } |
|
253 else |
|
254 { |
|
255 // check that we have item or container. cause leave if not |
|
256 if ( iStack->Count() == 0) |
|
257 { |
|
258 User::Leave( KErrArgument ); |
|
259 } |
|
260 // Ignore rest of the elements |
|
261 } |
|
262 __LOG( "CUPnPXMLParserLite::OnStartElementL, end" ); |
|
263 } |
|
264 |
|
265 // -------------------------------------------------------------------------- |
|
266 // CUPnPXMLParserLite::OnEndElementL |
|
267 // See upnpxmlparser.h |
|
268 // -------------------------------------------------------------------------- |
|
269 void CUPnPXMLParserLite::OnEndElementL( const RTagInfo& aElement, |
|
270 TInt aErrorCode ) |
|
271 { |
|
272 __LOG( "CUPnPXMLParserLite::OnEndElementL(), begin" ); |
|
273 if ( aErrorCode != KErrNone ) |
|
274 { |
|
275 return; |
|
276 } |
|
277 |
|
278 const TDesC8& desName = aElement.LocalName().DesC(); |
|
279 if ( !desName.CompareF( KContainer ) || !desName.CompareF( KItem ) ) |
|
280 { |
|
281 if( iTitleBuf ) |
|
282 { |
|
283 CUpnpObjectLite* obj = iStack->Top(); |
|
284 __ASSERTD( obj, __FILE__, __LINE__ ); |
|
285 |
|
286 if( iFormatString ) |
|
287 { |
|
288 HBufC* tempBuf = UpnpString::ToUnicodeL( *iTitleBuf ); |
|
289 CleanupStack::PushL( tempBuf ); |
|
290 HBufC* buf = HBufC::NewL( iFormatString->Length() + |
|
291 tempBuf->Length() ); |
|
292 buf->Des().Format( *iFormatString, tempBuf ); |
|
293 CleanupStack::PopAndDestroy( tempBuf ); |
|
294 obj->SetTitleL( buf ); |
|
295 } |
|
296 else |
|
297 { |
|
298 HBufC* buf = HBufC::NewL( iTitleBuf->Length() ); |
|
299 buf->Des().Copy( *iTitleBuf ); |
|
300 obj->SetTitleL( buf ); |
|
301 } |
|
302 delete iTitleBuf; iTitleBuf = NULL; |
|
303 } |
|
304 |
|
305 iResultRoot->AppendL( iStack->Top() ); |
|
306 iStack->Pop(); // Remove object from stack. |
|
307 } |
|
308 else if( KErrNone != desName.CompareF( KDIDL )) |
|
309 { |
|
310 CUpnpObjectLite* obj = iStack->Top(); |
|
311 __ASSERTD( obj, __FILE__, __LINE__ ); |
|
312 |
|
313 if ( iElementValue ) |
|
314 { |
|
315 if( !desName.CompareF( KTitle ) ) |
|
316 { |
|
317 delete iTitleBuf; iTitleBuf = NULL; |
|
318 iTitleBuf = iElementValue; |
|
319 iElementValue = NULL; |
|
320 } |
|
321 else if( !desName.CompareF( KClass ) ) |
|
322 { |
|
323 obj->SetObjectClass( *iElementValue ); |
|
324 iObjectClass = EFalse; |
|
325 if( iFormatString ) |
|
326 { |
|
327 SetIconIndex( *obj ); |
|
328 } |
|
329 } |
|
330 else |
|
331 { |
|
332 } |
|
333 } |
|
334 else |
|
335 { |
|
336 } |
|
337 |
|
338 delete iElementValue; iElementValue = NULL; |
|
339 } |
|
340 __LOG( "CUPnPXMLParserLite::OnEndElementL(), end" ); |
|
341 } |
|
342 |
|
343 // -------------------------------------------------------------------------- |
|
344 // CUPnPXMLParserLite::OnContentL |
|
345 // See upnpxmlparser.h |
|
346 // -------------------------------------------------------------------------- |
|
347 void CUPnPXMLParserLite::OnContentL( const TDesC8& aBytes, TInt aErrorCode ) |
|
348 { |
|
349 __LOG( "CUPnPXMLParserLite::OnContentL(), begin" ); |
|
350 if ( !iStack->Count() || aErrorCode != KErrNone ) |
|
351 { |
|
352 return; |
|
353 } |
|
354 |
|
355 if( iTitle || iObjectClass ) // We are only interested in title or |
|
356 // object class! |
|
357 { |
|
358 if( !iElementValue ) //if 1st time |
|
359 { |
|
360 iElementValue = HBufC8::NewL(aBytes.Length()); |
|
361 iElementValue->Des().Copy(aBytes); |
|
362 } |
|
363 else |
|
364 { |
|
365 HBufC8* previousValue = iElementValue; |
|
366 iElementValue = HBufC8::NewL( previousValue->Des().Length() + |
|
367 aBytes.Length() ); |
|
368 iElementValue->Des().Append( *previousValue ); |
|
369 iElementValue->Des().Append( aBytes ); |
|
370 delete previousValue; |
|
371 } |
|
372 } |
|
373 |
|
374 __LOG( "CUPnPXMLParserLite::OnContentL(), end" ); |
|
375 } |
|
376 |
|
377 // -------------------------------------------------------------------------- |
|
378 // CUPnPXMLParserLite::OnStartPrefixMappingL |
|
379 // See upnpxmlparser.h |
|
380 // -------------------------------------------------------------------------- |
|
381 void CUPnPXMLParserLite::OnStartPrefixMappingL( const RString& /*aPrefix*/, |
|
382 const RString& /*aUri*/, |
|
383 TInt /*aErrorCode*/ ) |
|
384 { |
|
385 // No implementation needed |
|
386 } |
|
387 |
|
388 // -------------------------------------------------------------------------- |
|
389 // CUPnPXMLParserLite::OnEndPrefixMappingL |
|
390 // See upnpxmlparser.h |
|
391 // -------------------------------------------------------------------------- |
|
392 void CUPnPXMLParserLite::OnEndPrefixMappingL( const RString& /*aPrefix*/, |
|
393 TInt /*aErrorCode*/ ) |
|
394 { |
|
395 // No implementation needed |
|
396 } |
|
397 |
|
398 // -------------------------------------------------------------------------- |
|
399 // CUPnPXMLParserLite::OnIgnorableWhiteSpaceL |
|
400 // See upnpxmlparser.h |
|
401 // -------------------------------------------------------------------------- |
|
402 void CUPnPXMLParserLite::OnIgnorableWhiteSpaceL( const TDesC8& /*aBytes*/, |
|
403 TInt /*aErrorCode*/ ) |
|
404 { |
|
405 // No implementation needed |
|
406 } |
|
407 |
|
408 // -------------------------------------------------------------------------- |
|
409 // CUPnPXMLParserLite::OnSkippedEntityL |
|
410 // See upnpxmlparser.h |
|
411 // -------------------------------------------------------------------------- |
|
412 void CUPnPXMLParserLite::OnSkippedEntityL( const RString& /*aName*/, |
|
413 TInt /*aErrorCode*/ ) |
|
414 { |
|
415 // No implementation needed |
|
416 } |
|
417 |
|
418 // -------------------------------------------------------------------------- |
|
419 // CUPnPXMLParserLite::OnProcessingInstructionL |
|
420 // See upnpxmlparser.h |
|
421 // -------------------------------------------------------------------------- |
|
422 void CUPnPXMLParserLite::OnProcessingInstructionL( const TDesC8& /*aTarget*/, |
|
423 const TDesC8& /*aData*/, |
|
424 TInt /*aErrorCode*/ ) |
|
425 { |
|
426 // No implementation needed |
|
427 } |
|
428 |
|
429 // -------------------------------------------------------------------------- |
|
430 // CUPnPXMLParserLite::OnError |
|
431 // See upnpxmlparser.h |
|
432 // -------------------------------------------------------------------------- |
|
433 void CUPnPXMLParserLite::OnError( TInt /*aErrorCode*/ ) |
|
434 { |
|
435 // No implementation needed |
|
436 } |
|
437 |
|
438 // -------------------------------------------------------------------------- |
|
439 // CUPnPXMLParserLite::GetExtendedInterface |
|
440 // See upnpxmlparser.h |
|
441 // -------------------------------------------------------------------------- |
|
442 TAny* CUPnPXMLParserLite::GetExtendedInterface( const TInt32 /*aUid*/ ) |
|
443 { |
|
444 // No implementation needed |
|
445 return NULL; |
|
446 } |
|
447 |
|
448 // -------------------------------------------------------------------------- |
|
449 // CUPnPXMLParserLite::SetAttributesL |
|
450 // See upnpxmlparser.h |
|
451 // -------------------------------------------------------------------------- |
|
452 void CUPnPXMLParserLite::SetAttributesL( CUpnpObjectLite& aObject, |
|
453 const RAttributeArray& aAttributes ) |
|
454 { |
|
455 __LOG( "CUPnPXMLParserLite::SetAttributesL" ); |
|
456 |
|
457 if ( iStack->Count() ) |
|
458 { |
|
459 // Object has a parent. |
|
460 // Should not really happen |
|
461 __LOG( "Object has a parent!" ); |
|
462 __PANICD(__FILE__, __LINE__); |
|
463 } |
|
464 |
|
465 RAttribute attribute; |
|
466 TInt count = aAttributes.Count(); |
|
467 for ( TInt i = 0 ; i < count; i++ ) // Read attributes. |
|
468 { |
|
469 attribute = aAttributes[ i ]; |
|
470 const TDesC8& name = attribute.Attribute().LocalName().DesC(); |
|
471 |
|
472 if( !name.CompareF( KId ) ) |
|
473 { |
|
474 aObject.SetObjectIdL( attribute.Value().DesC() ); |
|
475 } |
|
476 } |
|
477 __LOG( "CUPnPXMLParserLite::SetAttributesL - End" ); |
|
478 } |
|
479 |
|
480 void CUPnPXMLParserLite::SetIconIndex( const CUpnpObjectLite& aObject ) |
|
481 { |
|
482 if( aObject.IsTypeOf( CUpnpObjectLite::EContainer ) ) |
|
483 { |
|
484 iFormatString->Des().Replace( 0, 1, KIndexContainer ); |
|
485 } |
|
486 else if( aObject.IsTypeOf( CUpnpObjectLite::EMusicItem ) ) |
|
487 { |
|
488 iFormatString->Des().Replace( 0, 1, KIndexAudio ); |
|
489 } |
|
490 else if( aObject.IsTypeOf( CUpnpObjectLite::EImageItem ) ) |
|
491 { |
|
492 iFormatString->Des().Replace( 0, 1, KIndexImage ); |
|
493 } |
|
494 else if( aObject.IsTypeOf( CUpnpObjectLite::EVideoItem ) ) |
|
495 { |
|
496 iFormatString->Des().Replace( 0, 1, KIndexVideo ); |
|
497 } |
|
498 else |
|
499 { |
|
500 // Other |
|
501 iFormatString->Des().Replace( 0, 1, KIndexOther ); |
|
502 } |
|
503 } |
|
504 |
|
505 // end of file |
|
506 |
|
507 |