diff -r ccd0fd43f247 -r 208a4ba3894c harvesterplugins/messaging/smsmms/src/cmessagedatahandler.cpp --- /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 + +#include +#include // SMS Headers +#include // MMS Headers +#include +#include // IMAP Headers +#include // SMTP +#include // POP + +#include "harvesterserverlogger.h" +#include "cmessagedatahandler.h" +#include "cmessageplugin.h" +#include +#include + +#include +#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 (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 (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 (iMtmReg->NewMtmL(KUidMsgTypeSMTP))); + CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iSmtpMtm err = %d",err); + TRAP(err, iPop3Mtm = static_cast (iMtmReg->NewMtmL(KUidMsgTypePOP3))); + CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iPop3Mtm err = %d",err); + TRAP(err,iImap4Mtm = static_cast (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 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 (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 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 (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(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 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(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 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* availCharSets = + CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableLC(aFs); + + CArrayFix* utf8CharSet = + new (ELeave) CArrayFixFlat(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 +