--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/upnpavcontroller/upnpxmlparser/src/upnpitemtoxml.cpp Thu Dec 17 08:52:00 2009 +0200
@@ -0,0 +1,945 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: generates XML from an UPNP item
+*
+*/
+
+
+
+
+
+
+// INCLUDE FILES
+// System
+#include <e32base.h>
+
+// upnp stack api
+#include <upnpstring.h>
+#include <upnpitem.h>
+#include <upnpdlnaprotocolinfo.h>
+
+// upnpframework / avcontroller helper api
+#include "upnpconstantdefs.h" // for upnp definitions
+#include "upnpitemutility.h"
+
+// xmlparser internal
+#include "upnpitemtoxml.h"
+
+_LIT( KComponentLogfile, "upnpxmlparser.txt");
+#include "upnplog.h"
+
+// CONSTANTS
+_LIT8(KItemHeading1, "<item id=\"");
+_LIT8(KItemHeading2, "\" parentID=\"");
+_LIT8(KItemHeading3False, "\" restricted=\"0\">");
+_LIT8(KItemHeading3True, "\" restricted=\"1\">");
+_LIT8(KItemTitleBegin, "<dc:title>");
+_LIT8(KItemTitleEnd, "</dc:title>");
+_LIT8(KItemDateBegin, "<dc:date>");
+_LIT8(KItemDateEnd, "</dc:date>");
+_LIT8(KItemClassBegin, "<upnp:class>");
+_LIT8(KItemClassEnd, "</upnp:class>");
+_LIT8(KItemPInfoEmpty, "<res protocolInfo=\"*:*:*:*\"></res>");
+_LIT8(KItemPInfoEmptyDlna, "<res protocolInfo=\"*:*:");
+_LIT8(KDlnaPn, "DLNA.ORG_PN=" );
+_LIT8(KColon, ":");
+_LIT8(KItemPInfoBegin, "<res protocolInfo=\"");
+_LIT8(KItemPInfoMiddle, ">");
+_LIT8(KItemPInfoEnd, "</res>");
+_LIT8(KItemPInfoEnd2, "\"></res>");
+_LIT8(KItemEnd, "</item>");
+
+_LIT8(KQuotationMark, "\" ");
+_LIT8(KItemSize, "size=\"");
+_LIT8(KItemDuration, "duration=\"");
+_LIT8(KItemResolution, "resolution=\"");
+
+// Music metadata
+_LIT8(KItemArtistBegin, "<upnp:artist>");
+_LIT8(KItemArtistEnd, "</upnp:artist>");
+_LIT8(KItemCreatorBegin, "<dc:creator>");
+_LIT8(KItemCreatorEnd, "</dc:creator>");
+_LIT8(KItemAlbumBegin, "<upnp:album>");
+_LIT8(KItemAlbumEnd, "</upnp:album>");
+_LIT8(KItemGenreBegin, "<upnp:genre>");
+_LIT8(KItemGenreEnd, "</upnp:genre>");
+_LIT8(KItemAlbumArtURIBegin, "<upnp:albumArtURI>");
+_LIT8(KItemAlbumArtURIEnd, "</upnp:albumArtURI>");
+
+_LIT8(KDIDLBeginXmlEscaped,
+ "<DIDL-Lite "
+ "xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" "
+ "xmlns:dc="http://purl.org/dc/elements/1.1/" "
+ "xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/""
+ ">");
+_LIT8(KDIDLEndXmlEscaped, "</DIDL-Lite>");
+
+_LIT8( KAsterisk, "*" );
+
+const TInt KBufLen = 256;
+const TInt KDateStringLength = 10;
+const TInt KDateTimeStringLength = 19;
+const TInt KMaxDateStringLength = 30;
+const TInt KSeparatorAscii = 58;
+
+
+// ============================ MEMBER FUNCTIONS ============================
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::CUpnpItemToXML
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// --------------------------------------------------------------------------
+CUpnpItemToXML::CUpnpItemToXML( const CUpnpItem& aItem ) :
+ iItem( const_cast<CUpnpItem*>(&aItem) )
+ {
+ }
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::ConstructL
+// Symbian 2nd phase constructor can leave.
+// --------------------------------------------------------------------------
+void CUpnpItemToXML::ConstructL()
+ {
+ }
+
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::NewL
+// Two-phased constructor.
+// --------------------------------------------------------------------------
+CUpnpItemToXML* CUpnpItemToXML::NewL( const CUpnpItem& aItem )
+ {
+ CUpnpItemToXML* self = CUpnpItemToXML::NewLC( aItem );
+
+ CleanupStack::Pop();
+
+ return self;
+ }
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::NewLC
+// Two-phased constructor.
+// --------------------------------------------------------------------------
+CUpnpItemToXML* CUpnpItemToXML::NewLC( const CUpnpItem& aItem )
+ {
+ CUpnpItemToXML* self = new( ELeave ) CUpnpItemToXML( aItem );
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+
+ return self;
+ }
+
+// Destructor
+CUpnpItemToXML::~CUpnpItemToXML()
+ {
+ }
+
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::AsXmlL
+// Returns XML buffer
+// (other items were commented in a header).
+// --------------------------------------------------------------------------
+HBufC8* CUpnpItemToXML::AsXmlL( const TBool /*aIncludeChilds = ETrue */ )
+ {
+ __LOG( "CUpnpItemToXML::AsXmlL" );
+
+ const TInt bufferSize = 64; // Buffer size, grows dynamicly in 64b steps
+ CBufFlat *pBuf = CBufFlat::NewL( bufferSize );
+ CleanupStack::PushL( pBuf );
+
+ RBufWriteStream stream( *pBuf );
+ CleanupClosePushL( stream );
+
+ // Then add the actual data
+ stream.WriteL( KItemHeading1() );
+ // xml encoding added
+ HBufC8* encodeTemp = HBufC8::NewLC( iItem->Id().Length() );
+ encodeTemp->Des().Copy( iItem->Id() );
+
+ HBufC8* tempPtr = NULL;
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+
+ stream.WriteL( KItemHeading2() );
+
+ stream.WriteL( iItem->ParentId() );
+ if (iItem->Restricted())
+ {
+ stream.WriteL( KItemHeading3True() );
+ }
+ else
+ {
+ stream.WriteL( KItemHeading3False() );
+ }
+ stream.WriteL( KItemTitleBegin() );
+
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( iItem->Title().Length() );
+ encodeTemp->Des().Copy( iItem->Title() );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+
+ stream.WriteL( KItemTitleEnd() );
+ stream.WriteL( KItemClassBegin() );
+
+ stream.WriteL( iItem->ObjectClass() );
+ stream.WriteL( KItemClassEnd() );
+
+ // Music meta data information
+ const TDesC8& artist = GetValueFromElement( KElementArtist );
+ if ( artist != KNullDesC8 )
+
+ {
+ stream.WriteL( KItemArtistBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( artist.Length() );
+ encodeTemp->Des().Copy( artist );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+
+ stream.WriteL( KItemArtistEnd );
+ }
+ const TDesC8& creator = GetValueFromElement( KElementCreator );
+ if ( creator != KNullDesC8 )
+ {
+ stream.WriteL( KItemCreatorBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( creator.Length() );
+ encodeTemp->Des().Copy( creator );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+
+ stream.WriteL( KItemCreatorEnd );
+ }
+ const TDesC8& album = GetValueFromElement( KElementAlbum );
+ if ( album != KNullDesC8 )
+ {
+ stream.WriteL( KItemAlbumBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( album.Length() );
+ encodeTemp->Des().Copy( album );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+ //stream.WriteL( Album() );
+ stream.WriteL( KItemAlbumEnd );
+ }
+ const TDesC8& genre = GetValueFromElement( KElementGenre );
+ if ( genre != KNullDesC8 )
+ {
+ stream.WriteL( KItemGenreBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( genre.Length() );
+ encodeTemp->Des().Copy( genre );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+ //stream.WriteL( Genre() );
+ stream.WriteL( KItemGenreEnd );
+ }
+ const TDesC8& albumarturi = GetValueFromElement( KElementAlbumArtUri );
+ if ( albumarturi != KNullDesC8 )
+ {
+ stream.WriteL( KItemAlbumArtURIBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( albumarturi.Length() );
+ encodeTemp->Des().Copy( albumarturi );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+ stream.WriteL( KItemAlbumArtURIEnd );
+ }
+ const TDesC8& date = GetValueFromElement( KElementDate );
+ if ( date != KNullDesC8 )
+ {
+ if( ValidateDateL( date ) )
+ {
+ stream.WriteL( KItemDateBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( date.Length() );
+ encodeTemp->Des().Copy( date );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+ stream.WriteL( KItemDateEnd );
+ }
+ }
+
+ RUPnPElementsArray elArray;
+ CleanupClosePushL( elArray );
+ UPnPItemUtility::GetResElements( *iItem, elArray );
+ TInt count = elArray.Count();
+ for( TInt i = 0; i < count; i++ )
+ {
+ // Res-element starts
+ stream.WriteL( KItemPInfoBegin );
+
+ const CUpnpAttribute* attrproinfo = UPnPItemUtility
+ ::FindAttributeByName( *elArray[ i ], KAttributeProtocolInfo );
+ if ( attrproinfo )
+ {
+ stream.WriteL( attrproinfo->Value() );
+ stream.WriteL( KCriteriaQuot );
+ stream.WriteL( KCriteriaSpace );
+ }
+ const CUpnpAttribute* attrsize = UPnPItemUtility
+ ::FindAttributeByName( *elArray[ i ], KAttributeSize );
+ if ( attrsize )
+ {
+ stream.WriteL( KAttributeSize );
+ stream.WriteL( KCriteriaEQ );
+ stream.WriteL( KCriteriaQuot );
+ stream.WriteL( attrsize->Value() );
+ stream.WriteL( KCriteriaQuot );
+ stream.WriteL( KCriteriaSpace );
+ }
+ const CUpnpAttribute* attrresolution = UPnPItemUtility
+ ::FindAttributeByName( *elArray[ i ], KAttributeResolution );
+ if ( attrresolution )
+ {
+ stream.WriteL( KAttributeResolution );
+ stream.WriteL( KCriteriaEQ );
+ stream.WriteL( KCriteriaQuot );
+ stream.WriteL( attrresolution->Value() );
+ stream.WriteL( KCriteriaQuot );
+ stream.WriteL( KCriteriaSpace );
+ }
+ const CUpnpAttribute* attrduration = UPnPItemUtility
+ ::FindAttributeByName( *elArray[ i ], KAttributeDuration );
+ if ( attrduration )
+ {
+ if( ValidateDurationL( attrduration->Value() ) )
+ {
+ stream.WriteL( KAttributeDuration );
+ stream.WriteL( KCriteriaEQ );
+ stream.WriteL( KCriteriaQuot );
+ stream.WriteL( attrduration->Value() );
+ stream.WriteL( KCriteriaQuot );
+ stream.WriteL( KCriteriaSpace );
+ }
+ else
+ {
+ // Format of duration is not valid, do not include it
+ // Fixes ESLX-7AYFD6
+ }
+
+ }
+ const CUpnpAttribute* attrbitrate = UPnPItemUtility
+ ::FindAttributeByName( *elArray[ i ], KAttributeBitrate );
+ if ( attrbitrate )
+ {
+ stream.WriteL( KAttributeBitrate );
+ stream.WriteL( KCriteriaEQ );
+ stream.WriteL( KCriteriaQuot );
+ stream.WriteL( attrbitrate->Value() );
+ stream.WriteL( KCriteriaQuot );
+ stream.WriteL( KCriteriaSpace );
+ }
+ stream.WriteL( KItemPInfoMiddle );
+
+ // Get the content URI
+ encodeTemp = HBufC8::NewLC( elArray[ i ]->Value().Length() );
+ encodeTemp->Des().Copy( elArray[ i ]->Value() );
+
+ // Encode the content URI
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ // Write the encoded content URI
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ // Clean up
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+
+ // Res-element ends
+ stream.WriteL( KItemPInfoEnd );
+ }
+
+ CleanupStack::PopAndDestroy( &elArray );
+
+ stream.WriteL( KItemEnd() );
+
+ CleanupStack::PopAndDestroy(); // stream.Close();
+
+ TPtrC8 start = pBuf->Ptr(0);
+
+ // JLi: Do NOT decode retBuffer since it will be given to XML Parser
+ HBufC8* retBuffer = start.AllocL();
+ CleanupStack::PopAndDestroy( pBuf );
+
+ return retBuffer;
+ }
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::AsXmlEmptyL
+// Returns object's XML description. This version of the method is used to
+// create the XML with empty <res> tag.
+// (other items were commented in a header).
+// --------------------------------------------------------------------------
+HBufC8* CUpnpItemToXML::AsXmlEmptyL()
+ {
+ __LOG( "CUpnpItemToXML::AsXmlEmptyL" );
+
+ const TInt bufferSize = 64; // Buffer size, grows dynamicly in 64b steps
+ CBufFlat *pBuf = CBufFlat::NewL( bufferSize );
+ CleanupStack::PushL( pBuf );
+
+ RBufWriteStream stream( *pBuf );
+ CleanupClosePushL( stream );
+
+ // Then add the actual data
+ stream.WriteL( KItemHeading1() );
+ stream.WriteL( iItem->Id() );
+ stream.WriteL( KItemHeading2() );
+ stream.WriteL( iItem->ParentId() );
+ stream.WriteL( KItemHeading3False() );
+ //stream.WriteL( KItemEndTag() );
+ stream.WriteL( KItemTitleBegin() );
+ // xml encode name
+ HBufC8* encodeTemp = HBufC8::NewLC( iItem->Title().Length() );
+ encodeTemp->Des().Copy( iItem->Title() );
+ HBufC8* tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ CleanupStack::PopAndDestroy( encodeTemp );
+ stream.WriteL( KItemTitleEnd() );
+ stream.WriteL( KItemClassBegin() );
+
+ stream.WriteL( iItem->ObjectClass() );
+ stream.WriteL( KItemClassEnd() );
+
+ // Music meta data information
+ const TDesC8& artist = GetValueFromElement( KElementArtist );
+ if ( artist != KNullDesC8 )
+ {
+ stream.WriteL( KItemArtistBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( artist.Length() );
+ encodeTemp->Des().Copy( artist );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+
+ stream.WriteL( KItemArtistEnd );
+ }
+ const TDesC8& creator = GetValueFromElement( KElementCreator );
+ if ( creator != KNullDesC8 )
+ {
+ stream.WriteL( KItemCreatorBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( creator.Length() );
+ encodeTemp->Des().Copy( creator );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+
+ stream.WriteL( KItemCreatorEnd );
+ }
+ const TDesC8& album = GetValueFromElement( KElementAlbum );
+ if ( album != KNullDesC8 )
+ {
+ stream.WriteL( KItemAlbumBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( album.Length() );
+ encodeTemp->Des().Copy( album );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+ //stream.WriteL( Album() );
+ stream.WriteL( KItemAlbumEnd );
+ }
+ const TDesC8& genre = GetValueFromElement( KElementGenre );
+ if ( genre != KNullDesC8 )
+ {
+ stream.WriteL( KItemGenreBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( genre.Length() );
+ encodeTemp->Des().Copy( genre );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+ //stream.WriteL( Genre() );
+ stream.WriteL( KItemGenreEnd );
+ }
+ const TDesC8& albumarturi = GetValueFromElement( KElementAlbumArtUri );
+ if ( albumarturi != KNullDesC8 )
+ {
+ stream.WriteL( KItemAlbumArtURIBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( albumarturi.Length() );
+ encodeTemp->Des().Copy( albumarturi );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+ stream.WriteL( KItemAlbumArtURIEnd );
+ }
+ const TDesC8& date = GetValueFromElement( KElementDate );
+ if ( date != KNullDesC8 )
+ {
+ if( ValidateDateL( date ) )
+ {
+ stream.WriteL( KItemDateBegin );
+ // xml encoding added
+ encodeTemp = HBufC8::NewLC( date.Length() );
+ encodeTemp->Des().Copy( date );
+
+ tempPtr = UpnpString::EncodeXmlStringL( encodeTemp );
+ CleanupStack::PushL( tempPtr );
+
+ stream.WriteL( *tempPtr );
+ CleanupStack::PopAndDestroy( tempPtr );
+ tempPtr = NULL;
+
+ CleanupStack::PopAndDestroy( encodeTemp );
+ encodeTemp = NULL;
+ stream.WriteL( KItemDateEnd );
+ }
+ }
+
+ // Create dlna compliant protocolinfo
+ const RUPnPElementsArray& elms = iItem->GetElements();
+ CUpnpDlnaProtocolInfo* pInfo = NULL;
+ HBufC8* duration = NULL;
+ HBufC8* size = NULL;
+ HBufC8* resolution = NULL;
+ HBufC8* info = NULL;
+ for( TInt i = 0; i < elms.Count(); i++)
+ {
+ if( elms[ i ]->Name() == KElementRes )
+ {
+ const RUPnPAttributesArray& attr = elms[ i ]->GetAttributes();
+ for( TInt j = 0; j < attr.Count(); j++ )
+ {
+ if( attr[ j ]->Name() == KAttributeProtocolInfo )
+ {
+ pInfo = CUpnpDlnaProtocolInfo::NewL( attr[ j ]->Value() );
+ if ( pInfo )
+ {
+ CleanupStack::PushL( pInfo );
+ info = HBufC8::NewLC( KBufLen );
+ }
+ }
+ if ( attr[ j ]->Name() == KAttributeDuration )
+ {
+ duration= HBufC8::NewLC( attr[ j ]->Value().Length() );
+ duration->Des().Copy( attr[ j ]->Value() );
+ }
+ if ( attr[ j ]->Name() == KAttributeSize )
+ {
+ size = HBufC8::NewLC( attr[ j ]->Value().Length() );
+ size->Des().Copy( attr[ j ]->Value() );
+ }
+ if ( attr[ j ]->Name() == KAttributeResolution )
+ {
+ resolution = HBufC8::NewLC( attr[ j ]->Value().Length() );
+ resolution->Des().Copy( attr[ j ]->Value() );
+ }
+ }
+ i = elms.Count();
+ }
+ }
+
+ if( pInfo )
+ {
+ info->Des().Copy( KItemPInfoEmptyDlna );
+ info->Des().Append( pInfo->ThirdField() ); // Third param )
+ info->Des().Append( KColon );
+ if( pInfo->PnParameter().Length() > 0 )
+ {
+ info->Des().Append( KDlnaPn );
+ info->Des().Append( pInfo->PnParameter() ); // Fourth param )
+ }
+ else
+ {
+ info->Des().Append( KAsterisk );
+ }
+ if ( resolution )
+ {
+ info->Des().Append( KQuotationMark );
+ info->Des().Append( KItemResolution );
+ info->Des().Append( *resolution );
+ CleanupStack::PopAndDestroy( resolution );
+ resolution = NULL;
+ }
+ if ( duration )
+ {
+ info->Des().Append( KQuotationMark );
+ info->Des().Append( KItemDuration );
+ info->Des().Append( *duration );
+ CleanupStack::PopAndDestroy( duration );
+ duration = NULL;
+ }
+ if ( size )
+ {
+ info->Des().Append( KQuotationMark );
+ info->Des().Append( KItemSize );
+ info->Des().Append( *size );
+ CleanupStack::PopAndDestroy( size );
+ size = NULL;
+ }
+
+ info->Des().Append( KItemPInfoEnd2 );
+ stream.WriteL( *info );
+ CleanupStack::PopAndDestroy( info );
+ CleanupStack::PopAndDestroy( pInfo );
+
+ }
+ else
+ {
+ stream.WriteL( KItemPInfoEmpty );
+ }
+
+ stream.WriteL( KItemEnd() );
+
+ CleanupStack::PopAndDestroy( &stream );
+
+ TPtrC8 start = pBuf->Ptr(0);
+
+ HBufC8* tmpBuffer = start.AllocL();
+
+ CleanupStack::PopAndDestroy( pBuf );
+
+ return tmpBuffer;
+ }
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::AsResultArgumentL
+// Returns object's XML description that is embedded inside a DIDL-LITE tag.
+// The <res> tag of xml description is empty.The returned value is xml encoded
+// can therefore be used for example when creating a CreateObject action.
+// (other items were commented in a header).
+// --------------------------------------------------------------------------
+HBufC8* CUpnpItemToXML::AsResultArgumentL()
+ {
+ __LOG( "CUpnpItemToXML::AsResultArgumentL" );
+
+ HBufC8* asEmptyXml = this->AsXmlEmptyL();
+ CleanupStack::PushL( asEmptyXml );
+
+ // Xml must be encoded because eventually it will be embedded inside
+ // another Xml tag (Elements tag in CreateObject action).
+ HBufC8* encodedItem = UpnpString::EncodeXmlStringL( asEmptyXml );
+ CleanupStack::PopAndDestroy( asEmptyXml );
+ CleanupStack::PushL( encodedItem );
+
+ // Put item xml inside DIDL-LITE tag which must also be xml encoded.
+ HBufC8* retval = CreateUnDecodedXmlL( *encodedItem );
+ CleanupStack::PopAndDestroy( encodedItem );
+
+ return retval;
+ }
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::CreateUnDecodedXmlL
+// Fills common DIDL-Lite XML headers over the given XML fragment.
+// --------------------------------------------------------------------------
+HBufC8* CUpnpItemToXML::CreateUnDecodedXmlL( const TDesC8& aData )
+ {
+ __LOG( "CUpnpItemToXML::CreateUnDecodedXmlL" );
+
+ const TInt bufferSize = 128; // Buffer size
+ CBufFlat *pBuf = CBufFlat::NewL( bufferSize );
+ CleanupStack::PushL( pBuf );
+
+ RBufWriteStream stream( *pBuf );
+ CleanupClosePushL( stream );
+
+ stream.WriteL( KDIDLBeginXmlEscaped() );
+ stream.WriteL( aData );
+ stream.WriteL( KDIDLEndXmlEscaped() );
+
+ CleanupStack::PopAndDestroy( &stream ); // stream.Close();
+
+ TPtrC8 start = pBuf->Ptr(0);
+
+ HBufC8* tmpBuffer = start.AllocL();
+
+ CleanupStack::PopAndDestroy( pBuf );
+ return tmpBuffer;
+ }
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::GetValueFromElement
+// Returns the value of an element.
+// --------------------------------------------------------------------------
+const TDesC8& CUpnpItemToXML::GetValueFromElement(
+ const TDesC8& aElementName )
+ {
+ const RUPnPElementsArray& elms = iItem->GetElements();
+ TInt count = elms.Count();
+ for( TInt i = 0; i < count; i++)
+ {
+ if( elms[ i ]->Name() == aElementName )
+ {
+ return elms[ i ]->Value();
+ }
+ }
+ return KNullDesC8;
+ }
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::ValidateDateL
+// Validates dc:date
+// --------------------------------------------------------------------------
+TBool CUpnpItemToXML::ValidateDateL( const TDesC8& aDate )
+ {
+ TDateTime time;
+ TBuf<KMaxDateStringLength> formatDateString;
+ HBufC* dateString = HBufC::NewL( aDate.Length() );
+ dateString->Des().Copy( aDate );
+ TInt err = KErrNone;
+ TInt year = 0;
+ TInt month = 1;
+ TInt day = 1;
+ TInt hours = 0;
+ TInt minutes = 0;
+ TInt seconds = 0;
+
+ if( aDate.Length() >= KDateStringLength )
+ {
+ TLex lex( dateString->Des().Left( 4 ) ); //Year
+ err = lex.Val( year );
+ if( err == KErrNone )
+ {
+ lex.Assign( dateString->Des().Mid( 5,2 ) ); //Month
+ TInt err = lex.Val( month );
+ if( err == KErrNone )
+ {
+ lex.Assign( dateString->Des().Mid( 8,2 ) ); //Day
+ TInt err = lex.Val(day);
+ }
+ }
+ }
+
+ if (err)
+ {
+ return EFalse;
+ }
+
+ if( aDate.Length() >= KDateTimeStringLength )
+ {
+ TLex lex( dateString->Des().Mid( 11,2 ) ); //Hours
+ err = lex.Val( hours );
+ if( err == KErrNone )
+ {
+ lex.Assign( dateString->Des().Mid( 14,2 ) ); //Minutes
+ TInt err = lex.Val( hours );
+ if( err == KErrNone )
+ {
+ lex.Assign( dateString->Des().Mid( 17,2 ) ); //Seconds
+ TInt err = lex.Val( hours );
+ }
+ }
+ }
+
+ if (err)
+ {
+ return EFalse;
+ }
+
+ TBool retVal = EFalse;
+ //DateTime month and day are 0-based
+ if( time.Set( year, TMonth(month - 1),
+ day - 1, hours, minutes, seconds,0 ) == KErrNone )
+ {
+ retVal = ETrue;
+ }
+
+ delete dateString;
+
+ return retVal;
+ }
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::ValidateDurationL
+// Validates res@duration
+// --------------------------------------------------------------------------
+TBool CUpnpItemToXML::ValidateDurationL( const TDesC8& aDuration )
+ {
+
+ TBool retVal = ETrue;
+ TLex8 input( aDuration );
+
+ // Hours
+ ParseToDelimeter( input, TChar( KSeparatorAscii ) );
+ TInt hours = input.MarkedToken().Length();
+ if( !input.Eos() )
+ {
+ input.SkipAndMark( 1 ); // Skip the delimeter
+ }
+ if( hours < 1 || hours > 5 ) // hours must be 1-5 digits long
+ {
+ retVal = EFalse;
+ }
+ else
+ {
+ // Minutes
+ ParseToDelimeter( input, TChar( KSeparatorAscii ) );
+ TInt minutes = input.MarkedToken().Length();
+ if( !input.Eos() )
+ {
+ input.SkipAndMark( 1 ); // Skip the delimeter
+ }
+
+ if( minutes != 2 ) // minutes must be 2 digits long
+ {
+ retVal = EFalse;
+ }
+ else
+ {
+ // Seconds
+ ParseToDelimeter( input, TChar( KSeparatorAscii ) );
+ TInt seconds = input.MarkedToken().Length();
+ if( seconds < 2 || seconds > 6 ) // seconds must be 2-6 digits
+ // long
+ {
+ retVal = EFalse;
+ }
+
+ if( !input.Eos() )
+ {
+ // Something is wrong, we should be in the end
+ retVal = EFalse;
+ }
+ }
+ }
+
+ return retVal;
+ }
+
+// --------------------------------------------------------------------------
+// CUpnpItemToXML::ParseToDelimeter
+// Parse to a given delimeter
+// --------------------------------------------------------------------------
+void CUpnpItemToXML::ParseToDelimeter( TLex8& aLex, TChar aDelimeter )
+ {
+ aLex.Mark();
+
+ TChar chr = 0;
+
+ while( !aLex.Eos() )
+ {
+ chr = aLex.Peek();
+ if( chr == aDelimeter )
+ {
+ break;
+ }
+
+ aLex.Inc();
+ }
+ }
+
+
+// End of File