--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/upnpmediaserver/contentdirectoryservice/src/upnpcontentdirectory.cpp Thu Dec 17 08:52:00 2009 +0200
@@ -0,0 +1,3726 @@
+/** @file
+* Copyright (c) 2005-2006 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: Content Directory
+ *
+*/
+
+
+// INCLUDE FILES
+#include <fbs.h>
+#include <uri8.h>
+#include <pathinfo.h>
+#include <xmlengdom.h>
+#include <xmlengserializationoptions.h>
+#include <xmlengdomparser.h>
+#include <sysutil.h>
+#include <bautils.h>
+#include <caf/caf.h>
+
+#include "upnpsender.h"
+#include "upnpcontentdirectory.h"
+#include "upnperrors.h"
+#include "upnpdominterface.h"
+#include "upnpstring.h"
+#include "upnpargument.h"
+#include "upnphttpmessagefactory.h"
+#include "upnpcons.h"
+#include "upnpdevice.h"
+#include "upnpfileutils.h"
+#include "upnpcommonupnplits.h"
+#include "upnpcontainerupdateid.h"
+#include "upnpcontentdirectorydb.h"
+#include "upnpfiletransfertimerobserver.h"
+#include "upnperror.h"
+#include "upnpcustomlog.h"
+#include "upnpprotocolinfo.h"
+#include "upnpcontentdirectoryglobals.h"
+#include "upnpresourcesbean.h"
+#include "upnpcdutils.h"
+#include "upnpmetadatastorage.h"
+#include "upnpautodestroyobjectlist.h"
+#include "upnpautodestroyobject.h"
+#include "upnpcontentdirectoryeventobserver.h"
+#include "upnpfiletransferevent.h"
+#include "upnpfiletransfer.h"
+#include "upnpprotocolinfolocal.h"
+#include "upnpxmlcontentfilter.h"
+#include "upnpstatehandler.h"
+#include "upnptransferuploader.h"
+#include "upnpmimemapper.h"
+#include "upnptransfercontroller.h"
+#include "upnptransferinterface.h"
+#include "upnpdlnafilter.h"
+#include "upnphttpserversession.h"
+#include "upnphttpserverruntime.h"
+#include "upnpsettings.h"
+#include "upnpdeviceimplementationbase.h"
+#include "upnpsecuritymanager.h"
+#include "upnpmediaserversettings.h"
+
+// Constant definitions
+using namespace UpnpPaths;
+using namespace UpnpDlnaProtocolInfo;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// DestroyRPointerArray
+// Defined in upnpelementfactory.cpp
+// -----------------------------------------------------------------------------
+//
+void DestroyRArray( TAny* aArray );
+void RPointerArrayTPtrC8( TAny* aArray )
+ {
+ RPointerArray<TPtrC8>* array =
+ reinterpret_cast<RPointerArray<TPtrC8>*>(aArray);
+ array->ResetAndDestroy( );
+ }
+
+// ================= MEMBER FUNCTIONS =======================
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CUpnpContentDirectory
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CUpnpContentDirectory::CUpnpContentDirectory( CUpnpDevice& aDevice,
+ MUpnpThumbnailCreatorObserver* aThmbObs, MUpnpTransferInterface* aTransfer ) :
+
+ CUpnpServiceImplementation(aDevice), iThmbObs(aThmbObs),
+ iTransferHandler(aTransfer)
+
+ {
+ SetExecutedAction( EUndefinedAction );
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::~CUpnpContentDirectory
+// C++ default destructor
+// -----------------------------------------------------------------------------
+//
+CUpnpContentDirectory::~CUpnpContentDirectory()
+ {
+ delete iDownloadDir;
+ delete iThumbDir;
+ delete iElementdb;
+
+ delete iTransferController;
+ delete iMimeToExtMap;
+
+ delete iContentDirectoryDb;
+
+ iThObjectIds.Close( );
+
+ iThumbnailCreators.ResetAndDestroy( );
+
+ iDOMImpl.Close( );
+ if ( iBitmapServerConnection == KErrNone )
+ RFbsSession::Disconnect( );
+ iFs.Close( );
+ if ( iEcomUsed )
+ {
+ REComSession::FinalClose( );
+ }
+ delete iAutoDestroyObjects;
+ delete iStateHandler;
+ if ( iHttpServerSession )
+ {
+ iHttpServerSession->Stop();
+ }
+ delete iHttpServerSession;
+ delete iDlnaFilter;
+ delete iSecurityManager;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ConstructL
+// Two-phased constructor.
+// Initialize variables, set parent service and create XML reader.
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::ConstructL( TUpnpCdSettings aSettings,
+ CUpnpMetadataStorage* aMetadataStorage )
+ {
+ iDOMImpl.OpenL( );
+
+ iTransferController = CUpnpTransferController::NewL( this );
+
+ iMimeToExtMap = CUpnpMimeMapper::NewL( );
+
+ BaseConstructL( aSettings.iDescriptionPath, KContentDirectoryType( ) );
+
+ User::LeaveIfNull( aSettings.iDevice );
+
+ CUpnpSecurityManager* secMan = CUpnpSecurityManager::NewInstanceFromUpnpSettingsL();
+
+ iSecurityManager = secMan;
+ iDlnaFilter = CUpnpDlnaFilter::NewL( this, secMan );
+
+ iElementdb = CUpnpElementFactory::NewL( aSettings.iObjectsXmlPath );
+ iElementdb->GetContentDirectoryReference( this );
+
+ SetStateVariableL( KSystemUpdateID( ), KZero( ) );
+ SetStateVariableL( KContainerUpdateIDs( ), UpnpCD::KEmptyString( ) );
+ SetStateVariableL( KTransferIDs( ), UpnpCD::KEmptyString( ) , EFalse );
+ SetStateVariableL( KSortCapsVariableName( ), KSortCapabilities( ) );
+ SetStateVariableL( KSearchCapsVariableName( ), KSearchCapabilities( ) );
+
+ // file session
+ User::LeaveIfError( iFs.Connect( ) );
+
+ iBitmapServerConnection = RFbsSession::Connect( );
+ iDownloadDir = aSettings.iDownloadDir.AllocL( );
+ iThumbDir = aSettings.iThumbnailDir.AllocL( );
+ iContentDirectoryDb = CUpnpContentDirectoryDb::NewL( aMetadataStorage );
+ iAutoDestroyObjects = CUpnpAutoDestroyObjectList::NewL( );
+ iCreateThumbnails = aSettings.iCreateThumbnail;
+ iMaxRequestCount = aSettings.iMaxRequestCount;
+ iEventObserver = aSettings.iEventObserver;
+ iStateHandler = CUpnpStateHandler::NewL( this );
+
+ ConstructHttpL();
+ }
+
+void CUpnpContentDirectory::ConstructHttpL()
+ {
+ TInt iapId = CUpnpSettings::GetIapL();
+ iHttpServerSession = CUpnpHttpServerSession::NewL( iapId, *this );
+ iHttpServerSession->DefaultRuntime().SetCreator( *this );
+ iHttpServerSession->StartL();
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CUpnpContentDirectory* CUpnpContentDirectory::NewL(
+ TUpnpCdSettings aSettings, CUpnpMetadataStorage* aMetadataStorage,
+ MUpnpTransferInterface* aTransfer )
+ {
+ CUpnpContentDirectory* cd = new (ELeave) CUpnpContentDirectory( *aSettings.iDevice,
+ aSettings.iThmbObs,
+ aTransfer
+ );
+ CleanupStack::PushL( cd );
+ cd->ConstructL( aSettings, aMetadataStorage );
+ CleanupStack::Pop( cd );
+ return cd;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ActionReceivedLD
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::ActionReceivedLD( CUpnpAction* aAction )
+ {
+ CleanupStack::PushL( aAction );
+ //check security
+ if ( iSecurityManager &&
+ KErrNone != iSecurityManager->AuthorizeAction( aAction ) )
+ {
+ //server returns upnp error action failed when not authorized
+ User::Leave(EActionFailed);
+ }
+ // in case of low disk space
+ if ( !IsDbOrDiskProblemL( aAction ) )
+ {
+ // handle event
+ TInt ret = EUpnpUndefined;
+ TRAPD( err, ret = DoActionReceivedL( aAction ) );
+ if ( DataBaseHasBeenRecoveredL( err ) )
+ {
+ TRAP( err, ret = DoActionReceivedL( aAction ) );
+ if ( err == KErrCorrupt )
+ {
+ err = iContentDirectoryDb->RecreateDatabaseFile();
+ }
+ }
+ else if ( err == KErrNone )
+ {
+ err = ret;
+ }
+ LOGS( "ContentDirectory ActionReceivedLD sending soon." );
+ DoSendActionL( aAction, TUpnpError( err ) );
+ }
+ CleanupStack::PopAndDestroy( aAction );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::DoActionReceivedL
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpContentDirectory::DoActionReceivedL( CUpnpAction* aAction )
+ {
+ // sendAndDestroy defines that after processing action must be
+ // sent and destroyed
+ TUpnpErrorCode err = EUndefined;
+
+ // Get the name, saves calls in the if-else statements
+ TPtrC8 name( aAction->Name() );
+ // Verify the action and do the operation(s)
+ if ( name.Compare( KBrowse ) == 0 )
+ {
+ err = BrowseL( aAction );
+ }
+ else if ( name.Compare( KCreateReference ) == 0 )
+ {
+ err = CreateReferenceL( aAction );
+ }
+ else if ( name.Compare( KCreateObject ) == 0 )
+ {
+ LOGS( "ContentDirectory: Creating a new object" );
+ err = CreateObjectL( aAction );
+ }
+ else if ( name.Compare( KDeleteResource ) == 0 )
+ {
+ err = DeleteResourceL( aAction );
+ }
+ else if ( name.Compare( KDestroyObject ) == 0 )
+ {
+ err = DestroyObjectL( aAction );
+ }
+ else if ( name.Compare( KExportResource ) == 0 )
+ {
+ err = ExportResourceL( aAction );
+ }
+ else if ( name.Compare( KGetSearchCapabilities ) == 0 )
+ {
+ err = GetSearchCapabilitiesL( aAction );
+ }
+ else if ( name.Compare( KGetSortCapabilities ) == 0 )
+ {
+ err = GetSortCapabilitiesL( aAction );
+ }
+ else if ( name.Compare( KGetSystemUpdateID ) == 0 )
+ {
+ err = GetSystemUpdateIdL( aAction );
+ }
+ else if ( name.Compare( KGetTransferProgress ) == 0 )
+ {
+ err = GetTransferProgressL( aAction );
+ }
+ else if ( name.Compare( KImportResource ) == 0 )
+ {
+ err = ImportResourceL( aAction );
+ }
+ else if ( name.Compare( KStopTransferResource ) == 0 )
+ {
+ err = StopTransferResourceL( aAction );
+ }
+ else
+ {
+ err = EInvalidAction;
+ }
+ return err;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::DoActionReceivedCDL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::HttpGetStartedSoapNotifyL( TInt /*aSessionId*/)
+ {
+ // not needed upnp response returned by ActionReceivedCDL
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::DoActionReceivedCDL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::HttpPostStartedL( TInt /*aSessionId*/)
+ {
+ // not needed upnp response returned by ActionReceivedCDL
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::UnknownHttpEventReceivedL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpContentDirectory::UnknownHttpEventReceivedL( CUpnpHttpMessage& aHttpMsg )
+ {
+ CUpnpFileTransferEvent* transferEvent =
+ iTransferController->TransferL( aHttpMsg.SessionId( ) );
+ if ( !transferEvent )
+ {
+ return;
+ }
+
+ TInt err = aHttpMsg.Error( );
+ if ( err != EHttpRequestTimeout && err != EHttpInsufficientStorage )
+ {
+ err = EHttpOk;
+ }
+
+ HBufC* fileName16 = UpnpString::ToUnicodeL( aHttpMsg.InFilename( ) );
+ CleanupStack::PushL( fileName16 );
+ transferEvent->SetFilePathL( *fileName16 );
+ CleanupStack::PopAndDestroy( fileName16 );
+
+ iTransferController->HttpResponseReceivedL( aHttpMsg.SessionId( ), err );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::IsDrmFileL
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpContentDirectory::IsDrmFileL( const TDesC8& aFileName )
+ {
+ HBufC* tmp = UpnpCdUtils::Des8ToDesLC( aFileName );
+ TBool ret = IsDrmFileL( *tmp );
+ CleanupStack::PopAndDestroy( tmp );
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::IsDrmFileL
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpContentDirectory::IsDrmFileL( const TDesC& aFileName )
+ {
+ if ( !BaflUtils::FileExists( iFs, aFileName ) )
+ {
+ return EFalse;
+ }
+ TBool ret = EFalse;
+ TInt value=0, err;
+
+ ContentAccess::CManager *manager = ContentAccess::CManager::NewL( );
+ CleanupStack::PushL( manager );
+
+ ContentAccess::CVirtualPath *path =
+ ContentAccess::CVirtualPath::NewL( aFileName );
+ CleanupStack::PushL( path );
+
+ ContentAccess::TVirtualPathPtr virtualPath = *path;
+
+ err = manager->GetAttribute( ContentAccess::EIsProtected, value,
+ virtualPath );
+ if ( err == KErrNone )
+ {
+ if ( value )
+ {
+ // delete file
+ iFs.Delete( aFileName );
+ ret = ETrue;
+ }
+ }
+ CleanupStack::PopAndDestroy( 2, manager );
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CreateReferenceL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::CreateReferenceL( CUpnpAction*& aAction )
+ {
+ TUpnpErrorCode ret = EUpnpUndefined;
+
+ // Get IDs from action
+ TInt conId( KErrNotFound );
+ TInt objId( KErrNotFound );
+
+ TInt err = UpnpCdUtils::StringToInteger(
+ aAction->ArgumentValue( KContainerID ), &conId );
+ if ( err!=KErrNone )
+ {
+ err=ENoContainer;
+ User::Leave( ENoContainer );
+ }
+
+ err = UpnpCdUtils::StringToInteger(
+ aAction->ArgumentValue( UpnpCD::KObjectID ), &objId );
+ if ( err!=KErrNone )
+ {
+ err=ENoContainer;
+ User::Leave( ENoSuchObject );
+ }
+
+ objId = iContentDirectoryDb->ReferedObjectIdL( objId );
+
+ RXmlEngDocument conDidl;
+ RXmlEngDocument objDidl;
+ CleanupClosePushL( conDidl );
+ CleanupClosePushL( objDidl );
+
+ ret = iContentDirectoryDb->GetObjectL( conId, conDidl, KAsterisk8 );
+ if ( ret != EUpnpOk )
+ User::Leave( ENoContainer );
+
+ ret = iContentDirectoryDb->GetObjectL( objId, objDidl, KAsterisk8 );
+ if ( ret != EUpnpOk )
+ User::Leave( ENoSuchObject );
+
+ TXmlEngElement con = conDidl.DocumentElement().FirstChild().AsElement( );
+ TXmlEngElement obj = objDidl.DocumentElement().FirstChild().AsElement( );
+
+ if ( obj.Name().Compare( KItem ) != 0 )
+ {
+ User::Leave( ENoSuchObject );
+ }
+ if ( con.Name().Compare( KContainer ) != 0 )
+ {
+ User::Leave( ENoContainer );
+ }
+ if ( iContentDirectoryDb->CheckObjectRestrictionL( conId ) != EUpnpOk )
+ {
+ User::Leave( ERestrictedParentObject );
+ }
+
+ TInt refId;
+ RXmlEngDocument refDidl = iContentDirectoryDb->PrepareDidlDocumentL( );
+ CleanupClosePushL( refDidl );
+
+ TXmlEngElement refEl = refDidl.DocumentElement().AddNewElementSameNsL( KItem( ) );
+
+ refEl.AddNewAttributeL( KRefID( ),
+ aAction->ArgumentValue( UpnpCD::KObjectID ) );
+
+ refEl.AddNewAttributeL( KParentID( ),
+ aAction->ArgumentValue( KContainerID ) );
+
+ refEl.AddNewAttributeL( KRestricted( ), KFalseValue8( ) );
+
+ // title
+ TXmlEngElement objTitle;
+ UpnpDomInterface::GetElementL( obj, objTitle, KObjTiltleColName8( ) );
+ refEl.AppendChildL( objTitle.Unlink().AsElement( ) );
+
+ // class
+ TXmlEngElement objClass;
+ UpnpDomInterface::GetElementL( obj, objClass, KObjClassColName8( ) );
+ refEl.AppendChildL( objClass.Unlink().AsElement( ) );
+
+ iContentDirectoryDb->InsertObjectL( refDidl, conId, &refId );
+
+ //increase system update ID
+ iStateHandler->IncreaseSystemUpdateIdL( );
+ iStateHandler->IncreaseContainerUpdateIdL( (TDesC8&)aAction->ArgumentValue( KContainerID ) );
+
+ TBuf8<KMaxIntegerLen> newid;
+ newid.Num( refId );
+ aAction->SetArgumentL( (TDesC8&)KNewID, newid );
+
+ CleanupStack::PopAndDestroy( &refDidl );
+ CleanupStack::PopAndDestroy( &objDidl );
+ CleanupStack::PopAndDestroy( &conDidl );
+
+ return EHttpOk;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::BrowseL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::BrowseL( CUpnpAction*& aAction )
+ {
+ RDebug::Print( _L( "CUpnpContentDirectory::BrowseL start" ) );
+ TInt err( KErrGeneral );
+
+ //Check ObjectID
+ TInt objectID( KErrNotFound );
+ err = UpnpCdUtils::StringToInteger(
+ (TDesC8&)aAction->ArgumentValue( UpnpCD::KObjectID( ) ), &objectID );
+ if ( err != KErrNone )
+ {
+ User::Leave( ENoSuchObject );
+ }
+ //Check SortCriteria
+ if ( aAction->ArgumentValue( (TDesC8&) KSortCriteria ).Compare( (TDesC8&)KSortCapabilities )
+ != 0 )
+ {
+ User::Leave( EInvalidSort ); //wrong sort flag
+ }
+
+ //Check BrowseFlag
+ TDesC8& browseFlag =
+ (TDesC8&)aAction->ArgumentValue( (TDesC8&)KBrowseFlag );
+ if ( browseFlag.Compare( KBrowseMeta ) != 0
+ && browseFlag.Compare( KBrowseChilds ) != 0 )
+ {
+ User::Leave( EInvalidArgs ); //wrong browse flag
+ }
+
+ //Check StartIndex
+ TInt startIndex( KErrNotFound );
+ err = UpnpString::StringToInt(
+ (TDesC8&)aAction->ArgumentValue( (TDesC8&)KStartingIndex ),
+ &startIndex );
+ if ( KErrNone != err )
+ {
+ User::Leave( EInvalidArgs );
+ }
+
+ //Additional check of StartIndex, see documentation
+ if ( browseFlag.Compare( KBrowseMeta ) == 0 && startIndex != 0 )
+ {
+ User::Leave( EInvalidArgs );
+ }
+
+ //Check RequestedCount
+ TInt reqCount( KErrNotFound );
+ err = UpnpString::StringToInt(
+ (TDesC8&)aAction->ArgumentValue( (TDesC8&)KRequestedCount ),
+ &reqCount );
+ if ( KErrNone != err )
+ {
+ User::Leave( EInvalidArgs );
+ }
+
+ //Filter
+ HBufC8* filter = aAction->ArgumentValue( KFilter() ).AllocLC( );
+ filter->Des().TrimAll( );
+
+ // Metadata browse
+ if ( browseFlag.Compare( KBrowseMeta ) == 0 )
+ {
+
+ RXmlEngDocument objectDoc;
+ CleanupClosePushL( objectDoc );
+ // Try to get original object not a reference
+ TInt id = iContentDirectoryDb->ReferedObjectIdL( objectID );
+ CleanupStack::Check( &objectDoc );
+ TUpnpErrorCode err = EUndefined;
+ err = iContentDirectoryDb->GetObjectL( id, objectDoc, *filter );
+ if ( err != EUpnpOk )
+ User::Leave( err );
+ CleanupStack::Check( &objectDoc );
+ //--------- new solution for references --------
+
+ // if id != objectID it means that we have a reference, so now id = 'real object id' and objectID = 'reference object id'
+ if ( id != objectID )
+ {
+ TInt refParentID = iContentDirectoryDb->GetParentIdL( objectID );
+ User::LeaveIfError( refParentID );
+
+ UpnpCdUtils::SetObjectIdL(
+ UpnpCdUtils::GetObjectElementL( objectDoc ), objectID );
+ UpnpCdUtils::SetObjectRefIdL(
+ UpnpCdUtils::GetObjectElementL( objectDoc ), id );
+ UpnpCdUtils::SetObjectParentIdL(
+ UpnpCdUtils::GetObjectElementL( objectDoc ), refParentID );
+ UpnpCdUtils::SetRestrictedFieldL(
+ UpnpCdUtils::GetObjectElementL( objectDoc ), EFalse );
+ }
+ //---------------------------------------------
+
+ // Serialize object to descriptor - without DIDL-Lite element
+ RBuf8 buf;
+ TXmlEngSerializationOptions
+ options(TXmlEngSerializationOptions::KOptionOmitXMLDeclaration
+ | TXmlEngSerializationOptions::KOptionIncludeNsPrefixes);
+ objectDoc.SaveL( buf, iElementdb->ActiveElementL( objectDoc ),
+ options );
+ CleanupStack::Check( &objectDoc );
+ CleanupClosePushL( buf );
+ HBufC8* subResponse = buf.AllocLC( );
+
+ CBufFlat* response = CBufFlat::NewL( KRespBufGranularity );
+ CleanupStack::PushL( response );
+ UpnpString::AppendStringL( *response, KDidlTag );
+ UpnpString::AppendStringL( *response, *subResponse );
+ UpnpString::AppendStringL( *response, (TDesC8&) KDidlEnd( ) );
+
+ HBufC8* resultTmp =
+ UpnpCdUtils::EncodeXmlStringL( response->Ptr( 0 ) );
+ CleanupStack::PushL( resultTmp );
+ TPtr8 resultTmpPtr(resultTmp->Des( ));
+ InsertRealIpAndPortL( resultTmpPtr );
+
+ // Set action's OUT arguments
+ TBuf8<KMaxIntegerLen> num;
+
+ //Result
+ aAction->SetArgumentL( KResult, *resultTmp );
+
+ //NumberReturned
+ num.Num( 1 );
+ aAction->SetArgumentL( KNumberReturned, num );
+
+ //TotalMatches
+ //num.Num(1);
+ aAction->SetArgumentL( KTotalMatches, num );
+
+ //UpadateID
+ num.Format(
+ UpnpCD::KOneNumber,
+ ContainerUpdateId( (TDesC8&)aAction->ArgumentValue( (TDesC8&)UpnpCD::KObjectID ) ) );
+ aAction->SetArgumentL( KUpdateID, num );
+
+ // clean up
+ CleanupStack::PopAndDestroy( resultTmp );
+ CleanupStack::PopAndDestroy( response );
+ CleanupStack::PopAndDestroy( subResponse );
+ CleanupStack::PopAndDestroy( &buf );
+ CleanupStack::PopAndDestroy( &objectDoc );
+
+ }
+ //Children browse
+ else if ( browseFlag.Compare( KBrowseChilds ) == 0 )
+ {
+ //array contains pointers to direct childrens.
+ RArray<TInt> listOfAllObjects;
+ CleanupClosePushL( listOfAllObjects );
+
+ TUpnpErrorCode err = iContentDirectoryDb->GetObjectListL( objectID,
+ listOfAllObjects );
+
+ if ( err == ENoSuchObject )
+ {
+ User::Leave( err );
+ }
+
+ // if requestedCount==0 then return all matched objects
+ if ( !reqCount )
+ {
+ reqCount = listOfAllObjects.Count( );
+ }
+
+ // if requestedCount cannot be greater than iMaxRequestCount
+ if ( iMaxRequestCount > 0 && reqCount > iMaxRequestCount )
+ {
+ reqCount = iMaxRequestCount;
+ }
+
+ // get upnp objects
+ RArray<RXmlEngDocument> objs;
+ CleanupStack::PushL(TCleanupItem( DestroyRArray, &objs ));
+
+ if ( startIndex < listOfAllObjects.Count( ) )
+ { // prepare list of objects which are to be returned
+ if ( startIndex + reqCount > listOfAllObjects.Count( ) )
+ reqCount = listOfAllObjects.Count( ) - startIndex;
+ RArray<TInt> alistOfWantedObjs( &listOfAllObjects[startIndex],
+ reqCount);
+
+ iContentDirectoryDb->GetObjectListL( alistOfWantedObjs, *filter,
+ objs );
+ }
+
+ // prepare response
+ // Result
+ HBufC8* resp = SerializeObjectsListL( objs );
+ CleanupStack::PushL( resp );
+ TPtr8 respPtr(resp->Des( ));
+ InsertRealIpAndPortL( respPtr );
+ aAction->SetArgumentL( KResult, *resp );
+ // NumberReturned
+ TBuf8<KMaxIntegerLen> num;
+ num.Num( objs.Count( ) );
+ aAction->SetArgumentL( KNumberReturned, num );
+ // TotalMatches
+ num.Num( listOfAllObjects.Count( ) );
+ aAction->SetArgumentL( KTotalMatches, num );
+ // UpdateID
+ num.Format(
+ UpnpCD::KOneNumber,
+ ContainerUpdateId( (TDesC8&)aAction->ArgumentValue( (TDesC8&)UpnpCD::KObjectID ) ) );
+ aAction->SetArgumentL( KUpdateID, num );
+
+ // clean up
+ CleanupStack::PopAndDestroy( resp );
+ CleanupStack::PopAndDestroy( &objs );
+ CleanupStack::PopAndDestroy( &listOfAllObjects );
+ }
+ else //no valid browseflag
+ {
+ User::Leave( EInvalidArgs );
+ }
+
+ RDebug::Print( _L( "CUpnpContentDirectory::BrowseL Result got OK" ) );
+
+ CleanupStack::PopAndDestroy( filter );
+
+ return EHttpOk;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::SerializeObjectsListL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CUpnpContentDirectory::SerializeObjectsListL(
+ const RArray<RXmlEngDocument>& aObjs )
+ {
+ CBufFlat* buff = CBufFlat::NewL( KRespBufGranularity );
+ CleanupStack::PushL( buff );
+
+ // Didl start
+ UpnpString::AppendStringL( *buff, KDidlTag );
+
+ // content
+ for ( TInt i = 0; i < aObjs.Count( ); i++ )
+ {
+ RBuf8 tmp;
+ TXmlEngSerializationOptions
+ options(TXmlEngSerializationOptions::KOptionOmitXMLDeclaration
+ | TXmlEngSerializationOptions::KOptionIncludeNsPrefixes);
+ aObjs[i].SaveL( tmp, iElementdb->ActiveElementL( aObjs[i] ), options );
+ CleanupClosePushL( tmp );
+ UpnpString::AppendStringL( *buff, tmp );
+ UpnpString::AppendStringL( *buff, KLF8 );
+ CleanupStack::PopAndDestroy( &tmp );
+ }
+
+ // Didl end
+ UpnpString::AppendStringL( *buff, KDidlEnd );
+
+ // prepare to return
+ HBufC8* ret = UpnpCdUtils::EncodeXmlStringL( buff->Ptr( 0 ) );
+
+ // clean up
+ CleanupStack::PopAndDestroy( buff );
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::DestroyObjectL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::DestroyObjectL( CUpnpAction*& aAction )
+ {
+ TInt objId( KErrNotFound );
+
+ TInt error(0);
+ error = UpnpCdUtils::StringToInteger(
+ (TDesC8&)aAction->ArgumentValue( UpnpCD::KObjectID( ) ), &objId );
+ if ( (error == KErrArgument)||(error == KErrOverflow) )
+ {
+ User::Leave( ENoSuchObject );
+ }
+ else if ( error<0 )
+ {
+ User::Leave( error );
+ }
+ // check object restriction
+ TUpnpErrorCode err = iContentDirectoryDb->CheckObjectRestrictionL( objId ); // if returned ENoContainer it is OK because first of all the restriction is checked
+ if ( err == ERestrictedObject || err == ENoSuchObject )
+ {
+ User::Leave( err );
+ }
+
+ // check parent restriction
+ err = iContentDirectoryDb->CheckObjectRestrictionL( objId );
+ if ( err == ERestrictedObject )
+ {
+ User::Leave( ERestrictedParentObject );
+ }
+
+ // root and download containers must not be deleted
+ if ( objId <= KDownloadContId )
+ {
+ /*
+ Designing a UPnP AV MediaServer (3.2.4):
+ "If a CDS implementation exposes a CDS object that is not restricted but cannot fulfill a
+ CDS:DestroyObject(), CDS:CreateObject(), or CDS:UpdateObject() request, then the MediaServer should
+ return error code 720 to indicate the request could not be processed."
+ */
+ User::Leave( ECannotProcess );
+ }
+
+ RArray<TInt> refList;
+ CleanupClosePushL( refList );
+
+ TBuf8<KMaxIntegerLen> containerID;
+ containerID.Num( iContentDirectoryDb->GetParentIdL( objId ) );
+
+ iContentDirectoryDb->DeleteObjectL( objId, refList, ETrue );
+
+ iStateHandler->IncreaseSystemUpdateIdL( );
+ iStateHandler->IncreaseContainerUpdateIdL( containerID );
+
+ for ( TInt i(0); i<refList.Count( ); i++ )
+ {
+ if ( objId!=refList[i] )
+ {
+ containerID.Num( refList[i] );
+ iStateHandler->IncreaseSystemUpdateIdL( );
+ iStateHandler->IncreaseContainerUpdateIdL( containerID );
+ }
+ }
+ // clean up
+ CleanupStack::PopAndDestroy( &refList );
+ return EHttpOk;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::AddToMetaDbL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::AddToMetaDbL(
+ RXmlEngDocument& aFragment, TInt aContainer, TInt* aId, TBool aIsLocal )
+ {
+ // res list
+ RArray<TXmlEngElement> resList;
+ CleanupClosePushL( resList );
+ UpnpDomInterface::GetElementListL( aFragment.DocumentElement( ), resList,
+ KRes );
+
+ // a source file for thumbnail
+ HBufC* thumbSrcFile = NULL;
+
+ if ( aIsLocal )
+ { // local action
+ // create thumbnail if there is only one res in the object
+ if ( resList.Count( ) == 1 )
+ {
+ // get resource file name
+ TPtrC8 val(resList[0].Text( ));
+ // ignore if empty string
+ if ( val.Length( ) && (!UpnpCdUtils::IsWhiteString( val )) )
+ {
+ TUriParser8 up;
+ User::LeaveIfError( up.Parse( val ) );
+ if ( up.Extract( EUriScheme ) == UpnpHTTP::KSchemeFile8 )
+ {
+ thumbSrcFile = up.GetFileNameL( ); // thumbnail will be created at the end of this function
+ CleanupStack::PushL( thumbSrcFile );// and the pointer will be poped
+ }
+ }
+ }
+ TInt nextId = iContentDirectoryDb->GetObjectIdL( );
+ // handle resources
+ for ( TInt i = 0; i < resList.Count( ); i++ )
+ {
+ HandleLocalResourcesL( resList[i], nextId );
+ }
+ }
+
+ // if only one empty res add importUri
+ if ( resList.Count( ) )
+ {
+ TPtrC8 resValue(resList[0].Text( ));
+ if ( !resValue.Length( ) || UpnpCdUtils::IsWhiteString( resValue ) )
+ {
+ AddImportUriToElL( resList[0] );
+ }
+ }
+ if ( !resList.Count( ) )
+ {
+ AddNewResTagL( aFragment.DocumentElement( ) );
+ }
+ // add to database
+ TUpnpErrorCode ret = iContentDirectoryDb->InsertObjectL( aFragment,
+ aContainer, aId );
+ if ( ret == EUpnpOk )
+ {
+ PrepareAutoDestroyObjectL( aFragment.DocumentElement( ), *aId );
+ ret = EHttpOk;
+ }
+
+ if ( thumbSrcFile )
+ {
+ CreateThumbnailL( *thumbSrcFile, *aId );
+ CleanupStack::PopAndDestroy( thumbSrcFile );
+ }
+ CleanupStack::PopAndDestroy( &resList );
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CreateThumbnailForResourceL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::PrepareAutoDestroyObjectL(
+ TXmlEngElement aObject, TInt aObjId )
+ {
+ // check res
+ RArray<TXmlEngElement> resList;
+ CleanupClosePushL( resList );
+ UpnpDomInterface::GetElementListL( aObject, resList, KRes );
+ if ( resList.Count( ) > 0 )
+ {
+ // only first res is important
+ TPtrC8 resValue(resList[0].Text( ));
+ if ( !resValue.Length( ) || UpnpCdUtils::IsWhiteString( resValue ) )
+ {
+ TXmlEngAttr impUri = resList[0].AttributeNodeL( KImportUri( ) );
+ // auto destroy
+ CUpnpAutoDestroyObject* ado = CUpnpAutoDestroyObject::NewLC(
+ this, aObjId, UpnpCdUtils::ResIdFromUriL( impUri.Value( ) ) );
+ iAutoDestroyObjects->AppendL( ado );
+ CleanupStack::Pop( ado );
+ }
+ }
+
+ // clean up
+ CleanupStack::PopAndDestroy( &resList );
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CreateThumbnailForResourceL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::CreateThumbnailL( const TDesC& aSrcFile,
+ TInt aObjId )
+ {
+ if ( iCreateThumbnails && IsThumbnailAvailableL( aSrcFile ) )
+ {
+ // thumbnail name
+ HBufC* thumbName = CreateNameForThumbnailL( aSrcFile );
+ CleanupStack::PushL( thumbName );
+
+ // create thumbnail creator
+ CUpnpThumbnailCreator* thCreator = CreateThumbnailCreatorL( aObjId ); // do not push it onto CleanupStack
+ // ThumbnailCreator is created and added to iThumbnailCreators
+ // but the creation process is not yet started,
+ // therefore, not leaving code should be performed until the thCreator->CreateL method is called
+ if ( thCreator )
+ {
+ // start creation process
+ TRAPD( err, thCreator->CreateL( aSrcFile, *thumbName ) );
+ if ( err )
+ {
+ RDebug::Print( _L( "Error while creating thumbnail, it won't be created. Removing from creator list." ) );
+ RemoveThCreatorAndObjectIdLD( thCreator );
+ }
+ iEcomUsed = ETrue;
+ }
+ // clean up
+ CleanupStack::PopAndDestroy( thumbName );
+ }
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::IsThumbnailAvailableL
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpContentDirectory::IsThumbnailAvailableL( const TDesC& aFile )
+ {
+ HBufC8* tmp = HBufC8::NewLC( aFile.Length( ) );
+ tmp->Des().Copy( aFile );
+ TBool ret = IsThumbnailAvailableL( *tmp );
+ CleanupStack::PopAndDestroy( tmp );
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::IsThumbnailAvailableL
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpContentDirectory::IsThumbnailAvailableL( const TDesC8& aFile )
+ {
+ TBool result = EFalse;
+
+ // get mime type for file
+ HBufC8* mt = GetMimeTypeLC( aFile );
+ TPtr8 mimeType(mt->Des( ));
+ mimeType.LowerCase( );
+
+ if ( !mimeType.Compare( KMT_IMAGE_JPEG( ) ) )
+ {
+ result = ETrue;
+ }
+ else if ( !mimeType.Compare( KMT_IMAGE_PNG( ) ) )
+ {
+ result = ETrue;
+ }
+ else if ( !mimeType.Compare( KMT_IMAGE_GIF( ) ) )
+ {
+ result = ETrue;
+ }
+ else if ( !mimeType.Compare( KMT_IMAGE_BMP( ) ) )
+ {
+ result = ETrue;
+ }
+ CleanupStack::PopAndDestroy( mt );
+
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::AddImportUriToElL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::AddImportUriToElL( TXmlEngElement aElement )
+ {
+ HBufC8* impUriVal = BuildImportUriShorterLC( );
+ HBufC8* impUriValRandomize = HBufC8::NewLC( impUriVal->Des().Length( )+ KRandomRangeLength );
+ HBufC8* number = UpnpCdUtils::RandomizeL( KRandomMax );
+ CleanupStack::PushL( number );
+ impUriValRandomize->Des().Copy( *impUriVal );
+ impUriValRandomize->Des().Append( *number );
+ aElement.AddNewAttributeL( KImportUri( ), *impUriValRandomize );
+ // clean up
+ CleanupStack::PopAndDestroy( number );
+ CleanupStack::PopAndDestroy( impUriValRandomize );
+ CleanupStack::PopAndDestroy( impUriVal );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::AddNewResTagL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::AddNewResTagL( TXmlEngElement aObjEl )
+ {
+ TXmlEngElement item;
+ UpnpDomInterface::GetElementL( aObjEl, item, KItem );
+
+ // ignore if null
+ if ( item.NotNull( ) )
+ {
+ TXmlEngElement newEl = item.AddNewElementL( KRes( ) );
+ newEl.AddNewAttributeL( KprotocolInfo( ), KEmptyProtocolInfoVal8( ) );
+ newEl.AddNewAttributeL( KProtInfoReqAtrSufPattern( ), KTrueValue8( ) );
+ // add importUri
+ AddImportUriToElL( newEl );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::BuildContentUriL
+// -----------------------------------------------------------------------------
+HBufC8* CUpnpContentDirectory::BuildContentUriL( const TDesC& aFileExt,
+ TInt aObjectId )
+ {
+ TBuf8<KMaxIntegerLen> objectId;
+ objectId.Num( aObjectId );
+ return UpnpCdUtils::BuildContentUriL(
+ iContentDirectoryDb->GetKeyForUriL( ), aFileExt, objectId );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::BuildImportUriL
+// -----------------------------------------------------------------------------
+HBufC8* CUpnpContentDirectory::BuildImportUriLC()
+ {
+ return UpnpCdUtils::BuildImportUriLC( iContentDirectoryDb->GetKeyForUriL( ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::BuildImportUriShorterLC
+// -----------------------------------------------------------------------------
+HBufC8* CUpnpContentDirectory::BuildImportUriShorterLC()
+ {
+ return UpnpCdUtils::BuildImportUriShorterLC( iContentDirectoryDb->GetKeyForUriL( ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::InsertRealIpAndPortL
+// -----------------------------------------------------------------------------
+void CUpnpContentDirectory::InsertRealIpAndPortL( TDes8& aString )
+ {
+ // prepare pettern
+ HBufC8* pattern = HBufC8::NewLC( KHttpTag().Length( ) + KIpPortPlaceholder8().Length( ) );
+ TPtr8 patternPtr(pattern->Des( ));
+ patternPtr.Append( KHttpTag );
+ patternPtr.Append( KIpPortPlaceholder8 );
+
+ // repare address
+ HBufC8* address = GetIpAndPortDes8L( );
+ CleanupStack::PushL( address );
+
+ TInt pos = aString.Find( patternPtr );
+
+ while ( pos != KErrNotFound )
+ {
+ aString.Replace( pos + KHttpTag().Length( ), KIpPortPlaceholder8().Length( ), *address );
+ pos = aString.Find( patternPtr );
+ }
+
+ // clean up
+ CleanupStack::PopAndDestroy( address );
+ CleanupStack::PopAndDestroy( pattern );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::InsertIpAndPortPlaceholderL
+// -----------------------------------------------------------------------------
+HBufC8* CUpnpContentDirectory::InsertIpAndPortPlaceholderL(
+ const TDesC8& aString )
+ {
+ HBufC8* ipAndPort = GetIpAndPortDes8L( );
+ CleanupStack::PushL( ipAndPort );
+
+ HBufC8* ret = aString.AllocLC( );
+
+ TInt pos = KErrNotFound;
+ while ( (pos = ret->Find( *ipAndPort )) != KErrNotFound )
+ {
+ // realloc if too small
+ if ( ipAndPort->Length( ) < KIpPortPlaceholder8().Length( ) )
+ {
+ HBufC8* tmp = ret->ReAllocL( ret->Length( )
+ + KIpPortPlaceholder8().Length( ) - ipAndPort->Length( ) );
+ CleanupStack::Pop( ret );
+ ret = tmp;
+ CleanupStack::PushL( ret );
+ }
+ ret->Des().Replace( pos, ipAndPort->Length( ), KIpPortPlaceholder8 );
+ }
+ // clean up
+ CleanupStack::Pop( ret );
+ CleanupStack::PopAndDestroy( ipAndPort );
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetAddress
+// -----------------------------------------------------------------------------
+TInetAddr CUpnpContentDirectory::GetAddress()
+ {
+ TInetAddr resourceServerAddress;
+ iHttpServerSession->GetAddress( resourceServerAddress );
+ return resourceServerAddress;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::AutoDestroyObjectList
+// -----------------------------------------------------------------------------
+CUpnpAutoDestroyObjectList* CUpnpContentDirectory::GetAutoDestroyObjectList()
+ {
+ return iAutoDestroyObjects;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetIpAndPortDes8L
+// -----------------------------------------------------------------------------
+HBufC8* CUpnpContentDirectory::GetIpAndPortDes8L()
+ {
+ TInetAddr resourceServerAddress = GetAddress();
+
+ TBuf<KMaxName> addrTmp;
+ resourceServerAddress.Output( addrTmp );
+ HBufC8* addr = UpnpString::FromUnicodeL( addrTmp );
+ CleanupStack::PushL( addr );
+
+ TInt portNo = resourceServerAddress.Port();
+ TBuf8<KMaxName> port;
+ port.Num( portNo );
+
+ HBufC8* temp = HBufC8::NewLC( addr->Length( ) + KColon8().Length( ) + port.Length( ) );
+ TPtr8 tempPtr( temp->Des() );
+ tempPtr.Copy( *addr );
+ tempPtr.Append( KColon8 );
+ tempPtr.Append( port );
+
+ CleanupStack::Pop( temp );
+ CleanupStack::PopAndDestroy( addr );
+
+ return temp;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetSearchCapabilitiesL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::GetSearchCapabilitiesL(
+ CUpnpAction*& aAction )
+ {
+ aAction->SetArgumentL( KSearchCaps,
+ StateVariableValue( KSearchCapsVariableName ) );
+ return EHttpOk;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetSortCapabilitiesL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::GetSortCapabilitiesL(
+ CUpnpAction*& aAction )
+ {
+ aAction->SetArgumentL( KSortCaps,
+ StateVariableValue( KSortCapsVariableName ) );
+ return EHttpOk;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetSystemUpdateIdL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::GetSystemUpdateIdL(
+ CUpnpAction*& aAction )
+ {
+ const TPtrC8 idValue = StateVariableValue( (TDesC8&)KSystemUpdateID );
+ aAction->SetArgumentL( KId, idValue );
+ return EHttpOk;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ImportResourceL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::ImportResourceL( CUpnpAction*& aAction )
+ {
+ if ( iTransferController->IsMaxImportExportTransfers( ) )
+ {
+ return ETransferBusy;
+ }
+
+ TPtrC8 src = aAction->ArgumentValue( (TDesC8&) KSourceURI );
+ TPtrC8 dest = aAction->ArgumentValue( (TDesC8&) KDestinationURI );
+ TUriParser8 srcParser;
+ TUriParser8 dstParser;
+
+ if ( !(dstParser.Parse( dest ) ==
+ KErrNone && dstParser.Extract( EUriScheme ).CompareF( UpnpHTTP::KSchemeHTTP8 ) == 0 ) )
+ {
+ User::Leave( ENoDestinationResource );
+ }
+
+ // there are placeholders instead the real values in the database
+ HBufC8* destBuf = InsertIpAndPortPlaceholderL( dest );
+ CleanupStack::PushL( destBuf );
+
+ TInt objId;
+ // object existence
+ if ( (objId
+ = iContentDirectoryDb->GetObjIdByAttrL( KImportUri8, *destBuf ) )
+ == KErrNotFound )
+ {
+ User::Leave( ENoDestinationResource );
+ }
+ // object restrictions
+ if ( iContentDirectoryDb->CheckObjectRestrictionL( objId )
+ == ERestrictedObject )
+ {
+ User::Leave( ERestrictedObject );
+ }
+ // parent restricions
+ if ( iContentDirectoryDb->CheckParentRestrictionL( objId ) != EUpnpOk )
+ {
+ User::Leave( ERestrictedParentObject );
+ }
+
+ TInt destinationCut = dest.LocateReverse( '/' );
+ if ( destinationCut < KErrNone )
+ {
+ User::Leave( EInvalidArgs );
+ }
+
+ HBufC* name = GetFileNameL( objId );
+ CleanupStack::PushL( name );
+ if ( !name )
+ {
+ User::Leave( ENoDestinationResource );
+ }
+
+ for ( TInt i( 0); i < iTransferController->iFileTransfers.Count( ) ; i++ )
+ {
+ if ( iTransferController->iFileTransfers[i]->ObjectId( ) == objId
+ && iTransferController->iFileTransfers[i]->TransferState( )
+ == ETransferInProgress )
+ {
+ User::Leave( EDestinationAccess );
+ }
+ }
+
+ HBufC8* name8 = UpnpString::FromUnicodeL( *name );
+ CleanupStack::PushL( name8 );
+
+ TPtr8 fileNamePtr(name8->Des( ) );
+
+ HBufC16* fileNamePtr16 = UpnpString::ToUnicodeL( fileNamePtr );
+ CleanupStack::PushL( fileNamePtr16 );
+ TParse parseFilename;
+ parseFilename.Set( fileNamePtr16->Des( ), NULL, NULL );
+ HBufC16* diskNameTemp=parseFilename.Drive().Alloc( );
+ HBufC16* diskName = diskNameTemp->ReAlloc( diskNameTemp->Des().Length( ) +
+ KDiskPathElSep().Length( ) );
+ CleanupStack::PushL( diskName );
+ TPtr16 diskNamePtr = diskName->Des( );
+ diskNamePtr.Append( KDiskPathElSep );
+ if ( !BaflUtils::PathExists( iFs, diskNamePtr ) )
+ {
+ User::Leave( ENoDestinationResource );
+ }
+
+ UpnpString::ReplaceHttpCharacters( fileNamePtr );
+
+ // forbidden chars
+ UpnpCdUtils::ValidateFilePath( fileNamePtr );
+
+ HBufC* targetPath = HBufC::NewMaxLC( fileNamePtr.Length( ) );
+ TPtr targetPtr = targetPath->Des( );
+ targetPtr.Copy( fileNamePtr );
+
+ TInt transferid = CUpnpHttpMessage::NewSessionIdL( );
+ iTransferHandler->DownloadFileL( transferid, src, targetPtr );
+
+ CleanupStack::PopAndDestroy( targetPath );
+
+ TransferStartL( dest );
+
+ TBuf8<KMaxIntegerLen> tid;
+ tid.Num( transferid );
+ aAction->SetArgumentL( (TDesC8&)KTransferID, tid );
+
+ CUpnpFileTransfer* transfer = CUpnpFileTransfer::NewLC( transferid,
+ objId, CUpnpFileTransfer::EImport );
+
+ transfer->SetTransferState(:: ETransferInProgress );
+
+ // starting to get the number if import
+ TPtrC8 dest1 = aAction->ArgumentValue( (TDesC8&) KDestinationURI );
+ TInt posOfLastSlash = dest1.LocateReverse( '/' );
+ if( posOfLastSlash != KErrNotFound )
+ {
+ dest1.Set( dest1.Mid( posOfLastSlash + 1 ) );
+ // converting value
+ TLex8 string( dest1 );
+ TInt value( 0 );
+ TInt error = string.Val( value );
+ // conversion ok, we can add this to
+ if( error == KErrNone )
+ {
+ transfer->SetImportNumber( value );
+ }
+ }
+ //add transfer to transfers list
+ CleanupStack::Pop( transfer );
+ iTransferController->iFileTransfers.Append( transfer );
+
+ HBufC* fileName16 = UpnpString::ToUnicodeL( *name8 );
+ CleanupStack::PushL( fileName16 );
+
+ CUpnpFileTransferEvent* event = CUpnpFileTransferEvent::NewLC();
+ event->SetProgressState( CUpnpFileTransferEvent::ECompleted );
+ event->SetDirection( CUpnpFileTransferEvent::EIncoming );
+ event->SetFilePathL( *fileName16 );
+ event->SetContentDirectoryObjectId( objId );
+ event->SetTransferId( transferid );
+ CleanupStack::Pop( event );
+ transfer->SetEvent( event );
+
+ AddFileTransferToTransferIDsStateVariableL( transferid );
+ // clean up
+ CleanupStack::PopAndDestroy( fileName16 );
+ CleanupStack::PopAndDestroy( diskName );
+ CleanupStack::PopAndDestroy( fileNamePtr16 );
+ CleanupStack::PopAndDestroy( name8 );
+ CleanupStack::PopAndDestroy( name );
+ CleanupStack::PopAndDestroy( destBuf );
+
+ return EHttpOk;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ExportResourceL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::ExportResourceL( CUpnpAction*& aAction )
+ {
+ if ( iTransferController->IsMaxImportExportTransfers( ) )
+ {
+ return ETransferBusy;
+ }
+ HBufC8* srcBuf = aAction->ArgumentValue( KSourceURI ).AllocLC( );
+ TPtr8 src(srcBuf->Des( ));
+ UpnpString::ReplaceHttpCharacters( src );
+
+ HBufC8* ipAndPort = GetIpAndPortDes8L( );
+ CleanupStack::PushL( ipAndPort );
+ UpnpCdUtils::ValidateSrcUriL( src, *ipAndPort );
+ CleanupStack::PopAndDestroy( ipAndPort );
+
+ TPtrC8 dest = aAction->ArgumentValue( KDestinationURI );
+
+ // check src existence -----------------------------
+ CUpnpResourcesBean* rscBean = NULL;
+ TRAPD(
+ error,
+ rscBean
+ = iContentDirectoryDb->GetResourceL( UpnpCdUtils::ResIdFromUriL( src ) ) );
+ if ( error < 0 || !rscBean )
+ {
+ User::Leave( ENoSourceResource );
+ }
+ CleanupStack::PushL( rscBean );
+ // check whether resource and src uri file names matches
+ TPtrC rscPath(rscBean->Path( ) );
+
+ if ( !BaflUtils::FileExists( iFs, rscPath ) )
+ {
+ User::Leave( ENoSourceResource );
+ }
+
+ TParse rscParse;
+ rscParse.Set( rscPath, NULL, NULL );
+ TPtrC rscFileName = rscParse.NameAndExt( );
+
+ TBuf8<KMaxIntegerLen> objId;
+ objId.Num( rscBean->ObjectId( ) );
+
+ TPtrC rscFileExt = rscParse.Ext( );
+ HBufC8* srcNoEsc = src.AllocLC( );
+ TPtr8 srcNoEscPtr(srcNoEsc->Des( ));
+
+ HBufC* srcPath = UpnpCdUtils::Des8ToDesLC( srcNoEscPtr );
+ TPtr srcPathPtr(srcPath->Des( ) );
+
+ TInt position = srcPathPtr.LocateReverse( '/' );
+ HBufC* newFileName = HBufC::NewLC( KMaxIntegerLen + rscFileExt.Length( ) );
+ newFileName->Des().Copy( objId );
+ newFileName->Des().Append( rscFileExt );
+ if ( position )
+ {
+ position = srcPathPtr.Length( )-position-1;
+ TPtrC srcFilePtr = srcPathPtr.Right( position );
+ if ( srcFilePtr.Compare( *newFileName ) )
+ {
+ User::Leave( ENoSourceResource );
+ }
+ }
+ if ( srcPathPtr.Find( *newFileName ) == KErrNotFound )
+ {
+ User::Leave( ENoSourceResource );
+ }
+ // get mimeType = Content-Type in the header
+ HBufC8* contentType = UpnpFileUtil::GetMimeTypeForFileL( *newFileName );
+ TPtrC8 contentTypePtr(contentType->Des( ) );
+
+ CleanupStack::PopAndDestroy( newFileName );
+ CleanupStack::PushL( contentType );
+
+ //checking number of slash in sourceURI
+ TInt numberOfSlash(0);
+ position = srcPathPtr.LocateReverse( '/' );
+ while ( position>0 )
+ {
+ numberOfSlash++;
+ if ( numberOfSlash>KMaxSlashAmount )
+ {
+ User::Leave( ENoSourceResource );
+ }
+ srcPathPtr = srcPathPtr.Left( position );
+ position = srcPathPtr.LocateReverse( '/' );
+ }
+
+ TInt transferid = CUpnpHttpMessage::NewSessionIdL( );
+ iTransferHandler->UploadFileL( transferid, dest, rscPath, contentTypePtr );
+
+ TBuf8<KMaxIntegerLen> tid;
+ tid.Num( transferid );
+ aAction->SetArgumentL( (TDesC8&)KTransferID, tid );
+
+ TPtrC8 pert = UpnpCdUtils::ResIdFromUriDesL( src );
+
+ TInt objectId = rscBean->ObjectId( );
+ CUpnpFileTransfer* transfer = CUpnpFileTransfer::NewL( transferid,
+ objectId, CUpnpFileTransfer::EExport );
+ transfer->SetTransferState(:: ETransferInProgress);
+
+ iTransferController->iFileTransfers.Append( transfer );
+
+ CUpnpFileTransferEvent* event = CUpnpFileTransferEvent::NewLC();
+ event->SetProgressState( CUpnpFileTransferEvent::ECompleted );
+ event->SetDirection( CUpnpFileTransferEvent::EOutgoing );
+ event->SetFilePathL( rscPath);
+ event->SetContentDirectoryObjectId( objectId );
+ event->SetTransferId( transferid );
+ CleanupStack::Pop( event );
+ transfer->SetEvent(event);
+
+ AddFileTransferToTransferIDsStateVariableL( transferid );
+ CleanupStack::PopAndDestroy( contentType );
+ CleanupStack::PopAndDestroy( srcPath );
+ CleanupStack::PopAndDestroy( srcNoEsc );
+ CleanupStack::PopAndDestroy( rscBean );
+ CleanupStack::PopAndDestroy( srcBuf );
+
+ return EHttpOk;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::StopTransferResourceL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::StopTransferResourceL(
+ CUpnpAction*& aAction )
+ {
+ TInt transferId;
+ TInt err =
+ UpnpString::StringToInt(
+ (TDesC8&) aAction->ArgumentValue( (TDesC8&)KTransferID ),
+ &transferId );
+ if ( KErrNone != err )
+ {
+ User::Leave( ENoFileTransfer );
+ }
+ TUpnpErrorCode
+ upnpErr(iTransferController->StopTransferResourceL( transferId ) );
+ TransferCompletedL( transferId, KErrCancel );
+ return upnpErr;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetTransferProgressL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::GetTransferProgressL(
+ CUpnpAction*& aAction )
+ {
+ TUint transferId;
+ TInt length( KErrNone );
+ TInt totalLength( KErrNone );
+ // TInt lenght is max 15 digits, KMaxInfoName is 16
+ TBuf8<KMaxInfoName> res;
+
+ TInt err = UpnpCdUtils::StringToTUint(
+ (TDesC8&)aAction->ArgumentValue( (TDesC8&)KTransferID ), &transferId );
+
+ if ( KErrNone != err )
+ {
+ User::Leave( EInvalidArgs );
+ }
+ if ( transferId > KMaxTInt )
+ {
+ User::Leave( ENoFileTransfer );
+ }
+ TInt transferFound = iTransferController->Transfer( transferId );
+ if ( KErrNotFound == transferFound )
+ {
+ User::Leave( ENoFileTransfer );
+ }
+
+ switch ( (iTransferController->iFileTransfers[ transferFound ])->TransferState( ) )
+ {
+ case:: ETransferInProgress:
+ {
+ aAction->SetArgumentL( (TDesC8&)KTransferStatus, KInProgress );
+ break;
+ }
+ case EStopped:
+ {
+ aAction->SetArgumentL( (TDesC8&)KTransferStatus, KStopped );
+ break;
+ }
+ case EError:
+ {
+ aAction->SetArgumentL( (TDesC8&)KTransferStatus, KError );
+ break;
+ }
+ case ECompleted:
+ {
+ aAction->SetArgumentL( (TDesC8&)KTransferStatus, KCompleted );
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ length = (iTransferController->iFileTransfers[ transferFound ])->TransferLength();
+ totalLength = (iTransferController->iFileTransfers[ transferFound ])->TransferTotal();
+
+ res.Num( length );
+ aAction->SetArgumentL( (TDesC8&)KTransferLength, res );
+ res.Num( totalLength );
+ aAction->SetArgumentL( (TDesC8&)KTransferTotal, res );
+ return EHttpOk;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::DeleteResourceL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::DeleteResourceL( CUpnpAction*& aAction )
+ {
+ TPtrC8 uri8(aAction->ArgumentValue( KResourceURI( ) ));
+
+ if ( !uri8.Length( ) )
+ User::Leave( ENoSourceResource );
+
+ // replace http characters
+ HBufC8* uri = uri8.AllocLC( );
+ TPtr8 uriPtr(uri->Des( ));
+
+ // ip placeholder
+ HBufC8* internalUri = InsertIpAndPortPlaceholderL( uriPtr );
+ CleanupStack::PushL( internalUri );
+ // delete resource
+ RArray<TInt> contIds;
+ CleanupClosePushL( contIds );
+ iContentDirectoryDb->DeleteResourceL( *internalUri, contIds );
+
+ // updateIDs
+ for ( TInt i = 0; i < contIds.Count( ); i++ )
+ {
+ TBuf8<KMaxIntegerLen> num;
+ num.Num( contIds[i] );
+ iStateHandler->IncreaseContainerUpdateIdL( num );
+ }
+
+ // systemUpdateId
+ iStateHandler->IncreaseSystemUpdateIdL( );
+
+ // clean up
+ CleanupStack::PopAndDestroy( &contIds );
+ CleanupStack::PopAndDestroy( internalUri );
+ CleanupStack::PopAndDestroy( uri );
+
+ return EHttpOk;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::AddFileTransferL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::AddFileTransferToTransferIDsStateVariableL(
+ TInt aTransferID )
+ {
+ TBuf8<KMaxIntegerLen> tid;
+ tid.Format( UpnpCD::KOneNumber, aTransferID );
+ TPtrC8 tmp = StateVariableValue( KTransferIDs( ) );
+ HBufC8* buf = UpnpString::AddValueToCsvL( tmp, tid );
+ CleanupStack::PushL( buf );
+ SetStateVariableL( KTransferIDs( ), *buf, EFalse );
+ CleanupStack::PopAndDestroy( buf );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::RemoveFileTransferL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::RemoveFileTransferFromTransferIDsStateVariableL(
+ TInt aTransferID )
+ {
+ TBuf8<KMaxIntegerLen> tid;
+ tid.Format( UpnpCD::KOneNumber, aTransferID );
+ TPtrC8 tmp = StateVariableValue( KTransferIDs( ) );
+ HBufC8* buf = UpnpString::RemoveFromCsvLC( tmp, tid );
+ SetStateVariableL( KTransferIDs( ), *buf, EFalse );
+ CleanupStack::PopAndDestroy( buf );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ContainerUpdateId
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpContentDirectory::ContainerUpdateId( const TDesC8& aContainerID )
+ {
+ return iStateHandler->ContainerUpdateId( aContainerID );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CreateObjectL
+// -----------------------------------------------------------------------------
+//
+TUpnpErrorCode CUpnpContentDirectory::CreateObjectL( CUpnpAction*& aAction )
+ {
+ SetExecutedAction( ECreateObjectAction );
+
+ HBufC8* objNoDes(aAction->ArgumentValue(KContainerID()).AllocLC( ) );
+ TPtr8 objNoPtr(objNoDes->Des( ));
+ objNoPtr.TrimAll( );
+
+ TInt objNo = KErrNotFound; // container id
+ TInt error( KErrGeneral );
+
+ // any container support
+ if ( !objNoPtr.Compare( KAnyContainerIndicator8 ) )
+ {
+ objNo = KAnyContainerId;
+ }
+ else
+ {
+ // checking whether containerID has proper decimal value
+ error = UpnpCdUtils::StringToInteger( objNoPtr, &objNo );
+ if ( error != KErrNone )
+ {
+ User::Leave( ENoContainer );
+ }
+
+ TUpnpErrorCode err =
+ iContentDirectoryDb->CheckObjectRestrictionL( objNo );
+ if ( err != EUpnpOk )
+ {
+ CleanupStack::PopAndDestroy( objNoDes );
+ if ( err == ENoSuchObject )
+ err = ENoContainer;
+ if ( err == ERestrictedObject )
+ err = ERestrictedParentObject;
+ return err;
+ }
+ }
+ CleanupStack::PopAndDestroy( objNoDes );
+
+ // now we have found the unrestricted parent container
+ // let's inspect the element that should be added
+ // decode "elements" argument of the create action
+ const TDesC8& elem = (TDesC8&)aAction->ArgumentValue( KElements( ) );
+
+ // check that we've got correctly formed xml
+ if ( elem.FindF( KXmlNsDc( ) ) == KErrNotFound )
+ {
+ User::Leave( EBadMetadata );
+ }
+
+ HBufC8* trimmed = UpnpString::TrimLC( elem, EFalse );
+
+ HBufC8* trimmedlf8 = UpnpString::StringReplaceL( *trimmed, KLF8,
+ KNullString8 );
+ CleanupStack::PushL( trimmedlf8 );
+ // parse decoded buffer
+ RXmlEngDocument fragment;
+ TRAPD( xmlerr, fragment = XmlFragmentL( *trimmedlf8 ) );
+ if ( xmlerr )
+ {
+ RDebug::Print( _L( "CUpnpContentDirectory::CreateObjectL ERROR IN XML" ) );
+ User::Leave( xmlerr );
+ }
+ CleanupClosePushL( fragment );
+
+ // if container, check the number of nested levels
+ TXmlEngElement container;
+ UpnpDomInterface::GetElementL( fragment.DocumentElement( ), container,
+ KContainer );
+ if ( container.NotNull( ) && !iContentDirectoryDb->CanBeNestedL( objNo ) )
+ {
+ User::Leave( ECannotProcess );
+ }
+
+ RArray<TXmlEngAttr> importUris;
+ CleanupClosePushL( importUris );
+ RArray<TXmlEngElement> ress;
+ CleanupClosePushL( ress );
+
+ TBool isLocal = aAction->Local( );
+
+ // to avoid errors in validation process
+ UpnpCdUtils::SetObjectIdL( UpnpCdUtils::GetObjectElementL( fragment ),
+ objNo ); // value does not matter - it will be changed later
+ UpnpCdUtils::SetContainerIdL( UpnpCdUtils::GetObjectElementL( fragment ),
+ objNo );
+
+ //created new object shouldn't have refID value
+ if ( UpnpCdUtils::HasRefIdL( fragment ) )
+ {
+ User::Leave( EParameterMismatch );
+ }
+
+ // validate the new element
+ iElementdb->ValidateNewObjectL( fragment.DocumentElement( ), ETrue,
+ isLocal );
+
+ // now we have fragment, lets add this to CD metadata
+ TInt id( KErrNotFound );
+ TUpnpErrorCode err = AddToMetaDbL( fragment, objNo, &id, isLocal );
+
+ CleanupStack::PopAndDestroy( &ress );
+ CleanupStack::PopAndDestroy( &importUris );
+
+ ConstructCreateResultsetL( aAction, fragment, id );
+
+ CleanupStack::PopAndDestroy( &fragment );
+ CleanupStack::PopAndDestroy( trimmedlf8 );
+ CleanupStack::PopAndDestroy( trimmed );
+
+ if ( err == EHttpOk )
+ {
+ iStateHandler->IncreaseSystemUpdateIdL( );
+ iStateHandler->IncreaseContainerUpdateIdL(
+ ( TDesC8& )aAction->ArgumentValue( KContainerID ) );
+
+ }
+ return err;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::HandleLocalResourcesL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::HandleLocalResourcesL( TXmlEngElement aRes,
+ TInt aObjectId )
+ {
+ // contentUri, contentPath
+ TUriParser8 up;
+ TPtrC8 resVal = aRes.Text( );
+ if ( resVal.Length( ) )
+ {
+ TPtrC8 resValCandidatePtr(resVal);
+
+ // There should be no slash at the end of URI, if so -> leave occurs
+ if ( resValCandidatePtr.Length( ) > 0 )
+ {
+ if ( !resValCandidatePtr.Right(1).Compare( KSlash8( ) ) )
+ {
+ User::Leave( EBadMetadata );
+ }
+ }
+
+ User::LeaveIfError( up.Parse( resValCandidatePtr ) );
+
+ // get schema
+ TPtrC8 scheme(up.Extract( EUriScheme ));
+
+ // only local sharing
+ if ( !scheme.Compare( UpnpHTTP::KSchemeFile8 ) )
+ {
+ HBufC* fn = UpnpString::ToUnicodeL( resValCandidatePtr );
+ CleanupStack::PushL( fn );
+
+ TInt extPosition = fn->Des().LocateReverse( '.' );
+ TPtrC ext;
+ if ( extPosition>0 )
+ ext.Set( fn->Des().Mid( extPosition ) );
+ else
+ ext.Set( KNullString );
+
+ HBufC8* contentUri = BuildContentUriL( ext, aObjectId );
+ CleanupStack::PushL( contentUri );
+
+ HBufC* contentPath = up.GetFileNameL( );
+ CleanupStack::PushL( contentPath );
+
+ // update res tag
+ aRes.SetTextL( *contentUri );
+
+ // add resource to the database
+ CUpnpResourcesBean* resBn = CUpnpResourcesBean::NewLC( );
+ resBn->SetId( UpnpCdUtils::ResIdFromUriL( *contentUri ) );
+ resBn->SetPathL( *contentPath );
+ resBn->SetIsReadonly( ETrue );
+ resBn->SetIsThumbnail( EFalse );
+
+ iContentDirectoryDb->AddResourceL( resBn, aObjectId );
+
+ // clean up
+ CleanupStack::PopAndDestroy( resBn );
+ CleanupStack::PopAndDestroy( contentPath );
+ CleanupStack::PopAndDestroy( contentUri );
+ CleanupStack::PopAndDestroy( fn );
+ }
+ // else -> ignore
+ }
+ // else -> ignore
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ConstructCreateResultsetL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::ConstructCreateResultsetL( CUpnpAction*& aAction,
+ RXmlEngDocument aDocument, TInt aId )
+ {
+ TBuf8<KMaxIntegerLen> num;
+ num.Num( aId );
+
+ aAction->SetArgumentL( KObjectID, num );
+ TXmlEngElement elem = aDocument.DocumentElement( );
+
+ HBufC8* buf = CUpnpXmlContentFilter::SerializeLC( aDocument, elem );
+
+ TPtr8 bufPtr(buf->Des( ));
+ InsertRealIpAndPortL( bufPtr );
+ HBufC8* encoded = UpnpCdUtils::EncodeXmlStringL( bufPtr );
+ CleanupStack::PushL( encoded );
+
+ aAction->SetArgumentL( KResult, *encoded );
+
+ CleanupStack::PopAndDestroy( encoded );
+ CleanupStack::PopAndDestroy( buf );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::XmlFragmentL
+// -----------------------------------------------------------------------------
+//
+RXmlEngDocument CUpnpContentDirectory::XmlFragmentL( const TDesC8 &aBuffer )
+ {
+ //Create a parser
+ RXmlEngDOMParser parser;
+ User::LeaveIfError( parser.Open( iDOMImpl ) );
+ CleanupClosePushL( parser );
+ // DOM document
+ RXmlEngDocument docTree;
+
+ if ( aBuffer.FindF( KXmlNsDc( ) ) == KErrNotFound )
+ {
+ HBufC8* withDidl = HBufC8::NewLC( KDidlTag().Length( ) + aBuffer.Length( ) +
+ KDidlEnd().Length( ) );
+ withDidl->Des().Append( KDidlTag( ) );
+ withDidl->Des().Append( aBuffer );
+ withDidl->Des().Append( KDidlEnd( ) );
+
+ docTree = parser.ParseL( *withDidl );
+ CleanupStack::PopAndDestroy( withDidl );
+ }
+ else
+ {
+ docTree = parser.ParseL( aBuffer );
+ }
+ CleanupStack::PopAndDestroy( &parser );
+ return docTree;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetMimeTypeLC
+// -----------------------------------------------------------------------------
+//
+HBufC8* CUpnpContentDirectory::GetMimeTypeLC( const TDesC8& aFilename )
+ {
+ HBufC16* filename16 = UpnpString::ToUnicodeL( aFilename );
+ CleanupStack::PushL( filename16 );
+ HBufC8* mimetype = UpnpFileUtil::GetMimeTypeForFileL( *filename16 );
+ if ( !mimetype )
+ {
+ mimetype = KNullString8().AllocL( );
+ }
+ CleanupStack::PopAndDestroy( filename16 );
+ CleanupStack::PushL( mimetype );
+ return mimetype;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ChangeFileNameWithExtensionL
+// -----------------------------------------------------------------------------
+HBufC8* CUpnpContentDirectory::ChangeFileNameWithExtensionL(
+ TDesC8& aFilePath, const TDesC8& aMimeType )
+ {
+
+ HBufC8* temp = NULL;
+ TInt position = aFilePath.LocateReverse( '.' );
+ if ( position != KErrNotFound )
+ {
+ return temp;
+ }
+ if ( aMimeType == KNullDesC8 )
+ {
+ return temp;
+ }
+
+ HBufC8* ext = iMimeToExtMap->GetExtensionL( aMimeType );
+ if ( ext == NULL )
+ {
+ return temp;
+ }
+ CleanupStack::PushL( ext );
+ HBufC8* newFilename = HBufC8::NewLC( ext->Length( ) + 1
+ + aFilePath.Length( ) );
+ TPtr8 fileNamePtr(newFilename->Des( ) );
+ fileNamePtr.Append( aFilePath );
+ //fileNamePtr.Append( KDot8());
+ fileNamePtr.Append( *ext );
+
+ HBufC* oldFilename16 = HBufC::NewLC( aFilePath.Length( ) );
+ TPtr oldFilename16Ptr(oldFilename16->Des( ));
+ oldFilename16Ptr.Copy( aFilePath );
+
+ HBufC* newFilename16 = HBufC::NewLC( newFilename->Length( ) );
+ TPtr newFilename16Ptr(newFilename16->Des( ));
+ newFilename16Ptr.Copy( *newFilename );
+
+ TBool exists = BaflUtils::FileExists( iFs, *newFilename16 );
+ if ( exists )
+ {
+ TInt error( KErrNone );
+ TInt count( 0);
+ _LIT( KUnderline, "_" );
+
+ CleanupStack::PopAndDestroy( newFilename16 );
+ newFilename16 = NULL;
+
+ HBufC16* ext16 = HBufC16::NewLC( ext->Length( ) );
+ ext16->Des().Copy( *ext );
+
+ TBuf<KMaxIntegerLen> value;
+ newFilename16 = HBufC16::NewLC( aFilePath.Length( ) + KMaxIntegerLen
+ + ext16->Length( ) + KUnderline().Length( ) + KDot().Length( ) );
+ for ( ;; )
+ {
+ // name_xxxxx.ext
+ value.Num( count );
+
+ newFilename16->Des().Copy( aFilePath );
+ newFilename16->Des().Append( KUnderline );
+ newFilename16->Des().Append( value );
+ //adding dot is not not needed anymore
+ newFilename16->Des().Append( *ext16 );
+
+ RFile file;
+ error = file.Open( iFs, *newFilename16, EFileShareExclusive );
+ file.Close( );
+
+ if ( error == KErrNotFound )
+ {
+ break;
+ }
+ else
+ {
+ count++;
+ }
+ }
+ CleanupStack::Pop( newFilename16 );
+ CleanupStack::PopAndDestroy( ext16 );
+ CleanupStack::PushL( newFilename16 );
+ }
+
+ TInt result = iFs.Rename( *oldFilename16, *newFilename16 );
+ if ( result == KErrNone )
+ {
+ temp = HBufC8::NewL( newFilename16->Length( ) );
+ temp->Des().Copy( *newFilename16 );
+
+ }
+ CleanupStack::PopAndDestroy( newFilename16 );
+ CleanupStack::PopAndDestroy( oldFilename16 );
+ CleanupStack::PopAndDestroy( newFilename );
+ CleanupStack::PopAndDestroy( ext );
+
+ return temp;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CreateResTagWithDBRecoveyrL
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpContentDirectory::CreateResTagInternalWithDBRecoveryL(
+ TInt aSessionId, TDesC8& aFilePath, HBufC8* aImportUri,
+ TBool aOnlyThumbnail )
+ {
+ TInt result = 0;
+ TRAPD( err, result = CreateResTagInternalL( aSessionId, aFilePath,
+ aImportUri, aOnlyThumbnail ) );
+ if ( err )
+ {
+ if ( DataBaseHasBeenRecoveredL( err ) )
+ {
+ TRAP( err, iContentDirectoryDb->CheckDatabaseL( ) );
+ if ( err == KErrCorrupt )
+ {
+ err = iContentDirectoryDb->RecreateDatabaseFile( );
+ User::LeaveIfError( err );
+ }
+ TRAP( err, result = CreateResTagInternalL( aSessionId, aFilePath,
+ aImportUri, aOnlyThumbnail ) );
+ if ( err == KErrCorrupt )
+ {
+ err = iContentDirectoryDb->RecreateDatabaseFile( );
+ }
+ }
+ User::LeaveIfError( err );
+ }
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CreateResTagInternalL
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpContentDirectory::CreateResTagInternalL( TInt aSessionId,
+ TDesC8& aFilePath, HBufC8* aImportUri, TBool aOnlyThumbnail )
+ {
+ TInt ret = KErrGeneral;
+ HBufC8* number = UpnpCdUtils::RandomizeL( KRandomMax );
+ CleanupStack::PushL( number );
+ HBufC8* number2 = UpnpCdUtils::RandomizeL( KRandomMax );
+ CleanupStack::PushL( number2 );
+ HBufC8* importRandomize = HBufC8::NewLC( aImportUri->Des().Length( )+number->Des().Length( ) );
+ importRandomize->Des().Copy( *aImportUri );
+ importRandomize->Des().Replace( importRandomize->Length( ) - 4, 4, *number2 );
+ importRandomize->Des().Append( *number );
+
+ RXmlEngDocument obj;
+ TInt objId = KErrNotFound;
+ iContentDirectoryDb->GetObjectByAttrL( obj, &objId, KImportUri8,
+ *aImportUri );
+ CleanupClosePushL( obj );
+
+ if ( !obj.NotNull( ) )
+ {
+ CleanupStack::PopAndDestroy( &obj );
+ CleanupStack::PopAndDestroy( importRandomize );
+ CleanupStack::PopAndDestroy( number2 );
+ CleanupStack::PopAndDestroy( number );
+ return ret;
+ }
+
+ HBufC8* mimeType = GetMimeTypeLC( aFilePath );
+ // CheckFileName
+ HBufC8* newName = ChangeFileNameWithExtensionL( aFilePath, *mimeType );
+ if ( !newName )
+ {
+ // renaming file failed, set the old name
+ newName = HBufC8::NewL( aFilePath.Length( ) );
+ newName->Des().Copy( aFilePath );
+ }
+ CleanupStack::PushL( newName );
+
+ TSize objectSize( 0, 0);
+
+ //GetFileName
+ HBufC16* filename16 = UpnpString::ToUnicodeL( *newName );
+ CleanupStack::PushL( filename16 );
+
+ if ( obj.NotNull( ) && !aOnlyThumbnail )
+ {
+ // if there is already a file related to this importUri delete it
+ DeleteOldResourcesL( obj, *aImportUri, *filename16 );
+
+ // set new contentUri
+ TXmlEngElement objEl = obj.DocumentElement( );
+
+ TPtrC8 fileNamePtr =
+ newName->Mid( newName->LocateReverse( '\\' ) + 1 );
+
+ TInt extPosition = fileNamePtr.LocateReverse( '.' );
+ TPtrC8 ext;
+ if ( extPosition>0 )
+ ext.Set( fileNamePtr.Mid( extPosition ) );
+ else
+ ext.Set( KNullString8 );
+ HBufC8* contUri = HBufC8::NewLC( importRandomize->Length( ) + KSlash().Length( ) +
+ KMaxLongIntegerLen + ext.Length( ) );
+ TPtr8 contUriPtr(contUri->Des( ));
+ contUriPtr.Copy( *importRandomize );
+ contUriPtr.Append( KSlash );
+
+ TBuf8<KMaxLongIntegerLen> num;
+ num.Num( objId );
+ contUriPtr.Append( num );
+ contUriPtr.Append( ext );
+
+ TXmlEngElement resEl;
+ UpnpDomInterface::GetDirectoryElementL( objEl, resEl, KRes( ),
+ KImportUri8( ), aImportUri->Des( ) );
+ resEl.SetTextL( contUriPtr );
+
+ CleanupStack::PopAndDestroy( contUri );
+
+ // set res@size
+ TXmlEngAttr size = resEl.AttributeNodeL( KSize( ) );
+ if ( size.NotNull( ) )
+ {
+ SetResSizeL( size, *filename16 );
+ }
+
+ // set res@protocolInfo
+ HBufC8* protocolInfo =
+ ProtocolInfoFromMimeL( mimeType->Des( ), resEl );
+ CleanupStack::PushL( protocolInfo );
+
+ TXmlEngAttr protInf = resEl.AttributeNodeL( KprotocolInfo( ) );
+ protInf.SetValueL( *protocolInfo );
+
+ CleanupStack::PopAndDestroy( protocolInfo );
+
+ CheckItemTypeForObjectL( obj, *mimeType );
+
+ RemoveFileTransferFromTransferIDsStateVariableL( aSessionId );
+
+ // update database
+ iElementdb->ValidateNewObjectL( obj.DocumentElement( ), EFalse );
+ iContentDirectoryDb->UpdateObjectL( objId, obj );
+
+ // add resource
+ CUpnpResourcesBean* resBn = CUpnpResourcesBean::NewLC( );
+ resBn->SetId( UpnpCdUtils::ResIdFromUriL( *importRandomize ) );
+ resBn->SetPathL( *newName );
+ resBn->SetIsReadonly( EFalse );
+ resBn->SetIsThumbnail( EFalse );
+ iContentDirectoryDb->AddResourceL( resBn, objId );
+ // clean up
+ CleanupStack::PopAndDestroy( resBn );
+ ret = KErrNone;
+ }
+
+ //send event to Media server
+
+
+ CUpnpFileTransferEvent* event =
+ iTransferController->TransferL( aSessionId );
+
+ if ( event )
+ {
+ event->SetFilePathL( *filename16 );
+ //CleanupStack::Pop( event);
+ //iEventObserver->FileTransferEvent( event );
+ }
+
+ // create thumbnail
+ CreateThumbnailL( *filename16, objId );
+
+ // clean up
+ CleanupStack::PopAndDestroy( filename16 );
+ CleanupStack::PopAndDestroy( newName );
+ CleanupStack::PopAndDestroy( mimeType );
+ CleanupStack::PopAndDestroy( &obj );
+ CleanupStack::PopAndDestroy( importRandomize );
+ CleanupStack::PopAndDestroy( number2 );
+ CleanupStack::PopAndDestroy( number );
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::SetResSizeL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::SetResSizeL( TXmlEngAttr aSize,
+ const TDesC& aFilePath )
+ {
+ // get file size
+ RFile file;
+ CleanupClosePushL( file );
+ User::LeaveIfError( file.Open( iFs, aFilePath, EFileRead|EFileShareAny ) );
+ TInt size;
+ User::LeaveIfError( file.Size( size ) );
+
+ // set size
+ TBuf8<KMaxLongIntegerLen> num;
+ num.Num( size );
+ aSize.SetValueL( num );
+
+ CleanupStack::PopAndDestroy( &file );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::DeleteOldResourcesL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::DeleteOldResourcesL( RXmlEngDocument& aObj,
+ const TDesC8& aImportUri, const TDesC& aNewFile )
+ {
+ // for main res tag delete only corresponding record in the resources table
+ TXmlEngElement el;
+ UpnpDomInterface::GetDirectoryElementL( aObj.DocumentElement( ), el,
+ KImportUri8( ), aImportUri );
+ if ( el.NotNull( ) ) // should always be true
+ {
+ TPtrC8 resVal(UpnpDomInterface::GetElementValueL( el ));
+ if ( resVal.Length( ) )
+ {
+ TInt64 resId = UpnpCdUtils::ResIdFromUriL( resVal ) ;
+ // check src existence -----------------------------
+ CUpnpResourcesBean* rscBean = NULL;
+ rscBean = iContentDirectoryDb->GetResourceL( resId );
+ TBool deletefile = ETrue;
+ //checking if a new file is the same as the old one
+ //if so, it means the old one was by chance deleted from the file system
+ if ( rscBean )
+ {
+ TPtrC rscPath(rscBean->Path( ) );
+ if ( !rscPath.Compare( aNewFile ) )
+ deletefile = EFalse;
+ delete rscBean;
+ }
+ iContentDirectoryDb->DeleteResourceByResIdL( resId, deletefile );
+ }
+
+ }
+
+ // destroy all other res tags
+ RArray<TXmlEngElement> elms;
+ CleanupClosePushL( elms );
+ UpnpDomInterface::GetElementListL( aObj.DocumentElement( ), elms, KRes );
+ // for each element
+ for ( TInt i=0; i < elms.Count( ); i++ )
+ {
+ TXmlEngAttr impUri(elms[i].AttributeNodeL( KImportUri( ) ) );
+ if ( impUri.IsNull( ) && !el.IsSameNode( elms[i] ) )
+ {
+ TPtrC8 resVal(UpnpDomInterface::GetElementValueL( elms[i] ));
+ if ( resVal.Length( ) )
+ {
+ iContentDirectoryDb->DeleteResourceByResIdL(
+ UpnpCdUtils::ResIdFromUriL( resVal ) );
+ }
+ elms[i].Remove( );
+ }
+ }
+ CleanupStack::PopAndDestroy( &elms );
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CreateThumbnailCreatorL
+// -----------------------------------------------------------------------------
+//
+CUpnpThumbnailCreator* CUpnpContentDirectory::CreateThumbnailCreatorL(
+ TInt aObjectId )
+ {
+ CUpnpThumbnailCreator* thumbCreator = NULL;
+
+ if ( iBitmapServerConnection == KErrNone )
+ {
+ //check if from the file THUMB can be created.
+ //create thumbnail
+ // in thumbnail save the information.
+ thumbCreator = CUpnpThumbnailCreator::NewLC( this );
+ iThumbnailCreators.AppendL( thumbCreator );
+ TInt index = iThumbnailCreators.Find( thumbCreator );
+ User::LeaveIfError( index );
+ iThObjectIds.Insert( aObjectId, index );
+ CleanupStack::Pop( thumbCreator );
+ }
+ return thumbCreator;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::RemoveThCreatorAndObjectIdLD
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::RemoveThCreatorAndObjectIdLD(
+ CUpnpThumbnailCreator* aThCreator )
+ {
+ TInt index = iThumbnailCreators.Find( aThCreator );
+ if ( index == KErrNotFound )
+ {
+ RDebug::Print( _L( "There is no corresponding thCreator in list. Error situation." ) );
+ delete aThCreator;
+ return;
+ }
+ else
+ {
+ iThumbnailCreators.Remove( index );
+ }
+ if ( index < iThObjectIds.Count( ) )
+ {
+ iThObjectIds.Remove( index );
+ }
+ delete aThCreator;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetObjectIdFromThCreator
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpContentDirectory::GetObjectIdFromThCreator(
+ CUpnpThumbnailCreator* aThCreator )
+ {
+ TInt result = KErrNotFound;
+ TInt index = iThumbnailCreators.Find( aThCreator );
+ RDebug::Print( _L( "Whole number of objects. %d" ) ,
+ iThObjectIds.Count( ) );
+ if ( index < iThObjectIds.Count( ) )
+ {
+ result = iThObjectIds[index];
+ }
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::NotifyThumbnailResultL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::NotifyThumbnailResultL(
+ CUpnpThumbnailCreator* aThCreator, TInt aResult )
+ {
+ TInt result = aResult;
+ RDebug::Print( _L( "Thumbnail has been created with result: %d" ),
+ aResult );
+ if ( aResult == KErrNone )
+ {
+ RXmlEngDocument obj;
+ CleanupClosePushL( obj );
+ TInt objectId = GetObjectIdFromThCreator( aThCreator );
+ TInt err =
+ iContentDirectoryDb->GetObjectL( objectId, obj, KAsterisk8 );
+ if ( err == EUpnpOk )
+ {
+ // get item element
+ TXmlEngElement objElement;
+ UpnpDomInterface::GetElementL( obj.DocumentElement( ),
+ objElement, KItem );
+
+ // add new res tag
+ TXmlEngElement thumbRes(objElement.AddNewElementL( KRes( ) ) );
+
+ // add protocolInfo
+ HBufC8* protocolInfo = ProtocolInfoFromMimeL( KThumbMimeType( ),
+ JPEG_TN, ETrue, ETrue );
+ CleanupStack::PushL( protocolInfo );
+ thumbRes.AddNewAttributeL( KprotocolInfo( ), *protocolInfo );
+ CleanupStack::PopAndDestroy( protocolInfo );
+
+ // add contentUri
+ HBufC8* contUri = BuildContentUriL( aThCreator->GetFileExt( ),
+ objectId );
+ CleanupStack::PushL( contUri );
+ thumbRes.SetTextL( *contUri );
+
+ // add new resource
+ CUpnpResourcesBean* resBean = CUpnpResourcesBean::NewLC( );
+ resBean->SetId( UpnpCdUtils::ResIdFromUriL( *contUri ) );
+ resBean->SetPathL( aThCreator->GetPath( ) );
+ resBean->SetIsReadonly( EFalse );
+ resBean->SetIsThumbnail( ETrue );
+ iContentDirectoryDb->AddResourceL( resBean, objectId );
+
+ // update
+ iElementdb->ValidateNewObjectL( obj.DocumentElement( ), EFalse );
+ iContentDirectoryDb->UpdateObjectL( objectId, obj );
+ RemoveThCreatorAndObjectIdLD( aThCreator );
+
+ // clean up
+ CleanupStack::PopAndDestroy( resBean );
+ CleanupStack::PopAndDestroy( contUri );
+ }
+ else
+ {
+ // delete thumbnail file if exists
+ iFs.Delete( aThCreator->GetPath( ) ); // ignore errors
+ // remove thCreator and objectID from list
+ RemoveThCreatorAndObjectIdLD( aThCreator );
+ result = err;
+ }
+ CleanupStack::PopAndDestroy( &obj );
+ }
+ else
+ {
+ // delete thumbnail file if exists
+ iFs.Delete( aThCreator->GetPath( ) ); // ignore errors
+ // remove thCreator and objectID from list
+ RemoveThCreatorAndObjectIdLD( aThCreator );
+ }
+
+ // notify
+ if ( iThmbObs )
+ {
+ iThmbObs->NotifyThumbnailResultL( 0, result );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CreateResTagL
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpContentDirectory::CreateResTagL( TInt aSessionId,
+ TDesC8& aFilePath, TInt aImportNumber, TBool aOnlyThumbnail )
+ {
+ HBufC8* importUri = UpnpCdUtils::BuildImportUriLC( aImportNumber );
+ TInt ret = CreateResTagInternalWithDBRecoveryL( aSessionId, aFilePath,
+ importUri, aOnlyThumbnail );
+ CleanupStack::PopAndDestroy( importUri );
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ProtocolInfoFromMimeLC
+// -----------------------------------------------------------------------------
+//
+CUpnpDlnaProtocolInfo* CUpnpContentDirectory::CreateProtocolInfoFromMimeL(
+ const TDesC8& aMimeType, TInt aAddInfo )
+ {
+ CUpnpProtocolInfoLocal* protInfo = CUpnpProtocolInfoLocal::NewL(
+ aMimeType, aAddInfo );
+ CleanupStack::PushL( protInfo );
+ protInfo->SetThirdFieldL( aMimeType );
+ CleanupStack::Pop( protInfo );
+ return protInfo;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ProtocolInfoFromMimeL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CUpnpContentDirectory::ProtocolInfoFromMimeL(
+ const TDesC8& aMimeType, TInt aAddInfo, TBool aOpRangeParam,
+ TBool aCiParam /*= EFalse*/)
+ {
+ CUpnpDlnaProtocolInfo* protInfo = CreateProtocolInfoFromMimeL( aMimeType,
+ aAddInfo );
+ if ( aCiParam )
+ {
+ protInfo->SetCiParameter( ETrue );
+ }
+ if ( aOpRangeParam )
+ {
+ protInfo->SetOpParameterL( B_VAL, ETrue );
+ }
+
+ CleanupStack::PushL( protInfo );
+ TPtrC8 protocolInfo = protInfo->ProtocolInfoL( );
+ HBufC8* protocolInfoDes = protocolInfo.Alloc( );
+ CleanupStack::PopAndDestroy( protInfo );
+ return protocolInfoDes;
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ProtocolInfoFromMimeL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CUpnpContentDirectory::ProtocolInfoFromMimeL(
+ const TDesC8& aMimeType, TXmlEngElement& aResEl )
+ {
+ HBufC8* result = NULL;
+ const TDesC8& value = UpnpDomInterface::GetAttrValueL( aResEl,
+ KprotocolInfo );
+ if ( aMimeType.Length( ) > 0 )
+ {
+ if ( value.Length( ) )
+ {
+ CUpnpDlnaProtocolInfo* protocolInfo =
+ CUpnpDlnaProtocolInfo::NewL( (TDesC8&) value );
+ CleanupStack::PushL( protocolInfo );
+ TPtrC8 third = protocolInfo->ThirdField( );
+ if ( !(aMimeType == third ) )
+ {
+ protocolInfo->SetThirdFieldL( (TDesC8&)aMimeType );
+ protocolInfo->SetFourthFieldL( KAsterisk8( ) );
+ }
+ TPtrC8 protInfo = protocolInfo->ProtocolInfoL( );
+ result = protInfo.Alloc( );
+ CleanupStack::PopAndDestroy( protocolInfo );
+ }
+ }
+ else
+ {
+ result = value.AllocL( );
+ }
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetFileNameL
+// -----------------------------------------------------------------------------
+//
+HBufC* CUpnpContentDirectory::GetFileNameL( TInt aObjId )
+ {
+ TInt objId = aObjId;
+ HBufC* result = NULL;
+ RXmlEngDocument objDidl;
+ iContentDirectoryDb->GetObjectL( objId, objDidl, KAsterisk8( ) );
+ CleanupClosePushL( objDidl );
+ TXmlEngElement obj = objDidl.DocumentElement().FirstChild().AsElement( );
+ if ( obj.IsNull( ) )
+ {
+ CleanupStack::PopAndDestroy( &objDidl );
+ return NULL;
+ }
+
+ // file name
+ TXmlEngElement objTitle;
+ UpnpDomInterface::GetElementL( obj, objTitle, KObjTiltleColName8( ) );
+ if ( objTitle.IsNull( ) )
+ {
+ CleanupStack::PopAndDestroy( &objDidl );
+ return NULL;
+ }
+
+ // mime type
+ RArray<TXmlEngElement> reses;
+ CleanupClosePushL( reses );
+ UpnpDomInterface::GetElementListL( obj, reses, KRes );
+ HBufC8* mimeType = NULL;
+ for ( TInt i = 0; i < reses.Count( ); i++ )
+ { // should be only one importUri
+ TXmlEngAttr impUri;
+ impUri = reses[i].AttributeNodeL( KImportUri );
+ if ( impUri.NotNull( ) )
+ {
+ TXmlEngAttr prInfoAttr = reses[i].AttributeNodeL( KprotocolInfo );
+ CUpnpDlnaProtocolInfo* prInfo =
+ CUpnpDlnaProtocolInfo::NewL( prInfoAttr.Value( ) );
+ CleanupStack::PushL( prInfo );
+ mimeType = prInfo->ThirdField().AllocL( );
+ CleanupStack::PopAndDestroy( prInfo );
+ break;
+ }
+ }
+ CleanupStack::PopAndDestroy( &reses );
+
+ TPtrC ext;
+ if ( mimeType )
+ {
+ TPtrC8 mimeTypeCut( *mimeType);
+ TInt position = mimeType->Des().Find( KSemicolon8 );
+ if ( position != KErrNotFound )
+ {
+ mimeTypeCut.Set( mimeType->Des().Left( position ) );
+ }
+
+ const HBufC* tmp = iMimeToExtMap->Get( mimeTypeCut );
+ if ( tmp )
+ {
+ ext.Set( tmp->Ptr( ), tmp->Length( ) ); // do not delete
+ }
+ delete mimeType;
+ }
+
+ result = HBufC::NewLC( objTitle.Value().Length( ) + ext.Length( ) );
+ TPtr resPtr(result->Des( ) );
+ HBufC* title = UpnpCdUtils::Des8ToDesLC( objTitle.Value( ) );
+
+ resPtr.Copy( *title );
+
+ TInt wholeNameLength = title->Des().LocateReverse( '.' );
+ TInt extenLength = title->Length( )-wholeNameLength;
+ TPtrC exten;
+ if ( extenLength )
+ {
+ exten.Set( title->Right( extenLength ) );
+ }
+
+ if ( ext.CompareF( exten ) != 0 )
+ {
+ resPtr.Append( ext );
+ }
+
+ // forbidden chars
+ UpnpCdUtils::ValidateFilePath( resPtr );
+
+ HBufC* basePath = HBufC::NewL( iDownloadDir->Des().Length( ) + result->Des().Length( ) );
+ basePath -> Des().Append( iDownloadDir->Des( ) );
+ basePath -> Des().Append( result->Des( ) );
+
+ CleanupStack::PopAndDestroy( title );
+ CleanupStack::PopAndDestroy( result );
+ CleanupStack::PopAndDestroy( &objDidl );
+
+ if ( BaflUtils::FileExists( iFs, *basePath ) )
+ {
+ CleanupStack::PushL( basePath );
+ HBufC* fileName = CreateFileNameL( basePath->Des( ) );
+ CleanupStack::PopAndDestroy( basePath );
+ return fileName;
+ }
+
+ return basePath;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetFileNameWithoutPathL
+// -----------------------------------------------------------------------------
+//
+HBufC* CUpnpContentDirectory::GetFileNameWithoutPathL( TInt aObjId )
+ {
+ TInt objId = aObjId;
+ HBufC* result = NULL;
+ RXmlEngDocument objDidl;
+ iContentDirectoryDb->GetObjectL( objId, objDidl, KAsterisk8( ) );
+ CleanupClosePushL( objDidl );
+ TXmlEngElement obj = objDidl.DocumentElement().FirstChild().AsElement( );
+ if ( obj.IsNull( ) )
+ {
+ CleanupStack::PopAndDestroy( &objDidl );
+ return NULL;
+ }
+
+ // file name
+ TXmlEngElement objTitle;
+ UpnpDomInterface::GetElementL( obj, objTitle, KObjTiltleColName8( ) );
+ if ( objTitle.IsNull( ) )
+ {
+ CleanupStack::PopAndDestroy( &objDidl );
+ return NULL;
+ }
+
+ // mime type
+ RArray<TXmlEngElement> reses;
+ CleanupClosePushL( reses );
+ UpnpDomInterface::GetElementListL( obj, reses, KRes );
+ HBufC8* mimeType = NULL;
+ for ( TInt i = 0; i < reses.Count( ); i++ )
+ { // should be only one importUri
+ TXmlEngAttr impUri;
+ impUri = reses[i].AttributeNodeL( KImportUri );
+ if ( impUri.NotNull( ) )
+ {
+ TXmlEngAttr prInfoAttr = reses[i].AttributeNodeL( KprotocolInfo );
+ CUpnpDlnaProtocolInfo* prInfo =
+ CUpnpDlnaProtocolInfo::NewL( prInfoAttr.Value( ) );
+ CleanupStack::PushL( prInfo );
+ mimeType = prInfo->ThirdField().AllocL( );
+ CleanupStack::PopAndDestroy( prInfo );
+ break;
+ }
+ }
+ CleanupStack::PopAndDestroy( &reses );
+
+ TPtrC ext;
+ if ( mimeType )
+ {
+ TPtrC8 mimeTypeCut(*mimeType);
+ TInt position = mimeType->Des().Find( KSemicolon8 );
+ if ( position != KErrNotFound )
+ {
+ mimeTypeCut.Set( mimeType->Des().Left( position ) );
+ }
+
+ const HBufC* tmp = iMimeToExtMap->Get( mimeTypeCut );
+ if ( tmp )
+ {
+ ext.Set( tmp->Ptr( ), tmp->Length( ) ); // do not delete
+ }
+ delete mimeType;
+ }
+
+ result = HBufC::NewLC( objTitle.Value().Length( ) + ext.Length( ) );
+ TPtr resPtr(result->Des( ));
+ HBufC* title = UpnpCdUtils::Des8ToDesLC( objTitle.Value( ) );
+
+ resPtr.Copy( *title );
+
+ TInt wholeNameLength = title->Des().LocateReverse( '.' );
+ TInt extenLength = title->Length( )-wholeNameLength;
+ TPtrC exten;
+ if ( extenLength )
+ {
+ exten.Set( title->Right( extenLength ) );
+ }
+
+ if ( ext.CompareF( exten )!=0 )
+ resPtr.Append( ext );
+
+ // forbidden chars
+ UpnpCdUtils::ValidateFilePath( resPtr );
+
+ // clean up
+ CleanupStack::PopAndDestroy( title );
+ CleanupStack::Pop( result );
+ CleanupStack::PopAndDestroy( &objDidl );
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CreateFileNameL
+// -----------------------------------------------------------------------------
+//
+HBufC* CUpnpContentDirectory::CreateFileNameL( const TDesC16& aFileName )
+ {
+ const TInt KMaxSameFileNames = 10000;
+ TParse parseFilename;
+ parseFilename.Set( aFileName, NULL, NULL );
+
+ // orginal file + underscore + number
+ HBufC* name = HBufC::NewLC( aFileName.Length( ) + KMaxIntegerLen );
+ TPtr namePtr(name->Des( ) );
+
+ for ( TInt count = 1; count < KMaxSameFileNames; count++ )
+ {
+ TBuf<KMaxIntegerLen> value;
+ value.Num( count );
+
+ namePtr.Append( parseFilename.DriveAndPath( ) );
+ namePtr.Append( parseFilename.Name( ) );
+ namePtr.Append( KUndersc( ) );
+ namePtr.Append( value );
+ namePtr.Append( parseFilename.Ext( ) );
+
+ if ( !BaflUtils::FileExists( iFs, namePtr ) )
+ {
+ break;
+ }
+ namePtr.Zero( );
+ }
+
+ CleanupStack::Pop( name );
+ return name;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetTitleForUriL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::GetTitleForUriL( TInt aObjectId, TPtr& aValue )
+ {
+ HBufC* result = GetFileNameWithoutPathL( aObjectId );
+ TPtr des = result->Des( );
+ UpnpCdUtils::ValidateFilePath( des );
+ if ( result == NULL )
+ {
+ return;
+ }
+ aValue.Copy( *result );
+ delete result;
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CheckImportUriL
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpContentDirectory::CheckImportUriL( const TDesC8& aImportUri )
+ {
+ TInt objId = KErrNotFound;
+
+ // http characters
+ HBufC8* dest8 = HBufC8::NewLC( aImportUri.Length( ) );
+ TPtr8 dest8Ptr(dest8->Des( ));
+ dest8Ptr.Copy( aImportUri );
+
+ UpnpString::ReplaceHttpCharacters( dest8Ptr );
+
+ // ip and port placeholder
+ HBufC8* dest = InsertIpAndPortPlaceholderL( dest8Ptr );
+ CleanupStack::PushL( dest );
+
+ objId = iContentDirectoryDb->GetObjIdByAttrLikeL( KImportUri8, *dest );
+
+ // clean up
+ CleanupStack::PopAndDestroy( dest );
+ CleanupStack::PopAndDestroy( dest8 );
+
+ return objId;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CreateAddressValueLC
+// -----------------------------------------------------------------------------
+//
+HBufC8* CUpnpContentDirectory::CreateAddressValueLC()
+ {
+
+ HBufC8* result = NULL;
+
+ CBufFlat* resBuf = CBufFlat::NewL( KMaxName );
+ CleanupStack::PushL( resBuf );
+
+ UpnpString::AppendStringL( *resBuf, KHttpTag( ) );
+ UpnpString::AppendStringL( *resBuf, KIpPortPlaceholder8( ) );
+
+ result = HBufC8::NewL( resBuf->Size( ) );
+ TPtr8 resultPtr(result->Des( ));
+ resultPtr.Copy( resBuf->Ptr( 0 ) );
+ CleanupStack::PopAndDestroy( resBuf );
+ CleanupStack::PushL( result );
+ return result;
+ // path
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetImportUriLC
+// -----------------------------------------------------------------------------
+//
+HBufC8* CUpnpContentDirectory::GetImportUriLC( CUpnpHttpMessage* aMessage )
+ {
+ TPtrC8 path = aMessage->SenderPathFromHeader( );
+ if ( path.Find( KHttpTag ) == KErrNotFound )
+ {
+ HBufC8* serverAddr = CreateAddressValueLC( );
+ HBufC8* result =
+ HBufC8::NewL( serverAddr->Length( ) + path.Length( ) );
+ TPtr8 resultPtr(result->Des( ) );
+ resultPtr.Append( *serverAddr );
+ resultPtr.Append( path );
+ CleanupStack::PopAndDestroy( serverAddr );
+ CleanupStack::PushL( result );
+ return result;
+ }
+ else
+ {
+ HBufC8* pathHBuf = InsertIpAndPortPlaceholderL( path );
+ CleanupStack::PushL( pathHBuf );
+ return pathHBuf;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetProtocolInfoByImportUriL
+// -----------------------------------------------------------------------------
+//
+CUpnpDlnaProtocolInfo* CUpnpContentDirectory::GetProtocolInfoByImportUriL(
+ const TDesC8& aImportUri )
+ {
+ TPtrC8 importUri;
+ importUri.Set( UpdateImportUriL( aImportUri ) );
+
+ CUpnpDlnaProtocolInfo* protocolInfo = NULL;
+ // check restriction - cannot export to the restricted object
+ TInt objId = iContentDirectoryDb->
+ GetObjIdByAttrLikeL( KImportUri8, importUri );
+
+ if ( objId < 0 )
+ {
+ User::Leave( ENoSuchObject );
+ }
+
+ if ( iContentDirectoryDb->
+ CheckObjectRestrictionL( objId ) == ERestrictedObject )
+ {
+ User::Leave( ERestrictedObject );
+ }
+ // parent restricions
+ if ( iContentDirectoryDb->CheckParentRestrictionL( objId ) != EUpnpOk )
+ {
+ User::Leave( ERestrictedParentObject );
+ }
+ else
+ {
+ HBufC8* protInfoBuf = iContentDirectoryDb->
+ GetProtocolInfoByImportUriL( importUri );
+
+ if ( protInfoBuf )
+ {
+ CleanupStack::PushL( protInfoBuf );
+ protocolInfo = CUpnpDlnaProtocolInfo::NewL( protInfoBuf->Des( ) );
+ CleanupStack::PopAndDestroy( protInfoBuf );
+ }
+ }
+ return protocolInfo;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::UpdateImportUriL
+// -----------------------------------------------------------------------------
+//
+TPtrC8 CUpnpContentDirectory::UpdateImportUriL( const TDesC8& aImportUri )
+ {
+ HBufC8* portAndIp = GetIpAndPortDes8L();
+ CleanupStack::PushL( portAndIp );
+
+ TPtrC8 importUri;
+ importUri.Set( aImportUri );
+
+ TInt index = aImportUri.Find( *portAndIp );
+ if ( index > 0 )
+ {
+ importUri.Set( aImportUri.Mid( index + portAndIp->Des().Length() ) );
+ }
+
+ CleanupStack::PopAndDestroy( portAndIp );
+
+ //--- replaceing e.g '/0000000004' -> '0000000004'
+ index = importUri.Find( KSlash8() );
+ // importUri must begins with '/'
+ if ( !index )
+ {
+ importUri.Set( importUri.Mid( index + 1 ) );
+ }
+ else
+ {
+ User::Leave( ENoSuchObject );
+ }
+ //----------------------------------------
+
+ if ( importUri.Length() < KMaxIntegerLen )
+ {
+ User::Leave(ENoSuchObject);
+ }
+
+ // Check if all signs in uri are digits
+ TLex8 lex( importUri );
+ for( TInt i( 0 ); i < importUri.Length(); i++ )
+ {
+ if ( !( lex.Get() ).IsDigit() )
+ {
+ User::Leave( ENoSuchObject );
+ }
+ }
+ return importUri;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetProtocolInfoL
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpContentDirectory::GetProtocolInfoL( const TDesC8& aContentUri,
+ CUpnpDlnaProtocolInfo*& aProtocolInfo )
+ {
+ HBufC8 *buf = InsertIpAndPortPlaceholderL( aContentUri );
+ CleanupStack::PushL( buf );
+ TInt err = iContentDirectoryDb->GetProtocolInfoL( buf->Des( ),
+ aProtocolInfo );
+ CleanupStack::PopAndDestroy( buf );
+ return err;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::FindSharedFolderL
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpContentDirectory::FindSharedFolderL( const TDesC& aUrlPath,
+ const TDesC& aFileName, HBufC*& aSystemPath )
+ {
+ TInt ret = KErrNotFound;
+ aSystemPath = NULL;
+ if ( aUrlPath.Length( ) )
+ {
+ // validate the path string
+ if ( IsValidUrlPath( aUrlPath ) )
+ {
+ // get resource id
+ TLex lexer(aUrlPath);
+ TInt64 resId;
+ if ( !lexer.Val( resId ) )
+ {
+ // get resource
+ CUpnpResourcesBean* resBn = iContentDirectoryDb->
+ GetResourceL( resId );
+ if ( resBn )
+ {
+ CleanupStack::PushL( resBn );
+ aSystemPath = resBn->Path().AllocL( );
+ TInt objectId = resBn->ObjectId( );
+ CleanupStack::PopAndDestroy( resBn );
+
+ // make sure that systam path points to the wanted file
+ TParse fp;
+ fp.Set( *aSystemPath, 0, 0 );
+ HBufC* tmp = aFileName.AllocLC( );
+ TPtr tmpPtr(tmp->Des( ));
+ UpnpString::ReplaceHttpCharactersL( tmpPtr );
+ TPtrC ext = fp.Ext( );
+ HBufC* file = HBufC::NewLC( KMaxIntegerLen
+ + ext.Length( ) );
+ TBuf<KMaxIntegerLen> num;
+ num.Num( objectId );
+ file->Des().Append( num );
+ file->Des().Append( ext );
+
+ if ( file->Des( ) == tmpPtr )
+ {
+ ret = KErrNone;
+ }
+ CleanupStack::PopAndDestroy( file );
+ CleanupStack::PopAndDestroy( tmp );
+ }
+ }
+ }
+ }
+ else
+ { // default download dir
+ aSystemPath = iDownloadDir->AllocL( );
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::IsValidUrlPathL
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpContentDirectory::IsValidUrlPath( const TDesC& aUrlPath )
+ {
+ TInt ret = ETrue;
+ if ( (aUrlPath.Length( ) != KMaxIntegerLen + KRandomRangeLength)
+ && (aUrlPath.Length( ) != KMaxIntegerLen + KRandomRangeLength
+ + KRandomRangeLength) )
+ {
+ ret = EFalse;
+ }
+ else
+ {
+ for ( TInt i = 0; i < aUrlPath.Length( ); i++ )
+ if ( aUrlPath[i] < '0' || aUrlPath[i] > '9' )
+ {
+ ret = EFalse;
+ break;
+ }
+ }
+
+ return ret;
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetItemTypeFromMimeTypeLC
+// -----------------------------------------------------------------------------
+HBufC8* CUpnpContentDirectory::GetItemTypeFromMimeTypeLC(
+ const TDesC8& aMimeType )
+ {
+ HBufC8* result = NULL;
+ if ( aMimeType.Compare( KNullDesC8( ) ) == 0 )
+ {
+ return result;
+ }
+ TInt indexOfSlash = aMimeType.Find( KSlash8( ) );
+ if ( indexOfSlash < KErrNone )
+ {
+ return result;
+ }
+ TPtrC8 firstValue = aMimeType.Left( indexOfSlash );
+ if ( firstValue.Compare( KImageMime( ) ) == 0 )
+ {
+ result = KObjectClassImageItem().AllocLC( );
+ }
+ else if ( firstValue.Compare( KTextMime( ) ) == 0 )
+ {
+ result = KObjectClassTextItem().AllocLC( );
+ }
+ else if ( firstValue.Compare( KVideoMime( ) ) == 0 )
+ {
+ result = KObjectClassVideoItem().AllocLC( );
+ }
+ else if ( firstValue.Compare( KAudioMime( ) ) == 0 )
+ {
+ result = KObjectClassAudioItem().AllocLC( );
+ }
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::GetItemTypeFromMimeTypeLC
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::CheckItemTypeForObjectL( RXmlEngDocument& aObj,
+ const TDesC8& aMimeType )
+ {
+ // temporary disable because of mime-type recognition problem
+ HBufC8* itemType = GetItemTypeFromMimeTypeLC( aMimeType );
+ if ( !itemType )
+ {
+ return;
+ }
+ TXmlEngElement obj = aObj.DocumentElement( );
+ TXmlEngElement objClass;
+ UpnpDomInterface::GetElementL( obj, objClass, KObjClassColName8 );
+ TPtrC8 classValue(UpnpDomInterface::GetElementValueL( objClass ));
+ if ( classValue.Compare( itemType->Des( ) ) < 0 )
+ {
+ objClass.SetTextL( *itemType );
+ }
+ CleanupStack::PopAndDestroy( itemType );
+
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::SetDownloadDirectoryL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::SetDownloadDirectoryL( const TDesC& aDownloadDir )
+ {
+ // perform necessary changes in database
+ iContentDirectoryDb->NewMediaDirectoryL( *iDownloadDir );
+
+ // alloc new string
+ delete iDownloadDir;
+ iDownloadDir = NULL;
+ TPtrC last = aDownloadDir.Right( 1 );
+ if ( last.Compare( KDiskPathElSep )!=0 )
+ {
+ iDownloadDir = HBufC::NewL( aDownloadDir.Length( )+ KDiskPathElSep().Length( ) );
+ iDownloadDir->Des().Copy( aDownloadDir );
+ iDownloadDir->Des().Append( KDiskPathElSep );
+ }
+ else
+ {
+ iDownloadDir = HBufC::NewL( aDownloadDir.Length( ) );
+ iDownloadDir->Des().Copy( aDownloadDir );
+ }
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::SetThumbnailDirectoryL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::SetThumbnailDirectoryL( const TDesC& aDownloadDir )
+ {
+ // perform necessary changes in database
+ iContentDirectoryDb->NewMediaDirectoryL( *iThumbDir );
+
+ // alloc new string
+ delete iThumbDir;
+ iThumbDir = NULL;
+ iThumbDir = aDownloadDir.AllocL( );
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::HandleDbError
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpContentDirectory::HandleDbError( TInt aError )
+ {
+ return iContentDirectoryDb->HandleDbError( aError );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::DataBaseHasBeenRecoveredL
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpContentDirectory::DataBaseHasBeenRecoveredL( TInt aError )
+ {
+ TInt err = aError;
+ if ( err == KErrCorrupt )
+ {
+ err = HandleDbError( err );
+ }
+ return (err == KErrNone && aError == KErrCorrupt ) ? ETrue : EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::IsDbOrDiskProblemL
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpContentDirectory::IsDbOrDiskProblemL( CUpnpAction* aAction )
+ {
+ TBool noSpace = SysUtil::DiskSpaceBelowCriticalLevelL( &iFs,
+ KMinDiskSpace, EDriveC );
+ TInt error( KErrNone );
+ if ( !noSpace )
+ {
+ if ( !IsDbCreated() )
+ {
+ error = HandleDbError( KErrCorrupt );
+ }
+ }
+ if ( noSpace || error != KErrNone )
+ {
+ DoSendActionL( aAction, ECannotProcess );
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::IsDbCreated
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpContentDirectory::IsDbCreated()
+ {
+ return iContentDirectoryDb->IsDbCreated( );
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::CreateNameForThumbnailL
+// -----------------------------------------------------------------------------
+//
+HBufC* CUpnpContentDirectory::CreateNameForThumbnailL( const TDesC& aFileName )
+ {
+ // only name
+ TParse fp;
+ User::LeaveIfError( fp.Set( aFileName, 0, 0 ) );
+ TFileName bareName = fp.Name( );
+ // full name
+ User::LeaveIfError( fp.Set( bareName, iThumbDir, &KDefaultThumbExtension ) );
+ TFileName fullName = fp.FullName( );
+
+ //check if exists
+ TUint ignored;
+ TInt q = 0;
+ while ( iFs.Att( fullName, ignored ) == KErrNone )
+ {
+ q++;
+ TBuf<KMaxIntegerLen> num;
+ num.Num( q );
+ TFileName tmpName;
+ tmpName.Copy( bareName );
+ tmpName.Append( KUndersc );
+ tmpName.Append( num );
+ fp.Set( tmpName, iThumbDir, &KDefaultThumbExtension );
+ fullName = fp.FullName( );
+ }
+
+ return fullName.AllocL( );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::AutoDestroyEventL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::AutoDestroyEventL( TInt aObjId, TBool aDeleteObj )
+ {
+ if ( !ValidateObjectL( aObjId ) )
+ {
+ return;
+ }
+
+ if ( aDeleteObj )
+ {
+ TBuf8<KMaxIntegerLen> containerID;
+ containerID.Num( iContentDirectoryDb->GetParentIdL( aObjId ) );
+ RArray<TInt> refList;
+ CleanupClosePushL( refList );
+ iContentDirectoryDb->DeleteObjectL( aObjId, refList, ETrue );
+
+ // supporting ContainerUpdateIDs behaviour
+ iStateHandler->IncreaseSystemUpdateIdL( );
+ iStateHandler->IncreaseContainerUpdateIdL( containerID );
+ for ( TInt i(0); i<refList.Count( ); i++ )
+ {
+ iStateHandler->IncreaseSystemUpdateIdL( );
+ containerID.Num( refList[i] );
+ iStateHandler->IncreaseContainerUpdateIdL( containerID );
+ }
+
+ // clean up
+ CleanupStack::PopAndDestroy( &refList );
+ }
+ iAutoDestroyObjects->RemoveAndDestroyL( iAutoDestroyObjects->FindObjIndexByObjId( aObjId ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::HttpTransferEventReceivedL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpContentDirectory::HttpTransferEventReceivedL( CUpnpHttpMessage& aHttpMsg )
+ {
+ switch ( aHttpMsg.Type( ) )
+ {
+ case ETransferStart:
+ {
+ TransferStartL( aHttpMsg.SenderPathFromHeader( ) );
+
+ CUpnpFileTransfer::TTransferType type;
+ TInt objectid(0);
+
+ if ( aHttpMsg.Method().Find( KHttpGet ) == 0 )
+ {
+ objectid = iContentDirectoryDb->GetObjIdByAttrL( KImportUri8,
+ aHttpMsg.SenderPathFromHeader( ) );
+ type = CUpnpFileTransfer::EImport;
+ }
+ else
+ {
+ objectid = iContentDirectoryDb->GetObjIdByAttrLikeL(
+ KImportUri8, aHttpMsg.SenderPathFromHeader( ) );
+ type = CUpnpFileTransfer::EUpload;
+
+ }
+ CUpnpFileTransfer* transfer = CUpnpFileTransfer::NewLC(
+ aHttpMsg.SessionId( ), objectid, type );
+
+ transfer->SetTransferState(:: ETransferInProgress);
+ transfer->SetImportNumber(UpnpCdUtils::ResIdFromUriL(
+ aHttpMsg.SenderPathFromHeader()));
+
+ iTransferController->iFileTransfers.Append(transfer);
+ CleanupStack::Pop( transfer );
+
+ iTransferController->AddIncomingTransferInternalL(&aHttpMsg);
+ break;
+ }
+ case ETransferError:
+ {
+ iTransferController->TransferFailL( &aHttpMsg );
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ImportComplete
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::TransferProgress( TInt aId, TInt aBytes,
+ TInt aTotalBytes )
+ {
+ TInt transferId = iTransferController->Transfer( aId );
+ if ( transferId != KErrNotFound )
+ {
+ (iTransferController->iFileTransfers[ transferId ])->SetTransferLength( aBytes );
+ (iTransferController->iFileTransfers[ transferId ])->SetTransferTotal( aTotalBytes );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::TransferStartL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::TransferStartL( const TDesC8& aImpUri )
+ {
+ TInt index = iAutoDestroyObjects->FindObjIndexByResId( UpnpCdUtils::ResIdFromUriL( aImpUri ) );
+ if ( index != KErrNotFound )
+ {
+ (*iAutoDestroyObjects)[index]->SetTransferStartedL( ETrue );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::TransferCompleteL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::TransferCompleteL( TInt aResId, TInt aObjId )
+ {
+ TInt index = iAutoDestroyObjects->FindObjIndexByResId( aResId );
+ if ( index != KErrNotFound )
+ {
+ iAutoDestroyObjects->RemoveAndDestroyL( index );
+ }
+
+ if ( (aObjId>=0)&&(aResId>=0)
+ &&(iContentDirectoryDb->GetParentIdL( aObjId )>=0) )
+ {
+ TBuf8<KMaxIntegerLen> containerID;
+ containerID.Num( iContentDirectoryDb->GetParentIdL( aObjId ) );
+ iStateHandler->IncreaseSystemUpdateIdL( );
+ iStateHandler->IncreaseContainerUpdateIdL( containerID );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::NotifyTransferFailL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::NotifyTransferFailL( TInt aSessionId,
+ TInt aStatusCode )
+ {
+ CUpnpFileTransferEvent* event =
+ iTransferController->RemoveTransferLC( aSessionId );
+ if ( event )
+ {
+ event->SetProgressState( CUpnpFileTransferEvent::EFailed );
+ event->SetErrorCode( aStatusCode );
+ CleanupStack::Pop( event );
+ iEventObserver->FileTransferEvent( event );
+ }
+
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::NotifyTransferStoppedL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::NotifyTransferStoppedL( TInt aSessionId,
+ CUpnpFileTransfer::TTransferType aType )
+ {
+ CUpnpFileTransferEvent* event =
+ iTransferController->RemoveTransferLC( aSessionId );
+ if ( event )
+ {
+ event->SetProgressState( CUpnpFileTransferEvent::EStopped );
+ if ( aType == CUpnpFileTransfer::EImport )
+ {
+ event->SetDirection( CUpnpFileTransferEvent::EIncoming );
+ }
+ else
+ {
+ event->SetDirection( CUpnpFileTransferEvent::EOutgoing );
+ }
+
+ CleanupStack::Pop( event );
+ iEventObserver->FileTransferEvent( event );
+ }
+
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::NotifyOutgoingTransferL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::NotifyOutgoingTransferL( TInt aSessionId )
+ {
+ CUpnpFileTransferEvent* event =
+ iTransferController->RemoveTransferLC( aSessionId );
+ if ( event )
+ {
+ CleanupStack::Pop( event );
+ //send event to Media Server
+ iEventObserver->FileTransferEvent( event );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::SetSender
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpContentDirectory::SetSender( MUpnpCdsSender* aSender )
+ {
+ iSender = aSender;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::DoSendActionL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::DoSendActionL( CUpnpAction* aAction,
+ TUpnpErrorCode aError )
+ {
+ iSender->SendL( aAction, aError );
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::DoSendActionL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::DoSendMessageL( CUpnpHttpMessage* aMessage )
+ {
+ iSender->SendL( aMessage );
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::SendActionL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpContentDirectory::SendActionL( CUpnpAction* aAction,
+ TUpnpErrorCode aError )
+ {
+ SendL( aAction, aError );
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::DoSendActionL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpContentDirectory::SendMessageL( CUpnpHttpMessage* aMessage )
+ {
+ SendL( aMessage );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::StateVariableEvented
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::StateVariableEvented( const TDesC8& aVariableName )
+ {
+ iStateHandler->StateVariableEvented( aVariableName );
+ }
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::StateHandler
+// -----------------------------------------------------------------------------
+//
+CUpnpStateHandler* CUpnpContentDirectory::StateHandler()
+ {
+ return iStateHandler;
+ }
+
+// helper functions
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ExecutedAction
+// -----------------------------------------------------------------------------
+//
+TCurrentAction CUpnpContentDirectory::ExecutedAction()
+ {
+ return iCurrentAction;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::SetExecutedAction
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::SetExecutedAction( TCurrentAction aAction )
+ {
+ iCurrentAction = aAction;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::HttpResponseReceivedL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::HttpResponseReceivedL( TInt aSessionId,
+ TInt aStatusCode )
+ {
+ iTransferController->HttpResponseReceivedL( aSessionId, aStatusCode );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::EventObserver
+// -----------------------------------------------------------------------------
+//
+MUpnpContentDirectoryEventObserver* CUpnpContentDirectory::EventObserver()
+ {
+ return iEventObserver;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ContentDirectoryDb
+// -----------------------------------------------------------------------------
+//
+CUpnpContentDirectoryDb* CUpnpContentDirectory::ContentDirectoryDb()
+ {
+ return iContentDirectoryDb;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::IsObjectExistL
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpContentDirectory::IsObjectExistL( TInt aObjectId )
+ {
+ if ( iContentDirectoryDb->CheckObjectRestrictionL( aObjectId )
+ == ENoSuchObject )
+ {
+ return EFalse;
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::ValidateObjectL
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpContentDirectory::ValidateObjectL( TInt aObjectId )
+ {
+ //removes from autodestroy array orphaned objects
+ TInt i(0);
+ TInt index(0);
+ while ( i < iAutoDestroyObjects->Count( ) )
+ {
+ TInt parentID( iContentDirectoryDb->GetParentIdL(
+ ( *iAutoDestroyObjects )[ i ]->GetObjId( ) ) );
+ if ( parentID < 0 )
+ {
+ index = iAutoDestroyObjects->FindObjIndexByObjId( (
+ *iAutoDestroyObjects )[ i ]->GetObjId( ) );
+ iAutoDestroyObjects->RemoveAndDestroyL( index );
+ continue;
+ }
+ i++;
+ }
+
+ //checks if given object exists
+ if ( !IsObjectExistL( aObjectId ) )
+ {
+ index = iAutoDestroyObjects->FindObjIndexByObjId( aObjectId );
+ if ( index != KErrNotFound )
+ {
+ iAutoDestroyObjects->RemoveAndDestroyL( index );
+ }
+ }
+
+ //cheks if given object exists in autodestroy array
+ index = iAutoDestroyObjects->FindObjIndexByObjId( aObjectId );
+ if ( index != KErrNotFound )
+ {
+ return ETrue;
+ }
+
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::TransferHandler
+// -----------------------------------------------------------------------------
+//
+MUpnpTransferInterface* CUpnpContentDirectory::TransferHandler()
+ {
+ return iTransferHandler;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::TransferCompletedL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::TransferCompletedL( TInt aKey, TInt aResultCode )
+ {
+ HttpResponseReceivedL( aKey, aResultCode );
+ if ( aResultCode == EHttpOk )
+ {
+ TInt transferid = iTransferController->Transfer( aKey );
+ if ( transferid > KErrNotFound )
+ {
+ TInt
+ len =
+ iTransferController->iFileTransfers[transferid]->TransferTotal( );
+ iTransferController->iFileTransfers[transferid]->SetTransferLength( len );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::NewTransactionL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpContentDirectory::NewTransactionL(
+ const TDesC8& aMethod, const TDesC8& aUri,
+ const TInetAddr& aSender, CUpnpHttpServerTransaction*& aResultTrans )
+ {
+ iDlnaFilter->NewTransactionL( aMethod, aUri, aSender, aResultTrans );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::HttpEventLD
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::HttpEventLD( CUpnpHttpMessage* aMessage )
+ {
+ if ( aMessage )
+ {
+ CleanupStack::PushL( aMessage );
+ if( aMessage->Type() >= ETransferStart )
+ {
+ HttpTransferEventReceivedL( *aMessage );
+ }
+ else
+ {
+ UnknownHttpEventReceivedL( *aMessage );
+ }
+ CleanupStack::PopAndDestroy( aMessage );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpContentDirectory::AddressChangeL
+// -----------------------------------------------------------------------------
+//
+void CUpnpContentDirectory::AddressChangeL()
+ {
+ iHttpServerSession->Stop();
+ iHttpServerSession->StartL();
+ }
+
+//End of File