harvesterplugins/messaging/smsmms/src/cmessagedatahandler.cpp
changeset 2 208a4ba3894c
child 5 3bc31ad99ee7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/harvesterplugins/messaging/smsmms/src/cmessagedatahandler.cpp	Mon May 03 12:32:15 2010 +0300
@@ -0,0 +1,922 @@
+/*
+* Copyright (c) 2010 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:  Harvester message plugin
+ *
+*/
+
+
+//  INCLUDES 
+
+#include <e32base.h>
+
+#include <mtclreg.h>
+#include <smsclnt.h> // SMS Headers
+#include <mmsclient.h> // MMS Headers
+#include <mmsvattachmentmanager.h>
+#include <impcmtm.h> // IMAP Headers
+#include <smtcmtm.h> // SMTP
+#include <popcmtm.h> // POP
+
+#include "harvesterserverlogger.h"
+#include "cmessagedatahandler.h"
+#include "cmessageplugin.h"
+#include <csearchdocument.h>
+#include <common.h>
+
+#include <ccpixindexer.h>
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "cmessagedatahandlerTraces.h"
+#endif
+
+
+/** Number of symbols from MsgBody taken to excerpt */
+const TInt KMsgBodyExcerptSymbols = 90;
+
+// For Ucs2 detection
+const TInt KUtf8BomLength = 3;
+const TUint8 KUtf8Bom[KUtf8BomLength] = {0xEF, 0xBB, 0xBF};
+
+// CSearchDocument ID max length
+const TUint KMaxDocId = 20;
+// Hardcoded limit for the body size to index (and store)
+const TInt KMaxDocumentSize = 1024;
+
+_LIT8(KMimeTypeText, "text/plain" );
+
+_LIT(KMimeTypeField, CPIX_MIMETYPE_FIELD);
+_LIT(KMimeTypeMessaging, MESSAGING_MIMETYPE);
+
+/** Field names */
+_LIT(KToField, TO_FIELD);
+_LIT(KCcField, CC_FIELD);
+_LIT(KBccField, BCC_FIELD);
+_LIT(KFromField, FROM_FIELD);
+_LIT(KFolderField, FOLDER_FIELD);
+_LIT(KBodyField, BODY_FIELD);
+_LIT(KSubjectField, SUBJECT_FIELD);
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::NewL
+// ---------------------------------------------------------------------------
+//
+CMessageDataHandler* CMessageDataHandler::NewL(CMessagePlugin& aMessagePlugin,
+		CMsvSession& aSession)
+	{
+		OstTraceFunctionEntry0( CMESSAGEDATAHANDLER_NEWL_ENTRY );
+		CPIXLOGSTRING( "CMessageDataHandler::NewL() - enter" );
+
+	CMessageDataHandler* self = new (ELeave) CMessageDataHandler(
+			aMessagePlugin, aSession);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+
+		CPIXLOGSTRING( "CMessageDataHandler::NewL() - return" );
+	OstTraceFunctionExit0( CMESSAGEDATAHANDLER_NEWL_EXIT );
+	return self;
+	}
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::~CMessageDataHandler
+// ---------------------------------------------------------------------------
+//
+CMessageDataHandler::~CMessageDataHandler()
+	{
+	Cancel();
+	iFs.Close();
+	delete iMmsMtm;
+	delete iSmsMtm;
+	delete iSmtpMtm;
+	delete iPop3Mtm;
+	delete iImap4Mtm;
+	delete iMtmReg;
+	}
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::CMessageDataHandler
+// ---------------------------------------------------------------------------
+//
+CMessageDataHandler::CMessageDataHandler(CMessagePlugin& aMessagePlugin, CMsvSession& aSession)
+	: CActive(EPriorityLow), iMessagePlugin(aMessagePlugin), iMsvSession(aSession)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CMessageDataHandler::ConstructL()
+	{
+	// TODO iFs only used in MMS attachment logic, 
+	// from a performance perspective, is it worthwhile connecting here?
+	User::LeaveIfError(iFs.Connect());
+	iMtmReg = CClientMtmRegistry::NewL(iMsvSession);
+	TRAPD(err,iSmsMtm = static_cast<CSmsClientMtm*> (iMtmReg->NewMtmL(KUidMsgTypeSMS)));
+	OstTrace1( TRACE_NORMAL, CMESSAGEDATAHANDLER_CONSTRUCTL, "CMessageDataHandler::ConstructL;iSmsMtm err=%d",err );
+	CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iSmsMtm err = %d",err);
+	TRAP(err,iMmsMtm = static_cast<CMmsClientMtm*> (iMtmReg->NewMtmL(KUidMsgTypeMultimedia)));
+	OstTrace1( TRACE_NORMAL, DUP1_CMESSAGEDATAHANDLER_CONSTRUCTL, "CMessageDataHandler::ConstructL;iMmsMtm err=%d", err );
+	CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iMmsMtm err = %d",err);
+	/*
+	TRAP(err,iSmtpMtm = static_cast<CSmtpClientMtm*> (iMtmReg->NewMtmL(KUidMsgTypeSMTP)));
+	CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iSmtpMtm err = %d",err);
+	TRAP(err, iPop3Mtm = static_cast<CPop3ClientMtm*> (iMtmReg->NewMtmL(KUidMsgTypePOP3)));
+	CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iPop3Mtm err = %d",err);
+	TRAP(err,iImap4Mtm = static_cast<CImap4ClientMtm*> (iMtmReg->NewMtmL(KUidMsgTypeIMAP4)));
+	CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iImap4Mtm err = %d",err);
+	*/
+	}
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::GatherData
+// ---------------------------------------------------------------------------
+//
+void CMessageDataHandler::GatherDataL(TMsvId& aMessageId,
+		TCPixActionType aActionType, TMsvId& aFolderId)
+	{
+	TMessageItem item(aMessageId, aActionType, aFolderId);
+	iMessageArray.AppendL(item);
+	HandleNextRequest();
+	}
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::IsValidMessageTypeL
+// ---------------------------------------------------------------------------
+//	    
+TInt CMessageDataHandler::IsValidMessageType(TMsvId aIdToCheck,
+		TMsgType& aMessageType)
+	{
+		OstTraceFunctionEntry0( CMESSAGEDATAHANDLER_ISVALIDMESSAGETYPE_ENTRY );
+		CPIXLOGSTRING("ENTER CMessageDataHandler::IsValidMessageType");
+	TMsvEntry entry;
+	TMsvId service = 0;
+	TInt err = iMsvSession.GetEntry(aIdToCheck, service, entry);
+		OstTrace1( TRACE_NORMAL, CMESSAGEDATAHANDLER_ISVALIDMESSAGETYPE, "CMessageDataHandler::IsValidMessageType;GetEntry Error=%d", err );
+		CPIXLOGSTRING2("CMessageDataHandler::IsValidMessageType GetEntry: %d", err);
+	if (!err)
+		{
+		aMessageType = iMessagePlugin.CalculateMessageType(entry);
+			OstTrace1( TRACE_NORMAL, DUP1_CMESSAGEDATAHANDLER_ISVALIDMESSAGETYPE, "CMessageDataHandler::IsValidMessageType;Message Type=%d", aMessageType );
+			CPIXLOGSTRING2("CMessageDataHandler::IsValidMessageType type: %d", aMessageType );
+		}
+		CPIXLOGSTRING("END CMessageDataHandler::IsValidMessageType");
+	OstTraceFunctionExit0( CMESSAGEDATAHANDLER_ISVALIDMESSAGETYPE_EXIT );
+	return err;
+	}
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::CreateSmsIndexItemLC
+// ---------------------------------------------------------------------------
+//	    
+void CMessageDataHandler::CreateMessageIndexItemL(const TMsvId& aMsvId,
+		TCPixActionType aActionType, const TMsvId& aFolderId)
+	{
+	OstTrace1( TRACE_NORMAL, CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;aMsvId=%d", aMsvId );
+	CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): aMsvId = %d ", aMsvId );
+
+	// Index an empty item if removal action
+	if (aActionType == ECPixRemoveAction)
+		{
+		TBuf<20> docid_str;
+		docid_str.AppendNum(aMsvId);
+		if (iMessagePlugin.GetIndexer())
+			{
+			TRAPD(err, iMessagePlugin.GetIndexer()->DeleteL(docid_str));
+			if (err == KErrNone)
+				{
+				OstTrace0( TRACE_NORMAL, DUP1_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): Document deleted." );
+				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): Document deleted.");
+				}
+			else
+				{
+				OstTrace1( TRACE_NORMAL, DUP2_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in deleting the doc=%d", err );
+				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in deleting the document.", err);				
+				}
+			}
+		return;
+		}
+
+	// Check message type
+	TMsgType messageType = EMsgTypeInvalid; // initialisation
+	TInt error = IsValidMessageType(aMsvId, messageType);
+
+	// creating CSearchDocument object with unique ID for this application
+	CSearchDocument* index_item = NULL;
+
+	switch (messageType)
+		{
+		case EMsgTypeSms:
+			{
+			TRAPD(err, index_item = CreateSmsDocumentL(aMsvId, aFolderId));
+			if (err == KErrNone)
+				{
+				OstTrace0( TRACE_NORMAL, DUP3_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): SMS document created." );
+				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): SMS document created.");
+				}
+			else
+				{
+				OstTrace1( TRACE_NORMAL, DUP4_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in creating the sms doc=%d", err );
+				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in creating SMS document.", err);
+				}
+			break;
+			}
+		case EMsgTypeMms:
+			{
+			TRAPD(err, index_item = CreateMmsDocumentL(aMsvId, aFolderId));
+			if (err == KErrNone)
+				{
+				OstTrace0( TRACE_NORMAL, DUP5_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): MMS document created." );
+				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): MMS document created.");
+				}
+			else
+				{
+				OstTrace1( TRACE_NORMAL, DUP6_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in creating the mms doc=%d", err );
+				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in creating MMS document.", err);
+				}
+			break;
+			}
+		case EMsgTypeEmailPop3:
+		case EMsgTypeEmailImap4:
+		case EMsgTypeEmailSmtp:
+			{
+			TRAPD(err, index_item = CreateEmailDocumentL(aMsvId, aFolderId));
+			if (err == KErrNone)
+				{
+				OstTrace0( TRACE_NORMAL, DUP7_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): E-mail document created." );
+				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): E-mail document created.");
+				}
+			else
+				{
+				OstTrace1( TRACE_NORMAL, DUP8_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in ccreating the email doc=%d", err );
+				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in creating e-mail document.", err);
+				}
+			break;
+			}
+		case EMsgTypeInvalid:
+		// For EMsgTypeDraft there is no way to tell if it was a SMS, MMS or email,
+		// so don't create index_item.
+		case EMsgTypeDraft:
+		default:
+			// Error occurred
+			break;
+		}
+
+	// Exit if wrong message type
+	if (index_item == NULL)
+		{
+		OstTrace0( TRACE_NORMAL, DUP9_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): Document was not created." );
+		CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): Document was not created.");
+		return;
+		}
+	CleanupStack::PushL(index_item);
+		
+	// Folder field
+	TMsvEntry entry;
+	TMsvId service = 0;
+	iMsvSession.GetEntry(aFolderId, service, entry);
+	HBufC *folder_str = entry.iDetails.AllocLC();
+	index_item->AddFieldL(KFolderField, *folder_str, CDocumentField::EStoreYes | CDocumentField::EIndexNo);
+
+	// Mime type field
+	index_item->AddFieldL(KMimeTypeField, KMimeTypeMessaging, CDocumentField::EStoreYes | CDocumentField::EIndexUnTokenized);		
+	
+		// Send for indexing
+	if (iMessagePlugin.GetIndexer())
+		{
+		if (aActionType == ECPixAddAction)
+			{
+			TRAPD(err, iMessagePlugin.GetIndexer()->AddL(*index_item));
+			if (err == KErrNone)
+				{
+				OstTrace0( TRACE_NORMAL, DUP10_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): Added." );
+				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): Added.");
+				}
+			else
+				{
+				OstTrace1( TRACE_NORMAL, DUP11_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in Adding=%d", err );
+				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in adding.", err);
+				}
+			}
+		else if (aActionType == ECPixUpdateAction)
+			{
+			TRAPD(err, iMessagePlugin.GetIndexer()->UpdateL(*index_item));
+			if (err == KErrNone)
+				{
+				OstTrace0( TRACE_NORMAL, DUP12_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): Updated." );
+				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): Updated.");
+				}
+			else
+				{
+				OstTrace1( TRACE_NORMAL, DUP13_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in Updating=%d", err );
+				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in updating.", err);
+				}
+			}
+		}
+	else
+		{
+		OstTrace0( TRACE_NORMAL, DUP14_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "END CMessageDataHandler::CreateMessageIndexItemL(): No indexer present." );
+		CPIXLOGSTRING("END CMessageDataHandler::CreateMessageIndexItemL(): No indexer present.");
+		}
+		
+	CleanupStack::PopAndDestroy(folder_str);
+	CleanupStack::PopAndDestroy(index_item);
+	}
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::CreateSmsDocumentL
+// ---------------------------------------------------------------------------
+//
+CSearchDocument* CMessageDataHandler::CreateSmsDocumentL(const TMsvId& aMsvId, const TMsvId& aFolderId)
+	{
+	// Select mtm for this type
+	iSmsMtm->SwitchCurrentEntryL(aMsvId);
+	iSmsMtm->LoadMessageL();
+
+	// creating CSearchDocument object with unique ID for this application
+	TBuf<KMaxDocId> docid_str;
+	docid_str.AppendNum(aMsvId);
+	CSearchDocument* index_item = CSearchDocument::NewLC(docid_str, _L(SMSAPPCLASS));
+
+	// Add from field use the name instead of number if in the contacts db.
+	// (iSmsMtm->SmsHeader().FromAddress() - only returns the number)
+	TMsvEntry entry;
+	TMsvId service = 0;
+	iMsvSession.GetEntry(aMsvId, service, entry);
+	HBufC *fromNameOrNumberBuf = entry.iDetails.AllocLC();
+	index_item->AddFieldL(KFromField, *fromNameOrNumberBuf);
+
+	// Add the recipients as content items
+	TBuf<64> to_field;
+	const CDesCArray
+			& recipientArray =
+					static_cast<const CDesCArray&> (iSmsMtm->AddresseeList().RecipientList());
+	for (TInt i = 0; i < recipientArray.MdcaCount(); i++)
+		{
+		to_field = KToField;
+		if (i>0)
+			to_field.AppendNum(i);
+		index_item->AddFieldL(to_field, recipientArray.MdcaPoint(i));
+		}
+
+	// Add the body text as a content item
+	TInt msgLength = iSmsMtm->Body().DocumentLength();
+	HBufC* bodyText = HBufC::NewLC(msgLength);
+	TPtr body_ptr = bodyText->Des();
+	iSmsMtm->Body().Extract(body_ptr);
+	index_item->AddFieldL(KBodyField, *bodyText);
+	
+	// Add excerpt
+	// Note SMS does not have a subject field.
+	HBufC* excerpt = CreateExcerptLC(*fromNameOrNumberBuf, recipientArray, KNullDesC(), body_ptr, aFolderId);
+	index_item->AddExcerptL(*excerpt);
+	CleanupStack::PopAndDestroy(excerpt);	
+	CleanupStack::PopAndDestroy(bodyText);
+
+	CleanupStack::PopAndDestroy(fromNameOrNumberBuf);
+
+	// Pop the item
+	CleanupStack::Pop(index_item);
+	return index_item;
+	}
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::CreateMmsDocumentL
+// ---------------------------------------------------------------------------
+//
+CSearchDocument* CMessageDataHandler::CreateMmsDocumentL(const TMsvId& aMsvId, const TMsvId& aFolderId)
+	{
+	// Select mtm for this type
+ 	iMmsMtm->SwitchCurrentEntryL(aMsvId);
+	iMmsMtm->LoadMessageL();
+
+	// creating CSearchDocument object with unique ID for this application
+	TBuf<KMaxDocId> docid_str;
+	docid_str.AppendNum(aMsvId);
+	CSearchDocument* index_item = CSearchDocument::NewLC(docid_str, _L(MMSAPPCLASS));
+	
+	// Add from field
+	index_item->AddFieldL(KFromField, iMmsMtm->Sender());
+
+	// Add the recipients as content items
+	TBuf<64> to_field;
+	const CDesCArray
+			& recipientArray =
+					static_cast<const CDesCArray&> (iMmsMtm->AddresseeList().RecipientList());
+	for (TInt i = 0; i < recipientArray.MdcaCount(); i++)
+		{
+		to_field = KToField;
+		if (i>0)
+			to_field.AppendNum(i);
+		index_item->AddFieldL(to_field, recipientArray.MdcaPoint(i));
+		}
+
+	// Add subject
+	TPtrC subject(iMmsMtm->SubjectL());
+	index_item->AddFieldL(KSubjectField, subject);
+
+	// Add the body parts as a content items
+    // See if the MMS contains a text file attachment
+    TBool excerptFieldAdded(EFalse);
+    TInt bodycount = 0;
+    CMsvStore* msvStore = iMmsMtm->Entry().ReadStoreL();
+	CleanupStack::PushL( msvStore );
+	MMsvAttachmentManager& attManager = msvStore->AttachmentManagerL();
+	for ( TInt i = 0; i < attManager.AttachmentCount(); i++ )
+	    {
+		CMsvAttachment* attInfo = attManager.GetAttachmentInfoL(i);
+		CleanupStack::PushL( attInfo );
+		
+        if (attInfo->MimeType() == KMimeTypeText())
+            {
+            // Mime type
+            RFile attFile = attManager.GetAttachmentFileL(i);
+            CleanupClosePushL( attFile );
+            TInt charsetMIB = TextFileCharsetL(iFs, attFile);
+            
+            // Get the file size
+            TInt fileSize = 0;
+            User::LeaveIfError(attFile.Size(fileSize));
+            
+            // Read the file
+            HBufC8* textSource = HBufC8::NewLC(fileSize);
+            TPtr8 ptr8 = textSource->Des();
+            attFile.Read(ptr8);
+  
+  			// Convert character set
+            HBufC* text = HBufC::NewLC( fileSize );
+            TPtr buf = text->Des();
+            if ( KMmsIso10646Ucs2 != charsetMIB )
+                {
+                if ( KMmsUsAscii == charsetMIB )
+                    buf.Copy(*textSource);
+                else
+                    ConvertToUcs2FromUtfL(iFs, buf, *textSource, charsetMIB);
+                }
+            else
+                {
+                TPtrC ptr(reinterpret_cast<const TUint16*>(textSource->Des().Ptr()), 
+                                  textSource->Length() / sizeof(TText));
+        
+                // Ignore the first unicode charcter FFFE
+                ptr.Set( ptr.Mid( 1 ) );
+                buf = ptr;
+                }
+
+        
+            // Add the text of the file as a content item
+            // MMS message body is in attachment
+			TBuf<64> body_field;
+			body_field = KBodyField;
+			if (bodycount>0)
+			{
+				// Add additional body fields
+				body_field.AppendNum(bodycount);
+			}
+			else
+			{
+				// Add excerpt for the first body field
+				HBufC* excerpt = CreateExcerptLC(iMmsMtm->Sender(), recipientArray, subject, *text, aFolderId);
+				index_item->AddExcerptL(*excerpt);
+				CleanupStack::PopAndDestroy(excerpt);
+				excerptFieldAdded  = ETrue;
+			}
+
+            // TODO: add only few kilobytes of the body?
+            index_item->AddFieldL(body_field, *text);
+            ++bodycount;
+
+            CleanupStack::PopAndDestroy( 3, &attFile ); // text, textSource, attFile
+            }		
+        else 
+            {
+            // add attachment name when binary file.
+            if ( !excerptFieldAdded )
+                {
+                // attachment name might not be set
+                HBufC* excerpt = CreateExcerptLC(iMmsMtm->Sender(), recipientArray, subject, attInfo->AttachmentName(), aFolderId);
+                index_item->AddExcerptL(*excerpt);
+                CleanupStack::PopAndDestroy(excerpt);
+                excerptFieldAdded  = ETrue;
+                }
+            }
+	    CleanupStack::PopAndDestroy( attInfo );		
+	    }
+
+    // If no excerpt has been added yet, then add information have
+    if ( !excerptFieldAdded )
+        {
+        HBufC* excerpt = CreateExcerptLC(iMmsMtm->Sender(), recipientArray, subject, KNullDesC(), aFolderId);
+        index_item->AddExcerptL(*excerpt);
+        CleanupStack::PopAndDestroy(excerpt);
+        }
+
+    // Cleanup
+    CleanupStack::PopAndDestroy( msvStore );
+
+    // Pop the item
+    CleanupStack::Pop(index_item);
+    return index_item;
+    }
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::CreateEmailDocumentL
+// ---------------------------------------------------------------------------
+//
+CSearchDocument* CMessageDataHandler::CreateEmailDocumentL(const TMsvId& aMsvId, const TMsvId& aFolderId)
+	{
+	// creating CSearchDocument object with unique ID for this application
+	TBuf<KMaxDocId> docid_str;
+	docid_str.AppendNum(aMsvId);
+	CSearchDocument* index_item = CSearchDocument::NewLC(docid_str, _L(EMAILAPPCLASS));
+
+	// Open the message entry
+	CMsvEntry* message_entry = CMsvEntry::NewL(iMsvSession, aMsvId, TMsvSelectionOrdering());
+	CleanupStack::PushL(message_entry);
+	
+	// Get body
+	CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
+	CleanupStack::PushL(paraFormatLayer);
+	CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL();
+	CleanupStack::PushL(charFormatLayer);
+	CRichText* richtext = CRichText::NewL(paraFormatLayer, charFormatLayer);
+	CleanupStack::PushL(richtext);
+	CImEmailMessage* message_body = CImEmailMessage::NewLC(*message_entry);
+	message_body->GetBodyTextL(aMsvId, CImEmailMessage::EThisMessageOnly, *richtext, *paraFormatLayer, *charFormatLayer);
+	
+	// Read the message header
+	CMsvStore* message_store = message_entry->ReadStoreL();
+	CleanupStack::PushL(message_store);
+	CImHeader* header = CImHeader::NewLC();
+	header->RestoreL(*message_store);
+	
+	// Add from field
+	index_item->AddFieldL(KFromField, header->From());
+
+	// Add the ToRecipients as content items
+	TBuf<64> to_field;
+	for (TInt i = 0; i < header->ToRecipients().MdcaCount(); i++)
+		{
+		to_field = KToField;
+		if (i>0)
+			to_field.AppendNum(i);
+		index_item->AddFieldL(to_field, header->ToRecipients().MdcaPoint(i));
+		}
+
+	// Add the CcRecipients as content items
+	TBuf<64> cc_field;
+	for (TInt i = 0; i < header->CcRecipients().MdcaCount(); i++)
+		{
+		cc_field = KCcField;
+		if (i>0)
+			cc_field.AppendNum(i);
+		index_item->AddFieldL(cc_field, header->CcRecipients().MdcaPoint(i));
+		}
+
+	// Add the BccRecipients as content items
+	TBuf<64> bcc_field;
+	for (TInt i = 0; i < header->BccRecipients().MdcaCount(); i++)
+		{
+		bcc_field = KBccField;
+		if (i>0)
+			bcc_field.AppendNum(i);
+		index_item->AddFieldL(bcc_field, header->BccRecipients().MdcaPoint(i));
+		}
+
+	const TInt richTxtLen = (richtext->DocumentLength() < KMaxDocumentSize) ? richtext->DocumentLength() : KMaxDocumentSize;
+	HBufC* body_text = richtext->Read(0).Left(richTxtLen).AllocLC();
+
+	// Add subject
+	TPtrC subject(header->Subject());
+	index_item->AddFieldL(KSubjectField, subject);
+	
+	// Add message body
+	index_item->AddFieldL(KBodyField, *body_text);
+	
+	// Add excerpt
+    HBufC* excerpt = CreateExcerptLC(header->From(), header->ToRecipients(), subject, *body_text, aFolderId);
+    index_item->AddExcerptL(*excerpt);
+	CleanupStack::PopAndDestroy(excerpt);
+
+	// Cleanup everything last item message entry
+	CleanupStack::PopAndDestroy(8, message_entry);
+
+	// Pop the item
+	CleanupStack::Pop(index_item);
+	return index_item;	
+	}
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::CreateExcerptLC
+// ---------------------------------------------------------------------------
+//
+HBufC* CMessageDataHandler::CreateExcerptLC(const TDesC& aFromAddress,
+											const CDesCArray& aRecipientArray,
+											const TDesC& aSubject,
+											const TDesC& aBodyText,
+											const TMsvId& aFolderId)
+	{
+	_LIT(KEllipsis, "...");
+	_LIT(KSpace, " ");
+	TInt excerptLength = KMsgBodyExcerptSymbols + KEllipsis().Length(); 
+
+	TMsvEntry entry;
+	TMsvId service = 0;
+	iMsvSession.GetEntry(aFolderId, service, entry);
+	HBufC *folder_str = entry.iDetails.AllocLC();
+
+	excerptLength += folder_str->Length();
+	excerptLength += KSpace().Length();
+
+	if ((aFromAddress.Length() > 0) && (aFolderId == KMsvGlobalInBoxIndexEntryIdValue))
+		{
+		excerptLength += aFromAddress.Length();
+		excerptLength += KSpace().Length();
+		}
+	if ((aRecipientArray.MdcaCount() > 0) && (aFolderId != KMsvGlobalInBoxIndexEntryIdValue))
+		{
+		excerptLength += aRecipientArray.MdcaPoint(0).Length();
+		excerptLength += KSpace().Length(); 
+		}
+	if (aSubject.Length() > 0)
+		{
+		excerptLength += aSubject.Length();
+		excerptLength += KSpace().Length();
+		}
+
+	HBufC* excerpt = HBufC::NewL(excerptLength);
+	TPtr excerptPtr = excerpt->Des();
+
+	excerptPtr.Copy(*folder_str);
+	excerptPtr.Append(KSpace);
+	
+	if ((aFromAddress.Length() > 0) && (aFolderId == KMsvGlobalInBoxIndexEntryIdValue))
+		{
+		excerptPtr.Append(aFromAddress);
+		excerptPtr.Append(KSpace);
+		}
+	if ((aRecipientArray.MdcaCount() > 0) && (aFolderId != KMsvGlobalInBoxIndexEntryIdValue))
+		{
+		excerptPtr.Append(aRecipientArray.MdcaPoint(0));
+		excerptPtr.Append(KSpace);
+		}
+	if (aSubject.Length() > 0)
+		{
+		excerptPtr.Append(aSubject);
+		excerptPtr.Append(KSpace);
+		}
+
+	excerptPtr.Append(aBodyText.Left(KMsgBodyExcerptSymbols));
+	if (aBodyText.Length() > KMsgBodyExcerptSymbols)
+		excerptPtr.Append(KEllipsis);
+
+	CleanupStack::PopAndDestroy(folder_str);
+	CleanupStack::PushL(excerpt);
+	return excerpt;
+	}
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::IsTextUcs2
+// ---------------------------------------------------------------------------
+//
+TBool CMessageDataHandler::IsTextUcs2(const TDesC8& aText)
+    {
+    TBool ret = EFalse;
+    // Check UCS-2 Byte order mark is in the first two bytes of aText
+    if (aText.Length() >= sizeof(KMmsByteOrderMark))
+        {
+        TPtrC ptr(reinterpret_cast<const TUint16*>(aText.Ptr()), 
+                        aText.Length() / sizeof(TText));
+
+        if (KMmsByteOrderMark == ptr[0] ||
+            KMmsReversedByteOrderMark == ptr[0])
+            {
+            ret = ETrue;
+            }
+        }
+    return ret;
+    }   	
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::TextContainsUtf8Bom
+// ---------------------------------------------------------------------------
+//
+TBool CMessageDataHandler::TextContainsUtf8Bom(const TDesC8& aText)
+    {    
+    TBool ret = EFalse;
+    // Check to see if there is the UTF8 BOM at the begining
+    TPtrC8 utf8Id(KUtf8Bom, KUtf8BomLength);
+    if (aText.Length() >= KUtf8BomLength &&
+        aText.Left(KUtf8BomLength) == utf8Id)
+        {
+        ret = ETrue;
+        }
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::TextFileCharsetL
+// ---------------------------------------------------------------------------
+//
+TUint CMessageDataHandler::TextFileCharsetL(RFs aFs, RFile aFile)
+    {
+    TUint ret = KMmsUsAscii;
+    TBuf8<sizeof(KMmsByteOrderMark)> ucs2Buf;
+
+    TInt size;
+    User::LeaveIfError(aFile.Size(size));
+    if (size >= sizeof(KMmsByteOrderMark))
+        {
+        // Check for the UCS-2 Byte Order Mark (BOM) at the beginning 
+        // beginning of the file
+        User::LeaveIfError(aFile.Read(ucs2Buf));
+        if(IsTextUcs2(ucs2Buf))
+            {
+            ret = KMmsIso10646Ucs2;
+            }
+        }
+
+    if (KMmsIso10646Ucs2 != ret)
+        {
+        // If the text is not UCS-2 it will probably be Utf8 or Ascii
+
+        TInt seekPos = 0;
+        User::LeaveIfError(aFile.Seek(ESeekStart, seekPos));
+        
+        HBufC8* buf = HBufC8::NewLC(size);
+        TPtr8 ptr = buf->Des();
+        User::LeaveIfError(aFile.Read(ptr));
+
+        // Check to see if there is the UTF8 BOM at the begining
+        if (TextContainsUtf8Bom(ptr))
+            {
+            ret = KMmsUtf8;
+            }
+        else
+            {
+            CCnvCharacterSetConverter* converter = 
+                              CCnvCharacterSetConverter::NewLC();
+            CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* availCharSets =
+                CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableLC(aFs);
+
+            CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* utf8CharSet = 
+                new (ELeave) CArrayFixFlat<CCnvCharacterSetConverter::SCharacterSet>(1); 
+            CleanupStack::PushL(utf8CharSet);
+
+            TInt count = availCharSets->Count();
+            for (TInt i = 0; i < count; i++)
+                {
+                CCnvCharacterSetConverter::SCharacterSet& charSet = (*availCharSets)[i];
+                if (KCharacterSetIdentifierUtf8 == charSet.Identifier())
+                    {
+                    utf8CharSet->AppendL(charSet);
+                    break;
+                    }
+                }
+            TInt confidence;
+            TUint charSetId;
+            converter->AutoDetectCharacterSetL(confidence, 
+                                               charSetId, 
+                                               *utf8CharSet,
+                                               *buf);
+            const TInt KMaxConfidence = 100;
+            if (KMaxConfidence == confidence)
+                {
+                ret = KMmsUtf8;
+                }
+            CleanupStack::PopAndDestroy(3, converter);
+
+            }
+
+        CleanupStack::PopAndDestroy(buf);
+        }
+
+    TInt zero = 0;
+    User::LeaveIfError(aFile.Seek(ESeekStart, zero));
+
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// CMessageDataHandler::ConvertToUcs2FromUtfL
+// ---------------------------------------------------------------------------
+//
+void CMessageDataHandler::ConvertToUcs2FromUtfL(RFs& aFs,
+                                                 TDes& aUcs2Text,
+                                                 const TDesC8& aUtfText,
+                                                 TUint aMibCharset)
+    {
+    TPtrC8 toConvert(aUtfText);
+    if (KMmsUtf8 == aMibCharset)
+        {
+        if (TextContainsUtf8Bom(toConvert))
+            {
+            toConvert.Set(toConvert.Mid(KUtf8BomLength));
+            }
+        }
+    // prepare to convert character set to unicode
+    CCnvCharacterSetConverter* converter = 
+                          CCnvCharacterSetConverter::NewLC();
+    // change character set ID from MIB to Symbian
+    TUint charsetID = converter->ConvertMibEnumOfCharacterSetToIdentifierL(
+                                     aMibCharset, aFs);
+    CCnvCharacterSetConverter::TAvailability availability =
+            converter->PrepareToConvertToOrFromL(charsetID, aFs);
+
+    if (availability == CCnvCharacterSetConverter::ENotAvailable)
+        {
+        User::Leave(KErrNotSupported);
+        }
+    TInt state = CCnvCharacterSetConverter::KStateDefault;
+
+    User::LeaveIfError(converter->ConvertToUnicode(aUcs2Text, toConvert, state));
+
+    CleanupStack::PopAndDestroy(converter);
+    }
+    
+	
+// -----------------------------------------------------------------------------
+// CMessageDataHandler::DoCancel
+// -----------------------------------------------------------------------------
+//   
+void CMessageDataHandler::DoCancel()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CMessageDataHandler::RunL
+// -----------------------------------------------------------------------------
+//   
+void CMessageDataHandler::RunL()
+	{
+		OstTrace1( TRACE_NORMAL, CMESSAGEDATAHANDLER_RUNL, "CMessageDataHandler::RunL;status=%d", iStatus.Int() );
+		CPIXLOGSTRING2( "CMessageDataHandler::RunL status %d",iStatus.Int() );
+
+	// Implement round robin for the CActives
+	Deque();
+	CActiveScheduler::Add(this);
+
+	// Handle next message
+	if (iMessageArray.Count() > 0)
+		{
+		// Take first id from array
+		CreateMessageIndexItemL(iMessageArray[0].iMessageId,
+				iMessageArray[0].iActionType, iMessageArray[0].iFolderId);
+		
+		// Remove item that is handled
+		iMessageArray.Remove(0);
+
+		// Handle next
+		HandleNextRequest();
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CMessageDataHandler::RunError
+// -----------------------------------------------------------------------------
+//   
+TInt CMessageDataHandler::RunError(TInt aError)
+	{
+		OstTrace1( TRACE_NORMAL, CMESSAGEDATAHANDLER_RUNERROR, "CMessageDataHandler::RunError;Error=%d", aError );
+		CPIXLOGSTRING2( "CMessageDataHandler::RunError err %d", aError );
+	if (iMessageArray.Count() > 0)
+		{
+		// Remove item that is handled
+		iMessageArray.Remove(0);
+
+		// Handle next after the error
+		HandleNextRequest();
+		}
+	return KErrNone;
+	}
+
+// ---------------------------------------------------------------------------
+// HandleNextRequest
+// ---------------------------------------------------------------------------
+//
+void CMessageDataHandler::HandleNextRequest()
+	{
+	if (!IsActive())
+		{
+		SetActive();
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete(status, KErrNone);
+		}
+	}
+
+// End of File
+