/*
* Copyright (c) 2002-2007 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:  Default Epoc-style content handler.
*
*/


#include <bautils.h>                // For NearestLanguageFile(..)
#include <eikdoc.h>                 // CEikDocument
#include <AknQueryDialog.h>         // CAknQueryDialog
#include <StringLoader.h>           // For loading resource strings
#include <stringresourcereader.h>   // CStringResourceReader
#include <sysutil.h>                // For FFSSpaceBelowCriticalLevelL(..)
#include <uri16.h>                  // For url handling.

#include <avkon.rsg>                // Avkon ids
#include <documenthandlerui.rsg>    // Resource ids

#include "DocDefaultHandler.h"      // Class decration
#include "DocSaver.h"               // Saver util
#include "DocConstants.h"           // Documenthandler constants
#include "DocResourceFile.h"        // CDocResourceFile

#include <AiwGenericParam.h>        // Generic parameters

#ifdef RD_MULTIPLE_DRIVE
#include <CAknMemorySelectionDialogMultiDrive.h>
#include <driveinfo.h>      //DriveInfo
#include <AknCommonDialogsDynMem.h>
#include <coemain.h>
#include <rsfwmountman.h>
#else
#include "CAknMemorySelectionDialog.h" // CAknMemorySelectionDialog
#endif

#include "pathinfo.h"               // PathInfo
#include <featmgr.h>                // FeatureManager

#ifdef RD_CONTENTNOTIFICATION
#include <contentnotification.hrh>
#include <contentcreatedevent.h>
#include <contentnotification.h>
#endif

#ifdef ENABLE_DRM
#include <caf/caf.h>
#include <Oma2Agent.h>
#include <DcfEntry.h>               // CDcfEntry 
#include <DcfRep.h>                 // CDcfRep
#endif 

#ifdef __KEEP_DRM_CONTENT_ON_PHONE
#include <oem/distributablechecker.h>
#endif

#include <f32file.h>

using namespace ContentAccess;
_LIT( KFSName, "Fat" );

// ================= LOCAL FUNCTIONS ========================
LOCAL_C inline TBool NeedsToReplaceDcf2Extension( TDes& aFileName )
    {
    TParsePtrC ptr( aFileName );
    if ( ptr.ExtPresent() )
        {
        TPtrC ext( ptr.Ext() );
        if( !KOma2DcfExtensionAudio().CompareF( ext ) ||
            !KOma2DcfExtensionVideo().CompareF( ext ) ||
            !KOma2DcfExtension().CompareF( ext ) )
            {
            // no need to replace extension.
            return EFalse;
            }
        }
    return ETrue;
    }

// ================= MEMBER FUNCTIONS =======================

// C++ default constructor can NOT contain any code, that
// might leave.
//
CDocDefaultHandler::CDocDefaultHandler(    
    const TDataType& aDataType,
    const TUid& aUid,
    CDocumentHandler* aDocDispatcher,
    TDocServiceMode aServiceMode ) : 
        iApaLs( aDocDispatcher->ApaLs() ),
        iDataType( aDataType ),
        iDocDispatcher( aDocDispatcher ),
        iFileManager( NULL ),
        iSavedAsTemp( EFalse ),
        iServiceMode( aServiceMode ),
        iStatus( KErrNone ),
        iUid( aUid ),
        iOpenService( NULL ),
        iMMCSaveAllowed ( ETrue )
    {
    }
    
// Destructor  
//
CDocDefaultHandler::~CDocDefaultHandler()
    {
    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::~CDocDefaultHandler"));
    #endif      
      
    iFs.Close();        // Close sessions
    
    if ( iOpenService )
    {
        delete iOpenService;
    }                            

    delete iFileManager; // Delete members  
    delete iAiwParams;
    delete iOutAiwParams;
    delete iMimeExtensions;
    delete iExtensions;
    delete iIdle;
    }

// ---------------------------------------------------------
// Two-phased constructor. 
// ---------------------------------------------------------
//
CDocDefaultHandler* CDocDefaultHandler::NewL(
    const TDataType& aDataType,
    const TUid& aUid,
    CDocumentHandler* aDocDispatcher,
    TDocServiceMode aServiceMode )
    {
    CDocDefaultHandler * self = NewLC( aDataType, aUid, 
                                       aDocDispatcher, aServiceMode );
    CleanupStack::Pop();
    return self;
    }
    
// ---------------------------------------------------------
// Two-phased constructor. Leaves the contructed instance in to the 
// clean up stack.
// ---------------------------------------------------------
//
CDocDefaultHandler* CDocDefaultHandler::NewLC(
    const TDataType& aDataType,
    const TUid& aUid,
    CDocumentHandler* aDocDispatcher,
    TDocServiceMode aServiceMode )
    {
    CDocDefaultHandler* self = 
        new ( ELeave ) CDocDefaultHandler( aDataType, aUid, 
                                           aDocDispatcher, aServiceMode );
    CleanupStack::PushL( self );
    self->BaseConstructL();
    return self;
    }

// ---------------------------------------------------------
// Epoc contructor
// ---------------------------------------------------------
//  
void CDocDefaultHandler::BaseConstructL()
    {       
    User::LeaveIfError( iFs.Connect() ); // Connect to servers                      
    iFileManager = CFileMan::NewL( iFs );// Construct a filemanager   
    PopulateAppInfo();    
    }

// ---------------------------------------------------------
// CDocDefaultHandler::SaveTempFileL()
// Save the content to the correct directory. 
// This method is used from CDocumentHandler::SaveTempFileL() 
// and CDocumentHandler::SaveL()
// ---------------------------------------------------------
//
TInt CDocDefaultHandler::SaveTempFileL( 
    const TDesC8& aContent, 
    const TUint aAttr,
    TDes& aFileName)
    {
    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::SaveTempFileL(aContent, aAttr, aFileName) Called"));
    #endif 

    TInt error = KErrNone;              // Error code

    if ( aContent.Size() == 0 )         // Check if there is anything to save.
        {
        return SetAndReturnStatus( KNullContent );  
        }

    error = SaveChecksL(aContent);
    
    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::SaveTempFileL: error=%d after filename checks."), error);
    #endif 
    if ( error == KErrNone )
        {              
        #ifdef _DEBUG        
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::SaveTempFileL: Trying to save the file..."));
        #endif 
        iFs.MkDirAll( iDestFile );
        
        RFile tempfile;
        User::LeaveIfError( tempfile.Replace( iFs, iDestFile, EFileShareAny | EFileWrite) );   
        
        HBufC* waitNoteText = HBufC::NewLC( KDocWaitNoteMaxLen );
        TPtr waitNoteTextPtr = waitNoteText->Des();  
        WaitNoteTextL( waitNoteTextPtr );              
        
        CDocAsyncSaver* asyncSaver = CDocAsyncSaver::NewLC();
        AddResourcesL();
        asyncSaver->WriteToFileL(
            aContent, 
            tempfile, 
            waitNoteTextPtr );
        RemoveResources();
        User::LeaveIfError( asyncSaver->Status().Int() );
        CleanupStack::PopAndDestroy( 2 ); // asyncSaver, waitNoteTextPtr

        User::LeaveIfError( tempfile.SetAtt( aAttr, 0 ) );
        tempfile.Close();
        
        // Put filename to aFileName
        aFileName.Copy(iDestFile);

        #ifdef _DEBUG        
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::SaveTempFileL: File %S saved and closed!"), &iDestFile);
        #endif 
        }

    return SetAndReturnStatus( error );

    }

// ---------------------------------------------------------
// CDocDefaultHandler::SaveChecksL()
// This method is called from SaveTempFileL.
// Check disk space for file and generate filename.
// ---------------------------------------------------------
//
TInt CDocDefaultHandler::SaveChecksL(const TDesC8& aContent)
    {
    TInt error = KErrNone;   
    if (GenerateFileNameL( iUid, iDestFile, iDataType, aContent.Length() ) == KErrCancel)
        {
        return KUserCancel;
        }
        
    CheckDiskspaceL( aContent.Size() ); // Leave if not enough space to save.
    TBool done = EFalse;                // Try saving until done    
    do
        {
        TBool valid  = iFs.IsValidName( iDestFile );
        TBool exists = BaflUtils::FileExists( iFs, iDestFile );

        #ifdef _DEBUG        
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::SaveChecksL: Filename valid=%d"), valid);
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::SaveChecksL: Filename exists=%d"), exists);
        #endif 

        // If filename allready exists, generate new name without asking user 
        if ( exists || !valid )
            {
            GenerateTempFileNameL( iDestFile ,MaxNameLen() );
            }
        else
            {
            if ( error == KErrNone )
                {
                done = ETrue;
                }
            else
                {
                User::Leave( SetAndReturnStatus( error ) );
                }
            } // else
        }
    while ( !done ); 
    
    // If file is saved to temp place, DocumentHandler is responsible of deleting this file.
    if ( iSavedAsTemp ) 
        {
        iDocDispatcher->SetTempFile(iDestFile);
        }

    return error;
    }

