ipsservices/ipssosplugin/src/ipsplgnewchildpartfromfileoperation.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 27 May 2010 12:43:55 +0300
changeset 27 9ba4404ef423
parent 20 ecc8def7944a
permissions -rw-r--r--
Revision: 201019 Kit: 2010121

/*
* Copyright (c) 2006-2008 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: This file implements class CCIpsPlgNewChildPartFromFileOperation.
*
*/

// <qmail>
// INCLUDE FILES

#include "emailtrace.h"
#include "ipsplgheaders.h"

// LOCAL CONSTANTS AND MACROS

_LIT( KMimeTextCalRequest,  "text/calendar; method=REQUEST;" );
_LIT( KMimeTextCalResponse, "text/calendar; method=RESPONSE;" );
_LIT( KMimeTextCalCancel,   "text/calendar; method=CANCEL;" );
_LIT( KFileExtensionICS, ".ics" );

_LIT8( KMethod, "method" );
_LIT8( KRequest, "REQUEST" );
_LIT8( KResponse, "RESPONSE" );
_LIT8( KCancel, "CANCEL" );

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

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::CIpsPlgNewChildPartFromFileOperation
// ----------------------------------------------------------------------------
//
CIpsPlgNewChildPartFromFileOperation::CIpsPlgNewChildPartFromFileOperation(
    CMsvSession& aMsvSession,
    TRequestStatus& aObserverRequestStatus,
    const TFSMailMsgId& aMailBoxId,
    const TFSMailMsgId& aMessageId,
    MFSMailRequestObserver& aOperationObserver,
    const TInt aRequestId)
    :
    CIpsPlgBaseOperation( 
        aMsvSession, 
        aObserverRequestStatus,
        aRequestId,
        aMailBoxId),
    iMessageId(aMessageId),
    iOperationObserver(aOperationObserver)
    {
    FUNC_LOG;
    CActiveScheduler::Add( this );
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::NewL
// ----------------------------------------------------------------------------
//
CIpsPlgNewChildPartFromFileOperation* CIpsPlgNewChildPartFromFileOperation::NewL(
    CMsvSession& aMsvSession,
    TRequestStatus& aObserverRequestStatus,
    const TFSMailMsgId& aMailBoxId,
    const TFSMailMsgId& aMessageId,
    const TDesC& aContentType,
    const TDesC& aFilePath,
    MFSMailRequestObserver& aOperationObserver,
    const TInt aRequestId,
    CIpsPlgMsgMapper *aMsgMapper)
    {
    FUNC_LOG;
    CIpsPlgNewChildPartFromFileOperation* self =
        new (ELeave) CIpsPlgNewChildPartFromFileOperation(
            aMsvSession,
            aObserverRequestStatus,
            aMailBoxId,
            aMessageId,
            aOperationObserver,
            aRequestId );
    CleanupStack::PushL( self );
    self->ConstructL(aMsgMapper,aContentType,aFilePath);
    CleanupStack::Pop( self ); 
    return self;
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::ConstructL
// ----------------------------------------------------------------------------
//
void CIpsPlgNewChildPartFromFileOperation::ConstructL(CIpsPlgMsgMapper *aMsgMapper,
    const TDesC& aContentType,
    const TDesC& aFilePath)
    {
    FUNC_LOG;
    iMsgMapper = aMsgMapper;
    iContentType = aContentType.AllocL();
    iFilePath = aFilePath.AllocL();

    // Start from attachment manager initialization
    InitAttachmentManagerL();
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::~CIpsPlgNewChildPartFromFileOperation
// ----------------------------------------------------------------------------
//
CIpsPlgNewChildPartFromFileOperation::~CIpsPlgNewChildPartFromFileOperation()
    {
    FUNC_LOG;
    Cancel(); // Cancel any request, if outstanding
    delete iOperation;
    iOperation = NULL;
    delete iContentType;
    iContentType = NULL;
    delete iFilePath;
    iFilePath = NULL;
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::DoCancel
// ----------------------------------------------------------------------------
//
void CIpsPlgNewChildPartFromFileOperation::DoCancel()
    {
    FUNC_LOG;

    if (iOperation)
        {
        iOperation->Cancel();
        }

    if (iMessage)
        {
        iMessage->AttachmentManager().CancelRequest();
        iMessage->Cancel();
        }

    TRequestStatus* status = &iObserverRequestStatus;
    if ( status && status->Int() == KRequestPending )
        {
        SignalFSObserver(iStatus.Int(),NULL);
        User::RequestComplete( status, iStatus.Int() );
        }
    }

// ----------------------------------------------------------------------------
// CIpsPlgSosBasePlugin::GetMessageEntryL( )
// Checks whether the requested message is already cached. If not, the cached 
// objects are deleted and new objects are created.
// ----------------------------------------------------------------------------
void CIpsPlgNewChildPartFromFileOperation::GetMessageEntryL( 
    TMsvId aId, 
    CMsvEntry*& aMessageEntry,
    CImEmailMessage*& aImEmailMessage )
    {
    FUNC_LOG;
    if ( !iCachedEntry || ( aId != iCachedEntry->Entry().Id() ) ||
            iCachedEmailMessage->IsActive() )
        {
        CleanCachedMessageEntries();
        
        iCachedEntry = iMsvSession.GetEntryL( aId );
        if ( iCachedEntry->Entry().iType == KUidMsvMessageEntry )
            {
            iCachedEmailMessage = CImEmailMessage::NewL( *iCachedEntry );
            }
        }
    aMessageEntry = iCachedEntry;
    aImEmailMessage = iCachedEmailMessage;
    }

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//
void CIpsPlgNewChildPartFromFileOperation::CleanCachedMessageEntries()
    {
    FUNC_LOG;
    delete iCachedEmailMessage;
    iCachedEmailMessage = NULL;
    delete iCachedEntry;
    iCachedEntry = NULL;
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::RunL
// ----------------------------------------------------------------------------
//
void CIpsPlgNewChildPartFromFileOperation::RunL()
    {
    if( iStatus.Int() == KErrNone )
        {
            // Divided to 3 steps. Run asunchronously after InitAttachmentManagerL.
            // PrepareMsvEntryL, PrepareStoreL and StoreMessagePartL respectively
            switch (iStep)
            {
            case EPrepareMsvEntry:
                PrepareMsvEntryL();
                break;
            case EPrepareStore:
                PrepareStoreL();
                break;
            case EStoreMessagePart:
                StoreMessagePartL();
                break;
            }
        }
    else if (iStatus.Int() == KErrCancel) 
        {
        // Do Nothing
        }
    else
        {
        User::Leave(iStatus.Int());
        }
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::InitAttachmentManagerL
// ----------------------------------------------------------------------------
//
void CIpsPlgNewChildPartFromFileOperation::InitAttachmentManagerL()
    {
    iEntry = NULL;
    iMessage = NULL;
    RFile file;
    TInt fileSize( 0 );

    // Read attachment size
    User::LeaveIfError(
        file.Open( iMsvSession.FileSession(), iFilePath->Des(), EFileShareReadersOnly )
        );
 
    //in rare case that file has disappeared while sending
    //we just won't get the size for it
    file.Size( fileSize );
    file.Close();    

    // Initialize CMsvAttachment instance for the attachment creation
    CMsvAttachment* info = CMsvAttachment::NewL( CMsvAttachment::EMsvFile );
    CleanupStack::PushL( info );

    info->SetAttachmentNameL( iFilePath->Des() );
    info->SetSize( fileSize );

    // Create/acquire Symbian message entry objects
    GetMessageEntryL( iMessageId.Id(), iEntry, iMessage );

    // Start attachment creation
    iMessage->AttachmentManager().AddAttachmentL( 
        iFilePath->Des(), info, iStatus );
    CleanupStack::Pop( info ); // attachment manager takes ownership
    iStep = EPrepareMsvEntry; // Next step
    SetActive();
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::PrepareMsvEntryL
// ----------------------------------------------------------------------------
//
void CIpsPlgNewChildPartFromFileOperation::PrepareMsvEntryL()
    {
    // Dig out the entry ID of the new attachment
    iMessage->GetAttachmentsListL( iEntry->Entry().Id( ), 
        CImEmailMessage::EAllAttachments, CImEmailMessage::EThisMessageOnly );
    TKeyArrayFix key( 0, ECmpTInt32 );
    CMsvEntrySelection* attachmentIds = iMessage->Selection().CopyLC();
    attachmentIds->Sort( key );
    if ( !attachmentIds->Count() )
        {
        User::Leave( KErrGeneral );
        }
    iNewAttachmentId = (*attachmentIds)[ attachmentIds->Count()-1 ];
    CleanupStack::PopAndDestroy( attachmentIds );
    
    CMsvEntry* cAtta = iMsvSession.GetEntryL( iNewAttachmentId );
    CleanupStack::PushL( cAtta );
    
    // Set filename to iDetails
    TMsvEntry tEntry = cAtta->Entry();
    tEntry.iDetails.Set(iFilePath->Des());

    // Do async
    iOperation = cAtta->ChangeL( tEntry, iStatus );
    CleanupStack::PopAndDestroy( cAtta );
    iStep = EPrepareStore; // Next step
    SetActive();
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::PrepareStoreL
// ----------------------------------------------------------------------------
//
void CIpsPlgNewChildPartFromFileOperation::PrepareStoreL()
    {
    CMsvEntry* cAtta = iMsvSession.GetEntryL( iNewAttachmentId );
    CleanupStack::PushL( cAtta );
    TBool parentToMultipartAlternative( EFalse );
    if( cAtta->HasStoreL() )
        {
        CMsvStore* store = cAtta->EditStoreL();
        CleanupStack::PushL( store );
        CImMimeHeader* mimeHeader = CImMimeHeader::NewLC();
        
        if( store->IsPresentL( KUidMsgFileMimeHeader ) )
            {
            mimeHeader->RestoreL( *store );
            CDesC8Array& array = mimeHeader->ContentTypeParams();
            array.AppendL( KMethod );
            parentToMultipartAlternative = ETrue;
            
            if( iContentType->Des().Find( KMimeTextCalRequest ) != KErrNotFound )
                {    
                array.AppendL( KRequest );
                }
            else if( iContentType->Des().Find( KMimeTextCalResponse ) != KErrNotFound )
                {
                array.AppendL( KResponse );
                }
            else if( iContentType->Des().Find( KMimeTextCalCancel ) != KErrNotFound ) 
                {
                array.AppendL( KCancel );
                }
            else
                {
                parentToMultipartAlternative = EFalse;
                }
            mimeHeader->StoreWithoutCommitL( *store );
            store->CommitL();
            }
        
        CleanupStack::PopAndDestroy( 2, store );
        }

    if( parentToMultipartAlternative &&
        iFilePath->Find( KFileExtensionICS ) != KErrNotFound )
        {        
        TMsvEntry tAttaEntry = cAtta->Entry();
        TMsvId id = tAttaEntry.Parent();
        CMsvEntry* cParent = iMsvSession.GetEntryL( id );
        CleanupStack::PushL( cParent );
        
        TMsvEmailEntry tEntry = cParent->Entry();
        tEntry.SetMessageFolderType( EFolderTypeAlternative );
        
        // Do async again if needed

        iOperation = cParent->ChangeL( tEntry, iStatus );
        CleanupStack::PopAndDestroy( cParent );
        CleanupStack::PopAndDestroy( cAtta );
        }
    else
        {
        CleanupStack::PopAndDestroy( cAtta );
        iStatus = KRequestPending;
        TRequestStatus* status = &iStatus;
        User::RequestComplete(status,KErrNone);
        }
    iStep = EStoreMessagePart; // Next step
    SetActive();
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::StoreMessagePartL
// ----------------------------------------------------------------------------
//
void CIpsPlgNewChildPartFromFileOperation::StoreMessagePartL()
    {
    // Delete the message entries to get all the changes to disk and 
    // possible store locks released
    CleanCachedMessageEntries();
    
    CFSMailMessagePart* result ( NULL );
    // Create the FS message part object
    result = iMsgMapper->GetMessagePartL( iNewAttachmentId, iFSMailboxId, 
        iMessageId );

    // Set attachment name
    result->SetAttachmentNameL(iFilePath->Des());

    // store message part
    result->SaveL();
    
    // set flag
    result->SetFlag(EFSMsgFlag_Attachments);
    
    SignalFSObserver(iStatus.Int(),result);
    // nothing left to process, so complete the observer
    TRequestStatus* status = &iObserverRequestStatus;
    User::RequestComplete( status, iStatus.Int() );
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::RunError
// ----------------------------------------------------------------------------
//
TInt CIpsPlgNewChildPartFromFileOperation::RunError(TInt aError)
    {
    FUNC_LOG;
    SignalFSObserver( aError, NULL );
    
    TRequestStatus* status = &iObserverRequestStatus;
    User::RequestComplete( status, aError );
    return KErrNone; // RunError must return KErrNone to active sheduler.
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::SignalFSObserver
// ----------------------------------------------------------------------------
//
void CIpsPlgNewChildPartFromFileOperation::SignalFSObserver(
        TInt aStatus, CFSMailMessagePart* aMessagePart )
    {
    FUNC_LOG;
    if ( aStatus == KErrCancel )
        {
        iFSProgress.iProgressStatus = TFSProgress::EFSStatus_RequestCancelled;
        iFSProgress.iError = KErrCancel;
        iFSProgress.iParam = NULL;
        }
    else
        {
        iFSProgress.iProgressStatus = TFSProgress::EFSStatus_RequestComplete;
        iFSProgress.iError = aStatus;
        iFSProgress.iParam = aMessagePart;
        }

    TRAP_IGNORE( iOperationObserver.RequestResponseL( iFSProgress, iFSRequestId ) );
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::ProgressL
// ----------------------------------------------------------------------------
//
const TDesC8& CIpsPlgNewChildPartFromFileOperation::ProgressL()
    {
    FUNC_LOG;
    // Make sure that operation is active
    return (IsActive() && iOperation) ? 
        iOperation->ProgressL() : KNullDesC8;
    }

// ---------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::GetErrorProgressL
// ---------------------------------------------------------------------------
//   
const TDesC8& CIpsPlgNewChildPartFromFileOperation::GetErrorProgressL( TInt /*aError*/ )
    {
    FUNC_LOG;
    return KNullDesC8; // error progress info not supported
    }

// ---------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::GetFSProgressL
// ---------------------------------------------------------------------------
//   
TFSProgress CIpsPlgNewChildPartFromFileOperation::GetFSProgressL() const
    {
    FUNC_LOG;
    return iFSProgress;
    }

// ----------------------------------------------------------------------------
// CIpsPlgNewChildPartFromFileOperation::IpsOpType
// ----------------------------------------------------------------------------    
TIpsOpType CIpsPlgNewChildPartFromFileOperation::IpsOpType() const
    {
    FUNC_LOG;
    return EIpsOpTypeNewChildPartFromFile;
    }

//  End of File

// </qmail>