messagingfw/biomsgfw/BDBSRC/BIODB.CPP
changeset 0 8e480a14352b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/biomsgfw/BDBSRC/BIODB.CPP	Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,1046 @@
+// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// BIODB.CPP
+//
+
+#include "BIODB.H"
+#include "BDBPAN.H"
+#include "cbifentry.h"
+
+#include <s32file.h>		// CFileStore
+#include <bautils.h>
+
+#include <basched.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS 
+#include <bifchangeobserver.h>
+#endif
+
+//
+// Globals & Constants
+//
+// Old search paths are /system/bif
+// New (platsec) search paths are /resource/messaging/bif
+
+_LIT(KSecureBifPath, "\\resource\\messaging\\Bif\\");     
+_LIT(KSecureBifSearchString, "?:\\resource\\messaging\\Bif\\");
+
+_LIT(KLanguageFileExt, ".r");
+_LIT(KDotRsc, ".rsc");
+
+// 30 seconds between attempts to scan drives if we get completed with an error,
+const TInt KBifRetryTimeOut=30000000;
+// Maximam attempts to scan drives if we get completed with an error,
+const TInt KMaxRetries = 1;
+
+// default size of array of entries in a bif directory
+const TInt KBifEntryArrayDefaultSize=5;
+const TInt KMinFileNameLength = 5;
+
+/*
+ *	CBifChangeObserver
+ */
+ 
+/** Allocates and constructs a new BIF change observer.
+
+@param	aObserver 
+Callback interface to notify when a change occurs
+
+@param	afileSystem 
+Connected file system handle
+
+@return 
+New BIF change observer 
+*/
+EXPORT_C CBifChangeObserver* CBifChangeObserver::NewL(MBifChangeObserver& aObserver, RFs& aFs)
+	{
+	CBifChangeObserver* self=new(ELeave) CBifChangeObserver(aObserver, aFs);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CBifChangeObserver::ConstructL()
+	{
+	iBioDB = CBIODatabase::NewL(iFs);
+	User::LeaveIfError(iTimer.CreateLocal());
+	}
+
+CBifChangeObserver::CBifChangeObserver(MBifChangeObserver& aObserver, RFs& aFs)
+: CActive(EPriorityStandard), iChangeObserver(aObserver), iFs(aFs)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+/** Destructor. */
+CBifChangeObserver::~CBifChangeObserver()
+	{
+	Cancel();
+	iTimer.Close();
+	delete iBioDB;
+	iEntries.ResetAndDestroy();
+	}
+
+/** Starts the object watching for changes.
+
+To stop the object, simply delete it.
+*/
+EXPORT_C void CBifChangeObserver::Start()
+	{
+	// just complete myself so that RunL builds the list of entries and asks the file
+	// sever to notify us of changes.
+	TRequestStatus *status=&iStatus;
+	User::RequestComplete(status,KErrNone);
+	SetActive();
+	}
+
+void CBifChangeObserver::RunL()
+	{
+	TInt err=KErrNone;
+	if(iStatus.Int()==KErrNone)
+		{
+		// ignore the error
+		TRAP(err, DoRunL());
+		}
+#ifdef _DEBUG
+ 	else
+		{
+		// I don't expect to get here, it means that RFs::NotifyChangeL has completed
+		// this class with an error, which means we would loop rather quickly.
+		User::Invariant();
+		}
+#endif
+	
+	if((iStatus.Int() != KErrNone || err != KErrNone) && iRetryCount < KMaxRetries)
+		{
+		iTimer.After(iStatus,KBifRetryTimeOut);
+		iRetryCount ++;
+		SetActive();
+		}
+	else
+		{
+		WaitForFileNotification();	
+		iRetryCount = 0;
+		}
+	}
+
+void CBifChangeObserver::DoRunL()
+    {
+    TBool notify=EFalse;
+	// build a list of all the TEntrys in KBifPath on all drives/
+	RPointerArray<CBifEntry> entryList(KBifEntryArrayDefaultSize);
+	TCleanupItem cleanup(CleanupBifArray, &entryList);
+	CleanupStack::PushL(cleanup);
+	
+	TFindFile fileFinder(iFs);     
+	CDir *dir=NULL;     
+	// Scan this folder from V1.5 onwards
+	TInt err = fileFinder.FindWildByDir(_L("*"),KSecureBifPath,dir);
+	while(err==KErrNone)
+		{
+		CleanupStack::PushL(dir);
+		TInt count=dir->Count();
+		while(count--)
+			{
+			CBifEntry* bifEntry = CBifEntry::NewLC((*dir)[count]);
+			entryList.AppendL(bifEntry);
+			CleanupStack::Pop(bifEntry);
+			}
+		CleanupStack::PopAndDestroy(dir);
+		err=fileFinder.Find();
+		} 
+	
+	if (err != KErrNotFound)
+		User::LeaveIfError(err);
+
+	// Check to see if iEntries matches entryList
+	if(iEntries.Count()!=0) // iEntries is empty the first time in so don't notify anyone.
+		{
+		// check to see if the two lists of entries are the same
+		if(iEntries.Count()!=entryList.Count())
+			notify=ETrue;  // not the same if one is larger than the other
+		else
+			{
+			TInt count=entryList.Count();
+			while(count-- && notify==EFalse)
+				{
+				TInt index;
+				TInt found=FindEntry(*(entryList)[count],iEntries,index);
+				if(found==KErrNone)
+					{
+					delete (iEntries)[index];
+					iEntries.Remove(index);
+					}
+				else
+					notify=ETrue; // not the same if entryList contains something not in iEntries
+				}
+			if(iEntries.Count()!=0)
+				notify=ETrue; // not the same if iEntries contains something not in entryList;
+			}
+		}
+		
+	// replace old iEntries with new entryList
+	CleanupStack::Pop(&entryList);
+	iEntries.ResetAndDestroy();
+	iEntries=entryList;
+	
+	// notify observers if iEntries was != entryList;
+	if(notify!=EFalse) 
+		NotifyObserverL();
+	}
+
+TInt CBifChangeObserver::FindEntry(const CBifEntry& aBifEntry, const RPointerArray<CBifEntry>& aEntries, TInt& aIndex) const
+	{
+	aIndex = aEntries.Count();
+
+	while (aIndex--)
+		{
+		if ( aBifEntry == *aEntries[aIndex] )
+			{
+			return KErrNone;
+			}
+		}
+
+	return KErrNotFound;
+	}
+
+void CBifChangeObserver::WaitForFileNotification()
+	{
+	// Observe this folder from V1.5 onwards
+	iFs.NotifyChange(ENotifyAll, iStatus, KSecureBifSearchString);
+	SetActive();
+	}
+
+void CBifChangeObserver::DoCancel()
+	{
+    iTimer.Cancel();
+	
+	iFs.NotifyChangeCancel(iStatus);	// Cancel only the specific
+										// request made by this observer
+	}
+
+TBool CBifChangeObserver::CompareReaders(const CBioInfoFileReader& aReader1, const CBioInfoFileReader& aReader2) const
+	{
+	TBool retVal = aReader1.BifEntry() == aReader2.BifEntry();
+
+	if (retVal)
+		{
+		//Compare the readers
+		retVal = 
+			   (aReader1.MessageParserName().Compare(aReader2.MessageParserName()) == 0)
+			&& (aReader1.MessageAppCtrlName().Compare(aReader2.MessageAppCtrlName()) == 0)
+			&& (aReader1.MessageAppUid() == aReader2.MessageAppUid())
+			&& (aReader1.GeneralData1() == aReader2.GeneralData1())
+			&& (aReader1.GeneralData2() == aReader2.GeneralData2())
+			&& (aReader1.GeneralData3() == aReader2.GeneralData3())
+			&& (aReader1.IconsFilename().Compare(aReader2.IconsFilename()) == 0)
+			&& (aReader1.Description().Compare(aReader2.Description()) == 0);
+
+		//To Do: Should aReader1.IdsLC() and aReader2.IdsLC() be compared?
+		}
+
+	return retVal;
+	}
+
+void CBifChangeObserver::NotifyObserverL()
+	{
+	CArrayFixFlat<TUid>* addedBifs = new (ELeave) CArrayFixFlat<TUid>(1);
+	CleanupStack::PushL(addedBifs);
+
+	CArrayFixFlat<TUid>* changedBifs = new (ELeave) CArrayFixFlat<TUid>(1);
+	CleanupStack::PushL(changedBifs);
+
+	CArrayFixFlat<TUid>* deletedBifs = new (ELeave) CArrayFixFlat<TUid>(1);
+	CleanupStack::PushL(deletedBifs);
+
+	// Figure out what kind of change really happened here
+	CBIODatabase* newBioDB = CBIODatabase::NewL(iFs);
+	CleanupStack::PushL(newBioDB);
+
+
+	TInt err = KErrNone;
+
+	TUid uid;
+	TInt index = 0;
+	TKeyArrayFix key(0, ECmpTInt);
+	TInt count = newBioDB->BIOCount();
+	
+	while (count--)
+		{
+		newBioDB->GetBioMsgID(count, uid);
+		TRAP(err, iBioDB->GetBioIndexWithMsgIDL(uid, index));
+		
+		if (err)
+			{
+			//BIF in New BIO DB not found in Old BIO DB
+			addedBifs->InsertIsqL(uid, key);
+			}
+		else
+			{
+			
+			//BIF in both BIO DBs, therefore check to see if the files have changed
+			if  (!CompareReaders(iBioDB->BifReader(index), newBioDB->BifReader(count)))
+				{
+				changedBifs->InsertIsqL(uid, key);
+				}
+
+			//Remove this BIF from the Old BIO DB for efficiency in the next while loop.
+			iBioDB->RemoveBifL(index);
+			}
+		}
+
+	count = iBioDB->BIOCount();
+
+	while (count--)
+		{
+		//All remaining members of iBioDB are deleted BIFs
+		iBioDB->GetBioMsgID(count, uid);
+		deletedBifs->InsertIsqL(uid, key);
+		}
+
+	count = addedBifs->Count();
+
+	while (count--)
+		{
+		iChangeObserver.HandleBifChangeL(MBifChangeObserver::EBifAdded, addedBifs->At(count));
+		}
+
+	count = deletedBifs->Count();
+
+	while (count--)
+		{
+		iChangeObserver.HandleBifChangeL(MBifChangeObserver::EBifDeleted, deletedBifs->At(count));
+		}
+
+	count = changedBifs->Count();
+
+	while (count--)
+		{
+		iChangeObserver.HandleBifChangeL(MBifChangeObserver::EBifChanged, changedBifs->At(count));
+		}
+
+	// update the list we're holding onto
+	delete iBioDB;
+	iBioDB = newBioDB;
+	
+	CleanupStack::Pop(); //newBioDB
+  	CleanupStack::PopAndDestroy(3); //arrays
+	}
+	
+void CBifChangeObserver::CleanupBifArray( TAny* aBifArray )
+	{
+	RPointerArray<CBifEntry>* bifArray = static_cast<RPointerArray<CBifEntry>*>(aBifArray);
+	bifArray->ResetAndDestroy();
+	}
+
+//
+// CBIODatabase
+//
+
+//
+// Construction
+//	protected
+//
+CBIODatabase::CBIODatabase()
+	{
+	// We're a CBase derived class so we can assume that our data members are intialized to 0
+	}
+
+//
+EXPORT_C CBIODatabase* CBIODatabase::NewLC(RFs& afileSystem)
+/** Allocates and constructs a new BIO database object, leaving the object on the 
+cleanup stack.
+
+It initialises the object from all the BIF files in the system\\bif directory.
+
+@param afileSystem Connected file system handle
+@return New BIO database object */
+	{
+	CBIODatabase* self=new(ELeave) CBIODatabase();
+	CleanupStack::PushL(self);
+	self->ConstructL(afileSystem);
+	return self;
+	}
+
+//
+EXPORT_C CBIODatabase* CBIODatabase::NewL(RFs& afileSystem)
+/** Allocates and constructs a new BIO database object.
+
+It initialises the object from all the BIF files in the system\\bif directory.
+
+@param afileSystem Connected file system handle
+@return New BIO database object */
+	{
+	CBIODatabase* self=CBIODatabase::NewLC(afileSystem);
+	CleanupStack::Pop();		// self
+	return self;
+	}
+
+//
+// Construction/destruction
+void CBIODatabase::ConstructL(RFs& afileSystem)
+	{
+	// put the real construction here
+	iBifReaders= new (ELeave) CArrayPtrFlat<CBioInfoFileReader>(10);
+	AddAllBifsL(afileSystem);
+	}
+
+//
+// Construction/destruction
+EXPORT_C CBIODatabase::~CBIODatabase()
+/** Destructor. */
+	{
+	if (iBifReaders)
+		iBifReaders->ResetAndDestroy();
+	delete iBifReaders;
+	}
+
+
+//
+EXPORT_C TInt CBIODatabase::BIOCount()
+/** Gets the number of BIF files.
+
+@return Number of BIF files */
+	{
+	return iBifReaders->Count();
+	}
+
+//
+EXPORT_C void CBIODatabase::AddAllBifsL(RFs& afileSystem)
+/** Initialises the object from all the BIF files in the system\\bif or resource\\messaging\\bif directory.
+
+@param afileSystem Connected file system handle */
+	{
+	// Walk through all the BIF Files, adding each one
+	// to the iBifReaders array
+	TDriveList drvList;
+
+	// User::LeaveIfError(afileSystem.Connect());
+	User::LeaveIfError(afileSystem.DriveList(drvList));
+
+	for (TInt n=0 ; n<KMaxDrives ; ++n)
+		{
+		if (drvList[n]!=0)
+			{
+			TDriveInfo driveinfo;
+			TInt ret=afileSystem.Drive(driveinfo,n);
+			if ((ret==KErrNone) && (driveinfo.iType!=EMediaNotPresent) && (driveinfo.iType!=EMediaRemote) 
+												&& (!(driveinfo.iMediaAtt & KMediaAttLocked)) )
+				{
+				TDriveUnit driveUnit(n);
+				TPath fullPath; // Length must hold x:\resource\messaging\bif\ 
+				fullPath.FillZ();
+				fullPath = driveUnit.Name();
+				fullPath += KSecureBifPath;
+
+				if (afileSystem.SetSessionPath(fullPath) == KErrNone)
+					{
+					CDir* entryList = NULL;
+
+					// Walk through all the BIF Files, adding each one
+
+ 					ret = afileSystem.GetDir( fullPath,
+											  KEntryAttNormal|KEntryAttAllowUid,
+											  ESortByDate,
+											  entryList );
+					if (ret==KErrNone)
+						{
+						CleanupStack::PushL(entryList);
+						TInt cnt = entryList->Count();
+						for (TInt i = 0; i < cnt; ++i)
+							{
+							// get the file
+							TEntry entry = (*entryList)[i];
+							
+								TFileName fileName(fullPath);
+								fileName.Append(entry.iName);
+
+								// Remove localization index from the filename and replace it with "rsc"
+								// example, abc.r05 -> abc.rsc
+								TInt extLength(0);
+								if ( IsLanguageFileL(entry.iName, extLength) && (fileName.Length() >= KMinFileNameLength) )
+									{
+									fileName.Replace(fileName.Length() - extLength, extLength, KDotRsc);
+									}
+								// Use the file most appropriate to the current language
+								BaflUtils::NearestLanguageFile(afileSystem,fileName);
+
+								// Load the bif file
+								CBioInfoFileReader* bifReader = NULL;
+								TRAPD(error, bifReader=CBioInfoFileReader::NewL(afileSystem,fileName));
+								if (!error)
+									{
+									AddBifL(bifReader);									
+									}
+								else
+									{
+									// Ignore corrupt files
+									delete bifReader;
+
+									if (error != KErrCorrupt && error != KErrExtended && error != KErrNotFound)
+										{
+										User::LeaveIfError(error);
+										}
+									}
+							}
+						CleanupStack::PopAndDestroy(entryList); 
+						}
+					}
+				}
+				if (!(ret==KErrNone || 
+					  ret==KErrPathNotFound || 
+					  ret==KErrNotFound || 
+					  ret==KErrNotReady  || 
+					  ret==KErrCorrupt ||
+					  ret==KErrInUse ||
+					  ret==KErrLocked || 
+					  ret==KErrNotSupported))
+					{
+					User::LeaveIfError(ret);
+					}
+			}
+		}
+
+	}
+
+// Is the file a language file
+TBool CBIODatabase::IsLanguageFileL(const TDesC& aFileName, TInt& aExtLength) const
+	{
+	// Check the extension to see if it's a language file. we
+ 	// have to assume ".rXXX" is a resource file
+ 	TParse parse;
+ 	User::LeaveIfError(parse.Set(aFileName, NULL, NULL));
+	aExtLength=parse.Ext().Length();
+ 	return parse.Ext().Left(2).CompareF(KLanguageFileExt) == 0;
+	}
+
+//
+// This will add the Parser
+// Error returned
+EXPORT_C void CBIODatabase::AddBifL(CBioInfoFileReader* aBifReader)
+/** Adds a specified BIF.
+
+@param abifReader BIF file to add */
+	{
+	// This will manage the array - if a conflicting message
+	// id comes in, it will take the one with higher confidence
+	// or if a tie, the first one in
+	CleanupStack::PushL(aBifReader);
+
+	// Check if we have a reader with this message id
+	TInt index = 0;
+    
+	TRAPD(leaveValue,GetBioIndexWithMsgIDL(aBifReader->MessageTypeUid(), index));
+    
+	// We haven't read a BIF with the msgID in yet
+	if (leaveValue == KErrNotFound)
+		{
+		// just add it
+		iBifReaders->AppendL(aBifReader);
+		CleanupStack::Pop(); // aBifReader
+		}
+	else
+		{
+		CApaDataRecognizerType::TRecognitionConfidence newBifConf, oldBifConf;
+
+		// If we do have a match, take the one with higher confidence
+		const CArrayFix<TBioMsgId>* msgIDArray = BIOEntryLC(index);
+		oldBifConf = (*msgIDArray)[0].iConfidence;
+		CleanupStack::PopAndDestroy(); //msgIDArray
+		
+		newBifConf = (*(aBifReader->IdsLC()))[0].iConfidence; 
+		CleanupStack::PopAndDestroy(); //IdsLC
+		
+		if ( newBifConf > oldBifConf )
+			{
+			CleanupStack::PushL(aBifReader);
+			RemoveBifL(aBifReader->MessageTypeUid());
+			iBifReaders->AppendL(aBifReader);
+			CleanupStack::Pop();	// aBifReader
+			}
+		else
+			CleanupStack::PopAndDestroy();// aBifReader
+
+		}
+
+	}
+
+//
+// Error returned
+EXPORT_C void CBIODatabase::RemoveBifL(TUid aMsgID)
+/** Removes a BIF specified by UID.
+
+@param aMsgID BIO type UID */
+	{
+	TInt index = 0;
+    
+	TRAPD(leaveValue,GetBioIndexWithMsgIDL(aMsgID, index));
+    
+	// We haven't read a BIF with the msgID in yet
+	if (leaveValue == KErrNone)
+		{
+		// just remove it
+		RemoveBifL(index);
+		}
+	else
+		{
+		//__ASSERT_DEBUG(Panic(EBioDBNotFound));
+		}
+	}
+
+EXPORT_C void CBIODatabase::RemoveBifL(TInt aIndex)
+/** Removes a BIF specified by index.
+
+@param aIndex Index of file in this object */
+	{
+	CBioInfoFileReader *bifReader = iBifReaders->At(aIndex);
+	iBifReaders->Delete(aIndex);
+	delete bifReader;
+	}
+
+
+//
+// Get the BioEntry at this index
+// Return Index if found, error if not
+EXPORT_C const CBioInfoFileReader& CBIODatabase::BifReader(TInt aIndex) const
+/** Gets a BIF reader for a BIF at a specified index.
+
+@param aIndex Index
+@return BIF file reader */
+	{
+		__ASSERT_DEBUG(aIndex >= 0 && aIndex <= iBifReaders->Count(),
+								Panic(EBioDBNotFound));
+		return *iBifReaders->At(aIndex);
+	}
+
+//
+// Get the BioEntry at this index
+// Return Index if found, error if not
+EXPORT_C const CArrayFix<TBioMsgId>* CBIODatabase::BIOEntryLC(TInt index)
+/** Gets the ID array of a BIF at a specified index.
+
+@param index Index
+@return ID array, or NULL if not found */
+	{
+	if (index >= 0 && index < iBifReaders->Count())
+		{
+		return iBifReaders->At(index)->IdsLC();
+		}
+	else
+		return NULL;
+	}
+
+//
+// Get the Index for the BioMessageID
+EXPORT_C void CBIODatabase::GetBioIndexWithMsgIDL(TUid aMsgID, TInt& rIndex)
+/** Gets the index of a BIF of a specified BIO message type.
+
+@param aMsgID BIO message type
+@param rIndex On return, index of found BIF
+@leave KErrNotFound Not found */
+	{
+	rIndex = iBifReaders->Count();
+
+	// See if we have one of these Messages
+	while (rIndex--)
+		{
+		if ((*iBifReaders)[rIndex]->MessageTypeUid() == aMsgID)
+			{
+			return;
+			}
+		}
+	User::Leave(KErrNotFound);
+	}
+
+
+//
+// Get the BioMessageID for the Index
+EXPORT_C void CBIODatabase::GetBioMsgID(TInt aIndex, TUid& rMsgID)
+/** Gets the BIO message type for a specified index.
+
+@param aIndex Index
+@param rMsgID On return, BIO message type */
+	{
+	__ASSERT_DEBUG(aIndex >= 0 && aIndex <= iBifReaders->Count(),
+								Panic(EBioDBNotFound));
+	
+	rMsgID =  (*iBifReaders)[aIndex]->MessageTypeUid();
+	}
+
+
+//
+// Get the BioParserName for the Index
+EXPORT_C const TPtrC CBIODatabase::GetBioParserName(TInt aIndex)
+/** Gets the BIO parser name for a specified index.
+
+@param aIndex Index
+@return BIO parser name */
+	{
+	__ASSERT_DEBUG( aIndex >= 0 && aIndex <= iBifReaders->Count(),
+								Panic(EBioDBNotFound));
+	return (*iBifReaders)[aIndex]->MessageParserName();	
+	}
+	
+/** Depreacated method.
+
+Need to use CBIODatabase::GetBioControlName instead.
+
+@see CBIODatabase::GetBioControlName
+
+@param aIndex Not used
+@param rControlID Not used 
+
+@panic USER	EInvariantFalse
+
+@deprecated */
+EXPORT_C void CBIODatabase::GetBioControlID(TInt /*aIndex*/, TUid& /*rControlID*/)
+	{
+	User::Invariant();
+	}
+	
+/** Gets the BIO control name for a specified index.
+
+@param aIndex Index
+@return BIO control name */
+EXPORT_C const TPtrC CBIODatabase::GetBioControlName(TInt aIndex)
+	{
+	__ASSERT_DEBUG( aIndex >= 0 && aIndex <= iBifReaders->Count(), 
+								Panic(EBioDBNotFound));
+	return (*iBifReaders)[aIndex]->MessageAppCtrlName();
+	}
+ 
+
+//
+// Get the first Port Number for this messaga type 
+EXPORT_C void CBIODatabase::GetPortNumberL(TUid aMsgID, TBioMsgIdType aPortType, TInt& aPortNumber)
+/** Gets the port number for the BIF ID entry for a specified BIO message type 
+and bearer type.
+
+@param aMsgID BIO message type
+@param aPortType Bearer type
+@param aPortNumber On return, the port number
+@leave KErrNotFound Not found */
+	{
+	TInt index = 0;
+	GetBioIndexWithMsgIDL(aMsgID, index);
+	
+	// We haven't read a BIF with the msgID in yet
+	TBioMsgId tranportID;
+	GetTransportIDL(index, aPortType, tranportID);
+	aPortNumber = tranportID.iPort;
+	}
+
+
+//
+// Get the first ID String for this messaga type 
+EXPORT_C void CBIODatabase::GetIdentifierTextL(TUid aMsgID, TBioMsgIdType aPortType, TBioMsgIdText& aText)
+/** Gets the identifier text for the BIF ID entry for a specified BIO message type 
+and bearer type.
+
+@param aMsgID BIO message type
+@param aPortType Bearer type
+@param aText On return, the identifier text */
+	{
+	TInt index = 0;
+	GetBioIndexWithMsgIDL(aMsgID, index);
+	
+	TBioMsgId tranportID;
+	GetTransportIDL(index, aPortType, tranportID);
+	aText.Copy(tranportID.iText);
+	}
+
+//
+// Get the GetTransportIDL 
+void CBIODatabase::GetTransportIDL(TInt aIndex, TBioMsgIdType aPortType, TBioMsgId& aBioMsgID) 
+	{
+	TBioMsgId tranportID;
+	TBool found = EFalse;
+
+	const CArrayFix<TBioMsgId>* msgIDArray = BIOEntryLC(aIndex);
+
+	for (TInt i = 0; i < msgIDArray->Count() && !found ; i++)
+		{
+		if ( (*msgIDArray)[i].iType == aPortType)
+			{
+			tranportID = (*msgIDArray)[i];
+
+			// Really should make a copy contructor & = operator
+			aBioMsgID.iType = (*msgIDArray)[i].iType;
+			aBioMsgID.iConfidence = (*msgIDArray)[i].iConfidence;			
+			aBioMsgID.iText.Copy((*msgIDArray)[i].iText);
+			aBioMsgID.iPort = (*msgIDArray)[i].iPort;
+			aBioMsgID.iCharacterSet = (*msgIDArray)[i].iCharacterSet;
+			aBioMsgID.iGeneralIdData = (*msgIDArray)[i].iGeneralIdData;
+			found = ETrue;
+			}
+		}
+	CleanupStack::PopAndDestroy(); //msgIDArray
+	
+	if (!found)
+		User::Leave(KErrNotFound);
+	}
+
+
+//
+// Get the BioParserName for the Message ID
+EXPORT_C const TPtrC CBIODatabase::GetBioParserNameL(TUid aMsgID)
+/** Gets the BIO parser name for a specified BIO message type.
+
+@param aMsgID BIO message type
+@return BIO parser name
+@leave KErrNotFound Not found */
+	{
+	TInt index = 0;
+	TRAPD(leaveValue, GetBioIndexWithMsgIDL(aMsgID, index));
+
+	// We haven't read a BIF with the msgID in yet
+	if (leaveValue != KErrNone)
+		{
+		__ASSERT_DEBUG(0, Panic(EBioDBNotFound));
+		User::Leave(leaveValue);
+		}
+		
+	return GetBioParserName(index);
+	}
+
+
+/** Depreacated method.
+
+Need to use CBIODatabase::GetBioControlNameL instead.
+
+@see CBIODatabase::GetBioControlNameL
+
+@param aIndex Not used
+@param rControlID Not used
+
+@panic USER	EInvariantFalse
+
+@deprecated */
+EXPORT_C void CBIODatabase::GetBioControlIDL(TUid /*aMsgID*/, TUid& /*rControlID*/)
+	{
+	User::Invariant();
+	}
+	
+/** Gets the BIO control name for a specified BIO message type.
+
+@param aMsgID BIO message type
+@return BIO Control name
+
+@leave KErrNotFound BIO message type does not exist */
+EXPORT_C const TPtrC CBIODatabase::GetBioControlNameL(TUid aMsgID)
+ 	{
+ 	TInt index = 0;
+	TRAPD(leaveValue, GetBioIndexWithMsgIDL(aMsgID, index));
+     
+ 	// We haven't read a BIF with the msgID in yet
+	if( leaveValue != KErrNone )
+ 		{
+ 		__ASSERT_DEBUG(0, Panic(EBioDBNotFound));
+		User::Leave(leaveValue);
+ 		}
+		
+	return GetBioControlName(index);
+ 	}
+ 
+
+//
+// Get the String Extension for the BioMessageID
+EXPORT_C const TPtrC CBIODatabase::GetFileExtL(TUid aMsgID)
+/** Gets the BIO file extension for a specified BIO message type.
+
+@param aMsgID BIO message type
+@leave KErrNotFound Not found
+@return BIO file extension */
+{
+	TInt index = 0;
+	GetBioIndexWithMsgIDL(aMsgID, index);
+	return (*iBifReaders)[index]->FileExtension();
+}
+
+
+//
+EXPORT_C void CBIODatabase::GetDefaultSendBearerL(TUid aBioUID, TBioMsgId& rBioMsgIdentifier)
+/** Gets the default BIF ID entry for a specified BIO message type.
+
+@param aBioUID BIO message type
+@param rBioMsgIdentifier On return, the default BIF ID entry
+@leave KErrNotFound Not found */
+	{
+	TInt index = 0;
+	TBioMsgIdType portType = EBioMsgIdUnknown;
+	GetBioIndexWithMsgIDL(aBioUID, index);
+	GetDefaultSendBearerTypeL(aBioUID, portType);
+	GetTransportIDL(index, portType, rBioMsgIdentifier);
+	}
+
+//
+EXPORT_C void CBIODatabase::GetDefaultSendBearerTypeL(TUid aBioUID, TBioMsgIdType& rPortType)
+/** Gets the bearer type for the default BIF ID entry for a specified BIO message 
+type.
+
+@param aBioUID BIO message type
+@param rPortType On return, the bearer type
+@leave KErrNotFound Not found */
+	{
+	TInt index = 0;
+	GetBioIndexWithMsgIDL(aBioUID, index);
+	const CArrayFix<TBioMsgId>* msgIDArray = BIOEntryLC(index);
+	rPortType = (*msgIDArray)[0].iType;
+	CleanupStack::PopAndDestroy(); 
+	}
+
+//
+EXPORT_C void CBIODatabase::GetDefaultSendBearerByTypeL(TUid aBioUID, TBioMsgIdType aPortType, TBioMsgId& rBioMsgIdentifier)
+/** Gets the default BIF ID entry for a specified BIO message type and bearer type.
+
+@param aBioUID BIO message type
+@param aPortType Bearer type
+@param rBioMsgIdentifier On return, the default BIF ID entry
+@leave KErrNotFound Not found */
+	{
+	TInt index = 0;
+	GetBioIndexWithMsgIDL(aBioUID, index);
+	GetTransportIDL(index, aPortType, rBioMsgIdentifier);
+	}
+
+//
+// Get the BIO Entry based on what type it is, pos indicates where to start looking after
+// if it can't be found, NULL returned
+EXPORT_C const CArrayFix<TBioMsgId>* CBIODatabase::BioEntryByTypeLC(
+							TSearchList aSearchType,
+							TBioMsgIdType portType, 
+							TInt& rIndex)
+/** Gets the ID array of a BIF of a specified bearer source type.
+
+@param aSearchType Search type
+@param portType Bearer source type
+@param rIndex On return, index of found BIF
+@return ID array, or NULL if not found */
+	{
+	
+	switch(aSearchType)
+	{
+		case EStart:
+			rIndex = 0;
+			break;
+		case ENext:
+			rIndex++;
+			break;
+		default:
+			__ASSERT_DEBUG(0 ,Panic(EBioDBNotFound));
+			break;
+	}
+
+
+		
+	const CArrayFix<TBioMsgId>* msgIDArray = BIOEntryLC(rIndex);
+	
+	while (msgIDArray)
+		{
+		for (TInt i = 0; i < msgIDArray->Count() ; i++)
+			{
+			if ( (*msgIDArray)[i].iType == portType)
+				return msgIDArray;
+			}
+		CleanupStack::PopAndDestroy(); //msgIDArray
+		msgIDArray = BIOEntryLC(++rIndex);
+		}
+	return NULL;
+	
+	}	
+
+
+
+//
+// This will compare strings for both NBS & IANA types handy when you have a start string
+// and want to know if there's a Bio Message to support this
+
+EXPORT_C TInt CBIODatabase::IsBioMessageL(TBioMsgIdType aPortType, const TDesC& aPattern, TUint16 aPort, TUid& rBioMsgUID)
+/** Tests if there is a BIO parser for the specificed BIF ID settings.
+
+@param aPortType Bearer type
+@param aPattern Text identifier to match
+@param aPort Port to match
+@param rBioMsgUID On return, the matching BIO message type
+@return KErrNone if found, else KErrNotFound */
+{
+	TBioMsgId bioMessageData;
+	bioMessageData.iType = aPortType;
+	bioMessageData.iText.Copy(aPattern.Left(KMaxBioIdText));
+	bioMessageData.iPort = aPort;
+
+	return ( IsBioMessageL(bioMessageData, rBioMsgUID) );
+}
+
+//
+EXPORT_C TInt CBIODatabase::IsBioMessageL(TBioMsgId bioMessageData, TUid& rBioMsgUID)
+/** Tests if there is a BIO parser for a specified BIF ID.
+
+@param bioMessageData BIF ID to match
+@param rBioMsgUID On return, the matching BIO message type
+@return KErrNone if found, else KErrNotFound */
+	{
+	rBioMsgUID = KNullUid;
+	TInt pos;
+	TUid msgID;
+	TBool bioFound = EFalse;
+
+	const CArrayFix<TBioMsgId>* bioMsgIDs = BioEntryByTypeLC(EStart, bioMessageData.iType, pos);
+	
+	while (!bioFound && bioMsgIDs)
+		{
+		GetBioMsgID(pos, msgID);
+		for (TInt i = 0; !bioFound && i < bioMsgIDs->Count(); i++)
+			{
+			if (bioMsgIDs->At(i).iType == bioMessageData.iType)
+				{
+				switch(bioMessageData.iType)
+					{
+					case EBioMsgIdIana:
+					case EBioMsgIdNbs:
+						if (bioMsgIDs->At(i).iText.CompareF(bioMessageData.iText)==0)
+						{
+							rBioMsgUID = msgID;
+							bioFound = ETrue;
+						}
+						break;
+					case EBioMsgIdWap:
+					case EBioMsgIdWapSecure:
+					case EBioMsgIdWsp:
+					case EBioMsgIdWspSecure:
+						if (bioMsgIDs->At(i).iPort == bioMessageData.iPort)
+						{
+							rBioMsgUID = msgID;
+							bioFound = ETrue;
+						}
+						break;
+					case EBioMsgIdUnknown:
+					default:
+						break;
+					}
+				}
+			}
+		CleanupStack::PopAndDestroy();	// bioMsgIDs
+
+		if (!bioFound)
+			bioMsgIDs = BioEntryByTypeLC(ENext, bioMessageData.iType, pos);	
+		} 
+	
+
+	if (!bioFound)
+		return KErrNotFound;
+
+	return KErrNone;
+	}
+