// ---------------------------------------------------------    
// CDocDefaultHandler::CopyChecksAndQueriesL()   
// This method is called from CopyOrMoveL and CopyHandleL. 
// Check disk space for file, generate filename and
// and show save as query to user.
// ---------------------------------------------------------    
//
TInt CDocDefaultHandler::CopyChecksAndQueriesL(TInt aDataSize)
    {
    TInt error = KErrNone;      // Error code
    
    #ifdef _DEBUG      
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CopyChecksAndQueriesL: Enter, aDataSize = %d"), aDataSize);
    #endif
    
    if (GenerateFileNameL( iUid, iDestFile, iDataType, aDataSize) == KErrCancel)
        {
        return KUserCancel;
        }
    CheckDiskspaceL( aDataSize ); // Leave if not enough space to save.
    
    // Make destination directories
    error = iFs.MkDirAll( iDestFile );
    if ( error != KErrAlreadyExists && error != KErrNone )
        {
        User::Leave( error );   // Something unexpected happend
        }
    TBool done = EFalse;        // Try until done    
    do 
        {
        TBool valid  = iFs.IsValidName( iDestFile );
        TBool exists = BaflUtils::FileExists( iFs, iDestFile );

        #ifdef _DEBUG      
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CopyChecksAndQueriesL: Filename = %S"), &iDestFile);
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CopyChecksAndQueriesL: Filename valid=%d"), valid);
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CopyChecksAndQueriesL: Filename exists=%d"), exists);
        #endif 

        // If filename allready exists, generate new name without asking 
        // user in case of SilentMove
        if ( (DocOperation() == EDocSilentMove) &&
             (exists || !valid) )
            {
            GenerateTempFileNameL( iDestFile ,MaxNameLen() );
            }
        else if ( !valid || (exists && !iSavedAsTemp) )
            {
            switch ( SaveAsQueryL( iDestFile ) )
                {
                case EDocFileCancelWrite:
                    done = ETrue;  
                    iDestFile.Zero();
                    error = KUserCancel;
                    HandleServerAppExit(0);
                    break;
                case EDocFileOverWrite:
                    done = ETrue;
                    error = KErrNone;
                    break;
                case EDocFileRenameNew:  
                    CheckFileNameExtensionL( iDestFile, iDataType );
                    break;
                default:
                    User::Leave( SetAndReturnStatus( KErrUnknown ) );
                } // switch
            } // if
        else  // if
            {
             done = ETrue;
             error = KErrNone;
            }
        } while ( !done );// while
    
    // If file is saved to temp place, DocumentHandler is responsible of deleting this file.
    if ( iSavedAsTemp ) 
        {
        iDocDispatcher->SetTempFile(iDestFile);
        }
        
    #ifdef _DEBUG      
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CopyChecksAndQueriesL: Finished, error = %d"), error);
    #endif
        
    return error;
    }

// ---------------------------------------------------------    
// CDocDefaultHandler::CopyOrMoveL()    
// Copy/Move file to the correct directory. DocOperation() 
// tells what we do (copy/move/silentmove)
// --------------------------------------------------------- 
//   
TInt CDocDefaultHandler::CopyOrMoveL( const TUint aAttr )
    {
    TInt error = KErrNone;      // Error code
    TEntry fileEntry;           // File entry
    
    IsMMCSaveAllowedL(iSourceFile);
    
    User::LeaveIfError( iFs.Entry( iSourceFile, fileEntry ) );

    error = CopyChecksAndQueriesL(fileEntry.iSize);

    if ( error == KErrNone )
        {             
        HBufC* waitNoteText = HBufC::NewLC( KDocWaitNoteMaxLen );
        TPtr waitNoteTextPtr = waitNoteText->Des();  
      
        CDocAsyncSaver* asyncSaver = CDocAsyncSaver::NewLC();
		if (DocOperation() == EDocSilentMove)    
            {
            asyncSaver->MoveFileL(
                iFileManager,
                iSourceFile, 
                iDestFile, 
                ETrue,                 
                waitNoteTextPtr,
                ETrue );
            }
		else 
			{
			WaitNoteTextL( waitNoteTextPtr );                
			// This function is called either from MoveL or CopyL or SilentMoveL
			if (DocOperation() == EDocMove)
    			{
           	 	AddResourcesL();
           	 	asyncSaver->MoveFileL(
           		   iFileManager,
           	 	   iSourceFile, 
       			   iDestFile, 
       			   ETrue,                
   		    	   waitNoteTextPtr,
          	 	   EFalse );
           	 	RemoveResources();
    			}
   		 	else
   		 		{
   		 		AddResourcesL();
            	asyncSaver->CopyFileL(
       		 		iFileManager,
       		 		iSourceFile, 
       		 		iDestFile, 
           			ETrue,                 
           	 		waitNoteTextPtr );
           		 RemoveResources();
           		 }
			}
    
        error = asyncSaver->Status().Int();   
        User::LeaveIfError( error );
        User::LeaveIfError( iFileManager->Attribs( iDestFile, aAttr, 0, TTime( 0 ), 0 ) );
        if(asyncSaver->ShowDialog() && IsConfNoteAllowed())
            {
            HBufC* confNoteText = HBufC::NewLC( KDocConfNoteMaxLen );
            TPtr confNoteTextPtr = confNoteText->Des();  
            ConfirmationNoteTextL( confNoteTextPtr );  
            CDocSaver::ConfNoteL( confNoteTextPtr, ETrue );
            CleanupStack::PopAndDestroy( 1 ); // confNoteTextPtr
            }
        
        CleanupStack::PopAndDestroy( 2 ); // asyncSaver, waitNoteTextPtr
          
        // Notify MediaGallery that its content may have been changed
        TRAP_IGNORE(UpdateMediaGalleryIfNeededL());
    
        // Notify DCFRepository about new file
        // DcfRepository leaves if file is not-DRM file, so this call needs to be TRAPPED
        TRAP_IGNORE(UpdateDCFRepositoryL());
        }

    return SetAndReturnStatus( error );
    }
    
// ---------------------------------------------------------    
// CDocDefaultHandler::CopyHandleL()    
// Copy file to the correct directory. 
// --------------------------------------------------------- 
//   
TInt CDocDefaultHandler::CopyHandleL( const RFile& aSourceFile, const TUint aAttr )
    {
    TInt error = KErrNone;      // Error code    
    TInt fileSize;
    
    IsMMCSaveAllowedL(aSourceFile);
    
    User::LeaveIfError( aSourceFile.Size(fileSize) );

    error = CopyChecksAndQueriesL(fileSize);

    if ( error == KErrNone )
        {
        HBufC* waitNoteText = HBufC::NewLC( KDocWaitNoteMaxLen );
        TPtr waitNoteTextPtr = waitNoteText->Des();  
        WaitNoteTextL( waitNoteTextPtr );              

        CDocAsyncSaver* asyncSaver = CDocAsyncSaver::NewLC();

        AddResourcesL();
        asyncSaver->CopyFileL(
            iFileManager, 
            aSourceFile, 
            iDestFile, 
            ETrue, 
            waitNoteTextPtr );
        RemoveResources();

        error = asyncSaver->Status().Int();   
        User::LeaveIfError( error );
        User::LeaveIfError( iFileManager->Attribs( iDestFile, aAttr, 0, TTime( 0 ), 0 ) );       
        if(asyncSaver->ShowDialog() && IsConfNoteAllowed())
            {
            HBufC* confNoteText = HBufC::NewLC( KDocConfNoteMaxLen );
            TPtr confNoteTextPtr = confNoteText->Des();  
            ConfirmationNoteTextL( confNoteTextPtr );
            CDocSaver::ConfNoteL( confNoteTextPtr, ETrue );
            CleanupStack::PopAndDestroy( 1 ); // confNoteTextPtr
            }
        
        CleanupStack::PopAndDestroy( 2 ); // asyncSaver, waitNoteTextPtr
        
        // Notify MediaGallery that its content may have been changed
        TRAP_IGNORE(UpdateMediaGalleryIfNeededL());
    
        // Notify DCFRepository about new file
        // DcfRepository leaves if file is not-DRM file, so this call needs to be TRAPPED
        TRAP_IGNORE(UpdateDCFRepositoryL());
        }

    return SetAndReturnStatus( error );
    }

// ---------------------------------------------------------
// CDocDefaultHandler::SetSrcFileName()
// Check the name and sets iSourceFile if ok.
// ---------------------------------------------------------
//
TInt CDocDefaultHandler::SetSrcFileName( const TDesC& aFileName )
    {
    __ASSERT_DEBUG( 
        aFileName.Length() <= KMaxFileName,
        User::Panic( _L( "DocDefaultHandler" ), KErrBadName ) );

    if ( !iFs.IsValidName( aFileName ) )
        return SetAndReturnStatus( KErrBadName );
        
    iSourceFile = aFileName;
    return SetAndReturnStatus( KErrNone );
    }

// ---------------------------------------------------------
// CDocDefaultHandler::SetDestName()
// Check the name and set iDestFile.
// ---------------------------------------------------------
//    
TInt CDocDefaultHandler::SetDestName( const TDesC &aFilename )
    {
    TParse parse;

    parse.Set( aFilename, NULL, NULL );
    // drop possible drive letter and path.
    iDestFile.Copy( parse.NameAndExt() );        

    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::SetDestName : iDestFile=%S"), &iDestFile);
    #endif 

    return SetAndReturnStatus( KErrNone );
    }

