email/mail/PluginSrc/MailPlainView/MailLoadStateHtml.cpp
changeset 0 72b543305e3a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/email/mail/PluginSrc/MailPlainView/MailLoadStateHtml.cpp	Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,420 @@
+/*
+* Copyright (c) 2002-2004 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:  Loads html content
+*
+*/
+
+
+
+// INCLUDE FILES
+#include 	"MailLog.h"
+#include 	"MailUtils.h"
+#include    "MailLoadStateHtml.h"
+#include    "MailLoadStateInline.h"
+#include 	"MailLoadStateMachine.h"
+#include 	"MsgMailViewerHtmlConv.h"
+#include 	<MailPlainView.rsg>
+#include    <MMailAppUiInterface.h>
+#include    <CMailMessage.h>
+#include 	<StringLoader.h>
+#include 	<charconv.h>
+
+_LIT8( KStartTag, "<html>" );
+_LIT8( KHtmlHeader1, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
+_LIT8( KHtmlHeader2, "\">\n");
+_LIT8( KCharsetTag, "CHARSET" );
+_LIT16( KCDrive, "C:" );
+const TInt KPathNameLength( 100 );
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// load html file
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::MessageLoadingL
+// -----------------------------------------------------------------------------
+//
+void CLoadHtmlFile::MessageLoadingL(TInt aStatus, CMailMessage& aMessage)
+	{
+	if( aStatus == CMailMessage::EBodyTextReady )
+		{
+        TRAPD( err, HandleBodyTextReadyL( aMessage ) );
+
+        if( err )
+            {
+            // Complete request and leave if error occured
+            CompleteRequest( err );
+            User::LeaveIfError( err );
+            }
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::CLoadHtmlFile
+// -----------------------------------------------------------------------------
+//
+CLoadHtmlFile::CLoadHtmlFile(
+	MMailAppUiInterface* aAppUI, MStateMachine& aStateMachine ) :
+	CActive( CActive::EPriorityStandard )
+	{
+	CActiveScheduler::Add( this );
+	iAppUI = aAppUI;
+	iStateMachine = &aStateMachine;
+	}
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::~CLoadHtmlFile
+// -----------------------------------------------------------------------------
+//
+CLoadHtmlFile::~CLoadHtmlFile()
+	{
+	Cancel();
+	delete iConverter;
+	}
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::NextStateL
+// -----------------------------------------------------------------------------
+//
+MLoadState* CLoadHtmlFile::NextStateL()
+	{
+	return new( ELeave ) CLoadInlineImages(
+		iAppUI, *iStateMachine );
+	}
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::MakeRequestL
+// -----------------------------------------------------------------------------
+//
+void CLoadHtmlFile::MakeRequestL(
+	TRequestStatus& aStatus,
+	CMailMessage& aMessage )
+	{
+	iLoadStatus = &aStatus;
+	iMessage = &aMessage;
+	aMessage.LoadHtmlContentL( *this );
+	aStatus = KRequestPending;
+	}
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::HandleBodyTextReadyL
+// -----------------------------------------------------------------------------
+//
+void CLoadHtmlFile::HandleBodyTextReadyL( CMailMessage& aMessage )
+    {
+	RFile handle = aMessage.HtmlContent();
+	CleanupClosePushL( handle );
+
+	if ( handle.SubSessionHandle() == 0 )
+		{
+		// if html content can not be found try to show plain text
+		// content
+		CRichText* bodyText = aMessage.MessageBody();
+		// Partial loaded or corrupted message?
+		if ( aMessage.MessageEntry().PartialDownloaded() )
+			{
+			HBufC* text = StringLoader::LoadLC(
+				R_QTN_MAIL_REST_OF_MAIL_NOT_FETCHED, CCoeEnv::Static());
+
+	        bodyText->InsertL(0, *text);
+	        CleanupStack::PopAndDestroy(); // text
+			}
+		else // Corrupted?
+			{
+			MailUtils::InformationNoteL(
+				R_MAIL_VIEWER_HTML_ERROR_DLG_TEXT );
+			}
+        iAppUI->SetBodyTextL(*aMessage.MessageBody());
+        CompleteRequest( KErrNone );
+		}
+	else
+		{
+		// Add html content as attachment before conversion.
+		if ( !aMessage.MessageEntry().PartialDownloaded() )
+			{
+			AddHtmlFileAttachmentAndCharsetL( aMessage, handle );
+			}
+        ParseHtmlFileL( aMessage, handle );
+		}
+    CleanupStack::PopAndDestroy(); // handle
+    }
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::ShowHtmlErrorNoteIfNeededL
+// -----------------------------------------------------------------------------
+//
+void CLoadHtmlFile::ShowHtmlErrorNoteIfNeededL( TInt aResult )
+	{
+    if ( aResult == KErrNotFound )
+        {
+		MailUtils::InformationNoteL( R_MAIL_VIEWER_HTML_ERROR_DLG_TEXT );
+        }
+    else if ( aResult == KErrCorrupt )
+        {
+		MailUtils::InformationNoteL( R_MAIL_VIEWER_HTML_CORRUPTED_NOTE_TEXT );
+        }
+    else if ( aResult == KErrEof )
+        {
+        // Successfully parsed. Do nothing.
+        }
+    else
+        {
+        User::LeaveIfError( aResult );
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::AddHtmlFileAttachmentL
+// -----------------------------------------------------------------------------
+//
+void CLoadHtmlFile::AddHtmlFileAttachmentL(
+    CMailMessage& aMessage, RFile aFile )
+    {
+	CMsvAttachment* htmlFileInfo = CMsvAttachment::NewL(
+		CMsvAttachment::EMsvFile );
+	CleanupStack::PushL( htmlFileInfo );
+
+	TInt htmlSize(0);
+	aFile.Size( htmlSize );
+	htmlFileInfo->SetSize( htmlSize );
+	TFileName filename;
+	User::LeaveIfError( aFile.Name( filename ) );
+	htmlFileInfo->SetAttachmentNameL( filename );
+	htmlFileInfo->SetComplete( ETrue );
+	htmlFileInfo->SetId( aMessage.MhtmlPartId() );
+
+    iAppUI->AddAttachmentL( *htmlFileInfo, EFalse );
+    CleanupStack::PopAndDestroy( htmlFileInfo );
+    }
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::ParseHtmlFileL
+// -----------------------------------------------------------------------------
+//
+void CLoadHtmlFile::ParseHtmlFileL(CMailMessage& aMessage, RFile aFile )
+    {
+    LOG( "CLoadHtmlFile::ParseHtmlFileL" );
+    LOGHANDLESIZE( aFile );
+
+    // Get the charset of the html part from the message. If the message
+    // thinks it knows the html charset then force the conversion of the html
+    // part using the specified character set decoding.
+    //
+    // Otherwise, if the html message part character set is unknown, then
+    // we'll let the conversion object try to identify the character set during
+    // the parsing process.
+    const TUint htmlCharSetId = aMessage.HtmlCharsetIdL();
+    const TBool forceCharSet = ( htmlCharSetId != 0 );
+
+    delete iConverter;
+    iConverter = NULL;
+    iConverter = CMsgMailViewerHtmlConv::NewL(
+            aFile,
+            htmlCharSetId,
+            forceCharSet );
+
+    iConverter->Convert( &iStatus );
+    SetActive();
+    }
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::RunL
+// -----------------------------------------------------------------------------
+//
+void CLoadHtmlFile::RunL()
+    {
+    LOG( "CLoadHtmlFile::RunL" );
+    ShowHtmlErrorNoteIfNeededL( iStatus.Int() );
+
+    CRichText* bodyText = iMessage->MessageBody();
+    bodyText->Reset();
+    bodyText->InsertL(0, *(iConverter->GetText()));
+
+    // If the conversion process successfully identified the characterset
+    // of the html part, then update the message with this new charset
+    // decoding value.
+    if ( iConverter->AutoParsedCharSetNameAndIdentifier() )
+        {
+        const TUint autoParsedCharSetId = iConverter->AutoParsedCharSetIdentifier();
+        iMessage->OverrideHtmlMessageCharset( autoParsedCharSetId );
+        }
+
+    iStateMachine->SetIdArray( iConverter->FileIdArray() );
+
+    if ( iMessage->MessageEntry().PartialDownloaded() )
+        {
+        HBufC* text = StringLoader::LoadLC(
+            R_QTN_MAIL_REST_OF_MAIL_NOT_FETCHED, CCoeEnv::Static());
+
+        bodyText->InsertL(bodyText->DocumentLength(), CEditableText::ELineBreak);
+
+        bodyText->InsertL(bodyText->DocumentLength(), *text);
+
+        CleanupStack::PopAndDestroy(); // text
+        }
+
+    iAppUI->SetBodyTextL( *(iMessage->MessageBody()) );
+
+    // All done
+    CompleteRequest( KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::RunError
+// -----------------------------------------------------------------------------
+//
+TInt CLoadHtmlFile::RunError( TInt aError )
+    {
+    LOG( "CLoadHtmlFile::DoCancel" );
+    CompleteRequest( aError );
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::DoCancel
+// -----------------------------------------------------------------------------
+//
+void CLoadHtmlFile::DoCancel()
+    {
+    LOG( "CLoadHtmlFile::DoCancel" );
+
+    if( iConverter )
+        {
+        iConverter->Cancel();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::CompleteRequest
+// -----------------------------------------------------------------------------
+//
+void CLoadHtmlFile::CompleteRequest( TInt aError )
+    {
+    LOG( "CLoadHtmlFile::CompleteRequest" );
+    User::RequestComplete( iLoadStatus, aError );
+    iAppUI->ViewMessageComplete();
+    }
+
+// -----------------------------------------------------------------------------
+// CLoadHtmlFile::AddCharsetToHtmlAttachment
+// -----------------------------------------------------------------------------
+//
+void CLoadHtmlFile::AddHtmlFileAttachmentAndCharsetL( CMailMessage& aMessage, RFile& aHandle )
+	{
+	// We have to check if the html body contains information about
+	// charset used. If it does, we use original file. Otherwise
+	// we create a new html file which has charset
+	// information added
+
+	// Get charset Id and handle for the html body content
+	TUint htmlCharsetId = aMessage.HtmlCharsetIdL();
+
+	// Convert charset Id into string
+	RFs& fs = CCoeEnv::Static()->FsSession();
+	CCnvCharacterSetConverter* charConv = CCnvCharacterSetConverter::NewLC();
+	HBufC8* charsetBuf = charConv->
+		ConvertCharacterSetIdentifierToStandardNameL(
+				htmlCharsetId, fs);
+	CleanupStack::PopAndDestroy( charConv ); // charConv
+	CleanupStack::PushL( charsetBuf );
+	TPtr8 charsetPtr = charsetBuf->Des();
+
+	// Calculate buffer size for charsetRowBuf and also for
+	// htmlContentBuf to avoid reallocation of memory
+	TInt bufferSize( 0 );
+	bufferSize += KHtmlHeader1().Length();
+	bufferSize += charsetBuf->Length();
+	bufferSize += KHtmlHeader2().Length();
+
+	// Read html content from the html file
+	TInt fileSize(0);
+	aHandle.Size( fileSize );
+	HBufC8* htmlContentBuf = HBufC8::NewLC( fileSize+bufferSize );
+	TPtr8 htmlContentPtr = htmlContentBuf->Des();
+	aHandle.Read( htmlContentPtr );
+	TInt i( 0 );
+	aHandle.Seek( ESeekStart, i );	// rewind the file
+
+	// Try to find strings CHARSET and <html>
+	// If the string is not found append information containing charset
+	TInt charsetFoundAt( htmlContentBuf->Find( KCharsetTag ) );
+	TInt htmlTagFoundAt( htmlContentBuf->Find( KStartTag ) );
+
+	// If CHARSET is defined in the email but it is not found from the
+	// html body part, we have to add it ourselves.
+	// Else use the original html file
+	if( charsetFoundAt <= 0
+		&& htmlTagFoundAt >= 0 )
+		{
+		// Create a new hmtl line containing character set information
+		// and append it.
+		// Create new buffer for storing charset html info row and
+		// insert it to the buffer containing html body
+		HBufC8* charsetRowBuf = HBufC8::NewLC( bufferSize );
+		TPtr8 charsetRowPtr = charsetRowBuf->Des();
+		charsetRowPtr.Append( KHtmlHeader1 );
+		charsetRowPtr.Append( charsetPtr );
+		charsetRowPtr.Append( KHtmlHeader2 );
+		htmlContentPtr.Insert( htmlTagFoundAt, charsetRowPtr );
+		CleanupStack::PopAndDestroy( charsetRowBuf );
+
+		// create mailviewer folder in c:\private
+		HBufC* pathNameBuf = HBufC::NewLC( KPathNameLength );
+		TPtr pathNamePtr = pathNameBuf->Des();
+		fs.PrivatePath( pathNamePtr );
+		pathNamePtr.Insert( 0, KCDrive );
+
+		TInt makeDir = fs.MkDir( pathNamePtr );
+		// Itīs ok if directory already exists. If other errors,
+		// use original html file
+		if( makeDir != KErrAlreadyExists && makeDir < 0 )
+			{
+			AddHtmlFileAttachmentL( aMessage, aHandle );
+			}
+		else	// continue creating new html attachment
+			{
+			// create new html attachment
+			RFile newHtmlFile;
+			HBufC* newHtmlFileNameBuf = HBufC::NewLC( KPathNameLength );
+			TPtr newHtmlFileNamePtr = newHtmlFileNameBuf->Des();
+			aHandle.Name( newHtmlFileNamePtr );
+			pathNamePtr.Append( newHtmlFileNamePtr );
+			CleanupStack::PopAndDestroy( newHtmlFileNameBuf );
+
+			TInt openResult = newHtmlFile.Replace( fs, pathNamePtr, EFileWrite );
+			CleanupClosePushL( newHtmlFile );
+			if( openResult >= KErrNone )
+				{
+				TInt writeResult = newHtmlFile.Write( 0, htmlContentPtr );
+				if( writeResult >= KErrNone )
+					{
+					AddHtmlFileAttachmentL( aMessage, newHtmlFile );
+					}
+				else	// else use original html file
+					{
+					AddHtmlFileAttachmentL( aMessage, aHandle );
+					}
+				}
+			CleanupStack::PopAndDestroy( &newHtmlFile );
+			}
+		CleanupStack::PopAndDestroy( pathNameBuf );
+		}
+	else	// charset found, use original html file
+		{
+		AddHtmlFileAttachmentL( aMessage, aHandle );
+		}
+	CleanupStack::PopAndDestroy( 2, charsetBuf );	// htmlContentBuf
+	}
+
+
+//  End of File