/*
* 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