ipsservices/ipssosplugin/src/ipsplgnewchildpartfromfileoperation.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 14:51:52 +0300
changeset 18 578830873419
child 20 ecc8def7944a
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/*
* 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;" );

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

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

// ----------------------------------------------------------------------------
// CCIpsPlgNewChildPartFromFileOperation::CCIpsPlgNewChildPartFromFileOperation
// ----------------------------------------------------------------------------
//
CCIpsPlgNewChildPartFromFileOperation::CCIpsPlgNewChildPartFromFileOperation(
    CMsvSession& aMsvSession,
    TRequestStatus& aObserverRequestStatus,
    const TFSMailMsgId& aMailBoxId,
    const TFSMailMsgId& aMessageId,
    MFSMailRequestObserver& aOperationObserver,
    const TInt aRequestId)
    :
    CMsvOperation( 
    aMsvSession, 
    CActive::EPriorityStandard, 
    aObserverRequestStatus),
    iMailBoxId(aMailBoxId),
    iMessageId(aMessageId),
    iOperationObserver(aOperationObserver),
    iRequestId(aRequestId)
    {
    FUNC_LOG;
    CActiveScheduler::Add( this );
    }

// ----------------------------------------------------------------------------
// CCIpsPlgNewChildPartFromFileOperation::NewL
// ----------------------------------------------------------------------------
//
CCIpsPlgNewChildPartFromFileOperation* CCIpsPlgNewChildPartFromFileOperation::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;
    CCIpsPlgNewChildPartFromFileOperation* self =
        new (ELeave) CCIpsPlgNewChildPartFromFileOperation(
            aMsvSession,
            aObserverRequestStatus,
            aMailBoxId,
            aMessageId,
            aOperationObserver,
            aRequestId );
    CleanupStack::PushL( self );
    self->ConstructL(aMsgMapper,aContentType,aFilePath);
    CleanupStack::Pop( self ); 
    return self;
    }

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

    // Start async request in RunL
    iStep = EStep1; // First step
    SetActive();
    iStatus = KRequestPending;
    TRequestStatus* status = &iStatus;
    User::RequestComplete(status,KErrNone);
    }

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

// ----------------------------------------------------------------------------
// CCIpsPlgNewChildPartFromFileOperation::DoCancel
// ----------------------------------------------------------------------------
//
void CCIpsPlgNewChildPartFromFileOperation::DoCancel()
    {
    FUNC_LOG;
    if (iOperation)
        {
        iOperation->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 CCIpsPlgNewChildPartFromFileOperation::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 CCIpsPlgNewChildPartFromFileOperation::CleanCachedMessageEntries()
    {
    FUNC_LOG;
    delete iCachedEmailMessage;
    iCachedEmailMessage = NULL;
    delete iCachedEntry;
    iCachedEntry = NULL;
    }

// ----------------------------------------------------------------------------
// CCIpsPlgNewChildPartFromFileOperation::RunL
// ----------------------------------------------------------------------------
//
void CCIpsPlgNewChildPartFromFileOperation::RunL()
    {
    if( iStatus.Int() == KErrNone )
        // divided to 4 steps, run asunchronously from 1 to 4
        switch (iStep)
        {
            case EStep1:
                {
                iEntry = NULL;
                iMessage = NULL;
                RFile file;
                TInt fileSize( 0 );

                // Read attachment size
                TRAPD(err,file.Open( iMsvSession.FileSession(), iFilePath->Des(), EFileShareReadersOnly ));
                if (err != KErrNone)
                    {
                    RunError(err);
                    }
             
                //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
                iStatus = KRequestPending;
                iMessage->AttachmentManager().AddAttachmentL( 
                    iFilePath->Des(), info, iStatus );
                CleanupStack::Pop( info ); // attachment manager takes ownership
                iStep = EStep2; // Next step
                SetActive();
                break;
                }
            case EStep2:
                {
                // Dig out the entry ID of the new attachment (unbelievable that
                // there seems to be no better way to do this)
                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
                iStatus = KRequestPending;
                cAtta->ChangeL( tEntry, iStatus );
                CleanupStack::PopAndDestroy( cAtta );
                iStep = EStep3; // Next step
                SetActive();
                break;
                }
            case EStep3:
                {
                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( _L(".ics")) != 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
                    iStatus = KRequestPending;
                    cParent->ChangeL( tEntry, iStatus );
                    CleanupStack::PopAndDestroy( cParent );
                    CleanupStack::PopAndDestroy( cAtta );
                    iStep = EStep4; // Next step
                    SetActive();
                    break;
                    }
                CleanupStack::PopAndDestroy( cAtta );
                iStep = EStep4; // Next step
                // Continue to next step wihout break;
                }
            case EStep4:
                {
                // 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, iMailBoxId, 
                    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() );
                break;
                }
        }
    }

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

// ----------------------------------------------------------------------------
// CCIpsPlgNewChildPartFromFileOperation::SignalFSObserver
// ----------------------------------------------------------------------------
//
void CCIpsPlgNewChildPartFromFileOperation::SignalFSObserver(
        TInt aStatus, CFSMailMessagePart* aMessagePart )
    {
    FUNC_LOG;
    TFSProgress result =
        { TFSProgress::EFSStatus_Waiting, 0, 0, KErrNone, aMessagePart };
    
    if ( aStatus == KErrCancel )
        {
        result.iProgressStatus = TFSProgress::EFSStatus_RequestCancelled;
        result.iError = KErrCancel;
        }
    else
        {
        result.iProgressStatus = TFSProgress::EFSStatus_RequestComplete;
        result.iError = aStatus;
        }

    TRAP_IGNORE( iOperationObserver.RequestResponseL( result, iRequestId ) );
    }

// ----------------------------------------------------------------------------
// CCIpsPlgNewChildPartFromFileOperation::ProgressL
// ----------------------------------------------------------------------------
//
const TDesC8& CCIpsPlgNewChildPartFromFileOperation::ProgressL()
    {
    FUNC_LOG;
    // Make sure that operation is active
    if ( IsActive() )
        {
        // Get progress
        if ( iOperation )
            {
            return iOperation->ProgressL();
            }
        }
    return iBlank;
    }

//  End of File

// </qmail>