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