diff -r 3785f754ee62 -r 5360b7ddc251 upnpavcontroller/upnpavcontrollerhelper/src/upnpitemutility.cpp --- a/upnpavcontroller/upnpavcontrollerhelper/src/upnpitemutility.cpp Fri Sep 17 08:31:21 2010 +0300 +++ b/upnpavcontroller/upnpavcontrollerhelper/src/upnpitemutility.cpp Mon Nov 01 12:37:49 2010 +0200 @@ -1,427 +1,427 @@ -/* -* Copyright (c) 2007 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: Utility for parsing upnp items -* -*/ - - - - - - -// INCLUDE FILES -// System -#include - -// upnp stack api -#include -#include - -// upnpframework / avcontroller helper api -#include "upnpconstantdefs.h" // for KValueNotImplemented -#include "upnpitemutility.h" - -_LIT( KComponentLogfile, "upnpavcontrollerhelper.txt"); -#include "upnplog.h" - -// CONSTANTS -const TInt KDateStringLength = 10; -const TInt KDateTimeStringLength = 19; -const TInt KMaxDateStringLength = 30; -const TInt KCodeSemicolon = 58; -_LIT( KSeparator, ":" ); -_LIT( KNullTime, "000000" ); -_LIT8( KHttp, "http://" ); -_LIT8( KCiParam, "DLNA.ORG_CI" ); - -/* removed due to M-DMC CTT test case 7.3.26.2 -_LIT8( KAudioSupport, "audio/" ); -_LIT8( KImageSupport, "image/" ); -_LIT8( KVideoSupport, "video/" ); -*/ - -// ============================ LOCAL FUNCTIONS ============================= - -// -------------------------------------------------------------------------- -// UPnPItemUtility::BelongsToClass -//--------------------------------------------------------------------------- -EXPORT_C TBool UPnPItemUtility::BelongsToClass( - const CUpnpObject& aObject, - const TDesC8& aClass ) - { - TBool beginsWith = - ( aObject.ObjectClass().Find( aClass ) == 0 ); - return beginsWith; - } - -// -------------------------------------------------------------------------- -// UPnPItemUtility::GetResElements -//--------------------------------------------------------------------------- -EXPORT_C void UPnPItemUtility::GetResElements( - const CUpnpObject& aObject, - RUPnPElementsArray& aResElementsArray ) - { - const RUPnPElementsArray& array = - const_cast(aObject).GetElements(); - - for( TInt i = 0; i < array.Count(); i++ ) - { - if( array[ i ]->Name() == KElementRes() ) - { - aResElementsArray.Append( array[ i ] ); - } - } - } - -// -------------------------------------------------------------------------- -// UPnPItemUtility::ResourceFromItemL -//--------------------------------------------------------------------------- -EXPORT_C const CUpnpElement& UPnPItemUtility::ResourceFromItemL( - const CUpnpItem& aItem ) - { - __LOG( "UpnpItemUtility:ResourceFromItemL" ); - - // Obtain list of item's res elements - RUPnPElementsArray elms; - GetResElements( aItem, elms ); - TInt count = elms.Count(); - - CUpnpDlnaProtocolInfo* pInfo = NULL; - TBool found = EFalse; - TInt i(0); - // bestCandidate is an index of some res element in the list. This res - // will be considered as the best candidate for desired res and that - // candidate will be returned if no res element contains false CI-flag. - - const CUpnpElement* bestCandidate = 0; - - // determine which resource is the original one - // 1. In DLNA 1.5 case, parse protocolInfo attribute and see if some res - // element has CI-flag false (=not converted so that is what we want) - // 2. In non-DLNA 1.5 case and in DLNA 1.5 case where CI-flag does not - // exist, do the following: - // o filter out other than HTTP GET resources (internal uri's, RTP) - // o filter out resources that do not match itemtype (mime type of - // audio file resources should start with "audio/" etc.) - for( i = 0 ; i < count; i++ ) - { - // Make sure that it is a HTTP GET resource. Otherwise continue. - if( elms[ i ]->Value().Left( KHttp.iTypeLength ).Compare( KHttp() ) - != 0 ) - { - continue; - } - - // Obtain protocolInfo of the res element. - const CUpnpAttribute* attr = FindAttributeByName( - *elms[i], KAttributeProtocolInfo() ); - if ( attr ) - { - TRAP_IGNORE( pInfo = CUpnpDlnaProtocolInfo::NewL( attr->Value() ) ); - if( !pInfo ) - { - //if pInfo, start next one! - continue; - } - // check if CI parameter is false or it doesn't have CI parameters at all. - //for upnp item, always the first res element is the best, resolution - // should be checked in the future - if ( ( attr->Value().Find( KCiParam() ) != KErrNotFound && - pInfo->CiParameter() == EFalse ) || - attr->Value().Find( KCiParam() ) == KErrNotFound ) - { - // end loop, we found what we were looking for. - found = ETrue; - delete pInfo; pInfo = NULL; - break; - } - -/* removed due to M-DMC CTT test case 7.3.26.2 - // check that mimetype corresponds to objectType - TPtrC8 mime = pInfo->ThirdField(); - - TPtrC8 objectClass = aItem.ObjectClass(); - if ( objectClass.Compare( KClassAudio ) == 0 ) - { - if ( mime.Left( KAudioSupport().Length() ).CompareF( - KAudioSupport() ) != 0 ) - { - // if mime type does not match to object type, this is - // not the correct resource. - delete pInfo; pInfo = NULL; - continue; - } - } - else if ( objectClass.Compare( KClassVideo ) == 0 ) - { - if ( mime.Left( KVideoSupport().Length() ).CompareF( - KVideoSupport() ) != 0 ) - { - // if mime type does not match to object type, this is - // not the correct resource. - delete pInfo; pInfo = NULL; - continue; - } - } - else if ( objectClass.Compare( KClassImage ) == 0 ) - { - if ( mime.Left( KImageSupport().Length() ).CompareF( - KImageSupport() ) != 0 ) - { - // if mime type does not match to object type, this is - // not the correct resource. - delete pInfo; pInfo = NULL; - continue; - } - } - */ - // use the first suitable res field as candidate which will be - // returned if better is not found. - // More sophisticated solution would be to compare resolution - // etc. attributes to determine the best candidate, - if ( 0 == bestCandidate ) - { - bestCandidate = elms[i]; - } - delete pInfo; pInfo = NULL; - } - else - { - // No mandatory protocolinfo attribute. This is not what we want. - } - } - if ( found ) - { - bestCandidate = elms[i]; - } - - // close the elements array - elms.Close(); - - if( bestCandidate == 0 ) - { - User::Leave( KErrNotFound ); - } - return *bestCandidate; - } - - -// -------------------------------------------------------------------------- -// UPnPItemUtility::FindElementByName -//--------------------------------------------------------------------------- -EXPORT_C const CUpnpElement* UPnPItemUtility::FindElementByName( - const CUpnpObject& aObject, const TDesC8& aName ) - { - __LOG( "UpnpItemUtility:FindElementByName" ); - - CUpnpElement* element = NULL; - const RUPnPElementsArray& array = - const_cast(aObject).GetElements(); - for( TInt i = 0; i < array.Count(); i++ ) - { - if( array[ i ]->Name() == aName ) - { - element = array[ i ]; - i = array.Count(); - } - } - return element; - } - -// -------------------------------------------------------------------------- -// UPnPItemUtility::FindElementByNameL -//--------------------------------------------------------------------------- -EXPORT_C const CUpnpElement& UPnPItemUtility::FindElementByNameL( - const CUpnpObject& aObject, const TDesC8& aName ) - { - __LOG( "UpnpItemUtility:FindElementByNameL" ); - - const CUpnpElement* element = FindElementByName( - aObject, aName ); - if( !element ) - { - User::Leave( KErrNotFound ); - } - return *element; - } - -// -------------------------------------------------------------------------- -// UPnPItemUtility::FindAttributeByName -//--------------------------------------------------------------------------- -EXPORT_C const CUpnpAttribute* UPnPItemUtility::FindAttributeByName( - const CUpnpElement& aElement, const TDesC8& aName ) - { - __LOG( "UpnpItemUtility:FindAttributeByName" ); - - CUpnpAttribute* attribute = NULL; - const RUPnPAttributesArray& array = - const_cast(aElement).GetAttributes(); - - for( TInt i = 0; i < array.Count(); i++ ) - { - - TBufC8<255> buf(array[ i ]->Name()); - if( array[ i ]->Name() == aName ) - { - attribute = array[ i ]; - i = array.Count(); - } - } - return attribute; - } - -// -------------------------------------------------------------------------- -// UPnPItemUtility::FindAttributeByNameL -//--------------------------------------------------------------------------- -EXPORT_C const CUpnpAttribute& UPnPItemUtility::FindAttributeByNameL( - const CUpnpElement& aElement, const TDesC8& aName ) - { - __LOG( "UpnpItemUtility:FindAttributeByNameL" ); - - const CUpnpAttribute* attribute = FindAttributeByName( - aElement, aName ); - if( !attribute ) - { - User::Leave( KErrNotFound ); - } - return *attribute; - } - -// -------------------------------------------------------------------------- -// UPnPItemUtility::UpnpDateAsTTime -//--------------------------------------------------------------------------- -EXPORT_C TInt UPnPItemUtility::UPnPDateAsTTime( - const TDesC8& aUpnpDate, TTime& aTime ) - { - __LOG( "UpnpItemUtility:UpnpDateAsTTime" ); - - TRAPD( err, UPnPItemUtility::UPnPDateAsTTimeL( aUpnpDate, aTime ) ); - return err; - } - -// -------------------------------------------------------------------------- -// UPnPItemUtility::UpnpDurationAsMilliseconds -//--------------------------------------------------------------------------- -EXPORT_C TInt UPnPItemUtility::UPnPDurationAsMilliseconds( - const TDesC8& aDuration, TInt& aMilliseconds ) - { - __LOG( "UpnpItemUtility:UpnpDurationAsMilliseconds" ); - - TInt retVal = KErrNone; - if( aDuration.Length() > 0 ) - { - // Check if information is actually returned by the device - if( aDuration.Compare( KValueNotImplemented ) != 0 ) - { - TInt time = 0; - TChar separator( KCodeSemicolon ); - TInt lposit = aDuration.Locate( separator ); - - if ( lposit != KErrNotFound ) - { - TInt rposit = aDuration.LocateReverse( separator ); - if( rposit != lposit ) - { - // Hours - TLex8 lex( aDuration.Left( lposit ) ); - retVal = lex.Val( time ); - if( retVal == KErrNone ) - { - // Convert to ms and add - aMilliseconds += time * 3600 * 1000; - // Minutes - lex.Assign( aDuration.Mid( - lposit + 1, rposit - lposit - 1 ) ); - retVal = lex.Val( time ); - if( retVal == KErrNone ) - { - // Convert to ms and add - aMilliseconds += time * 60* 1000; - // Seconds - lex.Assign( aDuration.Mid( - rposit + 1, 2 ) ); - retVal = lex.Val( time ); - if( retVal == KErrNone ) - { - // Convert to ms and add - aMilliseconds += time * 1000; - } - } - } - } - else - { - retVal = KErrNotSupported; - } - } - else - { - retVal = KErrNotSupported; - } - } - else - { - retVal = KErrNotSupported; - } - } - else - { - retVal = KErrNotSupported; - } - - return retVal; - } - -void UPnPItemUtility::UPnPDateAsTTimeL( const TDesC8& aUpnpDate, - TTime& aTime ) - { - // This method is capable of handling the most common dc:date formats: - // CCYY-MM-DD and CCYY-MM-DDThh:mm:ss - // Rest of the dc:date formats are handled as well, but they might not - // be converted precisely - - TBuf formatDateString; - HBufC* dateString = HBufC::NewL( aUpnpDate.Length() ); - dateString->Des().Copy( aUpnpDate ); - - if( aUpnpDate.Length() >= KDateStringLength ) - { - // CCYY-MM-DD --> CCYYMMDD - formatDateString.Copy( dateString->Des().Left( 4 ) ); // Year - formatDateString.Append( dateString->Des().Mid( 5,2 ) ); // Month - formatDateString.Append( dateString->Des().Mid( 8,2 ) ); // Day - - if( aUpnpDate.Length() >= KDateTimeStringLength ) - { - // hh:mm:ss --> hhmmss - formatDateString.Append( KSeparator ); - // Hours - formatDateString.Append( dateString->Des().Mid( 11, 2 ) ); - // Minutes - formatDateString.Append( dateString->Des().Mid( 14, 2 ) ); - // Seconds - formatDateString.Append( dateString->Des().Mid( 17, 2 ) ); - } - else - { - // hh:mm:ss --> 000000 - formatDateString.Append( KSeparator ); - formatDateString.Append( KNullTime ); - } - } - delete dateString; - - User::LeaveIfError( aTime.Set( formatDateString ) ); - } - +/* +* Copyright (c) 2007 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: Utility for parsing upnp items +* +*/ + + + + + + +// INCLUDE FILES +// System +#include + +// dlnasrv / mediaserver api +#include +#include + +// dlnasrv / avcontroller helper api +#include "upnpconstantdefs.h" // for KValueNotImplemented +#include "upnpitemutility.h" + +_LIT( KComponentLogfile, "upnpavcontrollerhelper.txt"); +#include "upnplog.h" + +// CONSTANTS +const TInt KDateStringLength = 10; +const TInt KDateTimeStringLength = 19; +const TInt KMaxDateStringLength = 30; +const TInt KCodeSemicolon = 58; +_LIT( KSeparator, ":" ); +_LIT( KNullTime, "000000" ); +_LIT8( KHttp, "http://" ); +_LIT8( KCiParam, "DLNA.ORG_CI" ); + +/* removed due to M-DMC CTT test case 7.3.26.2 +_LIT8( KAudioSupport, "audio/" ); +_LIT8( KImageSupport, "image/" ); +_LIT8( KVideoSupport, "video/" ); +*/ + +// ============================ LOCAL FUNCTIONS ============================= + +// -------------------------------------------------------------------------- +// UPnPItemUtility::BelongsToClass +//--------------------------------------------------------------------------- +EXPORT_C TBool UPnPItemUtility::BelongsToClass( + const CUpnpObject& aObject, + const TDesC8& aClass ) + { + TBool beginsWith = + ( aObject.ObjectClass().Find( aClass ) == 0 ); + return beginsWith; + } + +// -------------------------------------------------------------------------- +// UPnPItemUtility::GetResElements +//--------------------------------------------------------------------------- +EXPORT_C void UPnPItemUtility::GetResElements( + const CUpnpObject& aObject, + RUPnPElementsArray& aResElementsArray ) + { + const RUPnPElementsArray& array = + const_cast(aObject).GetElements(); + + for( TInt i = 0; i < array.Count(); i++ ) + { + if( array[ i ]->Name() == KElementRes() ) + { + aResElementsArray.Append( array[ i ] ); + } + } + } + +// -------------------------------------------------------------------------- +// UPnPItemUtility::ResourceFromItemL +//--------------------------------------------------------------------------- +EXPORT_C const CUpnpElement& UPnPItemUtility::ResourceFromItemL( + const CUpnpItem& aItem ) + { + __LOG( "UpnpItemUtility:ResourceFromItemL" ); + + // Obtain list of item's res elements + RUPnPElementsArray elms; + GetResElements( aItem, elms ); + TInt count = elms.Count(); + + CUpnpDlnaProtocolInfo* pInfo = NULL; + TBool found = EFalse; + TInt i(0); + // bestCandidate is an index of some res element in the list. This res + // will be considered as the best candidate for desired res and that + // candidate will be returned if no res element contains false CI-flag. + + const CUpnpElement* bestCandidate = 0; + + // determine which resource is the original one + // 1. In DLNA 1.5 case, parse protocolInfo attribute and see if some res + // element has CI-flag false (=not converted so that is what we want) + // 2. In non-DLNA 1.5 case and in DLNA 1.5 case where CI-flag does not + // exist, do the following: + // o filter out other than HTTP GET resources (internal uri's, RTP) + // o filter out resources that do not match itemtype (mime type of + // audio file resources should start with "audio/" etc.) + for( i = 0 ; i < count; i++ ) + { + // Make sure that it is a HTTP GET resource. Otherwise continue. + if( elms[ i ]->Value().Left( KHttp.iTypeLength ).Compare( KHttp() ) + != 0 ) + { + continue; + } + + // Obtain protocolInfo of the res element. + const CUpnpAttribute* attr = FindAttributeByName( + *elms[i], KAttributeProtocolInfo() ); + if ( attr ) + { + TRAP_IGNORE( pInfo = CUpnpDlnaProtocolInfo::NewL( attr->Value() ) ); + if( !pInfo ) + { + //if pInfo, start next one! + continue; + } + // check if CI parameter is false or it doesn't have CI parameters at all. + //for upnp item, always the first res element is the best, resolution + // should be checked in the future + if ( ( attr->Value().Find( KCiParam() ) != KErrNotFound && + pInfo->CiParameter() == EFalse ) || + attr->Value().Find( KCiParam() ) == KErrNotFound ) + { + // end loop, we found what we were looking for. + found = ETrue; + delete pInfo; pInfo = NULL; + break; + } + +/* removed due to M-DMC CTT test case 7.3.26.2 + // check that mimetype corresponds to objectType + TPtrC8 mime = pInfo->ThirdField(); + + TPtrC8 objectClass = aItem.ObjectClass(); + if ( objectClass.Compare( KClassAudio ) == 0 ) + { + if ( mime.Left( KAudioSupport().Length() ).CompareF( + KAudioSupport() ) != 0 ) + { + // if mime type does not match to object type, this is + // not the correct resource. + delete pInfo; pInfo = NULL; + continue; + } + } + else if ( objectClass.Compare( KClassVideo ) == 0 ) + { + if ( mime.Left( KVideoSupport().Length() ).CompareF( + KVideoSupport() ) != 0 ) + { + // if mime type does not match to object type, this is + // not the correct resource. + delete pInfo; pInfo = NULL; + continue; + } + } + else if ( objectClass.Compare( KClassImage ) == 0 ) + { + if ( mime.Left( KImageSupport().Length() ).CompareF( + KImageSupport() ) != 0 ) + { + // if mime type does not match to object type, this is + // not the correct resource. + delete pInfo; pInfo = NULL; + continue; + } + } + */ + // use the first suitable res field as candidate which will be + // returned if better is not found. + // More sophisticated solution would be to compare resolution + // etc. attributes to determine the best candidate, + if ( 0 == bestCandidate ) + { + bestCandidate = elms[i]; + } + delete pInfo; pInfo = NULL; + } + else + { + // No mandatory protocolinfo attribute. This is not what we want. + } + } + if ( found ) + { + bestCandidate = elms[i]; + } + + // close the elements array + elms.Close(); + + if( bestCandidate == 0 ) + { + User::Leave( KErrNotFound ); + } + return *bestCandidate; + } + + +// -------------------------------------------------------------------------- +// UPnPItemUtility::FindElementByName +//--------------------------------------------------------------------------- +EXPORT_C const CUpnpElement* UPnPItemUtility::FindElementByName( + const CUpnpObject& aObject, const TDesC8& aName ) + { + __LOG( "UpnpItemUtility:FindElementByName" ); + + CUpnpElement* element = NULL; + const RUPnPElementsArray& array = + const_cast(aObject).GetElements(); + for( TInt i = 0; i < array.Count(); i++ ) + { + if( array[ i ]->Name() == aName ) + { + element = array[ i ]; + i = array.Count(); + } + } + return element; + } + +// -------------------------------------------------------------------------- +// UPnPItemUtility::FindElementByNameL +//--------------------------------------------------------------------------- +EXPORT_C const CUpnpElement& UPnPItemUtility::FindElementByNameL( + const CUpnpObject& aObject, const TDesC8& aName ) + { + __LOG( "UpnpItemUtility:FindElementByNameL" ); + + const CUpnpElement* element = FindElementByName( + aObject, aName ); + if( !element ) + { + User::Leave( KErrNotFound ); + } + return *element; + } + +// -------------------------------------------------------------------------- +// UPnPItemUtility::FindAttributeByName +//--------------------------------------------------------------------------- +EXPORT_C const CUpnpAttribute* UPnPItemUtility::FindAttributeByName( + const CUpnpElement& aElement, const TDesC8& aName ) + { + __LOG( "UpnpItemUtility:FindAttributeByName" ); + + CUpnpAttribute* attribute = NULL; + const RUPnPAttributesArray& array = + const_cast(aElement).GetAttributes(); + + for( TInt i = 0; i < array.Count(); i++ ) + { + + TBufC8<255> buf(array[ i ]->Name()); + if( array[ i ]->Name() == aName ) + { + attribute = array[ i ]; + i = array.Count(); + } + } + return attribute; + } + +// -------------------------------------------------------------------------- +// UPnPItemUtility::FindAttributeByNameL +//--------------------------------------------------------------------------- +EXPORT_C const CUpnpAttribute& UPnPItemUtility::FindAttributeByNameL( + const CUpnpElement& aElement, const TDesC8& aName ) + { + __LOG( "UpnpItemUtility:FindAttributeByNameL" ); + + const CUpnpAttribute* attribute = FindAttributeByName( + aElement, aName ); + if( !attribute ) + { + User::Leave( KErrNotFound ); + } + return *attribute; + } + +// -------------------------------------------------------------------------- +// UPnPItemUtility::UpnpDateAsTTime +//--------------------------------------------------------------------------- +EXPORT_C TInt UPnPItemUtility::UPnPDateAsTTime( + const TDesC8& aUpnpDate, TTime& aTime ) + { + __LOG( "UpnpItemUtility:UpnpDateAsTTime" ); + + TRAPD( err, UPnPItemUtility::UPnPDateAsTTimeL( aUpnpDate, aTime ) ); + return err; + } + +// -------------------------------------------------------------------------- +// UPnPItemUtility::UpnpDurationAsMilliseconds +//--------------------------------------------------------------------------- +EXPORT_C TInt UPnPItemUtility::UPnPDurationAsMilliseconds( + const TDesC8& aDuration, TInt& aMilliseconds ) + { + __LOG( "UpnpItemUtility:UpnpDurationAsMilliseconds" ); + + TInt retVal = KErrNone; + if( aDuration.Length() > 0 ) + { + // Check if information is actually returned by the device + if( aDuration.Compare( KValueNotImplemented ) != 0 ) + { + TInt time = 0; + TChar separator( KCodeSemicolon ); + TInt lposit = aDuration.Locate( separator ); + + if ( lposit != KErrNotFound ) + { + TInt rposit = aDuration.LocateReverse( separator ); + if( rposit != lposit ) + { + // Hours + TLex8 lex( aDuration.Left( lposit ) ); + retVal = lex.Val( time ); + if( retVal == KErrNone ) + { + // Convert to ms and add + aMilliseconds += time * 3600 * 1000; + // Minutes + lex.Assign( aDuration.Mid( + lposit + 1, rposit - lposit - 1 ) ); + retVal = lex.Val( time ); + if( retVal == KErrNone ) + { + // Convert to ms and add + aMilliseconds += time * 60* 1000; + // Seconds + lex.Assign( aDuration.Mid( + rposit + 1, 2 ) ); + retVal = lex.Val( time ); + if( retVal == KErrNone ) + { + // Convert to ms and add + aMilliseconds += time * 1000; + } + } + } + } + else + { + retVal = KErrNotSupported; + } + } + else + { + retVal = KErrNotSupported; + } + } + else + { + retVal = KErrNotSupported; + } + } + else + { + retVal = KErrNotSupported; + } + + return retVal; + } + +void UPnPItemUtility::UPnPDateAsTTimeL( const TDesC8& aUpnpDate, + TTime& aTime ) + { + // This method is capable of handling the most common dc:date formats: + // CCYY-MM-DD and CCYY-MM-DDThh:mm:ss + // Rest of the dc:date formats are handled as well, but they might not + // be converted precisely + + TBuf formatDateString; + HBufC* dateString = HBufC::NewL( aUpnpDate.Length() ); + dateString->Des().Copy( aUpnpDate ); + + if( aUpnpDate.Length() >= KDateStringLength ) + { + // CCYY-MM-DD --> CCYYMMDD + formatDateString.Copy( dateString->Des().Left( 4 ) ); // Year + formatDateString.Append( dateString->Des().Mid( 5,2 ) ); // Month + formatDateString.Append( dateString->Des().Mid( 8,2 ) ); // Day + + if( aUpnpDate.Length() >= KDateTimeStringLength ) + { + // hh:mm:ss --> hhmmss + formatDateString.Append( KSeparator ); + // Hours + formatDateString.Append( dateString->Des().Mid( 11, 2 ) ); + // Minutes + formatDateString.Append( dateString->Des().Mid( 14, 2 ) ); + // Seconds + formatDateString.Append( dateString->Des().Mid( 17, 2 ) ); + } + else + { + // hh:mm:ss --> 000000 + formatDateString.Append( KSeparator ); + formatDateString.Append( KNullTime ); + } + } + delete dateString; + + User::LeaveIfError( aTime.Set( formatDateString ) ); + } +