diff -r 6369bfd1b60d -r 08b5eae9f9ff upnpframework/upnputilities/src/upnppathutility.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upnpframework/upnputilities/src/upnppathutility.cpp Wed Nov 03 11:45:09 2010 +0200 @@ -0,0 +1,614 @@ +/* +* Copyright (c) 2002-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 class to get path related info for the media files +*/ + +// INCLUDE FILES +#include +#include "upnpsettingsengine.h" +#include "upnpconstantdefs.h" +#include +#include +#include +#include + +#include "upnppathutility.h" +#include "Upnpcommonutils.h" + +// CONSTANTS +_LIT( KYearMonthDayFormat, "%04d\\%02d\\%02d\\"); +_LIT( KTitleExtFormat, "%S%S"); +_LIT( KArtistFormat, "%S\\"); +_LIT( KAlbumFormat, "%S\\"); +_LIT( KSlash, "\\"); +_LIT( KSlashData, "\\Data\\"); +_LIT( KUnknown, "Unknown"); + +_LIT( KSeparator, ":" ); +_LIT( KNullTime, "000000" ); + +const TInt KDateStringLength = 10; +const TInt KDateTimeStringLength = 19; +const TInt KMaxDateStringLength = 30; + +// ============================ MEMBER FUNCTIONS ============================ + +// --------------------------------------------------------------------------- +// CUPnPPathUtility::CUPnPPathUtility +// C++ default constructor can NOT contain any code, that +// might leave. +// --------------------------------------------------------------------------- +// +CUPnPPathUtility::CUPnPPathUtility() + { + } + +// --------------------------------------------------------------------------- +// CUPnPPathUtility::NewL +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +EXPORT_C CUPnPPathUtility* CUPnPPathUtility::NewL() + { + CUPnPPathUtility* self = CUPnPPathUtility::NewLC(); + CleanupStack::Pop(); + return self; + } + +// --------------------------------------------------------------------------- +// CUPnPPathUtility::NewLC +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +EXPORT_C CUPnPPathUtility* CUPnPPathUtility::NewLC() + { + CUPnPPathUtility* self = new( ELeave ) CUPnPPathUtility; + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// --------------------------------------------------------------------------- +// CUPnPPathUtility::ConstructL +// Symbian 2nd phase constructor can leave. +// --------------------------------------------------------------------------- +// +void CUPnPPathUtility::ConstructL() + { + iSettingsEngine = CUPnPSettingsEngine::NewL(); + } + +// --------------------------------------------------------------------------- +// CUPnPPathUtility::~CUPnPPathUtility() +// Destructor +// --------------------------------------------------------------------------- +// +EXPORT_C CUPnPPathUtility::~CUPnPPathUtility() + { + delete iSettingsEngine; + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::GetCopyPathDriveL +// Gets the drive for the copy operation +// (other items were commented in a header). +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPPathUtility::GetCopyPathDriveL( + TDriveNumber& aDrive ) const + { + iSettingsEngine->GetCopyLocationDriveL( aDrive ); + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::GetCopyPathL +// Returns the path of the upnp item to be copied +// (other items were commented in a header). +// -------------------------------------------------------------------------- +// +EXPORT_C HBufC* CUPnPPathUtility::GetCopyPathL( + const CUpnpItem& aItem, + const CUpnpElement& aResource, + TBool aAppendTitleAndExt ) const + { + TDriveNumber drive; + iSettingsEngine->GetCopyLocationDriveL( drive ); + return GetCreateCopyPathL( aItem, + aResource, + aAppendTitleAndExt, + EFalse, + drive ); + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::GetCopyPathL +// Returns the path of the upnp item to be copied +// (other items were commented in a header). +// -------------------------------------------------------------------------- +// +EXPORT_C HBufC* CUPnPPathUtility::GetCopyPathL( + const CUpnpItem& aItem, + const CUpnpElement& aResource, + TBool aAppendTitleAndExt, + TDriveNumber aDriveNumber ) const + { + + return GetCreateCopyPathL( aItem, + aResource, + aAppendTitleAndExt, + EFalse, + aDriveNumber ); + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::CreateCopyPathL +// Returns the path of the upnp item to be copied +// Creates the path if necessary and appends the filename and extension if +// required +// (other items were commented in a header). +// -------------------------------------------------------------------------- +// +EXPORT_C HBufC* CUPnPPathUtility::CreateCopyPathL( + const CUpnpItem& aItem, + const CUpnpElement& aResource, + TBool aAppendTitleAndExt ) const + { + TDriveNumber drive; + iSettingsEngine->GetCopyLocationDriveL( drive ); + return GetCreateCopyPathL( aItem, + aResource, + aAppendTitleAndExt, + ETrue, + drive ); + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::CreateCopyPathL +// Returns the path of the upnp item to be copied +// Creates the path if necessary and appends the filename and extension if +// required +// (other items were commented in a header). +// -------------------------------------------------------------------------- +// +EXPORT_C HBufC* CUPnPPathUtility::CreateCopyPathL( + const CUpnpItem& aItem, + const CUpnpElement& aResource, + TBool aAppendTitleAndExt, + TDriveNumber aDriveNumber ) const + { + return GetCreateCopyPathL( aItem, + aResource, + aAppendTitleAndExt, + ETrue, + aDriveNumber ); + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::RemoveEmptyFoldersFromCopyPathL +// Removes empty folders from the copy path +// (other items were commented in a header). +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPPathUtility::RemoveEmptyFoldersFromCopyPathL( + const TDesC& aCopyPath ) + { + TPtrC basePath; + const TDesC& soundsPath = PathInfo::SoundsPath(); + const TDesC& videosPath = PathInfo::VideosPath(); + const TDesC& imagesPath = PathInfo::ImagesPath(); + const TDesC& othersPath = PathInfo::OthersPath(); + + TInt baseLength = 0; + TInt found = KErrNotFound; + if ( KErrNotFound != ( found = aCopyPath.Find( + soundsPath ) ) ) + { + baseLength = soundsPath.Length(); + } + else if ( KErrNotFound != ( found = aCopyPath.Find( + videosPath ) ) ) + { + baseLength = videosPath.Length(); + } + else if ( KErrNotFound != ( found = aCopyPath.Find( + imagesPath ) ) ) + { + baseLength = imagesPath.Length(); + } + else if ( KErrNotFound != ( found = aCopyPath.Find( + othersPath ) ) ) + { + baseLength = othersPath.Length(); + } + + if ( KErrNotFound != found ) + { + TPtrC basePath = aCopyPath.Left( found + baseLength ); + TParse parsePath; + User::LeaveIfError( parsePath.Set( aCopyPath, NULL, NULL ) ); + //Remove filename and extension before passing the copy path + RemoveEmptyFoldersL( basePath, parsePath.DriveAndPath() ); + } + + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::GetCreateCopyPathL +// Returns the path of the upnp item to be copied +// Creates the path if necessary and appends the filename and extension if +// required +// (other items were commented in a header). +// -------------------------------------------------------------------------- +// +HBufC* CUPnPPathUtility::GetCreateCopyPathL( + const CUpnpItem& aItem, + const CUpnpElement& aResource, + TBool aAppendTitleAndExt, + TBool aCreatePath, + TDriveNumber aDriveNumber ) const + { + + HBufC* path = HBufC::NewLC( KMaxPath ); + TPtr refPath = path->Des(); + + TDriveUnit driveUnit = TDriveUnit( aDriveNumber ); + AppendDataL( refPath, driveUnit.Name() ); + if ( EDriveC == driveUnit ) + { + //C:\\Data\\(Images/Videos/Sounds).... + AppendDataL( refPath, KSlashData ); + } + else + { + //\\(Images/Videos/Sounds).... + AppendDataL( refPath, KSlash ); + } + + // Get the protocolinfo-attribute + const CUpnpAttribute* pInfo = FindAttributeByName( + aResource, KAttributeProtocolInfo ); + if ( NULL == pInfo ) + { + User::Leave( KErrArgument ); + } + + CUpnpDlnaProtocolInfo* dlnaInfo = + CUpnpDlnaProtocolInfo::NewL( pInfo->Value() ); + CleanupStack::PushL( dlnaInfo ); + TUPnPItemType fileType = UPnPCommonUtils::FileTypeByMimeTypeL( + dlnaInfo->ThirdField() ); + + switch( fileType ) + { + case ETypeAudio: + { + AppendDataL( refPath, PathInfo::SoundsPath() ); + AppendArtistAlbumL( refPath, aItem ); + break; + } + case ETypeVideo: + { + AppendDataL( refPath, PathInfo::VideosPath() ); + AppendYearMonthDayL( refPath, aItem ); + break; + } + case ETypeImage: + { + AppendDataL( refPath, PathInfo::ImagesPath() ); + AppendYearMonthDayL( refPath, aItem ); + break; + } + case ETypePlaylist: + case ETypeOther: + default: + { + AppendDataL( refPath, PathInfo::OthersPath() ); + } + } + if( aCreatePath ) + { + RFs fs; + User::LeaveIfError( fs.Connect() ); + CleanupClosePushL(fs); + BaflUtils::EnsurePathExistsL( fs, refPath ); + CleanupStack::PopAndDestroy(&fs); + } + if( aAppendTitleAndExt ) + { + AppendTitleAndExtL( refPath, *dlnaInfo, aItem ); + } + + CleanupStack::PopAndDestroy( dlnaInfo ); + CleanupStack::Pop( path ); + + return path; + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::AppendTitleAndExtL +// Appends title and extension to the path. +// -------------------------------------------------------------------------- +// +void CUPnPPathUtility::AppendTitleAndExtL( + TDes& aPath, CUpnpDlnaProtocolInfo& aProtocolInfo, + const CUpnpItem& aItem ) const + { + HBufC* fileExt = UPnPCommonUtils::FileExtensionByMimeTypeL( + aProtocolInfo.ThirdField() ); + + User::LeaveIfNull( fileExt ); + CleanupStack::PushL( fileExt ); + + HBufC* title16 = UpnpString::ToUnicodeL( aItem.Title() ); + CleanupStack::PushL( title16 ); + HBufC* title16checked = + UPnPCommonUtils::ReplaceIllegalFilenameCharactersL( *title16 ); + CleanupStack::PopAndDestroy( title16 ); + + CheckBufferSpaceL( aPath, + title16checked->Length()+fileExt->Length() ); + + aPath.AppendFormat( KTitleExtFormat(), title16checked, fileExt ); + + delete title16checked; title16checked = NULL; + CleanupStack::PopAndDestroy( fileExt ); + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::AppendYearMonthDayL +// Appends year, month and day to the path. +// -------------------------------------------------------------------------- +// +void CUPnPPathUtility::AppendYearMonthDayL( + TDes& aPath, const CUpnpItem& aItem ) const + { + // Get the date-element + const CUpnpElement* dateElem = FindElementByName( + aItem, KElementDate ); + + TTime date; date.HomeTime(); + TInt offsetMonthDay = 1; + // Use date element time instead of current time, + // if element exist + if ( dateElem != NULL ) + { + UPnPDateAsTTimeL( dateElem->Value(), date ); + offsetMonthDay = 0; + } + TDateTime ymd = date.DateTime(); + CheckBufferSpaceL( aPath, 11 ); //4(year)+2(month)+2(day)+3(\) + + aPath.AppendFormat( KYearMonthDayFormat(), + ymd.Year(), + ymd.Month() + offsetMonthDay, + ymd.Day() + offsetMonthDay ); + + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::AppendArtistAlbumL +// Appends artist and album to the path. +// -------------------------------------------------------------------------- +// +void CUPnPPathUtility::AppendArtistAlbumL( + TDes& aPath, const CUpnpItem& aItem ) const + { + + // Get the artist-element + const CUpnpElement* artistElem = FindElementByName( + aItem, KElementArtist ); + if ( NULL != artistElem ) + { + HBufC* artist = UpnpString::ToUnicodeL( artistElem->Value() ); + CleanupStack::PushL( artist ); + + HBufC* artistchecked = + UPnPCommonUtils::ReplaceIllegalDirNameCharactersL( *artist ); + CleanupStack::PopAndDestroy( artist ); + + CheckBufferSpaceL( aPath, artistchecked->Length()+1 );// 1 for '\' + aPath.AppendFormat( KArtistFormat(), artistchecked ); + + delete artistchecked; + } + else + { + CheckBufferSpaceL( aPath, KUnknown().Length()+1 ); // 1 for '\' + aPath.AppendFormat( KArtistFormat(), &KUnknown() ); + } + + // Get the album-element + const CUpnpElement* albumElem = FindElementByName( + aItem, KElementAlbum ); + if ( NULL != albumElem ) + { + HBufC* album = UpnpString::ToUnicodeL( albumElem->Value() ); + CleanupStack::PushL( album ); + + HBufC* albumchecked = + UPnPCommonUtils::ReplaceIllegalDirNameCharactersL( *album ); + CleanupStack::PopAndDestroy( album ); + + CheckBufferSpaceL( aPath, albumchecked->Length()+1 );// 1 for '\' + aPath.AppendFormat( KAlbumFormat(), albumchecked ); + + delete albumchecked; + } + else + { + CheckBufferSpaceL( aPath, KUnknown().Length()+1 ); // 1 for '\' + aPath.AppendFormat( KAlbumFormat(), &KUnknown() ); + } + + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::AppendDataL +// Appends data to the path's buffer. +// -------------------------------------------------------------------------- +// +void CUPnPPathUtility::AppendDataL( + TDes& aPath, const TDesC& aData ) const + { + CheckBufferSpaceL( aPath, aData ); + aPath.Append( aData ); + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::CheckBufferSpaceL +// Checks whether the data can be appended to buffer or not. +// -------------------------------------------------------------------------- +// +void CUPnPPathUtility::CheckBufferSpaceL( + const TDes& aPath, const TDesC& aData ) const + { + CheckBufferSpaceL( aPath, aData.Length() ); + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::CheckBufferSpaceL +// Checks whether the data of the specified length +// can be appended to buffer or not. +// -------------------------------------------------------------------------- +// +void CUPnPPathUtility::CheckBufferSpaceL( + const TDes& aPath, const TInt& aLength ) const + { + if ( (aPath.Length() + aLength) > aPath.MaxLength() ) + { + User::Leave( KErrOverflow ); + } + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::FindElementByName +// Finds an element within an object. +//--------------------------------------------------------------------------- +const CUpnpElement* CUPnPPathUtility::FindElementByName( + const CUpnpObject& aObject, const TDesC8& aName ) const + { + 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; + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::FindAttributeByName +// Finds an attribute within an element. +//--------------------------------------------------------------------------- +const CUpnpAttribute* CUPnPPathUtility::FindAttributeByName( + const CUpnpElement& aElement, const TDesC8& aName ) const + { + 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; + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::UPnPDateAsTTimeL +// Converts upnp date to TTime object. +//--------------------------------------------------------------------------- +void CUPnPPathUtility::UPnPDateAsTTimeL( const TDesC8& aUpnpDate, + TTime& aTime ) const + { + // 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 ) ); + } + +// -------------------------------------------------------------------------- +// CUPnPPathUtility::RemoveEmptyFoldersL +// Removes empty folders from the path +// (other items were commented in a header). +// -------------------------------------------------------------------------- +// +void CUPnPPathUtility::RemoveEmptyFoldersL( + const TDesC& aBasePath, const TDesC& aFullPath ) + { + + RFs fs; + User::LeaveIfError( fs.Connect() ); + CleanupClosePushL(fs); + + TParse parsePath; + User::LeaveIfError( parsePath.Set( aFullPath, NULL, NULL ) ); + while( 0 != aBasePath.Compare( parsePath.DriveAndPath() ) ) + { + if ( KErrNone != fs.RmDir( parsePath.DriveAndPath() ) || + KErrNone != parsePath.PopDir() ) + { + break; + } + } + CleanupStack::PopAndDestroy(&fs); + + } + +// End of File