harvesterplugins/messaging/smsmms/src/cmessagedatahandler.cpp
changeset 2 208a4ba3894c
child 5 3bc31ad99ee7
equal deleted inserted replaced
0:ccd0fd43f247 2:208a4ba3894c
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Harvester message plugin
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 //  INCLUDES 
       
    20 
       
    21 #include <e32base.h>
       
    22 
       
    23 #include <mtclreg.h>
       
    24 #include <smsclnt.h> // SMS Headers
       
    25 #include <mmsclient.h> // MMS Headers
       
    26 #include <mmsvattachmentmanager.h>
       
    27 #include <impcmtm.h> // IMAP Headers
       
    28 #include <smtcmtm.h> // SMTP
       
    29 #include <popcmtm.h> // POP
       
    30 
       
    31 #include "harvesterserverlogger.h"
       
    32 #include "cmessagedatahandler.h"
       
    33 #include "cmessageplugin.h"
       
    34 #include <csearchdocument.h>
       
    35 #include <common.h>
       
    36 
       
    37 #include <ccpixindexer.h>
       
    38 #include "OstTraceDefinitions.h"
       
    39 #ifdef OST_TRACE_COMPILER_IN_USE
       
    40 #include "cmessagedatahandlerTraces.h"
       
    41 #endif
       
    42 
       
    43 
       
    44 /** Number of symbols from MsgBody taken to excerpt */
       
    45 const TInt KMsgBodyExcerptSymbols = 90;
       
    46 
       
    47 // For Ucs2 detection
       
    48 const TInt KUtf8BomLength = 3;
       
    49 const TUint8 KUtf8Bom[KUtf8BomLength] = {0xEF, 0xBB, 0xBF};
       
    50 
       
    51 // CSearchDocument ID max length
       
    52 const TUint KMaxDocId = 20;
       
    53 // Hardcoded limit for the body size to index (and store)
       
    54 const TInt KMaxDocumentSize = 1024;
       
    55 
       
    56 _LIT8(KMimeTypeText, "text/plain" );
       
    57 
       
    58 _LIT(KMimeTypeField, CPIX_MIMETYPE_FIELD);
       
    59 _LIT(KMimeTypeMessaging, MESSAGING_MIMETYPE);
       
    60 
       
    61 /** Field names */
       
    62 _LIT(KToField, TO_FIELD);
       
    63 _LIT(KCcField, CC_FIELD);
       
    64 _LIT(KBccField, BCC_FIELD);
       
    65 _LIT(KFromField, FROM_FIELD);
       
    66 _LIT(KFolderField, FOLDER_FIELD);
       
    67 _LIT(KBodyField, BODY_FIELD);
       
    68 _LIT(KSubjectField, SUBJECT_FIELD);
       
    69 
       
    70 // ============================ MEMBER FUNCTIONS ===============================
       
    71 
       
    72 // ---------------------------------------------------------------------------
       
    73 // CMessageDataHandler::NewL
       
    74 // ---------------------------------------------------------------------------
       
    75 //
       
    76 CMessageDataHandler* CMessageDataHandler::NewL(CMessagePlugin& aMessagePlugin,
       
    77 		CMsvSession& aSession)
       
    78 	{
       
    79 		OstTraceFunctionEntry0( CMESSAGEDATAHANDLER_NEWL_ENTRY );
       
    80 		CPIXLOGSTRING( "CMessageDataHandler::NewL() - enter" );
       
    81 
       
    82 	CMessageDataHandler* self = new (ELeave) CMessageDataHandler(
       
    83 			aMessagePlugin, aSession);
       
    84 	CleanupStack::PushL(self);
       
    85 	self->ConstructL();
       
    86 	CleanupStack::Pop(self);
       
    87 
       
    88 		CPIXLOGSTRING( "CMessageDataHandler::NewL() - return" );
       
    89 	OstTraceFunctionExit0( CMESSAGEDATAHANDLER_NEWL_EXIT );
       
    90 	return self;
       
    91 	}
       
    92 
       
    93 // ---------------------------------------------------------------------------
       
    94 // CMessageDataHandler::~CMessageDataHandler
       
    95 // ---------------------------------------------------------------------------
       
    96 //
       
    97 CMessageDataHandler::~CMessageDataHandler()
       
    98 	{
       
    99 	Cancel();
       
   100 	iFs.Close();
       
   101 	delete iMmsMtm;
       
   102 	delete iSmsMtm;
       
   103 	delete iSmtpMtm;
       
   104 	delete iPop3Mtm;
       
   105 	delete iImap4Mtm;
       
   106 	delete iMtmReg;
       
   107 	}
       
   108 
       
   109 // ---------------------------------------------------------------------------
       
   110 // CMessageDataHandler::CMessageDataHandler
       
   111 // ---------------------------------------------------------------------------
       
   112 //
       
   113 CMessageDataHandler::CMessageDataHandler(CMessagePlugin& aMessagePlugin, CMsvSession& aSession)
       
   114 	: CActive(EPriorityLow), iMessagePlugin(aMessagePlugin), iMsvSession(aSession)
       
   115 	{
       
   116 	CActiveScheduler::Add(this);
       
   117 	}
       
   118 
       
   119 // ---------------------------------------------------------------------------
       
   120 // CMessageDataHandler::ConstructL
       
   121 // ---------------------------------------------------------------------------
       
   122 //
       
   123 void CMessageDataHandler::ConstructL()
       
   124 	{
       
   125 	// TODO iFs only used in MMS attachment logic, 
       
   126 	// from a performance perspective, is it worthwhile connecting here?
       
   127 	User::LeaveIfError(iFs.Connect());
       
   128 	iMtmReg = CClientMtmRegistry::NewL(iMsvSession);
       
   129 	TRAPD(err,iSmsMtm = static_cast<CSmsClientMtm*> (iMtmReg->NewMtmL(KUidMsgTypeSMS)));
       
   130 	OstTrace1( TRACE_NORMAL, CMESSAGEDATAHANDLER_CONSTRUCTL, "CMessageDataHandler::ConstructL;iSmsMtm err=%d",err );
       
   131 	CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iSmsMtm err = %d",err);
       
   132 	TRAP(err,iMmsMtm = static_cast<CMmsClientMtm*> (iMtmReg->NewMtmL(KUidMsgTypeMultimedia)));
       
   133 	OstTrace1( TRACE_NORMAL, DUP1_CMESSAGEDATAHANDLER_CONSTRUCTL, "CMessageDataHandler::ConstructL;iMmsMtm err=%d", err );
       
   134 	CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iMmsMtm err = %d",err);
       
   135 	/*
       
   136 	TRAP(err,iSmtpMtm = static_cast<CSmtpClientMtm*> (iMtmReg->NewMtmL(KUidMsgTypeSMTP)));
       
   137 	CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iSmtpMtm err = %d",err);
       
   138 	TRAP(err, iPop3Mtm = static_cast<CPop3ClientMtm*> (iMtmReg->NewMtmL(KUidMsgTypePOP3)));
       
   139 	CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iPop3Mtm err = %d",err);
       
   140 	TRAP(err,iImap4Mtm = static_cast<CImap4ClientMtm*> (iMtmReg->NewMtmL(KUidMsgTypeIMAP4)));
       
   141 	CPIXLOGSTRING2( "CMessageDataHandler::ConstructL() iImap4Mtm err = %d",err);
       
   142 	*/
       
   143 	}
       
   144 
       
   145 // ---------------------------------------------------------------------------
       
   146 // CMessageDataHandler::GatherData
       
   147 // ---------------------------------------------------------------------------
       
   148 //
       
   149 void CMessageDataHandler::GatherDataL(TMsvId& aMessageId,
       
   150 		TCPixActionType aActionType, TMsvId& aFolderId)
       
   151 	{
       
   152 	TMessageItem item(aMessageId, aActionType, aFolderId);
       
   153 	iMessageArray.AppendL(item);
       
   154 	HandleNextRequest();
       
   155 	}
       
   156 
       
   157 // ---------------------------------------------------------------------------
       
   158 // CMessageDataHandler::IsValidMessageTypeL
       
   159 // ---------------------------------------------------------------------------
       
   160 //	    
       
   161 TInt CMessageDataHandler::IsValidMessageType(TMsvId aIdToCheck,
       
   162 		TMsgType& aMessageType)
       
   163 	{
       
   164 		OstTraceFunctionEntry0( CMESSAGEDATAHANDLER_ISVALIDMESSAGETYPE_ENTRY );
       
   165 		CPIXLOGSTRING("ENTER CMessageDataHandler::IsValidMessageType");
       
   166 	TMsvEntry entry;
       
   167 	TMsvId service = 0;
       
   168 	TInt err = iMsvSession.GetEntry(aIdToCheck, service, entry);
       
   169 		OstTrace1( TRACE_NORMAL, CMESSAGEDATAHANDLER_ISVALIDMESSAGETYPE, "CMessageDataHandler::IsValidMessageType;GetEntry Error=%d", err );
       
   170 		CPIXLOGSTRING2("CMessageDataHandler::IsValidMessageType GetEntry: %d", err);
       
   171 	if (!err)
       
   172 		{
       
   173 		aMessageType = iMessagePlugin.CalculateMessageType(entry);
       
   174 			OstTrace1( TRACE_NORMAL, DUP1_CMESSAGEDATAHANDLER_ISVALIDMESSAGETYPE, "CMessageDataHandler::IsValidMessageType;Message Type=%d", aMessageType );
       
   175 			CPIXLOGSTRING2("CMessageDataHandler::IsValidMessageType type: %d", aMessageType );
       
   176 		}
       
   177 		CPIXLOGSTRING("END CMessageDataHandler::IsValidMessageType");
       
   178 	OstTraceFunctionExit0( CMESSAGEDATAHANDLER_ISVALIDMESSAGETYPE_EXIT );
       
   179 	return err;
       
   180 	}
       
   181 
       
   182 // ---------------------------------------------------------------------------
       
   183 // CMessageDataHandler::CreateSmsIndexItemLC
       
   184 // ---------------------------------------------------------------------------
       
   185 //	    
       
   186 void CMessageDataHandler::CreateMessageIndexItemL(const TMsvId& aMsvId,
       
   187 		TCPixActionType aActionType, const TMsvId& aFolderId)
       
   188 	{
       
   189 	OstTrace1( TRACE_NORMAL, CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;aMsvId=%d", aMsvId );
       
   190 	CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): aMsvId = %d ", aMsvId );
       
   191 
       
   192 	// Index an empty item if removal action
       
   193 	if (aActionType == ECPixRemoveAction)
       
   194 		{
       
   195 		TBuf<20> docid_str;
       
   196 		docid_str.AppendNum(aMsvId);
       
   197 		if (iMessagePlugin.GetIndexer())
       
   198 			{
       
   199 			TRAPD(err, iMessagePlugin.GetIndexer()->DeleteL(docid_str));
       
   200 			if (err == KErrNone)
       
   201 				{
       
   202 				OstTrace0( TRACE_NORMAL, DUP1_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): Document deleted." );
       
   203 				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): Document deleted.");
       
   204 				}
       
   205 			else
       
   206 				{
       
   207 				OstTrace1( TRACE_NORMAL, DUP2_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in deleting the doc=%d", err );
       
   208 				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in deleting the document.", err);				
       
   209 				}
       
   210 			}
       
   211 		return;
       
   212 		}
       
   213 
       
   214 	// Check message type
       
   215 	TMsgType messageType = EMsgTypeInvalid; // initialisation
       
   216 	TInt error = IsValidMessageType(aMsvId, messageType);
       
   217 
       
   218 	// creating CSearchDocument object with unique ID for this application
       
   219 	CSearchDocument* index_item = NULL;
       
   220 
       
   221 	switch (messageType)
       
   222 		{
       
   223 		case EMsgTypeSms:
       
   224 			{
       
   225 			TRAPD(err, index_item = CreateSmsDocumentL(aMsvId, aFolderId));
       
   226 			if (err == KErrNone)
       
   227 				{
       
   228 				OstTrace0( TRACE_NORMAL, DUP3_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): SMS document created." );
       
   229 				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): SMS document created.");
       
   230 				}
       
   231 			else
       
   232 				{
       
   233 				OstTrace1( TRACE_NORMAL, DUP4_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in creating the sms doc=%d", err );
       
   234 				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in creating SMS document.", err);
       
   235 				}
       
   236 			break;
       
   237 			}
       
   238 		case EMsgTypeMms:
       
   239 			{
       
   240 			TRAPD(err, index_item = CreateMmsDocumentL(aMsvId, aFolderId));
       
   241 			if (err == KErrNone)
       
   242 				{
       
   243 				OstTrace0( TRACE_NORMAL, DUP5_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): MMS document created." );
       
   244 				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): MMS document created.");
       
   245 				}
       
   246 			else
       
   247 				{
       
   248 				OstTrace1( TRACE_NORMAL, DUP6_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in creating the mms doc=%d", err );
       
   249 				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in creating MMS document.", err);
       
   250 				}
       
   251 			break;
       
   252 			}
       
   253 		case EMsgTypeEmailPop3:
       
   254 		case EMsgTypeEmailImap4:
       
   255 		case EMsgTypeEmailSmtp:
       
   256 			{
       
   257 			TRAPD(err, index_item = CreateEmailDocumentL(aMsvId, aFolderId));
       
   258 			if (err == KErrNone)
       
   259 				{
       
   260 				OstTrace0( TRACE_NORMAL, DUP7_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): E-mail document created." );
       
   261 				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): E-mail document created.");
       
   262 				}
       
   263 			else
       
   264 				{
       
   265 				OstTrace1( TRACE_NORMAL, DUP8_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in ccreating the email doc=%d", err );
       
   266 				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in creating e-mail document.", err);
       
   267 				}
       
   268 			break;
       
   269 			}
       
   270 		case EMsgTypeInvalid:
       
   271 		// For EMsgTypeDraft there is no way to tell if it was a SMS, MMS or email,
       
   272 		// so don't create index_item.
       
   273 		case EMsgTypeDraft:
       
   274 		default:
       
   275 			// Error occurred
       
   276 			break;
       
   277 		}
       
   278 
       
   279 	// Exit if wrong message type
       
   280 	if (index_item == NULL)
       
   281 		{
       
   282 		OstTrace0( TRACE_NORMAL, DUP9_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): Document was not created." );
       
   283 		CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): Document was not created.");
       
   284 		return;
       
   285 		}
       
   286 	CleanupStack::PushL(index_item);
       
   287 		
       
   288 	// Folder field
       
   289 	TMsvEntry entry;
       
   290 	TMsvId service = 0;
       
   291 	iMsvSession.GetEntry(aFolderId, service, entry);
       
   292 	HBufC *folder_str = entry.iDetails.AllocLC();
       
   293 	index_item->AddFieldL(KFolderField, *folder_str, CDocumentField::EStoreYes | CDocumentField::EIndexNo);
       
   294 
       
   295 	// Mime type field
       
   296 	index_item->AddFieldL(KMimeTypeField, KMimeTypeMessaging, CDocumentField::EStoreYes | CDocumentField::EIndexUnTokenized);		
       
   297 	
       
   298 		// Send for indexing
       
   299 	if (iMessagePlugin.GetIndexer())
       
   300 		{
       
   301 		if (aActionType == ECPixAddAction)
       
   302 			{
       
   303 			TRAPD(err, iMessagePlugin.GetIndexer()->AddL(*index_item));
       
   304 			if (err == KErrNone)
       
   305 				{
       
   306 				OstTrace0( TRACE_NORMAL, DUP10_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): Added." );
       
   307 				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): Added.");
       
   308 				}
       
   309 			else
       
   310 				{
       
   311 				OstTrace1( TRACE_NORMAL, DUP11_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in Adding=%d", err );
       
   312 				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in adding.", err);
       
   313 				}
       
   314 			}
       
   315 		else if (aActionType == ECPixUpdateAction)
       
   316 			{
       
   317 			TRAPD(err, iMessagePlugin.GetIndexer()->UpdateL(*index_item));
       
   318 			if (err == KErrNone)
       
   319 				{
       
   320 				OstTrace0( TRACE_NORMAL, DUP12_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL(): Updated." );
       
   321 				CPIXLOGSTRING("CMessageDataHandler::CreateMessageIndexItemL(): Updated.");
       
   322 				}
       
   323 			else
       
   324 				{
       
   325 				OstTrace1( TRACE_NORMAL, DUP13_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "CMessageDataHandler::CreateMessageIndexItemL;Error in Updating=%d", err );
       
   326 				CPIXLOGSTRING2("CMessageDataHandler::CreateMessageIndexItemL(): Error %d in updating.", err);
       
   327 				}
       
   328 			}
       
   329 		}
       
   330 	else
       
   331 		{
       
   332 		OstTrace0( TRACE_NORMAL, DUP14_CMESSAGEDATAHANDLER_CREATEMESSAGEINDEXITEML, "END CMessageDataHandler::CreateMessageIndexItemL(): No indexer present." );
       
   333 		CPIXLOGSTRING("END CMessageDataHandler::CreateMessageIndexItemL(): No indexer present.");
       
   334 		}
       
   335 		
       
   336 	CleanupStack::PopAndDestroy(folder_str);
       
   337 	CleanupStack::PopAndDestroy(index_item);
       
   338 	}
       
   339 
       
   340 // ---------------------------------------------------------------------------
       
   341 // CMessageDataHandler::CreateSmsDocumentL
       
   342 // ---------------------------------------------------------------------------
       
   343 //
       
   344 CSearchDocument* CMessageDataHandler::CreateSmsDocumentL(const TMsvId& aMsvId, const TMsvId& aFolderId)
       
   345 	{
       
   346 	// Select mtm for this type
       
   347 	iSmsMtm->SwitchCurrentEntryL(aMsvId);
       
   348 	iSmsMtm->LoadMessageL();
       
   349 
       
   350 	// creating CSearchDocument object with unique ID for this application
       
   351 	TBuf<KMaxDocId> docid_str;
       
   352 	docid_str.AppendNum(aMsvId);
       
   353 	CSearchDocument* index_item = CSearchDocument::NewLC(docid_str, _L(SMSAPPCLASS));
       
   354 
       
   355 	// Add from field use the name instead of number if in the contacts db.
       
   356 	// (iSmsMtm->SmsHeader().FromAddress() - only returns the number)
       
   357 	TMsvEntry entry;
       
   358 	TMsvId service = 0;
       
   359 	iMsvSession.GetEntry(aMsvId, service, entry);
       
   360 	HBufC *fromNameOrNumberBuf = entry.iDetails.AllocLC();
       
   361 	index_item->AddFieldL(KFromField, *fromNameOrNumberBuf);
       
   362 
       
   363 	// Add the recipients as content items
       
   364 	TBuf<64> to_field;
       
   365 	const CDesCArray
       
   366 			& recipientArray =
       
   367 					static_cast<const CDesCArray&> (iSmsMtm->AddresseeList().RecipientList());
       
   368 	for (TInt i = 0; i < recipientArray.MdcaCount(); i++)
       
   369 		{
       
   370 		to_field = KToField;
       
   371 		if (i>0)
       
   372 			to_field.AppendNum(i);
       
   373 		index_item->AddFieldL(to_field, recipientArray.MdcaPoint(i));
       
   374 		}
       
   375 
       
   376 	// Add the body text as a content item
       
   377 	TInt msgLength = iSmsMtm->Body().DocumentLength();
       
   378 	HBufC* bodyText = HBufC::NewLC(msgLength);
       
   379 	TPtr body_ptr = bodyText->Des();
       
   380 	iSmsMtm->Body().Extract(body_ptr);
       
   381 	index_item->AddFieldL(KBodyField, *bodyText);
       
   382 	
       
   383 	// Add excerpt
       
   384 	// Note SMS does not have a subject field.
       
   385 	HBufC* excerpt = CreateExcerptLC(*fromNameOrNumberBuf, recipientArray, KNullDesC(), body_ptr, aFolderId);
       
   386 	index_item->AddExcerptL(*excerpt);
       
   387 	CleanupStack::PopAndDestroy(excerpt);	
       
   388 	CleanupStack::PopAndDestroy(bodyText);
       
   389 
       
   390 	CleanupStack::PopAndDestroy(fromNameOrNumberBuf);
       
   391 
       
   392 	// Pop the item
       
   393 	CleanupStack::Pop(index_item);
       
   394 	return index_item;
       
   395 	}
       
   396 
       
   397 // ---------------------------------------------------------------------------
       
   398 // CMessageDataHandler::CreateMmsDocumentL
       
   399 // ---------------------------------------------------------------------------
       
   400 //
       
   401 CSearchDocument* CMessageDataHandler::CreateMmsDocumentL(const TMsvId& aMsvId, const TMsvId& aFolderId)
       
   402 	{
       
   403 	// Select mtm for this type
       
   404  	iMmsMtm->SwitchCurrentEntryL(aMsvId);
       
   405 	iMmsMtm->LoadMessageL();
       
   406 
       
   407 	// creating CSearchDocument object with unique ID for this application
       
   408 	TBuf<KMaxDocId> docid_str;
       
   409 	docid_str.AppendNum(aMsvId);
       
   410 	CSearchDocument* index_item = CSearchDocument::NewLC(docid_str, _L(MMSAPPCLASS));
       
   411 	
       
   412 	// Add from field
       
   413 	index_item->AddFieldL(KFromField, iMmsMtm->Sender());
       
   414 
       
   415 	// Add the recipients as content items
       
   416 	TBuf<64> to_field;
       
   417 	const CDesCArray
       
   418 			& recipientArray =
       
   419 					static_cast<const CDesCArray&> (iMmsMtm->AddresseeList().RecipientList());
       
   420 	for (TInt i = 0; i < recipientArray.MdcaCount(); i++)
       
   421 		{
       
   422 		to_field = KToField;
       
   423 		if (i>0)
       
   424 			to_field.AppendNum(i);
       
   425 		index_item->AddFieldL(to_field, recipientArray.MdcaPoint(i));
       
   426 		}
       
   427 
       
   428 	// Add subject
       
   429 	TPtrC subject(iMmsMtm->SubjectL());
       
   430 	index_item->AddFieldL(KSubjectField, subject);
       
   431 
       
   432 	// Add the body parts as a content items
       
   433     // See if the MMS contains a text file attachment
       
   434     TBool excerptFieldAdded(EFalse);
       
   435     TInt bodycount = 0;
       
   436     CMsvStore* msvStore = iMmsMtm->Entry().ReadStoreL();
       
   437 	CleanupStack::PushL( msvStore );
       
   438 	MMsvAttachmentManager& attManager = msvStore->AttachmentManagerL();
       
   439 	for ( TInt i = 0; i < attManager.AttachmentCount(); i++ )
       
   440 	    {
       
   441 		CMsvAttachment* attInfo = attManager.GetAttachmentInfoL(i);
       
   442 		CleanupStack::PushL( attInfo );
       
   443 		
       
   444         if (attInfo->MimeType() == KMimeTypeText())
       
   445             {
       
   446             // Mime type
       
   447             RFile attFile = attManager.GetAttachmentFileL(i);
       
   448             CleanupClosePushL( attFile );
       
   449             TInt charsetMIB = TextFileCharsetL(iFs, attFile);
       
   450             
       
   451             // Get the file size
       
   452             TInt fileSize = 0;
       
   453             User::LeaveIfError(attFile.Size(fileSize));
       
   454             
       
   455             // Read the file
       
   456             HBufC8* textSource = HBufC8::NewLC(fileSize);
       
   457             TPtr8 ptr8 = textSource->Des();
       
   458             attFile.Read(ptr8);
       
   459   
       
   460   			// Convert character set
       
   461             HBufC* text = HBufC::NewLC( fileSize );
       
   462             TPtr buf = text->Des();
       
   463             if ( KMmsIso10646Ucs2 != charsetMIB )
       
   464                 {
       
   465                 if ( KMmsUsAscii == charsetMIB )
       
   466                     buf.Copy(*textSource);
       
   467                 else
       
   468                     ConvertToUcs2FromUtfL(iFs, buf, *textSource, charsetMIB);
       
   469                 }
       
   470             else
       
   471                 {
       
   472                 TPtrC ptr(reinterpret_cast<const TUint16*>(textSource->Des().Ptr()), 
       
   473                                   textSource->Length() / sizeof(TText));
       
   474         
       
   475                 // Ignore the first unicode charcter FFFE
       
   476                 ptr.Set( ptr.Mid( 1 ) );
       
   477                 buf = ptr;
       
   478                 }
       
   479 
       
   480         
       
   481             // Add the text of the file as a content item
       
   482             // MMS message body is in attachment
       
   483 			TBuf<64> body_field;
       
   484 			body_field = KBodyField;
       
   485 			if (bodycount>0)
       
   486 			{
       
   487 				// Add additional body fields
       
   488 				body_field.AppendNum(bodycount);
       
   489 			}
       
   490 			else
       
   491 			{
       
   492 				// Add excerpt for the first body field
       
   493 				HBufC* excerpt = CreateExcerptLC(iMmsMtm->Sender(), recipientArray, subject, *text, aFolderId);
       
   494 				index_item->AddExcerptL(*excerpt);
       
   495 				CleanupStack::PopAndDestroy(excerpt);
       
   496 				excerptFieldAdded  = ETrue;
       
   497 			}
       
   498 
       
   499             // TODO: add only few kilobytes of the body?
       
   500             index_item->AddFieldL(body_field, *text);
       
   501             ++bodycount;
       
   502 
       
   503             CleanupStack::PopAndDestroy( 3, &attFile ); // text, textSource, attFile
       
   504             }		
       
   505         else 
       
   506             {
       
   507             // add attachment name when binary file.
       
   508             if ( !excerptFieldAdded )
       
   509                 {
       
   510                 // attachment name might not be set
       
   511                 HBufC* excerpt = CreateExcerptLC(iMmsMtm->Sender(), recipientArray, subject, attInfo->AttachmentName(), aFolderId);
       
   512                 index_item->AddExcerptL(*excerpt);
       
   513                 CleanupStack::PopAndDestroy(excerpt);
       
   514                 excerptFieldAdded  = ETrue;
       
   515                 }
       
   516             }
       
   517 	    CleanupStack::PopAndDestroy( attInfo );		
       
   518 	    }
       
   519 
       
   520     // If no excerpt has been added yet, then add information have
       
   521     if ( !excerptFieldAdded )
       
   522         {
       
   523         HBufC* excerpt = CreateExcerptLC(iMmsMtm->Sender(), recipientArray, subject, KNullDesC(), aFolderId);
       
   524         index_item->AddExcerptL(*excerpt);
       
   525         CleanupStack::PopAndDestroy(excerpt);
       
   526         }
       
   527 
       
   528     // Cleanup
       
   529     CleanupStack::PopAndDestroy( msvStore );
       
   530 
       
   531     // Pop the item
       
   532     CleanupStack::Pop(index_item);
       
   533     return index_item;
       
   534     }
       
   535 
       
   536 // ---------------------------------------------------------------------------
       
   537 // CMessageDataHandler::CreateEmailDocumentL
       
   538 // ---------------------------------------------------------------------------
       
   539 //
       
   540 CSearchDocument* CMessageDataHandler::CreateEmailDocumentL(const TMsvId& aMsvId, const TMsvId& aFolderId)
       
   541 	{
       
   542 	// creating CSearchDocument object with unique ID for this application
       
   543 	TBuf<KMaxDocId> docid_str;
       
   544 	docid_str.AppendNum(aMsvId);
       
   545 	CSearchDocument* index_item = CSearchDocument::NewLC(docid_str, _L(EMAILAPPCLASS));
       
   546 
       
   547 	// Open the message entry
       
   548 	CMsvEntry* message_entry = CMsvEntry::NewL(iMsvSession, aMsvId, TMsvSelectionOrdering());
       
   549 	CleanupStack::PushL(message_entry);
       
   550 	
       
   551 	// Get body
       
   552 	CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
       
   553 	CleanupStack::PushL(paraFormatLayer);
       
   554 	CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL();
       
   555 	CleanupStack::PushL(charFormatLayer);
       
   556 	CRichText* richtext = CRichText::NewL(paraFormatLayer, charFormatLayer);
       
   557 	CleanupStack::PushL(richtext);
       
   558 	CImEmailMessage* message_body = CImEmailMessage::NewLC(*message_entry);
       
   559 	message_body->GetBodyTextL(aMsvId, CImEmailMessage::EThisMessageOnly, *richtext, *paraFormatLayer, *charFormatLayer);
       
   560 	
       
   561 	// Read the message header
       
   562 	CMsvStore* message_store = message_entry->ReadStoreL();
       
   563 	CleanupStack::PushL(message_store);
       
   564 	CImHeader* header = CImHeader::NewLC();
       
   565 	header->RestoreL(*message_store);
       
   566 	
       
   567 	// Add from field
       
   568 	index_item->AddFieldL(KFromField, header->From());
       
   569 
       
   570 	// Add the ToRecipients as content items
       
   571 	TBuf<64> to_field;
       
   572 	for (TInt i = 0; i < header->ToRecipients().MdcaCount(); i++)
       
   573 		{
       
   574 		to_field = KToField;
       
   575 		if (i>0)
       
   576 			to_field.AppendNum(i);
       
   577 		index_item->AddFieldL(to_field, header->ToRecipients().MdcaPoint(i));
       
   578 		}
       
   579 
       
   580 	// Add the CcRecipients as content items
       
   581 	TBuf<64> cc_field;
       
   582 	for (TInt i = 0; i < header->CcRecipients().MdcaCount(); i++)
       
   583 		{
       
   584 		cc_field = KCcField;
       
   585 		if (i>0)
       
   586 			cc_field.AppendNum(i);
       
   587 		index_item->AddFieldL(cc_field, header->CcRecipients().MdcaPoint(i));
       
   588 		}
       
   589 
       
   590 	// Add the BccRecipients as content items
       
   591 	TBuf<64> bcc_field;
       
   592 	for (TInt i = 0; i < header->BccRecipients().MdcaCount(); i++)
       
   593 		{
       
   594 		bcc_field = KBccField;
       
   595 		if (i>0)
       
   596 			bcc_field.AppendNum(i);
       
   597 		index_item->AddFieldL(bcc_field, header->BccRecipients().MdcaPoint(i));
       
   598 		}
       
   599 
       
   600 	const TInt richTxtLen = (richtext->DocumentLength() < KMaxDocumentSize) ? richtext->DocumentLength() : KMaxDocumentSize;
       
   601 	HBufC* body_text = richtext->Read(0).Left(richTxtLen).AllocLC();
       
   602 
       
   603 	// Add subject
       
   604 	TPtrC subject(header->Subject());
       
   605 	index_item->AddFieldL(KSubjectField, subject);
       
   606 	
       
   607 	// Add message body
       
   608 	index_item->AddFieldL(KBodyField, *body_text);
       
   609 	
       
   610 	// Add excerpt
       
   611     HBufC* excerpt = CreateExcerptLC(header->From(), header->ToRecipients(), subject, *body_text, aFolderId);
       
   612     index_item->AddExcerptL(*excerpt);
       
   613 	CleanupStack::PopAndDestroy(excerpt);
       
   614 
       
   615 	// Cleanup everything last item message entry
       
   616 	CleanupStack::PopAndDestroy(8, message_entry);
       
   617 
       
   618 	// Pop the item
       
   619 	CleanupStack::Pop(index_item);
       
   620 	return index_item;	
       
   621 	}
       
   622 
       
   623 // ---------------------------------------------------------------------------
       
   624 // CMessageDataHandler::CreateExcerptLC
       
   625 // ---------------------------------------------------------------------------
       
   626 //
       
   627 HBufC* CMessageDataHandler::CreateExcerptLC(const TDesC& aFromAddress,
       
   628 											const CDesCArray& aRecipientArray,
       
   629 											const TDesC& aSubject,
       
   630 											const TDesC& aBodyText,
       
   631 											const TMsvId& aFolderId)
       
   632 	{
       
   633 	_LIT(KEllipsis, "...");
       
   634 	_LIT(KSpace, " ");
       
   635 	TInt excerptLength = KMsgBodyExcerptSymbols + KEllipsis().Length(); 
       
   636 
       
   637 	TMsvEntry entry;
       
   638 	TMsvId service = 0;
       
   639 	iMsvSession.GetEntry(aFolderId, service, entry);
       
   640 	HBufC *folder_str = entry.iDetails.AllocLC();
       
   641 
       
   642 	excerptLength += folder_str->Length();
       
   643 	excerptLength += KSpace().Length();
       
   644 
       
   645 	if ((aFromAddress.Length() > 0) && (aFolderId == KMsvGlobalInBoxIndexEntryIdValue))
       
   646 		{
       
   647 		excerptLength += aFromAddress.Length();
       
   648 		excerptLength += KSpace().Length();
       
   649 		}
       
   650 	if ((aRecipientArray.MdcaCount() > 0) && (aFolderId != KMsvGlobalInBoxIndexEntryIdValue))
       
   651 		{
       
   652 		excerptLength += aRecipientArray.MdcaPoint(0).Length();
       
   653 		excerptLength += KSpace().Length(); 
       
   654 		}
       
   655 	if (aSubject.Length() > 0)
       
   656 		{
       
   657 		excerptLength += aSubject.Length();
       
   658 		excerptLength += KSpace().Length();
       
   659 		}
       
   660 
       
   661 	HBufC* excerpt = HBufC::NewL(excerptLength);
       
   662 	TPtr excerptPtr = excerpt->Des();
       
   663 
       
   664 	excerptPtr.Copy(*folder_str);
       
   665 	excerptPtr.Append(KSpace);
       
   666 	
       
   667 	if ((aFromAddress.Length() > 0) && (aFolderId == KMsvGlobalInBoxIndexEntryIdValue))
       
   668 		{
       
   669 		excerptPtr.Append(aFromAddress);
       
   670 		excerptPtr.Append(KSpace);
       
   671 		}
       
   672 	if ((aRecipientArray.MdcaCount() > 0) && (aFolderId != KMsvGlobalInBoxIndexEntryIdValue))
       
   673 		{
       
   674 		excerptPtr.Append(aRecipientArray.MdcaPoint(0));
       
   675 		excerptPtr.Append(KSpace);
       
   676 		}
       
   677 	if (aSubject.Length() > 0)
       
   678 		{
       
   679 		excerptPtr.Append(aSubject);
       
   680 		excerptPtr.Append(KSpace);
       
   681 		}
       
   682 
       
   683 	excerptPtr.Append(aBodyText.Left(KMsgBodyExcerptSymbols));
       
   684 	if (aBodyText.Length() > KMsgBodyExcerptSymbols)
       
   685 		excerptPtr.Append(KEllipsis);
       
   686 
       
   687 	CleanupStack::PopAndDestroy(folder_str);
       
   688 	CleanupStack::PushL(excerpt);
       
   689 	return excerpt;
       
   690 	}
       
   691 
       
   692 // ---------------------------------------------------------------------------
       
   693 // CMessageDataHandler::IsTextUcs2
       
   694 // ---------------------------------------------------------------------------
       
   695 //
       
   696 TBool CMessageDataHandler::IsTextUcs2(const TDesC8& aText)
       
   697     {
       
   698     TBool ret = EFalse;
       
   699     // Check UCS-2 Byte order mark is in the first two bytes of aText
       
   700     if (aText.Length() >= sizeof(KMmsByteOrderMark))
       
   701         {
       
   702         TPtrC ptr(reinterpret_cast<const TUint16*>(aText.Ptr()), 
       
   703                         aText.Length() / sizeof(TText));
       
   704 
       
   705         if (KMmsByteOrderMark == ptr[0] ||
       
   706             KMmsReversedByteOrderMark == ptr[0])
       
   707             {
       
   708             ret = ETrue;
       
   709             }
       
   710         }
       
   711     return ret;
       
   712     }   	
       
   713 
       
   714 // ---------------------------------------------------------------------------
       
   715 // CMessageDataHandler::TextContainsUtf8Bom
       
   716 // ---------------------------------------------------------------------------
       
   717 //
       
   718 TBool CMessageDataHandler::TextContainsUtf8Bom(const TDesC8& aText)
       
   719     {    
       
   720     TBool ret = EFalse;
       
   721     // Check to see if there is the UTF8 BOM at the begining
       
   722     TPtrC8 utf8Id(KUtf8Bom, KUtf8BomLength);
       
   723     if (aText.Length() >= KUtf8BomLength &&
       
   724         aText.Left(KUtf8BomLength) == utf8Id)
       
   725         {
       
   726         ret = ETrue;
       
   727         }
       
   728     return ret;
       
   729     }
       
   730 
       
   731 // ---------------------------------------------------------------------------
       
   732 // CMessageDataHandler::TextFileCharsetL
       
   733 // ---------------------------------------------------------------------------
       
   734 //
       
   735 TUint CMessageDataHandler::TextFileCharsetL(RFs aFs, RFile aFile)
       
   736     {
       
   737     TUint ret = KMmsUsAscii;
       
   738     TBuf8<sizeof(KMmsByteOrderMark)> ucs2Buf;
       
   739 
       
   740     TInt size;
       
   741     User::LeaveIfError(aFile.Size(size));
       
   742     if (size >= sizeof(KMmsByteOrderMark))
       
   743         {
       
   744         // Check for the UCS-2 Byte Order Mark (BOM) at the beginning 
       
   745         // beginning of the file
       
   746         User::LeaveIfError(aFile.Read(ucs2Buf));
       
   747         if(IsTextUcs2(ucs2Buf))
       
   748             {
       
   749             ret = KMmsIso10646Ucs2;
       
   750             }
       
   751         }
       
   752 
       
   753     if (KMmsIso10646Ucs2 != ret)
       
   754         {
       
   755         // If the text is not UCS-2 it will probably be Utf8 or Ascii
       
   756 
       
   757         TInt seekPos = 0;
       
   758         User::LeaveIfError(aFile.Seek(ESeekStart, seekPos));
       
   759         
       
   760         HBufC8* buf = HBufC8::NewLC(size);
       
   761         TPtr8 ptr = buf->Des();
       
   762         User::LeaveIfError(aFile.Read(ptr));
       
   763 
       
   764         // Check to see if there is the UTF8 BOM at the begining
       
   765         if (TextContainsUtf8Bom(ptr))
       
   766             {
       
   767             ret = KMmsUtf8;
       
   768             }
       
   769         else
       
   770             {
       
   771             CCnvCharacterSetConverter* converter = 
       
   772                               CCnvCharacterSetConverter::NewLC();
       
   773             CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* availCharSets =
       
   774                 CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableLC(aFs);
       
   775 
       
   776             CArrayFix<CCnvCharacterSetConverter::SCharacterSet>* utf8CharSet = 
       
   777                 new (ELeave) CArrayFixFlat<CCnvCharacterSetConverter::SCharacterSet>(1); 
       
   778             CleanupStack::PushL(utf8CharSet);
       
   779 
       
   780             TInt count = availCharSets->Count();
       
   781             for (TInt i = 0; i < count; i++)
       
   782                 {
       
   783                 CCnvCharacterSetConverter::SCharacterSet& charSet = (*availCharSets)[i];
       
   784                 if (KCharacterSetIdentifierUtf8 == charSet.Identifier())
       
   785                     {
       
   786                     utf8CharSet->AppendL(charSet);
       
   787                     break;
       
   788                     }
       
   789                 }
       
   790             TInt confidence;
       
   791             TUint charSetId;
       
   792             converter->AutoDetectCharacterSetL(confidence, 
       
   793                                                charSetId, 
       
   794                                                *utf8CharSet,
       
   795                                                *buf);
       
   796             const TInt KMaxConfidence = 100;
       
   797             if (KMaxConfidence == confidence)
       
   798                 {
       
   799                 ret = KMmsUtf8;
       
   800                 }
       
   801             CleanupStack::PopAndDestroy(3, converter);
       
   802 
       
   803             }
       
   804 
       
   805         CleanupStack::PopAndDestroy(buf);
       
   806         }
       
   807 
       
   808     TInt zero = 0;
       
   809     User::LeaveIfError(aFile.Seek(ESeekStart, zero));
       
   810 
       
   811     return ret;
       
   812     }
       
   813 
       
   814 // ---------------------------------------------------------------------------
       
   815 // CMessageDataHandler::ConvertToUcs2FromUtfL
       
   816 // ---------------------------------------------------------------------------
       
   817 //
       
   818 void CMessageDataHandler::ConvertToUcs2FromUtfL(RFs& aFs,
       
   819                                                  TDes& aUcs2Text,
       
   820                                                  const TDesC8& aUtfText,
       
   821                                                  TUint aMibCharset)
       
   822     {
       
   823     TPtrC8 toConvert(aUtfText);
       
   824     if (KMmsUtf8 == aMibCharset)
       
   825         {
       
   826         if (TextContainsUtf8Bom(toConvert))
       
   827             {
       
   828             toConvert.Set(toConvert.Mid(KUtf8BomLength));
       
   829             }
       
   830         }
       
   831     // prepare to convert character set to unicode
       
   832     CCnvCharacterSetConverter* converter = 
       
   833                           CCnvCharacterSetConverter::NewLC();
       
   834     // change character set ID from MIB to Symbian
       
   835     TUint charsetID = converter->ConvertMibEnumOfCharacterSetToIdentifierL(
       
   836                                      aMibCharset, aFs);
       
   837     CCnvCharacterSetConverter::TAvailability availability =
       
   838             converter->PrepareToConvertToOrFromL(charsetID, aFs);
       
   839 
       
   840     if (availability == CCnvCharacterSetConverter::ENotAvailable)
       
   841         {
       
   842         User::Leave(KErrNotSupported);
       
   843         }
       
   844     TInt state = CCnvCharacterSetConverter::KStateDefault;
       
   845 
       
   846     User::LeaveIfError(converter->ConvertToUnicode(aUcs2Text, toConvert, state));
       
   847 
       
   848     CleanupStack::PopAndDestroy(converter);
       
   849     }
       
   850     
       
   851 	
       
   852 // -----------------------------------------------------------------------------
       
   853 // CMessageDataHandler::DoCancel
       
   854 // -----------------------------------------------------------------------------
       
   855 //   
       
   856 void CMessageDataHandler::DoCancel()
       
   857 	{
       
   858 	}
       
   859 
       
   860 // -----------------------------------------------------------------------------
       
   861 // CMessageDataHandler::RunL
       
   862 // -----------------------------------------------------------------------------
       
   863 //   
       
   864 void CMessageDataHandler::RunL()
       
   865 	{
       
   866 		OstTrace1( TRACE_NORMAL, CMESSAGEDATAHANDLER_RUNL, "CMessageDataHandler::RunL;status=%d", iStatus.Int() );
       
   867 		CPIXLOGSTRING2( "CMessageDataHandler::RunL status %d",iStatus.Int() );
       
   868 
       
   869 	// Implement round robin for the CActives
       
   870 	Deque();
       
   871 	CActiveScheduler::Add(this);
       
   872 
       
   873 	// Handle next message
       
   874 	if (iMessageArray.Count() > 0)
       
   875 		{
       
   876 		// Take first id from array
       
   877 		CreateMessageIndexItemL(iMessageArray[0].iMessageId,
       
   878 				iMessageArray[0].iActionType, iMessageArray[0].iFolderId);
       
   879 		
       
   880 		// Remove item that is handled
       
   881 		iMessageArray.Remove(0);
       
   882 
       
   883 		// Handle next
       
   884 		HandleNextRequest();
       
   885 		}
       
   886 	}
       
   887 
       
   888 // -----------------------------------------------------------------------------
       
   889 // CMessageDataHandler::RunError
       
   890 // -----------------------------------------------------------------------------
       
   891 //   
       
   892 TInt CMessageDataHandler::RunError(TInt aError)
       
   893 	{
       
   894 		OstTrace1( TRACE_NORMAL, CMESSAGEDATAHANDLER_RUNERROR, "CMessageDataHandler::RunError;Error=%d", aError );
       
   895 		CPIXLOGSTRING2( "CMessageDataHandler::RunError err %d", aError );
       
   896 	if (iMessageArray.Count() > 0)
       
   897 		{
       
   898 		// Remove item that is handled
       
   899 		iMessageArray.Remove(0);
       
   900 
       
   901 		// Handle next after the error
       
   902 		HandleNextRequest();
       
   903 		}
       
   904 	return KErrNone;
       
   905 	}
       
   906 
       
   907 // ---------------------------------------------------------------------------
       
   908 // HandleNextRequest
       
   909 // ---------------------------------------------------------------------------
       
   910 //
       
   911 void CMessageDataHandler::HandleNextRequest()
       
   912 	{
       
   913 	if (!IsActive())
       
   914 		{
       
   915 		SetActive();
       
   916 		TRequestStatus* status = &iStatus;
       
   917 		User::RequestComplete(status, KErrNone);
       
   918 		}
       
   919 	}
       
   920 
       
   921 // End of File
       
   922