sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: #include "DATASTOR.H"
sl@0: #include "APMPAN.H"
sl@0: 
sl@0: const TUid KOpenServiceUid = { 0x10208DCA };
sl@0: 
sl@0: const TInt KAppMappingGranularity=1;
sl@0: //
sl@0: //	class TMappingDataTypeToApp
sl@0: //
sl@0: 
sl@0: EXPORT_C TMappingDataTypeToApp::TMappingDataTypeToApp()
sl@0: 	:iDataType(TDataType(_L8(""))), iServiceUid(KOpenServiceUid)
sl@0: 	{
sl@0: 	iAppUid.iUid=0;
sl@0: 	}
sl@0: 
sl@0: EXPORT_C TMappingDataTypeToApp::TMappingDataTypeToApp(const TDataType& aDataType,
sl@0: 	TDataTypePriority aPriority, TUid aAppUid)
sl@0: 	:iDataType(aDataType),
sl@0: 	iPriority(aPriority),
sl@0: 	iAppUid(aAppUid),
sl@0: 	iServiceUid(KOpenServiceUid)
sl@0: 	{
sl@0: 	}
sl@0: 	
sl@0: EXPORT_C TMappingDataTypeToApp::TMappingDataTypeToApp(const TDataType& aDataType,
sl@0: 	TDataTypePriority aPriority, TUid aAppUid, TUid aServiceUid)
sl@0: 	:iDataType(aDataType),
sl@0: 	iPriority(aPriority),
sl@0: 	iAppUid(aAppUid),
sl@0: 	iServiceUid(aServiceUid)
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void TMappingDataTypeToApp::InternalizeL(RReadStream& aStream)
sl@0: 	{
sl@0: 	aStream >> iDataType;
sl@0: 	iPriority=aStream.ReadInt32L();
sl@0: 	iAppUid.iUid=aStream.ReadInt32L();
sl@0: 	iServiceUid.iUid=aStream.ReadInt32L();
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void TMappingDataTypeToApp::ExternalizeL(RWriteStream& aStream) const
sl@0: 	{
sl@0: 	aStream << iDataType;
sl@0: 	aStream.WriteInt32L(iPriority);
sl@0: 	aStream.WriteInt32L(iAppUid.iUid);
sl@0: 	aStream.WriteInt32L(iServiceUid.iUid);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: //
sl@0: // class CTypeStoreManager
sl@0: //
sl@0: 
sl@0: EXPORT_C void CTypeStoreManager::InternalizeL(RReadStream& aStream)
sl@0: /** Internalises the array of data type mappings from a read stream.
sl@0: 
sl@0: @param aStream Stream from which the data type mappings are internalised. */
sl@0: 	{
sl@0: 	aStream >> iAppMappings;
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CTypeStoreManager::ExternalizeL(RWriteStream& aStream) const
sl@0: /** Externalises the data type mappings to a write stream.
sl@0: 
sl@0: @param aStream Stream to which the data type mappings should be externalised. */
sl@0: 	{
sl@0: 	aStream << iAppMappings;
sl@0: 	}
sl@0: 
sl@0: EXPORT_C CTypeStoreManager* CTypeStoreManager::NewL(RFs& aFs)
sl@0: /** Constructs a CTypeStoreManager object.
sl@0: 
sl@0: @param aFs A session with the file server.
sl@0: @return The newly created CTypeStoreManager object. */
sl@0: 	{
sl@0: 	CTypeStoreManager* self = new(ELeave) CTypeStoreManager(aFs);
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL();
sl@0: 	CleanupStack::Pop(self);
sl@0: 	return (self);
sl@0: 	}
sl@0: 	
sl@0: void CTypeStoreManager::ConstructL()
sl@0: 	{
sl@0: 	TChar sysDrive = RFs::GetSystemDriveChar();
sl@0: 	TInt maxSizeOfFileName = KIniFileName().Length() + 1;
sl@0: 	iIniFileName.CreateL(maxSizeOfFileName);
sl@0: 	iIniFileName.Append(sysDrive);
sl@0: 	iIniFileName.Append(KIniFileName());
sl@0: 	}
sl@0: CTypeStoreManager::CTypeStoreManager(RFs& aFs)
sl@0: 	: iAppMappings(KAppMappingGranularity),
sl@0: 	iFs(aFs)
sl@0: 	{
sl@0: 	__ASSERT_ALWAYS(RProcess().SecureId()==0x10003a3f, Panic(EPanicNotBeingUsedFromWithinApparcServerProcess));
sl@0: 	}
sl@0: 
sl@0: EXPORT_C CTypeStoreManager::~CTypeStoreManager()
sl@0: /** Destructor. */
sl@0: 	{
sl@0: 	iIniFileName.Close();
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CTypeStoreManager::StoreL()
sl@0: /** Stores the data type mappings to the data store ini file 
sl@0: (c:\\System\\Data\\Dtstor.ini), creating a new ini file if it does 
sl@0: not already exist. */
sl@0: 	{
sl@0: 	CDictionaryStore* iniFile=OpenIniFileLC();
sl@0: 	iniFile->RemoveL(KUidDatastorSettings);
sl@0: 	RDictionaryWriteStream outStream;
sl@0: 	outStream.AssignLC(*iniFile,KUidDatastorSettings);
sl@0: 	outStream << *this;
sl@0: 	outStream.CommitL();
sl@0:     CleanupStack::PopAndDestroy();
sl@0:     iniFile->CommitL();
sl@0:     CleanupStack::PopAndDestroy();	// inifile
sl@0: 	}
sl@0: 	 
sl@0: EXPORT_C void CTypeStoreManager::RestoreL()
sl@0: /** Restores the data type mappings from the data store ini file. */
sl@0: 	{
sl@0: 	CDictionaryStore* iniFile=OpenIniFileLC();
sl@0: 	RDictionaryReadStream inStream;
sl@0: 	inStream.OpenLC(*iniFile,KUidDatastorSettings);
sl@0: 	inStream >> *this;
sl@0:     CleanupStack::PopAndDestroy(2); // inStream * iniFile
sl@0: 	}
sl@0: 
sl@0: /** Changes an existing data type mapping, or adds a new one.
sl@0: 
sl@0: If the data type does not exist in the store, the new mapping is appended. 
sl@0: If the data type does exist, its mapping is replaced.
sl@0: 
sl@0: The service is considered to be the KOpenServiceUid service.
sl@0: 
sl@0: @param aDataType A new or existing data type.
sl@0: @param aPriority The priority with which the application handles the data type.
sl@0: @param aUid The UID of the application to associate with the data type. 
sl@0: */
sl@0: EXPORT_C void CTypeStoreManager::InsertDataMappingL(const TDataType& aDataType, TDataTypePriority aPriority, TUid aUid)
sl@0: 	{
sl@0: 	InsertDataMappingL(aDataType, aPriority, aUid, KOpenServiceUid);
sl@0: 	}
sl@0: 	
sl@0: /** Changes an existing data type mapping, or adds a new one.
sl@0: 
sl@0: If the data type does not exist in the store, the new mapping is appended. 
sl@0: If the data type does exist, its mapping is replaced.
sl@0: 
sl@0: @param aDataType A new or existing data type.
sl@0: @param aPriority The priority with which the application handles the data type.
sl@0: @param aUid The UID of the application to associate with the data type. 
sl@0: @param aServiceUid The UID of the service. 
sl@0: */
sl@0: EXPORT_C void CTypeStoreManager::InsertDataMappingL(const TDataType& aDataType, 
sl@0: 	TDataTypePriority aPriority, TUid aUid, TUid aServiceUid)
sl@0: 	{
sl@0: 	TInt i = FindDataMapping(aDataType, aServiceUid);
sl@0: 	if ( i == KErrNotFound )
sl@0: 		iAppMappings.AppendL( TMappingDataTypeToApp( aDataType, aPriority, aUid, aServiceUid ) );
sl@0: 	else
sl@0: 		{
sl@0: 		TMappingDataTypeToApp& mapping = iAppMappings[i];
sl@0: 		mapping.iDataType=aDataType;
sl@0: 		mapping.iPriority=aPriority;
sl@0: 		mapping.iAppUid=aUid;
sl@0: 		mapping.iServiceUid=aServiceUid;
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /** Changes an existing data type mapping, or adds a new one.
sl@0: If the data type does not exist in the store, or if it does and its existing priority 
sl@0: is less than aPriority, the new mapping is added to the store, or replaces the existing one. 
sl@0: Otherwise, no change is made.
sl@0: 
sl@0: The service is considered to be the KOpenServiceUid service.
sl@0: 
sl@0: @param aDataType A new or existing data type.
sl@0: @param aPriority The priority with which the application handles the data type.
sl@0: @param aUid The UID of the application to associate with the data type.
sl@0: @return ETrue if the new mapping was added or an existing mapping replaced, EFalse if no 
sl@0: change was made.
sl@0: */
sl@0: EXPORT_C TBool CTypeStoreManager::InsertIfHigherL(const TDataType& aDataType, TDataTypePriority aPriority, TUid aUid)
sl@0: 	{
sl@0: 	return InsertIfHigherL(aDataType, aPriority, aUid, KOpenServiceUid);
sl@0: 	}
sl@0: 	
sl@0: /** Changes an existing data type mapping, or adds a new one.
sl@0: If the data type does not exist in the store, or if it does and its existing priority 
sl@0: is less than aPriority, the new mapping is added to the store, or replaces the existing one. 
sl@0: Otherwise, no change is made.
sl@0: 
sl@0: @param aDataType A new or existing data type.
sl@0: @param aPriority The priority with which the application handles the data type.
sl@0: @param aUid The UID of the application to associate with the data type.
sl@0: @param aServiceUid The UID of the service. 
sl@0: @return ETrue if the new mapping was added or an existing mapping replaced, EFalse if no 
sl@0: change was made.
sl@0: */
sl@0: EXPORT_C TBool CTypeStoreManager::InsertIfHigherL(const TDataType& aDataType, 
sl@0: 	TDataTypePriority aPriority, TUid aUid, TUid aServiceUid)
sl@0: 	{
sl@0: 	TInt i = FindDataMapping( aDataType, aServiceUid );
sl@0: 	if ( i == KErrNotFound || iAppMappings[i].iPriority < aPriority )
sl@0: 		{
sl@0: 		InsertDataMappingL( aDataType, aPriority, aUid, aServiceUid );
sl@0: 		return ETrue;
sl@0: 		}
sl@0: 	else
sl@0: 		return EFalse;
sl@0: 	}
sl@0: 
sl@0: /** Removes an existing data type mapping from the store.
sl@0: 
sl@0: The service is considered to be the KOpenServiceUid service.
sl@0: 
sl@0: @param aDataType Data type whose mapping should be removed.
sl@0: @panic USER 0 The specified data type cannot be found. Debug builds only.
sl@0: */
sl@0: EXPORT_C void CTypeStoreManager::DeleteDataMapping(const TDataType& aDataType)
sl@0: 	{
sl@0: 	DeleteDataMapping(aDataType, KOpenServiceUid);
sl@0: 	}
sl@0: 
sl@0: /** Removes an existing data type mapping from the store.
sl@0: 
sl@0: @param aDataType Data type whose mapping should be removed.
sl@0: @param aServiceUid The UID of the service. 
sl@0: @panic USER 0 The specified data type cannot be found. Debug builds only.
sl@0: */	
sl@0: EXPORT_C void CTypeStoreManager::DeleteDataMapping(const TDataType& aDataType, 
sl@0: 	TUid aServiceUid)
sl@0: 	{
sl@0: 	TInt i=FindDataMapping(aDataType, aServiceUid);
sl@0: 	__ASSERT_DEBUG(i!=KErrNotFound,User::Invariant());
sl@0: 	iAppMappings.Delete(i);
sl@0: 	}
sl@0: 
sl@0: /** Gets the UID of the application mapped to the specified data type.
sl@0: 
sl@0: The service is considered to be the KOpenServiceUid service.
sl@0: 
sl@0: @param aDataType The data type.
sl@0: @param aUid On return, the UID of the application associated with the 
sl@0: data type, or KNullUid if the data type is not found. 
sl@0: */
sl@0: EXPORT_C void CTypeStoreManager::GetAppByDataType(const TDataType& aDataType, TUid& aUid) const
sl@0: 	{
sl@0: 	GetAppByDataType(aDataType, KOpenServiceUid, aUid);
sl@0: 	}
sl@0: 	
sl@0: /** Gets the UID of the application mapped to the specified data type.
sl@0: 
sl@0: The service is considered to be the KOpenServiceUid service.
sl@0: 
sl@0: @param aDataType The data type.
sl@0: @param aServiceUid The UID of the service.
sl@0: @param aUid On return, the UID of the application associated with the 
sl@0: data type, or KNullUid if the data type is not found. 
sl@0: */
sl@0: EXPORT_C void CTypeStoreManager::GetAppByDataType(const TDataType& aDataType, 
sl@0: 	TUid aServiceUid, TUid& aUid) const
sl@0: 	{
sl@0: 	TInt i=FindDataMapping(aDataType, aServiceUid);
sl@0: 	aUid=(i==KErrNotFound? KNullUid : iAppMappings[i].iAppUid);
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CTypeStoreManager::GetDataTypesByAppL(TUid aUid, CArrayFix<TDataType>* aTypeArray) const
sl@0: /** Populates an array with all the data types supported by the specified application.
sl@0: 
sl@0: If the specified UID is zero, the array is populated with all the data types found in 
sl@0: the store.
sl@0: 
sl@0: @param aUid An application UID.
sl@0: @param aTypeArray An empty array. On return, contains all data types supported by the 
sl@0: application.
sl@0: @panic APMIME 5 The array is NULL.
sl@0: @panic APMIME 6 The array passed to the function is not empty. Debug builds only. */
sl@0: 	{
sl@0: 	__ASSERT_ALWAYS(aTypeArray,Panic(EInvalidArgument));
sl@0: 	__ASSERT_DEBUG(!aTypeArray->Count(),Panic(EArrayNotEmpty));
sl@0: 	TInt count=iAppMappings.Count();
sl@0: 	for (TInt i=0; i<count; i++)
sl@0: 		{
sl@0: 		if ((iAppMappings[i].iAppUid==aUid || aUid.iUid==0) &&
sl@0: 			(iAppMappings[i].iServiceUid == KOpenServiceUid))
sl@0: 			{
sl@0: 			aTypeArray->AppendL(iAppMappings[i].iDataType);
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: EXPORT_C const CArrayFixFlat<TMappingDataTypeToApp>& CTypeStoreManager::MappingArray() const
sl@0: /** Returns the array of data type mappings.
sl@0: 
sl@0: @return The array of data type mappings. */
sl@0: 	{
sl@0: 	return iAppMappings;
sl@0: 	}
sl@0: 
sl@0: TInt CTypeStoreManager::FindDataMapping(const TDataType& aDataType, 
sl@0: 	const TUid& aServiceUid) const
sl@0: 	{
sl@0: 	TInt count=iAppMappings.Count();
sl@0: 	for (TInt i=0; i<count; i++)
sl@0: 		{
sl@0: 		// Match the pattern at the start of the mime type
sl@0: 		if ((iAppMappings[i].iDataType.Des8().Match(aDataType.Des8())==0) &&
sl@0: 			(iAppMappings[i].iServiceUid == aServiceUid))
sl@0: 			{
sl@0: 			return i;
sl@0: 			}
sl@0: 		}
sl@0: 	return KErrNotFound;
sl@0: 	}
sl@0: 
sl@0: CDictionaryStore* CTypeStoreManager::OpenIniFileLC() const
sl@0: //	Open dtstor's ini file -  will create a new one if it doesn't exist or is corrupted
sl@0: 	{
sl@0: 	const TPtrC iniFileName(IniFileName());
sl@0: 	TInt err=iFs.MkDirAll(iniFileName);
sl@0: 	if(err!=KErrAlreadyExists)
sl@0: 		{
sl@0: 		User::LeaveIfError(err);
sl@0: 		}
sl@0: 	CDictionaryStore* iniFile=NULL;
sl@0: 	TRAP(err,iniFile=CDictionaryFileStore::OpenL(iFs,iniFileName,KUidDatastor));
sl@0: 	if (err==KErrNone)
sl@0: 		{
sl@0: 		CleanupStack::PushL(iniFile);
sl@0: 		}
sl@0: 	else if (err==KErrEof || err==KErrCorrupt)
sl@0: 		{
sl@0: 		User::LeaveIfError(iFs.Delete(iniFileName));
sl@0: 		iniFile=CDictionaryFileStore::OpenLC(iFs,iniFileName,KUidDatastor);
sl@0: 		err=KErrNone;
sl@0: 		}
sl@0: 	User::LeaveIfError(err);
sl@0: 	return iniFile;
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CTypeStoreManager::InsertAndStoreDataMappingL(const TDataType& aDataType, 
sl@0: 	TDataTypePriority aPriority, TUid aUid)
sl@0: 	{
sl@0: 	InsertAndStoreDataMappingL(aDataType, aPriority, aUid, KOpenServiceUid);
sl@0: 	}
sl@0: 
sl@0: EXPORT_C void CTypeStoreManager::InsertAndStoreDataMappingL(const TDataType& aDataType, 
sl@0: 	TDataTypePriority aPriority, TUid aUid, TUid aServiceUid)
sl@0: 	{
sl@0: 	InsertDataMappingL(aDataType, aPriority, aUid, aServiceUid);
sl@0: 	TRAPD(ret,StoreL());
sl@0: 	if(ret!=KErrNone)
sl@0: 		{
sl@0: 		DeleteDataMapping(aDataType, aServiceUid);	
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: EXPORT_C TBool CTypeStoreManager::InsertAndStoreIfHigherL(const TDataType& aDataType, TDataTypePriority aPriority, TUid aUid)
sl@0: 	{
sl@0: 	return InsertAndStoreIfHigherL(aDataType, aPriority, aUid, KOpenServiceUid);
sl@0: 	}
sl@0: 
sl@0: EXPORT_C TBool CTypeStoreManager::InsertAndStoreIfHigherL(const TDataType& aDataType, 
sl@0: 	TDataTypePriority aPriority, TUid aUid, TUid aServiceUid)
sl@0: 	{
sl@0: 	TInt i = FindDataMapping( aDataType, aServiceUid );
sl@0: 	if ( i == KErrNotFound || iAppMappings[i].iPriority < aPriority )
sl@0: 		{
sl@0: 		InsertAndStoreDataMappingL( aDataType, aPriority, aUid, aServiceUid );
sl@0: 		return ETrue;
sl@0: 		}
sl@0: 	else
sl@0: 		return EFalse;
sl@0: 	}	
sl@0: 
sl@0: EXPORT_C void CTypeStoreManager::DeleteAndStoreDataMappingL(const TDataType& aDataType)
sl@0: 	{
sl@0: 	DeleteAndStoreDataMappingL(aDataType, KOpenServiceUid);
sl@0: 	}	
sl@0: 
sl@0: EXPORT_C void CTypeStoreManager::DeleteAndStoreDataMappingL(const TDataType& aDataType, 
sl@0: 	TUid aServiceUid)
sl@0: 	{
sl@0: 	TInt i=FindDataMapping(aDataType, aServiceUid);
sl@0: 	__ASSERT_DEBUG(i!=KErrNotFound,User::Invariant());
sl@0: 	TMappingDataTypeToApp mapping (iAppMappings[i].iDataType,iAppMappings[i].iPriority,iAppMappings[i].iAppUid,iAppMappings[i].iServiceUid);
sl@0: 	iAppMappings.Delete(i);
sl@0: 	TRAPD(ret,StoreL());
sl@0: 	if(ret!=KErrNone)
sl@0: 		{
sl@0: 		iAppMappings.InsertL(i,mapping);	
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: //Removes data mappings related to aAppUid
sl@0: //Returns modification status of service registry
sl@0: EXPORT_C TBool CTypeStoreManager::DeleteApplicationDataMappings(const TUid aAppUid)
sl@0:     {
sl@0:     TInt count=iAppMappings.Count();
sl@0:     TInt index=0;
sl@0:     TBool modified=EFalse;
sl@0: 
sl@0:     //goes through service registry to find data mappings related to aAppUid
sl@0:     while(index<count)
sl@0:         {
sl@0:         if (iAppMappings[index].iAppUid==aAppUid) 
sl@0:             {
sl@0:              iAppMappings.Delete(index);
sl@0:              //As data mapping is removed from service registry,  reduce the count
sl@0:              count--;
sl@0:              modified=ETrue;
sl@0:              }
sl@0:         else
sl@0:             index++;
sl@0:         }
sl@0:     return(modified);
sl@0:     }