// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "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:
// This is the Cpp file which contains the utility functions common across the servers
//
//
/**
@file
*/
// User includes
#include <t_utils.h>
#include <t_utilscentralrepository.h>
// Epoc includes
#include <msvids.h>
#include <bautils.h>
#include <msvutils.h>
#include <barsc.h>
// Literals Used
const TInt KDefBufferSize = 1024;
/**
CT_MsgUtils()
Constructor
*/
EXPORT_C CT_MsgUtils::CT_MsgUtils()
{
}
/**
~CT_MsgUtils()
Constructor
*/
CT_MsgUtils::~CT_MsgUtils()
{
}
/**
OpenResourceFileL()
Opens a resource File
@param rFile
Resource File Handle
@param anFs
File Session associated
@param aFileName
The Name of resource File to be opened
*/
EXPORT_C void CT_MsgUtils::OpenResourceFileL(RResourceFile& rFile, RFs& anFs, const TDesC& aFileName )
{
// open resource file
TFileName fileName(aFileName);
MsvUtils::AddPathAndExtensionToResFileL(fileName);
BaflUtils::NearestLanguageFile( anFs, fileName );
if (BaflUtils::FileExists(anFs,fileName))
{
rFile.OpenL( anFs, fileName );
return;
}
User::Leave(KErrNotFound);
}
/**
CloseResourceFile()
Closes a recource File
@param aFile
The Name of resource File to be closed
*/
EXPORT_C void CT_MsgUtils::CloseResourceFile( TAny* aFile )
{
((RResourceFile*)aFile)->Close();
}
/**
FindEntryByNameL()
Search the entries under a given folder ID by name of the entry
i.e, iDescription or iDetails value of an entry
@param aSession
Session object
@param aParentId
Parent Id under which the entry needs to be found
@param aEntryName
The entry name that needs to be found
@leave KErrNotFound
Leaves if no entry's iDescription or iDetails matches with aEntryName
@return
Id of the entry that match
*/
EXPORT_C TMsvId CT_MsgUtils::FindEntryByNameL(CMsvSession* aSession, TMsvId aParentId, TDesC& aEntryName, TBool aCaseSensitive)
{
TMsvId msgEntryId = KMsvNullIndexEntryId;
// Set the context to the Parent
CMsvEntry* entry = CMsvEntry::NewL(*aSession, aParentId,TMsvSelectionOrdering
(KMsvNoGrouping,EMsvSortByNone, ETrue));
CleanupStack::PushL(entry);
entry->SetEntryL(aParentId);
msgEntryId = FindEntryByNameL(entry, aEntryName, aCaseSensitive);
CleanupStack::PopAndDestroy(entry);
return msgEntryId;
}
/**
FindEntryByNameL()
Search the entries under a given folder ID by name of the entry
i.e, iDescription or iDetails value of an entry
@param aSession
Session object
@param aParentId
Parent Id under which the entry needs to be found
@param aEntryName
The entry name that needs to be found
@param aParentEntryName
The Parent entry name that needs to be matched with the entry found
@leave KErrNotFound
Leaves if no entry's iDescription or iDetails matches with aEntryName
@return
Id of the entry that match
*/
EXPORT_C TMsvId CT_MsgUtils::FindEntryByNameL(CMsvSession* aSession, TMsvId aParentId, TDesC& aEntryName, TDesC& aParentEntryName, TBool aCaseSensitive)
{
TMsvId msgEntryId = KMsvNullIndexEntryId;
// Set the context to the Parent
CMsvEntry* entry = CMsvEntry::NewL(*aSession, aParentId,TMsvSelectionOrdering
(KMsvNoGrouping,EMsvSortByNone, ETrue));
CleanupStack::PushL(entry);
entry->SetEntryL(aParentId);
msgEntryId = FindEntryByNameL(entry, aEntryName, aParentEntryName, aCaseSensitive);
CleanupStack::PopAndDestroy(entry);
return msgEntryId;
}
/**
FindEntryByNameL()
Search the entries under a given entry(an object of CMsvEntry) by name of the entry
i.e, iDescription or iDetails value of an entry
@param aEntry
Parent entry under which the given entry needs to be searched
@param aEntryName
The entry name that needs to be found
@leave KErrNotFound
Leaves if no entry's iDescription or iDetails matches with aEntryName
@return
Id of the entry that match
*/
EXPORT_C TMsvId CT_MsgUtils::FindEntryByNameL(CMsvEntry* aEntry,TDesC& aEntryName, TBool aCaseSensitive)
{
TMsvId msgEntryId = KMsvNullIndexEntryId;
msgEntryId = RecFindEntryByNameL(*aEntry, aEntryName, aCaseSensitive);
if(msgEntryId == KMsvNullIndexEntryId)
{
User::Leave(KErrNotFound);
}
return msgEntryId;
}
/**
FindEntryByNameL()
Search the entries under a given entry(an object of CMsvEntry) by name of the entry
i.e, iDescription or iDetails value of an entry
@param aEntry
Parent entry under which the given entry needs to be searched
@param aEntryName
The entry name that needs to be found
@param aParentEntryName
The Parent entry name that needs to be matched with the entry found
@leave KErrNotFound
Leaves if no entry's iDescription or iDetails matches with aEntryName
@return
Id of the entry that match
*/
EXPORT_C TMsvId CT_MsgUtils::FindEntryByNameL(CMsvEntry* aEntry,TDesC& aEntryName, TDesC& aParentEntryName, TBool aCaseSensitive)
{
TMsvId msgEntryId = KMsvNullIndexEntryId;
msgEntryId = RecFindEntryByNameL(*aEntry, aEntryName, aParentEntryName, aCaseSensitive);
if(msgEntryId == KMsvNullIndexEntryId)
{
User::Leave(KErrNotFound);
}
return msgEntryId;
}
/**
RecFindEntryByNameL()
Recursively search the entries (including all sub entries) under a given entry (an object of CMsvEntry)
by name of the entry i.e, iDescription or iDetails value of an entry
@param aEntry
Parent entry under which the given entry needs to be searched
@param aEntryName
The entry name that needs to be found
@leave KErrNotFound
Leaves if no entry's iDescription or iDetails matches with aEntryName
@return
Id of the entry that match
*/
TMsvId CT_MsgUtils::RecFindEntryByNameL(CMsvEntry& aEntry, TDesC& aEntryName, TBool aCaseSensitive)
{
TMsvId msgEntryId = KMsvNullIndexEntryId;
CMsvEntrySelection* selection = aEntry.ChildrenL();
CleanupStack::PushL(selection);
// Search for the entry in the children selection, based on the entry name given
TBool found = EFalse;
TInt count = selection->Count();
for (TInt index = 0; (index<count) && (!found); index++)
{
// Set the context to the child entry
aEntry.SetEntryL((*selection)[index]);
if (aCaseSensitive)
{
if (( aEntryName.Compare( aEntry.Entry().iDescription ) == 0 ) ||
( aEntryName.Compare( aEntry.Entry().iDetails ) == 0 ))
{
found = ETrue;
}
}
else if (( aEntryName.CompareF( aEntry.Entry().iDescription ) == 0 ) ||
( aEntryName.CompareF( aEntry.Entry().iDetails ) == 0 ))
{
found = ETrue;
}
if (found)
{
msgEntryId = (*selection)[index];
}
else
{
CMsvEntry* nextEntry = CMsvEntry::NewL(aEntry.Session(), (*selection)[index],TMsvSelectionOrdering(KMsvNoGrouping, EMsvSortByNone, ETrue));
CleanupStack::PushL(nextEntry);
msgEntryId = RecFindEntryByNameL(*nextEntry, aEntryName, aCaseSensitive);
if(msgEntryId != KMsvNullIndexEntryId)
{
found = ETrue;
}
CleanupStack::PopAndDestroy(nextEntry);
}
}
CleanupStack::PopAndDestroy(selection);
return msgEntryId;
}
/**
RecFindEntryByNameL()
Recursively search the entries (including all sub entries) under a given entry (an object of CMsvEntry)
by name of the entry i.e, iDescription or iDetails value of an entry
@param aEntry
Parent entry under which the given entry needs to be searched
@param aEntryName
The entry name that needs to be found
@param aParentEntryName
The Parent entry name that needs to be matched with the entry found
@leave KErrNotFound
Leaves if no entry's iDescription or iDetails matches with aEntryName
@return
Id of the entry that match
*/
TMsvId CT_MsgUtils::RecFindEntryByNameL(CMsvEntry& aEntry, TDesC& aEntryName, TDesC& aParentEntryName, TBool aCaseSensitive)
{
TMsvId msgEntryId = KMsvNullIndexEntryId;
CMsvEntrySelection* selection = aEntry.ChildrenL();
CleanupStack::PushL(selection);
// Search for the entry in the children selection, based on the entry name given
TBool found = EFalse;
TInt count = selection->Count();
TBool matched = EFalse;
for (TInt index = 0; (index<count) && (!found); index++)
{
// Set the context to the child entry
aEntry.SetEntryL((*selection)[index]);
matched = EFalse;
if (aCaseSensitive)
{
if (( aEntryName.Compare( aEntry.Entry().iDescription ) == 0 ) ||
( aEntryName.Compare( aEntry.Entry().iDetails ) == 0 ))
{
matched = ETrue;
}
}
else if (( aEntryName.CompareF( aEntry.Entry().iDescription ) == 0 ) ||
( aEntryName.CompareF( aEntry.Entry().iDetails ) == 0 ))
{
matched = ETrue;
}
if (matched)
{
//Check Parent
CMsvEntry* parentEntry = CMsvEntry::NewL(aEntry.Session(), aEntry.Entry().Parent(),TMsvSelectionOrdering(KMsvNoGrouping, EMsvSortByNone, ETrue));
CleanupStack::PushL(parentEntry);
if(CheckParent(*parentEntry,aParentEntryName))
{
found = ETrue;
msgEntryId = (*selection)[index];
}
CleanupStack::PopAndDestroy(parentEntry);
}
if (!found)
{
CMsvEntry* nextEntry = CMsvEntry::NewL(aEntry.Session(), (*selection)[index],TMsvSelectionOrdering(KMsvNoGrouping, EMsvSortByNone, ETrue));
CleanupStack::PushL(nextEntry);
msgEntryId = RecFindEntryByNameL(*nextEntry, aEntryName, aParentEntryName, aCaseSensitive);
if(msgEntryId != KMsvNullIndexEntryId)
{
found = ETrue;
}
CleanupStack::PopAndDestroy(nextEntry);
}
}
CleanupStack::PopAndDestroy(selection);
return msgEntryId;
}
/**
CheckParent()
Checks if the given parent name matches the name of the given parent entry
@param aParentEntry
Parent entry whose name is to be checked
@param aParentEntryName
The Parent entry name that we are checking against
@return
ETrue if they match and EFalse if they do not
*/
TBool CT_MsgUtils::CheckParent(CMsvEntry& aParentEntry, TDesC& aParentEntryName)
{
TBool ret = EFalse;
if (( aParentEntryName.CompareF( aParentEntry.Entry().iDescription ) == 0 ) ||
( aParentEntryName.CompareF( aParentEntry.Entry().iDetails ) == 0 ))
{
ret = ETrue;
}
return ret;
}
/**
CreateChildrenSelectionL()
This function creates a selection of the children entries under a given parent Id
@param aSession
A CMsvSession object
@param aEntryId
Id of the entry
@return
Returns a selection of all child entries under the given entry
*/
EXPORT_C CMsvEntrySelection* CT_MsgUtils::CreateChildrenSelectionL(CMsvSession* aSession,
TMsvId aEntryId)
{
CMsvEntry* entry = CMsvEntry::NewL(*aSession, aEntryId,TMsvSelectionOrdering
( KMsvNoGrouping,EMsvSortByNone, ETrue));
CleanupStack::PushL(entry);
entry->SetEntryL(aEntryId);
TMsvSelectionOrdering order;
order.SetShowInvisibleEntries(ETrue);
entry->SetSortTypeL(order);
CMsvEntrySelection* selection = entry->ChildrenL();
CleanupStack::PopAndDestroy(entry);
return selection;
}
/**
CreateChildrenSelectionWithTypeL()
This function creates a selection of the children entries under a given parent Id
which are of a specified type.
@param aSession
A CMsvSession object
@param aEntryId
Id of the entry
@param aType
Type of entry to look for
@return
Returns a selection of all child entries under the given entry of the specified type
*/
EXPORT_C CMsvEntrySelection* CT_MsgUtils::CreateChildrenSelectionWithTypeL(CMsvSession* aSession, TMsvId aEntryId, TUid aType)
{
CMsvEntry* entry = CMsvEntry::NewL(*aSession, aEntryId, TMsvSelectionOrdering(KMsvNoGrouping, EMsvSortByNone, ETrue));
CleanupStack::PushL(entry);
entry->SetEntryL(aEntryId);
TMsvSelectionOrdering order;
order.SetShowInvisibleEntries(ETrue);
entry->SetSortTypeL(order);
CMsvEntrySelection* selection = entry->ChildrenWithTypeL(aType);
CleanupStack::PopAndDestroy(entry);
return selection;
}
/**
CreateChildrenSelectionRemoteFolderL()
This function creates a selection of the child entries under the
remote folder Id if the service name is specified
@param aSession
A CMsvSession object
@param aAccountName
The account name or service name
@param aFolderName
The name of the remote folder whose entries need to be fetched
@return
The selection of all entries under the given entry
*/
EXPORT_C CMsvEntrySelection* CT_MsgUtils::CreateChildrenSelectionRemoteFolderL(CMsvSession*
aSession,TPtrC aAccountName,TPtrC aFolderName)
{
TMsvId remoteFolderId = GetRemoteFolderIdByNameL(aSession, aAccountName, aFolderName);
return CreateChildrenSelectionL(aSession,remoteFolderId);
}
/**
CreateChildrenSelectionRemoteFolderWithTypeL()
This function creates a selection of the child entries under the
remote folder Id with a specified type if the service name is specified
@param aSession
A CMsvSession object
@param aAccountName
The account name or service name
@param aFolderName
The name of the remote folder whose entries need to be fetched
@param aType
Type of entry to look for
@return
The selection of all entries under the given entry with the specified type
*/
EXPORT_C CMsvEntrySelection* CT_MsgUtils::CreateChildrenSelectionRemoteFolderWithTypeL(CMsvSession*
aSession,TPtrC aAccountName,TPtrC aFolderName, TUid aType)
{
TMsvId remoteFolderId = GetRemoteFolderIdByNameL(aSession, aAccountName, aFolderName);
return CreateChildrenSelectionWithTypeL(aSession, remoteFolderId, aType);
}
/**
GetRemoteFolderIdByNameL()
Searches for a given entry under the remote folder Id specified and gets it Id
@param aSession
A CMsvSession object
@param aAccountName
The account name
@param aFolderName
The name of the remote folder whose Id is to be found
@return
The Id of the specified folder
*/
EXPORT_C TMsvId CT_MsgUtils::GetRemoteFolderIdByNameL(CMsvSession* aSession,TPtrC aAccountName,TPtrC aFolderName, TBool aCaseSensitive)
{
TMsvId imapServiceId = CT_MsgUtilsCentralRepository::GetImapServiceIdL((TDes&)aAccountName);
return CT_MsgUtils::FindEntryByNameL(aSession, imapServiceId, (TDesC&)aFolderName, aCaseSensitive);
}
/**
GetRemoteFolderIdByNameL()
Searches for a given entry under the remote folder Id specified and gets it Id
@param aSession
A CMsvSession object
@param aAccountName
The account name
@param aFolderName
The name of the remote folder whose Id is to be found
@param aFolderName
The name of the remote parent folder of the entry to be found
@return
The Id of the specified folder
*/
EXPORT_C TMsvId CT_MsgUtils::GetRemoteFolderIdByNameL(CMsvSession* aSession,TPtrC aAccountName,TPtrC aFolderName, TPtrC aParentFolderName, TBool aCaseSensitive)
{
TMsvId imapServiceId = CT_MsgUtilsCentralRepository::GetImapServiceIdL((TDes&)aAccountName);
return CT_MsgUtils::FindEntryByNameL(aSession, imapServiceId, (TDesC&)aFolderName, (TDesC&)aParentFolderName, aCaseSensitive);
}
/**
SearchMessageBySubjectL()
This function searches for a message based on the
subject under the specified local folder
@param aSession
A CMsvSession object
@param afolderId
The folder Id under which the search needs to be done
@param aSubject
The subject name of the message
@leave KErrNotFound
Leaves if the message is not found
@return
If the message is found it returns the message Id
*/
EXPORT_C TMsvId CT_MsgUtils::SearchMessageBySubjectL(CMsvSession* aSession,TMsvId afolderId,TPtrC aSubject)
{
TMsvId messageId = KMsvNullIndexEntryId;
CMsvEntry* entry = aSession->GetEntryL(afolderId);
CleanupStack::PushL(entry);
// Set the entry to the source folder id
entry->SetEntryL(afolderId);
//Get CMsvEntrySelection object
CMsvEntrySelection* selection = entry->ChildrenL();
CleanupStack::PushL(selection);
TInt count = selection->Count();
if ( count > 0)
{
CMsvEntry* childEntry = aSession->GetEntryL(selection->At(0));
CleanupStack::PushL(childEntry);
for(TInt entryIndex = 0 ; entryIndex< count; entryIndex++)
{
childEntry->SetEntryL(selection->At(entryIndex));
if (childEntry->Entry().iDescription.Compare(aSubject) == 0)
{
messageId = selection->At(entryIndex);
break;
}
}
CleanupStack::PopAndDestroy(childEntry);
}
if(messageId == KMsvNullIndexEntryId)
{
User::Leave(KErrNotFound);
}
CleanupStack::PopAndDestroy(2,entry); //selection,entry
return messageId;
}
/**
SearchMessageBySubjectL()
This function searches for a message based on the subject
under the specified local folder. This fucntion provides the
flexibility of making the invisible children entries visible.
@param aSession
A CMsvSession object
@param afolderId
The folder Id under which the search needs to be done
@param aSubject
The subject name of the message
@leave KErrNotFound
Leaves if the message is not found
@return
If the message is found it returns the message Id
*/
EXPORT_C TMsvId CT_MsgUtils::SearchMessageBySubjectL(CMsvSession* aSession,TMsvId afolderId,TPtrC aSubject, TBool aVisibleFlag)
{
TMsvId messageId = KMsvNullIndexEntryId;
CMsvEntry* entry = aSession->GetEntryL(afolderId);
CleanupStack::PushL(entry);
// Set the entry to the source folder id
entry->SetEntryL(afolderId);
if(aVisibleFlag)
{
// Make the message entries visible
TMsvSelectionOrdering order;
order.SetShowInvisibleEntries(ETrue);
entry->SetSortTypeL(order);
}
//Get CMsvEntrySelection object
CMsvEntrySelection* selection = entry->ChildrenL();
CleanupStack::PushL(selection);
TInt count = selection->Count();
if ( count > 0)
{
CMsvEntry* childEntry = aSession->GetEntryL(selection->At(0));
CleanupStack::PushL(childEntry);
for(TInt entryIndex = 0 ; entryIndex< count; entryIndex++)
{
childEntry->SetEntryL(selection->At(entryIndex));
if (childEntry->Entry().iDescription.Compare(aSubject) == 0)
{
messageId = selection->At(entryIndex);
break;
}
}
CleanupStack::PopAndDestroy(childEntry);
}
if(messageId == KMsvNullIndexEntryId)
{
User::Leave(KErrNotFound);
}
CleanupStack::PopAndDestroy(2,entry); //selection,entry
return messageId;
}
/**
CompareFilesL()
Compares two input files (ASCII & Unicode).
@param aFileOne
The first file to be compared
@param aFileTwo
The second file to be compared
@param aIsUnicode
To check if its unicode
@param aIgnoreCharList
An array of type CArrayFixFlat
@param aDiffFlag
Flag to indicate the difference
@return
Returns ETrue if the files are different.
*/
EXPORT_C TInt CT_MsgUtils::CompareFilesL(TPtrC aFileOne, TPtrC aFileTwo, TBool aIsUnicode,
CArrayFixFlat<TUint16>* aIgnoreCharList, TBool& aDiffFlag)
{
// Return Code
TInt retCode = KErrNone;
// Streams for the file1 and file2 to compare
RFileReadStream fileReadStream1;
RFileReadStream fileReadStream2;
// Files difference flag
aDiffFlag = EFalse;
RFs iFs;
User::LeaveIfError(iFs.Connect());
// Open file one to compare in the read only mode
retCode = fileReadStream1.Open( iFs, aFileOne, EFileShareReadersOnly);
// If the file open of the first file is successful then open the second file, also in read only mode
if(retCode == KErrNone)
{
retCode = fileReadStream2.Open( iFs, aFileTwo, EFileShareReadersOnly);
// The file open of the second file is successful
if(retCode == KErrNone)
{
// To hold the line content of file one
HBufC* lineOneBuffer = HBufC::NewLC(KDefBufferSize);
TPtr ptrLineOne = lineOneBuffer->Des();
// To hold the line content of file two
HBufC* lineTwoBuffer = HBufC::NewLC(KDefBufferSize);
TPtr ptrLineTwo = lineTwoBuffer->Des();
// End of File indicators
TBool eofOne = EFalse;
TBool eofTwo = EFalse;
// Read the file one and file two data
do
{
// Read file one data
eofOne = ReadDataL(fileReadStream1, ptrLineOne, aIsUnicode, aIgnoreCharList);
// Read file two data
eofTwo = ReadDataL(fileReadStream2, ptrLineTwo, aIsUnicode, aIgnoreCharList);
// Check EOF state of the files.
// Either both the files will be in EOF state or
// none of the files will be in EOF state
if((!eofOne && !eofTwo)||(eofOne && eofTwo))
{
// Compare the read lines from file one and the file two
if(ptrLineOne.Compare(ptrLineTwo) != 0)
{
// Different data content so set the differnce flag
aDiffFlag = ETrue;
}
}
else
{
// Different EOF
aDiffFlag = ETrue;
}
} while(!eofOne && !eofTwo && !aDiffFlag);
// Delete line buffers
CleanupStack::PopAndDestroy(2, lineOneBuffer);
}
}
// Close the open streams
fileReadStream1.Close();
fileReadStream2.Close();
iFs.Close();
// Return the difference flag
return retCode;
}
/**
ReadDataL()
Reads data chunk from the file stream. Returns ETrue if the EOF found
@param aFileReadStream
File Stream
@param aPtrLineBuffer
Buffer to hold a line
@param aIsUnicode
To check if its unicode
@param aIgnoreCharList
List of the characters to be ignored
@leave KErrNotFound
Leaves if aIgnoreCharList is empty
@return
Return end of file flag
*/
EXPORT_C TBool CT_MsgUtils::ReadDataL(RFileReadStream& aFileReadStream,
TPtr& aPtrLineBuffer, TBool aIsUnicode, CArrayFixFlat<TUint16>* aIgnoreCharList)
{
TUint16 element = 0;
TKeyArrayFix key(0, ECmpTUint16);
TInt charPosition = 0;
TBool eof = EFalse;
TInt errorCode = KErrNone;
TUint8 aCharASCII = 0;
aPtrLineBuffer.FillZ();
aPtrLineBuffer.SetLength(0);
// Validate the input ignore char list
if (!aIgnoreCharList)
{
// Invalid parameter passed to ReadDataL: No ignore char list passed
User::Leave(KErrNotFound);
}
// Read data from file and store it in lineBuffer
do
{
if(aIsUnicode)
{
TRAP(errorCode, (element = aFileReadStream.ReadUint16L()));
}
else
{
TRAP(errorCode, (aCharASCII = aFileReadStream.ReadUint8L()));
element = (TUint16) aCharASCII;
}
if (errorCode != KErrEof)
{
// Check the availability of ignore char in the array
if ( aIgnoreCharList->Find(element, key, charPosition) != KErrNone )
{
// Append the char to the buffer if the read char is not ignore char
aPtrLineBuffer.Append(element);
}
}
else
{
eof = ETrue;
break;
}
// Stop at the end of line or no more data
} while(aPtrLineBuffer.Length() < KDefBufferSize);
// Return end of file flag
return eof;
}