// ---------------------------------------------------------
// CDocDefaultHandler::SetRootPath()
// Set root path of File which should be used.
// ---------------------------------------------------------
//    
TInt CDocDefaultHandler::SetRootPath( const TDesC& aRootPath )
    {
    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::SetRootPath : aRootPath=%S"), &aRootPath);
    #endif  
   
    TChar rootChar = aRootPath[0];
    TDriveList driveList; 
    TBool invalidRootPath = ETrue;

    if( iFs.DriveList( driveList ) == KErrNone )
        {
        for ( TInt i = 0; i < driveList.Length(); i++ )
            {
            TDriveInfo info;  
            if ( iFs.Drive( info, i ) == KErrNone &&
                 info.iType != EMediaNotPresent )
                {
                TChar driveChar;
                RFs::DriveToChar( i, driveChar );
                if ( driveChar == rootChar)
                    {
                	invalidRootPath = EFalse;
                	break;
                    }  
                }
            }
        }
      
    if( !invalidRootPath )
        {
    	iRootPath.Copy( aRootPath ); 
    	return SetAndReturnStatus( KErrNone );
    	}
    else
        {
    	return KNotInitialized; 
    	}
    }

// ---------------------------------------------------------
// CDocDefaultHandler::AddToParamListL()
// Add parameters (gives as parameter) to iAiwParams
// ---------------------------------------------------------
//    
void CDocDefaultHandler::AddToParamListL(const CAiwGenericParamList& aParams)
    {
    // Clear previous parameters.
    if (!iAiwParams)
        {
        iAiwParams = CAiwGenericParamList::NewL();
        }
    iAiwParams->AppendL( aParams ); 
    }

