diff -r 000000000000 -r 094583676ce7 wvuing/wvlogger/Src/CCALoggerManager.cpp --- /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 +#include +#include + +#include "CCALoggerManager.h" +#include "CCALoggerWriter.h" +#include "MCALoggerMessageHeader.h" +#include "MCALoggerMessageFactory.h" +#include "MCALoggerMessage.h" + +#ifdef RD_MULTIPLE_DRIVE +#include +#include +#include +#include +#include +#include +#include +#include +#include // StringLoader +#include "IMDialogUtils.h" +#include +#include +#endif +#include + +//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