upnpavcontroller/upnpxmlparser/src/upnpitemtoxml.cpp
changeset 0 7f85d04be362
child 38 5360b7ddc251
equal deleted inserted replaced
-1:000000000000 0:7f85d04be362
       
     1 /*
       
     2 * Copyright (c) 2005 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:      generates XML from an UPNP item
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 // INCLUDE FILES
       
    24 // System
       
    25 #include <e32base.h>
       
    26 
       
    27 // upnp stack api
       
    28 #include <upnpstring.h>
       
    29 #include <upnpitem.h>
       
    30 #include <upnpdlnaprotocolinfo.h>
       
    31 
       
    32 // upnpframework / avcontroller helper api
       
    33 #include "upnpconstantdefs.h" // for upnp definitions
       
    34 #include "upnpitemutility.h"
       
    35 
       
    36 // xmlparser internal
       
    37 #include "upnpitemtoxml.h"
       
    38 
       
    39 _LIT( KComponentLogfile, "upnpxmlparser.txt");
       
    40 #include "upnplog.h"
       
    41 
       
    42 // CONSTANTS
       
    43 _LIT8(KItemHeading1,            "<item id=\"");
       
    44 _LIT8(KItemHeading2,            "\" parentID=\"");
       
    45 _LIT8(KItemHeading3False,       "\" restricted=\"0\">");
       
    46 _LIT8(KItemHeading3True,        "\" restricted=\"1\">");
       
    47 _LIT8(KItemTitleBegin,          "<dc:title>");
       
    48 _LIT8(KItemTitleEnd,            "</dc:title>");
       
    49 _LIT8(KItemDateBegin,           "<dc:date>");
       
    50 _LIT8(KItemDateEnd,             "</dc:date>");
       
    51 _LIT8(KItemClassBegin,          "<upnp:class>");
       
    52 _LIT8(KItemClassEnd,            "</upnp:class>");
       
    53 _LIT8(KItemPInfoEmpty,          "<res protocolInfo=\"*:*:*:*\"></res>");
       
    54 _LIT8(KItemPInfoEmptyDlna,      "<res protocolInfo=\"*:*:");
       
    55 _LIT8(KDlnaPn,                  "DLNA.ORG_PN=" );
       
    56 _LIT8(KColon,                   ":"); 
       
    57 _LIT8(KItemPInfoBegin,          "<res protocolInfo=\"");
       
    58 _LIT8(KItemPInfoMiddle,         ">");
       
    59 _LIT8(KItemPInfoEnd,            "</res>");
       
    60 _LIT8(KItemPInfoEnd2,            "\"></res>");
       
    61 _LIT8(KItemEnd,                 "</item>");
       
    62 
       
    63 _LIT8(KQuotationMark,           "\" ");
       
    64 _LIT8(KItemSize,                "size=\"");
       
    65 _LIT8(KItemDuration,            "duration=\"");
       
    66 _LIT8(KItemResolution,          "resolution=\"");
       
    67 
       
    68 // Music metadata
       
    69 _LIT8(KItemArtistBegin,         "<upnp:artist>");
       
    70 _LIT8(KItemArtistEnd,           "</upnp:artist>");
       
    71 _LIT8(KItemCreatorBegin,        "<dc:creator>");
       
    72 _LIT8(KItemCreatorEnd,          "</dc:creator>");
       
    73 _LIT8(KItemAlbumBegin,          "<upnp:album>");
       
    74 _LIT8(KItemAlbumEnd,            "</upnp:album>");
       
    75 _LIT8(KItemGenreBegin,          "<upnp:genre>");
       
    76 _LIT8(KItemGenreEnd,            "</upnp:genre>");
       
    77 _LIT8(KItemAlbumArtURIBegin,    "<upnp:albumArtURI>");
       
    78 _LIT8(KItemAlbumArtURIEnd,      "</upnp:albumArtURI>");
       
    79 
       
    80 _LIT8(KDIDLBeginXmlEscaped,
       
    81     "&lt;DIDL-Lite "
       
    82     "xmlns=&quot;urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/&quot; "
       
    83     "xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; "
       
    84     "xmlns:upnp=&quot;urn:schemas-upnp-org:metadata-1-0/upnp/&quot;"
       
    85     "&gt;");
       
    86 _LIT8(KDIDLEndXmlEscaped, "&lt;/DIDL-Lite&gt;");
       
    87 
       
    88 _LIT8( KAsterisk, "*" );
       
    89 
       
    90 const TInt KBufLen = 256;
       
    91 const TInt KDateStringLength        = 10;
       
    92 const TInt KDateTimeStringLength    = 19;
       
    93 const TInt KMaxDateStringLength     = 30;
       
    94 const TInt KSeparatorAscii          = 58;
       
    95 
       
    96 
       
    97 // ============================ MEMBER FUNCTIONS ============================
       
    98 
       
    99 // --------------------------------------------------------------------------
       
   100 // CUpnpItemToXML::CUpnpItemToXML
       
   101 // C++ default constructor can NOT contain any code, that
       
   102 // might leave.
       
   103 // --------------------------------------------------------------------------
       
   104 CUpnpItemToXML::CUpnpItemToXML( const CUpnpItem& aItem ) :
       
   105     iItem( const_cast<CUpnpItem*>(&aItem) )
       
   106     {
       
   107     }
       
   108 
       
   109 // --------------------------------------------------------------------------
       
   110 // CUpnpItemToXML::ConstructL
       
   111 // Symbian 2nd phase constructor can leave.
       
   112 // --------------------------------------------------------------------------
       
   113 void CUpnpItemToXML::ConstructL()
       
   114     {
       
   115     }
       
   116 
       
   117 
       
   118 // --------------------------------------------------------------------------
       
   119 // CUpnpItemToXML::NewL
       
   120 // Two-phased constructor.
       
   121 // --------------------------------------------------------------------------
       
   122 CUpnpItemToXML* CUpnpItemToXML::NewL( const CUpnpItem& aItem )
       
   123     {
       
   124     CUpnpItemToXML* self = CUpnpItemToXML::NewLC( aItem );
       
   125     
       
   126     CleanupStack::Pop();
       
   127 
       
   128     return self;
       
   129     }
       
   130 
       
   131 // --------------------------------------------------------------------------
       
   132 // CUpnpItemToXML::NewLC
       
   133 // Two-phased constructor.
       
   134 // --------------------------------------------------------------------------
       
   135 CUpnpItemToXML* CUpnpItemToXML::NewLC( const CUpnpItem& aItem )
       
   136     {
       
   137     CUpnpItemToXML* self = new( ELeave ) CUpnpItemToXML( aItem );
       
   138     
       
   139     CleanupStack::PushL( self );
       
   140     self->ConstructL();
       
   141     
       
   142     return self;
       
   143     }
       
   144     
       
   145 // Destructor
       
   146 CUpnpItemToXML::~CUpnpItemToXML()
       
   147     {
       
   148     }
       
   149 
       
   150 
       
   151 // --------------------------------------------------------------------------
       
   152 // CUpnpItemToXML::AsXmlL
       
   153 // Returns XML buffer
       
   154 // (other items were commented in a header).
       
   155 // --------------------------------------------------------------------------
       
   156 HBufC8* CUpnpItemToXML::AsXmlL( const TBool /*aIncludeChilds = ETrue */ ) 
       
   157     {
       
   158     __LOG( "CUpnpItemToXML::AsXmlL" );
       
   159     
       
   160     const TInt bufferSize = 64; // Buffer size, grows dynamicly in 64b steps
       
   161     CBufFlat *pBuf = CBufFlat::NewL( bufferSize );
       
   162     CleanupStack::PushL( pBuf );
       
   163 
       
   164     RBufWriteStream stream( *pBuf );
       
   165     CleanupClosePushL( stream );
       
   166 
       
   167     // Then add the actual data
       
   168     stream.WriteL( KItemHeading1() );
       
   169     // xml encoding added
       
   170     HBufC8* encodeTemp = HBufC8::NewLC( iItem->Id().Length() );
       
   171     encodeTemp->Des().Copy( iItem->Id() );
       
   172 
       
   173     HBufC8* tempPtr = NULL;
       
   174     tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   175     CleanupStack::PushL( tempPtr );
       
   176 
       
   177     stream.WriteL( *tempPtr );
       
   178     CleanupStack::PopAndDestroy( tempPtr );
       
   179     tempPtr = NULL;
       
   180 
       
   181     CleanupStack::PopAndDestroy( encodeTemp );
       
   182     encodeTemp = NULL;
       
   183 
       
   184     stream.WriteL( KItemHeading2() );
       
   185 
       
   186     stream.WriteL( iItem->ParentId() );
       
   187     if (iItem->Restricted())
       
   188         {
       
   189         stream.WriteL( KItemHeading3True() );
       
   190         }
       
   191     else
       
   192         {
       
   193         stream.WriteL( KItemHeading3False() );
       
   194         }
       
   195     stream.WriteL( KItemTitleBegin() );
       
   196 
       
   197     // xml encoding added
       
   198     encodeTemp = HBufC8::NewLC( iItem->Title().Length() );
       
   199     encodeTemp->Des().Copy( iItem->Title() );
       
   200     
       
   201     tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   202     CleanupStack::PushL( tempPtr );
       
   203 
       
   204     stream.WriteL( *tempPtr );
       
   205     CleanupStack::PopAndDestroy( tempPtr );
       
   206     tempPtr = NULL;
       
   207     
       
   208     CleanupStack::PopAndDestroy( encodeTemp );
       
   209     encodeTemp = NULL;    
       
   210     
       
   211     stream.WriteL( KItemTitleEnd() );
       
   212     stream.WriteL( KItemClassBegin() );
       
   213 
       
   214     stream.WriteL( iItem->ObjectClass() );
       
   215     stream.WriteL( KItemClassEnd() );
       
   216     
       
   217      // Music meta data information
       
   218     const TDesC8& artist = GetValueFromElement( KElementArtist ); 
       
   219     if ( artist != KNullDesC8 )
       
   220 
       
   221         {
       
   222         stream.WriteL( KItemArtistBegin );
       
   223         // xml encoding added
       
   224         encodeTemp = HBufC8::NewLC( artist.Length() );
       
   225         encodeTemp->Des().Copy( artist );
       
   226 
       
   227         tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   228         CleanupStack::PushL( tempPtr );
       
   229 
       
   230         stream.WriteL( *tempPtr );
       
   231         CleanupStack::PopAndDestroy( tempPtr );
       
   232         tempPtr = NULL;
       
   233         
       
   234         CleanupStack::PopAndDestroy( encodeTemp );
       
   235         encodeTemp = NULL;
       
   236 
       
   237         stream.WriteL( KItemArtistEnd );
       
   238         }
       
   239     const TDesC8& creator = GetValueFromElement( KElementCreator ); 
       
   240     if ( creator != KNullDesC8 )
       
   241         {
       
   242         stream.WriteL( KItemCreatorBegin );
       
   243         // xml encoding added
       
   244         encodeTemp = HBufC8::NewLC( creator.Length() );
       
   245         encodeTemp->Des().Copy( creator );
       
   246 
       
   247         tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   248         CleanupStack::PushL( tempPtr );
       
   249 
       
   250         stream.WriteL( *tempPtr );
       
   251         CleanupStack::PopAndDestroy( tempPtr );
       
   252         tempPtr = NULL;
       
   253         
       
   254         CleanupStack::PopAndDestroy( encodeTemp );
       
   255         encodeTemp = NULL;
       
   256 
       
   257         stream.WriteL( KItemCreatorEnd );
       
   258         }
       
   259     const TDesC8& album = GetValueFromElement( KElementAlbum ); 
       
   260     if ( album != KNullDesC8 )
       
   261         {
       
   262         stream.WriteL( KItemAlbumBegin );
       
   263         // xml encoding added
       
   264         encodeTemp = HBufC8::NewLC( album.Length() );
       
   265         encodeTemp->Des().Copy( album );
       
   266         
       
   267         tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   268         CleanupStack::PushL( tempPtr );
       
   269 
       
   270         stream.WriteL( *tempPtr );
       
   271         CleanupStack::PopAndDestroy( tempPtr );
       
   272         tempPtr = NULL;
       
   273     
       
   274         CleanupStack::PopAndDestroy( encodeTemp );
       
   275         encodeTemp = NULL;
       
   276         //stream.WriteL( Album() );
       
   277         stream.WriteL( KItemAlbumEnd );
       
   278         }
       
   279     const TDesC8& genre = GetValueFromElement( KElementGenre );     
       
   280     if ( genre != KNullDesC8 )
       
   281         {
       
   282         stream.WriteL( KItemGenreBegin );
       
   283         // xml encoding added
       
   284         encodeTemp = HBufC8::NewLC( genre.Length() );
       
   285         encodeTemp->Des().Copy( genre );
       
   286 
       
   287         tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   288         CleanupStack::PushL( tempPtr );
       
   289 
       
   290         stream.WriteL( *tempPtr );
       
   291         CleanupStack::PopAndDestroy( tempPtr );
       
   292         tempPtr = NULL;
       
   293     
       
   294         CleanupStack::PopAndDestroy( encodeTemp );
       
   295         encodeTemp = NULL;
       
   296         //stream.WriteL( Genre() );
       
   297         stream.WriteL( KItemGenreEnd );
       
   298         } 
       
   299     const TDesC8& albumarturi = GetValueFromElement( KElementAlbumArtUri );     
       
   300     if ( albumarturi != KNullDesC8 )
       
   301         {
       
   302         stream.WriteL( KItemAlbumArtURIBegin );
       
   303         // xml encoding added
       
   304         encodeTemp = HBufC8::NewLC( albumarturi.Length() );
       
   305         encodeTemp->Des().Copy( albumarturi );
       
   306 
       
   307         tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   308         CleanupStack::PushL( tempPtr );
       
   309 
       
   310         stream.WriteL( *tempPtr );
       
   311         CleanupStack::PopAndDestroy( tempPtr );
       
   312         tempPtr = NULL;
       
   313     
       
   314         CleanupStack::PopAndDestroy( encodeTemp );
       
   315         encodeTemp = NULL;        
       
   316         stream.WriteL( KItemAlbumArtURIEnd );
       
   317         }
       
   318     const TDesC8& date = GetValueFromElement( KElementDate );         
       
   319     if ( date != KNullDesC8 )
       
   320         {        
       
   321         if( ValidateDateL( date ) )
       
   322             {
       
   323             stream.WriteL( KItemDateBegin );
       
   324             // xml encoding added
       
   325             encodeTemp = HBufC8::NewLC( date.Length() );
       
   326             encodeTemp->Des().Copy( date );
       
   327 
       
   328             tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   329             CleanupStack::PushL( tempPtr );
       
   330 
       
   331             stream.WriteL( *tempPtr );
       
   332             CleanupStack::PopAndDestroy( tempPtr );
       
   333             tempPtr = NULL;
       
   334 
       
   335             CleanupStack::PopAndDestroy( encodeTemp );
       
   336             encodeTemp = NULL;
       
   337             stream.WriteL( KItemDateEnd );
       
   338             }
       
   339         }
       
   340  
       
   341     RUPnPElementsArray elArray;
       
   342     CleanupClosePushL( elArray );
       
   343     UPnPItemUtility::GetResElements( *iItem, elArray );
       
   344     TInt count = elArray.Count();
       
   345     for( TInt i = 0; i < count; i++ )
       
   346         {
       
   347         // Res-element starts
       
   348         stream.WriteL( KItemPInfoBegin );
       
   349         
       
   350         const CUpnpAttribute* attrproinfo = UPnPItemUtility
       
   351             ::FindAttributeByName( *elArray[ i ], KAttributeProtocolInfo );
       
   352         if ( attrproinfo )
       
   353             {        
       
   354             stream.WriteL( attrproinfo->Value() );
       
   355             stream.WriteL( KCriteriaQuot );
       
   356             stream.WriteL( KCriteriaSpace );
       
   357             }
       
   358         const CUpnpAttribute* attrsize = UPnPItemUtility
       
   359             ::FindAttributeByName( *elArray[ i ], KAttributeSize );            
       
   360         if ( attrsize )
       
   361             {
       
   362             stream.WriteL( KAttributeSize );
       
   363             stream.WriteL( KCriteriaEQ );
       
   364             stream.WriteL( KCriteriaQuot );
       
   365             stream.WriteL( attrsize->Value() );
       
   366             stream.WriteL( KCriteriaQuot );
       
   367             stream.WriteL( KCriteriaSpace );                   
       
   368             }         
       
   369         const CUpnpAttribute* attrresolution = UPnPItemUtility
       
   370             ::FindAttributeByName( *elArray[ i ], KAttributeResolution );
       
   371         if ( attrresolution )
       
   372             {
       
   373             stream.WriteL( KAttributeResolution );
       
   374             stream.WriteL( KCriteriaEQ );
       
   375             stream.WriteL( KCriteriaQuot );
       
   376             stream.WriteL( attrresolution->Value() );
       
   377             stream.WriteL( KCriteriaQuot );
       
   378             stream.WriteL( KCriteriaSpace );                        
       
   379             }        
       
   380         const CUpnpAttribute* attrduration = UPnPItemUtility
       
   381             ::FindAttributeByName( *elArray[ i ], KAttributeDuration );        
       
   382         if ( attrduration )
       
   383             {           
       
   384             if( ValidateDurationL( attrduration->Value() ) )
       
   385                 {
       
   386                 stream.WriteL( KAttributeDuration );
       
   387                 stream.WriteL( KCriteriaEQ );
       
   388                 stream.WriteL( KCriteriaQuot );
       
   389                 stream.WriteL( attrduration->Value() );
       
   390                 stream.WriteL( KCriteriaQuot );
       
   391                 stream.WriteL( KCriteriaSpace );
       
   392                 }
       
   393             else
       
   394                 {
       
   395                 // Format of duration is not valid, do not include it
       
   396                 // Fixes ESLX-7AYFD6
       
   397                 }    
       
   398             
       
   399             }        
       
   400         const CUpnpAttribute* attrbitrate = UPnPItemUtility
       
   401             ::FindAttributeByName( *elArray[ i ], KAttributeBitrate );
       
   402         if ( attrbitrate )
       
   403             {
       
   404             stream.WriteL( KAttributeBitrate );
       
   405             stream.WriteL( KCriteriaEQ );
       
   406             stream.WriteL( KCriteriaQuot );
       
   407             stream.WriteL( attrbitrate->Value() );
       
   408             stream.WriteL( KCriteriaQuot );
       
   409             stream.WriteL( KCriteriaSpace );
       
   410             } 
       
   411         stream.WriteL( KItemPInfoMiddle );
       
   412         
       
   413         // Get the content URI
       
   414         encodeTemp = HBufC8::NewLC( elArray[ i ]->Value().Length() );
       
   415         encodeTemp->Des().Copy( elArray[ i ]->Value() );
       
   416 
       
   417         // Encode the content URI
       
   418         tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   419         CleanupStack::PushL( tempPtr );
       
   420 
       
   421         // Write the encoded content URI
       
   422         stream.WriteL( *tempPtr );
       
   423         CleanupStack::PopAndDestroy( tempPtr );
       
   424         tempPtr = NULL;
       
   425         
       
   426         // Clean up
       
   427         CleanupStack::PopAndDestroy( encodeTemp );
       
   428         encodeTemp = NULL;
       
   429         
       
   430         // Res-element ends
       
   431         stream.WriteL( KItemPInfoEnd );
       
   432         }
       
   433     
       
   434     CleanupStack::PopAndDestroy( &elArray );                  
       
   435 
       
   436     stream.WriteL( KItemEnd() );
       
   437 
       
   438     CleanupStack::PopAndDestroy(); // stream.Close();
       
   439 
       
   440     TPtrC8 start = pBuf->Ptr(0);
       
   441 
       
   442     // JLi: Do NOT decode retBuffer since it will be given to XML Parser
       
   443     HBufC8* retBuffer = start.AllocL();
       
   444     CleanupStack::PopAndDestroy( pBuf );
       
   445     
       
   446     return retBuffer;
       
   447     }
       
   448 
       
   449 // --------------------------------------------------------------------------
       
   450 // CUpnpItemToXML::AsXmlEmptyL
       
   451 // Returns object's XML description. This version of the method is used to
       
   452 // create the XML with empty <res> tag.
       
   453 // (other items were commented in a header).
       
   454 // --------------------------------------------------------------------------
       
   455 HBufC8* CUpnpItemToXML::AsXmlEmptyL()
       
   456     {
       
   457     __LOG( "CUpnpItemToXML::AsXmlEmptyL" );
       
   458     
       
   459     const TInt bufferSize = 64; // Buffer size, grows dynamicly in 64b steps
       
   460     CBufFlat *pBuf = CBufFlat::NewL( bufferSize );
       
   461     CleanupStack::PushL( pBuf );
       
   462 
       
   463     RBufWriteStream stream( *pBuf );
       
   464     CleanupClosePushL( stream );
       
   465 
       
   466     // Then add the actual data
       
   467     stream.WriteL( KItemHeading1() );
       
   468     stream.WriteL( iItem->Id() );
       
   469     stream.WriteL( KItemHeading2() );
       
   470     stream.WriteL( iItem->ParentId() );
       
   471     stream.WriteL( KItemHeading3False() );
       
   472     //stream.WriteL( KItemEndTag() );
       
   473     stream.WriteL( KItemTitleBegin() );
       
   474     // xml encode name
       
   475     HBufC8* encodeTemp = HBufC8::NewLC( iItem->Title().Length() );
       
   476     encodeTemp->Des().Copy( iItem->Title() );
       
   477     HBufC8* tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   478     CleanupStack::PushL( tempPtr ); 
       
   479     stream.WriteL( *tempPtr );
       
   480     CleanupStack::PopAndDestroy( tempPtr );
       
   481     CleanupStack::PopAndDestroy( encodeTemp );
       
   482     stream.WriteL( KItemTitleEnd() );
       
   483     stream.WriteL( KItemClassBegin() );
       
   484     
       
   485     stream.WriteL( iItem->ObjectClass() );
       
   486     stream.WriteL( KItemClassEnd() );
       
   487     
       
   488     // Music meta data information
       
   489     const TDesC8& artist = GetValueFromElement( KElementArtist ); 
       
   490     if ( artist != KNullDesC8 )
       
   491         {
       
   492         stream.WriteL( KItemArtistBegin );
       
   493         // xml encoding added
       
   494         encodeTemp = HBufC8::NewLC( artist.Length() );
       
   495         encodeTemp->Des().Copy( artist );
       
   496 
       
   497         tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   498         CleanupStack::PushL( tempPtr );
       
   499 
       
   500         stream.WriteL( *tempPtr );
       
   501         CleanupStack::PopAndDestroy( tempPtr );
       
   502         tempPtr = NULL;
       
   503         
       
   504         CleanupStack::PopAndDestroy( encodeTemp );
       
   505         encodeTemp = NULL;
       
   506 
       
   507         stream.WriteL( KItemArtistEnd );
       
   508         }
       
   509     const TDesC8& creator = GetValueFromElement( KElementCreator ); 
       
   510     if ( creator != KNullDesC8 )
       
   511         {
       
   512         stream.WriteL( KItemCreatorBegin );
       
   513         // xml encoding added
       
   514         encodeTemp = HBufC8::NewLC( creator.Length() );
       
   515         encodeTemp->Des().Copy( creator );
       
   516 
       
   517         tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   518         CleanupStack::PushL( tempPtr );
       
   519 
       
   520         stream.WriteL( *tempPtr );
       
   521         CleanupStack::PopAndDestroy( tempPtr );
       
   522         tempPtr = NULL;
       
   523         
       
   524         CleanupStack::PopAndDestroy( encodeTemp );
       
   525         encodeTemp = NULL;
       
   526 
       
   527         stream.WriteL( KItemCreatorEnd );        
       
   528         }
       
   529     const TDesC8& album = GetValueFromElement( KElementAlbum ); 
       
   530     if ( album != KNullDesC8 )
       
   531         {
       
   532         stream.WriteL( KItemAlbumBegin );
       
   533         // xml encoding added
       
   534         encodeTemp = HBufC8::NewLC( album.Length() );
       
   535         encodeTemp->Des().Copy( album );
       
   536         
       
   537         tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   538         CleanupStack::PushL( tempPtr );
       
   539 
       
   540         stream.WriteL( *tempPtr );
       
   541         CleanupStack::PopAndDestroy( tempPtr );
       
   542         tempPtr = NULL;
       
   543     
       
   544         CleanupStack::PopAndDestroy( encodeTemp );
       
   545         encodeTemp = NULL;
       
   546         //stream.WriteL( Album() );
       
   547         stream.WriteL( KItemAlbumEnd );        
       
   548         }
       
   549     const TDesC8& genre = GetValueFromElement( KElementGenre );     
       
   550     if ( genre != KNullDesC8 )
       
   551         {
       
   552         stream.WriteL( KItemGenreBegin );
       
   553         // xml encoding added
       
   554         encodeTemp = HBufC8::NewLC( genre.Length() );
       
   555         encodeTemp->Des().Copy( genre );
       
   556 
       
   557         tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   558         CleanupStack::PushL( tempPtr );
       
   559 
       
   560         stream.WriteL( *tempPtr );
       
   561         CleanupStack::PopAndDestroy( tempPtr );
       
   562         tempPtr = NULL;
       
   563     
       
   564         CleanupStack::PopAndDestroy( encodeTemp );
       
   565         encodeTemp = NULL;
       
   566         //stream.WriteL( Genre() );
       
   567         stream.WriteL( KItemGenreEnd );        
       
   568         }
       
   569     const TDesC8& albumarturi = GetValueFromElement( KElementAlbumArtUri );     
       
   570     if ( albumarturi != KNullDesC8 )
       
   571         {
       
   572         stream.WriteL( KItemAlbumArtURIBegin );
       
   573         // xml encoding added
       
   574         encodeTemp = HBufC8::NewLC( albumarturi.Length() );
       
   575         encodeTemp->Des().Copy( albumarturi );
       
   576 
       
   577         tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   578         CleanupStack::PushL( tempPtr );
       
   579 
       
   580         stream.WriteL( *tempPtr );
       
   581         CleanupStack::PopAndDestroy( tempPtr );
       
   582         tempPtr = NULL;
       
   583     
       
   584         CleanupStack::PopAndDestroy( encodeTemp );
       
   585         encodeTemp = NULL;       
       
   586         stream.WriteL( KItemAlbumArtURIEnd );        
       
   587         }
       
   588     const TDesC8& date = GetValueFromElement( KElementDate );         
       
   589     if ( date != KNullDesC8 )
       
   590         {
       
   591         if( ValidateDateL( date ) )
       
   592             {
       
   593             stream.WriteL( KItemDateBegin );
       
   594             // xml encoding added
       
   595             encodeTemp = HBufC8::NewLC( date.Length() );
       
   596             encodeTemp->Des().Copy( date );
       
   597 
       
   598             tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
       
   599             CleanupStack::PushL( tempPtr );
       
   600 
       
   601             stream.WriteL( *tempPtr );
       
   602             CleanupStack::PopAndDestroy( tempPtr );
       
   603             tempPtr = NULL;
       
   604 
       
   605             CleanupStack::PopAndDestroy( encodeTemp );
       
   606             encodeTemp = NULL;
       
   607             stream.WriteL( KItemDateEnd );
       
   608             }       
       
   609         }
       
   610     
       
   611     // Create dlna compliant protocolinfo
       
   612     const RUPnPElementsArray& elms = iItem->GetElements();
       
   613     CUpnpDlnaProtocolInfo* pInfo = NULL; 
       
   614     HBufC8* duration  = NULL;
       
   615     HBufC8* size  = NULL;
       
   616     HBufC8* resolution  = NULL;
       
   617     HBufC8* info = NULL;
       
   618     for( TInt i = 0; i < elms.Count(); i++)
       
   619         {
       
   620         if( elms[ i ]->Name() == KElementRes )
       
   621             {
       
   622             const RUPnPAttributesArray& attr = elms[ i ]->GetAttributes();
       
   623             for( TInt j = 0; j < attr.Count(); j++ )
       
   624                 {
       
   625                 if( attr[ j ]->Name() == KAttributeProtocolInfo )
       
   626                     {
       
   627                     pInfo = CUpnpDlnaProtocolInfo::NewL( attr[ j ]->Value() );
       
   628                     if ( pInfo )
       
   629                         {
       
   630                         CleanupStack::PushL( pInfo );
       
   631                         info = HBufC8::NewLC( KBufLen );
       
   632                         }
       
   633                     }
       
   634                 if ( attr[ j ]->Name() == KAttributeDuration )
       
   635                     {
       
   636                     duration= HBufC8::NewLC( attr[ j ]->Value().Length() );
       
   637                     duration->Des().Copy( attr[ j ]->Value() );
       
   638                     }
       
   639                 if ( attr[ j ]->Name() == KAttributeSize )
       
   640                     {
       
   641                     size = HBufC8::NewLC( attr[ j ]->Value().Length() );
       
   642                     size->Des().Copy( attr[ j ]->Value() );
       
   643                     }
       
   644                 if ( attr[ j ]->Name() == KAttributeResolution )
       
   645                     {
       
   646                     resolution = HBufC8::NewLC( attr[ j ]->Value().Length() );
       
   647                     resolution->Des().Copy( attr[ j ]->Value() );
       
   648                     }
       
   649                 }
       
   650             i = elms.Count();
       
   651             }
       
   652         }
       
   653     
       
   654     if( pInfo )
       
   655         {
       
   656         info->Des().Copy( KItemPInfoEmptyDlna );
       
   657         info->Des().Append( pInfo->ThirdField() ); // Third param )
       
   658         info->Des().Append( KColon );
       
   659         if( pInfo->PnParameter().Length() > 0 )
       
   660             {
       
   661             info->Des().Append( KDlnaPn );
       
   662             info->Des().Append( pInfo->PnParameter() ); // Fourth param )
       
   663             }
       
   664         else
       
   665             {
       
   666             info->Des().Append( KAsterisk );
       
   667             }    
       
   668         if ( resolution )
       
   669             {
       
   670             info->Des().Append( KQuotationMark );
       
   671             info->Des().Append( KItemResolution );
       
   672             info->Des().Append( *resolution );
       
   673             CleanupStack::PopAndDestroy( resolution );
       
   674             resolution = NULL;
       
   675             }
       
   676         if ( duration )
       
   677             {
       
   678             info->Des().Append( KQuotationMark );
       
   679             info->Des().Append( KItemDuration );
       
   680             info->Des().Append( *duration );
       
   681             CleanupStack::PopAndDestroy( duration );
       
   682             duration = NULL;
       
   683             }
       
   684         if ( size )
       
   685             {
       
   686             info->Des().Append( KQuotationMark );
       
   687             info->Des().Append( KItemSize );
       
   688             info->Des().Append( *size );
       
   689             CleanupStack::PopAndDestroy( size );
       
   690             size = NULL;
       
   691             }
       
   692         
       
   693         info->Des().Append( KItemPInfoEnd2 );
       
   694         stream.WriteL( *info );
       
   695         CleanupStack::PopAndDestroy( info );
       
   696         CleanupStack::PopAndDestroy( pInfo );
       
   697         
       
   698         }
       
   699     else
       
   700         {
       
   701         stream.WriteL( KItemPInfoEmpty );    
       
   702         }    
       
   703             
       
   704     stream.WriteL( KItemEnd() );
       
   705 
       
   706     CleanupStack::PopAndDestroy( &stream );
       
   707 
       
   708     TPtrC8 start = pBuf->Ptr(0);
       
   709 
       
   710     HBufC8* tmpBuffer = start.AllocL();
       
   711 
       
   712     CleanupStack::PopAndDestroy( pBuf );
       
   713 
       
   714     return tmpBuffer;
       
   715     }
       
   716 
       
   717 // --------------------------------------------------------------------------
       
   718 // CUpnpItemToXML::AsResultArgumentL
       
   719 // Returns object's XML description that is embedded inside a DIDL-LITE tag. 
       
   720 // The <res> tag of xml description is empty.The returned value is xml encoded
       
   721 // can therefore be used for example when creating a CreateObject action.
       
   722 // (other items were commented in a header).
       
   723 // --------------------------------------------------------------------------
       
   724 HBufC8* CUpnpItemToXML::AsResultArgumentL()
       
   725     {
       
   726     __LOG( "CUpnpItemToXML::AsResultArgumentL" );
       
   727     
       
   728     HBufC8* asEmptyXml = this->AsXmlEmptyL();
       
   729     CleanupStack::PushL( asEmptyXml );
       
   730     
       
   731     // Xml must be encoded because eventually it will be embedded inside 
       
   732     // another Xml tag (Elements tag in CreateObject action).
       
   733     HBufC8* encodedItem = UpnpString::EncodeXmlStringL( asEmptyXml );
       
   734     CleanupStack::PopAndDestroy( asEmptyXml );
       
   735     CleanupStack::PushL( encodedItem );
       
   736     
       
   737     // Put item xml inside DIDL-LITE tag which must also be xml encoded.
       
   738     HBufC8* retval = CreateUnDecodedXmlL( *encodedItem );
       
   739     CleanupStack::PopAndDestroy( encodedItem );
       
   740     
       
   741     return retval;
       
   742     }
       
   743 
       
   744 // --------------------------------------------------------------------------
       
   745 // CUpnpItemToXML::CreateUnDecodedXmlL
       
   746 // Fills common DIDL-Lite XML headers over the given XML fragment.
       
   747 // --------------------------------------------------------------------------
       
   748 HBufC8* CUpnpItemToXML::CreateUnDecodedXmlL( const TDesC8& aData )
       
   749     {
       
   750     __LOG( "CUpnpItemToXML::CreateUnDecodedXmlL" );
       
   751     
       
   752     const TInt bufferSize = 128; // Buffer size
       
   753     CBufFlat *pBuf = CBufFlat::NewL( bufferSize );
       
   754     CleanupStack::PushL( pBuf );
       
   755 
       
   756     RBufWriteStream stream( *pBuf );
       
   757     CleanupClosePushL( stream );
       
   758 
       
   759     stream.WriteL( KDIDLBeginXmlEscaped() );
       
   760     stream.WriteL( aData );
       
   761     stream.WriteL( KDIDLEndXmlEscaped() );
       
   762 
       
   763     CleanupStack::PopAndDestroy( &stream ); // stream.Close();
       
   764 
       
   765     TPtrC8 start = pBuf->Ptr(0);
       
   766 
       
   767     HBufC8* tmpBuffer = start.AllocL();
       
   768 
       
   769     CleanupStack::PopAndDestroy( pBuf );
       
   770     return tmpBuffer;
       
   771     }
       
   772     
       
   773 // --------------------------------------------------------------------------
       
   774 // CUpnpItemToXML::GetValueFromElement
       
   775 // Returns the value of an element.
       
   776 // --------------------------------------------------------------------------
       
   777 const TDesC8& CUpnpItemToXML::GetValueFromElement(
       
   778     const TDesC8& aElementName )
       
   779     {
       
   780     const RUPnPElementsArray& elms = iItem->GetElements();
       
   781     TInt count = elms.Count();
       
   782     for( TInt i = 0; i < count; i++)
       
   783         {
       
   784         if( elms[ i ]->Name() == aElementName )
       
   785             {
       
   786             return elms[ i ]->Value();
       
   787             }
       
   788         }
       
   789     return KNullDesC8;              
       
   790     }
       
   791 
       
   792 // --------------------------------------------------------------------------
       
   793 // CUpnpItemToXML::ValidateDateL
       
   794 // Validates dc:date
       
   795 // --------------------------------------------------------------------------
       
   796 TBool CUpnpItemToXML::ValidateDateL( const TDesC8& aDate )
       
   797     {
       
   798     TDateTime time;    
       
   799     TBuf<KMaxDateStringLength> formatDateString;
       
   800     HBufC* dateString = HBufC::NewL( aDate.Length() );
       
   801     dateString->Des().Copy( aDate );
       
   802     TInt err = KErrNone;
       
   803     TInt year = 0;
       
   804     TInt month = 1; 
       
   805     TInt day = 1;
       
   806     TInt hours = 0;
       
   807     TInt minutes = 0;
       
   808     TInt seconds = 0;
       
   809 
       
   810     if( aDate.Length() >= KDateStringLength )
       
   811     {
       
   812         TLex lex( dateString->Des().Left( 4 ) ); //Year
       
   813         err = lex.Val( year );
       
   814         if(  err == KErrNone )
       
   815         {
       
   816             lex.Assign( dateString->Des().Mid( 5,2 ) ); //Month
       
   817             TInt err = lex.Val( month );
       
   818             if(  err == KErrNone )
       
   819             {
       
   820                 lex.Assign( dateString->Des().Mid( 8,2 ) ); //Day
       
   821                 TInt err = lex.Val(day);
       
   822             }
       
   823         }
       
   824     }
       
   825         
       
   826     if (err)
       
   827     {
       
   828         return EFalse;
       
   829     }
       
   830         
       
   831     if( aDate.Length() >= KDateTimeStringLength )
       
   832     {
       
   833         TLex lex( dateString->Des().Mid( 11,2 ) ); //Hours
       
   834         err = lex.Val( hours );
       
   835         if(  err == KErrNone )
       
   836         {
       
   837             lex.Assign( dateString->Des().Mid( 14,2 ) ); //Minutes
       
   838             TInt err = lex.Val( hours );
       
   839             if(  err == KErrNone )
       
   840             {
       
   841                 lex.Assign( dateString->Des().Mid( 17,2 ) ); //Seconds
       
   842                 TInt err = lex.Val( hours );
       
   843             }
       
   844         }
       
   845     }
       
   846 
       
   847     if (err)
       
   848     {
       
   849         return EFalse;
       
   850     }
       
   851         
       
   852     TBool retVal = EFalse;
       
   853     //DateTime month and day are 0-based
       
   854     if( time.Set( year, TMonth(month - 1), 
       
   855             day - 1, hours, minutes, seconds,0 ) == KErrNone )
       
   856         {
       
   857         retVal = ETrue;
       
   858         }
       
   859     
       
   860     delete dateString;
       
   861     
       
   862     return retVal;
       
   863     }
       
   864 
       
   865 // --------------------------------------------------------------------------
       
   866 // CUpnpItemToXML::ValidateDurationL
       
   867 // Validates res@duration
       
   868 // --------------------------------------------------------------------------
       
   869 TBool CUpnpItemToXML::ValidateDurationL( const TDesC8& aDuration )
       
   870     {
       
   871     
       
   872     TBool retVal = ETrue;
       
   873     TLex8 input( aDuration );
       
   874     
       
   875     // Hours
       
   876     ParseToDelimeter( input, TChar( KSeparatorAscii ) );
       
   877     TInt hours = input.MarkedToken().Length();
       
   878     if( !input.Eos() )
       
   879         {
       
   880         input.SkipAndMark( 1 ); // Skip the delimeter
       
   881         }
       
   882     if( hours < 1 || hours > 5 ) // hours must be 1-5 digits long
       
   883         {
       
   884         retVal = EFalse;
       
   885         }
       
   886     else
       
   887         {
       
   888         // Minutes
       
   889         ParseToDelimeter( input, TChar( KSeparatorAscii ) );   
       
   890         TInt minutes = input.MarkedToken().Length();
       
   891         if( !input.Eos() )
       
   892             {
       
   893             input.SkipAndMark( 1 ); // Skip the delimeter
       
   894             }
       
   895 
       
   896         if( minutes != 2 ) // minutes must be 2 digits long
       
   897             {
       
   898             retVal = EFalse;
       
   899             }
       
   900         else
       
   901             {
       
   902             // Seconds
       
   903             ParseToDelimeter( input, TChar( KSeparatorAscii ) );
       
   904             TInt seconds = input.MarkedToken().Length();
       
   905             if( seconds < 2 || seconds > 6 ) // seconds must be 2-6 digits
       
   906             // long
       
   907                 {
       
   908                 retVal = EFalse;
       
   909                 }
       
   910 
       
   911             if( !input.Eos() )
       
   912                 {
       
   913                 // Something is wrong, we should be in the end        
       
   914                 retVal = EFalse;
       
   915                 }            
       
   916             }    
       
   917         }    
       
   918   
       
   919     return retVal;
       
   920     }
       
   921     
       
   922 // --------------------------------------------------------------------------
       
   923 // CUpnpItemToXML::ParseToDelimeter
       
   924 // Parse to a given delimeter
       
   925 // --------------------------------------------------------------------------
       
   926 void CUpnpItemToXML::ParseToDelimeter( TLex8& aLex, TChar aDelimeter )
       
   927     {
       
   928     aLex.Mark();
       
   929         
       
   930     TChar chr = 0;
       
   931     
       
   932     while( !aLex.Eos() )
       
   933         {
       
   934         chr = aLex.Peek();
       
   935         if( chr == aDelimeter )
       
   936             {
       
   937             break;
       
   938             }
       
   939             
       
   940         aLex.Inc();        
       
   941         }
       
   942     }    
       
   943     
       
   944 
       
   945 //  End of File