// ---------------------------------------------------------
// CDocDefaultHandler::OutputParamsL()
// Is this method needed?
// ---------------------------------------------------------
//    
const CAiwGenericParamList* CDocDefaultHandler::OutputParamsL()
    { 
/* TODO: How to get outputparams, or is these even needed?    
    if (iStore && iDictionary)
        {       
        delete iOutAiwParams;
        iOutAiwParams = NULL;
        iOutAiwParams = CAiwGenericParamList::NewL();

        RStoreReadStream stream;
        TStreamId id = iDictionary->At(KUidEmbedOutputStream);

        stream.OpenLC(*iStore, id);
        iOutAiwParams->InternalizeL(stream);
        CleanupStack::PopAndDestroy();  // stream
        }
*/
    return iOutAiwParams;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::SetDataType()
// Set the data type (iDataType)
// ---------------------------------------------------------
//    
void CDocDefaultHandler::SetDataType( const TDataType& aDataType )
    {
    iDataType = aDataType;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::OpenFileEmbeddedL()
// Calls Avkon Open File Service with file handle which should
// be opened. Also UID of application which should be launched 
// and iAiwParams is given as parameter. 
// ---------------------------------------------------------
//        
TInt CDocDefaultHandler::OpenFileEmbeddedL(RFile& aFileHandle )
    {
    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::OpenFileEmbeddedL(aFileHandle) Called"));
    #endif 

    if ( iOpenService )
        {
        delete iOpenService;
        iOpenService = NULL;
        }
    
    iOpenService = CAknOpenFileService::NewL(iUid, aFileHandle, this, iAiwParams);

    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::OpenFileEmbeddedL: Returns")) ;
    #endif 
    return SetAndReturnStatus( KErrNone );  // If we're still here, everything is ok.
    } 
    
// ---------------------------------------------------------
// CDocDefaultHandler::OpenFileL( )
// Calls RApaLsSession::StartDocument with file handle which 
// should be launched on standalone. 
// ---------------------------------------------------------
//        
TInt CDocDefaultHandler::OpenFileL(RFile& aFileHandle )
    {
    TThreadId id;

    User::LeaveIfError( iApaLs->StartDocument( aFileHandle, iDataType, id ) );

    // If client try to open embedded, but handler application supports only 
    // stand-alone open, then we need to notify exit instantly to avoid problems.
    if (DocOperation() == EDocOpenFileEmb)
        {
        if ( !iIdle )
            {
            iIdle = CIdle::NewL( CActive::EPriorityIdle );
            }

        if ( !iIdle->IsActive() )
            {
            iIdle->Start( TCallBack( IdleNotifyServerAppExit, this ) );
            }
        }
    
    return SetAndReturnStatus( KErrNone );  // If we're still here, everything is ok.
    }

// ---------------------------------------------------------
// CDocDefaultHandler::IdleNotifyServerAppExit( )
// Used for notifying server app exit with CIdle when
// OpenFileEmbedded operation has actually opened stand-alone.
// ---------------------------------------------------------
//
TInt CDocDefaultHandler::IdleNotifyServerAppExit( TAny* aParam )
    {
    static_cast<CDocDefaultHandler*>( aParam )->HandleServerAppExit(0);
    return EFalse;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::HandleServerAppExit()
// Delegates the exit signal to the listener registered for
// DocumentHandler. Tries to delete temporary file. If it
// fail we'll try again in the destructor.
// ---------------------------------------------------------
//    
void CDocDefaultHandler::HandleServerAppExit( TInt aReason )
    {
    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::HandleServerAppExit : Exit notified."));
    #endif 

    if ( iExitNotified )
        return;
    
    if ( iDocDispatcher->ServerAppExitObserver() )
        {
         #ifdef _DEBUG        
         RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::HandleServerAppExit : Exit notification forwarded."));
        #endif 
        iDocDispatcher->ServerAppExitObserver()->HandleServerAppExit( aReason );
        }
        
    // We should base call in case of EAknCmdExit (to close client application)
    if (aReason == EAknCmdExit)
        {
        MAknServerAppExitObserver::HandleServerAppExit(aReason);
        }
        
    iExitNotified = ETrue;   
    SetAndReturnStatus( KErrNone );
    } 
// ---------------------------------------------------------
// CDocDefaultHandler::CanBeSavedToMmcL()
// Check if there is possibility to save data to MMC
// ---------------------------------------------------------
//    
TBool CDocDefaultHandler::CanBeSavedToMmcL()
    {       
    TBool retval = ETrue;
    TResourceReader reader;
    CDesCArrayFlat *exArr;

    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CanBeSavedToMmcL : Enter "));
    #endif 

    // Check if MMC feature is supported.
    if (!FeatureManager::FeatureSupported( KFeatureIdMmc ) )
        {
        return EFalse;
        }

    // Check if there is MMC card inserted & ok.
    if( !IsMMCLocked() ) // Request when unlocked.
        {            
        TDriveUnit unit(PathInfo::MemoryCardRootPath());
        TInt drive( unit );
        TVolumeInfo volumeInfo;
        TInt error(iFs.Volume(volumeInfo, drive));
        if ( error != KErrNone )
            {
            return EFalse;
            }
        }
        
    // It is not allowed to saving DRM protected file to MMC if this
    // feature flag is defined.
    #ifdef __KEEP_DRM_CONTENT_ON_PHONE
    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CanBeSavedToMmcL : (KEEP_DRM) Let's check if MMC save allowed."));
    #endif 
    if (!iMMCSaveAllowed)
        {
        #ifdef _DEBUG        
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CanBeSavedToMmcL : (KEEP_DRM) iMMCSaveAllowed = EFalse"));
        #endif 
        return EFalse;
        }
    #endif

    // Check if this MIME type is listed as an exception which is never saved to MMC
    // card.
    CreateDocResourceReaderLC(reader, R_DOCUMENT_HANDLER_EXCEPTION_TYPES_LIST);
    exArr = reader.ReadDesCArrayL();    
    if (exArr)
        {
        TInt posTmp;
        if (exArr->Find(iDataType.Des(), posTmp) == 0)
            {
            retval = EFalse;
            }
        delete exArr;   
        }
    CleanupStack::PopAndDestroy(); // reader

    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CanBeSavedToMmcL : Finished and returns %d"), retval);
    #endif 
    return retval;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::Status()
// Get the iStatus
// ---------------------------------------------------------
//        
TInt CDocDefaultHandler::Status() const
    {
    return iStatus;
    }
    
// ---------------------------------------------------------
// CDocDefaultHandler::GetPath()
// Return the path where the content was saved/copied
// ---------------------------------------------------------
//        
void CDocDefaultHandler::GetPath( TDes& aPath ) const
    {
    aPath.Copy( iDestFile );
    }

// ---------------------------------------------------------
// CDocDefaultHandler::CanOpen()
// Is the handler capable of opening the mime type
// ---------------------------------------------------------
//         
TBool CDocDefaultHandler::CanOpen() const 
    {
    return ( iServiceMode == EDocOpenOnly || iServiceMode == EDocOpenAndSave );
    }
    
// ---------------------------------------------------------
// CDocDefaultHandler::CanSave()
// Is the handler capable of saving the mime type
// ---------------------------------------------------------
//        
TBool CDocDefaultHandler::CanSave() const
    {
    return ( iServiceMode == EDocSaveOnly || iServiceMode == EDocOpenAndSave );
    }

// ---------------------------------------------------------
// CDocDefaultHandler::IsViewerOperation
// Is the operation viewing (ETrue) or saving (EFalse) operation
// ---------------------------------------------------------
// 
TBool CDocDefaultHandler::IsViewerOperation( TDocOperation aOperation )
    {
    switch ( aOperation )
        {
        case EDocOpenFile:
        case EDocOpenFileEmb:
            return ETrue;
        case EDocCopy:  
        case EDocMove:
        case EDocSilentMove:
        case EDocSave:
        case EDocSaveAs:
        case EDocSaveTemp:
            return EFalse;
        default:
            break;
        }
    return EFalse;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::IsConfNoteAllowed()
// Are we allowed to show confirmation note. In case of 
// SilentMove and viewer operation we are not allowed to
// show this note.
// ---------------------------------------------------------
// 
TBool CDocDefaultHandler::IsConfNoteAllowed()
    {
    if (DocOperation() == EDocSilentMove || DocOperation() == EDocSaveTemp)
        {
        return EFalse;
        }
    else 
        {
        return ( !IsViewerOperation( DocOperation() ) );
        }
    }

// ---------------------------------------------------------
// CDocDefaultHandler::HideFileExtension()
// Should we hide file extension. This should be overriden
// in derived handlers if needed.
// ---------------------------------------------------------
// 
TBool CDocDefaultHandler::HideFileExtension()
    {
    return EFalse;
    }
#ifdef RD_MULTIPLE_DRIVE
// ---------------------------------------------------------
// CDocDefaultHandler::CanOnlyBeSavedToPhoneMemory()
// check to see if the content can only be saved to Phone memory
// ---------------------------------------------------------
//
TBool CDocDefaultHandler::CanOnlyBeSavedToPhoneMemoryL()
	{
	TBool retval = EFalse;
	CDesCArrayFlat *exArr;
	TResourceReader reader;
	// It is not allowed to saving DRM protected file to MMC if this
    // feature flag is defined.
    #ifdef __KEEP_DRM_CONTENT_ON_PHONE
    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CanBeSavedToMmcL : (KEEP_DRM) Let's check if MMC save allowed."));
    #endif 
    if (!iMMCSaveAllowed)
        {
        #ifdef _DEBUG        
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CanBeSavedToMmcL : (KEEP_DRM) iMMCSaveAllowed = EFalse"));
        #endif 
        return ETrue;
        }
    #endif

    // Check if this MIME type is listed as an exception which is never saved to MMC
    // card.
    CreateDocResourceReaderLC(reader, R_DOCUMENT_HANDLER_EXCEPTION_TYPES_LIST);
    exArr = reader.ReadDesCArrayL();    
    if (exArr)
        {
        TInt posTmp;
        if (exArr->Find(iDataType.Des(), posTmp) == 0)
            {
            retval = ETrue;
            }
        delete exArr;   
        }
    CleanupStack::PopAndDestroy(); // reader
    return retval;
	}
#endif

#ifdef RD_MULTIPLE_DRIVE 
// ---------------------------------------------------------
// CDocDefaultHandler::GetSystemDrivesCount()
// This should not be called when RD_MULTIPLE_DRIVE flag is diabled
// ---------------------------------------------------------
// 
TInt CDocDefaultHandler::GetAvailableDrivesCountL()
	{
	TDriveList driveList;
	TInt driveCount;
	User::LeaveIfError(
			DriveInfo::GetUserVisibleDrives(
				iFs,
	            driveList,
	            driveCount ) );
	
	TInt driveListLen(driveList.Length());
	TDriveNumber driveNumber;
	driveCount=0;
	TInt defaultPhoneMem( KErrNotFound );
    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultPhoneMemory, defaultPhoneMem );

	for( TInt i( 0 ); i < driveListLen; ++i )
		{
	    if ( driveList[ i ] ) // Non zero items are valid drives
	    	{
	    	driveNumber=TDriveNumber(i);
	    	if( defaultPhoneMem == driveNumber)
	    		driveCount++;
	    	else if(IsDriveAvailableL(driveNumber))
	    		driveCount++;
	       	}
	    }
	return driveCount;
	}
#endif

#ifdef RD_MULTIPLE_DRIVE 
// ---------------------------------------------------------
// CDocDefaultHandler::IsDriveAvailable( const TDriveNumber & aDriveNumber)
// check drive availability ie is it available for user read/write operations
// This should not be called when RD_MULTIPLE_DRIVE flag is diabled
// ---------------------------------------------------------
// 
TBool CDocDefaultHandler::IsDriveAvailableL(const TInt & aDriveNumber)
	{

	 TInt error;
	 TUint status=0;
	 TDriveInfo driveInfo;
	 TVolumeInfo volumeInfo;
	 error = DriveInfo::GetDriveStatus( iFs, aDriveNumber, status );
	 if( error )
		 {
	     return EFalse;
	     }
	 TFullName fsName;
	 error = iFs.FileSystemName( fsName, aDriveNumber );
	 if(error)
		 {
		 return EFalse;
		 }
	 // if not mounted, try to mount it.
	 if( fsName.Length() == 0 )
		 {
		 error = iFs.MountFileSystem( KFSName,aDriveNumber );
		 switch( error )
		 	{
	        case KErrNone:
	        case KErrLocked:
	        	{
	        	break;
	        	}
	        default:
		        {
		        return EFalse;
		        }
		    }
	     }
	 error = iFs.Drive( driveInfo, aDriveNumber );
    if( error && ( error != KErrLocked ) )
		 {
	     return EFalse;
	     }
	 error = iFs.Volume( volumeInfo, aDriveNumber );
    if( error && ( error != KErrLocked  ) ) // if memory card locked, don't return false
		 {
	     return EFalse;
		 }
	 if( driveInfo.iDriveAtt & KDriveAttRemote )
		 {
		 /*TChar driveLetter;
		 iFs.DriveToChar( aDriveNumber, driveLetter );
		 //This statement migth cause leave.. to be solve
         CRsfwMountMan* mountMgr = CRsfwMountMan::NewL( 0, NULL );
         CleanupStack::PushL( mountMgr );
		 TRsfwMountInfo mountInfo;
		 error = mountMgr->GetMountInfo( driveLetter, mountInfo );
		 CleanupStack::PopAndDestroy( mountMgr );
		 if( error )
			 {
		 	 return EFalse;
			 }*/
		 /* Always return EFlase for Remote drives*/
		 return EFalse;
		 }
	 return ETrue;
	}
#endif
// ---------------------------------------------------------
// CDocDefaultHandler::GetDataDirL( 
// Get the data directory for the mime type. Directory is
// saved finally to aPath.
// ---------------------------------------------------------
//        
TInt CDocDefaultHandler::GetDataDirL( 
    const TDataType& aDataType, 
    const TUid& /*aUid*/, 
    TDes& aPath,
    TInt aDataSize)
    {    
    TFileName path;                     // The path
    TFileName folder;
    
    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::GetDataDirL : Enter "));
    #endif 
    
    if ( DocOperation() == EDocSaveTemp )
        {
        User::LeaveIfError( SetTemporaryPathL( aDataSize, path, ETrue ) );
        
        // DocumentHandler will take care deleting this file
        iSavedAsTemp = ETrue;
        }
    else if ( !IsViewerOperation( DocOperation() ) )
        {
        if (DocOperation() == EDocSilentMove)
            {
            TParsePtrC parse(iRootPath);
            // If we try to save to MMC, let's check that it is allowed.
            if( parse.Drive().CompareF( PathInfo::MemoryCardRootPath().Left(2) ) == 0 )
                {
                if ( !CanBeSavedToMmcL() )
                    {
                    #ifdef _DEBUG        
                    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::GetDataDir: Return ERROR, we are not allowed to save to MMC."));
                    #endif 
                    return KErrCancel;
                    }
                }
            path.Copy( iRootPath );
            }
#ifdef RD_MULTIPLE_DRIVE 
        else if( (!CanOnlyBeSavedToPhoneMemoryL())&&(1 < GetAvailableDrivesCountL()) )
        	{
        	TFileName defaultFolder;
            CAknMemorySelectionDialogMultiDrive* dlg =NULL;
			// Remote drives are not shown in the list of available drives.. FIX for error ANAE-76S7KX
	        dlg = CAknMemorySelectionDialogMultiDrive::NewL(ECFDDialogTypeBrowse,0,EFalse, 
	        			AknCommonDialogsDynMem::EMemoryTypePhone | AknCommonDialogsDynMem::EMemoryTypeInternalMassStorage | AknCommonDialogsDynMem::EMemoryTypeMMCExternal);
		    CleanupStack::PushL( dlg );
			TDriveNumber driveNumber;
		    TBool result(dlg->ExecuteL(driveNumber,&path,&defaultFolder));// driveNumber );
			CleanupStack::PopAndDestroy( dlg );
			if (!result)
				{
		        SetAndReturnStatus( KErrCancel );
		        return KErrCancel;
		        }
           }
#else  
        else if ( CanBeSavedToMmcL() )
            {
            CAknMemorySelectionDialog::TMemory mem( CAknMemorySelectionDialog::EPhoneMemory);
            AddResourcesL();
            TFileName defaultFolder;
            CAknMemorySelectionDialog* memoryDialog = CAknMemorySelectionDialog::NewL(
                                                            ECFDDialogTypeSave,
                                                            R_DOCHANDLER_MEMORY_SELECTION_DIALOG,
                                                            EFalse );
            CleanupStack::PushL( memoryDialog );    
            
            TBool result( memoryDialog->ExecuteL( mem, &path, &defaultFolder ) );
            if (!result)
                {
                RemoveResources();
                CleanupStack::PopAndDestroy();  // memoryDialog
                SetAndReturnStatus( KErrCancel );
                return KErrCancel;
                }

            CleanupStack::PopAndDestroy();  // memoryDialog

            RemoveResources();
            }
        #endif
        else 
            {
            path.Copy( PathInfo::PhoneMemoryRootPath() );
            }

		if ( iUid.iUid == 0 ) // Data type not supported
			{
			folder.Copy( PathInfo::OthersPath() );
            }	
		else // Data type supported
			{						
			iMediaGalleryData = GetDefaultFolderForDataTypeL( aDataType, folder );       		
        	if ( !iMediaGalleryData ) // Non-gallery files
            	{                                    	
            	if ( IsInstallerData() ) // Installable files.
                	{
                	folder.Copy( PathInfo::InstallsPath() );
                	}
            	else              		// Other supported non-gallery files.
                	{
                	folder.Copy( PathInfo::OthersPath() );                    	
               	 	}
            	}
            }
        }
    else
        {
        // do nothing
        }

    if ( DocOperation() != EDocSaveTemp )
        {
        if (( folder.Length() == 0 ) || ( path.Length() == 0 ))
            {
            User::LeaveIfError(SetTemporaryPathL(aDataSize, path, EFalse));

            // DocumentHandler will take care deleting this file
            iSavedAsTemp = ETrue;
            }        
        else
            {
            path.Append( folder );      
            }
        }
    
    TParsePtr parse( path );
    if ( parse.NamePresent() )                  // There is no '\' in the end.
        {
        path.Append( _L( "\\" ) );              // Append it. We need it!
        }

    aPath.Copy( path );
    return SetAndReturnStatus( KErrNone );
    }

// ---------------------------------------------------------
// CDocDefaultHandler::QueryRenameL()
// Ask from the user if he wants to rename aName
// ---------------------------------------------------------
//      
TBool CDocDefaultHandler::QueryRenameL( const TDesC& aName )
    {
    TParsePtrC parse( aName );

    return RunQueryDialogL( R_DOCHANDLER_RENAME_QUERY,
                            R_DOCUMENT_HANDLER_NAME_IN_USE_TEXT,
                            HideFileExtension() ? 
                            parse.Name(): 
                            parse.NameAndExt() );
    }

// ---------------------------------------------------------
// CDocDefaultHandler::QueryOverWriteL()
// Ask from the user if he wants to overwrite aName
// ---------------------------------------------------------
//      
TBool CDocDefaultHandler::QueryOverWriteL( const TDesC& aName )
    {
    TParsePtrC parse( aName );
    
    return RunQueryDialogL( R_DOCHANDLER_OVERWRITE_QUERY,
                            R_DOCUMENT_HANDLER_OVERWRITE_TEXT,
                            HideFileExtension() ? 
                            parse.Name(): 
                            parse.NameAndExt() );
    }

// ---------------------------------------------------------
// CDocDefaultHandler::QueryNewNameL()
// Ask a new name for aName from the user.
// ---------------------------------------------------------
//      
TBool CDocDefaultHandler::QueryNewNameL( TFileName& aName, const TInt aMaxLen )
    {
    TBool cancel( EFalse );
    TBool valid( EFalse );
    CApaApplication::GenerateFileName( iFs, aName );
    TParsePtr parse( aName );
    HBufC* extension = HBufC::NewLC( parse.Ext().Length() );
    extension->Des().Copy( parse.Ext() );
    TFileName name;

    do 
        {
        if ( HideFileExtension() )
            name.Copy( parse.Name() );
        else
            name.Copy( parse.NameAndExt() );
        TInt len = Min( KMaxFileName - KLengthOfFileExtension - parse.DriveAndPath().Length(), 
                        aMaxLen);
        if ( HideFileExtension() )
            {
            len -= extension->Des().Length();
            }
        if ( len <= 0 )
            User::Leave( KErrUnknown );

        if (name.Length() > len)
            {
            if ( HideFileExtension() )
                {
                name.SetLength( len );              
                }
            else
                {
                name.SetLength( len - extension->Des().Length() );
                name.Append( *extension );
                }
            }

        CAknTextQueryDialog* dlg = new( ELeave ) CAknTextQueryDialog( name );
        dlg->SetMaxLength( len );    
        if ( dlg->ExecuteLD( R_DOCHANDLER_NAME_QUERY_DIALOG ) ) 
            {          
            valid = iFs.IsValidName( name ) ;
            if ( !valid )
                {
                CAknNoteDialog* note = new (ELeave) CAknNoteDialog(CAknNoteDialog::ENoTone, CAknNoteDialog::ELongTimeout);
                HBufC* noteText = NULL;
                noteText = StringLoader::LoadLC( R_DOCUMENT_HANDLER_ILLEGAL_CHARACTERS );
                note->PrepareLC( R_DOCUMENT_HANDLER_INFO_NOTE );
                note->SetTextPluralityL(EFalse);
                note->SetTextL( *noteText );
                note->RunLD();
                CleanupStack::PopAndDestroy(noteText);
                cancel = EFalse;
                }
            else
                {
                aName.Copy( parse.DriveAndPath() );
                aName.Append( name );  
                if ( HideFileExtension() )
                    aName.Append( extension->Des() );        
                cancel = EFalse;        
                }
            }
        else
            {
            cancel = ETrue;
            }    
        }
        while ( !valid && !cancel );
    CleanupStack::PopAndDestroy(); // extension
    return !cancel;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::GenerateTempFileNameL()
// Creates a new name (based on existing name) without asking anything from user.
// ---------------------------------------------------------
//      
void CDocDefaultHandler::GenerateTempFileNameL( TFileName& aName, const TInt aMaxLen )
    {
    TBool valid( EFalse );
    CApaApplication::GenerateFileName( iFs, aName );
    TParsePtr parse( aName );
    HBufC* extension = HBufC::NewLC( parse.Ext().Length() );
    extension->Des().Copy( parse.Ext() );
    TFileName name;

    if ( HideFileExtension() )
        name.Copy( parse.Name() );
    else
        name.Copy( parse.NameAndExt() );
        
    TInt len = Min( KMaxFileName - KLengthOfFileExtension - parse.DriveAndPath().Length(), aMaxLen);
    if ( HideFileExtension() )
        {
        len -= extension->Des().Length();
        }
    if ( len <= 0 )
        User::Leave( KErrUnknown );

    if (name.Length() > len)
        {
        if ( HideFileExtension() )
            {
            name.SetLength( len );              
            }
        else
            {
            name.SetLength( len - extension->Des().Length() );
            name.Append( *extension );
            }
        }
      
    valid = iFs.IsValidName( name ) ;
        
    if ( !valid )
        {
        User::Leave( KErrUnknown );
        }
    else
        {
        aName.Copy( parse.DriveAndPath() );
        aName.Append( name );  
        if ( HideFileExtension() )
            aName.Append( extension->Des() );           
        }

    CleanupStack::PopAndDestroy(); // extension
    }

// ---------------------------------------------------------
// TCDocDefaultHandler::SaveAsQueryL()
// Run "save as" dialog chain.
// ---------------------------------------------------------
//      
TDocSaveAsResult CDocDefaultHandler::SaveAsQueryL( TFileName& aPath )
    {    
    AddResourcesL();
    TDocSaveAsResult response = EDocFileCancelWrite;   

    TParsePtr parse( aPath );
    
    if ( IsFileWritableL( aPath ) )         // If the file is writable.
        {                                   // If the user wants to overwrite.
        if ( QueryOverWriteL( parse.NameAndExt() ) )
            {
            response = EDocFileOverWrite;   // Overwrite, please.
            }
        else
            {
            response = EDocFileRenameNew;   // Rename please.
            }
        }
    else                                    // If the file is not writable.
        {                                   // Ask if the user wants to rename.
        if ( QueryRenameL( parse.NameAndExt() ) )
            {
            response = EDocFileRenameNew;   // Rename, please.
            }
        else
            {
            response = EDocFileCancelWrite; // User cancelled.
            }
        }
    if ( response == EDocFileRenameNew )    // Ask the user to rename the file.
        {
        if ( !QueryNewNameL( aPath, MaxNameLen() ) )      // Run rename dialog.
            {
            response = EDocFileCancelWrite; // User cancelled.           
            }
        }       
    RemoveResources();
    return response;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::RunQueryDialogL()
// Run CAknQueryDialog with given resources. 
// ---------------------------------------------------------
//         
TInt CDocDefaultHandler::RunQueryDialogL(
    TInt aDialogTypeResID,
    TInt aStringResID,
    const TDesC& aFileName )
    {
    TInt response;
    HBufC* promptPtr = NULL;
    promptPtr = StringLoader::LoadL( aStringResID, aFileName );
    CleanupStack::PushL( promptPtr );
    TPtrC prompt( promptPtr->Des() );
    CAknQueryDialog* dlg = CAknQueryDialog::NewL( );
    dlg->SetPromptL(prompt);
    dlg->PrepareLC(aDialogTypeResID);    
    response = dlg->RunLD();
    CleanupStack::PopAndDestroy(); // promptPtr
    return response;
    }
    
// ---------------------------------------------------------
// CDocDefaultHandler::GenerateFileNameL()
// Try to generate a file name.
// 1. Try to find the handler app's default document name.
// 2. If failed, try to load DocHandler's document name. ("unnamed")
// 3. If still failed, use a hardcoded name
// ---------------------------------------------------------
//           
TInt CDocDefaultHandler::GenerateFileNameL( 
    const TUid& aUid, 
    TDes& aFileName, 
    const TDataType& aDataType,
    TInt aDataSize)
    {
    #ifdef _DEBUG        
    TPtrC mimetype = aDataType.Des();        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::GenerateFileNameL( %x, %S, %S ) Called"), aUid.iUid, &aFileName, &mimetype);
    #endif 

    TFileName path;
    TParsePtr parse( aFileName );

    if ( parse.NamePresent() )
        {
            aFileName.Copy( parse.NameAndExt() );
        }
    else
        {
        TFileName resFileName;        

        // Find an application's resource file
        if ( iAppInfo.iFullName.Length() > 0 )
            {                                       
            TParsePtr appParse( iAppInfo.iFullName );
            resFileName.Copy( resourceaApps );       //"\resource\apps\" 
            resFileName.Append( appParse.Name() );   //"\resource\apps\ap"
            resFileName.Append( resExt );            //"\resource\apps\ap.rsc"
            
            CStringResourceReader* reader = NULL;
            TRAPD( 
                error, 
                ( reader = CStringResourceReader::NewL( resFileName ) ) );
            if ( error == KErrNone )
                {
                CleanupStack::PushL( reader );       // This is needed, it can leave!
                aFileName = reader->ReadResourceString( EDefaultNameResourceOffset );
                CleanupStack::PopAndDestroy();       // reader
                }
            } 

        // Use the docHandler's (fall back) doc name            
        if ( aFileName == errorStr || aFileName.Length() == 0 ) 
            {                                                   
            resFileName.Copy( KDocResourceFileName );
            CStringResourceReader* reader = NULL;
            TRAPD( 
                error, 
                ( reader = CStringResourceReader::NewL( resFileName ) ) );
            if ( error == KErrNone )
                {
                __ASSERT_DEBUG (
                    reader,
                    User::Panic( _L( "DocDefaultHandler" ), KErrNoMemory ) );
                CleanupStack::PushL( reader );      // This is needed, it can leave!
                aFileName = reader->ReadResourceString( EDefaultNameResourceOffset );
                CleanupStack::PopAndDestroy();      // reader
                }
            }
        
        if ( aFileName == errorStr || aFileName.Length() == 0 )
            {
            #ifdef _DEBUG        
            User::Panic( _L( "DocumentHandler: CDocDefaultHandler::GenerateFileNameL: resource problem" ), KErrUnknown );
            #endif 
            aFileName.Copy( KDocFallBackName );
            }
        }

    CheckFileNameExtensionL( aFileName, aDataType );
    if (GetDataDirL( iDataType, aUid, path, aDataSize ) == KErrCancel)
        {
        return KErrCancel;  
        }
    aFileName.Insert( 0, path );
    
    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::GenerateFileNameL exit, aFileName=\"%S\""), &aFileName);
    #endif 

    return KErrNone;
    }
    
// ---------------------------------------------------------
// CDocDefaultHandler::CheckDiskspaceL()
// Always leave if no space left on flash
// ---------------------------------------------------------
//      
void CDocDefaultHandler::CheckDiskspaceL( TInt aBytes )
    {
    // If MoveL command used, we do not need any more space because
    // Symbian API renames the file -> we can skip this check
    if (DocOperation() == EDocMove || DocOperation() == EDocSilentMove)
        {
        return;
        }

    if (iDestFile.FindF( PathInfo::PhoneMemoryRootPath() ) != KErrNotFound)
        {
        #ifdef _DEBUG        
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CheckDiskspaceL: Disk Space checked"));
        #endif 
        if ( SysUtil::FFSSpaceBelowCriticalLevelL( &iFs, aBytes ) )
            {
            #ifdef _DEBUG        
            RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CheckDiskspaceL: Leave with KErrDiskFull"));
            #endif 
            User::Leave( KErrDiskFull );
            }
        }
    }

// ---------------------------------------------------------
// CDocDefaultHandler::ReplaceExtension()
// Replace current extension at aName with extension given (eExt).
// ---------------------------------------------------------
//      
void CDocDefaultHandler::ReplaceExtension( TDes& aName, const TDesC& aExt )
    {
    #ifdef _DEBUG        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::ReplaceExtension: Enter, aName =%S, aExt=%S"),&aName, &aExt);
    #endif 
    
    TInt dotPos = aName.LocateReverse( '.' );
    if ( dotPos != KErrNotFound )
       {
       aName.Delete( dotPos, aName.Length()- dotPos );
       }
    aName.Append( aExt );
    }

// ---------------------------------------------------------
// CDocDefaultHandler::AddRecourcesL()
// Calls CDocResourceFile::AddLC()
// ---------------------------------------------------------
//      
void CDocDefaultHandler::AddResourcesL()
    {
    CDocResourceFile::AddLC( KDocResourceFileName, iFs );
    }

// ---------------------------------------------------------
// CDocDefaultHandler::RemoveRecources()
// Calls CDocResourceFile::Remove()
// ---------------------------------------------------------
//  
void CDocDefaultHandler::RemoveResources()
    {
    CDocResourceFile::Remove();
    }

// ---------------------------------------------------------
// CDocDefaultHandler::CheckFileNameExtensionL()
// We should not have to do this. But some recognizers
// don't work as expected and for example browser may suggest wrong file
// extensions (such as .asp). 
// ---------------------------------------------------------
//       
void CDocDefaultHandler::CheckFileNameExtensionL(
    TDes &aFileName,
    const TDataType& aDataType )
    {
    #ifdef _DEBUG        
    TPtrC mimetype = aDataType.Des();        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CheckFileNameExtensionL: Enter, aFileName =%S, aDataType =%S"), &aFileName, &mimetype);
    #endif 
    
    // Jad files should always have jad extension even proctected.
    if ( aDataType.Des().FindF( KDocMimeJad ) != KErrNotFound )
    	{
    	// change extension to .jad
    	TBuf<6> ext;
        ext.Copy( KDocExtJad );         
        ReplaceExtension( aFileName, ext );                    
        return;            
    	}
    	
    // If we have iSourceFile available, we check first that is file DCF file. 
    // If it is, then we will use dcf file extensions, which override all other extensions.
    if (iSourceFile.Length() > 0)
        {
        TInt ret = EFalse;
        TBuf<6> ext;

		CContent* content = NULL;
        TRAPD(err,content = CContent::NewL( iSourceFile ));

		if(err == KErrNone)
			{	
			CleanupStack::PushL(content);
			content->GetAttribute( ContentAccess::EIsProtected, ret  );
			if ( ret )
				{
				content->GetAttribute( EFileType, ret );
            
				#ifdef _DEBUG             
				RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CheckFileNameExtensionL: GetAttribute called, ret =%d"), ret);
				#endif 
    
				if ( ret == EOma1Dcf )
					{
					// change extension to .dcf
					ext.Copy( KOma1DcfExtension );         
					ReplaceExtension( aFileName, ext );            
					CleanupStack::PopAndDestroy();  // content
					return;            
					}
				else if ( ret == EOma2Dcf )
	                {
		            // change extension to .odf if not already .o4a, .o4v or .odf
			        ext.Copy( KOma2DcfExtension );
				    if ( NeedsToReplaceDcf2Extension( aFileName ) )
					    {
						ReplaceExtension( aFileName, ext );
	                    }
		            CleanupStack::PopAndDestroy();  // content
			        return;            
				    }
				}
			CleanupStack::PopAndDestroy();  // content
			}
        }

    //if mime type=oma 2 dcf check extension separately
    if ( aDataType.Des8().FindF( KOma2DcfContentType ) != KErrNotFound )
        {
        if ( NeedsToReplaceDcf2Extension( aFileName ) )
            {
            ReplaceExtension( aFileName, KOma2DcfExtension() );
            }
        }
    else
        {
        if (!iMimeExtensions)
            {
            TResourceReader reader; 

            CreateDocResourceReaderLC(reader, R_EXTENSION_GUARANTEED_MIME_TYPES);
            iMimeExtensions = reader.ReadDesCArrayL();  
            CleanupStack::PopAndDestroy();  // reader

            CreateDocResourceReaderLC(reader, R_EXTENSION_GUARANTEED_EXTENSIONS);
            iExtensions = reader.ReadDesCArrayL();  
            CleanupStack::PopAndDestroy();  // reader
            }   

        TInt position;
        TFileName mimeType;
        mimeType.Copy(aDataType.Des8());
        if (!iMimeExtensions->Find(mimeType, position))
            {
        #ifdef _DEBUG             
            RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CheckFileNameExtensionL: Founded from mapping table."));
        #endif 
            TBuf<6> ext = iExtensions->MdcaPoint( position );
            ext.Insert(0, _L("."));
            ReplaceExtension( aFileName, ext );
            }
        }
    #ifdef _DEBUG             
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::CheckFileNameExtensionL: Finished"));
    #endif          
    }

// ---------------------------------------------------------
// CDocDefaultHandler::IsFileInUse()
// Try to open file for writing. If it fails return EFalse. 
// If it succeeds close the file and return ETrue?
// ---------------------------------------------------------
//       
TBool CDocDefaultHandler::IsFileInUse( const TDesC& aFileName )
    {
    RFile file;
    TInt error;
    TBool retValue = EFalse;
    error = file.Open( iFs, aFileName, EFileWrite );
    if ( error == KErrInUse || error == KErrLocked )
        {
        retValue = ETrue;
        }
    file.Close();
    return retValue;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::IsFileWritableL()
// check if the file is read only or in use.
// ---------------------------------------------------------
//       
TBool CDocDefaultHandler::IsFileWritableL( const TDesC& aFileName )
    {
    TEntry fileEntry;    
    TInt error = iFs.Entry( aFileName, fileEntry );
    if ( error != KErrNone && error != KErrBadName )
        {
        User::Leave( error );
        }
    
    if ( fileEntry.IsReadOnly() || IsFileInUse( aFileName ) ) 
        {
        return EFalse;
        }
    else
        {
        return ETrue;
        }
    }

// ---------------------------------------------------------
// CDocDefaultHandler::SetAndReturnStatus()
// Set iStatus.
// ---------------------------------------------------------
//       
TInt CDocDefaultHandler::SetAndReturnStatus( TInt aErrorCode )
    {
    if (aErrorCode == KErrCancel)
        {
        iStatus = KErrNone;
        }
    else
        {
        iStatus = aErrorCode;
        }
    return iStatus;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::DocOperation() const
// Return iOperation.
// ---------------------------------------------------------
//       
TDocOperation CDocDefaultHandler::DocOperation() const
    {
    return iDocDispatcher->DocOperation();
    }
    
// ---------------------------------------------------------
// CDocDefaultHandler::PopulateAppInfo()
// Construct iAppInfo with iUid.
// ---------------------------------------------------------
//       
void CDocDefaultHandler::PopulateAppInfo()
    {
    PopulateAppInfo( iUid );    
    }
    
// ---------------------------------------------------------
// CDocDefaultHandler::PopulateAppInfo()
// Construct iAppInfo.
// ---------------------------------------------------------
//      
void CDocDefaultHandler::PopulateAppInfo( const TUid& aUid )
    {
    TInt error = iApaLs->GetAppInfo( iAppInfo, aUid );    
    if ( error != KErrNone )
        {
        // TODO: What happends if GetAppInfo fails?
        }
    }
    
// ---------------------------------------------------------
// CDocDefaultHandler::MaxNameLen()
// Return max lenght of file name.
// ---------------------------------------------------------
//      
TInt CDocDefaultHandler::MaxNameLen()
    {
    return KMaxFileName;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::ReverseSlashes()
// Reverses slashes at aString ('/' -> '\').
// ---------------------------------------------------------
//      
void CDocDefaultHandler::ReverseSlashes(TDes& aString)
    {
    TInt findPos = aString.Locate('/');
    while (findPos != KErrNotFound)
        {
        aString.Replace(findPos, 1, _L("\\"));
        findPos = aString.Locate('/');
        }
    }

// ---------------------------------------------------------
// CDocDefaultHandler::IsParameterAlreadyInList()
// Check if given parameter is allready on iAiwParams.
// ---------------------------------------------------------
//    
TBool CDocDefaultHandler::IsParameterAlreadyInList(TGenericParamId aId)
    {
    if ( iAiwParams )
        {
        TInt index = 0;
        iAiwParams->FindFirst(index, aId);
        if (index!=KErrNotFound)
            {
            return ETrue;
            }
        }
    return EFalse;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::WaitNoteTextL
// Resolve wait note text.
// ---------------------------------------------------------
// 
void CDocDefaultHandler::WaitNoteTextL( TPtr& aTextPtr )
    {
    AddResourcesL();
    HBufC* text;
	if(IsInstallerData())
       	{
       	text = StringLoader::LoadLC( R_DOCUMENT_HANDLER_SAVING_INSTALLS_DIRECTORY );
       	}
    else if( iUid.iUid == 0 || !iMediaGalleryData )//KWmlcHandler == iUid.iUid ) 
        {
        text = StringLoader::LoadLC( R_DOCUMENT_HANDLER_SAVING_OTHERS_DIRECTORY );
        }
    else
        {
        TApaAppCaption caption;
        ResolveCaptionName( caption );
        text = StringLoader::LoadLC( R_DOCUMENT_HANDLER_SAVING_FILE_TO, caption );
        }
    aTextPtr.Copy( text->Des() );
    CleanupStack::PopAndDestroy(); // text
    RemoveResources();
    }
    
// ---------------------------------------------------------
// CDocDefaultHandler::ConfirmationNoteTextL
// Resolve confirmation note text.
// ---------------------------------------------------------
// 
void CDocDefaultHandler::ConfirmationNoteTextL( TPtr& aTextPtr  )
    {
    AddResourcesL();
    HBufC* text;
    TBuf<100> mime16;
    mime16.Copy( iDataType.Des() );
    
	if(IsInstallerData())
    	{
    	text = StringLoader::LoadLC( R_DOCUMENT_HANDLER_SAVED_INSTALLS_DIRECTORY );
    	}
    else if( mime16.FindF(KMIMETypeSvg) != KErrNotFound 
           || iUid.iUid == 0 || !iMediaGalleryData ) // Data type not supported.
        {
        text = StringLoader::LoadLC( R_DOCUMENT_HANDLER_SAVED_OTHERS_DIRECTORY );
        }
    else
        {
        TApaAppCaption caption;
        ResolveCaptionName( caption );
        text = StringLoader::LoadLC( R_DOCUMENT_HANDLER_FILE_SAVED_TO, caption );
        }
    aTextPtr.Copy( text->Des() );
    CleanupStack::PopAndDestroy(); // text
    RemoveResources();
    }


// ---------------------------------------------------------
// CDocDefaultHandler::ResolveCaptionName
// Resolve confirmation note text.
// ---------------------------------------------------------
// 
void CDocDefaultHandler::ResolveCaptionName( TApaAppCaption& aCaption )
    {
    if ( iMediaGalleryData || IsInstallerData() )
        {
        TBuf<100> mime16;
        mime16.Copy( iDataType.Des() );
        // Get app info for media gallery app or app manager.
        TApaAppInfo appInfo;
        TUid uid;
        if( mime16.FindF( KMIMETypeImage ) != KErrNotFound )
            {    	
            uid = KPhotosUID3;
            }
        else if ( mime16.FindF(KMIMETypeVideo)!= KErrNotFound 
            || mime16.FindF(KMIMETypeVideoReal)!= KErrNotFound 
            || mime16.FindF(KMIMETypeVideoSdp)!= KErrNotFound )
            {
            uid = KVideoCenterAppUid;
            } 
        else if( mime16.FindF(KMIMETypeAudioMpeg)!= KErrNotFound 
            || mime16.FindF(KMIMETypeAudioMp4)!= KErrNotFound )
            {
            uid = KMusicPlayerAppUid;
            }
        else if(mime16.FindF(KMIMETypeAudio)!= KErrNotFound )
            {
            uid = KFileManagerUID3;
            }
        else
            {
            uid = KAppManagerUID3;
            }
        TInt error = iApaLs->GetAppInfo( appInfo, uid );
        if ( error == KErrNone )
            {
            aCaption = appInfo.iCaption;
            }
        }
    else
        {
        aCaption = iAppInfo.iCaption;
        }          
    }
// ---------------------------------------------------------
// CDocDefaultHandler::GetDefaultFolderForDataTypeL()
// Get folder for given datatype. This info is get from
// documenthandlerui.rss file.
// ---------------------------------------------------------
// 
TBool CDocDefaultHandler::GetDefaultFolderForDataTypeL(const TDataType& aDataType, TDes& result)
    {
    #ifdef _DEBUG        
    TPtrC mimetype = aDataType.Des();        
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::GetDefaultFolderForDataTypeL: Enter, aDataType =%S"), &mimetype);
    #endif 
    
    TResourceReader resReader;
    CreateDocResourceReaderLC(resReader, R_DOCHANDLER_DEFAULT_PATH_ARRAY);

    TBuf<100> mime16;
    mime16.Copy( aDataType.Des() );

    result.Zero();

    TInt count = resReader.ReadInt16();

    TBool found = EFalse;   
    for (TInt i = 0; i < count; i++)
        {
        HBufC* mimetype = resReader.ReadHBufCL();
        CleanupStack::PushL( mimetype );        
        HBufC* path = resReader.ReadHBufCL();
        CleanupStack::PushL( path );        

        if (mime16.FindF( *mimetype ) != KErrNotFound)
            {
            result.Copy( path->Des() );
            found = ETrue;
            }

        CleanupStack::PopAndDestroy( 2 );  // mimetype, path

        if (found)
            {
            break;
            }
        }

    CleanupStack::PopAndDestroy(); // resReader

    #ifdef _DEBUG             
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::GetDefaultFolderForDataTypeL: Finished, returns =%d"), found);
    #endif 

    return found;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::IsInstallerData()
// Check if application installer is handler application.
// ---------------------------------------------------------
// 
TBool CDocDefaultHandler::IsInstallerData() const
    {
    TUid uid;
    HandlerAppUid(uid);
    if (uid.iUid == KAppInstHandler)
        {
        return ETrue;
        }
    else
        {
        return EFalse;
        }  
    }

// ---------------------------------------------------------
// CDocDefaultHandler::SetTemporaryPathL()
// Set temporary path to aPath. First choice to temporary 
// place is 
// -if we prefer private folder (aPrivate = ETrue) -> d:\[process_private_directory] 
// -if not any need where to save -> d:\system\temp, 
// Second choice is to save to c:\system\temp.
// ---------------------------------------------------------
// 
TInt CDocDefaultHandler::SetTemporaryPathL(TInt aDataSize, TDes& aPath, TBool aPrivate)
    {    
    #ifdef _DEBUG           
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::SetTemporaryPathL: Enter"));
    #endif 
    
    //TDriveUnit unit(KDocDDriveRoot);
    TDriveUnit unit(EDriveD);
    TInt drive( unit );
    TVolumeInfo volumeInfo;
    TInt error(iFs.Volume(volumeInfo, drive));

    if (error == KErrNone)
        {
        if (volumeInfo.iFree >= aDataSize)
            {
            if (aPrivate)
                {
                // Get process privatepath     
                User::LeaveIfError( iFs.PrivatePath(aPath) );
                    
                // Add used memory to beginning 
                aPath.Insert(0,unit.Name());
                }
            else
                {
               	// Set temp to drive D.
                aPath.Insert(0,KDocTempPath);
                aPath.Insert(0,unit.Name());
                }      
            return KErrNone;
            }
        }  

    // Not enough space in drive D, try drive C instead
    if ( SysUtil::FFSSpaceBelowCriticalLevelL( &iFs, aDataSize ) )
        {
        return KErrDiskFull;
        }

    // Set temp to drive C
    aPath.Copy(KDocTempPath2);

    return KErrNone;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::UpdateMediaGalleryIfNeededL()
// Calls MediaGallery Update method so that media gallery
// knows update its view.
// ---------------------------------------------------------
// 
void CDocDefaultHandler::UpdateMediaGalleryIfNeededL()
    {
    if (!iSavedAsTemp)
        {  
        #ifdef _DEBUG        
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::UpdateMediaGalleryIfNeededL: aFileName=\"%S\""), &iDestFile);
        #endif 
#ifdef RD_CONTENTNOTIFICATION            
        CContentNotification* notifier = CContentNotification::NewL();
        CleanupStack::PushL( notifier );        
        CContentNotificationEvent* event = CContentCreatedEvent::NewL( iDestFile );                    
        CleanupStack::PushL( event );               
        CArrayFixFlat<CContentNotificationEvent*>* eventArray;
        eventArray = new CArrayFixFlat<CContentNotificationEvent*>(2);    	        	        
        CleanupStack::PushL( eventArray );        
        eventArray->AppendL( event );        
        User::LeaveIfError( notifier->SendNotification( eventArray->Array() ) );
        eventArray->Delete( 0 );
        CleanupStack::PopAndDestroy( 3 ); // eventArray, event, notifier.
#endif        
        }
    }

// ---------------------------------------------------------
// CDocDefaultHandler::UpdateDCFRepositoryL()
// Update saved file to DCFRepository  
// ---------------------------------------------------------
// 
void CDocDefaultHandler::UpdateDCFRepositoryL()
    {
#ifdef ENABLE_DRM
    CDcfEntry* dcf = NULL;
    dcf = CDcfEntry::NewL();    
    CleanupStack::PushL( dcf );
    
    CDcfRep* dcfRep = NULL;
    dcfRep = CDcfRep::NewL();
    CleanupStack::PushL( dcfRep );
    
    dcf->SetLocationL( iDestFile, 0 );    
    dcfRep->UpdateL( dcf );
    
    CleanupStack::PopAndDestroy(2); // dcf, dcfRep
#endif
    }


// ---------------------------------------------------------
// CDocDefaultHandler::HandlerAppUid()
// Returns handler application Uid.
// ---------------------------------------------------------
// 
void CDocDefaultHandler::HandlerAppUid(TUid& aUid) const
    {
    aUid = iUid;
    }
    
// ---------------------------------------------------------
// CDocDefaultHandler::DeleteFile()
// Utility method: Delete file given in parameter if possible.
// ---------------------------------------------------------
//       
void CDocDefaultHandler::DeleteFile(const TDesC& aFileName)
    {
    #ifdef _DEBUG  
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::DeleteFile: Trying to delete file %S "), &aFileName );
    #endif   
    
    // Delete file, don't care about possible errors
    TInt error = iFileManager->Delete( aFileName, 0 );
    
    if ( error == KErrNone ) 
        {      
        #ifdef _DEBUG        
        RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::DeleteFile: Deleting succesful!"));
        #endif      
        }
    }

// ---------------------------------------------------------
// CDocDefaultHandler::IsMMCSaveAllowedL()
// Check if we are allowed to save MMC DRM content. Result
// is saved to iMMCSaveAllowed member variable.
// ---------------------------------------------------------
//
void CDocDefaultHandler::IsMMCSaveAllowedL(const TDesC& aSourceFile)
    {
#ifndef __KEEP_DRM_CONTENT_ON_PHONE
    iMMCSaveAllowed = ETrue;
    (void)aSourceFile; // This is because of removing warning
#else
    iMMCSaveAllowed = EFalse;   // paranoia
    CDistributableChecker* distributableChecker = CDistributableChecker::NewL();
    CleanupStack::PushL( distributableChecker );
    TBool isProtected( ETrue );
    TInt err(KErrNone);

    #ifdef _DEBUG
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::IsMMCSaveAllowedL : (KEEP_DRM) Filename version. Created CDistributableChecker.") );
    #endif

    err = distributableChecker->Check( aSourceFile, isProtected );

    #ifdef _DEBUG
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::IsMMCSaveAllowedL : (KEEP_DRM) isProtected =%d, err =%d."), isProtected, err);
    #endif

    if ( err == KErrNone && isProtected == EFalse )
        {
        iMMCSaveAllowed = ETrue;
        }

    CleanupStack::PopAndDestroy( distributableChecker );
#endif // __KEEP_DRM_CONTENT_ON_PHONE
    }

// ---------------------------------------------------------
// CDocDefaultHandler::IsMMCSaveAllowedL()
// Check if we are allowed to save MMC DRM content. Result
// is saved to iMMCSaveAllowed member variable.
// ---------------------------------------------------------
//
void CDocDefaultHandler::IsMMCSaveAllowedL(const RFile& aSourceFile)
    {


#ifndef __KEEP_DRM_CONTENT_ON_PHONE
    iMMCSaveAllowed = ETrue;
    (void)aSourceFile; // This is because of removing warning
#else
    iMMCSaveAllowed = EFalse;   //paranoia
    CDistributableChecker* distributableChecker = CDistributableChecker::NewL();
    CleanupStack::PushL( distributableChecker );
    TBool isProtected( ETrue );
    TInt err(KErrNone);

    #ifdef _DEBUG
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::IsMMCSaveAllowedL : (KEEP_DRM) Filehandle version. Created CDistributableChecker.") );
    #endif

    RFile& source = const_cast<RFile&>(aSourceFile);    // not nice, but needed to go between APIs
    err = distributableChecker->Check( source, isProtected );

    #ifdef _DEBUG
    RDebug::Print( _L("DocumentHandler: CDocDefaultHandler::IsMMCSaveAllowedL : (KEEP_DRM) isProtected =%d, err =%d."), isProtected, err);
    #endif

    if ( err == KErrNone && isProtected == EFalse )
        {
        iMMCSaveAllowed = ETrue;
        }

    CleanupStack::PopAndDestroy( distributableChecker );
#endif // __KEEP_DRM_CONTENT_ON_PHONE
    }

// ---------------------------------------------------------
// CDocDefaultHandler::CreateDocResourceReaderLC()
// Setup aReader (TResourceReader) for resource reading with 
// aResourceID. This method is because need to use DocumentHandler 
// services from server-side, where CCoeEnv is not available.
// ---------------------------------------------------------
//      
void CDocDefaultHandler::CreateDocResourceReaderLC(TResourceReader& aReader, TInt aResourceID)
    {  
    TFileName resourceFile(KDocResourceFileName);
    BaflUtils::NearestLanguageFile( iFs, resourceFile );
    
    RResourceFile rfile;
    rfile.OpenL( iFs, resourceFile ); 
    CleanupClosePushL(rfile);             

    HBufC8* buffer = rfile.AllocReadL( (KRIMask & aResourceID) );
    
    CleanupStack::PopAndDestroy();  // rfile
    CleanupStack::PushL(buffer);
        
    aReader.SetBuffer(buffer);
    }

// ---------------------------------------------------------
// CDocDefaultHandler::IsMMCLocked()
// Checks if Mmc card is currently locked.
// ---------------------------------------------------------
//  
TBool CDocDefaultHandler::IsMMCLocked()
    {
    TBool ret = EFalse;
   
    // Check if MMC mounted, mount if required
    TInt err = TryMountMMC();

    if( !err )
        {
        TDriveInfo driveInfo;    
        err = iFs.Drive( driveInfo, EDriveE );
        if( !err ) 
            {            
            if( driveInfo.iMediaAtt & KMediaAttLocked )
                {
                ret = ETrue;  
                }
            }
        }
        
    return ret;
    }

// ---------------------------------------------------------
// CDocDefaultHandler::TryMountMMC()
// Mounts Mmc card.
// ---------------------------------------------------------
//      
TInt CDocDefaultHandler::TryMountMMC()
    {
    // Check if MMC mounted, mount if required

    TFullName fsname;
    
    // If can't use the drive, returns KErrNotFound
    TInt err = iFs.FileSystemName( fsname, EDriveE );

    if ( !err )
        {
        // MMC found. Checking if it is mounted
        if ( fsname.Length( ) == 0 )
            {
            // Returns KErrLocked, if card locked and password not in store
            err = iFs.MountFileSystem( KFSName, EDriveE );                        
            }
        }
    return err;
    }    
//  End of File  
