|         |      1 /* | 
|         |      2 * Copyright (c) 2002-2006 Nokia Corporation and/or its subsidiary(-ies). | 
|         |      3 * All rights reserved. | 
|         |      4 * This component and the accompanying materials are made available | 
|         |      5 * under the terms of "Eclipse Public License v1.0" | 
|         |      6 * which accompanies this distribution, and is available | 
|         |      7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". | 
|         |      8 * | 
|         |      9 * Initial Contributors: | 
|         |     10 * Nokia Corporation - initial contribution. | 
|         |     11 * | 
|         |     12 * Contributors: | 
|         |     13 * | 
|         |     14 * Description:  mail message class | 
|         |     15 * | 
|         |     16 */ | 
|         |     17  | 
|         |     18  | 
|         |     19  | 
|         |     20 // INCLUDE FILES | 
|         |     21 #include    "CMailMessage.h" | 
|         |     22 #include    <MMailMessageView.h> | 
|         |     23 #include    <MMessageLoadObserver.h> | 
|         |     24 #include    "MailLog.h" | 
|         |     25 #include    <miuthdr.h> // CImHeader | 
|         |     26 #include    <miutmsg.h> | 
|         |     27 #include    <miutconv.h> | 
|         |     28 #include    <charconv.h> | 
|         |     29 #include    <featmgr.h> | 
|         |     30 #include    <MuiuOperationWait.h> | 
|         |     31 #include 	<mmsvattachmentmanager.h> | 
|         |     32 #include    <ErrorUI.h> | 
|         |     33  | 
|         |     34 // MODULE DATA STRUCTURES | 
|         |     35 enum TLoadState | 
|         |     36     { | 
|         |     37     ELoadMessageBody = 1, | 
|         |     38     EHtmlNotFound, | 
|         |     39     ELoadAttachments, | 
|         |     40     ELoadAttachedMessages, | 
|         |     41     ELoadLinkedHtmlContent | 
|         |     42     }; | 
|         |     43  | 
|         |     44 // Constants | 
|         |     45 enum MessageFlags | 
|         |     46     { | 
|         |     47     EFlagAttachment = KBit0, | 
|         |     48     EFlagAttachedMessages = KBit1, | 
|         |     49     EFlagStopAfterLoad = KBit2, | 
|         |     50     EFlagHtmlError = KBit3, | 
|         |     51     EFlagHtmlMessageCharSetOverridden = KBit4 | 
|         |     52     }; | 
|         |     53  | 
|         |     54 // ============================ MEMBER FUNCTIONS =============================== | 
|         |     55  | 
|         |     56 // ----------------------------------------------------------------------------- | 
|         |     57 // CMailMessage::CMailMessage | 
|         |     58 // C++ default constructor can NOT contain any code, that | 
|         |     59 // might leave. | 
|         |     60 // ----------------------------------------------------------------------------- | 
|         |     61 // | 
|         |     62 CMailMessage::CMailMessage() | 
|         |     63 : CActive(0), iFlags(0) | 
|         |     64     { | 
|         |     65     } | 
|         |     66  | 
|         |     67 // ----------------------------------------------------------------------------- | 
|         |     68 // CMailMessage::ConstructL | 
|         |     69 // Symbian 2nd phase constructor can leave. | 
|         |     70 // ----------------------------------------------------------------------------- | 
|         |     71 // | 
|         |     72 void CMailMessage::ConstructL(CMsvEntry& aEntry) | 
|         |     73     { | 
|         |     74     CActiveScheduler::Add(this); | 
|         |     75  | 
|         |     76     iHeader = CImHeader::NewLC(); | 
|         |     77     CleanupStack::Pop(); | 
|         |     78     iEntry = aEntry.Session().GetEntryL( aEntry.EntryId() ); | 
|         |     79  | 
|         |     80     iMessage = CImEmailMessage::NewL(*iEntry); | 
|         |     81     iMessageID = iEntry->EntryId(); | 
|         |     82     if (iEntry->HasStoreL()) | 
|         |     83         { | 
|         |     84         CMsvStore* msvStore = iEntry->ReadStoreL(); | 
|         |     85         CleanupStack::PushL(msvStore); | 
|         |     86         TRAP_IGNORE(iHeader->RestoreL(*msvStore)); | 
|         |     87         CleanupStack::PopAndDestroy(); // store | 
|         |     88         } | 
|         |     89  | 
|         |     90     iGlobalParaLayer = CParaFormatLayer::NewL(); | 
|         |     91     iGlobalCharLayer = CCharFormatLayer::NewL(); | 
|         |     92  | 
|         |     93     iBodyText = CRichText::NewL( | 
|         |     94         iGlobalParaLayer, | 
|         |     95         iGlobalCharLayer); | 
|         |     96  | 
|         |     97 	iLinkedHtmlItems = new( ELeave ) RPointerArray< | 
|         |     98 		CLinkedHtmlItem>(5);		// CSI: 47 # approx granularity 5 | 
|         |     99  | 
|         |    100     iAsyncWait = CMuiuOperationWait::NewLC(); //only NewLC variant exists | 
|         |    101     CleanupStack::Pop( iAsyncWait ); | 
|         |    102     } | 
|         |    103  | 
|         |    104 // ----------------------------------------------------------------------------- | 
|         |    105 // CMailMessage::NewL | 
|         |    106 // Two-phased constructor. | 
|         |    107 // ----------------------------------------------------------------------------- | 
|         |    108 // | 
|         |    109 EXPORT_C CMailMessage* CMailMessage::NewL(CMsvEntry& aEntry) | 
|         |    110     { | 
|         |    111     CMailMessage* self = new( ELeave ) CMailMessage(); | 
|         |    112     CleanupStack::PushL( self ); | 
|         |    113     self->ConstructL(aEntry); | 
|         |    114  | 
|         |    115     CleanupStack::Pop(); | 
|         |    116     return self; | 
|         |    117     } | 
|         |    118  | 
|         |    119  | 
|         |    120 // Destructor | 
|         |    121 CMailMessage::~CMailMessage() | 
|         |    122     { | 
|         |    123     Cancel(); | 
|         |    124     delete iAsyncWait; // gets cancelled if running | 
|         |    125     delete iHeader; | 
|         |    126     delete iMessage; | 
|         |    127     delete iBodyText; | 
|         |    128     delete iGlobalParaLayer; | 
|         |    129     delete iGlobalCharLayer; | 
|         |    130     delete iURI; | 
|         |    131     delete iEntry; | 
|         |    132     if ( iLinkedHtmlItems ) | 
|         |    133         { | 
|         |    134         iLinkedHtmlItems->ResetAndDestroy(); | 
|         |    135         delete iLinkedHtmlItems; | 
|         |    136         } | 
|         |    137  | 
|         |    138    	iWaitArray.ResetAndDestroy(); | 
|         |    139     } | 
|         |    140  | 
|         |    141  | 
|         |    142 EXPORT_C void CMailMessage::LoadMessageL( | 
|         |    143     MMessageLoadObserver& aMessageObserver) | 
|         |    144     { | 
|         |    145     iState = ELoadMessageBody; | 
|         |    146     iMessageObserver = &aMessageObserver; | 
|         |    147  | 
|         |    148     // Header is already loaded | 
|         |    149     NotifyObserverL(EHeaderReady); | 
|         |    150  | 
|         |    151     if( !MessageEntry().MHTMLEmail() ) | 
|         |    152         { | 
|         |    153         LoadBodyTextL(); | 
|         |    154         } | 
|         |    155     else | 
|         |    156         { | 
|         |    157    		LoadAttachmentsL(); | 
|         |    158         } | 
|         |    159     SetActive(); | 
|         |    160     } | 
|         |    161  | 
|         |    162 // ----------------------------------------------------------------------------- | 
|         |    163 // CMailMessage::LoadLinkedHtmlContentL | 
|         |    164 // ----------------------------------------------------------------------------- | 
|         |    165 // | 
|         |    166 EXPORT_C void CMailMessage::LoadLinkedHtmlContentL( | 
|         |    167 	const TDesC& aBase, const TDesC& aURI) | 
|         |    168 	{ | 
|         |    169 	LoadLinkedHTMLContentL(aBase, aURI); | 
|         |    170 	} | 
|         |    171  | 
|         |    172 // ----------------------------------------------------------------------------- | 
|         |    173 // CMailMessage::HtmlCharsetIdL | 
|         |    174 // ----------------------------------------------------------------------------- | 
|         |    175 // | 
|         |    176 EXPORT_C TUint CMailMessage::HtmlCharsetIdL() | 
|         |    177     { | 
|         |    178     TUint charset = 0; | 
|         |    179     // | 
|         |    180     if (iMhtmlPartId != 0) | 
|         |    181         { | 
|         |    182         if ( iFlags & EFlagHtmlMessageCharSetOverridden ) | 
|         |    183             { | 
|         |    184             charset = iCharacterSetId; | 
|         |    185             } | 
|         |    186         else | 
|         |    187             { | 
|         |    188             CMsvEntry* htmlEntry = iEntry->Session().GetEntryL( iMhtmlPartId ); | 
|         |    189             CleanupStack::PushL( htmlEntry ); | 
|         |    190         	charset = DoGetMimeCharsetIdL( *htmlEntry ); | 
|         |    191             CleanupStack::PopAndDestroy( htmlEntry ); | 
|         |    192             } | 
|         |    193         } | 
|         |    194  | 
|         |    195 	LOG1( "CMailMessage::HtmlCharsetIdL %08x", charset ); | 
|         |    196     return charset; | 
|         |    197     } | 
|         |    198  | 
|         |    199 // ----------------------------------------------------------------------------- | 
|         |    200 // CMailMessage::CharsetIdL | 
|         |    201 // ----------------------------------------------------------------------------- | 
|         |    202 // | 
|         |    203 EXPORT_C TUint CMailMessage::CharsetIdL() | 
|         |    204     { | 
|         |    205     TUint characterSetId(0); | 
|         |    206     TBool override; | 
|         |    207     iMessage->GetCharacterSetL( iMessageID, characterSetId, override); | 
|         |    208 	LOG1( "CMailMessage::CharsetIdL from CImEmailMessage %08x", | 
|         |    209 	    	characterSetId ); | 
|         |    210 	if ( characterSetId != 0 ) | 
|         |    211 	    { | 
|         |    212 	    return characterSetId; | 
|         |    213 	    } | 
|         |    214  | 
|         |    215     if( iEntry->Entry().Id() != iMessageID ) | 
|         |    216     	iEntry->SetEntryL(iMessageID); | 
|         |    217  | 
|         |    218    	return DoGetMimeCharsetIdL( *iEntry ); | 
|         |    219     } | 
|         |    220  | 
|         |    221 // ----------------------------------------------------------------------------- | 
|         |    222 // CMailMessage::ConvertToCharsetL | 
|         |    223 // ----------------------------------------------------------------------------- | 
|         |    224 // | 
|         |    225 EXPORT_C void CMailMessage::ConvertToCharsetL(TUint aCharsetId) | 
|         |    226     { | 
|         |    227     iMessage->SetCharacterSetL( iMessageID, aCharsetId ); | 
|         |    228     } | 
|         |    229  | 
|         |    230  | 
|         |    231 // ----------------------------------------------------------------------------- | 
|         |    232 // CMailMessage::AttachmentManager | 
|         |    233 // ----------------------------------------------------------------------------- | 
|         |    234 // | 
|         |    235 EXPORT_C MMsvAttachmentManager& CMailMessage::AttachmentManager() const | 
|         |    236     { | 
|         |    237     ASSERT( iState == ELoadAttachments ); | 
|         |    238 	LOG2( "CMailMessage::AttachmentManager %08x - %08x", | 
|         |    239 	    iMessageID, | 
|         |    240 	    iEntry->EntryId() ); | 
|         |    241     // context still in message ? | 
|         |    242     if( iEntry->Entry().Id() != iMessageID ) | 
|         |    243     	TRAP_IGNORE( iEntry->SetEntryL(iMessageID) ); | 
|         |    244     return iMessage->AttachmentManager(); | 
|         |    245     } | 
|         |    246  | 
|         |    247 // ----------------------------------------------------------------------------- | 
|         |    248 // CMailMessage::LoadAttachmentsL | 
|         |    249 // ----------------------------------------------------------------------------- | 
|         |    250 // | 
|         |    251 EXPORT_C void CMailMessage::LoadAttachmentsL(MMessageLoadObserver& aObserver) | 
|         |    252 	{ | 
|         |    253 	iMessageObserver = &aObserver; | 
|         |    254 	Cancel(); | 
|         |    255 	LoadAttachmentsL(); | 
|         |    256 	iFlags |= EFlagStopAfterLoad; | 
|         |    257 	SetActive(); | 
|         |    258 	} | 
|         |    259  | 
|         |    260 // ----------------------------------------------------------------------------- | 
|         |    261 // CMailMessage::LoadAttachedMessagesL | 
|         |    262 // ----------------------------------------------------------------------------- | 
|         |    263 // | 
|         |    264 EXPORT_C void CMailMessage::LoadAttachedMessagesL( | 
|         |    265 	MMessageLoadObserver& aObserver) | 
|         |    266 	{ | 
|         |    267 	iMessageObserver = &aObserver; | 
|         |    268 	Cancel(); | 
|         |    269 	LoadAttachedMessagesL(); | 
|         |    270 	iFlags |= EFlagStopAfterLoad; | 
|         |    271 	SetActive(); | 
|         |    272 	} | 
|         |    273  | 
|         |    274 // ----------------------------------------------------------------------------- | 
|         |    275 // CMailMessage::LoadHtmlContentL | 
|         |    276 // ----------------------------------------------------------------------------- | 
|         |    277 // | 
|         |    278 EXPORT_C void CMailMessage::LoadHtmlContentL(MMessageLoadObserver& aObserver) | 
|         |    279 	{ | 
|         |    280 	iMessageObserver = &aObserver; | 
|         |    281 	Cancel(); | 
|         |    282 	LoadHTMLContentL(); | 
|         |    283 	iFlags |= EFlagStopAfterLoad; | 
|         |    284 	SetActive(); | 
|         |    285 	} | 
|         |    286  | 
|         |    287 // ----------------------------------------------------------------------------- | 
|         |    288 // CMailMessage::LoadLinkedHtmlContentL | 
|         |    289 // ----------------------------------------------------------------------------- | 
|         |    290 // | 
|         |    291 EXPORT_C void CMailMessage::LoadLinkedHtmlContentL( | 
|         |    292         	const TDesC& aBase, | 
|         |    293         	const TDesC& aURI, | 
|         |    294         	MMessageLoadObserver& aObserver ) | 
|         |    295 	{ | 
|         |    296 	iMessageObserver = &aObserver; | 
|         |    297 	Cancel(); | 
|         |    298 	delete iURI; | 
|         |    299 	iURI = NULL; | 
|         |    300 	iURI = aURI.AllocL(); | 
|         |    301  | 
|         |    302 	LoadLinkedHTMLContentL( aBase, aURI ); | 
|         |    303 	iFlags |= EFlagStopAfterLoad; | 
|         |    304 	SetActive(); | 
|         |    305 	} | 
|         |    306  | 
|         |    307 // ----------------------------------------------------------------------------- | 
|         |    308 // CMailMessage::GetFileHandleL | 
|         |    309 // ----------------------------------------------------------------------------- | 
|         |    310 // | 
|         |    311 EXPORT_C RFile CMailMessage::GetFileHandleL( TMsvAttachmentId aId ) | 
|         |    312     { | 
|         |    313     LOG( ">CMailMessage::GetFileHandleL" ); | 
|         |    314     Cancel(); | 
|         |    315     // Force message cancel for special cases(lost network coverage) | 
|         |    316     if ( iMessage ) | 
|         |    317     	{ | 
|         |    318     	iMessage->Cancel(); | 
|         |    319     	} | 
|         |    320  | 
|         |    321     // create an array for active scheduler waits if it does not exist | 
|         |    322     CMuiuOperationWait* wait = CMuiuOperationWait::NewLC(); //only NewLC variant exists | 
|         |    323     // append the wait to the array | 
|         |    324     iWaitArray.AppendL( wait ); | 
|         |    325     CleanupStack::Pop( wait ); | 
|         |    326  | 
|         |    327     RFile handle; | 
|         |    328  | 
|         |    329     if ( aId == iMhtmlPartId ) | 
|         |    330         { | 
|         |    331         // html body part | 
|         |    332         iMessage->FindFirstHTMLPageFileHandleL( iMessageID, | 
|         |    333                                                 wait->iStatus ); | 
|         |    334         wait->Start(); | 
|         |    335         User::LeaveIfError( wait->iStatus.Int() ); | 
|         |    336  | 
|         |    337         User::LeaveIfError( | 
|         |    338             iMessage->GetUniversalResourceIdentifierFileHandle( | 
|         |    339             iMhtmlPartId, handle) ); | 
|         |    340  | 
|         |    341         } | 
|         |    342     else if ( IsLinkedItemL( handle, aId) ) | 
|         |    343         { | 
|         |    344         // linked html item | 
|         |    345         } | 
|         |    346     else | 
|         |    347         { | 
|         |    348         // normal attachment | 
|         |    349  | 
|         |    350         //Async version of GetAttachmentsListL used here, | 
|         |    351         //because it is quite slow operation and when there is | 
|         |    352         //many attachments to be loaded Ui jams if synchrounous | 
|         |    353         //method is called. | 
|         |    354  | 
|         |    355         iMessage->GetAttachmentsListL( | 
|         |    356             wait->iStatus, | 
|         |    357             iMessageID, | 
|         |    358             CImEmailMessage::EAllAttachments, | 
|         |    359             CImEmailMessage::EThisMessageAndEmbeddedMessages ); | 
|         |    360  | 
|         |    361         LOG( "CMailMessage::GetFileHandleL: Starting wait" ); | 
|         |    362         wait->Start(); | 
|         |    363         LOG( "CMailMessage::GetFileHandleL: Wait finished" ); | 
|         |    364  | 
|         |    365         User::LeaveIfError( wait->iStatus.Int() ); | 
|         |    366  | 
|         |    367         LOG( "CMailMessage::GetFileHandleL: Status ok" ); | 
|         |    368         MMsvAttachmentManager& manager = iMessage->AttachmentManager(); | 
|         |    369         handle = manager.GetAttachmentFileL( aId ); | 
|         |    370         } | 
|         |    371  | 
|         |    372     // clean up the wait array for any non-active waits | 
|         |    373     CleanupWaitArray(); | 
|         |    374  | 
|         |    375     __ASSERT_DEBUG( handle.SubSessionHandle() != 0, User::Invariant() ); | 
|         |    376  | 
|         |    377     LOG( "<CMailMessage::GetFileHandleL" ); | 
|         |    378     return handle; | 
|         |    379     } | 
|         |    380  | 
|         |    381 // ----------------------------------------------------------------------------- | 
|         |    382 // CMailMessage::CleanupWaitArray | 
|         |    383 // ----------------------------------------------------------------------------- | 
|         |    384 // | 
|         |    385 void CMailMessage::CleanupWaitArray() | 
|         |    386 	{ | 
|         |    387 	TInt count( iWaitArray.Count() ); | 
|         |    388     // cleanup the whole array | 
|         |    389     for( TInt i = count - 1; i >= 0; i-- ) | 
|         |    390     	{ | 
|         |    391     	CMuiuOperationWait* wait = iWaitArray[i]; | 
|         |    392     	if( !wait->IsActive() ) | 
|         |    393     		{ | 
|         |    394     		iWaitArray.Remove( i ); | 
|         |    395     		delete wait; | 
|         |    396     		} | 
|         |    397     	} | 
|         |    398 	} | 
|         |    399  | 
|         |    400 // ----------------------------------------------------------------------------- | 
|         |    401 // CMailMessage::OverrideHtmlMessageCharset | 
|         |    402 // ----------------------------------------------------------------------------- | 
|         |    403 // | 
|         |    404 EXPORT_C void CMailMessage::OverrideHtmlMessageCharset( TUint aCharSet ) | 
|         |    405     { | 
|         |    406     iCharacterSetId = aCharSet; | 
|         |    407  | 
|         |    408     if ( aCharSet ) | 
|         |    409         { | 
|         |    410         iFlags |= EFlagHtmlMessageCharSetOverridden; | 
|         |    411         } | 
|         |    412     else | 
|         |    413         { | 
|         |    414         iFlags &= ~EFlagHtmlMessageCharSetOverridden; | 
|         |    415         } | 
|         |    416     } | 
|         |    417 // ----------------------------------------------------------------------------- | 
|         |    418 // CMailMessage::DoCancel | 
|         |    419 // ----------------------------------------------------------------------------- | 
|         |    420 // | 
|         |    421 void CMailMessage::DoCancel() | 
|         |    422     { | 
|         |    423     LOG1("DoCancel @ iState:%d", iState); | 
|         |    424     if ( iMessage ) | 
|         |    425     	{ | 
|         |    426     	iMessage->Cancel(); | 
|         |    427     	} | 
|         |    428     } | 
|         |    429  | 
|         |    430 // ----------------------------------------------------------------------------- | 
|         |    431 // CMailMessage::RunL | 
|         |    432 // ----------------------------------------------------------------------------- | 
|         |    433 // | 
|         |    434 void CMailMessage::RunL() | 
|         |    435     { | 
|         |    436     switch(iState) | 
|         |    437         { | 
|         |    438         case ELoadMessageBody: | 
|         |    439             { | 
|         |    440             LOG("CMailMessage::RunL @ ELoadMessageBody"); | 
|         |    441             User::LeaveIfError( iStatus.Int() ); | 
|         |    442             // Body content loaded to iBodyText | 
|         |    443             // if HTML mail get file handle to content (iBodyText is empty) | 
|         |    444             if( MessageEntry().MHTMLEmail() && !(iFlags & EFlagHtmlError) ) | 
|         |    445                 { | 
|         |    446             	TInt error(KErrNone); | 
|         |    447                 // html file handle | 
|         |    448                 error = iMessage-> | 
|         |    449                     GetUniversalResourceIdentifierFileHandle( | 
|         |    450                     iMhtmlPartId, iHtmlFile); | 
|         |    451  | 
|         |    452 	            if (error == KErrNone) | 
|         |    453 	               	{ | 
|         |    454 	                iFlags |= EFlagAttachment; | 
|         |    455 	               	} | 
|         |    456 	            else | 
|         |    457 	            	{ | 
|         |    458 	               	// Can't load HTML, so try to load plain text body | 
|         |    459                     LOG1("CMailMessage::RunL @ Can't load HTML: %d", | 
|         |    460             	        error); | 
|         |    461 	               	iState = EHtmlNotFound; | 
|         |    462 	               	iFlags |= EFlagHtmlError; | 
|         |    463 	            	break; | 
|         |    464 	            	} | 
|         |    465                 } | 
|         |    466             NotifyObserverL(EBodyTextReady); | 
|         |    467             break; | 
|         |    468             } | 
|         |    469         case ELoadAttachments: | 
|         |    470             { | 
|         |    471             LOG("CMailMessage::RunL @ ELoadAttachments"); | 
|         |    472             // Attachment files loaded | 
|         |    473             User::LeaveIfError( iStatus.Int() ); | 
|         |    474             NotifyObserverL(EAttachmentsReady); | 
|         |    475             LOG("CMailMessage::RunL, NotifyObserverL returned"); | 
|         |    476             break; | 
|         |    477             } | 
|         |    478         case ELoadAttachedMessages: | 
|         |    479             { | 
|         |    480             // Attached files loaded | 
|         |    481             User::LeaveIfError( iStatus.Int() ); | 
|         |    482             const CMsvEntrySelection& sel = iMessage->Selection(); | 
|         |    483             TInt attachedCount(sel.Count()); | 
|         |    484             LOG1("CMailMessage::RunL @ ELoadAttachedMessages %d", | 
|         |    485             	attachedCount); | 
|         |    486             if (attachedCount) | 
|         |    487                 { | 
|         |    488                 iFlags |= EFlagAttachedMessages; | 
|         |    489                 } | 
|         |    490 			NotifyObserverL(EAttachedMessagesReady); | 
|         |    491             break; | 
|         |    492             } | 
|         |    493         case ELoadLinkedHtmlContent: | 
|         |    494             { | 
|         |    495             LOG("CMailMessage::RunL @ ELoadLinkedHtmlContent"); | 
|         |    496             // linked file loaded | 
|         |    497             TInt error = iMessage-> | 
|         |    498                     GetUniversalResourceIdentifierFileHandle( | 
|         |    499                     iLinkedfileId, iLinkedHtmlFile); | 
|         |    500             if ( error == KErrNone ) | 
|         |    501                 { | 
|         |    502                 CLinkedHtmlItem* htmlItem = new(ELeave) CLinkedHtmlItem( | 
|         |    503                     *iURI, iLinkedfileId ); | 
|         |    504                 CleanupStack::PushL( htmlItem ); | 
|         |    505                 iLinkedHtmlItems->AppendL( htmlItem ); | 
|         |    506                 CleanupStack::Pop( htmlItem ); | 
|         |    507                 } | 
|         |    508             else | 
|         |    509                 { | 
|         |    510                 // ignore errors. If fails linked item is not added to | 
|         |    511                 // attachment view. | 
|         |    512                 LOG1("CMailMessage::RunL @ ELoadLinkedHtmlContent error:%d", | 
|         |    513                      error); | 
|         |    514                 iLinkedHtmlFile = RFile(); // return empty handle | 
|         |    515                 iEntry->SetEntryL( iMessageID ); | 
|         |    516                 } | 
|         |    517 			NotifyObserverL(ELinkedFileReady); | 
|         |    518             break; | 
|         |    519             } | 
|         |    520         default: | 
|         |    521         	// all loading done. Do nothing | 
|         |    522             break; | 
|         |    523         } | 
|         |    524     DoNextStateL(); | 
|         |    525     } | 
|         |    526  | 
|         |    527 // ----------------------------------------------------------------------------- | 
|         |    528 // CMailMessage::RunError | 
|         |    529 // ----------------------------------------------------------------------------- | 
|         |    530 // | 
|         |    531 TInt CMailMessage::RunError(TInt aError) | 
|         |    532     { | 
|         |    533     LOG2("CMailMessage::RunError @ iState: %d, aError:%d", iState, aError); | 
|         |    534     // ActiveSheduler Panics if this returns != KErrNone | 
|         |    535     Cancel(); | 
|         |    536     //We have to return KLeaveExit(appui's exit code), otherwise our appui is not deleted | 
|         |    537     if(aError == KLeaveExit) | 
|         |    538         { | 
|         |    539         return KLeaveExit; | 
|         |    540         } | 
|         |    541     TRAP_IGNORE( ShowErrorNoteL( aError ) ); | 
|         |    542  | 
|         |    543     // exit from viewer app if OOM | 
|         |    544     if( aError == KErrNoMemory ) | 
|         |    545         { | 
|         |    546         return KLeaveExit; | 
|         |    547         } | 
|         |    548  | 
|         |    549     // Try to continue loading | 
|         |    550     TRAP_IGNORE( DoNextStateL() ); | 
|         |    551  | 
|         |    552     return KErrNone; | 
|         |    553     } | 
|         |    554  | 
|         |    555 // ----------------------------------------------------------------------------- | 
|         |    556 // CMailMessage::DoNextStateL | 
|         |    557 // ----------------------------------------------------------------------------- | 
|         |    558 // | 
|         |    559 void CMailMessage::DoNextStateL() | 
|         |    560     { | 
|         |    561 	// Step to next state | 
|         |    562     if ( (!(iFlags & EFlagStopAfterLoad) || | 
|         |    563         (iState == EHtmlNotFound)) | 
|         |    564         && NextStateL() ) | 
|         |    565         { | 
|         |    566         SetActive(); | 
|         |    567         } | 
|         |    568     else | 
|         |    569         { | 
|         |    570 		// message loaded | 
|         |    571         NotifyObserverL(ELoadEnd); | 
|         |    572         } | 
|         |    573     } | 
|         |    574  | 
|         |    575 // ----------------------------------------------------------------------------- | 
|         |    576 // CMailMessage::DoGetMimeCharsetIdL | 
|         |    577 // ----------------------------------------------------------------------------- | 
|         |    578 // | 
|         |    579 TUint CMailMessage::DoGetMimeCharsetIdL( CMsvEntry& aEntry ) | 
|         |    580     { | 
|         |    581     //Try to read the character set from two places: | 
|         |    582     // 1) Main entry's MIME headers | 
|         |    583     // 2) Child entrys' MIME headers | 
|         |    584     TUint characterSetId(0); | 
|         |    585  | 
|         |    586     // If the message store cannot be read, abort here | 
|         |    587     CMsvStore* store = NULL; | 
|         |    588     TRAPD( err, store = aEntry.ReadStoreL() ); | 
|         |    589     if( err != KErrNone ) | 
|         |    590         { | 
|         |    591         return 0; | 
|         |    592         } | 
|         |    593     CleanupStack::PushL(store); | 
|         |    594  | 
|         |    595     //------------------------------------------------ | 
|         |    596     // Option 1. Read the MIME header from main entry | 
|         |    597     //------------------------------------------------ | 
|         |    598     if (store->IsPresentL(KUidMsgFileMimeHeader)) | 
|         |    599         { | 
|         |    600         //Main entry's mime header | 
|         |    601     	CImMimeHeader* mime = CImMimeHeader::NewLC(); | 
|         |    602 	    mime->RestoreL(*store); | 
|         |    603 	    characterSetId = DetermineCharactersetIdFromMimeHeaderL( aEntry, mime ); | 
|         |    604         CleanupStack::PopAndDestroy(mime); | 
|         |    605         } | 
|         |    606  | 
|         |    607     //Store is no longer needed | 
|         |    608  	CleanupStack::PopAndDestroy(store); | 
|         |    609  | 
|         |    610  	//If character set is valid stop now | 
|         |    611  	if( characterSetId ) | 
|         |    612 	 	{ | 
|         |    613 	 	return characterSetId; | 
|         |    614 	 	} | 
|         |    615  | 
|         |    616      //-------------------------------------------------- | 
|         |    617     // Option 2. Read the MIME headers from child entrys' | 
|         |    618     //--------------------------------------------------- | 
|         |    619     CMsvEntrySelection* entrySelection = iEntry->ChildrenL(); | 
|         |    620     CleanupStack::PushL(entrySelection); | 
|         |    621  | 
|         |    622     //Go through the children | 
|         |    623 	TInt count = entrySelection->Count(); | 
|         |    624 	for (TInt counter = 0; counter < count; counter++) | 
|         |    625 		{ | 
|         |    626 		//Get the child entry | 
|         |    627 		CMsvEntry* child = iEntry->ChildEntryL((*entrySelection)[counter]); | 
|         |    628 		CleanupStack::PushL(child); | 
|         |    629  | 
|         |    630 		//Read child entry store | 
|         |    631 		CMsvStore* childStore = NULL; | 
|         |    632 		TRAPD( err, childStore = child->ReadStoreL() ); | 
|         |    633  | 
|         |    634 		//If error occurs in store read try the next children | 
|         |    635 		if( err ) | 
|         |    636 			{ | 
|         |    637 			CleanupStack::PopAndDestroy(child); | 
|         |    638 			continue; | 
|         |    639 			} | 
|         |    640  | 
|         |    641 		//Read the childs MIME header if they are available | 
|         |    642 		CleanupStack::PushL(childStore); | 
|         |    643 		if (childStore->IsPresentL(KUidMsgFileMimeHeader)) | 
|         |    644 			{ | 
|         |    645 			CImMimeHeader* mime = CImMimeHeader::NewLC(); | 
|         |    646 			mime->RestoreL( *childStore ); | 
|         |    647 			characterSetId = DetermineCharactersetIdFromMimeHeaderL( *child, mime ); | 
|         |    648 			CleanupStack::PopAndDestroy(mime); | 
|         |    649 			} | 
|         |    650 		CleanupStack::PopAndDestroy(childStore); | 
|         |    651 		CleanupStack::PopAndDestroy(child);	//This is brutal | 
|         |    652  | 
|         |    653 		//If we got the characterSetId set from this child we can stop | 
|         |    654 		if( characterSetId ) | 
|         |    655 			{ | 
|         |    656 			break; | 
|         |    657 			} | 
|         |    658 		} | 
|         |    659 	CleanupStack::PopAndDestroy(); // entrySelection | 
|         |    660  | 
|         |    661     return characterSetId; | 
|         |    662     } | 
|         |    663  | 
|         |    664 // ----------------------------------------------------------------------------- | 
|         |    665 // CMailMessage::DetermineCharactersetIdFromMimeHeader | 
|         |    666 // ----------------------------------------------------------------------------- | 
|         |    667 // | 
|         |    668 TUint CMailMessage::DetermineCharactersetIdFromMimeHeaderL( CMsvEntry& aEntry, | 
|         |    669 															const CImMimeHeader* aMime ) | 
|         |    670 	{ | 
|         |    671 	TUint characterSetFromMimeHeader(0); | 
|         |    672 	TUint characterSetFromContentType(0); | 
|         |    673  | 
|         |    674 	//Character can sometimes be read from MimeCharset | 
|         |    675 	characterSetFromMimeHeader = aMime->MimeCharset(); | 
|         |    676  | 
|         |    677 	//Determine character set from ContentTypeParams | 
|         |    678 	const CDesC8Array& array = aMime->ContentTypeParams(); | 
|         |    679     CCnvCharacterSetConverter* charconv =  CCnvCharacterSetConverter::NewLC(); | 
|         |    680     RFs& session = aEntry.Session().FileSession(); | 
|         |    681  | 
|         |    682     for(TInt i = 0; i < array.Count() && characterSetFromContentType == 0; i++) | 
|         |    683         { | 
|         |    684         characterSetFromContentType = charconv-> | 
|         |    685         	ConvertStandardNameOfCharacterSetToIdentifierL( array[i], session); | 
|         |    686         } | 
|         |    687     CleanupStack::PopAndDestroy(); //charconv | 
|         |    688  | 
|         |    689     //Determine whitch one we use: | 
|         |    690     //characterSetFromMimeHeader or characterSetFromContentType | 
|         |    691     if( characterSetFromMimeHeader ) | 
|         |    692     	return characterSetFromMimeHeader; | 
|         |    693     else if ( characterSetFromContentType ) | 
|         |    694     	return characterSetFromContentType; | 
|         |    695     else | 
|         |    696     	return 0; | 
|         |    697 	} | 
|         |    698  | 
|         |    699 // ----------------------------------------------------------------------------- | 
|         |    700 // CMailMessage::NextStateL | 
|         |    701 // ----------------------------------------------------------------------------- | 
|         |    702 // | 
|         |    703 TBool CMailMessage::NextStateL() | 
|         |    704     { | 
|         |    705     TBool retValue(ETrue); | 
|         |    706     switch(iState) | 
|         |    707         { | 
|         |    708         case ELoadMessageBody: | 
|         |    709             // load attachment next | 
|         |    710             LoadAttachmentsL(); | 
|         |    711             break; | 
|         |    712         case EHtmlNotFound: | 
|         |    713         	// Html content not found, so try plain content | 
|         |    714             LoadBodyTextL(); | 
|         |    715             break; | 
|         |    716         case ELoadAttachments: | 
|         |    717 			// FALLTROUGH | 
|         |    718 			// Load Attached messages only if clien requests them. | 
|         |    719         default: | 
|         |    720             // "ELoadAttachedMessages" or "ELoadLinkedHtmlContent" | 
|         |    721             // or unknown state, so we stop | 
|         |    722             retValue = EFalse; | 
|         |    723             break; | 
|         |    724         } | 
|         |    725     return retValue; | 
|         |    726     } | 
|         |    727  | 
|         |    728 // ----------------------------------------------------------------------------- | 
|         |    729 // CMailMessage::LoadBodyTextL | 
|         |    730 // ----------------------------------------------------------------------------- | 
|         |    731 // | 
|         |    732 void CMailMessage::LoadBodyTextL() | 
|         |    733     { | 
|         |    734     iState = ELoadMessageBody; | 
|         |    735  | 
|         |    736  | 
|         |    737     // delete the body text to avoid | 
|         |    738     // appending the same text in different | 
|         |    739     // character set at the end of the old text | 
|         |    740     delete iBodyText; | 
|         |    741     iBodyText = NULL; | 
|         |    742     iBodyText = CRichText::NewL( | 
|         |    743         iGlobalParaLayer, | 
|         |    744         iGlobalCharLayer); | 
|         |    745  | 
|         |    746     iMessage->GetBodyTextL(iStatus, | 
|         |    747         iMessageID, | 
|         |    748         CImEmailMessage::EThisMessageOnly, | 
|         |    749         *iBodyText, | 
|         |    750         *iGlobalParaLayer, | 
|         |    751         *iGlobalCharLayer); | 
|         |    752  | 
|         |    753     } | 
|         |    754  | 
|         |    755 // ----------------------------------------------------------------------------- | 
|         |    756 // CMailMessage::LoadHTMLContentL | 
|         |    757 // ----------------------------------------------------------------------------- | 
|         |    758 // | 
|         |    759 void CMailMessage::LoadHTMLContentL() | 
|         |    760     { | 
|         |    761     iState = ELoadMessageBody; | 
|         |    762     iMessage->FindFirstHTMLPageFileHandleL(iMessageID, iStatus); | 
|         |    763     } | 
|         |    764  | 
|         |    765 // ----------------------------------------------------------------------------- | 
|         |    766 // CMailMessage::LoadLinkedHTMLContentL | 
|         |    767 // ----------------------------------------------------------------------------- | 
|         |    768 // | 
|         |    769 void CMailMessage::LoadLinkedHTMLContentL(const TDesC& aBase, const TDesC& aURI) | 
|         |    770     { | 
|         |    771     iState = ELoadLinkedHtmlContent; | 
|         |    772  | 
|         |    773     iMessage->FindUniversalResourceIdentifierFileHandleL( | 
|         |    774     	iMhtmlPartId, | 
|         |    775     	aBase, | 
|         |    776     	aURI, | 
|         |    777     	iStatus); | 
|         |    778     } | 
|         |    779  | 
|         |    780 // ----------------------------------------------------------------------------- | 
|         |    781 // CMailMessage::LoadAttachmentsL | 
|         |    782 // ----------------------------------------------------------------------------- | 
|         |    783 // | 
|         |    784 void CMailMessage::LoadAttachmentsL() | 
|         |    785     { | 
|         |    786     iState = ELoadAttachments; | 
|         |    787     iMessage->GetAttachmentsListL( | 
|         |    788         iStatus, iMessageID, | 
|         |    789         CImEmailMessage::EAllAttachments, | 
|         |    790         CImEmailMessage::EThisMessageAndEmbeddedMessages); | 
|         |    791     } | 
|         |    792  | 
|         |    793 // ----------------------------------------------------------------------------- | 
|         |    794 // CMailMessage::LoadAttachedMessagesL | 
|         |    795 // ----------------------------------------------------------------------------- | 
|         |    796 // | 
|         |    797 void CMailMessage::LoadAttachedMessagesL() | 
|         |    798     { | 
|         |    799     iState = ELoadAttachedMessages; | 
|         |    800     iMessage->GetMessageDigestEntriesL(iStatus, iMessageID); | 
|         |    801     } | 
|         |    802  | 
|         |    803 // ---------------------------------------------------------------------------- | 
|         |    804 //  CMailMessage::NotifyObserverL() | 
|         |    805 // ---------------------------------------------------------------------------- | 
|         |    806 // | 
|         |    807 void CMailMessage::NotifyObserverL(TInt aState) | 
|         |    808     { | 
|         |    809     iMessageObserver->MessageLoadingL(aState, *this); | 
|         |    810     } | 
|         |    811  | 
|         |    812 // ---------------------------------------------------------------------------- | 
|         |    813 //  CMailMessage::IsLinkedItemL() | 
|         |    814 // ---------------------------------------------------------------------------- | 
|         |    815 // | 
|         |    816 TBool CMailMessage::IsLinkedItemL( RFile& aHandle, TMsvAttachmentId aId ) | 
|         |    817 	{ | 
|         |    818 	TBool isLinkedItem(EFalse); | 
|         |    819     const TInt linkedItems = iLinkedHtmlItems->Count(); | 
|         |    820     if ( linkedItems ) | 
|         |    821         { | 
|         |    822         // linked html item? | 
|         |    823         for( TInt index(0); index<linkedItems; ++index ) | 
|         |    824             { | 
|         |    825             CLinkedHtmlItem* item = (*iLinkedHtmlItems)[index]; | 
|         |    826             if( item->iLinkedItemId == aId ) | 
|         |    827                 { | 
|         |    828                 ASSERT( !iAsyncWait->IsActive() ); // nested calls illegal | 
|         |    829                 iMessage->FindUniversalResourceIdentifierFileHandleL( | 
|         |    830                 	iMhtmlPartId, | 
|         |    831                 	KNullDesC(), | 
|         |    832                 	*item->iUriAddress, | 
|         |    833                 	iAsyncWait->iStatus ); | 
|         |    834                 iAsyncWait->Start(); | 
|         |    835                 User::LeaveIfError( iAsyncWait->iStatus.Int() ); | 
|         |    836  | 
|         |    837                 User::LeaveIfError( | 
|         |    838                     iMessage->GetUniversalResourceIdentifierFileHandle( | 
|         |    839                     iLinkedfileId, aHandle) ); | 
|         |    840                 isLinkedItem = ETrue; | 
|         |    841                 } | 
|         |    842             } | 
|         |    843         } | 
|         |    844     return isLinkedItem; | 
|         |    845 	} | 
|         |    846  | 
|         |    847 // ---------------------------------------------------------------------------- | 
|         |    848 //  CMailMessage::ShowErrorNoteL() | 
|         |    849 // ---------------------------------------------------------------------------- | 
|         |    850 // | 
|         |    851 void CMailMessage::ShowErrorNoteL( TInt aError ) | 
|         |    852     { | 
|         |    853     CErrorUI* errorUI = CErrorUI::NewLC(); | 
|         |    854     errorUI->ShowGlobalErrorNoteL( aError ); // ignore return value | 
|         |    855     CleanupStack::PopAndDestroy(); // errorUI | 
|         |    856     } | 
|         |    857  | 
|         |    858 // End Of File |