diff -r 6369bfd1b60d -r 08b5eae9f9ff upnpsharing/upnpsharingalgorithm/src/upnpsharingalgorithmimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upnpsharing/upnpsharingalgorithm/src/upnpsharingalgorithmimpl.cpp Wed Nov 03 11:45:09 2010 +0200 @@ -0,0 +1,714 @@ +/* +* Copyright (c) 2009 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: Implementation of the class CUpnpSharingAlgorithmImpl. +* +*/ + +// INCLUDE FILES, SYSTEM +#include +#include +#include "upnpcommonutils.h" +#include "upnpmetadatafetcher.h" +#include "upnpfileutility.h" +#include // ConvertFromUnicodeToUtf8L +#include // File existence check +#include "upnpconstantdefs.h" +#include // for array cleanup + +// INCLUDE FILES, USER +#include "upnpcontainerresolver.h" +#include "upnpsharingao.h" +#include "upnpcdsreaderao.h" +#include "upnpsharingalgorithmimpl.h" +#include "upnpsharingalgorithmconstants.h" +#include "upnplog.h" +#include "upnpcdsliteobject.h" +#include "upnpcdsliteobjectarray.h" + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithm::NewL +// -------------------------------------------------------------------------- +// +CUpnpSharingAlgorithmImpl* CUpnpSharingAlgorithmImpl::NewL() + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithmImpl::NewL" ); + + CUpnpSharingAlgorithmImpl* self = CUpnpSharingAlgorithmImpl::NewLC(); + CleanupStack::Pop( self ); + + return self; + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::NewLC +// Two-phased constructor +// -------------------------------------------------------------------------- +// +CUpnpSharingAlgorithmImpl* CUpnpSharingAlgorithmImpl::NewLC() + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithmImpl::NewLC" ); + + CUpnpSharingAlgorithmImpl* self = + new ( ELeave ) CUpnpSharingAlgorithmImpl(); + CleanupStack::PushL( self ); + self->ConstructL(); + + return self; + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::~CUpnpSharingAlgorithmImpl +// -------------------------------------------------------------------------- +// +CUpnpSharingAlgorithmImpl::~CUpnpSharingAlgorithmImpl() + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithmImpl::\ +~CUpnpSharingAlgorithmImpl" ); + + delete iContainerResolver; + delete iSharingAO; + delete iSharedContentArray; + + iMediaServer.Close(); + } + +// -------------------------------------------------------------------------- +// CCUpnpSharingAlgorithmImpl::ConstructL +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::ConstructL() + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithmImpl::\ +ConstructL" ); + + // connect to server + User::LeaveIfError( iMediaServer.Connect() ); + // Start server if not yet started + StartServer(); + + // An array to list all the shared files on the CDS + iSharedContentArray = CUpnpCdsLiteObjectArray::NewL(); + // container structure resolver + // contentarray is always up-to-date + iContainerResolver = + CUpnpContainerResolver::NewL( *iSharedContentArray ); + + CUpnpCdsReaderAO* cdsReader = + CUpnpCdsReaderAO::NewL( *iSharedContentArray ); + CleanupStack::PushL( cdsReader ); + cdsReader->ReadCdsStructureL(); + CleanupStack::PopAndDestroy( cdsReader ); + + // Active object for sharing and unsharing the items + iSharingAO = CUpnpSharingAO::NewL(); + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::ShareFileL +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::ShareFileL( + const TFileName & aFileName ) + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithm::\ + ShareFileL" ); + + // Check that file exists. Leaves with KErrArgument if not exist. + CheckFileExistenceL( aFileName ); + + // Check that file is not protected. Leaves with KAccessDenied if yes. + CheckFileProtectionL( aFileName ); + + if ( !IsFileSharedL( aFileName ) ) + { + // Start server if not yet started + StartServer(); + + // create upnpitem... + CUpnpItem* upnpItem = + UPnPMetadataFetcher::CreateItemFromFileLC( aFileName ); + + // Resolve container structure + RPointerArray containerArray = + iContainerResolver->ResolveContainerStructureL( *upnpItem ); + CleanupResetAndDestroyPushL( containerArray ); + + if ( containerArray.Count() ) + { + // Share containers + ShareContainersL( containerArray ); + + // parent container id for item is the last shared container id + TPtrC8 itemParentContainerId = + containerArray[ containerArray.Count()-1 ]->Id(); + // ... and share it + iSharingAO->ShareFileL( itemParentContainerId, upnpItem ); + + // Add the file to the shared content array + iSharedContentArray->AppendL( upnpItem ); + } + else + { + // All containers exists already. + // Resolver put parentid to item + iSharingAO->ShareFileL( upnpItem->ParentId(), upnpItem ); + + // Add the file to the shared content array + iSharedContentArray->AppendL( upnpItem ); + } + + // SHARE reference containers and items + ShareReferenceObjectsL( upnpItem ); + + // Cleanup + CleanupStack::PopAndDestroy( &containerArray ); + CleanupStack::PopAndDestroy( upnpItem ); + } + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::UnshareFileL +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::UnshareFileL( + const TFileName& aFileName ) + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithm::UnshareFileL" ); + + // Convert the filename to 8bit + HBufC8* filename = EscapeUtils::ConvertFromUnicodeToUtf8L( aFileName ); + CleanupStack::PushL( filename ); + + // Search the array for the item + TInt arrayindex = iSharedContentArray->FindByName( *filename ); + + // Continue only if the file was found + if ( arrayindex >= 0 ) + { + // Start server if not yet started + StartServer(); + + // Get the object reference + CUpnpCdsLiteObject& object = + iSharedContentArray->ObjectAtL( arrayindex ); + + // unshare references first + UnshareReferenceObjectsL( object ); + + // Checks the container tree and unshares if needed + // First container id to be checked is item's parentid + TBool containerUnshared = + UnshareEmptyContainersL( object.ParentId() ); + + // if container is not unshared the item needs to be unshared + if ( !containerUnshared ) + { + // Leave if ObjectId not found + if( object.ObjectId() == KNullDesC8 ) + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithm::\ + UnshareFileL, ObjectId not found!" ); + User::Leave( KErrCorrupt ); + } + + TInt objectIdInt( KErrNotFound ); + User::LeaveIfError( + objectIdInt = UPnPCommonUtils::DesC8ToInt( object.ObjectId() )); + + // Unshare the item + iSharingAO->UnshareFileL( objectIdInt ); + + // index must be retrieved again because reference item removal + // changes indexes + arrayindex = + iSharedContentArray->FindByObjectId(object.ObjectId()); + // Remove the file from the shared content array + iSharedContentArray->RemoveObjectAtL( arrayindex ); + } + else + { + // index must be retrieved again because removal of containers + // change indexes + arrayindex = iSharedContentArray->FindByName( *filename ); + // item was also unshared when container was unshared + // it's enough to remove item from contentarray + iSharedContentArray->RemoveObjectAtL( arrayindex ); + } + } + // Cleanup + CleanupStack::PopAndDestroy( filename ); + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::IsFileSharedL +// -------------------------------------------------------------------------- +// +TBool CUpnpSharingAlgorithmImpl::IsFileSharedL( + const TFileName& aFileName ) + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithmImpl::\ + IsFileSharedL" ); + + TBool returnValue = EFalse; + + // Convert the filename to 8bit + HBufC8* tempFilename = + EscapeUtils::ConvertFromUnicodeToUtf8L( aFileName ); + CleanupStack::PushL( tempFilename ); + + // Search the file from the array + TInt index = iSharedContentArray->FindByName( *tempFilename ); + if( index >= 0 ) + { + returnValue = ETrue; + } + + // Clean up + CleanupStack::PopAndDestroy( tempFilename ); + + return returnValue; + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::CheckFileExistenceL +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::CheckFileExistenceL( + const TFileName& aFileName ) + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithmImpl::\ +CheckFileExistenceL" ); + + TBool fileExists( EFalse ); + + RFs fsSession; + User::LeaveIfError( fsSession.Connect() ); // connect session + CleanupClosePushL( fsSession ); + + // check that file exists + fileExists = BaflUtils::FileExists( fsSession, aFileName ); + + CleanupStack::PopAndDestroy( &fsSession ); + + if ( !fileExists ) + { + User::Leave( KErrArgument ); + } + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::UnshareEmptyContainersL +// -------------------------------------------------------------------------- +// +TBool CUpnpSharingAlgorithmImpl::UnshareEmptyContainersL( TDesC8& aParentId ) + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithmImpl::\ +UnshareEmptyContainersL" ); + + TBool containerUnshared( EFalse ); + + // get top container id that does not contain item + // starting from container where item is. + RPointerArray containerList = + iContainerResolver->ResolveEmptyContainersL( aParentId ); + CleanupClosePushL( containerList ); + + TInt containerCount = containerList.Count(); + if ( containerCount ) + { + // Get top containerId which needs to be unshared. + TPtrC8 containerIdStr = containerList[containerCount-1]->ObjectId(); + TInt objectIdInt( KErrNotFound ); + User::LeaveIfError( + objectIdInt = UPnPCommonUtils::DesC8ToInt( containerIdStr )); + // unshares all objecs under this container with single call + TRAPD( error, iSharingAO->UnshareContainerL( objectIdInt )); + if ( !error ) + { + for ( TInt i = 0; i < containerCount; i++ ) + { + // get container's array index + TInt arrayIndex = + iSharedContentArray->FindByObjectId( + containerList[i]->ObjectId() ); + + // Remove the container from the shared content array + iSharedContentArray->RemoveObjectAtL( arrayIndex ); + } + } + containerUnshared = ETrue; + } + + CleanupStack::PopAndDestroy( &containerList ); + + return containerUnshared; + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::ShareContainersL +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::ShareContainersL( + RPointerArray& aContainerArray ) + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithm::\ +ShareContainersL" ); + + TPtrC8 previousContainerId( KNullDesC8 ); + + // Share containers + for ( TInt i = 0; i < aContainerArray.Count(); i++ ) + { + CUpnpContainer* container = aContainerArray[i]; + + // first container ( index = 0 ) have parent id ready + if ( container->ParentId() == KNullDesC8 ) + { + // parentid is previously shared container id + container->SetParentIdL( previousContainerId ); + } + + TInt error( KErrNone ); + TRAP( error, iSharingAO->ShareContainerL( container )); + if ( error ) + { + // remove shared objects from server because of error + RemoveSharedObjectsL( aContainerArray ); + User::LeaveIfError( error ); + } + // container got id on sharing - keep it safe for next container + // because it it used as parent container id + previousContainerId.Set( container->Id()); + + // no errors - append containers to cdsliteobjectarray + TRAP( error, iSharedContentArray->AppendL( container )); + if ( error ) + { + // remove shared objects from array because of error + RemoveSharedObjectsL( aContainerArray ); + User::LeaveIfError( error ); + } + } + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::ShareReferenceObjectsL +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::ShareReferenceObjectsL( CUpnpItem* aItem ) + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithm::\ +ShareReferenceObjectsL" ); + + // Get cds object from array. Reference item ids will be + // added to this item + TInt index = iSharedContentArray->FindByObjectId( aItem->Id() ); + CUpnpCdsLiteObject& object = iSharedContentArray->ObjectAtL( index ); + + // reset id because a new one will be given when reference is shared + aItem->SetIdL( KNullDesC8 ); + // reset refid field because item is reference + aItem->SetRefIdL( KNullDesC8 ); + // reset title + aItem->SetTitleL( KNullDesC8 ); + // reset parentId + aItem->SetParentIdL( KNullDesC8 ); + + if ( aItem->ObjectClass() == KClassAudioMusicTrack ) + { + // Resolve genre containers + RPointerArray refContainers = + iContainerResolver->ResolveReferenceContainersL( EGenreType, + *aItem ); + CleanupResetAndDestroyPushL( refContainers ); + if ( refContainers.Count() || + aItem->ParentId() != KNullDesC8 ) + { + // share container(s) and item + ShareReferenceObjectL( refContainers, object, *aItem ); + } + CleanupStack::PopAndDestroy( &refContainers ); + + // reset parentId + aItem->SetParentIdL( KNullDesC8 ); + // Resolve album containers + refContainers = + iContainerResolver->ResolveReferenceContainersL( EAlbumType, + *aItem ); + CleanupResetAndDestroyPushL( refContainers ); + if ( refContainers.Count() || + aItem->ParentId() != KNullDesC8 ) + { + // share container(s) and item + ShareReferenceObjectL( refContainers, object, *aItem ); + } + CleanupStack::PopAndDestroy( &refContainers ); + + // reset parentId + aItem->SetParentIdL( KNullDesC8 ); + // Resolve artist containers + refContainers = + iContainerResolver->ResolveReferenceContainersL( EArtistType, + *aItem ); + CleanupResetAndDestroyPushL( refContainers ); + if ( refContainers.Count() || + aItem->ParentId() != KNullDesC8 ) + { + // share container(s) and item + ShareReferenceObjectL( refContainers, object, *aItem ); + } + CleanupStack::PopAndDestroy( &refContainers ); + + // reset parentId + aItem->SetParentIdL( KNullDesC8 ); + // Resolve artist containers + refContainers = + iContainerResolver->ResolveReferenceContainersL( EMusicByDateType, + *aItem ); + CleanupResetAndDestroyPushL( refContainers ); + if ( refContainers.Count() || + aItem->ParentId() != KNullDesC8 ) + { + // share container(s) and item + ShareReferenceObjectL( refContainers, object, *aItem ); + } + CleanupStack::PopAndDestroy( &refContainers ); + } + + + else if ( aItem->ObjectClass() == KClassImage ) + { + // reset parentId + aItem->SetParentIdL( KNullDesC8 ); + // resolve date container + RPointerArray refContainers = + iContainerResolver->ResolveReferenceContainersL( EImageByDateType, + *aItem ); + CleanupResetAndDestroyPushL( refContainers ); + if ( refContainers.Count() || + aItem->ParentId() != KNullDesC8 ) + { + // share container(s) and item + ShareReferenceObjectL( refContainers, object, *aItem ); + } + CleanupStack::PopAndDestroy( &refContainers ); + } + + else if ( aItem->ObjectClass() == KClassVideo ) + { + // reset parentId + aItem->SetParentIdL( KNullDesC8 ); + // resolve date container + RPointerArray refContainers = + iContainerResolver->ResolveReferenceContainersL( EVideoByDateType, + *aItem ); + CleanupResetAndDestroyPushL( refContainers ); + if ( refContainers.Count() ) + { + // share container(s) and item + ShareReferenceObjectL( refContainers, object, *aItem ); + } + CleanupStack::PopAndDestroy( &refContainers ); + } + else + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithm::\ + ShareReferenceObjectsL object class not defined" ); + } + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::UnshareReferenceObjectsL +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::UnshareReferenceObjectsL( + CUpnpCdsLiteObject& aOriginalObject ) + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithm::\ +UnshareReferenceObjectsL" ); + + TInt refIndex( KErrNotFound ); + + do + { + // find reference items created from original item + refIndex = iSharedContentArray->FindRefItemIdByOriginalIdL( + aOriginalObject.ObjectId() ); + + if ( refIndex != KErrNotFound ) + { + CUpnpCdsLiteObject& refObject = + iSharedContentArray->ObjectAtL( refIndex ); + + // Checks the container tree and unshares if needed + // First container id to be checked is item's parentid + TBool containerUnshared = + UnshareEmptyContainersL( refObject.ParentId() ); + + // if container is not unshared the item needs to be unshared + if ( !containerUnshared ) + { + // Leave if ObjectId not found + if( refObject.ObjectId() == KNullDesC8 ) + { + __LOG( "[CUpnpSharingAlgorithm]\t \ +CUpnpSharingAlgorithm::UnshareFileL, ObjectId not found!" ); + User::Leave( KErrCorrupt ); + } + + TInt objectIdInt( KErrNotFound ); + User::LeaveIfError( objectIdInt = + UPnPCommonUtils::DesC8ToInt( refObject.ObjectId() )); + + // Unshare the item + iSharingAO->UnshareFileL( objectIdInt ); + + // Remove the file from the shared content array + iSharedContentArray->RemoveObjectAtL( refIndex ); + } + else + { + // index has changed because container(s) was unshared + refIndex = iSharedContentArray->FindByObjectId( + refObject.ObjectId() ); + // item was also unshared when container was unshared + // it's enough to remove item from contentarray + iSharedContentArray->RemoveObjectAtL( refIndex ); + } + } + } while ( refIndex != KErrNotFound ); + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::ShareReferenceObjectL +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::ShareReferenceObjectL( + RPointerArray& aContainerArray, + CUpnpCdsLiteObject& aOriginalObject, + CUpnpItem& aItem ) + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithm::\ +ShareReferenceObjectL" ); + + TPtrC8 refParentId( KNullDesC8 ); + TInt parentContainerId( KErrNotFound ); + + TInt count = aContainerArray.Count(); + + if ( count ) + { + // reference container must be non-restricted + aContainerArray[count-1]->SetRestricted(EFalse); + // share containers + ShareContainersL( aContainerArray ); + + refParentId.Set( aContainerArray[count-1]->Id() ); + User::LeaveIfError( + parentContainerId = UPnPCommonUtils::DesC8ToInt( refParentId )); + } + else // share just item + { + refParentId.Set( aItem.ParentId() ); + User::LeaveIfError( + parentContainerId = UPnPCommonUtils::DesC8ToInt( refParentId )); + } + + TInt originalItemId( KErrNotFound ); + User::LeaveIfError( originalItemId = UPnPCommonUtils::DesC8ToInt( + aOriginalObject.ObjectId() )); + + iSharingAO->ShareReferenceL( parentContainerId, originalItemId, &aItem ); + // Add the file to the shared content array + iSharedContentArray->AppendL( &aItem ); + + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::RemoveSharedObjectsL +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::RemoveSharedObjectsL( + RPointerArray& aContainerArray ) + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithm::\ +RemoveSharedObjectsL" ); + + // Unshare starting from first container + TPtrC8 containerIdStr = aContainerArray[0]->Id(); + TInt objectIdInt( KErrNotFound ); + User::LeaveIfError( + objectIdInt= UPnPCommonUtils::DesC8ToInt( containerIdStr )); + // unshares all objecs under this container with single call + iSharingAO->UnshareContainerL( objectIdInt ); + + for ( TInt i = 0; i < aContainerArray.Count(); i++) + { + // Remove object from the shared content array + iSharedContentArray->RemoveL( aContainerArray[i] ); + } + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::ReadSharedContent +// -------------------------------------------------------------------------- +// +CUpnpCdsLiteObjectArray& CUpnpSharingAlgorithmImpl::ReadSharedContent() + { + return *iSharedContentArray; + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::StartServer +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::StartServer() + { + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithm::\ +StartServer" ); + + // start offline if not started + TInt status( RUpnpMediaServerClient::EStopped ); + iMediaServer.Status( status ); + if ( status == RUpnpMediaServerClient::EStopped ) + { + iMediaServer.StartOffline(); + __LOG( "[CUpnpSharingAlgorithm]\t CUpnpSharingAlgorithm::\ +StartServer started offline" ); + } + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::Close +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::Close() + { + delete this; + } + +// -------------------------------------------------------------------------- +// CUpnpSharingAlgorithmImpl::CheckFileProtectionL +// -------------------------------------------------------------------------- +// +void CUpnpSharingAlgorithmImpl::CheckFileProtectionL( + const TFileName& aFileName ) + { + if ( UPnPFileUtility::IsFileProtectedL( aFileName ) ) + { + User::Leave( KErrAccessDenied ); + } + } + +// End of file