messagingfw/biomsgfw/ENPSRC/ENP.CPP
changeset 0 8e480a14352b
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <msvids.h>
       
    17 #include <msvuids.h>
       
    18 #include <msvapi.h>
       
    19 #include <cemailaccounts.h>
       
    20 
       
    21 #include "ENP.H"
       
    22 #include <pop3set.h>
       
    23 #include <imapset.h>
       
    24 #include <miutconv.h>
       
    25 #include <e32math.h>
       
    26 
       
    27 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS 
       
    28 #include "tmsvbioinfo.h"
       
    29 #endif
       
    30 
       
    31 // Parse constants
       
    32 _LIT(KEmailHeader,"//MLAP11");
       
    33 #define KCharColon          ':'
       
    34 #define KCharSpace          ' '
       
    35 #define KCharTab            '\t'
       
    36 #define KCharLineFeed       '\n'
       
    37 #define KCharSlash			'/'
       
    38 
       
    39 // Header fields defined in Nokia Smart Messaging Specification grammar (3.9.2.1).
       
    40 // N.B. If new fields are added, (cf. <extension-field>) PrintFieldToRichTextL()
       
    41 // will need to be changed accordingly.
       
    42 _LIT(KHeaderNumberMessages, "msgcount");
       
    43 _LIT(KHeaderFrom,"from");
       
    44 _LIT(KHeaderSubject,"subject");
       
    45 _LIT(KHeaderSize,"size");
       
    46 _LIT(KHeaderUidImap,"iuid");
       
    47 _LIT(KHeaderUidPop,"puid");
       
    48 _LIT(KHeaderServerId,"sid");
       
    49 _LIT(KHeaderAttachments,"att");
       
    50 _LIT(KHeaderTo,"to");
       
    51 _LIT(KHeaderCc,"cc");
       
    52 _LIT(KHeaderDate,"date");
       
    53 _LIT(KHeaderFolder,"fldr");
       
    54 _LIT(KHeaderSender,"sender");
       
    55 _LIT(KHeaderReplyTo,"reply-to");
       
    56 _LIT(KHeaderUidValidity,"uidv");
       
    57 _LIT(KInitialFieldValue,"");
       
    58 
       
    59 #define KUidCharsetISO88591         0x10003b10
       
    60 #define	KServerIdModVal				512
       
    61 
       
    62 //
       
    63 // Factory methods
       
    64 //
       
    65 EXPORT_C CEmailNotificationParser* CEmailNotificationParser::NewL(CRegisteredParserDll& aRegisteredParserDll, CMsvEntry& aEntry, RFs& aFs)
       
    66     {
       
    67     CEmailNotificationParser* self = new (ELeave) CEmailNotificationParser(aRegisteredParserDll, aEntry, aFs);
       
    68     CleanupStack::PushL(self);
       
    69     self->ConstructL();
       
    70     CleanupStack::Pop();
       
    71     return self;
       
    72     }
       
    73 // end CEmailNotificationParser::NewL()
       
    74 
       
    75 
       
    76 void CEmailNotificationParser::ConstructL()
       
    77     {
       
    78     iParsedFieldArray = new (ELeave) CArrayPtrSeg<CParsedField>(16);
       
    79 
       
    80     // Initialise array with required field names
       
    81     // N.B. This dictates the order in which the headers will appear in the message body.
       
    82     AddRequiredFieldL(KHeaderNumberMessages);
       
    83 	AddRequiredFieldL(KHeaderFrom);
       
    84     AddRequiredFieldL(KHeaderSubject);
       
    85     AddRequiredFieldL(KHeaderTo);
       
    86     AddRequiredFieldL(KHeaderDate);
       
    87 	AddRequiredFieldL(KHeaderAttachments);
       
    88 	AddRequiredFieldL(KHeaderCc);
       
    89     AddRequiredFieldL(KHeaderSize);
       
    90     AddRequiredFieldL(KHeaderServerId);
       
    91     AddRequiredFieldL(KHeaderUidImap);
       
    92     AddRequiredFieldL(KHeaderUidPop);
       
    93 	//The following fields added to fix defect INC023328 
       
    94 	AddRequiredFieldL(KHeaderFolder);
       
    95     AddRequiredFieldL(KHeaderSender);
       
    96     AddRequiredFieldL(KHeaderReplyTo);
       
    97     AddRequiredFieldL(KHeaderUidValidity);
       
    98 
       
    99 	iFoundServer = EFalse;
       
   100 
       
   101     CActiveScheduler::Add(this);
       
   102     }
       
   103 // end CEmailNotificationParser::ConstructL()
       
   104 
       
   105 void CEmailNotificationParser::ParseL(TRequestStatus& aStatus, const TDesC& aSms)
       
   106     {
       
   107     TMsvEntry entry = iEntry.Entry();   //  Get the generic stuff
       
   108     iEntryId = entry.Id();              //  store the TMsvId
       
   109 
       
   110     __ASSERT_DEBUG((entry.MtmData3() == 0 || entry.MtmData3() == 1),
       
   111                             User::Panic(_L("ENP-DLL"),KErrCorrupt));
       
   112     //  Already parsed....
       
   113     if(entry.MtmData3() == 1)
       
   114         {
       
   115         iReport = &aStatus;
       
   116         User::RequestComplete(iReport, KErrNone);
       
   117         }
       
   118     //  not parsed
       
   119     else if(entry.MtmData3() == 0)
       
   120         {
       
   121         if (iSmsBuf != NULL)
       
   122             {
       
   123             delete iSmsBuf;
       
   124             iSmsBuf = NULL;
       
   125             }
       
   126         iSmsBuf = aSms.AllocL();            // Allocate new HBufC object
       
   127         ChangeStateL(EUnfoldMessage);       //Set to initial request
       
   128         aStatus = KRequestPending;
       
   129         iReport = &aStatus;
       
   130         }
       
   131     else
       
   132         {
       
   133         User::Leave(KErrNotSupported);
       
   134         }
       
   135     }
       
   136 // end CEmailNotificationParser::ParseL(TRequestStatus&, const TDesC&)
       
   137 
       
   138 
       
   139 
       
   140 //
       
   141 //  ProcessL() --    Email notification parser doesn't actually commit
       
   142 //                  any information to persistant store other than the 
       
   143 //                  iParsedFieldsArray data as part of the parse method
       
   144 //                  .. Complete  KErrNotSupported..
       
   145 //
       
   146 void CEmailNotificationParser::ProcessL(TRequestStatus& aStatus)
       
   147     {
       
   148     iReport = &aStatus;
       
   149     User::RequestComplete(iReport, KErrNotSupported);
       
   150     }
       
   151 // end CEmailNotificationParser::CommitL(TRequestStatus&)
       
   152 
       
   153 
       
   154 void CEmailNotificationParser::DoCancel()
       
   155     {
       
   156 	User::RequestComplete(iReport,KErrCancel);
       
   157     }
       
   158 // end CEmailNotificationParser::DoCancel()
       
   159 
       
   160 
       
   161 void CEmailNotificationParser::RunL()
       
   162     {
       
   163     iCompleted = iStatus.Int();
       
   164     if (iCompleted != KErrNone)
       
   165         {
       
   166         User::RequestComplete(iReport,iCompleted);
       
   167         return;
       
   168         }
       
   169 
       
   170     switch (iState)
       
   171         {
       
   172         case EUnfoldMessage:        // UnfoldSmsL completed
       
   173             TRAPD(err, ChangeStateL(EParseMessage));
       
   174             if (err != KErrNone)
       
   175                 User::RequestComplete(iReport, err);
       
   176             break;
       
   177 
       
   178         case EParseMessage:
       
   179             TRAP(err, ChangeStateL(ECompleteMessage));
       
   180             if(err != KErrNone)
       
   181                 {
       
   182                 User::RequestComplete(iReport, err);
       
   183                 }
       
   184             break;
       
   185                         
       
   186         case ECompleteMessage:
       
   187             // CompleteMessage completed
       
   188             User::RequestComplete(iReport, KErrNone);
       
   189             break;
       
   190 
       
   191         default:
       
   192             break;
       
   193         }
       
   194     }
       
   195 // end CEmailNotificationParser::RunL()
       
   196 
       
   197 
       
   198 void CEmailNotificationParser::ChangeStateL(TParseSession aState)
       
   199     {
       
   200     iState = aState;
       
   201     switch (iState)
       
   202         {                    
       
   203         case EUnfoldMessage:
       
   204             UnfoldMessageL();
       
   205             iSms = iSmsBuf->Des();      // initialise Tlex object
       
   206             break;
       
   207 
       
   208         case EParseMessage:
       
   209             ParseMessageL();
       
   210             break;
       
   211 
       
   212         case ECompleteMessage:
       
   213             CompleteMessageL();
       
   214             break;
       
   215 
       
   216         default:
       
   217             break;
       
   218         }
       
   219 	RequestComplete(iStatus, KErrNone);
       
   220 
       
   221     SetActive();
       
   222     }
       
   223 // end CEmailNotificationParser::ChangeStateL(TParseSession)
       
   224 
       
   225 
       
   226 void CEmailNotificationParser::UnfoldMessageL()
       
   227     {
       
   228     // Nokia protocol allows for folding of long fields (see Nokia Smart
       
   229     // Messaging spec 2.0.0pre, 3-34 and RFC822, 3.1.1). This method
       
   230     // unfolds the message by deleting any linefeed characters which are
       
   231     // followed immediately by linear white space.
       
   232     //   Note that the value returned by pBuf.Length() will change if
       
   233     // linefeeds are deleted. Hence this is called for each iteration to
       
   234     // avoid violating buffer bounds.
       
   235 
       
   236     TPtr pBuf(iSmsBuf->Des());     // Create modifiable pointer to HBufC
       
   237 
       
   238     for (TInt pos = 0; pos < (pBuf.Length() - 1); pos++)
       
   239         {
       
   240         // Find linefeed followed by whitespace
       
   241         if (pBuf[pos] == KCharLineFeed  &&
       
   242             (pBuf[pos+1] == KCharSpace  ||  pBuf[pos+1] == KCharTab))
       
   243             {
       
   244             pBuf.Delete(pos, 1);
       
   245             }
       
   246         }
       
   247 
       
   248     // Reallocate iSmsBuf with new size
       
   249     iSmsBuf = iSmsBuf->ReAllocL(pBuf.Length());
       
   250     }
       
   251 // end CEmailNotificationParser::UnfoldSmsL()
       
   252 
       
   253 //
       
   254 //  ParseMessageL()
       
   255 //
       
   256 //  Simple Notification:
       
   257 //      Looks for number of messages and "From:" field
       
   258 //      writes numMsg into the parsed field array, sets
       
   259 //      entry.iDetails to the "From:" 
       
   260 //  Complicated Notification:
       
   261 //      does the above and writes everything else into
       
   262 //      the array....
       
   263 //
       
   264 void CEmailNotificationParser::ParseMessageL()
       
   265     {
       
   266     TBool isSimpleNotification = EFalse; 
       
   267     TLex  tokenLex;
       
   268     TPtrC fieldName;
       
   269     TPtrC fieldValue;
       
   270 
       
   271 	// reset parsedfield array
       
   272 	for(TInt i = iParsedFieldArray->Count();--i>=0;)
       
   273 		(*iParsedFieldArray)[i]->SetFieldValueL(_L(""));
       
   274 
       
   275     // Set extraction mark at first character
       
   276     iSms.SkipSpaceAndMark();
       
   277 	if(iSms.Peek() == KCharSlash)
       
   278 		{
       
   279 		// Check first line is <header>
       
   280 		iSms.SkipCharacters();
       
   281 
       
   282 		if (iSms.MarkedToken() != KEmailHeader)
       
   283 			{
       
   284 			User::Leave(KBspInvalidMessage);
       
   285 			}
       
   286 		// Get <new-amount> from second line and check for terminating linefeed
       
   287 		iSms.SkipSpaceAndMark();
       
   288 		}
       
   289 
       
   290     // Val() seeks forward from next char position, looking for valid
       
   291     // digits and incrementing next char as it goes.
       
   292     if (!(iSms.Val(iMessageCount) == KErrNone  &&  iMessageCount >= 0))     // If marked token is not a valid positive integer
       
   293         {
       
   294         iMessageCount = 0;
       
   295         User::Leave(KBspInvalidMessage);
       
   296         }
       
   297     else
       
   298         {
       
   299         fieldValue.Set(iSms.MarkedToken());                            //  The message count..
       
   300         AddParsedFieldL(KHeaderNumberMessages, fieldValue, ETrue);
       
   301         }
       
   302 
       
   303     // Next character may now be at newline or space after integer.
       
   304     // If at space, advance to newline.
       
   305     while (iSms.Peek() != KCharLineFeed && !iSms.Eos())
       
   306         iSms.Inc();
       
   307 
       
   308     iSms.SkipSpaceAndMark();
       
   309 
       
   310     // Now parse the rest of the fields, if any.
       
   311     while (!iSms.Eos())
       
   312         {
       
   313         while (iSms.Peek() != KCharLineFeed  &&  !iSms.Eos())
       
   314             iSms.Inc();     //  Skip to next delimiter
       
   315 
       
   316         if (iSms.Eos())
       
   317             break;          //  we've finished break out of the function
       
   318 
       
   319         if (iSms.TokenLength() == 0)
       
   320             User::Leave(KBspSmartMessageInvalidToken);
       
   321 
       
   322         //  Parsing....
       
   323         tokenLex.Assign(iSms.MarkedToken());        // Assign token to a new TLex
       
   324         while (tokenLex.Peek() != KCharColon  &&  !tokenLex.Eos())
       
   325             tokenLex.Inc();     //  Advance to a ':'
       
   326 
       
   327         if (tokenLex.Eos()  ||  tokenLex.TokenLength() == 0)
       
   328             User::Leave(KBspSmartMessageInvalidToken);
       
   329 
       
   330 
       
   331         fieldName.Set(tokenLex.MarkedToken());      // Store (pointer to) field name
       
   332         tokenLex.Inc();
       
   333 
       
   334 		//fix for DEF017686
       
   335 		LeaveIfEmptyFieldsL(fieldName,tokenLex);
       
   336 		
       
   337         
       
   338         tokenLex.SkipSpaceAndMark();                // Step past optional spaces
       
   339 
       
   340 		//fix for DEF017686
       
   341         LeaveIfEmptyFieldsL(fieldName,tokenLex);
       
   342 	
       
   343 		// if it's the server id field try to extract the id value
       
   344 		// and match to an existing email service
       
   345 		if(fieldName.CompareF(KHeaderServerId)==KErrNone)
       
   346 			{
       
   347 			TInt valErr = tokenLex.Val(iServerId);
       
   348 			if(valErr != KErrNone)
       
   349 				iServerId = 0;
       
   350 			else
       
   351 				GetEmailServicesL();
       
   352 
       
   353 			tokenLex.UnGetToMark();
       
   354 			}	
       
   355 		fieldValue.Set(tokenLex.Remainder());       // Store (pointer to) field value
       
   356 
       
   357         if(!isSimpleNotification)
       
   358             {
       
   359             AddParsedFieldL(fieldName, fieldValue, EFalse);
       
   360             }		
       
   361 
       
   362         // Successfully parsed a token. Move iSms's next character past the
       
   363         // (linefeed) delimiter, set the extraction mark and reiterate to
       
   364         // look for next token.
       
   365         iSms.SkipSpaceAndMark();
       
   366         }
       
   367     }
       
   368 // end CEmailNotificationParser::ParseMessageL()
       
   369 
       
   370 
       
   371 //fix for DEF017686: EMail notification parser leaves when field data is empty  
       
   372 void CEmailNotificationParser::LeaveIfEmptyFieldsL(const TDesC& aFieldName,
       
   373 												   const TLex& aTokenLex)
       
   374 	{
       
   375 /*
       
   376  		The following  checks for an empty field value.
       
   377  		The only fields allowed to be empty are the subject  and extension fields.
       
   378  		Hence, the check is done when aFieldName is not  a subject field and an extension field.
       
   379  		However, it is not possible to explicitly check for an extension field as we don't 
       
   380  		know which strings to compare. Therefore, a comparison with all the known field names
       
   381  		must be performed instead. The risk is fairly small as the change is localised and it can 
       
   382  		be easily tested.
       
   383 */
       
   384 
       
   385 	if ((aFieldName.CompareF(KHeaderFrom)==KErrNone) ||
       
   386  		(aFieldName.CompareF(KHeaderSize)==KErrNone) ||
       
   387 		(aFieldName.CompareF(KHeaderUidImap)==KErrNone) ||
       
   388  		(aFieldName.CompareF(KHeaderUidPop)==KErrNone) ||
       
   389  		(aFieldName.CompareF(KHeaderServerId)==KErrNone) ||
       
   390  		(aFieldName.CompareF(KHeaderAttachments)==KErrNone) ||
       
   391  		(aFieldName.CompareF(KHeaderTo)==KErrNone) ||
       
   392  		(aFieldName.CompareF(KHeaderCc)==KErrNone) ||
       
   393  		(aFieldName.CompareF(KHeaderDate)==KErrNone) ||
       
   394  		(aFieldName.CompareF(KHeaderFolder)==KErrNone) ||
       
   395  		(aFieldName.CompareF(KHeaderSender)==KErrNone) ||
       
   396  		(aFieldName.CompareF(KHeaderReplyTo)==KErrNone) ||
       
   397  		(aFieldName.CompareF(KHeaderUidValidity)==KErrNone) //not sure if this actually exists*/
       
   398 	   )
       
   399  		
       
   400  		if (aTokenLex.Eos())
       
   401  			User::Leave(KBspSmartMessageInvalidToken);	
       
   402 	}
       
   403 
       
   404 
       
   405 //
       
   406 //  CompleteMessageL()
       
   407 //
       
   408 //  -   Function streams the contents of iParsedFieldsArray
       
   409 //      as a child entry of the original message. If this
       
   410 //      returns OK sets the iMtmData3 flag to 1 (parsed) and
       
   411 //      writes a new message body into the SmartMessage
       
   412 //
       
   413 //  -   If externalization fails the function sets the message
       
   414 //      not parsed and does not alter the message body.
       
   415 //
       
   416 void CEmailNotificationParser::CompleteMessageL()
       
   417     {
       
   418 	//Create new stream (containing parsed data) within CMsvStore associated with message entry
       
   419 	iEntry.SetEntryL(iEntryId);
       
   420 	CMsvStore* store=iEntry.EditStoreL();
       
   421 	CleanupStack::PushL(store);
       
   422 	StoreL(*store);
       
   423 	CleanupStack::PopAndDestroy();
       
   424 
       
   425 	TMsvEntry entry= iEntry.Entry();
       
   426     entry.SetMtmData3(1);                                //  Indicates that we've parsed it..
       
   427 
       
   428 	// set iRelated id if we know which server the message corresponds to
       
   429 	// iRelatedId is set to the id of the relevant service entry.
       
   430 	if(iFoundServer)
       
   431 		entry.iRelatedId = iServiceMsvId;
       
   432 	iEntry.ChangeL(entry);
       
   433     }
       
   434 // end CEmailNotificationParser::CompleteMessageL()
       
   435 
       
   436 void CEmailNotificationParser::AddRequiredFieldL(const TDesC& aFieldName)
       
   437     {
       
   438     // Create new CParsedField object on heap
       
   439     CParsedField* parsedField = new (ELeave) CParsedField;
       
   440 	CleanupStack::PushL(parsedField);
       
   441     // Initialise field name
       
   442     parsedField->SetFieldNameL(aFieldName);
       
   443     parsedField->SetFieldValueL(KInitialFieldValue);
       
   444     parsedField->SetMandatoryField(EFalse);
       
   445 
       
   446     // Add pointer to array
       
   447     iParsedFieldArray->AppendL(parsedField);
       
   448     CleanupStack::Pop();
       
   449     // No need to delete the CParsedField object, since it's now owned by the array
       
   450     }
       
   451 // end CEmailNotificationParser::AddRequiredFieldL(const TDesC&)
       
   452 
       
   453 
       
   454 void CEmailNotificationParser::AddParsedFieldL(const TDesC& aFieldName,
       
   455                                               const TDesC& aFieldValue,
       
   456                                               TBool aMandatory)
       
   457     {
       
   458     // This method is responsible for adding field values found
       
   459     // by the parser to the array of parsed fields. It also
       
   460     // enforces the "each field once only" rule (see Nokia Smart
       
   461     // Messaging spec, 2.0.0pre, 3-34).
       
   462     for (TInt i = 0; i < iParsedFieldArray->Count(); i++)
       
   463         {
       
   464         // Use CompareF() to perform case-insensitive match
       
   465         if (aFieldName.CompareF(iParsedFieldArray->At(i)->FieldName()) == 0)
       
   466             {
       
   467             // Field name exists, so insert a value
       
   468             iParsedFieldArray->At(i)->SetFieldValueL(aFieldValue);
       
   469             iParsedFieldArray->At(i)->SetMandatoryField(aMandatory);
       
   470             iExtendedNotification = ETrue;
       
   471 			return;
       
   472             }
       
   473         }
       
   474 
       
   475 	// This has been added to fix defect INC38950
       
   476 	// If we have got here, then we have a new field, not specified by one of the fields in iParseFieldArray
       
   477     CParsedField* parsedField = new (ELeave) CParsedField;
       
   478 	CleanupStack::PushL(parsedField);
       
   479     parsedField->SetFieldNameL(aFieldName);
       
   480     parsedField->SetFieldValueL(aFieldValue);
       
   481     parsedField->SetMandatoryField(EFalse);
       
   482     iParsedFieldArray->AppendL(parsedField);
       
   483     CleanupStack::Pop(parsedField);
       
   484 	}
       
   485 // end CEmailNotificationParser::AddParsedFieldL(const TDesC&, const TDesC&, TBool)
       
   486 
       
   487 //
       
   488 // Get all email services
       
   489 //
       
   490 void CEmailNotificationParser::GetEmailServicesL()
       
   491 	{
       
   492 
       
   493 	CCnvCharacterSetConverter* charconv = CCnvCharacterSetConverter::NewL();
       
   494 	CleanupStack::PushL(charconv);
       
   495 	CArrayFix<CCnvCharacterSetConverter::SCharacterSet> *charsetsAvailable = charconv->CreateArrayOfCharacterSetsAvailableL(iFs);
       
   496 	CleanupStack::PushL(charsetsAvailable);
       
   497 
       
   498 	charconv->PrepareToConvertToOrFromL(KUidCharsetISO88591,*charsetsAvailable,iFs);
       
   499 	
       
   500 	const TMsvId current = iEntry.Entry().Id();
       
   501 	iEntry.SetEntryL(KMsvRootIndexEntryId);
       
   502 	// Get all POP3 and Imap services
       
   503 	CMsvEntrySelection* rootChildren = iEntry.ChildrenL();
       
   504 	CleanupStack::PushL(rootChildren);
       
   505 
       
   506 	TMsvEntry entry;
       
   507 
       
   508 	CEmailAccounts* accounts = CEmailAccounts::NewLC();
       
   509 
       
   510 	const TInt count = rootChildren->Count(); 
       
   511 	TInt j =0;
       
   512 	while(j < count && iFoundServer ==EFalse)
       
   513 		{
       
   514 		// set context to service entry
       
   515 		iEntry.SetEntryL((*rootChildren)[j]);
       
   516 		entry = iEntry.Entry(); 
       
   517 		if (entry.iType == KUidMsvServiceEntry && (entry.iMtm == KUidMsgTypePOP3 || entry.iMtm == KUidMsgTypeIMAP4))
       
   518 			{
       
   519 			TBuf8<8> port;
       
   520 
       
   521 			if(entry.iMtm == KUidMsgTypePOP3)
       
   522 				{
       
   523 				// calculate hash value
       
   524 				CImPop3Settings* settings = new(ELeave)CImPop3Settings;
       
   525 				CleanupStack::PushL(settings);
       
   526  
       
   527  				TPopAccount id;
       
   528 				accounts->GetPopAccountL(entry.Id(), id);
       
   529 				accounts->LoadPopSettingsL(id, *settings);
       
   530 
       
   531 				port.Num((TUint)KPOP3DefaultPortNumber);
       
   532 				iFoundServer = CalcHashValueL( *charconv, settings->LoginName(), settings->ServerAddress(), port);
       
   533 				}
       
   534 			else // entry.iMtm == KUidMsgTypeIMAP4
       
   535 				{
       
   536 				CImImap4Settings* settings = new(ELeave)CImImap4Settings;
       
   537 				CleanupStack::PushL(settings);
       
   538 				
       
   539  				TImapAccount id;
       
   540 				accounts->GetImapAccountL(entry.Id(), id);
       
   541 				accounts->LoadImapSettingsL(id, *settings);
       
   542 
       
   543 				port.Num((TUint)KIMAPDefaultPortNumber);
       
   544 				iFoundServer = CalcHashValueL( *charconv, settings->LoginName(), settings->ServerAddress(), port);
       
   545 				}
       
   546 			CleanupStack::PopAndDestroy(); // settings
       
   547 			}
       
   548 		j++;
       
   549 		}
       
   550 
       
   551 	if(	iFoundServer )
       
   552 		iServiceMsvId = entry.Id();
       
   553 
       
   554 	CleanupStack::PopAndDestroy(4, charconv); // charconv, charsetsAvailable, rootChildren, accounts
       
   555 	
       
   556 	iEntry.SetEntryL(current);
       
   557 	}
       
   558 
       
   559 //
       
   560 // Calculate a hash value for each server entry
       
   561 // 
       
   562 TBool CEmailNotificationParser::CalcHashValueL(CCnvCharacterSetConverter& aCharConv, const TDesC8& aUserName, const TDesC& aServerName, const TDesC8& aPortNum)
       
   563 	{
       
   564 	TInt total = 0;
       
   565 	TInt loop = 0;
       
   566 	TInt unConvertChar;
       
   567 	TInt posOfUnconv;
       
   568 
       
   569 	delete iServerName;
       
   570 	iServerName = NULL;
       
   571 	iServerName = HBufC8::NewL(aServerName.Length());
       
   572 
       
   573 	TPtr8 svr = iServerName->Des();
       
   574 	aCharConv.ConvertFromUnicode( svr, aServerName, unConvertChar,posOfUnconv);
       
   575 
       
   576 	// Fix for DEF044588: the Smart Messaging Specification (Revision 3.0.0) states (page 3-17) that
       
   577 	// the value of the first character of S is multiplied by one, second character by two etc.
       
   578 	for(loop = 0; loop < aUserName.Length(); loop++)
       
   579 		{
       
   580 		total += ( (loop+1) * (TUint)aUserName[loop]);
       
   581 		}
       
   582 
       
   583 	TInt pos = aUserName.Length();
       
   584 
       
   585 	for(loop = 0; loop < svr.Length(); loop++)
       
   586 		{
       
   587 		total += ( (pos + (loop+1) )* (TUint)svr[loop]);
       
   588 		}
       
   589 
       
   590 	pos += aServerName.Length();
       
   591 
       
   592 	for(loop = 0; loop < aPortNum.Length(); loop++)
       
   593 		{
       
   594 		total += ( (pos + (loop+1) )* (TUint)aPortNum[loop]);
       
   595 		}
       
   596 
       
   597 	TReal hashVal;
       
   598 	User::LeaveIfError(Math::Mod(hashVal, total, KServerIdModVal));
       
   599 	return ((TInt)hashVal == iServerId);
       
   600 	}
       
   601 
       
   602 void CEmailNotificationParser::RequestComplete(TRequestStatus& aStatus, TInt aError)
       
   603     {
       
   604     TRequestStatus* p = &aStatus;
       
   605     User::RequestComplete(p, aError);
       
   606     }
       
   607 // end CEmailNotificationParser::RequestComplete(TRequestStatus&, TInt)
       
   608 
       
   609 //
       
   610 // Constructor
       
   611 //
       
   612 CEmailNotificationParser::CEmailNotificationParser(CRegisteredParserDll& aRegisteredParserDll, CMsvEntry& aEntry, RFs& aFs)
       
   613 : CBaseScriptParser2(aRegisteredParserDll, aEntry, aFs), 
       
   614 iState(0), iSmsBuf(0), iReport(0), iCompleted(0), iMessageCount(0), iExtendedNotification(EFalse)
       
   615     {
       
   616     }
       
   617 // end CEmailNotificationParser::CEmailNotificationParser()
       
   618 
       
   619 CEmailNotificationParser::~CEmailNotificationParser()
       
   620     {
       
   621 	delete iSmsBuf;
       
   622 	if(iParsedFieldArray)
       
   623 		{
       
   624 		iParsedFieldArray->ResetAndDestroy();
       
   625 		delete iParsedFieldArray;
       
   626 		}
       
   627 	delete iServerName;
       
   628     }
       
   629 // end CEmailNotificationParser::~CEmailNotificationParser()