wvuing/wvlogger/Src/CCALoggerManager.cpp
changeset 0 094583676ce7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wvuing/wvlogger/Src/CCALoggerManager.cpp	Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,1215 @@
+/*
+* Copyright (c) 2003 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:  Logger manager with read access to history files.
+*
+*/
+
+
+// INCLUDE FILES
+#include <SysUtil.h>
+#include <bautils.h>
+#include <s32file.h>
+
+#include "CCALoggerManager.h"
+#include "CCALoggerWriter.h"
+#include "MCALoggerMessageHeader.h"
+#include "MCALoggerMessageFactory.h"
+#include "MCALoggerMessage.h"
+
+#ifdef RD_MULTIPLE_DRIVE
+#include <centralrepository.h>
+#include <IMPSServiceSettingsUINGInternalCRKeys.h>
+#include <E32std.h>
+#include <EIKAPP.H>
+#include <eikappui.h>
+#include <eikenv.h>
+#include <eikbtgpc.h>
+#include <driveinfo.h>
+#include <StringLoader.h>            // StringLoader	
+#include "IMDialogUtils.h"
+#include <CAknMemorySelectionDialogMultiDrive.h>
+#include <rsfwmountman.h>
+#endif
+#include <chatNG.rsg>
+
+//for debug
+#include "ChatDebugPrint.h"
+
+//CONSTANTS
+const TInt KLengthOfPathEnd = 1;
+const TInt KArrayBegin = 0;
+
+//Max length for number is 10
+const TInt KMaxNumberLength = 10;
+
+// ================= MEMBER FUNCTIONS =======================
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::~CCALoggerManager
+// destructor
+// -----------------------------------------------------------------------------
+//
+CCALoggerManager::~CCALoggerManager()
+    {
+    CHAT_DP_TXT( "CCALoggerManager::~CCALoggerManager" );
+
+    //Close filesession
+    iFileSession.Close();
+
+    //reset toc array
+    iFileTocArray.ResetAndDestroy();
+
+    //reset temp toc array
+    iFileTempTocArray.ResetAndDestroy();
+
+    //reset write array
+    for ( TInt a = 0; a < iWriteFileArray.Count(); ++a )
+        {
+        //CCALoggerManager owns iFile in TFileRelation struct, but not the key
+        delete iWriteFileArray[a].iFile;
+        }
+
+    iWriteFileArray.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::NewL
+// Two phase constructor.
+// -----------------------------------------------------------------------------
+//
+CCALoggerManager* CCALoggerManager::NewL()
+    {
+    CHAT_DP_TXT( "CCALoggerManager::NewL" );
+
+    CCALoggerManager* lm = new ( ELeave ) CCALoggerManager();
+    CleanupStack::PushL( lm );
+    lm->ConstructL();
+    User::LeaveIfError( Dll::SetTls( static_cast< TAny* >( lm ) ) );
+    CleanupStack::Pop( lm );
+    return lm;
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::CCALoggerManager
+// Constructor
+// -----------------------------------------------------------------------------
+//
+CCALoggerManager::CCALoggerManager()
+    {
+    CHAT_DP_TXT( "CCALoggerManager::CCALoggerManager" );
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::ConstructL
+// Initialization of CCALoggerManager
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::ConstructL()
+    {
+    CHAT_DP_TXT( "CCALoggerManager::ConstructL" );
+
+    User::LeaveIfError( iFileSession.Connect() );
+
+    TBuf< KMaxPath > pathTemp;
+    iFileSession.PrivatePath( pathTemp );
+    pathTemp.Append( KCAHistoryDirectory );
+
+    //Ensure, that there is no file named IMHistory beforehand. Ignore errors
+    iFileSession.Delete( pathTemp.Left( pathTemp.Length() - KLengthOfPathEnd ) );
+
+    //Create directories which are needed by IM Logger
+    iFileSession.MkDirAll( pathTemp );
+
+    iFileSession.PrivatePath( pathTemp );
+    pathTemp.Append( KCAHistoryDataDirectory );
+
+    //Ensure, that there is no file named IMHistory beforehand. Ignore errors
+    iFileSession.Delete( pathTemp.Left( pathTemp.Length() - KLengthOfPathEnd ) );
+
+    //Create directories which are needed by IM Logger
+    iFileSession.MkDirAll( pathTemp );
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::InstanceL
+// Singleton instance of CCALoggerManager
+// -----------------------------------------------------------------------------
+//
+CCALoggerManager* CCALoggerManager::InstanceL(
+    MCALoggerMessageFactory* aMessageFactory,
+    TBool aCreate , TBool aFirstTime )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::InstanceL" );
+
+    CCALoggerManager* lm = static_cast< CCALoggerManager* > ( Dll::Tls() );
+
+    //If instance of CCALoggerManager is not created yet. Create it.
+    if ( ! lm )
+        {
+        if ( !aCreate )
+            {
+            return NULL;
+            }
+        lm = NewL();
+        }
+
+    //If aMessageFactory is passed to instance, change it.
+
+    if ( aMessageFactory )
+        {
+        lm->SetLoggerMessageFactory( aMessageFactory );
+        }
+
+    //if toc file is not yet read, try to read it.
+    if ( ( ! lm->iTocFileRead ) )
+        {
+        // here it's application booting up time..then don't show the error note..
+        // check whether this call during application boot up or not....
+
+        lm->ReadTocFileL( aFirstTime ) ;// this first time, we are reading..so we can ignore errors while reading...
+        }
+
+    return lm;
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::SuitableLogFileNameL
+// Get first possible filename (number)
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::SuitableLogFileNameL()
+    {
+    CHAT_DP_TXT( "CCALoggerManager::SuitableLogFileNameL" );
+
+    //If suitable log filename is already checked just use it.
+    if ( iWeHaveLatestFileNameNumber )
+        {
+        iLatestFileNameNumber++;
+        }
+    else	//Check next suitable log filename
+        {
+        //Sort does not help us, because numbers cannot be sorted like letters.
+        //10 is before 2 and so on. So we have to go through all files to get
+        //right ones.
+
+        // Get all the files in the directory
+        // These are named as 1, 2, 5 i.e. numbers
+        CDir* directoryFiles;
+
+        //TODOMD: get the correct path name here...
+
+        TBuf< KMaxPath > pathTemp;
+
+#ifndef RD_MULTIPLE_DRIVE
+        iFileSession.PrivatePath( pathTemp );
+#else
+        TBuf< KMaxPath > defaultDrive;
+        TBuf< KMaxPath > pathTempWithoutDrive;
+        TBuf< KMaxPath > driveAndPath;
+
+        CRepository* cenrep = CRepository::NewL( KWVSettingsCenRepUid );
+        TInt err = KErrNone;
+        TRAP( err,
+              CleanupStack::PushL( cenrep );
+              err = cenrep->Get( KIMPSCRIMDefaultMemoryDrive, defaultDrive );
+              CleanupStack::PopAndDestroy( cenrep );
+            ); // TRAP
+        cenrep = NULL;
+
+        driveAndPath.Append( defaultDrive.Left( 2 ) ); 		// append the drive root here
+        iFileSession.PrivatePath( pathTempWithoutDrive ); // copy the private path info here..
+        driveAndPath.Append( pathTempWithoutDrive ); 	// append the private path to root folder...
+        pathTemp.Copy( driveAndPath );	    				// copy this new path into tocfile...
+
+#endif
+
+        pathTemp.Append( KCAHistoryDataDirectory );
+
+        User::LeaveIfError( iFileSession.GetDir(	pathTemp,
+                                                 KEntryAttNormal,
+                                                 ESortNone,
+                                                 directoryFiles ) );
+
+        //If directoryFiles success and is files, last will be noticed and
+        //next free number chosen. If there is not files,
+        //zero is first one to go.
+        CleanupStack::PushL( directoryFiles );
+        TLex lexer;
+        TInt latestNumber;
+        for ( TInt a = 0; a < directoryFiles->Count(); ++a )
+            {
+            lexer.Assign( ( *directoryFiles )[ a ].iName );
+            if ( lexer.Val( latestNumber ) == KErrNone )
+                {
+                if ( latestNumber >= iLatestFileNameNumber )
+                    {
+                    iLatestFileNameNumber = latestNumber + 1;
+                    }
+                }
+            }
+
+        CleanupStack::PopAndDestroy( directoryFiles );
+        iWeHaveLatestFileNameNumber = ETrue;
+        }
+    }
+#ifdef RD_MULTIPLE_DRIVE
+
+// ---------------------------------------------------------------------------
+// CCALoggerManager::DriveStatus
+// ---------------------------------------------------------------------------
+//
+
+TBool CCALoggerManager::GetDriveStatusL( const TDriveNumber aDriveNumber )
+    {
+
+
+    RFs& fs = CCoeEnv::Static()->FsSession();
+    _LIT( KFat, "Fat" );
+
+    // Check if the drive is already mounted
+    TFullName fsName;
+    TInt error( fs.FileSystemName( fsName, aDriveNumber ) );
+    if ( error )
+        {
+        return EFalse;
+        }
+
+    // check if MMC already mounted
+    if ( fsName.Length() == 0 )
+        {
+        // MMC drive isnt mounted at present, so try it now....
+        error = fs.MountFileSystem( KFat, aDriveNumber );
+
+        // If it's a locked MMC and the password is already known it'll be
+        // unlocked automatically when it's mounted., otherwise the mount will
+        // return with KErrLocked.....
+        switch ( error )
+            {
+            case KErrNone:
+            case KErrLocked:
+                {
+                break;
+                }
+            default:
+                {
+                return EFalse;
+                }
+            }
+        }
+    TDriveInfo driveInfo;
+    error = fs.Drive( driveInfo, aDriveNumber );
+    if ( error )
+        {
+        return EFalse;
+        }
+
+    // MMC is in slot
+    if ( driveInfo.iMediaAtt & KMediaAttLocked )
+        {
+        return EFalse;
+        }
+
+    TVolumeInfo volumeInfo;
+    error = fs.Volume( volumeInfo, aDriveNumber );
+    if ( error )
+        {
+        return EFalse;
+        }
+
+    // If type is remote drive and aConnectionState is required
+    if ( driveInfo.iDriveAtt & KDriveAttRemote )
+        {
+        TChar driveLetter;
+        fs.DriveToChar( aDriveNumber, driveLetter );
+        // This statement migth cause leave.. to be solved
+        CRsfwMountMan* mountMgr = CRsfwMountMan::NewL( 0, NULL );
+        TRsfwMountInfo mountInfo;
+        error = mountMgr->GetMountInfo( driveLetter, mountInfo );
+        delete mountMgr;
+
+        if ( error )
+            {
+            return EFalse;
+            }
+        }
+    return ETrue;
+    }
+
+#endif
+// -----------------------------------------------------------------------------
+// CCALoggerManager::ReadTocFile
+// Read toc file for headers.
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::ReadTocFileL( TBool aNotFirstTime /*ETrue*/ )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::ReadTocFileL" );
+
+    TBuf< KMaxPath > tocFile;
+    TBuf< KMaxPath > tempTocFile;
+#ifndef RD_MULTIPLE_DRIVE
+    iFileSession.PrivatePath( tocFile );
+#else
+    TBuf< KMaxPath > defaultDrive;
+    TBuf< KMaxPath > pathTempWithoutDrive;
+    TBuf< KMaxPath > driveAndPath;
+
+    CRepository* cenrep = NULL;
+    TRAPD( err, cenrep = CRepository::NewL( KWVSettingsCenRepUid ) );
+
+    if ( err != KErrNone )
+        {
+        // creation of cenrep failed -> use default path to save the conversation
+        iFileSession.PrivatePath( driveAndPath );
+        }
+    else
+        {
+
+        TRAP( err,
+              CleanupStack::PushL( cenrep );
+              err = cenrep->Get( KIMPSCRIMDefaultMemoryDrive, defaultDrive );
+              CleanupStack::PopAndDestroy( cenrep );
+            ); // TRAP
+        cenrep = NULL;
+
+        ///////////// end of reading from cenrep
+
+        TInt driveNo = 0;
+        err = RFs::CharToDrive( defaultDrive[0], driveNo );
+        TDriveNumber driveNumber = TDriveNumber( driveNo );
+
+
+        // Check drive's media status
+        TBool isDriveOk = GetDriveStatusL( driveNumber );
+        if ( !isDriveOk )// drive is not ready yet.....
+            {
+            if ( !aNotFirstTime )
+                {
+                HBufC* prompt = StringLoader::LoadLC( R_CHAT_SAVED_NOT_AVAILABLE );
+                IMDialogUtils::DisplayErrorNoteL( *prompt );
+                CleanupStack::PopAndDestroy( prompt ); // prompt
+                }
+            return; // return from here as there is an
+            }
+
+        /////// start atppend this info to complete path ////////////////////////////////
+
+        driveAndPath.Append( defaultDrive.Left( 2 ) ); 		// append the drive root here
+        iFileSession.PrivatePath( pathTempWithoutDrive ); // copy the private path info here..
+        driveAndPath.Append( pathTempWithoutDrive ); 	// append the private path to root folder...
+        tocFile.Copy( driveAndPath );	    				// copy this new path into tocfile...
+        }
+#endif
+
+    tempTocFile.Copy( tocFile );
+    tocFile.Append( KCAHistoryTocFile );
+    tempTocFile.Append( KCAHistoryTocTempFile );
+
+    //Cannot create headers without factory
+    //This is not error. Just return to caller.
+    if ( ! iMessageFactory )
+        {
+        return;
+        }
+#ifdef RD_MULTIPLE_DRIVE
+
+    PopulateTocArrayL( iFileTocArray, tocFile, aNotFirstTime );
+    PopulateTocArrayL( iFileTempTocArray, tempTocFile, aNotFirstTime ); // we no need to show the error dialog again.
+
+#else
+    PopulateTocArrayL( iFileTocArray, tocFile );
+    PopulateTocArrayL( iFileTempTocArray, tempTocFile ); // we no need to show the error dialog again.
+
+
+#endif
+    TBool onlyTempTocFlag( EFalse );
+    if ( iFileTocArray.Count() + iFileTempTocArray.Count() == 0 )
+        {
+        iTocFileRead = ETrue;
+        return;
+        }
+    else if ( iFileTocArray.Count() == 0 )
+        {
+        onlyTempTocFlag = ETrue;
+        }
+
+    // Merge temp toc to real toc if needed.
+    TInt arrayCount( iFileTempTocArray.Count() );
+    for ( TInt b( arrayCount - 1 ); b >= 0; --b )
+        {
+        // Check if real toc have header temp is offering.
+        TInt arrayCount2( iFileTocArray.Count() );
+        TBool newOne( ETrue );
+        for ( TInt a( 0 ); a < arrayCount2 && newOne; ++a )
+            {
+            if ( iFileTempTocArray[ b ]->FilenameL().CompareC(
+                     iFileTocArray[ a ]->FilenameL() ) == 0 )
+                {
+                newOne = EFalse;
+                }
+            }
+        // If header is newOne, then add it to real toc.
+        if ( newOne )
+            {
+            User::LeaveIfError( iFileTocArray.Insert( iFileTempTocArray[ b ],
+                                                      KArrayBegin ) );
+            iFileTempTocArray.Remove( b );
+            }
+        }
+
+    //Next save the toc file without those headers which are not valid anymore.
+    //This is easily done, because only valid headers were appended to array.
+    //Just make sure, that old header information does not lose in anycase.
+    if ( !onlyTempTocFlag )
+        {
+        iFileSession.Delete( tempTocFile );
+        User::LeaveIfError( iFileSession.Rename( tocFile, tempTocFile ) );
+        }
+
+    RFileWriteStream fileWriteStream;
+    TInt error( fileWriteStream.Create(	iFileSession,
+                                        tocFile,
+                                        EFileWrite ) );
+    if ( error != KErrNone )
+        {
+        iFileSession.Delete( tocFile );
+        User::LeaveIfError( iFileSession.Rename( tempTocFile, tocFile ) );
+        User::Leave( error );
+        }
+    CleanupClosePushL( fileWriteStream );
+
+    //Write headers and if file write fails trap leave because we want to
+    //change old file back.
+    // Write the array from end to start order to the file to keep
+    // order correct (from oldest to newest).
+    TInt maxIndex = iFileTocArray.Count() - 1;
+    for ( TInt a = maxIndex; a >= 0; --a )
+        {
+        if ( CheckMemoryL( iFileTocArray[a]->MessageSizeInBytesL() ) )
+            {
+            TRAPD( err, iFileTocArray[a]->ExternalizeL( fileWriteStream ) );
+            if ( err != KErrNone )
+                {
+				CleanupStack::PopAndDestroy( 1 ); // fileWriteStream
+                iFileSession.Delete( tocFile );
+                User::LeaveIfError( iFileSession.Rename( tempTocFile, tocFile ) );
+                User::Leave( err );
+                }
+            }
+        else
+            {
+			CleanupStack::PopAndDestroy( 1 ); // fileWriteStream
+            iFileSession.Delete( tocFile );
+            User::LeaveIfError( iFileSession.Rename( tempTocFile, tocFile ) );
+            User::Leave( KErrDiskFull );
+            }
+        }
+
+    CHAT_DP( D_CHAT_LIT( " ignore %d" ), aNotFirstTime );
+
+    CleanupStack::PopAndDestroy( 1 ); // fileWriteStream
+
+    //Delete old file.
+    iFileSession.Delete( tempTocFile );
+
+    //Now toc file is read.
+    iTocFileRead = ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::WriteTocFileL
+//
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::WriteTocFileL( MCALoggerMessageHeader& aHeader,
+                                      TBool aTemporary /*= EFalse*/ )
+    {
+    // incase of multidrive, write the header into the user selected drive itself..
+    CHAT_DP_TXT( "CCALoggerManager::WriteTocFileL" );
+
+    TBuf< KMaxPath > tocFile;
+    TBuf< KMaxPath > tempTocFile;
+
+#ifndef RD_MULTIPLE_DRIVE
+    iFileSession.PrivatePath( tocFile );
+#else
+    TBuf< KMaxPath > defaultDrive;
+    TBuf< KMaxPath > pathTempWithoutDrive;
+    TBuf< KMaxPath > driveAndPath;
+
+    CRepository* cenrep = NULL;
+    TRAPD( err, cenrep = CRepository::NewL( KWVSettingsCenRepUid ) );
+
+    if ( err != KErrNone )
+        {
+        // creation of cenrep failed -> use default path to save the conversation
+        iFileSession.PrivatePath( driveAndPath );
+        }
+    else
+        {
+
+        TRAP( err,
+              CleanupStack::PushL( cenrep );
+              err = cenrep->Get( KIMPSCRIMDefaultMemoryDrive, defaultDrive );
+              CleanupStack::PopAndDestroy( cenrep );
+            ); // TRAP
+        cenrep = NULL;
+
+        /////// start atppend this info to complete path ////////////////////////////////
+        driveAndPath.Append( defaultDrive.Left( 2 ) ); // append the drive root here
+        //check whether this is in mmc card and card was protected with pwd or not
+        iFileSession.PrivatePath( pathTempWithoutDrive ); // copy the private path info here..
+        driveAndPath.Append( pathTempWithoutDrive ); // append the private path here...
+        }
+    // copy this new path into tocfile...
+    tocFile.Copy( driveAndPath );
+
+#endif
+    tempTocFile.Copy( tocFile );
+    tocFile.Append( KCAHistoryTocFile );
+    tempTocFile.Append( KCAHistoryTocTempFile );
+
+    RFileWriteStream fileStream;
+    TInt error = fileStream.Open( iFileSession, !aTemporary ? tocFile :
+                                  tempTocFile, EFileWrite );
+
+    //if file does not exist.. create it
+    if ( error == KErrNotFound )
+        {
+        User::LeaveIfError( fileStream.Create( iFileSession, !aTemporary ?
+                                               tocFile : tempTocFile, EFileWrite ) );
+        }
+    else
+        {
+        User::LeaveIfError( error );
+        }
+
+    CleanupClosePushL( fileStream );
+
+    //Seek end of file.
+    fileStream.Sink()->SeekL( RFileBuf::EWrite, EStreamEnd );
+
+    if ( CheckMemoryL( aHeader.MessageSizeInBytesL() ) )
+        {
+        aHeader.ExternalizeL( fileStream );
+        }
+    else
+        {
+        User::Leave( KErrDiskFull );
+        }
+
+    CleanupStack::PopAndDestroy( 1 ); // fileStream
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::ReadMessageFileL
+// Read messages to array
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::ReadMessageFileL(
+    RPointerArray< MCALoggerMessage >& aMessageArray,
+    MCALoggerMessageHeader& aKey )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::ReadMessageFileL" );
+
+    if ( ! iMessageFactory )
+        {
+        User::Leave( KErrNotReady );
+        }
+
+    RFileReadStream fileStream;
+    User::LeaveIfError( fileStream.Open(	iFileSession,
+                                         aKey.FilenameL(),
+                                         EFileRead ) );
+    CleanupClosePushL( fileStream );
+
+    MCALoggerMessage* newMessage;
+
+    //Go through whole stream.
+    while ( fileStream.Source()->SizeL() !=
+            fileStream.Source()->TellL( RFileBuf::ERead ).Offset() )
+        {
+        newMessage = iMessageFactory->CreateLoggerMessageL( fileStream );
+        CleanupDeletePushL( newMessage );
+        newMessage->InternalizeL( fileStream );
+        User::LeaveIfError( aMessageArray.Append( newMessage ) );
+        CleanupStack::Pop( newMessage );
+        }
+
+    CleanupStack::PopAndDestroy( 1 );	// fileStream
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::ReadInstanceL
+// Return pointer to read interface
+// -----------------------------------------------------------------------------
+//
+MCALoggerReadInterface* CCALoggerManager::ReadInstanceL(
+    MCALoggerMessageFactory* aMessageFactory, TBool aFirstTime )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::ReadInstanceL" );
+
+    CCALoggerManager* lm = InstanceL( aMessageFactory , ETrue, aFirstTime );
+
+    return lm;
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::WriteInstanceL
+// Create write interface and return it.
+// -----------------------------------------------------------------------------
+//
+MCALoggerWriteInterface* CCALoggerManager::WriteInstanceL(
+    MCALoggerMessageFactory* aMessageFactory )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::WriteInstanceL" );
+
+    CCALoggerManager* lm = InstanceL( aMessageFactory );
+
+    return CCALoggerWriter::NewL( *lm, lm->iFileSession );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::ReleaseInstanceL
+// Create write interface and return it.
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::ReleaseInstanceL()
+    {
+    CHAT_DP_TXT( "CCALoggerManager::ReleaseInstanceL" );
+
+    CCALoggerManager* lm = InstanceL( NULL );
+    delete lm;
+    lm = NULL;
+    Dll::SetTls( NULL );
+    }
+
+
+// ================= INHERITED FUNCTIONS =======================
+
+//	FROM MCALoggerWriteObserver
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::AddFileL
+// Add new file to write array
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::AddFileL( TFileRelation aFile )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::AddFile" );
+
+    CleanupDeletePushL( aFile.iFile );
+    //Removes old file to this writer from iWriteFileArray if exists.
+    //This has been done in iWriter, but after this we can be sure of it.
+    RemoveFileL( *aFile.iWriter );
+
+    CleanupStack::Pop( aFile.iFile );
+    TInt err = iWriteFileArray.Append( aFile );
+    if ( err != KErrNone )
+        {
+        delete aFile.iFile;
+        User::Leave( err );
+        }
+
+    //Write header information to temporary toc file.
+    WriteTocFileL( *aFile.iFile, ETrue );
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::RemoveFileL
+// Remove used file from write array and add it to toc.
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::RemoveFileL( MCALoggerWriteInterface& aWriter )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::RemoveFileL" );
+
+    for ( TInt a = 0; a < iWriteFileArray.Count(); ++a )
+        {
+        if ( iWriteFileArray[ a ].iWriter == &aWriter )
+            {
+            TFileRelation relation( iWriteFileArray[ a ] );
+
+            //Recorded chat version will add file to toc array.
+            User::LeaveIfError( iFileTocArray.Insert( relation.iFile,
+                                                      KArrayBegin ) );
+
+            //Both versions will remove file from write array.
+            iWriteFileArray.Remove( a );
+
+            //Trigger footer information for history header
+            relation.iFile->EndLogging();
+
+            //Write header information to toc file.
+            WriteTocFileL( *relation.iFile );
+            return;
+            }
+        }
+    }
+
+
+void CCALoggerManager::LeaveIfDiskFull( TInt aErrorCode )
+    {
+    if ( aErrorCode == KErrDiskFull )
+        {
+        User::LeaveIfError( KErrDiskFull );
+        }
+    }
+
+
+
+#ifdef RD_MULTIPLE_DRIVE
+// -----------------------------------------------------------------------------
+// CCALoggerManager::CreateNewFilenameL
+// New actual filename for new history file.
+// -----------------------------------------------------------------------------
+//
+HBufC* CCALoggerManager::CreateNewFilenameMDL()
+    {
+    CHAT_DP_TXT( "CCALoggerManager::CreateNewFilenameMDL" );
+
+    ///////// read settings from cenrep ///////////////
+
+    TBuf< KMaxPath > defaultDrive;
+    TBuf< KMaxPath > pathTempWithoutDrive;
+    TBuf< KMaxPath > driveAndPath;
+
+    CRepository* cenrep = NULL;
+    TRAPD( err, cenrep = CRepository::NewL( KWVSettingsCenRepUid ) );
+
+    if ( err == KErrNone )
+        {
+        // creation of cenrep OK
+        CleanupStack::PushL( cenrep );
+        err = cenrep->Get( KIMPSCRIMDefaultMemoryDrive, defaultDrive );
+        if ( err != KErrNone )
+            {
+            CleanupStack::PopAndDestroy( cenrep );
+            cenrep = NULL;
+            User::Leave( err );
+            }///////////// end of reading from cenrep
+
+        // we need to check whether do we have access rights of this root drive or not..
+        // 1. Check whether this is write protected or not
+
+        //2. check whether this is in mmc card and card was protected with pwd or not
+
+        TInt driveNo = 0;
+        err = RFs::CharToDrive( defaultDrive[0], driveNo );
+        TDriveNumber driveNumber = TDriveNumber( driveNo );
+
+        driveAndPath.Append( defaultDrive.Left( 2 ) ); // append the drive root here
+        CleanupStack::PopAndDestroy( cenrep );
+        cenrep = NULL;
+
+        // added LeaveIfDiskFull() function call
+        LeaveIfDiskFull( iFileSession.CreatePrivatePath( driveNumber ) ); // create the private default drive info here...
+
+        iFileSession.PrivatePath( pathTempWithoutDrive ); // copy the private path info here..
+
+        driveAndPath.Append( pathTempWithoutDrive ); // append the private path here...
+        driveAndPath.Append( KCAHistoryDirectory );// apend imhistory/data folder here...
+
+        // now check whether this path was created or not.
+        // if not create the new path now.....
+
+        // Ensure, that there is no file named IMHistory beforehand.
+        iFileSession.Delete( driveAndPath.Left( driveAndPath.Length() - KLengthOfPathEnd ) );
+
+        // Create directories which are needed by IM Logger
+        // added LeaveIfDiskFull() function call
+        LeaveIfDiskFull( iFileSession.MkDirAll( driveAndPath ) ); // create IMHistory directory here...
+        driveAndPath.Append( KCADataDirectory );
+
+        // Ensure, that there is no file named IMHistory beforehand.
+        iFileSession.Delete( driveAndPath.Left( driveAndPath.Length() - KLengthOfPathEnd ) );
+
+        // Create directories which are needed by IM Logger
+        // added LeaveIfDiskFull() function call
+        LeaveIfDiskFull( iFileSession.MkDirAll( driveAndPath ) );// create data directory here...
+
+
+        }// end of cenrep error
+
+
+
+    HBufC* logFile = HBufC::NewL( KMaxNumberLength + driveAndPath.Length() );
+
+    CleanupStack::PushL( logFile );
+
+    SuitableLogFileNameL();
+
+    TPtr ptrPath( logFile->Des() );
+    ptrPath.Append( driveAndPath );
+    ptrPath.AppendNum( iLatestFileNameNumber );
+
+    CleanupStack::Pop( logFile );
+
+    return logFile;
+
+    }
+
+#endif
+
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::CreateNewFilenameL
+// New actual filename for new history file.
+// -----------------------------------------------------------------------------
+//
+HBufC* CCALoggerManager::CreateNewFilenameL()
+    {
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    CHAT_DP_TXT( "CCALoggerManager::CreateNewFilenameL" );
+
+    TBuf< KMaxPath > pathTemp;
+    iFileSession.PrivatePath( pathTemp );
+    pathTemp.Append( KCAHistoryDataDirectory );
+
+    HBufC* logFile = HBufC::NewL( KMaxNumberLength + pathTemp.Length() );
+
+    CleanupStack::PushL( logFile );
+
+    SuitableLogFileNameL();
+
+    TPtr ptrPath( logFile->Des() );
+    ptrPath.Append( pathTemp );
+    ptrPath.AppendNum( iLatestFileNameNumber );
+
+    CleanupStack::Pop( logFile );
+
+    return logFile;
+#else
+    return CreateNewFilenameMDL();
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::CheckMemoryL
+// New actual filename for new history file.
+// -----------------------------------------------------------------------------
+//
+TBool CCALoggerManager::CheckMemoryL( TInt aMemoryRequired )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::CheckMemory" );
+
+#ifndef RD_MULTIPLE_DRIVE
+    if ( ! SysUtil::FFSSpaceBelowCriticalLevelL(	&iFileSession,
+                                                 aMemoryRequired ) )
+        {
+        return ETrue;
+        }
+    return EFalse;
+
+#else
+    TBuf< KMaxPath > defaultDrive;
+
+    CRepository* cenrep = CRepository::NewL( KWVSettingsCenRepUid );
+
+    TInt err = cenrep->Get( KIMPSCRIMDefaultMemoryDrive, defaultDrive );
+
+    delete cenrep;
+    cenrep = NULL;
+    if ( err != KErrNone )
+        {
+        User::Leave( err );
+        }///////////// end of reading from cenrep
+    TInt driveNo = 0;
+    err = RFs::CharToDrive( defaultDrive[0], driveNo );
+    if ( err != KErrNone )
+        {
+        User::Leave( err );
+        }
+
+    TDriveNumber driveNumber = TDriveNumber( driveNo );
+
+    if ( ! SysUtil::DiskSpaceBelowCriticalLevelL( 	&iFileSession,
+                                                   aMemoryRequired, driveNumber ) )
+        {
+        return ETrue;
+        }
+
+    return EFalse;
+
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::GetLoggerMessageHeaderArray
+// Pass pointer to toc array to client.
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::GetLoggerMessageHeaderArray(
+    RPointerArray< MCALoggerMessageHeader >*& aHeaderArray )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::GetLoggerMessageHeaderArray" );
+
+    aHeaderArray = &iFileTocArray;
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::CreateLoggerMessagesL
+// Check that file is found from toc array
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::CreateLoggerMessagesL(
+    RPointerArray< MCALoggerMessage >& aMessageArray,
+    MCALoggerMessageHeader& aKey )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::CreateLoggerMessagesL" );
+
+    for ( TInt a = 0; a < iFileTocArray.Count(); ++a )
+        {
+        if ( iFileTocArray[a] == &aKey )
+            {
+            //Read the file
+            ReadMessageFileL( aMessageArray, aKey );
+            return;
+            }
+        }
+
+    //if header is missing
+    User::Leave( KErrNotFound );
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::DeleteHistoryFileL
+// If header is in toc array. Remove and delete it.
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::DeleteHistoryFileL( MCALoggerMessageHeader& aKey )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::DeleteHistoryFileL" );
+
+    for ( TInt a = 0; a < iFileTocArray.Count(); ++a )
+        {
+        if ( iFileTocArray[a] == &aKey )
+            {
+            //Remove header from array
+            iFileTocArray.Remove( a );
+
+            //delete file from storage space
+            iFileSession.Delete( aKey.FilenameL() );
+
+
+            // Get the toc file path string
+            TBuf< KMaxPath > tocFile;
+            TBuf< KMaxPath > tempTocFile;
+
+#ifndef RD_MULTIPLE_DRIVE
+            iFileSession.PrivatePath( tocFile );
+#else
+            TBuf< KMaxPath > defaultDrive;
+            TBuf< KMaxPath > pathTempWithoutDrive;
+            TBuf< KMaxPath > driveAndPath;
+
+            CRepository* cenrep = NULL;
+            TRAPD( err, cenrep = CRepository::NewL( KWVSettingsCenRepUid ) );
+
+            if ( err != KErrNone )
+                {
+                // creation of cenrep failed -> use default path to save the conversation
+                iFileSession.PrivatePath( driveAndPath );
+                }
+            else
+                {
+
+                TRAP( err,
+                      CleanupStack::PushL( cenrep );
+                      err = cenrep->Get( KIMPSCRIMDefaultMemoryDrive, defaultDrive );
+                      CleanupStack::PopAndDestroy( cenrep );
+                    ); // TRAP
+                cenrep = NULL;
+
+                /////// start atppend this info to complete path ////////////////////////////////
+                driveAndPath.Append( defaultDrive.Left( 2 ) ); // append the drive root here
+                //check whether this is in mmc card and card was protected with pwd or not
+                iFileSession.PrivatePath( pathTempWithoutDrive ); // copy the private path info here..
+                driveAndPath.Append( pathTempWithoutDrive ); // append the private path here...
+                }
+            // copy this new path into tocfile...
+            tocFile.Copy( driveAndPath );
+
+#endif
+
+            tempTocFile.Copy( tocFile );
+            tocFile.Append( KCAHistoryTocFile );
+            tempTocFile.Append( KCAHistoryTocTempFile );
+
+            User::LeaveIfError( iFileSession.Rename( tocFile, tempTocFile ) );
+
+            // Filewritestream
+            RFileWriteStream fileWriteStream;
+            TInt error( fileWriteStream.Create(	iFileSession,
+                                                tocFile,
+                                                EFileWrite ) );
+            if ( error != KErrNone )
+                {
+                iFileSession.Delete( tocFile );
+                User::LeaveIfError( iFileSession.Rename( tempTocFile, tocFile ) );
+                User::Leave( error );
+                }
+            CleanupClosePushL( fileWriteStream );
+
+            //Write headers and if file write fails trap leave because we want to
+            //change old file back.
+            // Write the array from end to start order to the file to keep
+            // order correct (from oldest to newest).
+            TInt maxIndex = iFileTocArray.Count() - 1;
+            for ( TInt a = maxIndex; a >= 0; --a )
+                {
+                if ( CheckMemoryL( iFileTocArray[a]->MessageSizeInBytesL() ) )
+                    {
+                    TRAPD( err, iFileTocArray[a]->ExternalizeL( fileWriteStream ) );
+                    if ( err != KErrNone )
+                        {
+                        iFileSession.Delete( tocFile );
+                        User::LeaveIfError( iFileSession.Rename( tempTocFile, tocFile ) );
+                        User::Leave( err );
+                        }
+                    }
+                else
+                    {
+                    iFileSession.Delete( tocFile );
+                    User::LeaveIfError( iFileSession.Rename( tempTocFile, tocFile ) );
+                    User::Leave( KErrDiskFull );
+                    }
+                }
+
+            // Delete the temp toc file
+            iFileSession.Delete( tempTocFile );
+
+            CleanupStack::PopAndDestroy( 1 ); // fileWriteStream
+
+
+            //release memory from key.
+            delete &aKey;
+            return;
+            }
+        }
+
+    //if header is missing
+    User::Leave( KErrNotFound );
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::SetLoggerMessageFactory
+// Set message factory
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::SetLoggerMessageFactory(
+    MCALoggerMessageFactory* aMessageFactory )
+    {
+    CHAT_DP_TXT( "CCALoggerManager::SetLoggerMessageFactory" );
+
+    iMessageFactory = aMessageFactory;
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::CheckIfHeaderExists
+// Checks if header already exists in array.
+// -----------------------------------------------------------------------------
+//
+TBool CCALoggerManager::CheckIfHeaderExistsL( MCALoggerMessageHeader& aHeader )
+    {
+    for ( TInt a = 0; a < iFileTocArray.Count(); ++a )
+        {
+        if ( aHeader.FilenameL().CompareC( iFileTocArray[ a ]->FilenameL() )
+             == 0 )
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CCALoggerManager::PopulateTocArray
+//
+// -----------------------------------------------------------------------------
+//
+void CCALoggerManager::PopulateTocArrayL( RPointerArray< MCALoggerMessageHeader >& aArray,
+                                          const TDesC& aTocFilename
+#ifdef RD_MULTIPLE_DRIVE
+                                          , TBool aNotFirstTime /*ETrue*/
+#endif
+                                        )
+    {
+    RFileReadStream fileReadStream;
+    TInt error = fileReadStream.Open(	iFileSession,
+                                      aTocFilename,
+                                      EFileWrite );
+    //if file does not exists, there is no headers. just return from method
+#ifndef RD_MULTIPLE_DRIVE
+    if ( error == KErrNotFound )
+        {
+        return;
+        }
+    else
+        {
+        User::LeaveIfError( error );
+        }
+#else
+    if ( aNotFirstTime )
+        {
+        if ( error )
+            {
+            return;
+            }
+        }
+    else
+        {
+        if ( error == KErrNotFound || error == KErrPathNotFound )
+            {
+            return;
+            }
+        else
+            {
+            User::LeaveIfError( error );
+            }
+        }
+#endif
+
+    CleanupClosePushL( fileReadStream );
+
+    MCALoggerMessageHeader* newHeader;
+
+    //Go through whole stream.
+    while ( fileReadStream.Source()->SizeL() !=
+            fileReadStream.Source()->TellL( RFileBuf::ERead ).Offset() )
+        {
+        newHeader = iMessageFactory->CreateLoggerMessageHeaderL();
+        CleanupDeletePushL( newHeader );
+        newHeader->InternalizeL( fileReadStream );
+
+        //if file for header exists, append it to iFileTocArray.
+        if ( BaflUtils::FileExists( iFileSession, newHeader->FilenameL() ) &&
+             !CheckIfHeaderExistsL( *newHeader ) )
+            {
+            User::LeaveIfError( aArray.Insert( newHeader, KArrayBegin ) );
+            CleanupStack::Pop( newHeader );
+            }
+        else
+            {
+            CleanupStack::PopAndDestroy( newHeader );
+            }
+        }
+
+    CleanupStack::PopAndDestroy( 1 ); // fileReadStream
+    }
+
+//end of file