ipsservices/ipssosplugin/src/ipsplgnewchildpartfromfileoperation.cpp
changeset 18 578830873419
child 20 ecc8def7944a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipsservices/ipssosplugin/src/ipsplgnewchildpartfromfileoperation.cpp	Fri Apr 16 14:51:52 2010 +0300
@@ -0,0 +1,417 @@
+/*
+* 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>