common/tools/ats/smoketest/email/email/smtp/src/Local_imcvrecv.cpp
changeset 719 d5603c08781b
child 872 17498133d9ad
equal deleted inserted replaced
718:b18be44be852 719:d5603c08781b
       
     1 // Copyright (c) 2006-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 the License "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 
       
    18 /**
       
    19  @file
       
    20 */
       
    21 
       
    22 
       
    23 // epoc include
       
    24 #include <e32base.h>
       
    25 #include <imutdll.h>
       
    26 #include <imcvtext.h>
       
    27 #include "Local_imcvrecv.h"
       
    28 #include <imcvcodc.h>	// TImConvert
       
    29 #include <imcvutil.h>
       
    30 
       
    31 #include <miuthdr.h>	// CImHeader
       
    32 #include <miutatch.h>	// TImAttachmentFile
       
    33 #include <txtrich.h>
       
    34 #include <imcm.rsg>		// resource definition for IMCM
       
    35 
       
    36 #include <pop3set.h>	// For including KUidMsgTypePOP3
       
    37 #include <barsread.h>	// TResourceReader
       
    38 
       
    39 #include <cmsvbodytext.h>
       
    40 
       
    41 #ifdef __WINS__
       
    42 #include <e32wins.h>    // for maxfilename lengths
       
    43 #include <msvapi.h>
       
    44 #endif
       
    45 
       
    46 #ifndef __WINS__
       
    47 #include <msvapi.h>
       
    48 #endif
       
    49 #include <cmsvattachment.h> 
       
    50 #include <mmsvattachmentmanager.h>
       
    51 #include <mmsvattachmentmanagersync.h>
       
    52 #ifndef _MSG_NO_LOGGING
       
    53 #define __IMUT_LOGGING
       
    54 
       
    55 
       
    56 // literals used
       
    57 _LIT(KLogFilePath, "c:\\logs\\mailtext\\in.txt");
       
    58 _LIT8(KNewLogHeader, "\r\n------ New Receive Session ------\r\n");
       
    59 _LIT8(KFound, "found: ");
       
    60 _LIT8(KPartLine, "unknown or part line");
       
    61 _LIT8(KEndOFHeader, "End of header");
       
    62 _LIT8(KSkippingData, "Skipping data");
       
    63 _LIT8(KCollectingData7, "Collecting 7/8-bit data");
       
    64 _LIT8(KCollectingDataQP, "Collecting QP data");
       
    65 _LIT8(KCollectingBase64, "Collecting BASE64 data");
       
    66 _LIT8(KCollectingUU, "Collecting UU data");
       
    67 _LIT8(KDecodingBase64, "Decoding BASE64 data");
       
    68 _LIT8(KDecodedBase64, "Decoded BASE64 data");
       
    69 _LIT8(KDecodingUU, "Decoding UU data");
       
    70 _LIT8(KDecodedUU, "Decoded UU data");
       
    71 _LIT8(KDecodingQP, "Decoding QP data");
       
    72 _LIT8(KDecodedQP, "Decoded QP data");
       
    73 _LIT8(KUUEDataCorrupt, "UU Data is corrupt");
       
    74 _LIT8(KFoundUUEStartBoundary, "UUE start boundary");
       
    75 _LIT8(KFoundUUEEndBoundary, "UUE end boundary");
       
    76 _LIT8(KClosingAttachFile, "Closing attachment file");
       
    77 _LIT8(KDeletingAttachFile, "Deleting attachment file");
       
    78 _LIT8(KDeletedAttachFile, "Deleted attachment file");
       
    79 _LIT8(KFailedToWriteToFile, "Failed to write to attachment file");
       
    80 _LIT8(KSectionHeader, "Section header");
       
    81 _LIT8(KFoundMIMEBoundary, "MIME boundary");
       
    82 _LIT8(KWritingToBody, "writing body");
       
    83 _LIT8(KWroteToBody, "wrote body");
       
    84 _LIT8(KWritingToFile, "writing attachment");
       
    85 _LIT8(KWroteToFile, "wrote attachment");
       
    86 _LIT8(KReset, "Resetting CLocalImRecvConvert");
       
    87 _LIT8(KReseted, "Resetting CLocalImRecvConvert");
       
    88 _LIT8(KDeleted, "Deleting CLocalImRecvConvert");
       
    89 _LIT8(KLineHasLineBreak, "Linebreak");
       
    90 _LIT8(KLastToken, "That was the last token");
       
    91 _LIT8(KBlankLine, "Blank line");
       
    92 _LIT8(KRemoveBoundary, "Remove boundary");
       
    93 _LIT8(KRemovedBoundary, "Removed boundary");
       
    94 _LIT8(KResetForNewEntry, "Reset for a New Entry");
       
    95 _LIT8(KResetedForNewEntry, "Reseted for a New Entry");
       
    96 _LIT8(KResetForNonMimeEntry, "Reset for a New Non-Mime Entry");
       
    97 _LIT8(KResetedForNonMimeEntry, "Reseted for a New Non-Mime Entry");
       
    98 _LIT8(KCreatingEntry, "Creating Entry");
       
    99 _LIT8(KCreatedEntry, "Created Entry");
       
   100 _LIT8(KUpdatingEntry, "Updating Entry");
       
   101 _LIT8(KUpdatedEntry, "Updated Entry");
       
   102 _LIT8(KMoveToParentEntry, "Moved to parent entry");
       
   103 _LIT8(KMovedToParentEntry, "End of Moved to parent entry");
       
   104 _LIT8(KStoringHeader, "Storing CImHeader");
       
   105 _LIT8(KStoredHeader, "Stored CImHeader");
       
   106 _LIT8(KStoringBody, "Storing CRichText");
       
   107 _LIT8(KStoring8BitBody, "Storing CMsvBodyText");
       
   108 _LIT8(KStoredBody, "Stored CRichText");
       
   109 _LIT8(KStored8BitBody, "Stored CMsvBodyText");
       
   110 _LIT8(KStoringMIMEHeader, "Storing CImMimeHeader");
       
   111 _LIT8(KStoredMIMEHeader, "Stored CImMimeHeader");
       
   112 _LIT8(KIgnoringStreams, "Discarding streams");
       
   113 _LIT8(KStartMessageComplete, "Start Message Complete");
       
   114 _LIT8(KMessageComplete, "Message Complete");
       
   115 _LIT8(KHeaderComplete, "Message Header complete");
       
   116 _LIT8(KReturnReceiptTo, "return-receipt-To is set");
       
   117 _LIT8(KStartStoringEntryStream, "Starting Storing Entry Stream");
       
   118 _LIT8(KStoringEntryStream, "Storing Entry Stream");
       
   119 _LIT8(KDoneStoringEntryStream, "Done Storing Entry Stream");
       
   120 #endif // _MSG_NO_LOGGING
       
   121 
       
   122 // uncomment the line below if logging is to be enabled
       
   123 
       
   124 #if defined(__IMUT_LOGGING)
       
   125 #define RECVLOG(text) (iImcvLog?iImcvLog->AppendComment(text):void(0));
       
   126 #define RECVLOG_OUT(text) (iImcvLog?iImcvLog->AppendOut(text):void(0));
       
   127 #define LOGGING(string1, string2) (Logging(string1, string2));
       
   128 #else
       
   129 #define RECVLOG(text) (void(0));
       
   130 #define RECVLOG_OUT(text) (void(0));
       
   131 #define LOGGING(string1, string2) (void(0));
       
   132 #endif
       
   133 
       
   134 #define UNUSED_VAR( var ) var = var  // fix for armv5 build warnings
       
   135 const TInt KBodyTextChunkSizeBytes = 512;
       
   136 
       
   137 _LIT(KIntegerKey,"%d");
       
   138 const TInt KSpaceToAddNumber=20;
       
   139 
       
   140 // added this to handle DRM files
       
   141 _LIT8(KTImcvDrm, "testagent.drm");
       
   142 
       
   143 
       
   144 /**
       
   145 IsIllegalChar()
       
   146 Checks if the character is illegal in EPOC32 file system
       
   147 
       
   148 @param aChar
       
   149 @return
       
   150 */
       
   151 LOCAL_C TBool IsIllegalChar(const TUint aChar)
       
   152 	{
       
   153 	// EPOC32 filenames must not contain any of the following chars
       
   154     return (aChar == '*' || aChar == '\\' || aChar == '<' || aChar == '>' ||
       
   155 			aChar == ':'  || aChar == '"' ||  aChar    == '/' || aChar == '|' ||
       
   156 			aChar < ' ' || aChar == '?');
       
   157 	}
       
   158 
       
   159 /**
       
   160 RemoveSurroundingCharacters()
       
   161 
       
   162 @param aLeft
       
   163 @param aRight
       
   164 @param aString
       
   165 */
       
   166 LOCAL_C void RemoveSurroundingCharacters( const TUint8& aLeft, const TUint8& aRight, HBufC8& aString)
       
   167 	{
       
   168 	TPtr8 des = aString.Des();
       
   169 	TInt len  = des.Length();
       
   170 	
       
   171 	if( len > 2 && des[0] == aLeft && des[len - 1] == aRight )
       
   172 		{
       
   173 		TPtrC8 mid = des.Mid(1, len - 1);
       
   174 		des.Copy(mid);
       
   175 		des.SetLength(len - 2);
       
   176 		}
       
   177 	}
       
   178 
       
   179 
       
   180 //****************************************************************************************
       
   181 //              Class CLocalRfc822Token Functions
       
   182 //****************************************************************************************
       
   183 
       
   184 
       
   185 /**
       
   186 NewLC()
       
   187 Static factory constructor. Uses two phase 
       
   188 construction.
       
   189 
       
   190 @leave KErrNoMemory
       
   191 @return
       
   192 A pointer to the newly created CLocalRfc822Token object.
       
   193 */
       
   194 CLocalRfc822Token* CLocalRfc822Token::NewLC()
       
   195 	{
       
   196 	CLocalRfc822Token* self = new (ELeave) CLocalRfc822Token;
       
   197 	CleanupStack::PushL(self);
       
   198 	self->ConstructL();
       
   199 	return self;
       
   200 	}
       
   201 
       
   202 
       
   203 /**
       
   204 ConstructL()
       
   205 
       
   206 */
       
   207 void CLocalRfc822Token::ConstructL()
       
   208 	{
       
   209 	iOutputLine = HBufC8::NewL(KMaxIMailHeaderReadLineLength + 1);
       
   210 	Reset();
       
   211 	}
       
   212 
       
   213 
       
   214 /**
       
   215 CLocalRfc822Token()
       
   216 Constructor
       
   217 */
       
   218 CLocalRfc822Token::CLocalRfc822Token()
       
   219 	{
       
   220 	__DECLARE_NAME(_S("CLocalRfc822Token"));
       
   221 	}
       
   222 
       
   223 
       
   224 /**
       
   225 ~CLocalRfc822Token()
       
   226 Destructor
       
   227 */
       
   228 CLocalRfc822Token::~CLocalRfc822Token()
       
   229 	{
       
   230 	delete iOutputLine;
       
   231 	iOutputLine=NULL;
       
   232 	}
       
   233 
       
   234 
       
   235 /**
       
   236 Reset()
       
   237 
       
   238 */
       
   239 void CLocalRfc822Token::Reset()
       
   240 	{
       
   241 	iOutputLine->Des().FillZ();
       
   242 	iBufferedInput.SetLength(0);
       
   243 	iBufferedInput.FillZ();
       
   244 
       
   245 	iLastToken = EFalse;
       
   246 	iFirstLine = ETrue;
       
   247 	i822FieldsExist=EFalse;
       
   248 	}
       
   249 
       
   250 
       
   251 /**
       
   252 ParseNextLineL()
       
   253 
       
   254 @param aSourceLine
       
   255 */
       
   256 void CLocalRfc822Token::ParseNextLineL(const TDesC8& aSourceLine)
       
   257 	{
       
   258 	TBool hitEof = EFalse;
       
   259 	TBool endOfField = EFalse;
       
   260 	// Always read one more packet than we need so we know we've read the entire field.
       
   261 
       
   262 	// Consequently, we need to check whether there is any buffered input from the
       
   263 	// previous rfc822 field:*******
       
   264 
       
   265 	if(iBufferedInput.Length())
       
   266 		{
       
   267 		// the buffered input is never more than a line of text...
       
   268 		*iOutputLine = iBufferedInput;
       
   269 		
       
   270  		iBufferedInput.FillZ();
       
   271 		iBufferedInput.SetLength(0);
       
   272 		}
       
   273 	iInputLine = aSourceLine;
       
   274 
       
   275 	// discard any LF character from the begining of the line (this is abit strange?)
       
   276 	while(iInputLine.Length() > 0 && (iInputLine[0] == KImcvLF || iInputLine[0] == KImcvCR))
       
   277 		iInputLine.Delete(0, 1);
       
   278 
       
   279 	// remove the CR at the end but only if there's stuff before it
       
   280 	while(iInputLine.Length() > 0 && (iInputLine[iInputLine.Length() - 1] == KImcvLF || iInputLine[iInputLine.Length() - 1] == KImcvCR))
       
   281 		iInputLine.Delete(iInputLine.Length() - 1, 1);
       
   282 
       
   283 	// if the newly read line is now empty, then don't read any more through this tokeniser
       
   284 	iLastToken = !iInputLine.Length();
       
   285 
       
   286 	// only bother with the rest of the parsing if there's any data left
       
   287 	if(iInputLine.Length() > 0 || iOutputLine->Length() > 0)
       
   288 		{
       
   289 		// check whether we're on the next field or still on the current one
       
   290 		if(!iFirstLine && iInputLine.Length() > 0 && iInputLine[0] != KImcvSP && iInputLine[0] != KImcvTab)
       
   291 			{
       
   292 			// we've read the first line of the next field
       
   293 			iBufferedInput = iInputLine;
       
   294 			endOfField = ETrue; // flag the fact that the current field is ready for parsing
       
   295 			}
       
   296 		else // the line belongs in the current field, but without any leading whitespace
       
   297 			{
       
   298 			// find the first non-whitespace character
       
   299 			const TUint8* ptr = iInputLine.Ptr();
       
   300 			while((*ptr == KImcvSP || *ptr == KImcvTab) && (ptr - iInputLine.Ptr() < iInputLine.Length())) ptr++;
       
   301 		
       
   302 			// make sure we're not about to exceed the buffer
       
   303 			if((iOutputLine->Length() + iInputLine.Length()) > iOutputLine->Des().MaxLength())
       
   304 				iOutputLine = iOutputLine->ReAlloc(iOutputLine->Length() + iInputLine.Length());
       
   305 
       
   306 			// now copy the remaining data into the buffer
       
   307 			iOutputLine->Des().Append(iInputLine.Right(iInputLine.Length() - (ptr - iInputLine.Ptr())));
       
   308 			}
       
   309 		}
       
   310 	else
       
   311 		hitEof = ETrue;		//this means that EEndOfHeader is set if a line of zero length is parsed - ie. (clean CRLF - CRLF) = 0.
       
   312 	iFirstLine = EFalse;
       
   313 
       
   314 	if(endOfField || iLastToken)
       
   315 		{ 
       
   316 		// only parse the input when we have a whole field, 
       
   317 		// or we just found the blank line that
       
   318 		// separates the body from the header
       
   319 		if(MatchAndRemoveL(KImcvFromPrompt))
       
   320 			iHeaderPart = EFrom;
       
   321 		else if(MatchAndRemoveL(KImcvReplyToPrompt))
       
   322 			iHeaderPart = EReplyTo;
       
   323 		else if(MatchAndRemoveL(KImcvToPrompt))
       
   324 			iHeaderPart = ETo;
       
   325 		else if(MatchAndRemoveL(KImcvCcPrompt))
       
   326 			iHeaderPart = ECc;
       
   327 		else if(MatchAndRemoveL(KImcvBccPrompt))
       
   328 			iHeaderPart = EBcc;
       
   329 		else if(MatchAndRemoveL(KImcvSubjectPrompt))
       
   330 			iHeaderPart = ESubject;
       
   331 		else if(MatchAndRemoveL(KImcvDatePrompt))
       
   332 			iHeaderPart = EDate;
       
   333 		else if(MatchAndRemoveL(KImcvMessageIdPrompt))
       
   334 			{
       
   335 			iHeaderPart = EMessageId;
       
   336 			RemoveSurroundingCharacters(KImcvLeftChevron, KImcvRightChevron, *iOutputLine);
       
   337 			}
       
   338 		else if (PriorityAndReceiptsMatchAndRemoveL(EPriority))
       
   339 			iHeaderPart=EPriority;
       
   340 		else if (PriorityAndReceiptsMatchAndRemoveL(EReturnReceiptTo))
       
   341 			iHeaderPart=EReturnReceiptTo;
       
   342 		else if(hitEof)
       
   343 			iHeaderPart = EEndOfHeader;
       
   344 		else
       
   345 			{
       
   346 			iHeaderPart = EUnknown;
       
   347 			iImRecvConvert->iMimeParser->ParseLineL(*iOutputLine);
       
   348 			}
       
   349 		}
       
   350 	else 
       
   351 		iHeaderPart = ENotFinished;
       
   352 	}
       
   353 
       
   354 
       
   355 /**
       
   356 PriorityAndReceiptsMatchAndRemoveL()
       
   357 
       
   358 @param aPriority
       
   359 */
       
   360 TBool CLocalRfc822Token::PriorityAndReceiptsMatchAndRemoveL(THeaderPart aPriority)
       
   361 	{
       
   362 	CDesC8Array* fields=new (ELeave)CDesC8ArrayFlat(6);
       
   363 	CleanupStack::PushL(fields);
       
   364 	if (aPriority==EPriority)
       
   365 		CImcvUtils::PriorityFieldsL(*fields);
       
   366 	else if (aPriority==EReturnReceiptTo)
       
   367 		CImcvUtils::ReceiptFieldsL(*fields);
       
   368 	else
       
   369 		{
       
   370 		CleanupStack::PopAndDestroy(); //fields
       
   371 		return EFalse;
       
   372 		}
       
   373 	TInt count=fields->Count();
       
   374 	TBool matched=EFalse;
       
   375 	for (TInt i=0;i<count;i++)
       
   376 		{
       
   377 		if (MatchAndRemoveL((*fields)[i]))
       
   378 			{
       
   379 			matched=ETrue;
       
   380 			break;
       
   381 			}
       
   382 		}
       
   383 	CleanupStack::PopAndDestroy(); //fields
       
   384 	return matched;
       
   385 	}
       
   386 
       
   387 
       
   388 /**
       
   389 MatchAndRemoveL()
       
   390 
       
   391 @param aString
       
   392 @return
       
   393 TBool
       
   394 */
       
   395 TBool CLocalRfc822Token::MatchAndRemoveL(const TDesC8& aString)
       
   396 	{
       
   397 	TInt comparison;
       
   398 	TInt stringLength = aString.Length();
       
   399 	TInt desLength = (*iOutputLine).Length();
       
   400 	TInt compareLength = stringLength > desLength ? desLength : stringLength;
       
   401 	TPtrC8 left((*iOutputLine).Left(compareLength));
       
   402 	
       
   403 	// now see whether the current line contains the search string
       
   404 	comparison = left.CompareF(aString);
       
   405 	if(!comparison)
       
   406 		{
       
   407 		// found the match string at the start of the output line, so remove it
       
   408 		// get rid of any whitespace betweebn the tag and the data while we have a chance
       
   409 		if (!i822FieldsExist)
       
   410 			i822FieldsExist=ETrue;
       
   411 		TInt whitespaceLength=0;
       
   412 		TInt maxLength=desLength-stringLength;
       
   413 		const TUint8* ptr = (*iOutputLine).Ptr();
       
   414 		while(whitespaceLength <= maxLength && (ptr[stringLength+whitespaceLength] == KImcvSP || ptr[stringLength+whitespaceLength] == KImcvTab))
       
   415 			whitespaceLength++;
       
   416 		(iOutputLine->Des()).Delete(0, stringLength+whitespaceLength);
       
   417 		}
       
   418 	return (comparison==0);
       
   419 	}
       
   420 
       
   421 //****************************************************************************************
       
   422 //             Class CLocalImRecvConvert
       
   423 //****************************************************************************************
       
   424 
       
   425 
       
   426 /**
       
   427 NewLC()
       
   428 Static factory constructor. Uses two phase construction 
       
   429 and pushes the newly created object into the Cleanup stack.
       
   430 
       
   431 @param anFs
       
   432 @param aServerEntry
       
   433 @param aMsgType
       
   434 @param aEmailServiceId
       
   435 @leave KErrNoMemory
       
   436 @return
       
   437 A pointer to the newly created CLocalImRecvConvert object.
       
   438 */
       
   439 CLocalImRecvConvert* CLocalImRecvConvert::NewLC(RFs& anFs, CMsvServerEntry* aServerEntry, 
       
   440 												TUid aMsgType, TMsvId aEmailServiceId)
       
   441 	{
       
   442 	CLocalImRecvConvert* self = new (ELeave) CLocalImRecvConvert(anFs, aServerEntry, aMsgType, 
       
   443 																		aEmailServiceId);
       
   444 	CleanupStack::PushL(self);
       
   445 	self->ConstructL(anFs);
       
   446 	return self;
       
   447 	}
       
   448 
       
   449 
       
   450 /**
       
   451 NewL()
       
   452 Static factory constructor. Uses two phase 
       
   453 construction.
       
   454 
       
   455 @param anFs
       
   456 @param aServerEntry
       
   457 @param aMsgType
       
   458 @param aEmailServiceId
       
   459 @leave KErrNoMemory
       
   460 @return
       
   461 A pointer to the newly created CLocalImRecvConvert object.
       
   462 */
       
   463 CLocalImRecvConvert* CLocalImRecvConvert::NewL(RFs& anFs, CMsvServerEntry* aServerEntry, 
       
   464 												TUid aMsgType, TMsvId aEmailServiceId)
       
   465 	{
       
   466 	CLocalImRecvConvert* self = CLocalImRecvConvert::NewLC(anFs, aServerEntry, aMsgType, 
       
   467 																aEmailServiceId);
       
   468 	CleanupStack::Pop();
       
   469 	return self;
       
   470 	}
       
   471 
       
   472   
       
   473 /**
       
   474 ConstructL()
       
   475 
       
   476 @param anFs
       
   477 */
       
   478 void CLocalImRecvConvert::ConstructL(RFs& anFs)
       
   479 	{
       
   480 	iFsSession = &anFs;  
       
   481 
       
   482 	RResourceFile resFile;
       
   483 	OpenResourceFileL(resFile, anFs);	// NB leaves if file not found
       
   484 
       
   485 	// make sure the resource file will be closed if anything goes wrong
       
   486 	// CloseResourceFile is declared in IMUTDLL.H and defined in IMUTDLL.CPP
       
   487 	TCleanupItem close( CloseResourceFile, &resFile );
       
   488 	CleanupStack::PushL( close );
       
   489 	
       
   490 	// Read iStore8BitData flag.
       
   491 	HBufC8* buf = resFile.AllocReadLC( STORE_8BIT_BODY_TEXT );
       
   492 	TResourceReader reader;
       
   493 	reader.SetBuffer(buf);
       
   494 	iStore8BitData = reader.ReadInt8();
       
   495 	CleanupStack::PopAndDestroy(buf);
       
   496 
       
   497 	buf = resFile.AllocReadLC( REMOVED_ATTACHMENT_TAG );
       
   498 	reader.SetBuffer(buf);
       
   499 	iRemovedAttachmentTag = reader.ReadTPtrC().AllocL();
       
   500 	CleanupStack::PopAndDestroy(buf);
       
   501 	
       
   502 	buf = resFile.AllocReadLC( DEFAULT_ATTACHMENT_NAME );
       
   503 	reader.SetBuffer(buf);
       
   504 	iDefaultAttachmentName = reader.ReadTPtrC().AllocL();
       
   505 	CleanupStack::PopAndDestroy(buf);
       
   506 	buf = resFile.AllocReadLC(PARTIAL_DOWNLOAD_FOOTER_MESSAGE);
       
   507 	reader.SetBuffer(buf);
       
   508 	iPartialEmailFooter = (reader.ReadTPtrC()).AllocL();
       
   509 	CleanupStack::PopAndDestroy(buf);
       
   510 	buf = NULL;
       
   511 	CleanupStack::PopAndDestroy(&resFile); // resFile (Close resfile)
       
   512 
       
   513 	// create CImHeader object to store Rfc822 header info...
       
   514 	iOutputHeader = CImHeader::NewLC();	// PushL(iHeader)
       
   515 	CleanupStack::Pop();				// iHeader
       
   516 
       
   517 	if (iStore8BitData)
       
   518 		{
       
   519 		//Create body text storage helper.
       
   520 		iBodyText = CMsvBodyText::NewL();
       
   521 		}
       
   522 	else
       
   523 		{
       
   524 		// create CRichText object to store body...
       
   525 		iParaLayer = CParaFormatLayer::NewL();
       
   526 		iCharLayer = CCharFormatLayer::NewL();
       
   527 		iOutputBody = CRichText::NewL(iParaLayer, iCharLayer);
       
   528 		}
       
   529 	
       
   530 	// Create Rfc822 filter object...
       
   531 	iRfc822Token = CLocalRfc822Token::NewLC(); // PushL(iRfc822Token)
       
   532 	CleanupStack::Pop();				  // iRfc822Token
       
   533 	iRfc822Token->SetImRecvConvert(this);
       
   534 
       
   535 	// Create converter objects...
       
   536 	iCharacterConverter = CCnvCharacterSetConverter::NewL();
       
   537 	iCharConv = CImConvertCharconv::NewL(*iCharacterConverter, anFs);
       
   538 	iHeaderConverter = CImConvertHeader::NewL(*iCharConv); 
       
   539 
       
   540 	
       
   541 	// Create MIME filter object...
       
   542 	iMimeParser = CLocalMimeParser::NewL(*this);
       
   543 	
       
   544 	
       
   545 	// logfile stuff
       
   546 	iImcvLog=NULL;
       
   547 
       
   548 #ifdef __IMUT_LOGGING	
       
   549 	TRAPD(err,iImcvLog=CImLog::NewL(KLogFilePath, EAppend));
       
   550 	UNUSED_VAR( err );
       
   551 #endif
       
   552 
       
   553 	iRootEntryId = EntryId();
       
   554 
       
   555 	iNotFinishedRfc822Header = ETrue;
       
   556 	
       
   557 	iEmailEntry = new (ELeave) TMsvEmailEntry;
       
   558 	iReceivingHeadersOnly=EFalse;	
       
   559 
       
   560 	iParent = new (ELeave) CArrayFixFlat<TParentDetails>(3);
       
   561 
       
   562 	iFirstBoundaryReached=EFalse;
       
   563 
       
   564 	ResetL();
       
   565 	
       
   566 	RECVLOG( KNewLogHeader )
       
   567 	}
       
   568 
       
   569 
       
   570 /**
       
   571 CLocalImRecvConvert()
       
   572 
       
   573 @param anFs
       
   574 @param aServerEntry
       
   575 @param aMsgType
       
   576 @param aEmailServiceId
       
   577 */
       
   578 CLocalImRecvConvert::CLocalImRecvConvert(RFs& anFs, CMsvServerEntry* aServerEntry, 
       
   579 							   TUid aMsgType, TMsvId aEmailServiceId)
       
   580 				: iServerEntry(aServerEntry), iNewMsgType(aMsgType), iDefaultEntryType(ETextEntry), 
       
   581 			  	  iEmailServiceId(aEmailServiceId), iAttachmentFile(anFs)
       
   582 	{
       
   583 	__DECLARE_NAME(_S("CLocalImRecvConvert"));
       
   584 	}
       
   585 
       
   586   
       
   587 /**
       
   588 ~CLocalImRecvConvert()
       
   589 Destructor
       
   590 */
       
   591 CLocalImRecvConvert::~CLocalImRecvConvert()
       
   592 	{
       
   593 	delete iEmailEntry;
       
   594 	iEmailEntry=NULL;
       
   595 	delete iOutputHeader;
       
   596 	iOutputHeader=NULL;
       
   597 	delete iBodyText;
       
   598 	iBodyText=NULL;
       
   599 	delete iBodyBuf;
       
   600 	iBodyBuf=NULL;
       
   601 	delete iParaLayer;
       
   602 	iParaLayer=NULL;
       
   603 	delete iCharLayer;
       
   604 	iCharLayer=NULL;
       
   605 	delete iOutputBody;
       
   606 	iOutputBody=NULL;
       
   607 	delete iRemovedAttachmentTag;
       
   608 	iRemovedAttachmentTag=NULL;
       
   609 	delete iDefaultAttachmentName;
       
   610 	iDefaultAttachmentName=NULL;
       
   611 	delete iRfc822Token;
       
   612 	iRfc822Token=NULL;
       
   613 	delete iMimeParser;
       
   614 	iMimeParser=NULL;
       
   615 	delete iHeaderConverter;
       
   616 	iHeaderConverter=NULL;
       
   617 	delete iCharConv;
       
   618 	iCharConv=NULL;
       
   619 	delete iCharacterConverter;
       
   620 	iCharacterConverter=NULL;
       
   621 	delete iAttachmentFullPath;
       
   622 	iAttachmentFullPath=NULL;
       
   623 	delete iImcvUtils;
       
   624 	iImcvUtils=NULL;
       
   625 	delete iParent;
       
   626 	iParent=NULL;
       
   627 	RECVLOG(KDeleted)
       
   628 	delete iImcvLog;
       
   629 	iImcvLog=NULL;
       
   630 	delete iPartialEmailFooter;
       
   631 	iPartialEmailFooter=NULL;
       
   632 	}
       
   633 
       
   634 
       
   635 /**
       
   636 ResetForHeadersL()
       
   637 This function is used in preference to ResetL() when the owner
       
   638 only wishes to create  email entries in the remote mailbox - 
       
   639 they do not wish to create any stores associated with the message
       
   640 entry
       
   641 
       
   642 */
       
   643 void CLocalImRecvConvert::ResetForHeadersL()
       
   644 	{
       
   645 	ResetL();
       
   646 	iReceivingHeadersOnly=ETrue;
       
   647 	}
       
   648 
       
   649 /**
       
   650 ResetL()
       
   651 
       
   652 */
       
   653 void CLocalImRecvConvert::ResetL()
       
   654 	{
       
   655 	RECVLOG(KReset) 
       
   656 	iBodyId=KMsvNullIndexEntryId;
       
   657 	iSizeOfAttachmentsRemoved=0;
       
   658 
       
   659 	User::LeaveIfError(iServerEntry->SetEntry(iRootEntryId));
       
   660 	
       
   661 	iReceivingHeadersOnly=EFalse;
       
   662 	iMessageEntryCalled=EFalse;
       
   663 	iLeaveError=KErrNone; 		
       
   664 	iCurrentMultipartFolderEntryId=0;
       
   665 
       
   666 	TParentDetails parent;
       
   667 	parent.iAttachment=parent.iMHTML=EFalse;
       
   668 	parent.iSize=0;
       
   669 	iParent->InsertL(0,parent);
       
   670 
       
   671 	delete iEmailEntry;
       
   672 	iEmailEntry=NULL;
       
   673 	iEmailEntry = new (ELeave) TMsvEmailEntry;
       
   674 
       
   675 	// "iSavingAttachments" commands this code to store attachments in files.
       
   676 	// Currently this is always set to ETrue as we intend to save all attachments
       
   677 	// However, if the user wishes to discard (ie do not save) any 
       
   678 	// attachments in incoming email messages - then this member variable
       
   679 	// may be set to EFalse by the inline accessor function "SaveAllAttachments(TBool)"
       
   680 	iSavingAttachments=ETrue;
       
   681 	iAttachmentFileState=EFileIsClosed;
       
   682 
       
   683 	// iLeaveError contains the error value of any functions that leaves (ie CRichText::InsertL)
       
   684 	// or any returned error value that generates a leave from within CLocalImRecvConvert (ie RFile::Create)
       
   685 
       
   686 	iGlobalIndent=0;
       
   687 	iLongestLine=50;
       
   688 	
       
   689 	iImPriority=EMsvMediumPriority;
       
   690 	delete iImcvUtils;
       
   691 	iImcvUtils=NULL;
       
   692 	iImcvUtils=CImcvUtils::NewL();
       
   693 
       
   694 	// reset internal date
       
   695 	iTimeDate.HomeTime();
       
   696 	
       
   697 	iMimeParser->Reset();
       
   698 	
       
   699 	iNewEntry=EFalse; //EFalse if the entry was moved to. ETrue if the entry was just created
       
   700 	iTopMessagePart=KMsvNullIndexEntryId; //A value of NULL indicates the next entry created is a main message entry
       
   701 	ResetForNewEntryL(iDefaultEntryType);
       
   702 	iMIMEPart_822Header = EFalse;
       
   703 	iPartialEmail=EFalse;
       
   704 
       
   705 	RECVLOG(KReseted) 
       
   706 	}
       
   707 
       
   708 
       
   709 /**
       
   710 ResetForNewEntryL()
       
   711 
       
   712 @param entryType
       
   713 */
       
   714 void CLocalImRecvConvert::ResetForNewEntryL(TValidEntryType entryType)
       
   715 	{
       
   716 	RECVLOG(KResetForNewEntry) 
       
   717 
       
   718 	iFinishedHeader = EFalse;
       
   719 
       
   720 	iPreviousLineLength = 0;
       
   721 	iPreviousTrailingWhitespace = 0;
       
   722 	iLastChar = 0;
       
   723 
       
   724 	// Reset the new entry state
       
   725 	ResetForNonMimeEntryL();
       
   726 
       
   727 	// Clear the storage classes
       
   728 	iMimeParser->ResetForNewEntry();
       
   729 	iRfc822Token->Reset();
       
   730 
       
   731 	iEmailPart = KNoPart;
       
   732 	iEntryType=entryType;
       
   733 
       
   734 	if (iEntryType==EMessageEntry)
       
   735 		{
       
   736 		iEmailPart = KParentPart;
       
   737 		iMimeParser->SetMessageFolderType(EFolderTypeRFC822);
       
   738 		}
       
   739 	}
       
   740 
       
   741 
       
   742 /**
       
   743 ResetForNonMimeEntryL()
       
   744 
       
   745 */
       
   746 void CLocalImRecvConvert::ResetForNonMimeEntryL()
       
   747 	{
       
   748 	iEntryType = ETextEntry;
       
   749 	RECVLOG(KResetForNonMimeEntry) 
       
   750 
       
   751 	iSkipData = EFalse;
       
   752 	iPrepared = EFalse;
       
   753 	iNewNonMIMEBodyPart=ETrue;
       
   754 	iEncounteredLineEndingInCarriageReturn=EFalse;
       
   755 
       
   756 	iAlgorithm = ENoAlgorithm;
       
   757 	iCurrentPartIsRichText = ETrue;	
       
   758 	CloseAttachmentFileL();
       
   759 	iEntryDataSize = 0;
       
   760 	
       
   761 	if (iStore8BitData)
       
   762 		{
       
   763 		//Create a buffer to hold the body text as it is down loaded.
       
   764 		delete iBodyBuf;
       
   765 		iBodyBuf = NULL;
       
   766 		iBodyBuf = CBufSeg::NewL(KBodyTextChunkSizeBytes);
       
   767 		}
       
   768 	else
       
   769 		{
       
   770 		iOutputBody->Reset();
       
   771 		}
       
   772 	
       
   773 	iAttachmentName.Zero();
       
   774 	iFinalLine = EFalse;
       
   775 
       
   776 	iOutputHeader->Reset();
       
   777 	iEmptyHeaderSize=iOutputHeader->DataSize();
       
   778 	RECVLOG(KResetedForNonMimeEntry) 
       
   779 	}
       
   780 
       
   781 
       
   782 /**
       
   783 ParseNextField()
       
   784 
       
   785 @param aSourceLine
       
   786 */
       
   787 TInt CLocalImRecvConvert::ParseNextField(const TDesC8& aSourceLine) 
       
   788 	{
       
   789 	__ASSERT_DEBUG(iRootEntryId!=KMsvNullIndexEntryId, gPanic(KPanicServiceIdNotValid));
       
   790 	RECVLOG_OUT(aSourceLine);
       
   791 
       
   792 	// If we are temporarily on the null entry then move back to the entry we are working on
       
   793 	if ((iLeaveError == KErrNone) && (iServerEntry->Entry().Id() == KMsvNullIndexEntryId))
       
   794 		iLeaveError = iServerEntry->SetEntry(iSavedEntryId);
       
   795 
       
   796 	if(iLeaveError==KErrNone)
       
   797 		TRAP(iLeaveError, ParseNextLineL(aSourceLine));		
       
   798 
       
   799 	// Save the current entry id for later.
       
   800 	if (iLeaveError==KErrNone)
       
   801 		iSavedEntryId = iServerEntry->Entry().Id();
       
   802 
       
   803 	TUid type = iServerEntry->Entry().iType;
       
   804 	if( type != KUidMsvMessageEntry    &&
       
   805 		type != KUidMsvEmailTextEntry  &&
       
   806 		type != KUidMsvEmailHtmlEntry  &&
       
   807 		type != KUidMsvAttachmentEntry)
       
   808 		{
       
   809 	// Set the current id to null so that we aren't locking any folders
       
   810 	iServerEntry->SetEntry(KMsvNullIndexEntryId);
       
   811 		}
       
   812 
       
   813 	return iLeaveError;
       
   814 	}
       
   815 
       
   816 
       
   817 /**
       
   818 ParseNextLineL()
       
   819 
       
   820 @param aSourceLine
       
   821 */
       
   822 void CLocalImRecvConvert::ParseNextLineL(const TDesC8& aSourceLine)
       
   823 	{
       
   824 	iParsedMimeBoundaryLast=0;
       
   825 	if(!iFinishedHeader)
       
   826 		{
       
   827 		// start by getting the next token from the header
       
   828 		iRfc822Token->ParseNextLineL(aSourceLine);
       
   829 
       
   830 		switch(iRfc822Token->iHeaderPart)
       
   831 			{
       
   832 			case CLocalRfc822Token::EUnknown:
       
   833 			case CLocalRfc822Token::ENotFinished:
       
   834 				RECVLOG(KPartLine)
       
   835 				break;
       
   836 			case CLocalRfc822Token::EFrom:
       
   837 				iOutputHeader->SetFromL(*iRfc822Token->OutputLine());
       
   838 				LOGGING(KFound,KImcvFromPrompt);
       
   839 				break;
       
   840 			case CLocalRfc822Token::EReplyTo:
       
   841 				iOutputHeader->SetReplyToL(*iRfc822Token->OutputLine());
       
   842 				LOGGING(KFound,KImcvReplyToPrompt);
       
   843 				break;
       
   844 			case CLocalRfc822Token::ETo:
       
   845 				ParseRecipientListL(iOutputHeader->ToRecipients());
       
   846 				LOGGING(KFound,KImcvToPrompt);
       
   847 				break;
       
   848 			case CLocalRfc822Token::ECc: 
       
   849 				ParseRecipientListL(iOutputHeader->CcRecipients());
       
   850 				LOGGING(KFound,KImcvCcPrompt);
       
   851 				break;
       
   852 			case CLocalRfc822Token::EBcc: 
       
   853 				ParseRecipientListL(iOutputHeader->BccRecipients());
       
   854 				LOGGING(KFound,KImcvBccPrompt);
       
   855 				break;
       
   856 			case CLocalRfc822Token::ESubject:
       
   857 				iOutputHeader->SetSubjectL(*iRfc822Token->OutputLine());
       
   858 				LOGGING(KFound,KImcvSubjectPrompt);
       
   859 				break;
       
   860 			case CLocalRfc822Token::EDate:
       
   861 				iRfc822Date.ParseDateField(*iRfc822Token->OutputLine() , iTimeDate); 
       
   862 				if (iEmailEntry->Id() != iTopMessagePart)
       
   863 					{
       
   864 					iEmailEntry->iDate = iTimeDate;
       
   865 					}
       
   866 				LOGGING(KFound,KImcvDatePrompt);
       
   867 				break;
       
   868 			case CLocalRfc822Token::EMessageId:
       
   869 				iOutputHeader->SetImMsgIdL(*iRfc822Token->OutputLine());
       
   870 				LOGGING(KFound,KImcvMessageIdPrompt);
       
   871 				break;
       
   872 			case CLocalRfc822Token::EPriority:
       
   873 				iImPriority=iImcvUtils->EvaluatePriorityText(*iRfc822Token->OutputLine());
       
   874 				LOGGING(KFound,KImcvPriorityPrompt);
       
   875 				break;
       
   876 			case CLocalRfc822Token::EReturnReceiptTo:
       
   877 				iOutputHeader->SetReceiptAddressL(*iRfc822Token->OutputLine());
       
   878 				LOGGING(KFound,KReturnReceiptTo);
       
   879 				break;
       
   880 			case CLocalRfc822Token::EEndOfHeader:
       
   881 				// the next line goes in the body part
       
   882 				iFinishedHeader = ETrue;
       
   883 				RECVLOG(KEndOFHeader)
       
   884 				break;
       
   885 			default:
       
   886 				RECVLOG(KEndOFHeader)
       
   887 				break;
       
   888 			}
       
   889 
       
   890 
       
   891 		if(iRfc822Token->iHeaderPart != CLocalRfc822Token::ENotFinished)
       
   892 			{
       
   893 			// Now that we've used the data, we also need to clear the output line from the tokeniser....
       
   894 			iRfc822Token->OutputLine()->Des() = KNullDesC8;
       
   895 
       
   896 			// whatever part we just read, we may also have read the empty line that separates
       
   897 			// the header from the body
       
   898 			if((iFinishedHeader = iRfc822Token->LastToken()) != EFalse)	//iFinishedHeader set to 1 on CRLF-
       
   899 				{
       
   900 				RECVLOG(KLastToken);
       
   901 				iNotFinishedRfc822Header = EFalse;
       
   902 
       
   903 				iHeaderConverter->SetMessageType(iMimeParser->MessageIsMime());
       
   904 				iHeaderConverter->DecodeAllHeaderFieldsL(*iOutputHeader);
       
   905 
       
   906 				if (iMimeParser->MessageIsMime())
       
   907 					EndOfHeaderMIMEProcessingL();
       
   908 				else
       
   909 					EndOfHeaderProcessingL();
       
   910 
       
   911 				if (iStore8BitData)
       
   912 					{
       
   913 					iBodyText->SetDefaultCharacterSet(iCharConv->SystemDefaultCharset());
       
   914 					if ( iMimeParser->MessageIsMime() && iMimeParser->ContentType()==EMimeText )
       
   915 						iBodyText->SetCharacterSet(iMimeParser->CurrentCharsetL());
       
   916 					else
       
   917 						iBodyText->SetCharacterSet(0);
       
   918 					}
       
   919 				else
       
   920 					{
       
   921 					// Get charset for decoding.
       
   922 					if ( iMimeParser->MessageIsMime() && iMimeParser->ContentType()==EMimeText )
       
   923 						iCharConv->PrepareToConvertToFromOurCharsetL(iMimeParser->CurrentCharsetL());
       
   924 					else
       
   925 						iCharConv->PrepareToConvertToFromOurCharsetL(iCharConv->SystemDefaultCharset());
       
   926 					}
       
   927 				}
       
   928 			}
       
   929 		}
       
   930 	else if (iReceivingHeadersOnly == EFalse)
       
   931 		{	
       
   932 		//Set to EFalse when a single line is to be skipped (ie boundary line)
       
   933 		iCommitLine=ETrue; 
       
   934 
       
   935 		// read one line of the message body if I am processing a whole email message
       
   936 		if(iMimeParser->MessageIsMime())
       
   937 			ParseMimeLineL(aSourceLine);
       
   938 		else
       
   939 			ParseBodyLineL(aSourceLine);	
       
   940 
       
   941 		if((iCommitLine) && (!iSkipData))
       
   942 			DecodeAndStoreLineL(aSourceLine);
       
   943 		}
       
   944 	}
       
   945 
       
   946 
       
   947 /**
       
   948 MessageEntryDetailsL()
       
   949 
       
   950 @return
       
   951 */
       
   952 TMsvEmailEntry CLocalImRecvConvert::MessageEntryDetailsL()
       
   953 	{
       
   954 	iMessageEntryCalled=ETrue;
       
   955 	CloseAttachmentFileL();
       
   956 
       
   957 	// A message requiring manual termination and not part way through a MIME part header
       
   958 	if( iTopMessagePart==EntryId() && iFinishedHeader) 
       
   959 		StoreEntryStreamsL(KStore822Header|KStoreMIMEHeader);
       
   960 	else
       
   961 		{
       
   962 		User::LeaveIfError(iServerEntry->SetEntry(iTopMessagePart));         
       
   963 		delete iEmailEntry;
       
   964 		iEmailEntry=NULL;
       
   965 		iEmailEntry = new (ELeave) TMsvEmailEntry(iServerEntry->Entry());
       
   966 		}
       
   967 		
       
   968 	return *iEmailEntry;
       
   969 	}
       
   970 
       
   971 
       
   972 /**
       
   973 MessageCompleteL()
       
   974 
       
   975 @param aEmailEntry
       
   976 */
       
   977 void CLocalImRecvConvert::MessageCompleteL(TMsvEmailEntry aEmailEntry)
       
   978 	{
       
   979 	// Restore the entry context
       
   980 	if (iServerEntry->Entry().Id() == KMsvNullIndexEntryId)
       
   981 		User::LeaveIfError(iServerEntry->SetEntry(iSavedEntryId));
       
   982 
       
   983 	__ASSERT_DEBUG(iMessageEntryCalled, gPanic(KPanicMessageEntryNotCalled));
       
   984 	__ASSERT_DEBUG(aEmailEntry.Id()==iTopMessagePart, gPanic(KPanicMessageEntryIdHasChanged)); // Id should be set to iTopMessagePart
       
   985 
       
   986 	// Called ResetL() to reset object instead of ResetForHeadersL()
       
   987 	__ASSERT_DEBUG(iReceivingHeadersOnly, gPanic(KPanicIncorrectResetState)); 
       
   988 
       
   989 	if(iEmailEntry)
       
   990 		{
       
   991 		if (iEmailEntry->Id())
       
   992 			{
       
   993 			if(iLeaveError==KErrNone)
       
   994 				{
       
   995 				// a remote email header cannot have any attachments or be marked as complete...
       
   996 				aEmailEntry.SetAttachment(EFalse);
       
   997 				aEmailEntry.SetMHTMLEmail(EFalse);
       
   998 				aEmailEntry.SetComplete(EFalse);
       
   999 				User::LeaveIfError(iServerEntry->ChangeEntry(aEmailEntry));
       
  1000 				RECVLOG(KHeaderComplete)
       
  1001 				}
       
  1002 			else
       
  1003 				{
       
  1004 				if (!iPopulateMessage)
       
  1005 					{
       
  1006 					TMsvId currentId = EntryId();
       
  1007 					User::LeaveIfError(iServerEntry->SetEntry(iServerEntry->Entry().Parent()));			
       
  1008 					User::LeaveIfError(iServerEntry->DeleteEntry(currentId));
       
  1009 					}
       
  1010 				User::Leave(iLeaveError);
       
  1011 				}
       
  1012 			}
       
  1013 		}
       
  1014 
       
  1015 	// Save the entry context and move it to null so that we're not locking any folders
       
  1016 	iSavedEntryId = iServerEntry->Entry().Id();
       
  1017 	User::LeaveIfError(iServerEntry->SetEntry(KMsvNullIndexEntryId));
       
  1018 	}
       
  1019 
       
  1020 
       
  1021 /**
       
  1022 MessageCompleteL()
       
  1023 
       
  1024 @param aPartialDownload
       
  1025 */
       
  1026 void CLocalImRecvConvert::MessageCompleteL(TBool aPartialDownload)
       
  1027 	{
       
  1028 	iPartialEmail=aPartialDownload;
       
  1029 	MessageCompleteL();
       
  1030 	}
       
  1031   
       
  1032 
       
  1033 /**
       
  1034 MessageCompleteL()
       
  1035 */
       
  1036 void CLocalImRecvConvert::MessageCompleteL()
       
  1037 	{
       
  1038 	// Restore the entry context
       
  1039 	RECVLOG(KStartMessageComplete)
       
  1040 	if (iServerEntry->Entry().Id() == KMsvNullIndexEntryId)
       
  1041 		User::LeaveIfError(iServerEntry->SetEntry(iSavedEntryId));
       
  1042 
       
  1043 	if (iParsedMimeBoundaryLast==EFalse && iAttachmentFileState==EFileIsOpen && iPartialEmail!=EFalse)
       
  1044 		{
       
  1045 		iAttachmentFileState=EFileTopIncomplete;
       
  1046 		}
       
  1047 
       
  1048 	CloseAttachmentFileL();
       
  1049 
       
  1050 	if(!iEmailEntry->Id())
       
  1051 		return;
       
  1052 
       
  1053 	if(iLeaveError!=KErrNone)
       
  1054 		{
       
  1055 		User::Leave(iLeaveError);
       
  1056 		}
       
  1057 
       
  1058 	if (EntryId()!=iTopMessagePart)
       
  1059 		{
       
  1060 		iEmailEntry->SetComplete(ETrue);
       
  1061 		StoreEntryStreamsL(KStoreBodyText);
       
  1062 		MoveToParentEntryL();
       
  1063 
       
  1064 		if( iTopMessagePart==EntryId() && iFinishedHeader) 
       
  1065 			{
       
  1066 			iEmailEntry->SetVisible(ETrue);
       
  1067 			iEmailEntry->SetInPreparation(EFalse);
       
  1068 			iEmailEntry->SetBodyTextComplete(ETrue);
       
  1069 			iEmailEntry->SetComplete(ETrue);
       
  1070 
       
  1071 			// Main message.
       
  1072 			StoreMessageEntryDetailsL();
       
  1073 			return;
       
  1074 			}
       
  1075 		else if(iEmailEntry->iType == KUidMsvMessageEntry)
       
  1076 			{
       
  1077 			StoreMessageEntryDetailsL();
       
  1078 			MoveToParentEntryL();
       
  1079 			StoreMessageEntryDetailsL();
       
  1080 			}
       
  1081 		}
       
  1082 
       
  1083 	// A message requiring manual termination and not part way through 
       
  1084 	// a MIME part header.
       
  1085 
       
  1086 	User::LeaveIfError(iServerEntry->SetEntry(iTopMessagePart));         
       
  1087 	if(NULL!=iEmailEntry)
       
  1088 		{
       
  1089 		delete iEmailEntry;
       
  1090 		iEmailEntry=NULL;
       
  1091 		}
       
  1092 	iEmailEntry = new (ELeave) TMsvEmailEntry(iServerEntry->Entry());
       
  1093 	iEmailEntry->SetVisible(ETrue);
       
  1094 	iEmailEntry->SetInPreparation(EFalse);
       
  1095 	iEmailEntry->SetComplete(ETrue);
       
  1096 	iEmailEntry->SetBodyTextComplete(ETrue);
       
  1097 
       
  1098 	iEmailEntry->SetAttachment(iParent->At(0).iAttachment);
       
  1099 	iEmailEntry->SetMHTMLEmail(iParent->At(0).iMHTML);
       
  1100 
       
  1101 	if(iEmailEntry->MHTMLEmail() == EFalse && iEmailEntry->Attachment() == EFalse && iRelatedAttachments !=EFalse)
       
  1102 		{
       
  1103 		iEmailEntry->SetAttachment(ETrue);
       
  1104 		}
       
  1105 	iRelatedAttachments=EFalse;
       
  1106 	
       
  1107 	iEmailEntry->iSize=iParent->At(0).iSize;
       
  1108 	iEmailEntry->SetMessageFolderType(iParent->At(0).iFolder);
       
  1109 
       
  1110 	User::LeaveIfError(iServerEntry->ChangeEntry(*iEmailEntry));
       
  1111 
       
  1112 	// Save the entry context and move it to null so that we're not locking any folders
       
  1113 	iSavedEntryId = iServerEntry->Entry().Id();
       
  1114 	User::LeaveIfError(iServerEntry->SetEntry(KMsvNullIndexEntryId));
       
  1115 	RECVLOG(KMessageComplete)
       
  1116 	}
       
  1117 
       
  1118 
       
  1119 /**
       
  1120 PrepareDecoder()
       
  1121 
       
  1122 */
       
  1123 void CLocalImRecvConvert::PrepareDecoder()
       
  1124 	{
       
  1125 	switch(iMimeParser->ContentEncoding())
       
  1126 		{
       
  1127 		case EEncodingTypeNone:
       
  1128 		case EEncodingType7Bit:
       
  1129 		case EEncodingType8Bit:
       
  1130 			iAlgorithm = ENoAlgorithm;
       
  1131 			RECVLOG(KCollectingData7)
       
  1132 			break;
       
  1133 		case EEncodingTypeQP:
       
  1134 			iAlgorithm = EQPDecode;
       
  1135 			RECVLOG(KCollectingDataQP)
       
  1136 			break;
       
  1137 		case EEncodingTypeBASE64:
       
  1138 			iAlgorithm = EBase64Decode;
       
  1139 			RECVLOG(KCollectingBase64)
       
  1140 			break;	
       
  1141 		case EEncodingTypeUU:
       
  1142 			iAlgorithm = EUUDecode;
       
  1143 			RECVLOG(KCollectingUU)
       
  1144 			break;	
       
  1145 		default:	// EEncodingTypeUnknown, EEncodingTypeNone, EEncodingTypeBinary	
       
  1146 			iAlgorithm = ENoAlgorithm;
       
  1147 			break;
       
  1148 		} // switch
       
  1149 	iPrepared = ETrue;
       
  1150 	}
       
  1151 
       
  1152   
       
  1153 /**
       
  1154 DecodeAndStoreLineL()
       
  1155 
       
  1156 @param aSourceLine
       
  1157 */
       
  1158 void CLocalImRecvConvert::DecodeAndStoreLineL(const TDesC8& aSourceLine)
       
  1159 	{
       
  1160 	TInt sourceLineLength=aSourceLine.Length();
       
  1161 	TBool blankLine = EFalse;
       
  1162 
       
  1163 	// create a temporary buffer to write the decoded data into. 
       
  1164 	// This will always be as long as or shorter than the original.
       
  1165 	
       
  1166 	HBufC8* convertedLine = HBufC8::NewLC(sourceLineLength+KConversionRemainderLength);
       
  1167 	TPtr8 des(convertedLine->Des());
       
  1168 
       
  1169 	if(iFinalLine)						
       
  1170 		{
       
  1171 		// We've got to the end of encoded section, so set in order to skip all
       
  1172 		// trailing empty lines & postamble until we reach the next MIME/UUE boundary
       
  1173 
       
  1174 		RECVLOG(KSkippingData)
       
  1175 		iSkipData = ETrue;
       
  1176 		}
       
  1177 	else
       
  1178 		{
       
  1179 		switch(iAlgorithm)
       
  1180 			{
       
  1181 			case EBase64Decode:
       
  1182 				RECVLOG(KDecodingBase64);
       
  1183 
       
  1184 				iB64Codec.Decode(aSourceLine, des); 
       
  1185 				RECVLOG(KDecodedBase64);
       
  1186 				break;
       
  1187 			case EUUDecode:
       
  1188 				RECVLOG(KDecodingUU);
       
  1189 				//used to end a Mime encoded UU section else no purpose
       
  1190 				iFinalLine=(aSourceLine.CompareF(KImcvUueLastLine)==0);	
       
  1191 				if(iFinalLine)
       
  1192 					iCommitLine=EFalse;
       
  1193 				else
       
  1194 					{
       
  1195 					//returns True on invalid data
       
  1196 					if((!iFinalLine)&&(iUUCodec.Decode(aSourceLine, des))) 
       
  1197 						{
       
  1198 						RECVLOG(KUUEDataCorrupt)
       
  1199 						if(iAttachmentFileState==EFileIsOpen)
       
  1200 							{
       
  1201 							iAttachmentFileState=EFileIsCorrupt;
       
  1202 							iLeaveError=KErrCorrupt;
       
  1203 							CloseAttachmentFileL();
       
  1204 							}
       
  1205 						else
       
  1206 							User::Leave(KErrCorrupt);
       
  1207 						}
       
  1208 					}
       
  1209 				RECVLOG(KDecodedUU);
       
  1210 				break;
       
  1211 			case EQPDecode:
       
  1212 				RECVLOG(KDecodingQP);
       
  1213 				iQPCodec.Decode(aSourceLine, des);
       
  1214 				RECVLOG(KDecodedQP);
       
  1215 				break;
       
  1216 			case ENoAlgorithm:
       
  1217 				{				
       
  1218 				// If the data is to be stored in CRichText clean it up before copying it to the buffer
       
  1219 				TLex8 lex(aSourceLine);
       
  1220 				blankLine=ETrue;
       
  1221 				while(blankLine && !lex.Eos())
       
  1222 					{
       
  1223 					blankLine = (lex.Peek()==KImcvSP || lex.Peek()==KImcvTab 
       
  1224 						|| lex.Peek()==KImcvCR || lex.Peek()==KImcvLF);
       
  1225 					lex.Inc();
       
  1226 					}
       
  1227 				des.Copy(aSourceLine);
       
  1228 				}				
       
  1229 			default:
       
  1230 				break;
       
  1231 			} // end switch
       
  1232 	
       
  1233 			// Commits the decoded data to the appropriate store or trashes the line 
       
  1234 			if(iCommitLine) 
       
  1235 				{
       
  1236 				if (iLeftOver.Length())
       
  1237 					{
       
  1238 					des.Insert(0, iLeftOver);
       
  1239 					iLeftOver.SetLength(0);
       
  1240 					}
       
  1241 
       
  1242 				if(iCurrentPartIsRichText)
       
  1243 					{
       
  1244 					if (iStore8BitData)
       
  1245 						iBodyBuf->InsertL(iBodyBuf->Size(), des);
       
  1246 					else
       
  1247 						WriteToBodyL(des, blankLine);
       
  1248 					}
       
  1249 				else
       
  1250 					WriteToAttachmentL(des);
       
  1251 				}
       
  1252 		} // end else
       
  1253 
       
  1254 	CleanupStack::PopAndDestroy(); // convertedLine
       
  1255 	}
       
  1256 
       
  1257 
       
  1258 /**
       
  1259 ParseMimeLineL()
       
  1260 
       
  1261 @param aSourceLine
       
  1262 */
       
  1263 void CLocalImRecvConvert::ParseMimeLineL(const TDesC8& aSourceLine)
       
  1264 	{
       
  1265 
       
  1266 	if(!iMimeParser->IsBoundary(aSourceLine))
       
  1267 		{
       
  1268 		if(!iPrepared) // first line of the body
       
  1269 			{		
       
  1270 			if (iMIMEPart_822Header)
       
  1271 				{
       
  1272 				// missing 822 part header. Revert to default.
       
  1273 				EndOfHeaderMIMEProcessingL();
       
  1274 				iMIMEPart_822Header=EFalse;
       
  1275 				}
       
  1276 
       
  1277 			PrepareDecoder();
       
  1278 			}
       
  1279 
       
  1280 		if (CheckUUEStartL(aSourceLine))
       
  1281 			{
       
  1282 			iAlgorithm=EUUDecode;
       
  1283 			iCommitLine=EFalse;
       
  1284 			}
       
  1285 		}
       
  1286 	else
       
  1287 		{
       
  1288 		// found a MIME boundary so store the current parts data and update its entry.
       
  1289 
       
  1290 		RECVLOG(KFoundMIMEBoundary)
       
  1291 		iCommitLine=EFalse; //Dont store this line as its a boundary.
       
  1292 
       
  1293 		if(!iFirstBoundaryReached && iEntryType==EFolderEntry)
       
  1294 			{
       
  1295 			iFirstBoundaryReached=ETrue;
       
  1296 			if (!iCurrentMultipartFolderEntryId)
       
  1297 				iCurrentMultipartFolderEntryId = EntryId();
       
  1298 			MoveToParentEntryL();
       
  1299 			ResetForNewEntryL(iDefaultEntryType);
       
  1300 			return; // First boundary encountered.
       
  1301 			}
       
  1302 
       
  1303 		CloseAttachmentFileL();
       
  1304 		if(iNewEntry)
       
  1305 			{
       
  1306 			iEmailEntry->SetComplete(ETrue);
       
  1307 			iEmailEntry->SetBodyTextComplete(ETrue);
       
  1308 			StoreEntryStreamsL(KStoreMIMEHeader | KStoreBodyText);
       
  1309 			if (iBodyId==KMsvNullIndexEntryId)
       
  1310 				{
       
  1311 				iBodyId=iEmailEntry->Id();
       
  1312 				}
       
  1313 			}
       
  1314 
       
  1315 		iSkipData = EFalse;
       
  1316 
       
  1317 		// check whether we just found the terminating boundary...
       
  1318 		if(iMimeParser->IsTerminatingBoundary())
       
  1319 			{
       
  1320 			RECVLOG(KRemoveBoundary);
       
  1321 			iMimeParser->RemoveBoundary();
       
  1322 			RECVLOG(KRemovedBoundary);
       
  1323 			iMIMEPart_822Header = EFalse;
       
  1324 
       
  1325 			if (EntryId()!=iTopMessagePart)
       
  1326 				{
       
  1327 				if(iEmailPart==KParentPart)
       
  1328 					{
       
  1329 					// rfc822 message which is not  not multipart.
       
  1330 					iEmailPart=KNoPart;
       
  1331 					MoveToParentEntryL();				
       
  1332 
       
  1333 					// Embedded message
       
  1334 					iEmailEntry->SetComplete(ETrue);
       
  1335 					iEmailEntry->SetBodyTextComplete(ETrue);
       
  1336 					StoreMessageEntryDetailsL();
       
  1337 					}
       
  1338 				else if (iEmailEntry->iType==KUidMsvMessageEntry)
       
  1339 					{
       
  1340 					// Moving up from a multi embedded rfc822 message.
       
  1341 					iEmailEntry->SetComplete(ETrue);
       
  1342 					iEmailEntry->SetBodyTextComplete(ETrue);
       
  1343 					StoreMessageEntryDetailsL();
       
  1344 					}
       
  1345 				}
       
  1346 
       
  1347 			MoveToParentEntryL();
       
  1348 			iEntryDataSize = iEmailEntry->iSize;
       
  1349 
       
  1350 			if(iServerEntry->Entry().iType == KUidMsvFolderEntry)
       
  1351 				{
       
  1352 				iCurrentMultipartFolderEntryId = EntryId();
       
  1353 				}
       
  1354 			else if (EntryId()!=iTopMessagePart)
       
  1355 				{
       
  1356 				if(iEmailEntry->iType == KUidMsvMessageEntry)
       
  1357 					{
       
  1358 					iEmailEntry->SetComplete(ETrue);
       
  1359 					iEmailEntry->SetBodyTextComplete(ETrue);
       
  1360 					StoreMessageEntryDetailsL();
       
  1361 					}
       
  1362 				MoveToParentEntryL();
       
  1363 				iEntryDataSize += iEmailEntry->iSize;
       
  1364 				}
       
  1365 
       
  1366 			if(!iNewEntry)
       
  1367 				ResetForNonMimeEntryL();
       
  1368 
       
  1369 			RECVLOG(KSkippingData)
       
  1370 			iSkipData = ETrue;
       
  1371 			iDefaultEntryType=ETextEntry;
       
  1372 			}
       
  1373 		else // if regular boundary
       
  1374 			{ 
       
  1375 			RECVLOG(KSectionHeader)
       
  1376 			if(iEmailPart==KParentPart && EntryId()!=iTopMessagePart)
       
  1377 				{
       
  1378 				// rfc822 message which is not  not multipart.
       
  1379 				iEmailPart=KNoPart;
       
  1380 				MoveToParentEntryL();
       
  1381 				// Embedded message
       
  1382 				iEmailEntry->SetComplete(ETrue);
       
  1383 				iEmailEntry->SetBodyTextComplete(ETrue);
       
  1384 				StoreMessageEntryDetailsL();
       
  1385 				}
       
  1386 
       
  1387 			if (!iCurrentMultipartFolderEntryId && iEmailPart==KNoPart)
       
  1388 				MoveToParentEntryL();
       
  1389 
       
  1390 			ResetForNewEntryL(iDefaultEntryType);
       
  1391 			}
       
  1392 		}
       
  1393 	}
       
  1394 
       
  1395   
       
  1396 /**
       
  1397 EndOfHeaderProcessingL()
       
  1398 
       
  1399 */
       
  1400 void CLocalImRecvConvert::EndOfHeaderProcessingL()
       
  1401 	{	
       
  1402 	CreateEntryL();
       
  1403 	StoreEntryStreamsL(KStore822Header);
       
  1404 	iEntryDataSize = 0;
       
  1405 	}
       
  1406 
       
  1407 
       
  1408 /**
       
  1409 EndOfHeaderMIMEProcessingL()
       
  1410 Have just finished processing header, what next.. ?
       
  1411 All MIME entry entry creation takes place here.
       
  1412 
       
  1413 */
       
  1414 void CLocalImRecvConvert::EndOfHeaderMIMEProcessingL()
       
  1415 	{	
       
  1416 	if (iMimeParser->IsMessageDigest())
       
  1417 		iDefaultEntryType=EMessageEntry;
       
  1418 
       
  1419 	if (iMimeParser->VCard() || iMimeParser->VCalendar())
       
  1420 		{
       
  1421 		iCurrentPartIsRichText = EFalse;	
       
  1422 		iEntryType = EAttachmentEntry;
       
  1423 		}
       
  1424 
       
  1425 	// Don't create entry if an embedded message header. 
       
  1426 	if (!iMIMEPart_822Header || iTopMessagePart==EntryId() )
       
  1427 		CreateEntryL(); 
       
  1428 
       
  1429 	if (!iMIMEPart_822Header && !iMimeParser->MimeFieldsExist() && iDefaultEntryType==EMessageEntry)
       
  1430 		{
       
  1431 		// MIME header not present. So expecting embedded 822 header
       
  1432 		iEmailPart = KParentPart;
       
  1433 		iMIMEPart_822Header=ETrue;
       
  1434 		iEntryType=ETextEntry;
       
  1435 		}
       
  1436 	else if (iMimeParser->ContentType()==EMimeMessage)
       
  1437 		{
       
  1438 		// Having received A MIME header of type message/..., store and continue.
       
  1439 
       
  1440 		StoreEntryStreamsL(KStore822Header|KStoreMIMEHeader);
       
  1441 		iMimeParser->ResetForNewEntry();
       
  1442 		iMIMEPart_822Header=ETrue;
       
  1443 
       
  1444 		// Non-multipart embedded message.
       
  1445 		if (iTopMessagePart==EntryId())
       
  1446 			{
       
  1447 			iEntryType = EMessageEntry;
       
  1448 			ResetForNonMimeEntryL();
       
  1449 			}
       
  1450 		else
       
  1451 			iEntryType=ETextEntry;
       
  1452 		}
       
  1453 	else if ( (iTopMessagePart==EntryId() || iMIMEPart_822Header)&&(!iReceivingHeadersOnly) )
       
  1454 		{
       
  1455 		// Main rfc822 header or embedded header.
       
  1456 
       
  1457 		TImEmailFolderType folderType=iMimeParser->MessageFolderType();
       
  1458 		if (iMIMEPart_822Header)
       
  1459 			{
       
  1460 			iEmailEntry->iDetails.Set(iOutputHeader->From());
       
  1461 			iEmailEntry->iDescription.Set(iOutputHeader->Subject());
       
  1462 			iMIMEPart_822Header=EFalse;
       
  1463 			}
       
  1464 
       
  1465 		if (iRfc822Token->i822FieldsExist)
       
  1466 			StoreEntryStreamsL(KStore822Header|KStoreMIMEHeader);
       
  1467 		else
       
  1468 			StoreEntryStreamsL(KStoreMIMEHeader);
       
  1469 
       
  1470 
       
  1471 		if (iMimeParser->ContentType()==EMimeMultipart)
       
  1472 			{	
       
  1473 			RECVLOG(KSkippingData)
       
  1474 			ResetForNewEntryL(EFolderEntry);
       
  1475 			iMimeParser->SetMessageFolderType(folderType);
       
  1476 			iSkipData = ETrue;
       
  1477 			iEmailPart = KMultiPart;
       
  1478 			iCurrentMultipartFolderEntryId=0;
       
  1479 			}
       
  1480 		else 
       
  1481 			{
       
  1482 			// Not multipart but some header data to store.
       
  1483 			iEntryDataSize = 0;
       
  1484 			}
       
  1485 
       
  1486 		CreateEntryL();
       
  1487 		}
       
  1488 
       
  1489 	iRfc822Token->i822FieldsExist=EFalse;
       
  1490 	iMimeParser->ResetMimeFieldsExist();
       
  1491 	
       
  1492 	iFinishedHeader = iMIMEPart_822Header ? EFalse:ETrue;
       
  1493 	iSkipData = iMimeParser->ContentType()==EMimeMultipart ? ETrue:EFalse;
       
  1494 	}
       
  1495 
       
  1496 
       
  1497 /**
       
  1498 ParseBodyLineL()
       
  1499 Non Mime body parsing
       
  1500 
       
  1501 @param aSourceLine
       
  1502 */
       
  1503 void CLocalImRecvConvert::ParseBodyLineL(const TDesC8& aSourceLine)
       
  1504 	{
       
  1505 	TInt len=aSourceLine.Length();
       
  1506 	iTopPartialDownloadCounter+=len; // added for TOP. increment the number of bytes of the attachment downloaded so far
       
  1507 	TMsvId id=0;
       
  1508 	if (iBodyId==KMsvNullIndexEntryId)
       
  1509 		{
       
  1510 		iBodyId=iEmailEntry->Id();
       
  1511 		}
       
  1512 
       
  1513 	// first check whether this line is a UUEncode start boundary
       
  1514 	if(CheckUUEStartL(aSourceLine)) 
       
  1515 		{
       
  1516 		RECVLOG(KFoundUUEStartBoundary)
       
  1517 		TFileName tempStore = iAttachmentName;
       
  1518 		id = EntryId();
       
  1519 		if (!iNewNonMIMEBodyPart || id!=iTopMessagePart) // main message entry
       
  1520 			{
       
  1521 			iEmailEntry->SetComplete(ETrue);
       
  1522 			iEmailEntry->SetBodyTextComplete(ETrue);
       
  1523 			StoreEntryStreamsL(KStoreBodyText);
       
  1524 			}
       
  1525 		MoveToParentEntryL();
       
  1526 		if ( !CreateNonMIMEFolderEntryL(id))
       
  1527 			ResetForNonMimeEntryL();
       
  1528 			
       
  1529 		iEntryType = EAttachmentEntry;
       
  1530 		CreateEntryL();
       
  1531 		SetAttachmentName(tempStore);
       
  1532 		
       
  1533 		iCurrentPartIsRichText = EFalse;
       
  1534 		iAlgorithm=EUUDecode;
       
  1535 		iCommitLine=EFalse;
       
  1536 		if(!iSavingAttachments)
       
  1537 			{
       
  1538 			RECVLOG(KSkippingData)
       
  1539 			iSkipData=ETrue;
       
  1540 			}
       
  1541 		iNewNonMIMEBodyPart=EFalse;
       
  1542 		}
       
  1543 	else if(aSourceLine.CompareF(KImcvUueEnd)==0) // Checks for the UUEncode end boundary
       
  1544 		{
       
  1545 		RECVLOG(KFoundUUEEndBoundary)
       
  1546 		CloseAttachmentFileL();
       
  1547 		StoreEntryDataL();
       
  1548 		MoveToParentEntryL();
       
  1549 		iSkipData = EFalse;
       
  1550 		iCommitLine=EFalse;
       
  1551 		iNewNonMIMEBodyPart=ETrue; 
       
  1552 		}
       
  1553 	else if (iNewNonMIMEBodyPart && !( len==2 && aSourceLine[0]==KImcvCR && aSourceLine[1]==KImcvLF ))
       
  1554 		{
       
  1555 		id = EntryId();
       
  1556 		if (!iNewNonMIMEBodyPart || id!=iTopMessagePart)
       
  1557 			{
       
  1558 			iEmailEntry->SetComplete(ETrue);
       
  1559 			iEmailEntry->SetBodyTextComplete(ETrue);
       
  1560 			StoreEntryStreamsL(KStoreBodyText);
       
  1561 			}
       
  1562 		MoveToParentEntryL();
       
  1563 		if ( !CreateNonMIMEFolderEntryL(id))
       
  1564 			ResetForNonMimeEntryL();
       
  1565 		iAlgorithm=ENoAlgorithm;
       
  1566 		iEntryType = ETextEntry;
       
  1567 		CreateEntryL();
       
  1568 		iNewNonMIMEBodyPart=EFalse;
       
  1569 		}	
       
  1570 	}
       
  1571 
       
  1572 
       
  1573 /**
       
  1574 CreateNonMIMEFolderEntryL()
       
  1575 
       
  1576 @param aCurrentId
       
  1577 @return
       
  1578 */
       
  1579 TBool CLocalImRecvConvert::CreateNonMIMEFolderEntryL(TMsvId aCurrentId)
       
  1580 	{
       
  1581 	if ( aCurrentId==iTopMessagePart || iCurrentMultipartFolderEntryId )
       
  1582 		return EFalse;
       
  1583 
       
  1584 	// Create Folder.
       
  1585 	iServerEntry->SetEntry(iTopMessagePart); 
       
  1586 	iEmailPart = KMultiPart;
       
  1587 	iEntryType = EFolderEntry;
       
  1588 	CreateEntryL();
       
  1589 
       
  1590 	// Move existing child entry under folder.
       
  1591 	TMsvId destId = EntryId();
       
  1592 	iServerEntry->SetEntry(iTopMessagePart); 
       
  1593 	iServerEntry->MoveEntryWithinService(aCurrentId, destId);
       
  1594 	User::LeaveIfError(iServerEntry->SetEntry(aCurrentId));
       
  1595 	User::LeaveIfError(iServerEntry->SetEntry(iServerEntry->Entry().Parent())); 
       
  1596 
       
  1597 	// Create MimeHeader.
       
  1598 	iEmailEntry->SetMessageFolderType(iMimeParser->MessageFolderType());
       
  1599 
       
  1600 	RECVLOG(KResetForNewEntry) 
       
  1601 
       
  1602 	iMimeParser->ResetForNewEntry();
       
  1603 	
       
  1604 	if (iStore8BitData)
       
  1605 		{
       
  1606 		//Create a buffer to hold the body text as it is down loaded.
       
  1607 		delete iBodyBuf;
       
  1608 		iBodyBuf = NULL;
       
  1609 		iBodyBuf = CBufFlat::NewL(KBodyTextChunkSizeBytes);
       
  1610 		}
       
  1611 	else
       
  1612 		{
       
  1613 		iOutputBody->Reset();
       
  1614 		}
       
  1615 		
       
  1616 	ResetForNonMimeEntryL(); 
       
  1617 	RECVLOG(KResetedForNewEntry) 
       
  1618 	return ETrue;
       
  1619 	}
       
  1620 
       
  1621 
       
  1622 /**
       
  1623 CreateAttachmentL()
       
  1624 
       
  1625 @return
       
  1626 */
       
  1627 TBool CLocalImRecvConvert::CreateAttachmentL()
       
  1628 	{
       
  1629 	// Get and set Attachment File path
       
  1630 	TFileName filepath;
       
  1631 	// added to support TOP command. Reset the download counter each time we have a new
       
  1632 	// attachment
       
  1633 	iTopPartialDownloadCounter = 0; 
       
  1634 
       
  1635 	// Need to check that the complete filename: iAttachmentFullPath & iAttachmentName	
       
  1636 	// does not exceed 256 characters. Greater than this and it cannot be saved as a file.
       
  1637 
       
  1638 	TBool addExtension=ETrue;
       
  1639 	if(iAttachmentName.Length() == 0)	//i.e. problem with Attachment name
       
  1640 	    {
       
  1641 		// No filename present. Generate one.
       
  1642 		if(iMimeParser->ContentDescription().Length()!=0)
       
  1643 			{
       
  1644 			// Use ContentDescription() as default name 
       
  1645 			// - as this is more informative than the default
       
  1646 
       
  1647 			TLex sourceLineLex = iMimeParser->ContentDescription();
       
  1648 			ExtractFilename(sourceLineLex, iAttachmentName);
       
  1649 			}
       
  1650 		else
       
  1651 			iAttachmentName = *iDefaultAttachmentName;
       
  1652 		}
       
  1653 	else
       
  1654 		{
       
  1655 		// Filename present. Check it is valid.
       
  1656 		ReplaceInvalidCharacters(iAttachmentName);
       
  1657 		if (iAttachmentName.Locate(KImcvFullStop)!=KErrNotFound)
       
  1658 			addExtension=EFalse;
       
  1659 		}
       
  1660 	if (addExtension)
       
  1661 		AddFileExtension();
       
  1662 
       
  1663 	CMsvStore* store = iServerEntry->EditStoreL(); 
       
  1664 	CleanupStack::PushL(store);
       
  1665 	CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
       
  1666 	RFile file; 
       
  1667 	store->AttachmentManagerExtensionsL().CreateAttachmentL(iAttachmentName,file,attachment);
       
  1668 	
       
  1669 	iAttachmentFile.SetFileHandle(file,TImAttachmentFile::EImFileWrite);
       
  1670 	store->CommitL();
       
  1671 	CleanupStack::PopAndDestroy(store); // store
       
  1672 
       
  1673 	if(KErrNone!=iLeaveError)
       
  1674 		{
       
  1675 		iAttachmentFileState=EFileFailedToOpen;
       
  1676 		CloseAttachmentFileL();
       
  1677 		return EFalse;
       
  1678 		}
       
  1679 
       
  1680 	iAttachmentFileState=EFileIsOpen;
       
  1681 	return ETrue;
       
  1682 	}
       
  1683 
       
  1684 
       
  1685 /**
       
  1686 WriteToAttachmentL()
       
  1687 
       
  1688 @param text
       
  1689 */
       
  1690 void CLocalImRecvConvert::WriteToAttachmentL(const TDesC8& text)
       
  1691 	{
       
  1692 	if ( (iAttachmentFileState==EFileIsClosed || iAttachmentFileState==EFileNotOpen) 
       
  1693 		&& CreateAttachmentL() && iEntryType!=EHtmlEntry)
       
  1694 			iEmailEntry->SetAttachment(ETrue);
       
  1695 	
       
  1696 	if(iAttachmentFileState!=EFileIsOpen || !text.Length())
       
  1697 		{
       
  1698 		RECVLOG(KSkippingData)
       
  1699 		iSkipData = ETrue;
       
  1700 		}
       
  1701 
       
  1702 	// write decoded data into a file if there is any data there to write.
       
  1703 
       
  1704 	RECVLOG(KWritingToFile)
       
  1705 
       
  1706 	// Convert text before writing to attachment.
       
  1707 	
       
  1708 	// Store as Binary files..
       
  1709 	iLeaveError=iAttachmentFile.WriteFile(text);
       
  1710 
       
  1711 	if(KErrNone==iLeaveError)
       
  1712 		iEntryDataSize += text.Length();
       
  1713 	else	
       
  1714 		{
       
  1715 		// the file write failed (eg.there is no space left), set new file state and skip 
       
  1716 		RECVLOG(KFailedToWriteToFile)
       
  1717 		iAttachmentFileState=EFileIsIncomplete;
       
  1718 		CloseAttachmentFileL();
       
  1719 		}
       
  1720 	RECVLOG(KWroteToFile)
       
  1721 	}
       
  1722 
       
  1723 
       
  1724 /**
       
  1725 CloseAttachmentFileL()
       
  1726 
       
  1727 */
       
  1728 void CLocalImRecvConvert::CloseAttachmentFileL()
       
  1729 	{
       
  1730 	// If anything bad happened a message is sent to the parts CRichText
       
  1731 	switch(iAttachmentFileState)
       
  1732 		{
       
  1733 		case EFileNotOpen:
       
  1734 			iAttachmentFileState=EFileIsClosed;
       
  1735 		case EFileIsClosed: //do nothing - this shouldn't happen	
       
  1736 			break;
       
  1737 		case EFileIsOpen:		//successful attachment decode
       
  1738 			RECVLOG(KClosingAttachFile)
       
  1739 			iAttachmentFile.CloseFile();
       
  1740 			iAttachmentFileState=EFileIsClosed;
       
  1741 			iEmailEntry->SetComplete(ETrue);
       
  1742 			break;
       
  1743 		case EFileIsIncomplete:		// file write failed
       
  1744 		case EFileFailedToOpen:		// can't open attach file
       
  1745 		case EFileIsCorrupt:		// UU data being decoded is corrupt
       
  1746 			RECVLOG(KClosingAttachFile)
       
  1747 			iAttachmentFile.CloseFile();	//file has to be closed before it can be deleted
       
  1748 			RECVLOG(KDeletingAttachFile)
       
  1749 			{ 
       
  1750 			// NOTE - need the braces to stop error for re-definition of store
       
  1751 			CMsvStore* store = iServerEntry->EditStoreL(); 
       
  1752 			CleanupStack::PushL(store);
       
  1753 		
       
  1754 			// Remove the attachment and commit the store.	
       
  1755 			store->AttachmentManagerExtensionsL().RemoveAttachmentL(0);
       
  1756 			store->CommitL();
       
  1757 			CleanupStack::PopAndDestroy(store);
       
  1758 			}
       
  1759 			iEmailEntry->SetAttachment(EFalse);
       
  1760 			iAttachmentFileState=EFileIsClosed;
       
  1761 			RECVLOG(KDeletedAttachFile)
       
  1762 
       
  1763 			if(iSavingAttachments && !iStore8BitData)
       
  1764 				{
       
  1765 				WriteToBodyL(KImcvParagraph);
       
  1766 				WriteToBodyL(*iRemovedAttachmentTag);	//lost attachment - notify user
       
  1767 				TBuf8<KMaxFileName> name;
       
  1768 				name.Copy(iAttachmentName); //16 to 8
       
  1769 				WriteToBodyL(name);
       
  1770 				WriteToBodyL(KImcvParagraph);
       
  1771 				}
       
  1772 
       
  1773 			User::Leave(iLeaveError);
       
  1774 			// Skip any remaining encoded data in message
       
  1775 			break;
       
  1776 		case EFileTopIncomplete:
       
  1777 			RECVLOG(KClosingAttachFile)
       
  1778 			iAttachmentFile.CloseFile();	//file has to be closed before it can be deleted
       
  1779 
       
  1780 			// added for TOP command. Ensure we know correct amount of data for later redownload
       
  1781 			iSizeOfAttachmentsRemoved+=iTopPartialDownloadCounter;
       
  1782 
       
  1783 
       
  1784 			RECVLOG(KDeletingAttachFile)
       
  1785 			{ 
       
  1786 			// NOTE - need the braces to stop error for re-definition of store
       
  1787 			CMsvStore* store = iServerEntry->EditStoreL(); 
       
  1788 			CleanupStack::PushL(store);
       
  1789 		
       
  1790 			// Remove the attachment and commit the store.	
       
  1791 			store->AttachmentManagerExtensionsL().RemoveAttachmentL(0);
       
  1792 			store->CommitL();
       
  1793 			CleanupStack::PopAndDestroy(store);
       
  1794 			}
       
  1795 			iEmailEntry->SetAttachment(EFalse);
       
  1796 			iAttachmentFileState=EFileIsClosed;
       
  1797 			RECVLOG(KDeletedAttachFile);
       
  1798 			TMsvId id = EntryId();
       
  1799 			TMsvId parent = iServerEntry->Entry().Parent();
       
  1800 			MoveToParentEntryL();
       
  1801 			TMsvId setTo=iServerEntry->Entry().Id();
       
  1802 			if(setTo!=parent)
       
  1803 				{
       
  1804 				iServerEntry->SetEntry(parent);
       
  1805 				}
       
  1806 			User::LeaveIfError(iServerEntry->DeleteEntry(id));			
       
  1807 			iServerEntry->SetEntry(setTo);
       
  1808 			break;
       
  1809 		}
       
  1810 	}
       
  1811 
       
  1812 
       
  1813 /**
       
  1814 LineIsAllWhitespace()
       
  1815 
       
  1816 @return
       
  1817 */
       
  1818 TBool CLocalImRecvConvert::LineIsAllWhitespace()
       
  1819 	{// returns 1 if all elements of the current line are whitespace
       
  1820 	TBool	spaceFound = 1;
       
  1821 	TLex8	aLex = iLineLex;
       
  1822 
       
  1823 	while (spaceFound && aLex.Peek()!=KImcvCR)
       
  1824 		{
       
  1825 		if (aLex.Peek()==KImcvSP)
       
  1826 			{
       
  1827 			spaceFound = 1;
       
  1828 			aLex.Inc();
       
  1829 			}	
       
  1830 		else spaceFound = 0;
       
  1831 		}
       
  1832 	return (spaceFound);
       
  1833 	}
       
  1834 
       
  1835   
       
  1836 /**
       
  1837 CheckUUEStartL()
       
  1838 
       
  1839 @param aSourceLine
       
  1840 @return
       
  1841 */
       
  1842 TBool CLocalImRecvConvert::CheckUUEStartL(const TDesC8& aSourceLine)
       
  1843 	{
       
  1844 	// Checks if the descriptor contains the UUE begin header
       
  1845 	// Extracts the file name if it is
       
  1846 	
       
  1847 	TInt sourceLength = aSourceLine.Length();
       
  1848 	if(sourceLength < KImcvUueStart().Length()+3) // can't be it, it's not long enough
       
  1849 		return EFalse;
       
  1850 
       
  1851 	if(!aSourceLine.Left(KImcvUueStart().Length()).CompareF(KImcvUueStart)) // start of line might be UUE boundary
       
  1852 		{
       
  1853 		// we also need to check that the next three chars are numbers - Unix file access code
       
  1854 		const TUint8* _ptr = aSourceLine.Ptr();
       
  1855 		TInt length=KImcvUueStart().Length();// this defines length as 6 ie. "b e g i n  " 
       
  1856 		if(TChar(_ptr[length]).IsDigit() && TChar(_ptr[length+1]).IsDigit() && TChar(_ptr[length+2]).IsDigit())
       
  1857 			{
       
  1858 			// we've found 'begin ###' at the start of a line -
       
  1859 			// that's about as good as we can do 
       
  1860 			// now grab the file name and paste it into the document
       
  1861 			// Extract filename from string, removing any surrounding quote marks
       
  1862 
       
  1863 			HBufC16* pBuf16 = HBufC16::NewLC(aSourceLine.Length());
       
  1864 			pBuf16->Des().Copy(aSourceLine);
       
  1865 			TLex sourceLineLex = pBuf16->Ptr();
       
  1866 			//parse until start of filename and mark
       
  1867 			length+=3;					// length (init'd to 6 above) now equals 9 ie. "begin ###"
       
  1868 			sourceLineLex.Inc(length);	// skips "begin ###"
       
  1869 			sourceLineLex.SkipSpace();	// skips any leading whitespace
       
  1870 
       
  1871 			ExtractFilename(sourceLineLex, iAttachmentName);
       
  1872 			CleanupStack::PopAndDestroy(); // pBuf8
       
  1873 			return ETrue;
       
  1874 			}
       
  1875 		}
       
  1876 		
       
  1877 	return EFalse;
       
  1878 	}
       
  1879 
       
  1880   
       
  1881 /**
       
  1882 AddFileExtension()
       
  1883 */
       
  1884 void CLocalImRecvConvert::AddFileExtension()
       
  1885 	{
       
  1886 	switch (iMimeParser->ContentType())
       
  1887 		{
       
  1888 		case EMimeText:
       
  1889 			// Add on extension to make opening file from email editor possible.
       
  1890 
       
  1891 			if ( iMimeParser->ContentSubType()==KImcvHtml )
       
  1892 				iAttachmentName.Append(KHtmlExtension);
       
  1893 			else if (iMimeParser->VCard() || iMimeParser->VCalendar())
       
  1894 				iAttachmentName.Append(KVCardExtension);
       
  1895 			else //if ( iMimeParser->ContentSubType()==KImcvPlain)
       
  1896 				iAttachmentName.Append(KTextExtension);
       
  1897 			break;
       
  1898 		case EMimeImage:
       
  1899 		case EMimeAudio:
       
  1900 		case EMimeVideo:
       
  1901 			if ( (iMimeParser->ContentSubType()==KImcvBmp) 
       
  1902 					|| (iMimeParser->ContentSubType()==KImcvGif)
       
  1903 					|| (iMimeParser->ContentSubType()==KImcvJpeg)
       
  1904 					|| (iMimeParser->ContentSubType()==KImcvTiff)
       
  1905 					|| (iMimeParser->ContentSubType()==KImcvWav) )
       
  1906 				{
       
  1907 				TBuf<KMaxExtensionLength> buf;
       
  1908 				buf.Copy(iMimeParser->ContentSubType());
       
  1909 				iAttachmentName.Append(KImcvFullStop);
       
  1910 				iAttachmentName.Append(buf);
       
  1911 				}
       
  1912 			break;
       
  1913 		default:
       
  1914 			break;
       
  1915 		} // End switch
       
  1916 	}
       
  1917 
       
  1918   
       
  1919 /**
       
  1920 WriteToBodyL()
       
  1921 
       
  1922 @param aText
       
  1923 @param aBlankLine
       
  1924 */
       
  1925 void CLocalImRecvConvert::WriteToBodyL(const TDesC8& aText, TBool aBlankLine)
       
  1926 	{
       
  1927 	RECVLOG(KWritingToBody)
       
  1928 
       
  1929 	if(aText.Length() && aText[aText.Length()-1]==CEditableText::ELineBreak )
       
  1930 		RECVLOG(KLineHasLineBreak)
       
  1931 	TInt pos = iOutputBody->DocumentLength();
       
  1932 
       
  1933 	// Add bits of body text, converting along the way, till no characters left
       
  1934 	// .. to convert.
       
  1935 
       
  1936 	if(aBlankLine)
       
  1937 		{
       
  1938 		RECVLOG(KBlankLine);
       
  1939 		iOutputBody->InsertL(pos, CEditableText::EParagraphDelimiter);
       
  1940 		pos++;
       
  1941 		return;
       
  1942 		}
       
  1943 
       
  1944 	// Convert text before writing to body.
       
  1945 	TInt rem = 0;
       
  1946 	HBufC16* text16=HBufC16::NewLC(aText.Length());
       
  1947 	TPtr16 ptr16(text16->Des());
       
  1948 	TInt unconvertedChars, firstPos; // not used 
       
  1949 	rem = iCharConv->ConvertToOurCharsetL(aText, ptr16, unconvertedChars, firstPos);
       
  1950 	if (rem < 0) // error
       
  1951 		{
       
  1952 		// Copy unconverted characters.
       
  1953 		Append(ptr16, aText);
       
  1954 		iOutputBody->InsertL(pos, ptr16);
       
  1955 		CleanupStack::PopAndDestroy(); // text16
       
  1956 		return;
       
  1957 		}
       
  1958 	else if (rem && rem < KConversionRemainderLength)
       
  1959 		iLeftOver.Copy(aText.Right(rem));	
       
  1960 	
       
  1961 	// Make sure that the line is not CRLF terminated 
       
  1962 	// - replace with a line break if necessary.
       
  1963 
       
  1964 	TInt length = ptr16.Length();
       
  1965 	switch(iAlgorithm)
       
  1966 		{
       
  1967 		case EBase64Decode:
       
  1968 		case EUUDecode:
       
  1969 			{
       
  1970 			// Check for CRLF throughout the string.
       
  1971 
       
  1972 			if (!length)
       
  1973 				break; // String length zero.
       
  1974 
       
  1975 			if (iEncounteredLineEndingInCarriageReturn)
       
  1976 				{
       
  1977 				pos--; // overwrite the stored CR.
       
  1978 				ptr16[0] = CEditableText::ELineBreak;
       
  1979 				}
       
  1980 			iEncounteredLineEndingInCarriageReturn = ptr16[length-1]==KImcvCR ? ETrue:EFalse;
       
  1981 
       
  1982 			TInt start = 0;
       
  1983 			TInt offset = ptr16.Find(KImcvCRLF16);
       
  1984 
       
  1985 			while (offset != KErrNotFound)
       
  1986 				{
       
  1987 				ptr16[offset] = CEditableText::ELineBreak;
       
  1988 				const TDesC& buf = ptr16.Mid(start, offset-start+1);
       
  1989 				iOutputBody->InsertL(pos, buf);
       
  1990 				pos += buf.Length();
       
  1991 				start=offset+2; // Skip the LF char.
       
  1992 				offset = ptr16.Find(KImcvCRLF16);
       
  1993 				} 
       
  1994 
       
  1995 			if (start<length)
       
  1996 				{
       
  1997 				const TDesC& buf = ptr16.Right(length-start);
       
  1998 				iOutputBody->InsertL(pos, buf);
       
  1999 				pos += buf.Length();
       
  2000 				}
       
  2001 			}
       
  2002 			break;
       
  2003 
       
  2004 		case EQPDecode:
       
  2005 		case ENoAlgorithm:
       
  2006 		default:
       
  2007 			// Check for CRLF at end of line.
       
  2008 			if(length>=2 && ptr16[length-2]==KImcvCR && ptr16[length-1]==KImcvLF)
       
  2009 				{
       
  2010 				ptr16[length-2] = CEditableText::ELineBreak;
       
  2011 				ptr16.SetLength(length-1);
       
  2012 				}	
       
  2013 
       
  2014 			const TDesC& buf = text16->Des();
       
  2015 			iOutputBody->InsertL(pos, buf);
       
  2016 			pos += buf.Length();
       
  2017 		}	
       
  2018 
       
  2019 	CleanupStack::PopAndDestroy(text16);
       
  2020 	
       
  2021 	RECVLOG(KWroteToBody)
       
  2022 	}
       
  2023 
       
  2024 
       
  2025 /**
       
  2026 WriteToBodyL()
       
  2027 
       
  2028 @param aText
       
  2029 */
       
  2030 void CLocalImRecvConvert::WriteToBodyL(const TDesC16& aText)  
       
  2031 	{
       
  2032 	RECVLOG(KWritingToBody)
       
  2033 	if (aText.Length() && aText[aText.Length()-1]==CEditableText::ELineBreak)
       
  2034 		RECVLOG(KLineHasLineBreak)
       
  2035 
       
  2036 	TInt pos = iOutputBody->Read(0).Length();
       
  2037 	// get the text in before the paragraph marker that's always there
       
  2038 	pos = pos-1 < 0 ? 0 : pos-1;
       
  2039 	iOutputBody->InsertL(pos,aText);
       
  2040 	
       
  2041 	RECVLOG(KWroteToBody)
       
  2042 	}
       
  2043 
       
  2044   
       
  2045 /**
       
  2046 ParseRecipientListL()
       
  2047 
       
  2048 @param aList
       
  2049 */
       
  2050 void CLocalImRecvConvert::ParseRecipientListL(CDesCArray& aList)
       
  2051 	{
       
  2052 	HBufC8* pBuf = HBufC8::NewLC(KMaxIMailHeaderReadLineLength);
       
  2053 	TPtrC8 source(iRfc822Token->OutputLine()->Ptr(), iRfc822Token->OutputLine()->Length());
       
  2054 	const TUint8* ptr = source.Ptr();
       
  2055 	TUint8 lookFor = 0;
       
  2056 	TInt count = 0;
       
  2057 	TBool finishedEntry = EFalse;
       
  2058 
       
  2059 	// get past white space
       
  2060 	while(*ptr&&((*ptr==KImcvSP)||(*ptr==KImcvSemiColon))) ptr++;
       
  2061 
       
  2062 	while(*ptr&&((ptr-source.Ptr())<(source.Length())))
       
  2063 		{
       
  2064 		if(!pBuf->Length())
       
  2065 			{
       
  2066 			finishedEntry = EFalse;
       
  2067 			}
       
  2068 
       
  2069 		switch(*ptr)
       
  2070 			{
       
  2071 			case KImcvLeftBracket:
       
  2072 				if(lookFor==KImcvRightBracket)
       
  2073 					count++;
       
  2074 				else
       
  2075 					{
       
  2076 					lookFor = KImcvRightBracket;
       
  2077 					count = 1;
       
  2078 					}
       
  2079 				break;
       
  2080 			case KImcvLeftChevron:
       
  2081 				if(lookFor==KImcvRightChevron)
       
  2082 					count++;
       
  2083 				else
       
  2084 					{
       
  2085 					lookFor = KImcvRightChevron;
       
  2086 					count = 1;
       
  2087 					}
       
  2088 				break;
       
  2089 			case KImcvDoubleQuote:
       
  2090  				lookFor = (TUint8)(lookFor==KImcvDoubleQuote ? 0 : KImcvDoubleQuote);
       
  2091 				count = (lookFor ? 1 : 0);
       
  2092 				break;
       
  2093 			case KImcvRightBracket:
       
  2094 			case KImcvRightChevron:
       
  2095 				count -= (*ptr == lookFor ? 1 : 0);
       
  2096 				lookFor = (TUint8)((*ptr == lookFor)&&(count == 0) ? 0 : lookFor);
       
  2097 				break;
       
  2098 			case KImcvComma:
       
  2099 			case KImcvSemiColon:
       
  2100 				finishedEntry = !lookFor;
       
  2101 				break;
       
  2102 			}
       
  2103 
       
  2104 		if(!finishedEntry)
       
  2105 			{
       
  2106 			// check we're not about to blow the buffer
       
  2107 			if(pBuf->Length() >= pBuf->Des().MaxLength())
       
  2108 				{
       
  2109 				pBuf = pBuf->ReAlloc(pBuf->Length() + 64); // arbitrary extension
       
  2110 				}
       
  2111 			pBuf->Des().Append((TChar)*ptr);
       
  2112 			// move to the next character
       
  2113 			ptr++;
       
  2114 			}
       
  2115 		else
       
  2116 			{
       
  2117 			// that's it! store the address away
       
  2118 			HBufC16* pBuf16 = HBufC16::NewLC(pBuf->Des().Length());
       
  2119 			pBuf16->Des().Copy(pBuf->Des());
       
  2120 			aList.AppendL( (HBufC16&) *pBuf16 );
       
  2121 			CleanupStack::PopAndDestroy(); // pBuf16
       
  2122 			pBuf->Des().SetLength(0);
       
  2123 
       
  2124 			// get past the separator
       
  2125 			ptr++;
       
  2126 
       
  2127 			// get past white space (& any other separators)
       
  2128 			while(*ptr && (*ptr==KImcvSP || *ptr==KImcvTab || *ptr==KImcvComma || *ptr==KImcvSemiColon)) ptr++;
       
  2129 			}
       
  2130 		}
       
  2131 		// catch the last name in the list
       
  2132 		if (pBuf)
       
  2133 			{
       
  2134 			TInt recipientLength = pBuf->Length();
       
  2135 			if (recipientLength)
       
  2136 				{
       
  2137 				HBufC16* pBuf16 = HBufC16::NewLC(recipientLength);
       
  2138 				pBuf16->Des().Copy(*pBuf);
       
  2139 				aList.AppendL(*pBuf16);
       
  2140 				CleanupStack::PopAndDestroy(); // pBuf16
       
  2141 				}
       
  2142 			}
       
  2143 
       
  2144 		CleanupStack::PopAndDestroy(); // pBuf
       
  2145 	}
       
  2146 
       
  2147 
       
  2148 /**
       
  2149 ExtractFilename()
       
  2150 
       
  2151 @param aLex
       
  2152 @param rFileName
       
  2153 */
       
  2154 void CLocalImRecvConvert::ExtractFilename(TLex& aLex, TDes& rFileName)
       
  2155 	{
       
  2156 	// This function steps through the filename extracting the bare name and checking 
       
  2157 	//  the length is less than the max of 256 for EPOC ;checks that all chars are legal for EPOC32
       
  2158 	
       
  2159 	TChar endChar = KImcvSemiColon;
       
  2160 
       
  2161 	aLex.SkipSpace();
       
  2162 	
       
  2163 	if (aLex.Peek()==KImcvDoubleQuote)
       
  2164 		{
       
  2165 		aLex.Inc();	// step over the " character
       
  2166 		endChar = KImcvDoubleQuote;
       
  2167 		}
       
  2168 
       
  2169 	aLex.Mark();	// marks where we are as this is the first char of the filename
       
  2170 	
       
  2171 	TInt fileNameLength = 0;
       
  2172 	TInt maxFileNameLength = rFileName.MaxLength();
       
  2173 
       
  2174 	while(!aLex.Eos() && aLex.Peek()!=endChar && aLex.Peek()!=KImcvCR && fileNameLength < maxFileNameLength)	
       
  2175 		//spools through the string until the end and marks char before quote (such that 
       
  2176 		//  it extracts only the filename), EOS or before the maximum buffer length is exceeded 
       
  2177 		{
       
  2178 		fileNameLength++;
       
  2179 		aLex.Inc();
       
  2180 		}
       
  2181 
       
  2182 	TPtrC marked = aLex.MarkedToken(); 
       
  2183 	rFileName.Copy(marked);
       
  2184 	
       
  2185 	ReplaceInvalidCharacters(rFileName);
       
  2186 	}
       
  2187 
       
  2188 
       
  2189 /**
       
  2190 SetAttachmentName()
       
  2191 
       
  2192 @param aFileName
       
  2193 */
       
  2194 void CLocalImRecvConvert::SetAttachmentName(TDes& aFileName)
       
  2195 	{
       
  2196 	ReplaceInvalidCharacters(aFileName);
       
  2197 	iAttachmentName.Zero();
       
  2198 
       
  2199 	TUint delimiter = '.';
       
  2200 	TInt  maxLength = iAttachmentName.MaxLength();
       
  2201 	
       
  2202 	__ASSERT_DEBUG(
       
  2203 		maxLength >= aFileName.Length(), gPanic(KPanicReadLengthTooLarge)
       
  2204 		);
       
  2205 
       
  2206 	iAttachmentName.Copy(aFileName);
       
  2207 	TInt attachmentLen = iAttachmentName.Length();
       
  2208 	if (attachmentLen == 0)
       
  2209 		iAttachmentName = *iDefaultAttachmentName;
       
  2210 	else if (iAttachmentName[0] == delimiter && maxLength >= attachmentLen + iDefaultAttachmentName->Length())
       
  2211 		iAttachmentName.Insert(0, *iDefaultAttachmentName);
       
  2212 	}
       
  2213 
       
  2214 	
       
  2215 /**
       
  2216 ReplaceInvalidCharacters()
       
  2217 
       
  2218 @param rFileName
       
  2219 */
       
  2220 void CLocalImRecvConvert::ReplaceInvalidCharacters(TDes& rFileName)
       
  2221 	{
       
  2222 	TInt length = rFileName.Length();
       
  2223 	for(TInt index=0; index < length; index++)
       
  2224 		{
       
  2225 		//parse extracted filename and replace any illegal chars with a default.
       
  2226 
       
  2227 		if(IsIllegalChar((TUint)rFileName[index]))
       
  2228 			rFileName[index] = KImcvDefaultChar;
       
  2229 		}
       
  2230 	}
       
  2231 
       
  2232 
       
  2233 /**
       
  2234 StoreEntryStreamsL()
       
  2235 */
       
  2236 void CLocalImRecvConvert::StoreEntryStreamsL()	
       
  2237 	{
       
  2238 	StoreEntryStreamsL(KStoreBodyText|KStore822Header|KStoreMIMEHeader);
       
  2239 	}
       
  2240 
       
  2241 
       
  2242 /**
       
  2243 StoreEntryStreamsL()
       
  2244 
       
  2245 @param aSettings
       
  2246 */
       
  2247 void CLocalImRecvConvert::StoreEntryStreamsL(TInt aSettings)	
       
  2248 	{
       
  2249 	RECVLOG(KStartStoringEntryStream);
       
  2250 	if (iReceivingHeadersOnly==EFalse)
       
  2251 		{
       
  2252 		CMsvStore* entryStore = NULL;
       
  2253 		TBool commitStore = EFalse;
       
  2254 
       
  2255 		TRAPD(error, entryStore = iServerEntry->EditStoreL());
       
  2256 		if(error==KErrNone) // if store does not exist then the entry is the wrong type
       
  2257 			{
       
  2258 			CleanupStack::PushL(entryStore);
       
  2259 
       
  2260 			if (aSettings & KStore822Header)
       
  2261 				Store822HeaderL(*entryStore, commitStore);
       
  2262 			
       
  2263 			if (aSettings & KStoreMIMEHeader)
       
  2264 				StoreMIMEHeaderL(*entryStore, commitStore);
       
  2265 
       
  2266 			if (aSettings & KStoreBodyText)
       
  2267 				StoreBodyTextL(*entryStore, commitStore);
       
  2268 
       
  2269 			// only commit to the store if I wrote something into it
       
  2270 			if (commitStore)
       
  2271 				{
       
  2272 				RECVLOG(KStoringEntryStream);
       
  2273 				entryStore->CommitL();
       
  2274 				}
       
  2275 
       
  2276 			StoreEntryDataL();
       
  2277 			CleanupStack::PopAndDestroy(); //entryStore		
       
  2278 			}
       
  2279 
       
  2280 		}
       
  2281 	RECVLOG(KDoneStoringEntryStream);
       
  2282 	}
       
  2283 
       
  2284 
       
  2285 /**
       
  2286 Store822HeaderL()
       
  2287 
       
  2288 @param aStore
       
  2289 @param aCommit 
       
  2290 */
       
  2291 void CLocalImRecvConvert::Store822HeaderL(CMsvStore& aStore, TBool& aCommit)	
       
  2292 	{
       
  2293 	if(iEmptyHeaderSize<(iOutputHeader->DataSize()))
       
  2294 		{
       
  2295 		iEntryDataSize += iOutputHeader->DataSize()-iEmptyHeaderSize;
       
  2296 		RECVLOG(KStoringHeader);
       
  2297 		iOutputHeader->StoreL(aStore);	
       
  2298 		RECVLOG(KStoredHeader);
       
  2299 		aCommit = ETrue;
       
  2300 		}
       
  2301 	}
       
  2302 
       
  2303 
       
  2304 /**
       
  2305 StoreMIMEHeaderL()
       
  2306 
       
  2307 @param aStore
       
  2308 @param aCommit
       
  2309 */
       
  2310 void CLocalImRecvConvert::StoreMIMEHeaderL(CMsvStore& aStore, TBool& aCommit)	
       
  2311 	{
       
  2312 	if(iMimeParser->MimeHeaderSize())
       
  2313 		{
       
  2314 		RECVLOG(KStoringMIMEHeader);
       
  2315  		iMimeParser->StoreMimeHeaderWithoutCommitL(aStore);
       
  2316 		aCommit = ETrue;
       
  2317 		RECVLOG(KStoredMIMEHeader);
       
  2318 		}
       
  2319 	}
       
  2320 
       
  2321 
       
  2322 /**
       
  2323 StoreBodyTextL()
       
  2324 
       
  2325 @param aStore
       
  2326 @param aCommit
       
  2327 */
       
  2328 void CLocalImRecvConvert::StoreBodyTextL(CMsvStore& aStore, TBool& aCommit)	
       
  2329 	{
       
  2330 	if (iStore8BitData)
       
  2331 		{
       
  2332 		if(iBodyBuf->Size())
       
  2333 			{
       
  2334 			iEntryDataSize += iBodyBuf->Size();
       
  2335 			RECVLOG(KStoring8BitBody);
       
  2336 			iBodyText->StoreL(aStore, *iBodyBuf);
       
  2337 			aCommit = ETrue;
       
  2338 			RECVLOG(KStored8BitBody);
       
  2339 			}
       
  2340 		}
       
  2341 	else
       
  2342 		{
       
  2343 		if(iOutputBody->DocumentLength())
       
  2344 			{
       
  2345 			iEntryDataSize += iOutputBody->DocumentLength();
       
  2346 			RECVLOG(KStoringBody);
       
  2347 			aStore.StoreBodyTextL(*iOutputBody);
       
  2348 			aCommit = ETrue;
       
  2349 			RECVLOG(KStoredBody);
       
  2350 			}
       
  2351 		}
       
  2352 	}
       
  2353 
       
  2354 
       
  2355 /**
       
  2356 StoreEntryDataL()
       
  2357 
       
  2358 @return
       
  2359 */
       
  2360 TBool CLocalImRecvConvert::StoreEntryDataL()
       
  2361 	{
       
  2362 	// NB function should only be called if a whole email is being processed
       
  2363 	TBool commit=EFalse;
       
  2364 	RECVLOG(KUpdatingEntry)
       
  2365 
       
  2366 	if (iEmailEntry->iType==KUidMsvMessageEntry)
       
  2367 		iParent->At(0).iSize += iEntryDataSize;
       
  2368 	else
       
  2369 		{
       
  2370 		iEmailEntry->iSize += iEntryDataSize;
       
  2371 		if (iEntryType==EAttachmentEntry || iEntryType==EHtmlEntry)
       
  2372 			iEmailEntry->iDetails.Set(iAttachmentName);
       
  2373 		}
       
  2374 	User::LeaveIfError(iServerEntry->ChangeEntry(*iEmailEntry));
       
  2375 
       
  2376 	RECVLOG(KUpdatedEntry)
       
  2377 	return commit;	// if I wrote data into the store, tell owner	
       
  2378 	}
       
  2379 
       
  2380 
       
  2381 /**
       
  2382 MoveToParentEntryL()
       
  2383 */
       
  2384 void CLocalImRecvConvert::MoveToParentEntryL()
       
  2385 	{
       
  2386 	// This function changes the context to the current entry's parent entry.
       
  2387 	RECVLOG(KMoveToParentEntry)
       
  2388 
       
  2389 	// Change context to the parent entry	
       
  2390 	if (EntryId()==iTopMessagePart)
       
  2391 		return; // Already there.
       
  2392 
       
  2393 	User::LeaveIfError(iServerEntry->SetEntry(iServerEntry->Entry().Parent())); 
       
  2394 
       
  2395 	iNewEntry = EFalse;
       
  2396 	
       
  2397 	// only read and write to store if this is a real email message; headers stored in
       
  2398 	// the remote mailbox do not require any store information.
       
  2399 	if (iReceivingHeadersOnly)
       
  2400 		{
       
  2401 		RECVLOG(KIgnoringStreams)
       
  2402 		return;
       
  2403 		}
       
  2404 
       
  2405 	TBool allowAttachmentFlag=ETrue;
       
  2406 	if(iServerEntry->Entry().iType == KUidMsvFolderEntry)
       
  2407 		{
       
  2408 		// Current entry is a folder entry signifying a MIME multipart.
       
  2409 		// Change context to the parent entry
       
  2410 		
       
  2411 		TMsvEmailEntry entry = (TMsvEmailEntry) iServerEntry->Entry();
       
  2412 		iCurrentMultipartFolderEntryId = EntryId();
       
  2413 		allowAttachmentFlag = !(entry.MessageFolderType()==EFolderTypeRelated || 
       
  2414 								entry.MessageFolderType()==EFolderTypeAlternative);
       
  2415 	
       
  2416 
       
  2417 		if (EntryId()!=iTopMessagePart)
       
  2418 			User::LeaveIfError(iServerEntry->SetEntry(iServerEntry->Entry().Parent())); 
       
  2419 		}
       
  2420 
       
  2421 	TBool childIsAttachment = (iEmailEntry->Attachment() || iEmailEntry->iType == KUidMsvMessageEntry) ? ETrue:EFalse;
       
  2422 	TBool childIsMHTML=EFalse;
       
  2423 	// Dont want the flag propogated 'up' past a message entry.
       
  2424 	if(iEmailEntry->iType != KUidMsvMessageEntry)
       
  2425 		childIsMHTML = iEmailEntry->MHTMLEmail() ? ETrue:EFalse;
       
  2426 
       
  2427 	//Make the parent entry the current entry 
       
  2428 	if (NULL!=iEmailEntry)
       
  2429 		{
       
  2430 		delete iEmailEntry;
       
  2431 		iEmailEntry=NULL;
       
  2432 		}
       
  2433 	iEmailEntry = new (ELeave) TMsvEmailEntry(iServerEntry->Entry());
       
  2434 
       
  2435 	if (!iParent->Count())
       
  2436 		{
       
  2437 		TParentDetails parentDetails;
       
  2438 		iParent->InsertL(0,parentDetails);
       
  2439 		}
       
  2440 
       
  2441 	if (! iParent->At(0).iAttachment)
       
  2442 		{
       
  2443 		iParent->At(0).iAttachment=(childIsAttachment && allowAttachmentFlag)? ETrue:EFalse;
       
  2444 
       
  2445 		// if we aren't allowing attachments because of the folder type
       
  2446 		// remember there where attachments and check at the end whether
       
  2447 		// it was an MHTML message or not.
       
  2448 		if(childIsAttachment && !allowAttachmentFlag)
       
  2449 			{
       
  2450 			iRelatedAttachments=ETrue;
       
  2451 			}
       
  2452 		}
       
  2453 	if (!iParent->At(0).iMHTML)
       
  2454 		iParent->At(0).iMHTML = childIsMHTML ? ETrue:EFalse;
       
  2455 	iParent->At(0).iSize += iEntryDataSize;
       
  2456 
       
  2457 	iOutputHeader->Reset();
       
  2458 	iEmptyHeaderSize=iOutputHeader->DataSize();
       
  2459 	iMimeParser->ResetForNewEntry();
       
  2460 
       
  2461 	iEntryDataSize=0;
       
  2462 
       
  2463 	RECVLOG(KMovedToParentEntry)
       
  2464 	}
       
  2465 
       
  2466 /**
       
  2467 WritePartialFooterL()
       
  2468 Helper function to add the partial footer to the email if it exists
       
  2469 
       
  2470 @param aAmountLeft
       
  2471 */
       
  2472 void CLocalImRecvConvert::WritePartialFooterL(TInt aAmountLeft)
       
  2473 	{
       
  2474 	TMsvId msgId=iBodyId;
       
  2475 	if (msgId==KMsvNullIndexEntryId)
       
  2476 		return;
       
  2477 	TMsvId id = iServerEntry->Entry().Id();
       
  2478 	if (iServerEntry->SetEntry(msgId)==KErrNone)
       
  2479 		{
       
  2480 		TBool storePresent = iServerEntry->HasStoreL();
       
  2481 		if (storePresent && iPartialEmailFooter->Length()>0 && aAmountLeft>0)
       
  2482 			{
       
  2483 			CMsvStore* store = iServerEntry->ReadStoreL();
       
  2484 			CleanupStack::PushL(store);
       
  2485 			if (store->HasBodyTextL())
       
  2486 				{
       
  2487 				iOutputBody->Reset();
       
  2488 				store->RestoreBodyTextL(*iOutputBody);
       
  2489 				CleanupStack::PopAndDestroy(store);
       
  2490 				HBufC* msg=NULL;
       
  2491 				if (iPartialEmailFooter->Find(KIntegerKey)!=KErrNotFound)
       
  2492 					{
       
  2493 					// display k left on the server, rounded up if between 1 and 1023 bytes
       
  2494 					TInt kBytesLeft = aAmountLeft / 1024;
       
  2495 					if(kBytesLeft == 0)
       
  2496 						kBytesLeft = 1;
       
  2497 					msg = HBufC::NewLC(iPartialEmailFooter->Length()+KSpaceToAddNumber);
       
  2498 					msg->Des().Format(*iPartialEmailFooter,kBytesLeft);
       
  2499 					}
       
  2500 				else
       
  2501 					{
       
  2502 					msg = iPartialEmailFooter->AllocLC();
       
  2503 					}
       
  2504 				iOutputBody->AppendParagraphL();
       
  2505 				TInt length = iOutputBody->DocumentLength();
       
  2506 				iOutputBody->InsertL(length,*msg);
       
  2507 				CleanupStack::PopAndDestroy(msg);
       
  2508 				store=NULL;
       
  2509 				store = iServerEntry->EditStoreL();
       
  2510 				CleanupStack::PushL(store);
       
  2511 				store->StoreBodyTextL(*iOutputBody);
       
  2512 				store->Commit();
       
  2513 				CleanupStack::PopAndDestroy(store);
       
  2514 				}
       
  2515 			else
       
  2516 				{
       
  2517 				CleanupStack::PopAndDestroy(store);
       
  2518 				}
       
  2519 			}
       
  2520 		}
       
  2521 	iServerEntry->SetEntry(id);
       
  2522 	}
       
  2523 
       
  2524 
       
  2525 /**
       
  2526 CreateEntryL()
       
  2527 */
       
  2528 void CLocalImRecvConvert::CreateEntryL()
       
  2529 	{
       
  2530 	RECVLOG(KCreatingEntry);
       
  2531 	if (NULL!=iEmailEntry)
       
  2532 		{
       
  2533 		delete iEmailEntry;
       
  2534 		iEmailEntry=NULL;
       
  2535 		}
       
  2536 
       
  2537 	if (iCurrentMultipartFolderEntryId)
       
  2538 		{
       
  2539 		User::LeaveIfError(iServerEntry->SetEntry(iCurrentMultipartFolderEntryId));
       
  2540 		iCurrentMultipartFolderEntryId=0;
       
  2541 		}
       
  2542 		
       
  2543 	iEmailEntry = new (ELeave) TMsvEmailEntry;
       
  2544 
       
  2545 	TValidEntryType previousEntryType = iEntryType;
       
  2546 	if (!iTopMessagePart || iMIMEPart_822Header)
       
  2547 		{
       
  2548 		// At the main header, want to create a message entry.
       
  2549 		// The stored iEntryType will indicate ( from header info) the next entry to be created.
       
  2550 		// Save temporarily.
       
  2551 		// Also applies to the special case where a message contains ony 1 embedded message.
       
  2552 
       
  2553 		previousEntryType=iEntryType;
       
  2554 		iEntryType=EMessageEntry;
       
  2555 		}
       
  2556 
       
  2557 	if ((iPopulateMessage) && (!iTopMessagePart))
       
  2558 	// If this is the root of a message that is being populated then do not create it.
       
  2559 		{
       
  2560 		User::LeaveIfError(iServerEntry->SetEntry(iRootEntryId));
       
  2561 		*iEmailEntry = iServerEntry->Entry();
       
  2562 		iTopMessagePart=iRootEntryId;
       
  2563 
       
  2564 		// Delete all the children of the message entry.  This is needed because if the
       
  2565 		// message has been purged, the entries will still exist.  When the message is populated,
       
  2566 		// new entries are created.  If the original entries are not removed, then duplicate 
       
  2567 		// entries will exist.
       
  2568 		CMsvEntrySelection*	children = new(ELeave) CMsvEntrySelection;
       
  2569 		CleanupStack::PushL(children);
       
  2570 		User::LeaveIfError(iServerEntry->GetChildren(*children));
       
  2571 		if (children->Count())
       
  2572 			iServerEntry->DeleteEntries(*children);
       
  2573 		CleanupStack::PopAndDestroy(children);
       
  2574 		}
       
  2575 	else
       
  2576 		{
       
  2577 		iEmailEntry->iMtm=iNewMsgType;
       
  2578 		iEmailEntry->iServiceId = iEmailServiceId;
       
  2579 		iEmailEntry->SetComplete(EFalse);
       
  2580 		iEmailEntry->iSize = 0;
       
  2581 		iEmailEntry->SetVisible(ETrue);
       
  2582 		iEmailEntry->SetInPreparation(EFalse);
       
  2583 		iEmailEntry->SetReceipt(EFalse);
       
  2584 
       
  2585 		iEmailEntry->SetVCard(iMimeParser->VCard());
       
  2586 		iEmailEntry->SetVCalendar(iMimeParser->VCalendar());
       
  2587 		iEmailEntry->SetMessageFolderType(iMimeParser->MessageFolderType());
       
  2588 		iEmailEntry->SetPriority(iImPriority);
       
  2589 		iEmailEntry->SetNew(EFalse);
       
  2590 
       
  2591 		if(iOutputHeader->ReceiptAddress().Length()>0)
       
  2592 			iEmailEntry->SetReceipt(ETrue);
       
  2593 
       
  2594 		iEmailEntry->iDate=iTimeDate;
       
  2595 		switch(iEntryType)
       
  2596 			{
       
  2597 			case EMessageEntry:
       
  2598 				if(!iTopMessagePart)
       
  2599 					{
       
  2600 					iEmailEntry->SetUnread(ETrue);
       
  2601 					iEmailEntry->SetNew(ETrue);
       
  2602 					iEmailEntry->SetVisible(EFalse);
       
  2603 					iEmailEntry->SetInPreparation(ETrue);
       
  2604 					iEmailEntry->SetSendingState(KMsvSendStateNotApplicable);
       
  2605 					}
       
  2606 				else
       
  2607 					{
       
  2608 					TParentDetails parentDetails;
       
  2609 					parentDetails.iMHTML=EFalse;
       
  2610 			        parentDetails.iAttachment=EFalse;
       
  2611 					parentDetails.iSize=0;
       
  2612 					iParent->InsertL(0,parentDetails);
       
  2613 					}
       
  2614 				iEmailEntry->iType=KUidMsvMessageEntry;
       
  2615 				iEmailEntry->iDetails.Set(iOutputHeader->From());
       
  2616 				iEmailEntry->iDescription.Set(iOutputHeader->Subject());
       
  2617 				break;
       
  2618 			case EFolderEntry:
       
  2619 				iEmailEntry->iType=KUidMsvFolderEntry;
       
  2620 				if (iMimeParser->MessageFolderType()==EFolderTypeUnknown)
       
  2621 					{
       
  2622 					// Get folder type of parent (the message)
       
  2623 					TMsvEmailEntry entry=iServerEntry->Entry();
       
  2624 					iEmailEntry->SetMessageFolderType(entry.MessageFolderType());
       
  2625 					}
       
  2626 				break;
       
  2627 			case EAttachmentEntry:
       
  2628 				iEmailEntry->iType=KUidMsvAttachmentEntry;
       
  2629 				iEmailEntry->iDetails.Set(iAttachmentName);
       
  2630 				iEmailEntry->iDescription.Set(iMimeParser->ContentDescription());
       
  2631 				break; 
       
  2632 			case ETextEntry:
       
  2633 				if ( iMimeParser->ContentDisposition()!=KImcvAttachment)
       
  2634 					iEmailEntry->iType=KUidMsvEmailTextEntry;
       
  2635 				else 
       
  2636 					{
       
  2637 					iEmailEntry->iType=KUidMsvAttachmentEntry;
       
  2638 					iEmailEntry->iDetails.Set(iAttachmentName);
       
  2639 					iEmailEntry->iDescription.Set(iMimeParser->ContentDescription());
       
  2640 					}
       
  2641 				break;
       
  2642 			case EHtmlEntry:
       
  2643 				iEmailEntry->iType=KUidMsvEmailHtmlEntry;
       
  2644 				// If disposition not set or is inline..
       
  2645 				if ( iMimeParser->ContentDisposition()==KImcvAttachment)
       
  2646 					iEmailEntry->iType=KUidMsvAttachmentEntry;
       
  2647 				else
       
  2648 					iEmailEntry->SetMHTMLEmail(ETrue);
       
  2649 				iEmailEntry->iDetails.Set(iAttachmentName);
       
  2650 				iEmailEntry->iDescription.Set(iMimeParser->ContentDescription());
       
  2651 				break;
       
  2652 			default:
       
  2653 				iEmailEntry->iType=KUidMsvAttachmentEntry;
       
  2654 				iEmailEntry->iDetails.Set(iAttachmentName);
       
  2655 				iEmailEntry->iDescription.Set(iMimeParser->ContentDescription());
       
  2656 			}
       
  2657 
       
  2658 		User::LeaveIfError(iServerEntry->CreateEntry(*iEmailEntry));
       
  2659 		User::LeaveIfError(iServerEntry->SetEntry(iEmailEntry->Id()));
       
  2660 		if(!iTopMessagePart)
       
  2661 			iTopMessagePart=iEmailEntry->Id();
       
  2662 
       
  2663 		//if (iEntryType==EHtmlEntry && iAttachmentFileState!=EFileIsOpen)
       
  2664 		//	CreateAttachmentL();
       
  2665 		}
       
  2666 
       
  2667 	iEntryType=previousEntryType;
       
  2668 	iNewEntry = ETrue;
       
  2669 	RECVLOG(KCreatedEntry);
       
  2670 	}
       
  2671 
       
  2672 
       
  2673 /**
       
  2674 Logging()
       
  2675 
       
  2676 @param aString1
       
  2677 @param aString2
       
  2678 */
       
  2679 void CLocalImRecvConvert::Logging(const TDesC8& aString1, const TDesC8& aString2)  
       
  2680 	{
       
  2681 	TBuf8<1024> aBuf(aString1);
       
  2682 
       
  2683 	aBuf.Append(aString2);
       
  2684 	RECVLOG(aBuf);
       
  2685 	}
       
  2686 
       
  2687 
       
  2688 /**
       
  2689 StoreMessageEntryDetailsL()
       
  2690 */
       
  2691  void CLocalImRecvConvert::StoreMessageEntryDetailsL()  
       
  2692 	{
       
  2693 	iEmailEntry->SetAttachment(iParent->At(0).iAttachment);
       
  2694 	iEmailEntry->SetMHTMLEmail(iParent->At(0).iMHTML);
       
  2695 
       
  2696 	if(iEmailEntry->MHTMLEmail() == EFalse && iEmailEntry->Attachment() == EFalse && iRelatedAttachments !=EFalse)
       
  2697 		{
       
  2698 		iEmailEntry->SetAttachment(ETrue);
       
  2699 		}
       
  2700 	iRelatedAttachments=EFalse;
       
  2701 	
       
  2702 	iEmailEntry->iSize=iParent->At(0).iSize;
       
  2703 	iEmailEntry->SetMessageFolderType(iParent->At(0).iFolder);
       
  2704 	StoreEntryDataL();
       
  2705 
       
  2706 	if (iParent->Count()>1)
       
  2707 		{
       
  2708 		iParent->At(1).iSize+=iEmailEntry->iSize;
       
  2709 		iParent->Delete(0);
       
  2710 		}
       
  2711 	else
       
  2712 		{
       
  2713 		iParent->At(0).iAttachment=iParent->At(0).iMHTML=EFalse;
       
  2714 		iParent->At(0).iSize=0;
       
  2715 		}
       
  2716 	}
       
  2717 
       
  2718 
       
  2719 /**
       
  2720 DeletedAttachmentSize()
       
  2721 
       
  2722 @return
       
  2723 */ 
       
  2724  TInt CLocalImRecvConvert::DeletedAttachmentSize()  
       
  2725 	{
       
  2726 	return iSizeOfAttachmentsRemoved;
       
  2727 	}
       
  2728 
       
  2729 /****************************************************************************
       
  2730 	Class CLocalMimeParser functions
       
  2731 *****************************************************************************/
       
  2732 
       
  2733 /**
       
  2734 NewLC()
       
  2735 Static factory constructor. Uses two phase construction 
       
  2736 and pushes the newly created object into the Cleanup stack.
       
  2737 
       
  2738 @param aImRecvConvert
       
  2739 @return
       
  2740 */    
       
  2741 CLocalMimeParser* CLocalMimeParser::NewLC(CLocalImRecvConvert& aImRecvConvert)  
       
  2742 	{
       
  2743 	CLocalMimeParser* self = new (ELeave) CLocalMimeParser(aImRecvConvert);
       
  2744 	CleanupStack::PushL(self);
       
  2745 	self->ConstructL();
       
  2746 	return self;
       
  2747 	}
       
  2748 
       
  2749 
       
  2750 /**
       
  2751 NewL()
       
  2752 Static factory constructor. Uses two phase construction.
       
  2753 
       
  2754 @param aImRecvConvert
       
  2755 @return
       
  2756 */
       
  2757  CLocalMimeParser* CLocalMimeParser::NewL(CLocalImRecvConvert& aImRecvConvert)  
       
  2758 	{
       
  2759 	CLocalMimeParser* self = CLocalMimeParser::NewLC(aImRecvConvert);
       
  2760 	CleanupStack::Pop();
       
  2761 	return self;
       
  2762 	}
       
  2763 
       
  2764 
       
  2765 /**
       
  2766 CLocalMimeParser()
       
  2767 
       
  2768 @param aImRecvConvert
       
  2769 @return
       
  2770 */
       
  2771 CLocalMimeParser::CLocalMimeParser(CLocalImRecvConvert& aImRecvConvert): iImRecvConvert(aImRecvConvert), 
       
  2772 											iStartId(NULL)
       
  2773 
       
  2774 	{
       
  2775 	__DECLARE_NAME(_S("CLocalMimeParser"));
       
  2776 	}
       
  2777 
       
  2778 
       
  2779 /**
       
  2780 ConstructL()
       
  2781 */
       
  2782 void CLocalMimeParser::ConstructL() 
       
  2783 	{
       
  2784 	iMimeHeader = CImMimeHeader::NewL();
       
  2785 	// Create a Desc array to store the boundary strings of a Mime message
       
  2786 	iBoundaryText = new (ELeave) CDesC8ArrayFlat(3);
       
  2787 	
       
  2788 	// Set charset default value
       
  2789 	iDefaultCharset=iImRecvConvert.CharacterConverter().DefaultCharset();
       
  2790 	iCharset = iDefaultCharset;
       
  2791 	ResetMimeFieldsExist();
       
  2792 
       
  2793 	Reset();
       
  2794 	}
       
  2795 
       
  2796 
       
  2797 /**
       
  2798 ~CLocalMimeParser()
       
  2799 */
       
  2800 CLocalMimeParser::~CLocalMimeParser() 
       
  2801 	{
       
  2802 	delete iMimeHeader;
       
  2803 	iMimeHeader=NULL;
       
  2804 	delete iBoundaryText;
       
  2805 	iBoundaryText=NULL;
       
  2806 	delete iMimeHeaderLine;
       
  2807 	iMimeHeaderLine=NULL;
       
  2808 	delete iStartId;
       
  2809 	iStartId=NULL;
       
  2810 	}
       
  2811 
       
  2812 
       
  2813 /**
       
  2814 Reset() 
       
  2815 */
       
  2816 void CLocalMimeParser::Reset() 
       
  2817 	{
       
  2818 	iBoundaryText->Reset();
       
  2819 	iBoundaryIndex = 0;
       
  2820 	iBoundaryLength = 0;
       
  2821 	isMime = EFalse;
       
  2822 	
       
  2823 	ResetForNewEntry();
       
  2824 	}
       
  2825 
       
  2826 
       
  2827 /**
       
  2828 ResetForNewEntry()
       
  2829 */
       
  2830 void CLocalMimeParser::ResetForNewEntry()
       
  2831 	{
       
  2832 	iMimeHeader->Reset();
       
  2833 	iEmptyMimeHeaderSize=iMimeHeader->Size();
       
  2834 		
       
  2835 	iContentType = EMimeUnknownContent;
       
  2836 	iContentEncoding = EEncodingTypeNone;
       
  2837 	iContentDescription.Zero();
       
  2838 	iVCard = EFalse;
       
  2839 	iVCalendar = EFalse;
       
  2840 	iStartPart=EFalse;
       
  2841 	iMessageFolderType = EFolderTypeUnknown;
       
  2842 	iTerminatingBoundary = EFalse;
       
  2843 	iBoundaryFound = EFalse;
       
  2844 	}
       
  2845 
       
  2846 
       
  2847 /**
       
  2848 RestoreMimeParserL()
       
  2849 
       
  2850 @param entryStore
       
  2851 */
       
  2852 void CLocalMimeParser::RestoreMimeParserL(CMsvStore& entryStore)
       
  2853 	{
       
  2854 	iMimeHeader->RestoreL(entryStore);
       
  2855 	if(iMimeHeader->ContentType().Compare(KImcvText)==0)
       
  2856 		iContentType=EMimeText; 
       
  2857 	else
       
  2858 	if(iMimeHeader->ContentType().Compare(KImcvMessage)==0)
       
  2859 		iContentType=EMimeMessage;
       
  2860 	else
       
  2861 	if(iMimeHeader->ContentType().Compare(KImcvMultipart)==0)
       
  2862 		iContentType=EMimeMultipart; 
       
  2863 	else
       
  2864 	if(iMimeHeader->ContentType().Compare(KImcvImage)==0)
       
  2865 		iContentType=EMimeImage; 
       
  2866 	else
       
  2867 	if(iMimeHeader->ContentType().Compare(KImcvApplication)==0)
       
  2868 		iContentType=EMimeApplication; 
       
  2869 	else
       
  2870 	if(iMimeHeader->ContentType().Compare(KImcvAudio)==0)
       
  2871 		iContentType=EMimeAudio; 
       
  2872 	else
       
  2873 	if(iMimeHeader->ContentType().Compare(KImcvVideo)==0)
       
  2874 		iContentType=EMimeVideo; 
       
  2875 	else
       
  2876 		iContentType=EMimeUnknownContent; 
       
  2877 
       
  2878 	}
       
  2879 
       
  2880 
       
  2881 /**
       
  2882 ParseLineL()
       
  2883 
       
  2884 @param aSourceLine
       
  2885 */
       
  2886 void CLocalMimeParser::ParseLineL(const TDesC8& aSourceLine)
       
  2887 	{
       
  2888 	if(iMimeHeaderLine==NULL)
       
  2889 		{
       
  2890 		iMimeHeaderLine = HBufC8::NewL(aSourceLine.Length());
       
  2891 		*iMimeHeaderLine = aSourceLine;
       
  2892 		}
       
  2893 	
       
  2894 	iLex = *iMimeHeaderLine;
       
  2895 
       
  2896 	// find out whether the current line has anything to do with currently understood MIME Content tokens
       
  2897 	if(!iMimeHeaderLine->MatchF(KImcvMime) || !iMimeHeaderLine->MatchF(KImcvContent))
       
  2898 		{ 
       
  2899 		if(MatchAndRemoveToken(KImcvMimePrompt))
       
  2900 			DoMimeVersion();
       
  2901 		else if(MatchAndRemoveToken(KImcvContentType))
       
  2902 			DoContentTypeL();
       
  2903 		else if(MatchAndRemoveToken(KImcvContentLocation))
       
  2904 			DoContentLocationL();
       
  2905 		else if(MatchAndRemoveToken(KImcvContentTransferEncoding))
       
  2906 			DoEncodingL();
       
  2907 		else if(MatchAndRemoveToken(KImcvContentId))
       
  2908 			{
       
  2909 			RemoveSurroundingCharacters(KImcvLeftChevron, KImcvRightChevron, *iMimeHeaderLine);
       
  2910 			DoContentIdL();
       
  2911 			}
       
  2912 		else if(MatchAndRemoveToken(KImcvContentDescription))
       
  2913 			DoDescriptionL();
       
  2914 		else if(MatchAndRemoveToken(KImcvContentDisposition))
       
  2915 			DoDispositionL();
       
  2916 		else if(MatchAndRemoveToken(KImcvContentBase))
       
  2917 			DoContentBaseL();
       
  2918 		}
       
  2919 		
       
  2920 	delete iMimeHeaderLine;	// clean up and null pointer iff CompleteMimeHeader and no foldover append req'd
       
  2921 	iMimeHeaderLine=NULL;
       
  2922 	}
       
  2923 
       
  2924 
       
  2925 /**
       
  2926 DoMimeVersion()
       
  2927 */
       
  2928 void CLocalMimeParser::DoMimeVersion()
       
  2929 	{
       
  2930 	// extract the MIME version from a header line which we already know
       
  2931 	// has 'MIME-Version' start of it.
       
  2932 	if(MatchAndRemoveToken(KImcvMimeVersion))
       
  2933 		iCorrectMimeVersion = ETrue;
       
  2934 	}
       
  2935 
       
  2936 
       
  2937 /**
       
  2938 DoContentIdL()
       
  2939 */
       
  2940 void CLocalMimeParser::DoContentIdL()
       
  2941 	{
       
  2942 	iMimeHeader->SetContentIDL(iMimeHeaderLine->Des());
       
  2943 	if(iStartId && iStartId->CompareF(iMimeHeaderLine->Des())==KErrNone)
       
  2944 		iStartPart=ETrue;
       
  2945 	}
       
  2946 
       
  2947 
       
  2948 /**
       
  2949 DoContentLocationL()
       
  2950 */
       
  2951 void CLocalMimeParser::DoContentLocationL()
       
  2952 	{
       
  2953 	TInt len = (*iMimeHeaderLine).Length();
       
  2954 	if (len == 0)
       
  2955 		return;
       
  2956 			
       
  2957 	RemoveSurroundingCharacters(KImcvQuote, KImcvQuote, *iMimeHeaderLine);
       
  2958 
       
  2959 	HBufC16* locationBuf = HBufC16::NewL( len );
       
  2960 	CleanupStack::PushL(locationBuf);
       
  2961 	TPtr locationPtr(locationBuf->Des());
       
  2962 	iImRecvConvert.iHeaderConverter->DecodeHeaderFieldL( iMimeHeaderLine->Des(), locationPtr);
       
  2963 	iMimeHeader->SetContentLocationL(locationPtr);
       
  2964 	CleanupStack::PopAndDestroy(); // locationBuf
       
  2965 	}
       
  2966 
       
  2967 
       
  2968 /**
       
  2969 DoContentBaseL()
       
  2970 */
       
  2971 void CLocalMimeParser::DoContentBaseL()
       
  2972 	{
       
  2973 	RemoveSurroundingCharacters(KImcvQuote, KImcvQuote, *iMimeHeaderLine);
       
  2974 	iMimeHeader->SetContentBaseL(iMimeHeaderLine->Des());
       
  2975 	}
       
  2976 
       
  2977 
       
  2978 /**
       
  2979 DoAttachmentTypeL()
       
  2980 */
       
  2981 void CLocalMimeParser::DoAttachmentTypeL()
       
  2982 	{
       
  2983 	iImRecvConvert.iEntryType = CLocalImRecvConvert::EAttachmentEntry;
       
  2984 	iImRecvConvert.iCurrentPartIsRichText = EFalse;	
       
  2985 
       
  2986 	if(MatchAndRemoveToken(KImcvForwardSlash))
       
  2987 		{
       
  2988 		if(MatchAndRemoveToken(KImcvBmp))
       
  2989 			{
       
  2990 			iMimeHeader->SetContentSubTypeL(KImcvBmp);
       
  2991 			}
       
  2992 		else
       
  2993 		if(MatchAndRemoveToken(KImcvGif))
       
  2994 			{
       
  2995 			iMimeHeader->SetContentSubTypeL(KImcvGif);
       
  2996 			}
       
  2997 		else
       
  2998 		if(MatchAndRemoveToken(KImcvJpeg))
       
  2999 			{
       
  3000 			iMimeHeader->SetContentSubTypeL(KImcvJpeg);
       
  3001 			}
       
  3002 		else
       
  3003 		if(MatchAndRemoveToken(KImcvTiff))
       
  3004 			{
       
  3005 			iMimeHeader->SetContentSubTypeL(KImcvTiff);
       
  3006 			}
       
  3007 		else
       
  3008 		if(MatchAndRemoveToken(KImcvWav))
       
  3009 			{
       
  3010 			iMimeHeader->SetContentSubTypeL(KImcvWav);
       
  3011 			}
       
  3012 		else
       
  3013 		if(MatchAndRemoveToken(KImcvZip))
       
  3014 			{
       
  3015 			iMimeHeader->SetContentSubTypeL(KImcvZip);
       
  3016 			}
       
  3017 		else
       
  3018 		if(MatchAndRemoveToken(KImcvOctetStream))
       
  3019 			{
       
  3020 			iMimeHeader->SetContentSubTypeL(KImcvOctetStream);
       
  3021 			}
       
  3022 		else
       
  3023 		if(MatchAndRemoveToken(KImcvExe))
       
  3024 			{
       
  3025 			iMimeHeader->SetContentSubTypeL(KImcvExe);
       
  3026 			}
       
  3027 		else
       
  3028 		if(MatchAndRemoveToken(KImcvCmd))
       
  3029 			{
       
  3030 			iMimeHeader->SetContentSubTypeL(KImcvCmd);
       
  3031 			}
       
  3032 		else
       
  3033 		if(MatchAndRemoveToken(KTImcvDrm))
       
  3034 			{ // added this to handle DRM files
       
  3035 			iMimeHeader->SetContentSubTypeL(KTImcvDrm);
       
  3036 			}
       
  3037 		}
       
  3038 	}
       
  3039 
       
  3040 
       
  3041 /**
       
  3042 DoMessageTypeL()
       
  3043 */
       
  3044 void CLocalMimeParser::DoMessageTypeL()
       
  3045 	{
       
  3046 	iImRecvConvert.iEntryType = CLocalImRecvConvert::EMessageEntry;
       
  3047 	iImRecvConvert.iEmailPart = CLocalImRecvConvert::KParentPart;
       
  3048 	
       
  3049 	iContentType=EMimeMessage; 
       
  3050 	iMimeHeader->SetContentTypeL(KImcvMessage);
       
  3051 
       
  3052 	if(MatchAndRemoveToken(KImcvForwardSlash))
       
  3053 		{
       
  3054 		if(MatchAndRemoveToken(KImcvRfc822))
       
  3055 			{
       
  3056 			//iMessageFolderType=EFolderTypeRFC822;
       
  3057 			iMimeHeader->SetContentSubTypeL(KImcvRfc822);
       
  3058 			}
       
  3059 		else if(MatchAndRemoveToken(KImcvExternal))
       
  3060 			{
       
  3061 			iMessageFolderType=EFolderTypeExternal;
       
  3062 			iMimeHeader->SetContentSubTypeL(KImcvExternal);
       
  3063 			}
       
  3064 		else if(MatchAndRemoveToken(KImcvPartial))
       
  3065 			{
       
  3066 			iMessageFolderType=EFolderTypePartial;
       
  3067 			iMimeHeader->SetContentSubTypeL(KImcvPartial);
       
  3068 			}
       
  3069 		else if(MatchAndRemoveToken(KImcvDeliveryStatus))
       
  3070 			{
       
  3071 			// We do not process this part. So store as text.
       
  3072 			iMimeHeader->SetContentSubTypeL(KImcvDeliveryStatus);
       
  3073 			iImRecvConvert.iEntryType = CLocalImRecvConvert::EAttachmentEntry;
       
  3074 			iImRecvConvert.iEmailPart = CLocalImRecvConvert::KNoPart;
       
  3075 			iContentType=EMimeUnknownContent; 
       
  3076 			iImRecvConvert.iCurrentPartIsRichText=EFalse;
       
  3077 			iImRecvConvert.iAttachmentName.Copy(KImcvDeliveryStatus);
       
  3078 			iImRecvConvert.iAttachmentName.Append(KTextExtension);
       
  3079 			}
       
  3080 		else
       
  3081 			{
       
  3082 			iMessageFolderType=EFolderTypeUnknown;
       
  3083 			iMimeHeader->SetContentSubTypeL(KImcvUnknown);
       
  3084 			}
       
  3085 		}	
       
  3086 	}
       
  3087 
       
  3088 
       
  3089 /**
       
  3090 DoMultipartTypeForNonMIMEL()
       
  3091 */
       
  3092 void CLocalMimeParser::DoMultipartTypeForNonMIMEL()
       
  3093 	{
       
  3094 	ResetForNewEntry();
       
  3095 	iMessageFolderType=EFolderTypeMixed;
       
  3096 	iMimeHeader->SetContentTypeL(KImcvMultipart);
       
  3097 	iMimeHeader->SetContentSubTypeL(KImcvMixed);
       
  3098 	}
       
  3099 
       
  3100 
       
  3101 /**
       
  3102 DoMultipartTypeL()
       
  3103 */
       
  3104 void CLocalMimeParser::DoMultipartTypeL()
       
  3105 	{
       
  3106 	iImRecvConvert.iEntryType = CLocalImRecvConvert::EFolderEntry;
       
  3107 	iImRecvConvert.iEmailPart = CLocalImRecvConvert::KMultiPart;
       
  3108 	
       
  3109 	iContentType=EMimeMultipart;
       
  3110 	iMimeHeader->SetContentTypeL(KImcvMultipart);
       
  3111 
       
  3112 	if(MatchAndRemoveToken(KImcvForwardSlash))
       
  3113 		{
       
  3114 		if(MatchAndRemoveToken(KImcvMixed))
       
  3115 			{
       
  3116 			iMessageFolderType=EFolderTypeMixed;
       
  3117 			iMimeHeader->SetContentSubTypeL(KImcvMixed);
       
  3118 			}
       
  3119 		else if(MatchAndRemoveToken(KImcvRelated))
       
  3120 			{
       
  3121 			iMessageFolderType=EFolderTypeRelated;
       
  3122 			iMimeHeader->SetContentSubTypeL(KImcvRelated);
       
  3123 			}
       
  3124 		else if(MatchAndRemoveToken(KImcvAlternative))
       
  3125 			{
       
  3126 			iMessageFolderType=EFolderTypeAlternative;
       
  3127 			iMimeHeader->SetContentSubTypeL(KImcvAlternative);
       
  3128 			}
       
  3129 		else if(MatchAndRemoveToken(KImcvEncrypted))
       
  3130 			{
       
  3131 //	Add this when Encryption is handled iMessageFolderType=EFolderTypeEncrypted;
       
  3132 			iMimeHeader->SetContentSubTypeL(KImcvEncrypted);
       
  3133 			}
       
  3134 		else if(MatchAndRemoveToken(KImcvParallel))
       
  3135 			{
       
  3136 			iMessageFolderType=EFolderTypeParallel;
       
  3137 			iMimeHeader->SetContentSubTypeL(KImcvParallel);
       
  3138 			}
       
  3139 		else if(MatchAndRemoveToken(KImcvDigest))
       
  3140 			{
       
  3141 			iMessageFolderType=EFolderTypeDigest;
       
  3142 			iMimeHeader->SetContentSubTypeL(KImcvDigest);
       
  3143 			isMessageDigest=ETrue;
       
  3144 			}
       
  3145 		else if(MatchAndRemoveToken(KImcvSigned))
       
  3146 			{
       
  3147 //	Add this when Signed is handled	iMessageFolderType=EFolderTypeSigned;
       
  3148 			iMimeHeader->SetContentSubTypeL(KImcvSigned);
       
  3149 			}
       
  3150 		else if(MatchAndRemoveToken(KImcvReport))
       
  3151 			{
       
  3152 			iMimeHeader->SetContentSubTypeL(KImcvReport);
       
  3153 			}
       
  3154 		else
       
  3155 			{
       
  3156 			iMessageFolderType=EFolderTypeUnknown;
       
  3157 			iMimeHeader->SetContentSubTypeL(KImcvUnknown);
       
  3158 			}
       
  3159 		}
       
  3160 
       
  3161 	if (iMessageFolderType==EFolderTypeRelated)
       
  3162 		iImRecvConvert.iParent->At(0).iFolder=iMessageFolderType; 
       
  3163 
       
  3164 	// Find any parameters specific to a Multipart content type	
       
  3165 
       
  3166 	HBufC8* paramValue = NULL;
       
  3167 
       
  3168 	// Extracts the boundary string
       
  3169 
       
  3170 	ExtractParameterInfoL(KImcvBoundary, paramValue);
       
  3171 	if( paramValue!=NULL ) 
       
  3172 		{
       
  3173 		CleanupStack::PushL(paramValue);
       
  3174 		iBoundaryFound = ETrue;
       
  3175 		iImRecvConvert.iEmailPart = CLocalImRecvConvert::KMultiPart;
       
  3176 		SetBoundaryL(*paramValue);
       
  3177 		CleanupStack::PopAndDestroy(paramValue);
       
  3178 		}
       
  3179 
       
  3180 	// Extracts start ID if it has been defined;
       
  3181 
       
  3182 	ExtractParameterInfoL(KImcvStartPart, paramValue);
       
  3183 	if( paramValue!=NULL )
       
  3184 		{
       
  3185 		delete iStartId;
       
  3186 		iStartId=NULL;
       
  3187 		iStartId = paramValue;
       
  3188 		}
       
  3189 	}
       
  3190 
       
  3191 
       
  3192 /**
       
  3193 DoTextTypeL()
       
  3194 */
       
  3195 void CLocalMimeParser::DoTextTypeL()
       
  3196 	{
       
  3197 	HBufC8* paramValue = NULL;
       
  3198 	
       
  3199 	iImRecvConvert.iEntryType = CLocalImRecvConvert::ETextEntry;
       
  3200 	iContentType=EMimeText;		
       
  3201 	iMimeHeader->SetContentTypeL(KImcvText);
       
  3202 
       
  3203 	if(MatchAndRemoveToken(KImcvForwardSlash))
       
  3204 		{
       
  3205 		if(MatchAndRemoveToken(KImcvPlain))
       
  3206 			iMimeHeader->SetContentSubTypeL(KImcvPlain);
       
  3207 		else
       
  3208 		if(MatchAndRemoveToken(KImcvHtml))
       
  3209 			{
       
  3210 			iMimeHeader->SetContentSubTypeL(KImcvHtml);
       
  3211 			iImRecvConvert.iEntryType = CLocalImRecvConvert::EHtmlEntry;
       
  3212 			iImRecvConvert.iCurrentPartIsRichText = EFalse;	
       
  3213 			}
       
  3214 		else
       
  3215 		if(MatchAndRemoveToken(KImcvDirectory))
       
  3216 			{
       
  3217 			iMimeHeader->SetContentSubTypeL(KImcvDirectory);
       
  3218 			iMimeHeader->ContentTypeParams().AppendL(KImcvProfile);
       
  3219 			ExtractParameterInfoL(KImcvProfile, paramValue);
       
  3220 			// Assume at right context, the email message, not attachment.
       
  3221 			
       
  3222 			iMessageFolderType=EFolderTypeDirectory;
       
  3223 			if( paramValue!=NULL )
       
  3224 				{
       
  3225 				CleanupStack::PushL(paramValue);
       
  3226 				iMimeHeader->ContentTypeParams().AppendL(*paramValue);
       
  3227 				if(paramValue->MatchF(KImcvVCard) == 0)
       
  3228 					{
       
  3229 					iVCard=ETrue;
       
  3230 					}
       
  3231 				CleanupStack::PopAndDestroy(paramValue);
       
  3232 				}
       
  3233 			}
       
  3234 		if(MatchAndRemoveToken(KImcvVCalender))
       
  3235 			iVCalendar=ETrue;
       
  3236 
       
  3237 		// Extract the charset value, 
       
  3238 
       
  3239 		ExtractParameterInfoL(KImcvCharset, paramValue);
       
  3240 
       
  3241 		if(paramValue!=NULL)
       
  3242 			{
       
  3243 			CleanupStack::PushL(paramValue);
       
  3244 			// check if at top level header or Mime part header
       
  3245 
       
  3246 			TUint charsetUid = iImRecvConvert.CharacterConverter().GetMimeCharsetUidL(*paramValue); 
       
  3247 			if(iImRecvConvert.NotFinishedRfc822Header() == EFalse)
       
  3248 				iCharset=charsetUid;
       
  3249 
       
  3250 			// Store in CMimeHeader::iContentTypeParams
       
  3251 			iMimeHeader->ContentTypeParams().AppendL(KImcvCharset);
       
  3252 			iMimeHeader->ContentTypeParams().AppendL(*paramValue);
       
  3253 			CleanupStack::PopAndDestroy(paramValue);
       
  3254 
       
  3255 			if (!iImRecvConvert.CharacterConverter().PrepareToConvertToFromOurCharsetL(charsetUid))
       
  3256 				charsetUid=KUidMsvCharsetNone;
       
  3257 			iMimeHeader->SetMimeCharset(charsetUid);
       
  3258 			}
       
  3259 		else
       
  3260 			iMimeHeader->SetMimeCharset(iDefaultCharset);
       
  3261 		}
       
  3262 	}
       
  3263 
       
  3264 
       
  3265 /**
       
  3266 DoContentTypeL()
       
  3267 */
       
  3268 void CLocalMimeParser::DoContentTypeL()
       
  3269 	{
       
  3270 	RemoveSurroundingCharacters(KImcvLeftChevron, KImcvRightChevron, *iMimeHeaderLine);
       
  3271 
       
  3272 	if(MatchAndRemoveToken(KImcvText))
       
  3273 		DoTextTypeL();
       
  3274 	else
       
  3275 	if(MatchAndRemoveToken(KImcvMultipart))
       
  3276 		DoMultipartTypeL();
       
  3277 	else
       
  3278 	if(MatchAndRemoveToken(KImcvMessage))
       
  3279 		DoMessageTypeL();
       
  3280 	else
       
  3281 	if(MatchAndRemoveToken(KImcvImage))
       
  3282 		{	
       
  3283 		iContentType=EMimeImage; 
       
  3284 		iMimeHeader->SetContentTypeL(KImcvImage);
       
  3285 		DoAttachmentTypeL();
       
  3286 		}
       
  3287 	else
       
  3288 	if(MatchAndRemoveToken(KImcvApplication))
       
  3289 		{
       
  3290 		iContentType=EMimeApplication; 
       
  3291 		iMimeHeader->SetContentTypeL(KImcvApplication);
       
  3292 		DoAttachmentTypeL();
       
  3293 		}
       
  3294 	else
       
  3295 	if(MatchAndRemoveToken(KImcvAudio))
       
  3296 		{
       
  3297 		iContentType=EMimeAudio; 
       
  3298 		iMimeHeader->SetContentTypeL(KImcvAudio);
       
  3299 		DoAttachmentTypeL();
       
  3300 		}
       
  3301 	else
       
  3302 	if(MatchAndRemoveToken(KImcvVideo))
       
  3303 		{
       
  3304 		iContentType=EMimeVideo; 
       
  3305 		iMimeHeader->SetContentTypeL(KImcvVideo);
       
  3306 		DoAttachmentTypeL();
       
  3307 		}
       
  3308 	else
       
  3309 		{
       
  3310 		iContentType=EMimeUnknownContent; 
       
  3311 		iMimeHeader->SetContentTypeL(KImcvUnknown);
       
  3312 		}
       
  3313 
       
  3314 	// Extract the filename if it exists
       
  3315 	HBufC* paramStore = HBufC::NewLC(MaxMimeParameterValueLength);
       
  3316 	HBufC8* paramStore8 = HBufC8::NewLC(KMimeEncodedParameterSize);
       
  3317 	TPtr paramValue(paramStore->Des());
       
  3318 	TPtr8 paramValue8(paramStore8->Des());
       
  3319 
       
  3320 	ExtractParameterInfoL(KImcvMimeTypeName, paramValue,paramValue8);
       
  3321 	if(paramValue.Length())
       
  3322 		{
       
  3323 		iMimeHeader->ContentTypeParams().AppendL(KImcvMimeTypeName);
       
  3324 		iMimeHeader->ContentTypeParams().AppendL(paramValue8);
       
  3325 		iImRecvConvert.SetAttachmentName(paramValue);
       
  3326 		}
       
  3327 	
       
  3328 	CleanupStack::PopAndDestroy(2,paramStore); 
       
  3329 	}
       
  3330 
       
  3331 
       
  3332 /**
       
  3333 DoEncodingL()
       
  3334 */
       
  3335 void CLocalMimeParser::DoEncodingL()
       
  3336 	{
       
  3337 	iMimeHeader->SetContentTransferEncodingL(*iMimeHeaderLine);
       
  3338 
       
  3339 	switch ((*iMimeHeaderLine)[0])
       
  3340 		{
       
  3341 		case '7': // 7bit
       
  3342 			iContentEncoding = EEncodingType7Bit;
       
  3343 			break;
       
  3344 		case '8': // 8bit
       
  3345 			iContentEncoding = EEncodingType8Bit;
       
  3346 			break;
       
  3347 		case 'q': // quoted-printable
       
  3348 		case 'Q': 
       
  3349 			iContentEncoding = EEncodingTypeQP;
       
  3350 			break;
       
  3351 		case 'b': // binary or base64
       
  3352 		case 'B':
       
  3353 			iContentEncoding = ((*iMimeHeaderLine)[1] == 'i' || (*iMimeHeaderLine)[1] == 'I' ? EEncodingTypeBinary : EEncodingTypeBASE64);
       
  3354 			break;
       
  3355 		case 'x': //in order to support UU encoded within a MIME message
       
  3356 		case 'X':
       
  3357 			iContentEncoding = ((*iMimeHeaderLine).FindF(KImcvXUUString)==KErrNotFound ? EEncodingTypeUnknown : EEncodingTypeUU);
       
  3358 			break;
       
  3359 		default:
       
  3360 			iContentEncoding = EEncodingTypeUnknown;
       
  3361 			break;
       
  3362 		}
       
  3363 	}
       
  3364 
       
  3365 
       
  3366 /**
       
  3367 DoDescriptionL()
       
  3368 */
       
  3369 void CLocalMimeParser::DoDescriptionL()
       
  3370 	{
       
  3371 	TPtrC8 marked(iMimeHeaderLine->Des());
       
  3372 	if (marked.Length()>KMaxFileName)
       
  3373 		marked.Set(marked.Left(KMaxFileName));
       
  3374 
       
  3375 	iContentDescription.Copy(marked);
       
  3376 
       
  3377 	// remove the CRLF
       
  3378 
       
  3379 	TInt length = iContentDescription.Length();
       
  3380 	if (length>2)
       
  3381 		{
       
  3382 		if (iContentDescription[length-2]==KImcvCR && iContentDescription[length-1]==KImcvLF)
       
  3383 			iContentDescription.SetLength(length-2);
       
  3384 		}
       
  3385 	iMimeHeader->SetContentDescriptionL(marked);
       
  3386 	}
       
  3387 
       
  3388 
       
  3389 /**
       
  3390 DoDispositionL()
       
  3391 */
       
  3392 void CLocalMimeParser::DoDispositionL()
       
  3393 	{
       
  3394 	TBool inLine = EFalse;
       
  3395 	if(MatchAndRemoveToken(KImcvAttachment))
       
  3396 		{
       
  3397 		iMimeHeader->SetContentDispositionL(KImcvAttachment);
       
  3398 		if (iMimeHeader->ContentSubType()!=KImcvRfc822)
       
  3399 			{
       
  3400 			iImRecvConvert.iCurrentPartIsRichText = EFalse;	
       
  3401 			}
       
  3402 		if (iImRecvConvert.iEntryType!=CLocalImRecvConvert::EMessageEntry)
       
  3403 			{
       
  3404 			iImRecvConvert.iEntryType = CLocalImRecvConvert::EAttachmentEntry;
       
  3405 			}
       
  3406 		}
       
  3407 	else if(MatchAndRemoveToken(KImcvInline))
       
  3408 		inLine = ETrue;
       
  3409 
       
  3410 	// Extract the filename if it exists, unless we already have a name for it	
       
  3411 	if(!iImRecvConvert.iAttachmentName.Length())
       
  3412 		{
       
  3413 		HBufC* paramStore = HBufC::NewLC(KHeaderBufferLength);
       
  3414 		TPtr paramValue(paramStore->Des());
       
  3415 		HBufC8* paramStore8 = HBufC8::NewLC(KMimeEncodedParameterSize);
       
  3416 		TPtr8 paramValue8(paramStore8->Des());
       
  3417 
       
  3418 		ExtractParameterInfoL(KImcvMimeDispositionFilename, paramValue,paramValue8);
       
  3419 		if(paramValue.Length())
       
  3420 			{
       
  3421 			iMimeHeader->ContentTypeParams().AppendL(KImcvMimeDispositionFilename);
       
  3422 			iMimeHeader->ContentTypeParams().AppendL(paramValue8);
       
  3423 			iImRecvConvert.SetAttachmentName(paramValue);
       
  3424 			}
       
  3425 
       
  3426 		CleanupStack::PopAndDestroy(2,paramStore); // paramStore, paramStore8
       
  3427 		}
       
  3428 
       
  3429 		if(inLine)
       
  3430  		{
       
  3431  		// Content Disposition set to inline
       
  3432  		if (iImRecvConvert.iAttachmentName.Length())
       
  3433  			// filename exists
       
  3434  			{
       
  3435  			iMimeHeader->SetContentDispositionL(KImcvAttachment);
       
  3436  			iImRecvConvert.iCurrentPartIsRichText = EFalse;	
       
  3437 			if (iImRecvConvert.iEntryType!=CLocalImRecvConvert::EMessageEntry)
       
  3438  				{
       
  3439  				iImRecvConvert.iEntryType = CLocalImRecvConvert::EAttachmentEntry;
       
  3440  				}
       
  3441  			}
       
  3442  		else
       
  3443  			iMimeHeader->SetContentDispositionL(KImcvInline);
       
  3444  		}
       
  3445 	}
       
  3446 
       
  3447 
       
  3448 /**
       
  3449 ContentSubType()
       
  3450 
       
  3451 @return
       
  3452 */  
       
  3453 TPtrC8 CLocalMimeParser::ContentSubType() const  
       
  3454 	{
       
  3455 	return iMimeHeader->ContentSubType();;
       
  3456 	}
       
  3457 
       
  3458 
       
  3459 /**
       
  3460 VCard()
       
  3461 
       
  3462 @return
       
  3463 */  
       
  3464 TBool CLocalMimeParser::VCard() const  
       
  3465 	{
       
  3466 	return iVCard;
       
  3467 	}
       
  3468 
       
  3469 
       
  3470 /**
       
  3471 VCalendar()
       
  3472 
       
  3473 @return
       
  3474 */  
       
  3475 TBool CLocalMimeParser::VCalendar() const  	
       
  3476 	{
       
  3477 	return iVCalendar;
       
  3478 	}
       
  3479 
       
  3480 
       
  3481 /**
       
  3482 StartPart()
       
  3483 
       
  3484 @return
       
  3485 */  
       
  3486 TBool CLocalMimeParser::StartPart() const  
       
  3487 	{
       
  3488 	return iStartPart;
       
  3489 	}
       
  3490 
       
  3491 
       
  3492 /**
       
  3493 MessageFolderType()
       
  3494 
       
  3495 @return
       
  3496 */  
       
  3497 TImEmailFolderType CLocalMimeParser::MessageFolderType() const  
       
  3498 	{
       
  3499 	return iMessageFolderType;
       
  3500 	}
       
  3501 
       
  3502 
       
  3503 /**
       
  3504 SetMessageFolderType()
       
  3505 
       
  3506 @param aFolderType
       
  3507 */  
       
  3508 void CLocalMimeParser::SetMessageFolderType(TImEmailFolderType aFolderType)  
       
  3509 	{
       
  3510 	iMessageFolderType=aFolderType;
       
  3511 	}
       
  3512 
       
  3513 
       
  3514 /**
       
  3515 SetBoundaryL()
       
  3516 
       
  3517 @param aBoundaryText
       
  3518 */  
       
  3519 void CLocalMimeParser::SetBoundaryL(const TDesC8& aBoundaryText)  
       
  3520 	{
       
  3521 	TBuf8<KMaxBoundaryTextLength+2> tempBoundary(KImcvMimeBoundaryStartEnd);
       
  3522 	// From RFC 1521, (Boundaries) must be no longer than 70 characters.
       
  3523 	// Including beginning and end "--" 
       
  3524 	if (aBoundaryText.Length()>70)
       
  3525 		tempBoundary.Append(aBoundaryText.Left(70));
       
  3526 	else
       
  3527 		tempBoundary.Append(aBoundaryText);
       
  3528 	iBoundaryText->AppendL(tempBoundary);
       
  3529 
       
  3530 	iBoundaryIndex = iBoundaryText->MdcaCount(); //iBoundaryIndex stores a count value not the index here
       
  3531 	iBoundaryIndex = (iBoundaryIndex)? --iBoundaryIndex: 0;
       
  3532 	iBoundaryLength = iBoundaryText->MdcaPoint(iBoundaryIndex).Length();
       
  3533 	}
       
  3534 
       
  3535 
       
  3536 /**
       
  3537 IsBoundary()
       
  3538 
       
  3539 @param aSourceLine
       
  3540  @return
       
  3541 */
       
  3542 TBool CLocalMimeParser::IsBoundary(const TDesC8& aSourceLine)
       
  3543 	{
       
  3544 	if(iBoundaryText->MdcaCount())
       
  3545 		{
       
  3546 		TInt found = 0;
       
  3547 		TInt aLineLength = aSourceLine.Length();
       
  3548 		TInt compareLength = aLineLength > iBoundaryLength ? iBoundaryLength : aLineLength;
       
  3549 		TPtrC8 tempSourceLine(aSourceLine.Ptr(), compareLength);
       
  3550 	
       
  3551 		TInt error = iBoundaryText->Find(tempSourceLine, found, ECmpNormal);
       
  3552 
       
  3553 		if(error||(!iBoundaryLength))
       
  3554 			return KBoundaryNotFound;
       
  3555 	
       
  3556 		// The following code is executed only if aSourceLine is a boundary
       
  3557 		if(found != iBoundaryIndex)
       
  3558 			{
       
  3559 			iReceiveError = (iReceiveError)? iReceiveError: KBoundaryError;
       
  3560 			iBoundaryIndex = found;
       
  3561 			iBoundaryText->Delete(found++);
       
  3562 			}
       
  3563 	
       
  3564 		if(aLineLength >= iBoundaryLength+4) // allow for CRLF & then check for the double hyphen
       
  3565 			{
       
  3566 			if((aSourceLine[iBoundaryLength] == KImcvHyphen) && (aSourceLine[iBoundaryLength+1] == KImcvHyphen))
       
  3567 				iTerminatingBoundary = ETrue; // this is a terminating boundary
       
  3568 			}
       
  3569 		else
       
  3570 			iTerminatingBoundary = EFalse;
       
  3571 	
       
  3572 		return KBoundaryFound;
       
  3573 		}
       
  3574 	
       
  3575 	return KBoundaryNotFound;
       
  3576 	}
       
  3577 
       
  3578 
       
  3579 /**
       
  3580 RemoveBoundary()
       
  3581 */
       
  3582 void CLocalMimeParser::RemoveBoundary()
       
  3583 	{
       
  3584 	iBoundaryText->Delete(iBoundaryIndex);
       
  3585 	if(iBoundaryText->MdcaCount())
       
  3586 		{
       
  3587 		iBoundaryIndex = iBoundaryText->MdcaCount(); //iBoundaryIndex stores a count value not the index here
       
  3588 	
       
  3589 		iBoundaryIndex = (iBoundaryIndex)? --iBoundaryIndex: 0;
       
  3590 		iBoundaryLength = iBoundaryText->MdcaPoint(iBoundaryIndex).Length();
       
  3591 		}
       
  3592 	}
       
  3593 
       
  3594 
       
  3595 /**
       
  3596 MatchAndRemoveToken()
       
  3597 
       
  3598 @param aToken
       
  3599 @return
       
  3600 */
       
  3601 TBool CLocalMimeParser::MatchAndRemoveToken( const TDesC8& aToken )
       
  3602 	{
       
  3603 	TInt comparison;
       
  3604 	TInt tokenLength = aToken.Length();
       
  3605 	TInt desLength = (*iMimeHeaderLine).Length();
       
  3606 	TInt compareLength = tokenLength > desLength ? desLength : tokenLength;
       
  3607 	TPtrC8 left((*iMimeHeaderLine).Left(compareLength));
       
  3608 	
       
  3609 	// now see whether the current line contains the search string
       
  3610 	comparison = left.CompareF(aToken);
       
  3611 	if (!comparison)
       
  3612 		{
       
  3613 		// found the match string at the start of the output line, so remove it
       
  3614 		iMimeFieldsExist=ETrue;
       
  3615 		isMime=ETrue;
       
  3616 		// get rid of any whitespace betweebn the tag and the data while we have a chance
       
  3617 		TInt whitespaceLength=0;
       
  3618 		TInt maxLength=desLength-tokenLength;
       
  3619 		const TUint8* ptr = (*iMimeHeaderLine).Ptr();
       
  3620 		while ( whitespaceLength <= maxLength && (ptr[tokenLength+whitespaceLength] == KImcvSP || ptr[tokenLength+whitespaceLength] == KImcvTab) )
       
  3621 			whitespaceLength++;
       
  3622 		iMimeHeaderLine->Des().Delete(0, tokenLength+whitespaceLength);
       
  3623 
       
  3624 		// Reset iLex, so its length is updated.
       
  3625 		iLex = *iMimeHeaderLine;
       
  3626 		}
       
  3627 	return (comparison==0);
       
  3628 	}
       
  3629 
       
  3630 
       
  3631 /**
       
  3632 IsSpecialChar()
       
  3633 
       
  3634 @param aChar
       
  3635 @return
       
  3636 */
       
  3637 TBool CLocalMimeParser::IsSpecialChar( const TUint8 aChar )
       
  3638 	{
       
  3639 	return (aChar == '(' || aChar == ')' || aChar == '<' || aChar == '>' || aChar == '@' 
       
  3640 		 || aChar == ',' || aChar == ';' || aChar == ':' || aChar == '\\'|| aChar == '"' 
       
  3641 		 || aChar == '/' || aChar == '[' || aChar == ']' || aChar == '?' || aChar == '=');
       
  3642 	}
       
  3643 
       
  3644 
       
  3645 /**
       
  3646 ExtractParameterInfoL()
       
  3647 Implicitly the parameter ASSUMED TO BE is not encoded as return parameter, rBuffer,
       
  3648 is 8 bit. iLex should currently be pointing at the space after content-type description.
       
  3649 
       
  3650 @param aTag
       
  3651 @param rBuffer
       
  3652 */
       
  3653 void CLocalMimeParser::ExtractParameterInfoL(const TDesC8& aTag, HBufC8*& rBuffer)
       
  3654 	{	
       
  3655 	rBuffer = NULL;
       
  3656 
       
  3657 	TLexMark8 mark;
       
  3658 	TInt offset;
       
  3659 
       
  3660 	if( (offset=iLex.Remainder().FindF(aTag)) != KErrNotFound )
       
  3661 		{
       
  3662 		// move past the tag	
       
  3663 		iLex.Inc(offset+aTag.Length());
       
  3664 
       
  3665 		// Default : no charset info or folding
       
  3666 		// move forward to the start of the boundary string itself.
       
  3667 
       
  3668 		while (iLex.Peek() != KImcvEquals  && !iLex.Eos())
       
  3669 			iLex.Inc(); 
       
  3670 
       
  3671 		TPtrC8 paramBuffer(ExtractParameterString(mark));
       
  3672 		if( paramBuffer.Length() > 0 )
       
  3673 			{
       
  3674 			rBuffer = paramBuffer.AllocL();
       
  3675 			}
       
  3676 		}
       
  3677 	}
       
  3678 
       
  3679 
       
  3680 /**
       
  3681 ExtractParameterInfoL()
       
  3682 iLex should currently be pointing at the space after content-type description.
       
  3683 
       
  3684 @param aTag
       
  3685 @param rBuffer
       
  3686 @param rBuffer8
       
  3687 */
       
  3688 void CLocalMimeParser::ExtractParameterInfoL(const TDesC8& aTag, TDes16& rBuffer, TDes8& rBuffer8)
       
  3689 	{
       
  3690 	TInt offset;
       
  3691 
       
  3692 	rBuffer.Copy(KNullDesC);
       
  3693 
       
  3694 	// we need to extract the <aTag> text from the same line
       
  3695 	// iLex should currently be pointing at the space after content-type description
       
  3696 
       
  3697 	if( (offset=iLex.Remainder().FindF(aTag))!=KErrNotFound )
       
  3698 		{
       
  3699 		// Check which type of encoding present.
       
  3700 
       
  3701 		TLexMark8 initMark;
       
  3702 		iLex.Mark(initMark);
       
  3703 		TLexMark8 mark;
       
  3704 		iLex.Inc(offset+aTag.Length()); 	// move past the tag
       
  3705 
       
  3706 		const TPtrC8 param = ExtractParameterString(mark);
       
  3707 
       
  3708 		rBuffer8.Copy(param);
       
  3709 
       
  3710 		if ( ParseRfc2047ParameterInfoL(param, rBuffer) == EFalse )
       
  3711 			{
       
  3712 			iLex.UnGetToMark(initMark);
       
  3713 			ParseRfc2231ParameterInfoL(aTag, rBuffer, offset );
       
  3714 			}
       
  3715 		}
       
  3716 	}
       
  3717 
       
  3718 
       
  3719 /**
       
  3720 ParseRfc2047ParameterInfoL()
       
  3721 Detect encoding of form =?charset?Q?" Text "?=
       
  3722 
       
  3723 @param aParam
       
  3724 @param rBuffer
       
  3725 @return
       
  3726 */
       
  3727 TBool CLocalMimeParser::ParseRfc2047ParameterInfoL(const TDesC8& aParam, TDes& rBuffer)
       
  3728 	{
       
  3729 	TBool parameterPresent = EFalse;
       
  3730 
       
  3731 	// Check for =? somewhere in text.
       
  3732 
       
  3733 	if ( aParam.Find(KImcvEncodedWordStart) != KErrNotFound )
       
  3734 		{
       
  3735 		// Make assumption that '=?' appearing in parameter means 
       
  3736 		//it is part of encoding
       
  3737 	
       
  3738 		parameterPresent = ETrue;
       
  3739 		iImRecvConvert.iHeaderConverter->DecodeHeaderFieldL(aParam, rBuffer);
       
  3740 		}
       
  3741 	return parameterPresent;
       
  3742 	}
       
  3743 
       
  3744 
       
  3745 /**
       
  3746 ParseRfc2231ParameterInfoL()
       
  3747 For extracting parameter data following Mime header fields, in the format
       
  3748 *(;tag=data). As specified in rfc2231
       
  3749 Assumes parameter data seperated by ';'
       
  3750 Takes tag(name) of parameter as input, returning a descriptor with the data
       
  3751 
       
  3752 @param aTag
       
  3753 @param rBuffer
       
  3754 @param aOffset
       
  3755 @return
       
  3756 */
       
  3757 TBool CLocalMimeParser::ParseRfc2231ParameterInfoL(const TDesC8& aTag, TDes& rBuffer, TInt aOffset)
       
  3758 	{
       
  3759 	TBool parameterPresent = ETrue;
       
  3760 
       
  3761 	// For storing extracted parameter information
       
  3762 
       
  3763 	HBufC8* info = HBufC8::NewLC(KHeaderBufferLength);
       
  3764 
       
  3765 	// For storing information relating to parameter extraction/conversion
       
  3766 
       
  3767 	TInt count = 0;
       
  3768 
       
  3769 	TPtrC8 charset8;
       
  3770 	TPtrC8 language8;
       
  3771 	
       
  3772 	// Following rfc 2231, parameter may be encoded & folded in the following way
       
  3773 	//
       
  3774 	// <name>*0*=us-ascii'en'<encoded data>
       
  3775 	// <name>*1*=< more encoded data>
       
  3776 	// <name>*2=<unencoded info>
       
  3777 
       
  3778 	do 
       
  3779 		{
       
  3780 		// move past the tag	
       
  3781 		iLex.Inc(aOffset+aTag.Length());
       
  3782 
       
  3783 		if (iLex.Peek() != KImcvAny) 
       
  3784 			{
       
  3785 			// Default : no charset info or folding
       
  3786 			// move forward to the start of the boundary string itself
       
  3787 
       
  3788 			while (iLex.Peek() != KImcvEquals  && !iLex.Eos())
       
  3789 				iLex.Inc();
       
  3790 			}
       
  3791 		else	// *, Parameter is encoded
       
  3792 			{
       
  3793 			iLex.Inc(); // Past '*'
       
  3794 
       
  3795 			// If parameter folded :- need to get several bits of data and join together.
       
  3796 		
       
  3797 			if ( iLex.Peek()!=KImcvEquals) // Get Number
       
  3798 				{
       
  3799 				iLex.Mark(); // Beginnig of number
       
  3800 				iLex.Inc();
       
  3801 				while (iLex.Peek() != KImcvEquals && iLex.Peek() != KImcvAny && !iLex.Eos())
       
  3802 					iLex.Inc(); 
       
  3803 				TPtrC8 numPtr = iLex.MarkedToken();
       
  3804 				TLex8 lex(numPtr);
       
  3805 				lex.Val(count);  // Store number in count.
       
  3806 
       
  3807 				if (iLex.Peek() == KImcvAny)
       
  3808 					iLex.Inc(); // Past *
       
  3809 				}
       
  3810 
       
  3811 
       
  3812 			// Must get charset & language information etc..
       
  3813 
       
  3814 			if (!count)
       
  3815 				{
       
  3816 
       
  3817 				iLex.Inc(); // Past '='
       
  3818 
       
  3819 				if (iLex.Peek()==KImcvQuote)
       
  3820 					iLex.Inc(); 
       
  3821 
       
  3822 				// Extract CHARSET token
       
  3823 				iLex.Mark();
       
  3824 				while (iLex.Peek() != KImcvSingleQuote && !iLex.Eos())
       
  3825 					iLex.Inc(); 
       
  3826 				TPtrC8 marked = iLex.MarkedToken();
       
  3827 
       
  3828 				charset8.Set(marked );
       
  3829 				iLex.Inc(); // Past ' 
       
  3830 
       
  3831 				// Extract LANGUAGE token
       
  3832 				iLex.Mark();
       
  3833 				while (iLex.Peek() != KImcvSingleQuote && !iLex.Eos())
       
  3834 					iLex.Inc(); 
       
  3835 				TPtrC8 marked1 = iLex.MarkedToken();
       
  3836 				language8.Set(marked1);
       
  3837 				}
       
  3838 
       
  3839 			} // else, param encoded
       
  3840 				
       
  3841 		TLexMark8 mark;
       
  3842 		TPtrC8 param = ExtractParameterString(mark);
       
  3843 
       
  3844 		// Save parameter data
       
  3845 		TInt maxlen=info->Des().MaxLength();
       
  3846 		if ((*info).Length() + param.Length() > maxlen )
       
  3847 			{
       
  3848 			info = info->ReAllocL(maxlen + param.Length() + MaxMimeParameterValueLength);
       
  3849 		 CleanupStack::Pop();
       
  3850 			CleanupStack::PushL(info); 
       
  3851 			}
       
  3852 		info->Des().Append( param );
       
  3853 
       
  3854 
       
  3855 		} while( ( aOffset=iLex.Remainder().FindF(aTag))!=KErrNotFound );
       
  3856 
       
  3857 	TPtr8 infoPtr(info->Des());	
       
  3858 	
       
  3859 	DecodeRfc2231ParameterInfoL( infoPtr, rBuffer, charset8/*, language8*/ );
       
  3860 
       
  3861 	CleanupStack::PopAndDestroy(info); 
       
  3862 	return parameterPresent;
       
  3863 	}
       
  3864 
       
  3865 
       
  3866 /**
       
  3867 DecodeRfc2231ParameterInfoL()
       
  3868 
       
  3869 @param aInput
       
  3870 @param rBufOut
       
  3871 @param aCharset
       
  3872 @return
       
  3873 */
       
  3874 TBool CLocalMimeParser::DecodeRfc2231ParameterInfoL(TDes8& aInput, TDes& rBufOut, TPtrC8 aCharset/*, TPtrC8 aLanguage*/)
       
  3875 	{
       
  3876 	HBufC8* QPdecodedbuf = HBufC8::NewLC( aInput.Length() );
       
  3877 	TPtr8 ptr(QPdecodedbuf->Des());
       
  3878 
       
  3879 	iImRecvConvert.iQPCodec.SetQPChar(KImcvPercentSign);
       
  3880 	iImRecvConvert.iQPCodec.Decode( aInput, ptr);
       
  3881 	iImRecvConvert.iQPCodec.SetQPChar(KImcvEquals);
       
  3882 
       
  3883 	// Convert parameter, based on charset supplied.
       
  3884 	CImConvertCharconv& charconv = iImRecvConvert.CharacterConverter();
       
  3885 	TUint id = charconv.GetMimeCharsetUidL( aCharset);
       
  3886 
       
  3887 	if(id==KUidMsvCharsetNone)
       
  3888 		{
       
  3889 		id=charconv.SystemDefaultCharset();
       
  3890 		}
       
  3891 
       
  3892 	if (!charconv.PrepareToConvertToFromOurCharsetL(id))
       
  3893 		{
       
  3894 		rBufOut.Copy(ptr);
       
  3895 		}
       
  3896 	else
       
  3897 		{
       
  3898 		// Charset found, so do conversion
       
  3899 		TInt unconverted;
       
  3900 		TInt indexOfFirst;
       
  3901 		TInt rem = charconv.ConvertToOurCharsetL(ptr, rBufOut, unconverted, indexOfFirst);
       
  3902 		if (rem < 0) // error
       
  3903 			Append(rBufOut, ptr);
       
  3904 		else if (rem && rem < KConversionRemainderLength)
       
  3905 			rBufOut.Copy(ptr);	
       
  3906 
       
  3907 		}
       
  3908 	
       
  3909 	CleanupStack::PopAndDestroy(QPdecodedbuf);
       
  3910 	return ETrue;
       
  3911 	}
       
  3912 
       
  3913 
       
  3914 /**
       
  3915 ExtractParameterString()
       
  3916 Check for delimiter & mark parameter text string
       
  3917 
       
  3918 @param rMark
       
  3919 @return
       
  3920 */
       
  3921 TPtrC8 CLocalMimeParser::ExtractParameterString(TLexMark8& rMark)
       
  3922 	{
       
  3923 	// move on to the first char of the boundary ; this MIGHT be a double-quote
       
  3924 
       
  3925 	TBool delimited = EFalse;
       
  3926 	iLex.Inc();
       
  3927 				
       
  3928 	if ( iLex.Peek() == KImcvDoubleQuote )
       
  3929 		{
       
  3930 		delimited = ETrue;
       
  3931 		iLex.Inc();
       
  3932 		}
       
  3933 
       
  3934 	while ( iLex.Peek().IsSpace() )
       
  3935 		iLex.Inc();
       
  3936 
       
  3937 	iLex.Mark( rMark );
       
  3938 
       
  3939 	TBool finished = EFalse;
       
  3940 	while ( !finished  && !iLex.Eos() )
       
  3941 		{
       
  3942 		iLex.Inc();
       
  3943 
       
  3944 		if ( delimited )
       
  3945 			finished = (iLex.Peek() == KImcvDoubleQuote);
       
  3946 		else
       
  3947 			finished = ( iLex.Peek().IsSpace() || IsSpecialChar((TUint8)iLex.Peek()) );
       
  3948 		} 
       
  3949 
       
  3950 	return iLex.MarkedToken( rMark );
       
  3951 	}
       
  3952 
       
  3953 
       
  3954 /**
       
  3955 CurrentCharsetL()
       
  3956 Which charset to use .. ? If the body part charset set, use that.
       
  3957 else if the main header charset set, use that... else default to us-ascii.
       
  3958 
       
  3959 @return
       
  3960 */
       
  3961 TUint CLocalMimeParser::CurrentCharsetL() const
       
  3962 	{
       
  3963 	TPtrC8 paramCharset = GetContentTypeValue(KImcvCharset);
       
  3964 
       
  3965 	TUint charsetId;
       
  3966 	if (paramCharset.Length())
       
  3967 		// charset parameter present.
       
  3968 		charsetId = iImRecvConvert.CharacterConverter().GetMimeCharsetUidL(paramCharset);
       
  3969 	else if (iCharset) 
       
  3970 		// Main Mime header has default charset value.
       
  3971 		charsetId = iCharset;
       
  3972 	else
       
  3973 		charsetId = iDefaultCharset;
       
  3974 
       
  3975 	return charsetId;		
       
  3976 	}
       
  3977 
       
  3978 
       
  3979 /**
       
  3980 GetContentTypeValue()
       
  3981 
       
  3982 @param aContentTypeParameter
       
  3983 @return
       
  3984 */
       
  3985 const TPtrC8 CLocalMimeParser::GetContentTypeValue(const TDesC8& aContentTypeParameter) const
       
  3986 	{
       
  3987 	CDesC8Array& contentTypeParams = iMimeHeader->ContentTypeParams();
       
  3988 	__ASSERT_DEBUG(!(contentTypeParams.Count()&1), User::Invariant());
       
  3989 
       
  3990 	TInt result;
       
  3991 	if (KErrNone == contentTypeParams.Find(aContentTypeParameter,result,ECmpFolded8))
       
  3992 		{
       
  3993 		result++;
       
  3994 		if ((result&1) && result <= contentTypeParams.Count())    
       
  3995 			{       
       
  3996 			// check result+1 is odd & entry exists
       
  3997 			return iMimeHeader->ContentTypeParams()[result];
       
  3998 			}
       
  3999 		}
       
  4000 	return TPtrC8();        // couldn't find match so return an empty descriptor
       
  4001 	}
       
  4002 
       
  4003 
       
  4004 /**s
       
  4005 EntryId()
       
  4006 
       
  4007 @return
       
  4008 */
       
  4009 TMsvId CLocalImRecvConvert::EntryId()
       
  4010 	{
       
  4011 	// If we are temporarily on the null entry then return the saved entry
       
  4012 	if (iServerEntry->Entry().Id() == KMsvNullIndexEntryId)
       
  4013 		{
       
  4014 		return iSavedEntryId;
       
  4015 		}
       
  4016 	else
       
  4017 		{
       
  4018 		return iServerEntry->Entry().Id();
       
  4019 		}
       
  4020 	}