email/pop3andsmtpmtm/servermtmutils/src/IMCVSEND.CPP
changeset 0 72b543305e3a
child 49 2a272ef608c4
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <e32base.h>
       
    17 #include <e32math.h>
       
    18 #include <txtrich.h>
       
    19 #include <bautils.h>
       
    20 #include <miut_err.h>
       
    21 
       
    22 #include "IMUTDLL.H"
       
    23 #include "IMCVSEND.H"
       
    24 
       
    25 #include <miuthdr.h>
       
    26 #include <miutpars.h>
       
    27 
       
    28 #include <imcm.rsg>	
       
    29 #include <barsread.h>	// TResourceReader
       
    30 
       
    31 #include <cmsvattachment.h> 
       
    32 #include <mmsvattachmentmanager.h>
       
    33 #include <cmsvplainbodytext.h>		
       
    34 
       
    35 #ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    36 #include "miut_errconsts.h"
       
    37 #include "timrfc822datefield.h"
       
    38 #include "cimconvertheader.h"
       
    39 #endif
       
    40 
       
    41 
       
    42 #define SENDLOG(x)				\
       
    43 	if (iLogFileExists)			\
       
    44 		iLogFile.Write(x);	
       
    45 
       
    46 
       
    47 #define SENDLOG2(x,y)			\
       
    48 	if (iLogFileExists)			\
       
    49 		{						\
       
    50 		iLogFile.Write(x);		\
       
    51 		iLogFile.Write(y);		\
       
    52 		}
       
    53 
       
    54 _LIT(KLogFilePath, "c:\\logs\\mailtext\\");
       
    55 _LIT(KLogFileName, "out.txt");
       
    56 _LIT8(KNewLogHeader, "\r\n------ New Send Session ------\r\n");
       
    57 _LIT8(KSent, "Sent : ");
       
    58 _LIT8(KSetBody, "Body length = %d\r\n");
       
    59 
       
    60 const TInt KArrayGranularity = 3;
       
    61 const TInt KChunkSize = 1024;
       
    62 
       
    63 
       
    64 //*********************************************************************************
       
    65 //              Class CImSendMessage Functions
       
    66 //*********************************************************************************
       
    67 
       
    68 //---------------------------------------------------------------------------------
       
    69 EXPORT_C CImSendMessage* CImSendMessage::NewLC(CMsvServerEntry& aServerEntry)
       
    70 //---------------------------------------------------------------------------------
       
    71 	{
       
    72 	CImSendMessage* self = new (ELeave) CImSendMessage(aServerEntry);
       
    73 	CleanupStack::PushL( self );
       
    74 	self->ConstructL();
       
    75 	return self;
       
    76 	}
       
    77 
       
    78 //---------------------------------------------------------------------------------
       
    79 EXPORT_C CImSendMessage* CImSendMessage::NewL(CMsvServerEntry& aServerEntry)
       
    80 //---------------------------------------------------------------------------------
       
    81 	{
       
    82 	CImSendMessage* self = CImSendMessage::NewLC(aServerEntry);
       
    83 	CleanupStack::Pop( );
       
    84 	return self;
       
    85 	}
       
    86 
       
    87 //---------------------------------------------------------------------------------
       
    88 CImSendMessage::CImSendMessage(CMsvServerEntry& aServerEntry) : iServerEntry(aServerEntry)
       
    89 //---------------------------------------------------------------------------------
       
    90 	{	
       
    91 	}
       
    92 
       
    93 
       
    94 //---------------------------------------------------------------------------------
       
    95 void CImSendMessage::ConstructL()
       
    96 //---------------------------------------------------------------------------------
       
    97 	{
       
    98 	// logfile stuff
       
    99 	TInt ret=0;
       
   100 	TParse logFileName;
       
   101 	logFileName.Set(KLogFileName, &KLogFilePath, NULL);
       
   102 	TFileName filename(logFileName.FullName());
       
   103 	ret=iLogFile.Replace(iServerEntry.FileSession(), filename, EFileShareExclusive|EFileWrite );
       
   104 	iLogFileExists = (ret==KErrNone);
       
   105 	SENDLOG( KNewLogHeader )
       
   106 
       
   107 	}
       
   108 
       
   109 //---------------------------------------------------------------------------------
       
   110 EXPORT_C void CImSendMessage::InitialiseL(TMsvId aMessageId, TImSendMethod aSendMethod, 
       
   111 					const TTime aTimeDate, const TDesC& aDomainName, 
       
   112 					TUint aCharset, const TImSMTPSendCopyToSelf aCopyToSelf)
       
   113 //---------------------------------------------------------------------------------
       
   114 	{
       
   115 	TImEmailTransformingInfo info;
       
   116 	info.SetToDefault(aSendMethod); // Sets defaults
       
   117 	info.SetHeaderAndBodyCharset(aCharset) ; // Sets charset for header/body
       
   118 
       
   119 	InitialiseL(aMessageId, aTimeDate, aDomainName, info, aCopyToSelf);
       
   120 	}
       
   121 
       
   122 
       
   123 //---------------------------------------------------------------------------------
       
   124 EXPORT_C void CImSendMessage::InitialiseL(TMsvId aMessageId, const TTime aTimeDate,
       
   125 							const TDesC& aDomainName,	const TImEmailTransformingInfo& aInfo,
       
   126 							const TImSMTPSendCopyToSelf aCopyToSelf)
       
   127 //---------------------------------------------------------------------------------
       
   128 	{
       
   129 	User::LeaveIfError(iServerEntry.SetEntry(aMessageId));
       
   130 	__ASSERT_ALWAYS(iServerEntry.Entry().iType==KUidMsvMessageEntry, gPanic(KPanicEntryIsNotMessage));
       
   131 
       
   132 	SetSendMethodL(aInfo.SendMethod());
       
   133 	iSendEmail->InitialiseL(aTimeDate, aDomainName, aCopyToSelf, aInfo);
       
   134 	Reset();
       
   135 
       
   136 	}
       
   137 
       
   138 //---------------------------------------------------------------------------------
       
   139 EXPORT_C void CImSendMessage::Reset()
       
   140 //---------------------------------------------------------------------------------
       
   141 	{
       
   142 	iSendEmail->Reset();
       
   143 	}
       
   144 
       
   145 
       
   146 // Creates the required email sending object, either Mime or non MIME.
       
   147 //---------------------------------------------------------------------------------
       
   148 void CImSendMessage::SetSendMethodL(TImSendMethod aSendMethod)
       
   149 //---------------------------------------------------------------------------------
       
   150 	{
       
   151 	switch (aSendMethod)
       
   152 		{
       
   153 		case ESendAsSimpleEmail:
       
   154 			iSendEmail = CImSendPlainEmail::NewL(iServerEntry);
       
   155 			break;
       
   156 		case ESendAsMimeEmail:
       
   157 			iSendEmail = CImSendMimeEmail::NewL(iServerEntry);
       
   158 			break;
       
   159 		default:
       
   160 			gPanic(KPanicUnknownSendingMethod);
       
   161 		}
       
   162 	}
       
   163 
       
   164 
       
   165 //---------------------------------------------------------------------------------
       
   166 EXPORT_C TInt CImSendMessage::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount  )
       
   167 //---------------------------------------------------------------------------------
       
   168 	{
       
   169 	// Format the next line of output into rOutputLine.
       
   170 	// If the output line contains more characters than the size of the source data cosumed 
       
   171 	// in preparing it, then the difference is passed back in aPaddingCount.
       
   172 	
       
   173 	TInt localPaddingCount=0;
       
   174 
       
   175 	rOutputLine.Zero();
       
   176 	TInt ret = iSendEmail->NextLineL( rOutputLine, localPaddingCount );
       
   177 
       
   178 	AddCRLFAtEndOfLine(rOutputLine, localPaddingCount);
       
   179 
       
   180 	SENDLOG(KSent);
       
   181 	SENDLOG(rOutputLine);
       
   182 
       
   183 	rPaddingCount = localPaddingCount;
       
   184 	return ret;
       
   185 	}
       
   186 
       
   187 
       
   188 //---------------------------------------------------------------------------------
       
   189 EXPORT_C CImSendMessage::~CImSendMessage( )
       
   190 //---------------------------------------------------------------------------------
       
   191 	{
       
   192 	if (iLogFileExists)
       
   193 		iLogFile.Close();
       
   194 	delete iSendEmail;
       
   195 	}
       
   196 
       
   197 //---------------------------------------------------------------------------------
       
   198 EXPORT_C TInt CImSendMessage::HeaderSize()
       
   199 //---------------------------------------------------------------------------------
       
   200 	{
       
   201 	TInt size = iSendEmail->HeaderSize();
       
   202 	iSendEmail->Reset();
       
   203 	return size;
       
   204 	}
       
   205 
       
   206 
       
   207 //---------------------------------------------------------------------------------
       
   208 EXPORT_C TInt CImSendMessage::BodySizeL()
       
   209 //---------------------------------------------------------------------------------
       
   210 	{
       
   211 	return iSendEmail->BodySizeL();
       
   212 	}
       
   213 
       
   214 
       
   215 //*********************************************************************************
       
   216 //              Class CImSendEmail Functions
       
   217 //*********************************************************************************
       
   218 
       
   219 //---------------------------------------------------------------------------------
       
   220 CImSendEmail::CImSendEmail(CMsvServerEntry& aServerEntry) : 
       
   221 							iServerEntry(aServerEntry), iDomainName(TPtrC())
       
   222 //---------------------------------------------------------------------------------
       
   223 	{
       
   224 	}
       
   225 
       
   226 
       
   227 //---------------------------------------------------------------------------------
       
   228 CImSendEmail::~CImSendEmail( )
       
   229 //---------------------------------------------------------------------------------
       
   230 	{
       
   231 	delete iCharConv;
       
   232 	delete iCharacterConverter;
       
   233 	delete iHeaderConverter;
       
   234 
       
   235 	delete iSendFile;
       
   236 	delete iEmailTraverser;
       
   237 
       
   238 	delete iRfc822Header;
       
   239 	delete iSendRichText;
       
   240 	}
       
   241 
       
   242 //---------------------------------------------------------------------------------
       
   243 void CImSendEmail::ConstructL()
       
   244 //---------------------------------------------------------------------------------
       
   245 	{
       
   246 	iCharacterConverter = CCnvCharacterSetConverter::NewL();
       
   247 	iCharConv = CImConvertCharconv::NewL(*iCharacterConverter, iServerEntry.FileSession());
       
   248 
       
   249 	iSendFile =	CImSendFile::NewL(iServerEntry.FileSession(), *iCharConv);
       
   250 
       
   251 	iEmailTraverser = CImEmailTraverser::NewL(iServerEntry);
       
   252 
       
   253 	iHeaderConverter = CImConvertHeader::NewL(*iCharConv);
       
   254 	iRfc822Header = CImSendRfc822Header::NewL(iServerEntry.FileSession(), *iHeaderConverter);
       
   255 	iSendRichText = CImSendRichText::NewL(*iCharConv);
       
   256 	}
       
   257 
       
   258 //---------------------------------------------------------------------------------
       
   259 void CImSendEmail::InitialiseL( const TTime aTimeDate, const TDesC& aDomainName,
       
   260 							   const TImSMTPSendCopyToSelf aCopyToSelf,
       
   261 							   const TImEmailTransformingInfo& aTransformingInfo)
       
   262 //---------------------------------------------------------------------------------
       
   263 	{
       
   264 	// get a list of all attachments
       
   265 	iDomainName.Set(aDomainName);
       
   266 	iDefaultTransformingInfo=aTransformingInfo;
       
   267 	iTimeDate=aTimeDate;
       
   268 	
       
   269 	iRfc822Header->InitialiseL(iTimeDate,	iDomainName, iServerEntry, 
       
   270 					iServerEntry.Entry().Priority(), aCopyToSelf, iDefaultTransformingInfo);
       
   271 
       
   272 	iEmailTraverser->InitialiseL( iServerEntry.Entry().Id() );
       
   273 
       
   274 	}
       
   275 
       
   276 
       
   277 //---------------------------------------------------------------------------------
       
   278 TBool CImSendEmail::InitBodyObjectL(TMsvEntry& rEntry)
       
   279 //---------------------------------------------------------------------------------
       
   280 	{
       
   281 	return ( rEntry.iType==KUidMsvEmailTextEntry
       
   282 		  && iSendRichText->InitialiseL( iServerEntry, 
       
   283 							Encoder(EEncodingTypeNone), EEncodingTypeNone,
       
   284 							iRfc822Header->TransformingInfo().BodyTextCharset()) );
       
   285 	}
       
   286 
       
   287 
       
   288 // calculates & returns the total size of the header info, including the RFC822 tags, 
       
   289 // comma & space separation, the CRLFs and the blank line after the header itself
       
   290 
       
   291 //---------------------------------------------------------------------------------
       
   292 TInt CImSendEmail::HeaderSize()
       
   293 //---------------------------------------------------------------------------------
       
   294 	{
       
   295 	return iRfc822Header->Size();
       
   296 	}
       
   297 
       
   298 // Sum of body parts and file attachments.
       
   299 //---------------------------------------------------------------------------------
       
   300 TInt CImSendEmail::BodySizeL()
       
   301 //---------------------------------------------------------------------------------
       
   302 	{
       
   303 	TMsvEntry entry;
       
   304 	TInt size=0;
       
   305 	TBool isEndOfEmail=EFalse;
       
   306 
       
   307 	entry = iEmailTraverser->ThisEntry();
       
   308 	do {
       
   309 		if (InitBodyObjectL(entry))
       
   310 			size += iSendRichText->Size();
       
   311 		else if (InitAttachmentObjectL(entry))
       
   312 			size += iSendFile->Size();
       
   313 
       
   314 		if ( iEmailTraverser->DownLevelL() )
       
   315 			entry = iEmailTraverser->ThisEntry();
       
   316 		else
       
   317 			while ( !iEmailTraverser->NextEntryL(entry) )
       
   318 				{
       
   319 				if ( !iEmailTraverser->UpLevelL() || iEmailTraverser->IsBaseLevel() )
       
   320 					{
       
   321 					// end of traversal, reached message entry.
       
   322 					isEndOfEmail=ETrue;
       
   323 					break;
       
   324 					}
       
   325 				}
       
   326 
       
   327 	} while (!isEndOfEmail);
       
   328 
       
   329 	return size;
       
   330 	}
       
   331 
       
   332 //---------------------------------------------------------------------------------
       
   333 void CImSendEmail::Reset()
       
   334 //---------------------------------------------------------------------------------
       
   335 	{
       
   336 	if(iRfc822Header)
       
   337 		{		
       
   338 		iRfc822Header->Reset();
       
   339 		}
       
   340 	iState = 0;
       
   341 	}
       
   342 
       
   343 //---------------------------------------------------------------------------------
       
   344 TImFileCodec&  CImSendEmail::Encoder(TImEncodingType aType)
       
   345 //---------------------------------------------------------------------------------
       
   346 	{
       
   347 	switch (aType)
       
   348 		{
       
   349 	case EEncodingTypeUU: 
       
   350 		iUUEncoder.Initialise();
       
   351 		return iUUEncoder;
       
   352 	case EEncodingTypeBASE64: 
       
   353 		iB64Encoder.Initialise();
       
   354 		return iB64Encoder;
       
   355 	case EEncodingTypeQP: 
       
   356 		return iQPEncoder;
       
   357 	case EEncodingTypeNone:
       
   358 		return iNULLEncoder;
       
   359 	default:
       
   360 		__ASSERT_DEBUG( ETrue, gPanic(KPanicInvalidEncodingType) );
       
   361 		return iNULLEncoder;
       
   362 		}
       
   363 	}
       
   364 
       
   365 
       
   366 //---------------------------------------------------------------------------------
       
   367 TBool CImSendEmail::InitAttachmentObjectL(TMsvEntry& rEntry)
       
   368 //---------------------------------------------------------------------------------
       
   369 	{
       
   370 	if ( !(rEntry.iType==KUidMsvAttachmentEntry || rEntry.iType==KUidMsvEmailHtmlEntry) )
       
   371 		return EFalse;
       
   372 		
       
   373 	iSendFile->InitialiseL(iServerEntry, Encoder(iRfc822Header->TransformingInfo().AttachmentEncoding())); 
       
   374 	return ETrue;
       
   375 	}
       
   376 
       
   377 
       
   378 
       
   379 //*********************************************************************************
       
   380 //              Class CImEmailTraverser Functions
       
   381 //*********************************************************************************
       
   382 
       
   383 
       
   384 //---------------------------------------------------------------------------------
       
   385 CImEmailTraverser* CImEmailTraverser::NewL( CMsvServerEntry& aServerEntry)
       
   386 //---------------------------------------------------------------------------------
       
   387 	{
       
   388 	CImEmailTraverser* self = new (ELeave) CImEmailTraverser( aServerEntry );
       
   389 	CleanupStack::PushL( self );
       
   390 	self->ConstructL();
       
   391 	CleanupStack::Pop( );
       
   392 	return self;
       
   393 	}
       
   394 
       
   395 //---------------------------------------------------------------------------------
       
   396 CImEmailTraverser::CImEmailTraverser( CMsvServerEntry& aServerEntry ) : 
       
   397 				iServerEntry(aServerEntry), iCurrentEntryList(KArrayGranularity)
       
   398 //---------------------------------------------------------------------------------
       
   399 	{
       
   400 	iBaseId = iServerEntry.Entry().Id();
       
   401 	}
       
   402 
       
   403 //---------------------------------------------------------------------------------
       
   404 void CImEmailTraverser::ConstructL()
       
   405 //---------------------------------------------------------------------------------
       
   406 	{
       
   407 	iSelectionList = new (ELeave) CArrayFixFlat<CMsvEntrySelection*>(KArrayGranularity);
       
   408 	}
       
   409 
       
   410 //---------------------------------------------------------------------------------
       
   411 CImEmailTraverser::~CImEmailTraverser()
       
   412 //---------------------------------------------------------------------------------
       
   413 	{
       
   414 	Reset();
       
   415 	delete iSelectionList;
       
   416 	}
       
   417 
       
   418 
       
   419 //---------------------------------------------------------------------------------
       
   420 void CImEmailTraverser::Reset()
       
   421 //---------------------------------------------------------------------------------
       
   422 	{
       
   423 	while (DeleteCurrentList())
       
   424 		;
       
   425 	}
       
   426 
       
   427 //---------------------------------------------------------------------------------
       
   428 void CImEmailTraverser::InitialiseL( TMsvId aId)
       
   429 //---------------------------------------------------------------------------------
       
   430 	{
       
   431 	iBaseId = aId;
       
   432 	User::LeaveIfError(iServerEntry.SetEntry(iBaseId));
       
   433 	Reset();
       
   434 	}
       
   435 
       
   436 
       
   437 //---------------------------------------------------------------------------------
       
   438 TBool CImEmailTraverser::DownLevelL()
       
   439 //---------------------------------------------------------------------------------
       
   440 	{
       
   441 	TMsvSelectionOrdering ordering(KMsvNoGrouping,EMsvSortById,ETrue);
       
   442 	iServerEntry.SetSort(ordering);
       
   443 	CMsvEntrySelection*	children = new(ELeave) CMsvEntrySelection;
       
   444 	CleanupStack::PushL(children);
       
   445 	User::LeaveIfError(iServerEntry.GetChildren(*children));
       
   446 
       
   447 	if (children->Count())
       
   448 		{
       
   449 		AddList(*children);
       
   450 		CleanupStack::Pop(children);
       
   451 		User::LeaveIfError(iServerEntry.SetEntry( CurrentList()[0]));
       
   452 		return ETrue;
       
   453 		}
       
   454 	
       
   455 	CleanupStack::PopAndDestroy(children);
       
   456 	return EFalse;
       
   457 	}
       
   458 
       
   459 //---------------------------------------------------------------------------------
       
   460 TBool CImEmailTraverser::UpLevelL()
       
   461 //---------------------------------------------------------------------------------
       
   462 	{
       
   463 	if (!DeleteCurrentList())
       
   464 		return EFalse;
       
   465 
       
   466 	if (!LevelExists())
       
   467 		User::LeaveIfError( iServerEntry.SetEntry(iBaseId) );
       
   468 	else
       
   469 		User::LeaveIfError( iServerEntry.SetEntry( CurrentList()[CurrentEntry()]) );
       
   470 	return ETrue;
       
   471 	}
       
   472 
       
   473 //---------------------------------------------------------------------------------
       
   474 TBool CImEmailTraverser::NextEntryL(TMsvEntry& rEntry)
       
   475 //---------------------------------------------------------------------------------
       
   476 	{	
       
   477 	if (IsBaseLevel())
       
   478 		return EFalse;
       
   479 
       
   480 	iCurrentEntryList[0] += 1;
       
   481 	if ( CurrentEntry()>=CurrentList().Count() )
       
   482 		return EFalse; // last entry on this level.
       
   483 
       
   484 	if (!LevelExists())
       
   485 		User::LeaveIfError( iServerEntry.SetEntry(iBaseId) );
       
   486 	else
       
   487 		User::LeaveIfError( iServerEntry.SetEntry( CurrentList()[CurrentEntry()]) );
       
   488 
       
   489 	rEntry = ThisEntry();
       
   490 	return ETrue;
       
   491 	}
       
   492 
       
   493 
       
   494 //*********************************************************************************
       
   495 //              Class CImSendPlainEmail Functions
       
   496 //*********************************************************************************
       
   497 
       
   498 //---------------------------------------------------------------------------------
       
   499 CImSendPlainEmail* CImSendPlainEmail::NewLC(CMsvServerEntry& aServerEntry)
       
   500 //---------------------------------------------------------------------------------
       
   501 	{
       
   502 	CImSendPlainEmail* self = new (ELeave) CImSendPlainEmail(aServerEntry);
       
   503 	CleanupStack::PushL( self );
       
   504 	self->ConstructL();
       
   505 	return self;
       
   506 	}
       
   507 
       
   508 //---------------------------------------------------------------------------------
       
   509 CImSendPlainEmail* CImSendPlainEmail::NewL(CMsvServerEntry& aServerEntry)
       
   510 //---------------------------------------------------------------------------------
       
   511 	{
       
   512 	CImSendPlainEmail* self = CImSendPlainEmail::NewLC(aServerEntry);
       
   513 	CleanupStack::Pop( );
       
   514 	return self;
       
   515 	}
       
   516 
       
   517 //---------------------------------------------------------------------------------
       
   518 CImSendPlainEmail::CImSendPlainEmail(CMsvServerEntry& aServerEntry) : CImSendEmail(aServerEntry)
       
   519 //---------------------------------------------------------------------------------
       
   520 	{
       
   521 	}
       
   522 
       
   523 // Sending header followed by body and attachment parts, in the order in which they are
       
   524 // arranged in the TMsventry structure.
       
   525 //---------------------------------------------------------------------------------
       
   526 TInt CImSendPlainEmail::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
       
   527 //---------------------------------------------------------------------------------
       
   528 	{
       
   529 	__ASSERT_DEBUG( iRfc822Header!=NULL, gPanic(KPanicNoRfc822Header) );
       
   530 	__ASSERT_DEBUG( iSendRichText!=NULL, gPanic(KPanicNoRichText) );
       
   531 	
       
   532 	TInt advance = 0;
       
   533 	TInt length = 0;
       
   534 	TInt localPaddingCount=0;
       
   535 	
       
   536 	rOutputLine.Zero();
       
   537 	do 
       
   538 		{
       
   539 		switch (iState)
       
   540 			{
       
   541 			case ERfc822Header:
       
   542 				advance = iRfc822Header->NextLineL(rOutputLine, rPaddingCount);
       
   543 				if (advance)
       
   544 					AppendCRLF(rOutputLine, localPaddingCount);
       
   545 				break;
       
   546 			case EBody:
       
   547 				advance = iSendRichText->NextLineL(rOutputLine, rPaddingCount);
       
   548 				break;
       
   549 			case EAttachmentFile:
       
   550 				advance = iSendFile->NextLineL(rOutputLine, rPaddingCount);
       
   551 				break;
       
   552 			}
       
   553 
       
   554 		length = rOutputLine.Length();
       
   555 		if ( !length || advance )
       
   556 			{
       
   557 			if ( iState==EBody )
       
   558 				AppendCRLF(rOutputLine, localPaddingCount);
       
   559 			while (!ChangeStateL())
       
   560 				;
       
   561 			}
       
   562 
       
   563 		} while ( !length && iState != KImCvFinished);
       
   564 		
       
   565 	rPaddingCount = localPaddingCount;
       
   566 	return (iState==KImCvFinished ? KImCvFinished : KErrNone);
       
   567 	}
       
   568 
       
   569 
       
   570 //---------------------------------------------------------------------------------
       
   571 TBool CImSendPlainEmail::ChangeStateL()
       
   572 //---------------------------------------------------------------------------------
       
   573 	{
       
   574 	TMsvEmailEntry entry = iEmailTraverser->ThisEntry();
       
   575 
       
   576 	if ( iEmailTraverser->DownLevelL() )
       
   577 		entry = iEmailTraverser->ThisEntry();
       
   578 	else
       
   579 		while ( !iEmailTraverser->NextEntryL(entry) )
       
   580 			{
       
   581 			if ( !iEmailTraverser->UpLevelL() || iEmailTraverser->IsBaseLevel() )
       
   582 				{
       
   583 				iState=KImCvFinished;
       
   584 				return ETrue;
       
   585 				}
       
   586 			}
       
   587 
       
   588 	// Is this entry an attachment entry?
       
   589 	if (InitBodyObjectL(entry))
       
   590 		iState=EBody;
       
   591 	else if (InitAttachmentObjectL(entry))
       
   592 		iState=EAttachmentFile;	
       
   593 	else
       
   594 		return EFalse;
       
   595 		
       
   596 	return ETrue;
       
   597 	}
       
   598 
       
   599 
       
   600 //*********************************************************************************
       
   601 //              Class CImSendMimeEmail Functions
       
   602 //*********************************************************************************
       
   603 
       
   604 //---------------------------------------------------------------------------------
       
   605 CImSendMimeEmail* CImSendMimeEmail::NewLC(CMsvServerEntry& aServerEntry )
       
   606 //---------------------------------------------------------------------------------
       
   607 	{
       
   608 	CImSendMimeEmail* self = new (ELeave) CImSendMimeEmail(aServerEntry);
       
   609 	CleanupStack::PushL( self );
       
   610 	self->ConstructL();
       
   611 	return self;
       
   612 	}
       
   613 
       
   614 //---------------------------------------------------------------------------------
       
   615 CImSendMimeEmail* CImSendMimeEmail::NewL(CMsvServerEntry& aServerEntry )
       
   616 //---------------------------------------------------------------------------------
       
   617 	{
       
   618 	CImSendMimeEmail* self = CImSendMimeEmail::NewLC(aServerEntry);
       
   619 	CleanupStack::Pop( );
       
   620 	return self;
       
   621 	}
       
   622 
       
   623 //---------------------------------------------------------------------------------
       
   624 CImSendMimeEmail::CImSendMimeEmail(CMsvServerEntry& aServerEntry ) : CImSendEmail(aServerEntry)
       
   625 //---------------------------------------------------------------------------------
       
   626 	{
       
   627 	}
       
   628 
       
   629 //---------------------------------------------------------------------------------
       
   630 CImSendMimeEmail::~CImSendMimeEmail()
       
   631 //---------------------------------------------------------------------------------
       
   632 	{
       
   633 	Reset();
       
   634 	delete iSendMimeHeader;
       
   635 	delete iBoundaryArray;
       
   636 	delete iMimeHeader;
       
   637 	}
       
   638 
       
   639 //---------------------------------------------------------------------------------
       
   640 void CImSendMimeEmail::ConstructL()
       
   641 //---------------------------------------------------------------------------------
       
   642 	{
       
   643 	TTime theTime;
       
   644 	theTime.UniversalTime(); // Gets the current universal time to use as a random number seed
       
   645 	iRandSeed = theTime.Int64();
       
   646 
       
   647 	iBoundaryArray = new (ELeave) CDesC8ArrayFlat(KArrayGranularity);
       
   648 	CImSendEmail::ConstructL();
       
   649 	}
       
   650 
       
   651 //---------------------------------------------------------------------------------
       
   652 void CImSendMimeEmail::Reset()
       
   653 //---------------------------------------------------------------------------------
       
   654 	{
       
   655 	iTextDisplayed=EFalse;
       
   656 	iBoundaryArray->Reset();
       
   657 	CImSendEmail::Reset();
       
   658 	}
       
   659 
       
   660 
       
   661 // Sending a MIME message consisting of a header, main MIME header followed by one or more
       
   662 // MIME parts. If more than one, the parts are seperated by a boundary string.
       
   663 
       
   664 //---------------------------------------------------------------------------------
       
   665 TInt CImSendMimeEmail::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
       
   666 //---------------------------------------------------------------------------------
       
   667 	{	
       
   668 	__ASSERT_DEBUG( iRfc822Header!=NULL, gPanic(KPanicNoRfc822Header) );
       
   669 	__ASSERT_DEBUG( iSendRichText!=NULL, gPanic(KPanicNoRichText) );
       
   670 
       
   671 	TInt advance = 0;
       
   672 	TInt length = 0;
       
   673 	TBool addBlankLine=EFalse;
       
   674 
       
   675 	rOutputLine.Zero();
       
   676 	do 
       
   677 	{
       
   678 	addBlankLine=EFalse;
       
   679 	switch (iState)
       
   680 		{
       
   681 		case ERfc822Header:
       
   682 			advance = iRfc822Header->NextLineL( rOutputLine, rPaddingCount );
       
   683 			break;
       
   684 		case EMimeMainHeader:
       
   685 			advance = iSendMimeHeader->NextLine( rOutputLine, rPaddingCount );
       
   686 			break;
       
   687 		case EMimeText:
       
   688 			if ( iBoundaryArray->Count() && !iTextDisplayed )
       
   689 				{
       
   690 				rOutputLine.Append(KImcvMimeText);
       
   691 				rPaddingCount=rOutputLine.Length();
       
   692 				AppendCRLF(rOutputLine, rPaddingCount);
       
   693 				addBlankLine=ETrue;
       
   694 				iTextDisplayed=ETrue;
       
   695 				}
       
   696 			advance=1;
       
   697 			break;
       
   698 		case EBoundary:
       
   699 			if ( iBoundaryArray->Count() )
       
   700 				{
       
   701 				SendBoundaryLine( rOutputLine, rPaddingCount );
       
   702 				AppendCRLF(rOutputLine, rPaddingCount);
       
   703 				}
       
   704 			advance = 1;
       
   705 			break;
       
   706 		case EMimePartHeader:
       
   707 			advance = iSendMimeHeader->NextLine( rOutputLine, rPaddingCount );
       
   708 			break;
       
   709 		case EBody:
       
   710 			advance = iSendRichText->NextLineL(rOutputLine, rPaddingCount);
       
   711 			break;
       
   712 		case EAttachmentFile:
       
   713 			advance = iSendFile->NextLineL(rOutputLine, rPaddingCount);
       
   714 			break;
       
   715 		case EEndBoundary:
       
   716 			if ( iBoundaryArray->Count() )
       
   717 				{
       
   718 				SendBoundaryLine( rOutputLine, rPaddingCount );
       
   719 				rOutputLine.Append(KImcvMimeBoundaryStartEnd);
       
   720 				DeleteBoundary();
       
   721 				rPaddingCount=rOutputLine.Length();
       
   722 				}
       
   723 			advance = 1;
       
   724 			break;
       
   725 		case ELineAfterEndBoundary:
       
   726 			AppendCRLF(rOutputLine, rPaddingCount);
       
   727 			advance = 1;
       
   728 			break;
       
   729 			}
       
   730 			
       
   731 		length = rOutputLine.Length();
       
   732 
       
   733 		if ( !length || advance )
       
   734 			ChangeStateL();
       
   735 
       
   736 		if (addBlankLine)
       
   737 			AppendCRLF(rOutputLine, rPaddingCount);
       
   738 
       
   739 		} while ( !length && iState != KImCvFinished);
       
   740 
       
   741 	return (iState==KImCvFinished ? KImCvFinished : KErrNone);
       
   742 	}
       
   743 
       
   744 
       
   745 //---------------------------------------------------------------------------------
       
   746 TBool CImSendMimeEmail::ChangeStateL()
       
   747 //---------------------------------------------------------------------------------
       
   748 	{
       
   749 	TInt ret=ETrue;
       
   750 	TMsvEmailEntry entry = iEmailTraverser->ThisEntry();
       
   751 	TImEmailFolderType folderType;
       
   752 
       
   753 	switch (iState)
       
   754 		{
       
   755 		case ERfc822Header:
       
   756 			InitSendMimeHeaderL(entry, EMainMimeHeader);
       
   757 			iState=EMimeMainHeader;
       
   758 			break;
       
   759 		case EMimeMainHeader:
       
   760 			iState=EMimeText;
       
   761 			break;
       
   762 		case EMimeText:
       
   763 			if ( !CheckForMultipartEmailL(entry, folderType) )
       
   764 				{
       
   765 				// NOT a multipart email.
       
   766 				// Get next entry and see what else it could be..
       
   767 				GetNextEntryL(entry);
       
   768 
       
   769 				if (iState!=EBoundary)
       
   770 					break; // Simple MIME message, only one part.
       
   771 
       
   772 				if ( InitBodyObjectL(entry) )
       
   773 					iState=EBody;	// Rich text
       
   774 				else if ( iEmbeddedEmail )
       
   775 					// An embeddef RFC822 message, change state to RGC822 header
       
   776 					InitEmbeddedEmailL(); 
       
   777 				else if ( InitAttachmentObjectL(entry) )
       
   778 					iState=EAttachmentFile; // Attachment part
       
   779 				else
       
   780 					GetNextEntryL(entry);
       
   781 				}
       
   782 			else
       
   783 				{
       
   784 				// A Multipart message, get next entry to see what first part is.
       
   785 				GetNextEntryL(entry);
       
   786 
       
   787 				// An multipart inside a multipart.
       
   788 				if ( iState==EBoundary && entry.iType==KUidMsvFolderEntry )
       
   789 					GetNextEntryL(entry); 
       
   790 				}
       
   791 			break;
       
   792 		case EBoundary:
       
   793 			iEmbeddedEmail = CheckForEmbeddedEmailL(entry);
       
   794 			InitSendMimeHeaderL(entry, EPartMimeHeader);
       
   795 			iState=EMimePartHeader;
       
   796 			break;	
       
   797 		case EMimePartHeader:
       
   798 			if ( entry.iType==KUidMsvFolderEntry )
       
   799 				GetNextEntryL(entry);
       
   800 			else if ( InitBodyObjectL(entry) )
       
   801 				iState=EBody;
       
   802 			else if ( iEmbeddedEmail )
       
   803 				InitEmbeddedEmailL();
       
   804 			else if ( InitAttachmentObjectL(entry) )
       
   805 				iState=EAttachmentFile;
       
   806 			else
       
   807 				GetNextEntryL(entry);
       
   808 			break;
       
   809 		case EBody:
       
   810 		case EAttachmentFile:
       
   811 			GetNextEntryL(entry);
       
   812 			break;
       
   813 		case EEndBoundary:
       
   814 			iState=ELineAfterEndBoundary;
       
   815 			break;
       
   816 		case ELineAfterEndBoundary:
       
   817 			GetNextEntryL(entry);
       
   818 			break;
       
   819 		} // end Switch	
       
   820 
       
   821 	return ret;
       
   822 	}
       
   823 
       
   824 
       
   825 // If mimeheader in store, crates relevant mimeHeader object.
       
   826 //---------------------------------------------------------------------------------
       
   827 TBool CImSendMimeEmail::CreateMimeHeaderL()
       
   828 //---------------------------------------------------------------------------------
       
   829 	{
       
   830 	TBool restored=EFalse;
       
   831 	delete iMimeHeader;
       
   832 	iMimeHeader=NULL;
       
   833 	iMimeHeader = CImMimeHeader::NewL();
       
   834 
       
   835 	if (iServerEntry.HasStoreL())
       
   836 		{
       
   837 		CMsvStore* entryStore = iServerEntry.ReadStoreL();
       
   838 		CleanupStack::PushL(entryStore);
       
   839 		if( entryStore->IsPresentL(KUidMsgFileMimeHeader) )
       
   840 			{
       
   841 			iMimeHeader->RestoreL(*entryStore);
       
   842 			restored=ETrue;
       
   843 			}
       
   844 		else
       
   845 		/* The MIME header store does not exist, but MIME header info will be
       
   846 		 * sent with this email, so the Sent message should reflect this.
       
   847 		 * So we create a KUidMsgFileMimeHeader in the store */
       
   848 			{
       
   849 			// open store for edit
       
   850 			CleanupStack::PopAndDestroy(entryStore);
       
   851 			entryStore = NULL;
       
   852 			entryStore = iServerEntry.EditStoreL();
       
   853 			CleanupStack::PushL(entryStore);
       
   854 			
       
   855 			// store the MIMEheader
       
   856 			iMimeHeader->StoreL(*entryStore);
       
   857 			entryStore->CommitL();
       
   858 			}
       
   859 
       
   860 		CleanupStack::PopAndDestroy(entryStore);
       
   861 		}
       
   862 	return restored;
       
   863 	}
       
   864 
       
   865 //---------------------------------------------------------------------------------
       
   866 void CImSendMimeEmail::InitMimeHeaderL( TMsvEntry& aEntry, TPtrC8& rBoundary, TPtrC& rFilename)
       
   867 //---------------------------------------------------------------------------------
       
   868 	{
       
   869 	TBool multipart=EFalse;
       
   870 	
       
   871 	TImEmailFolderType folderType;
       
   872 	if (!iEmbeddedEmail && CheckForMultipartEmailL(aEntry, folderType))
       
   873 		{
       
   874 		//iMimeHeader->Reset();
       
   875 		iMimeHeader->SetContentTypeL(KImcvMultipart);
       
   876 		switch(folderType)
       
   877 			{
       
   878 			case EFolderTypeRelated:
       
   879 				iMimeHeader->SetContentSubTypeL(KImcvRelated);
       
   880 				break;
       
   881 			case EFolderTypeMixed:
       
   882 				iMimeHeader->SetContentSubTypeL(KImcvMixed);
       
   883 				break;
       
   884 			case EFolderTypeParallel:
       
   885 				iMimeHeader->SetContentSubTypeL(KImcvParallel);
       
   886 				break;
       
   887 			case EFolderTypeAlternative:
       
   888 				iMimeHeader->SetContentSubTypeL(KImcvAlternative);
       
   889 				break;
       
   890 			case EFolderTypeDigest:
       
   891 				iMimeHeader->SetContentSubTypeL(KImcvDigest);
       
   892 				break;
       
   893 			default:
       
   894 				// Should really default to mixed rather than unknown.
       
   895 				iMimeHeader->SetContentSubTypeL(KImcvMixed);		
       
   896 			}
       
   897 		multipart=ETrue;
       
   898 		}
       
   899 
       
   900 	rBoundary.Set(SetBoundaryL(multipart));
       
   901 	
       
   902 	//Storing header information(ContentType and SubContentType) for e-mail with attachment
       
   903 	if ((aEntry.Attachment()) && (iMimeHeader->ContentType().Length() == 0) && (iServerEntry.HasStoreL()))
       
   904 		{
       
   905 		CMsvStore* store = iServerEntry.ReadStoreL(); 
       
   906 		CleanupStack::PushL(store);
       
   907 		MMsvAttachmentManager& manager=store->AttachmentManagerL();
       
   908 		if(manager.AttachmentCount())
       
   909 			{
       
   910 			CMsvAttachment* attachment = manager.GetAttachmentInfoL(0);
       
   911 			CleanupStack::PushL(attachment);
       
   912 			TInt length = attachment->MimeType().Length();
       
   913 			TInt location = attachment->MimeType().Locate('/');
       
   914 			if ((length > 0) && (location != KErrNotFound))
       
   915 				{
       
   916 				iMimeHeader->SetContentTypeL(attachment->MimeType().Left(location++));
       
   917 				iMimeHeader->SetContentSubTypeL(attachment->MimeType().Right((length-location)));	
       
   918 				}
       
   919 			CleanupStack::PopAndDestroy(attachment);	
       
   920 			}
       
   921 		CleanupStack::PopAndDestroy(store);	
       
   922 		}	
       
   923 
       
   924 	if(InitAttachmentObjectL(aEntry))
       
   925 		rFilename.Set(static_cast<TPtrC>(iSendFile->Filename()));
       
   926 	else
       
   927 		rFilename.Set(KNullDesC);	
       
   928 	}
       
   929 
       
   930 //---------------------------------------------------------------------------------
       
   931 void CImSendMimeEmail::InitSendMimeHeaderL( TMsvEntry& aEntry, TMimeHeaderType aMimeHeaderType )
       
   932 //---------------------------------------------------------------------------------
       
   933 	{
       
   934 	// When we are dealing with the main Mime header and we don't have a 
       
   935 	// multipart we want to check if the entry is a text entry and if it 
       
   936 	// has a Mime header in its store: this means we are probably dealing 
       
   937 	// with a scheduling message (i.e.meeting invite). In this case we take
       
   938 	// the Mime header from the text entry.
       
   939 
       
   940 	TImEmailFolderType folderType;
       
   941 	TBool found = EFalse;
       
   942 
       
   943 	if ( (aMimeHeaderType==EMainMimeHeader) && !CheckForMultipartEmailL(aEntry, folderType) )
       
   944 		{
       
   945 		if ( Down(aEntry) )
       
   946 			{
       
   947 			if ( aEntry.iType==KUidMsvEmailTextEntry )
       
   948 				{
       
   949 				if ( CreateMimeHeaderL() )
       
   950 					{
       
   951 					found = ETrue;
       
   952 					}
       
   953 				}
       
   954 
       
   955 			// We move back to the previous entry
       
   956 			iEmailTraverser->UpLevelL();
       
   957 			aEntry = iEmailTraverser->ThisEntry();
       
   958 			}
       
   959 		}
       
   960 
       
   961 	// We read the Mimeheader stream if we haven't done it already
       
   962 	if ( !found )
       
   963 		{
       
   964 		CreateMimeHeaderL();		
       
   965 		}
       
   966 	
       
   967 	TPtrC8 boundary;  
       
   968 	TPtrC filename;
       
   969 
       
   970 	InitMimeHeaderL(aEntry, boundary, filename);
       
   971 
       
   972 	delete iSendMimeHeader;
       
   973 	iSendMimeHeader = NULL;
       
   974  	iSendMimeHeader = CImSendMimeHeader::NewL(*iHeaderConverter, aMimeHeaderType);	
       
   975  	if (( aEntry.iType == KUidMsvMessageEntry )
       
   976  		&& ( !iEmailTraverser->IsBaseLevel() )
       
   977  		&& ( aMimeHeaderType == EPartMimeHeader ))
       
   978  		{
       
   979  		iSendMimeHeader->InitialiseL( *iMimeHeader, filename, boundary,iEmbeddedEmail, 
       
   980  										aEntry, iRfc822Header->TransformingInfo(), ETrue);
       
   981  		}
       
   982  	else
       
   983  		{
       
   984  		iSendMimeHeader->InitialiseL( *iMimeHeader, filename, boundary,iEmbeddedEmail, 
       
   985    										aEntry, iRfc822Header->TransformingInfo());
       
   986  		}
       
   987 
       
   988 	}
       
   989 
       
   990 
       
   991 //---------------------------------------------------------------------------------
       
   992 void CImSendMimeEmail::InitEmbeddedEmailL()
       
   993 //---------------------------------------------------------------------------------
       
   994 	{
       
   995 	iRfc822Header->InitialiseL(iServerEntry.Entry().iDate, iDomainName, iServerEntry,
       
   996 					iServerEntry.Entry().Priority(), ESendNoCopy, iDefaultTransformingInfo);
       
   997 
       
   998 	iState=ERfc822Header;
       
   999 	iEmbeddedEmail=0;
       
  1000 	}
       
  1001 
       
  1002 //---------------------------------------------------------------------------------
       
  1003 void CImSendMimeEmail::CreateBoundaryL()
       
  1004 //---------------------------------------------------------------------------------
       
  1005 	{
       
  1006 	TBuf8<57> validBoundaryBuffer(KBasicAsciiChars);
       
  1007 	TBuf8<KBoundaryStringLength> boundaryString; 
       
  1008 	TUint result = 0;
       
  1009 
       
  1010 	boundaryString.Append(KImcvEpoc32); 
       
  1011 	boundaryString.Append(KImcvHyphen); 
       
  1012 
       
  1013 	while( boundaryString.Length()<KBoundaryStringLength )
       
  1014 		{
       
  1015 		result=(Math::Rand(iRandSeed));
       
  1016 		// gets the mod of Rand() which is a number between 0 to KMaxTInt
       
  1017 		result%=57;
       
  1018 		boundaryString.AppendFormat(KPrintChar, validBoundaryBuffer[result]);
       
  1019 		result=0;
       
  1020 		}
       
  1021 
       
  1022 	iBoundaryArray->InsertL(0, boundaryString);
       
  1023 	}
       
  1024 
       
  1025 //---------------------------------------------------------------------------------
       
  1026 void CImSendMimeEmail::DeleteBoundary()
       
  1027 //---------------------------------------------------------------------------------
       
  1028 	{
       
  1029 	if (iBoundaryArray->Count())
       
  1030 		iBoundaryArray->Delete(0);
       
  1031 	}
       
  1032 
       
  1033 //---------------------------------------------------------------------------------
       
  1034 TInt CImSendMimeEmail::HeaderSize()
       
  1035 //---------------------------------------------------------------------------------
       
  1036 	{
       
  1037 	TInt size = CImSendEmail::HeaderSize();
       
  1038 
       
  1039 	TMsvId id = iServerEntry.Entry().Id();
       
  1040 	iEmailTraverser->SetBaseEntry();
       
  1041 
       
  1042 	TMsvEntry aId;
       
  1043 
       
  1044 	// DEF023106. Can't let Leaves pass into public non-leave function, so Trap.
       
  1045 	TRAPD(initialiseError, InitSendMimeHeaderL(aId, EMainMimeHeader));
       
  1046 
       
  1047 	if (initialiseError != KErrNone)
       
  1048 		{
       
  1049 		// DEF023106. Return double the rfc822 header size on Leave.
       
  1050 		size += size;
       
  1051 		}
       
  1052 	else
       
  1053 		{
       
  1054 		size +=  iSendMimeHeader->Size();
       
  1055 		}
       
  1056 
       
  1057 	iServerEntry.SetEntry(id);
       
  1058 	return size;
       
  1059 	}
       
  1060 
       
  1061 
       
  1062 //---------------------------------------------------------------------------------
       
  1063 TBool CImSendMimeEmail::InitBodyObjectL(TMsvEntry& rEntry)
       
  1064 //---------------------------------------------------------------------------------
       
  1065 	{
       
  1066 	TImEncodingType type=iRfc822Header->TransformingInfo().BodyTextEncoding();
       
  1067 
       
  1068 	return ( rEntry.iType==KUidMsvEmailTextEntry
       
  1069 		  && iSendRichText->InitialiseL( iServerEntry, 
       
  1070 							Encoder(type), type,
       
  1071 							iSendMimeHeader->CharsetUid()) );
       
  1072 	}
       
  1073 
       
  1074 
       
  1075 //*********************************************************************************
       
  1076 //              Class CImSendRfc822Header Functions
       
  1077 //*********************************************************************************
       
  1078 
       
  1079 //---------------------------------------------------------------------------------
       
  1080 CImSendRfc822Header* CImSendRfc822Header::NewLC( RFs& anFs, CImConvertHeader& aConverter )
       
  1081 //---------------------------------------------------------------------------------
       
  1082 	{
       
  1083 	CImSendRfc822Header* self = new (ELeave) CImSendRfc822Header(anFs, aConverter);
       
  1084 	CleanupStack::PushL( self );
       
  1085 	self->ConstructL();
       
  1086 	return self;
       
  1087 	}
       
  1088 
       
  1089 //---------------------------------------------------------------------------------
       
  1090 CImSendRfc822Header* CImSendRfc822Header::NewL( RFs& anFs, CImConvertHeader& aConverter )
       
  1091 //---------------------------------------------------------------------------------
       
  1092 	{
       
  1093 	CImSendRfc822Header* self = CImSendRfc822Header::NewLC(anFs, aConverter);
       
  1094 	CleanupStack::Pop( );
       
  1095 	return self;
       
  1096 	}
       
  1097 
       
  1098 //---------------------------------------------------------------------------------
       
  1099 CImSendRfc822Header::CImSendRfc822Header( RFs& anFs, CImConvertHeader& aConverter ) 
       
  1100 				: iFs(anFs), iHeaderConverter(aConverter)
       
  1101 //---------------------------------------------------------------------------------
       
  1102 	{
       
  1103 	}
       
  1104 
       
  1105 //---------------------------------------------------------------------------------
       
  1106 CImSendRfc822Header::~CImSendRfc822Header() 
       
  1107 //---------------------------------------------------------------------------------
       
  1108 	{
       
  1109 	delete iHeader;
       
  1110 	delete iDomainName;
       
  1111 
       
  1112 	delete iOutputBuffer;
       
  1113 	delete iProductName;
       
  1114 	delete iImcvUtils;
       
  1115 	delete iPriorityFields;
       
  1116 	delete iImportanceFields;
       
  1117 	delete iReceiptFields;
       
  1118 	}
       
  1119 
       
  1120 //---------------------------------------------------------------------------------
       
  1121 void CImSendRfc822Header::ConstructL()
       
  1122 //---------------------------------------------------------------------------------
       
  1123 	{
       
  1124 	RResourceFile resFile;
       
  1125 	OpenResourceFileL(resFile,iFs);	// leaves if file not found
       
  1126 
       
  1127 	// make sure the resource file will be closed if anything goes wrong
       
  1128 	TCleanupItem close( CloseResourceFile, &resFile );
       
  1129 	CleanupStack::PushL( close );
       
  1130 	HBufC8* buf = resFile.AllocReadLC( PRODUCT_NAME );
       
  1131 
       
  1132 	TResourceReader reader;
       
  1133 	reader.SetBuffer(buf);
       
  1134 	iProductName = reader.ReadTPtrC().AllocL();
       
  1135 	CleanupStack::PopAndDestroy(2); // close , buf
       
  1136 	resFile.Close();
       
  1137 
       
  1138 	}
       
  1139 
       
  1140 //---------------------------------------------------------------------------------
       
  1141 TBool CImSendRfc822Header::InitialiseL( const TTime aTimeDate , const TDesC& aDomainName,
       
  1142 							CMsvServerEntry& aServerEntry,const TMsvPriority aPriority,
       
  1143 							const TImSMTPSendCopyToSelf aCopyToSelf,
       
  1144 							TImEmailTransformingInfo& aInfo)
       
  1145 //---------------------------------------------------------------------------------
       
  1146 	{
       
  1147 	Reset();
       
  1148 	iTimeDate = aTimeDate;
       
  1149 
       
  1150 	delete iDomainName;
       
  1151 	iDomainName=NULL;
       
  1152 	iDomainName=aDomainName.AllocL();
       
  1153 
       
  1154 	delete iHeader;
       
  1155 	iHeader=NULL;
       
  1156 	iHeader = CImHeader::NewLC();
       
  1157 	CleanupStack::Pop(); // header
       
  1158 
       
  1159 	delete iImcvUtils;
       
  1160 	iImcvUtils=NULL;
       
  1161 	iImcvUtils=CImcvUtils::NewL();
       
  1162 	
       
  1163 	delete iPriorityFields;
       
  1164 	iPriorityFields=NULL;
       
  1165 	delete iImportanceFields;
       
  1166 	iImportanceFields=NULL;
       
  1167 	delete iReceiptFields;
       
  1168 	iReceiptFields=NULL;
       
  1169 	
       
  1170 	iPriorityFields=new (ELeave)CDesC8ArrayFlat(KArrayAllocationNumber);
       
  1171 	iImcvUtils->SendPriorityFieldsL(*iPriorityFields);
       
  1172 	
       
  1173 	iImportanceFields=new (ELeave)CDesC8ArrayFlat(KArrayAllocationNumber);
       
  1174 	iImcvUtils->SendImportanceFieldsL(*iImportanceFields);
       
  1175 
       
  1176 	TMsvEmailEntry entry = aServerEntry.Entry();
       
  1177 	if (entry.Receipt())
       
  1178 		{
       
  1179 		iReceiptFields = new (ELeave)CDesC8ArrayFlat(KArrayAllocationNumber);
       
  1180 		iImcvUtils->SendReturnReceiptFieldsL(*iReceiptFields);
       
  1181 		}
       
  1182 	iPriority = aPriority;
       
  1183 
       
  1184 	TBool validEmailMsg=EFalse;
       
  1185 	if (aServerEntry.HasStoreL())
       
  1186 		{
       
  1187 		CMsvStore* store = aServerEntry.ReadStoreL();
       
  1188 		CleanupStack::PushL(store);
       
  1189 
       
  1190 		if (store->IsPresentL( KUidMsgFileTransformingInfo))
       
  1191 			aInfo.RestoreL(*store);
       
  1192 		
       
  1193 		// Must have an rfc822 header.
       
  1194 		if (store->IsPresentL( KUidMsgFileIMailHeader) )
       
  1195 			{
       
  1196 			iHeader->RestoreL(*store);
       
  1197 			validEmailMsg=ETrue;
       
  1198 			}
       
  1199 
       
  1200 		CleanupStack::PopAndDestroy(store); 
       
  1201 		}
       
  1202 	
       
  1203 	iTransformingInfo=aInfo;
       
  1204 	if(aInfo.HeaderCharset() == 0)
       
  1205 		aInfo.SetHeaderCharset(iHeaderConverter.CharConv().DefaultCharset());
       
  1206 
       
  1207 	iHeaderCharset=aInfo.HeaderCharset();
       
  1208 	iHeaderEncoding=aInfo.HeaderEncoding();
       
  1209 	
       
  1210 	iCopyToSelf=aCopyToSelf;	
       
  1211 
       
  1212 	return validEmailMsg;
       
  1213 	}
       
  1214 
       
  1215 //---------------------------------------------------------------------------------
       
  1216 void CImSendRfc822Header::HandleSpecialCharacters(TPtr8& aAddressPtr)
       
  1217 //---------------------------------------------------------------------------------
       
  1218 	{
       
  1219 	// Single address passed in. Make sure the address is of the format
       
  1220 	// "quoted name" <name@domain>
       
  1221 	// quoted, name <name@domain>
       
  1222 	// quoted "name" <name@domain>
       
  1223 	// name <name@domain>
       
  1224 	// quoted "name <name@domain>
       
  1225 	// Comments are not supported.
       
  1226 	// Remove any leading and trailing white space.
       
  1227 	aAddressPtr.Trim();
       
  1228 	
       
  1229 	// If the address isn't the correct format.
       
  1230 	if (aAddressPtr[aAddressPtr.Length() - 1] != '>')
       
  1231 		return;
       
  1232 
       
  1233 	TInt leftChevron = aAddressPtr.LocateReverse(TChar('<'));
       
  1234 	if (leftChevron == KErrNotFound)
       
  1235 		return;
       
  1236 
       
  1237 	//If the address has allias
       
  1238 	if(leftChevron > 0)
       
  1239 		{
       
  1240 			
       
  1241 		TInt  firstDQuote = aAddressPtr.Locate(TChar('"'));
       
  1242 		TInt lastDQuote = aAddressPtr.Left(leftChevron).LocateReverse(TChar('"'));
       
  1243 		TInt aliasLastChar = leftChevron-1;
       
  1244 		
       
  1245 		//If alias has ',' in between
       
  1246 		if(aAddressPtr.Left(leftChevron).LocateReverse(TChar(',')) != KErrNotFound)
       
  1247 			{
       
  1248 			//get the last character of alias
       
  1249 			for (TInt index = aliasLastChar ; aAddressPtr[index] == ' ' ; --index )
       
  1250 				{
       
  1251 				aliasLastChar--;	
       
  1252 				}
       
  1253 			//if alias not with in quotes then add quotes
       
  1254 			if ( firstDQuote != 0 || lastDQuote != aliasLastChar)
       
  1255 				{
       
  1256 				aAddressPtr.Insert(0,KImcvQuoteString);	
       
  1257 				firstDQuote = 0;
       
  1258 				//because alias length has been increased by one character 
       
  1259 				aliasLastChar+=1;
       
  1260 				aAddressPtr.Insert(aliasLastChar+1 , KImcvQuoteString);
       
  1261 				lastDQuote = aliasLastChar+1;
       
  1262 				}
       
  1263 			}	
       
  1264 		if (lastDQuote == KErrNotFound || lastDQuote == firstDQuote)
       
  1265 		 		 return;
       
  1266 		
       
  1267 		//add 	KBackslash before all spacial characters in alias
       
  1268 		_LIT8(KBackslash,"\\");
       
  1269 		for (TInt index = lastDQuote - 1; index > firstDQuote; --index)
       
  1270 			{
       
  1271 			if (IsSpecialCharacter(aAddressPtr[index]))
       
  1272 				{
       
  1273 				// Character inserted before the current character.
       
  1274 				aAddressPtr.Insert(index, KBackslash);
       
  1275 				}
       
  1276 			}	
       
  1277 		}
       
  1278 	}
       
  1279 
       
  1280 //---------------------------------------------------------------------------------
       
  1281 TBool CImSendRfc822Header::IsSpecialCharacter(const TUint aChar)
       
  1282 //---------------------------------------------------------------------------------
       
  1283 	{
       
  1284 	return (aChar == '(' || aChar == ')' || aChar == '<' || aChar == '>' || aChar == '@' 
       
  1285 		 || aChar == '"' || aChar == ';' || aChar == ':' || aChar == '/' || aChar == ']' 
       
  1286 		 || aChar == '[');
       
  1287 	}
       
  1288 
       
  1289 //---------------------------------------------------------------------------------
       
  1290 void CImSendRfc822Header::Reset()
       
  1291 //---------------------------------------------------------------------------------
       
  1292 	{
       
  1293 	iState = 0;
       
  1294 	}
       
  1295 
       
  1296 //---------------------------------------------------------------------------------
       
  1297 TInt CImSendRfc822Header::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
       
  1298 //---------------------------------------------------------------------------------
       
  1299 	{
       
  1300 	// Format the next line of output into rOutputLine.
       
  1301 	// If the output line contains more characters than the size of the source data consumed 
       
  1302 	// in preparing it, then the difference is passed back in aPaddingCount.
       
  1303 
       
  1304 	__ASSERT_DEBUG( iHeader!=NULL, gPanic(KPanicNoRfc822Header) );
       
  1305 	
       
  1306 	TInt advance = 0;
       
  1307 	TInt length = 0;
       
  1308 	TInt localPaddingCount=0;
       
  1309 
       
  1310 	rOutputLine.Zero();
       
  1311 	do 
       
  1312 		{
       
  1313 		switch (iState)
       
  1314 			{
       
  1315 			case EFrom: // top of header, generate 'From'
       
  1316 				advance = FromL( rOutputLine ); // returns 1 if we've finished the field, 0 otherwise
       
  1317 				break;
       
  1318 			case EReplyTo: // generate 'Reply-To'
       
  1319 				advance = ReplyToL( rOutputLine );
       
  1320 				break;
       
  1321 			case ETo: // generate 'To'
       
  1322 				advance = ToL( rOutputLine );
       
  1323 				break;
       
  1324 			case ECc: // generate 'Cc'
       
  1325 				advance = CcL( rOutputLine  );
       
  1326 				break;
       
  1327 			case EBcc: // generate 'Bcc'
       
  1328 				advance = BccL( rOutputLine );
       
  1329 				break;
       
  1330 			case ESubject: // generate 'Subject'
       
  1331 				advance = SubjectL( rOutputLine );
       
  1332 				break;
       
  1333 			case EDate: // generate date
       
  1334 				rOutputLine = KImcvDatePrompt;
       
  1335 				iRfc822Date.SetDate( iTimeDate, rOutputLine );
       
  1336 				advance = 1;
       
  1337 				break;
       
  1338 			case EReturnReceiptTo:
       
  1339 				if (iReceiptFields)
       
  1340 					advance = ReturnReceiptsL( rOutputLine );
       
  1341 				break;
       
  1342 			case EPriority:
       
  1343 				advance = PriorityL(rOutputLine );
       
  1344 				break;
       
  1345 			case EImportance:
       
  1346 				advance = ImportanceL(rOutputLine );
       
  1347 				break;
       
  1348 			case EMessageID:  // iDomainName should be called somewhere before this is called!
       
  1349 				// (use SetDomainNameL(aDomainName))
       
  1350 				SetMessageIdL();
       
  1351 				advance = MessageIdL(rOutputLine);
       
  1352 				break;
       
  1353 			case EXMailer: // quick advert for ourselves
       
  1354 				advance = XMailerL( rOutputLine );
       
  1355 				break;
       
  1356 			}
       
  1357 
       
  1358 		length = rOutputLine.Length();
       
  1359 		if (!length || advance)
       
  1360 			iState ++;
       
  1361 
       
  1362 		} while ( !length && (iState < EEndOfRfc822Header) );
       
  1363 
       
  1364 	if ( !IsLineCRLF( rOutputLine ) )
       
  1365 		// only write something if there is any data!
       
  1366 		AppendCRLF(rOutputLine, localPaddingCount);
       
  1367 		
       
  1368 	rPaddingCount = localPaddingCount;
       
  1369 	return (iState>=EEndOfRfc822Header ? KImCvAdvance : KErrNone);
       
  1370 	}
       
  1371 
       
  1372 // Pass in 16 bit descriptor, encode before outputting
       
  1373 
       
  1374 //---------------------------------------------------------------------------------
       
  1375 void CImSendRfc822Header::PrepareBufferL( const TPtrC8& aPrompt, const TDesC& aData)
       
  1376 //---------------------------------------------------------------------------------
       
  1377 	{
       
  1378 	HBufC8* buf = HBufC8::NewL(aData.Length());
       
  1379 	RBuf8 bufPtr(buf);
       
  1380 	bufPtr.CleanupClosePushL();
       
  1381 	EncodeHeaderFieldL(aData, bufPtr, 0);
       
  1382 	PrepareBufferL(aPrompt,bufPtr);
       
  1383 	CleanupStack::PopAndDestroy(&bufPtr);
       
  1384 
       
  1385 	}
       
  1386 
       
  1387 // data is 8 bit, no encoding.
       
  1388 
       
  1389 //---------------------------------------------------------------------------------
       
  1390 void CImSendRfc822Header::PrepareBufferL( const TPtrC8& aPrompt, const TDesC8& aData)
       
  1391 //---------------------------------------------------------------------------------
       
  1392 	{
       
  1393 	if (iOutputBuffer)
       
  1394 		return;
       
  1395 
       
  1396 	iOutputBuffer = HBufC8::NewL( aPrompt.Length() + aData.Length() + 1 );
       
  1397 	*iOutputBuffer = aPrompt;
       
  1398 
       
  1399 	// need to buffer up some output
       
  1400 	iOutputBuffer->Des().Append( KImcvSpace );
       
  1401 	iOutputBuffer->Des().Append( aData );
       
  1402 	ipOutputBuffer = iOutputBuffer->Ptr();
       
  1403 	}
       
  1404 
       
  1405 
       
  1406 //---------------------------------------------------------------------------------
       
  1407 void CImSendRfc822Header::AddCopyToSelfL(TImSMTPSendCopyToSelf aCopyToSelf, CDesCArray& aList)
       
  1408 //---------------------------------------------------------------------------------
       
  1409 	{
       
  1410 	if (iCopyToSelf==aCopyToSelf)
       
  1411 		{
       
  1412 		if ( iHeader->ReceiptAddress().Length() )
       
  1413 			aList.AppendL(iHeader->ReceiptAddress());
       
  1414 		else if ( iHeader->ReplyTo().Length() )
       
  1415 			aList.AppendL(iHeader->ReplyTo());
       
  1416 		}
       
  1417 	}
       
  1418 
       
  1419 
       
  1420 //---------------------------------------------------------------------------------
       
  1421 TInt CImSendRfc822Header::DoRecipientsL( TDes8& rOutputLine, const TPtrC8& aPrompt, 
       
  1422 										 CDesCArray& aList)
       
  1423 //---------------------------------------------------------------------------------
       
  1424 	{
       
  1425 	if (iOutputBuffer)
       
  1426 		return SendOutput(rOutputLine);
       
  1427 
       
  1428 	// first call into this function, so build the output buffer
       
  1429 	// first establish the length (this is faster than guessing & having to re-allocate)
       
  1430 	TInt32 totalLength = aPrompt.Length()+1;
       
  1431 	TInt i=aList.Count(); // loop counter
       
  1432 	while (i--)
       
  1433 		// allow 2 chars for comma-separation
       
  1434 		totalLength += aList[i].Length() + 2;
       
  1435 
       
  1436 	iOutputBuffer = HBufC8::NewL( totalLength );
       
  1437 	// now build the combined list
       
  1438 	TInt count=aList.Count();
       
  1439 	for ( i=0; i<count; i++ )
       
  1440 		{
       
  1441 		if (!i) // first recipient in list needs to be preceeded by the field identifier
       
  1442 			{
       
  1443 			*iOutputBuffer = aPrompt;
       
  1444 			iOutputBuffer->Des().Append( KImcvSpace );
       
  1445 			}
       
  1446 		else // subsequent ones need comma-separation
       
  1447 			iOutputBuffer->Des().Append( KImcvCommaSpace );
       
  1448 		// ...and of course the data
       
  1449 		HBufC8* buf = HBufC8::NewL((aList[i]).Length());
       
  1450 		RBuf8 bufPtr(buf);
       
  1451 		bufPtr.CleanupClosePushL();
       
  1452 
       
  1453 		EncodeHeaderFieldL(aList[i] , bufPtr, i);
       
  1454 
       
  1455 		HBufC8* addrBuffer = HBufC8::NewLC(bufPtr.Length() * 2);
       
  1456 		TPtr8 addrPtr(addrBuffer->Des());
       
  1457 		addrPtr.Copy(bufPtr);
       
  1458 		HandleSpecialCharacters(addrPtr);
       
  1459 
       
  1460 		// May have to increase size of iOutputBuf
       
  1461 		if (iOutputBuffer->Des().MaxLength() < iOutputBuffer->Des().Length() + addrPtr.Length() + 2)
       
  1462 				iOutputBuffer = iOutputBuffer->ReAllocL( iOutputBuffer->Des().MaxLength() + addrPtr.Length());
       
  1463 		iOutputBuffer->Des().Append( addrPtr);
       
  1464 		bufPtr.Close();
       
  1465 		CleanupStack::PopAndDestroy(2, &bufPtr); // addrBuffer, buf
       
  1466 
       
  1467 		} // for (...)
       
  1468 	ipOutputBuffer = iOutputBuffer->Ptr();
       
  1469 	return SendOutput( rOutputLine );
       
  1470 	}
       
  1471 
       
  1472 void CImSendRfc822Header::PackRemainingData( TDes8& rOutputLine, TPtrC8& aBuf )
       
  1473 	{
       
  1474 
       
  1475 	if (iAddSpaceToNewLine)
       
  1476 		{
       
  1477 		// wrapped lines start with a space to indicate their wrappiness.
       
  1478 		rOutputLine = KImcvSpace;
       
  1479 		rOutputLine.Append( aBuf.Ptr(), aBuf.Length() );
       
  1480 		// we can add this extra byte since MKaxIMailLineLength allows for it 
       
  1481 		rOutputLine.SetLength( aBuf.Length() + 1 );
       
  1482 		}
       
  1483 	else
       
  1484 		{
       
  1485 		rOutputLine = aBuf;
       
  1486 		}
       
  1487 	}
       
  1488 
       
  1489 
       
  1490 //---------------------------------------------------------------------------------
       
  1491 TInt CImSendRfc822Header::SendOutput( TDes8& rOutputLine )
       
  1492 //---------------------------------------------------------------------------------
       
  1493 	{
       
  1494 	// we have buffered output - first check whether we can bung the rest out on one line.
       
  1495 	// the size of the remaining data is the whole length less the distance we've already got through
       
  1496 
       
  1497 	TInt offset = (ipOutputBuffer-iOutputBuffer->Ptr());
       
  1498 
       
  1499 	TInt dataRemaining = iOutputBuffer->Length() - offset;
       
  1500 	if ( dataRemaining < KMaxIMailHeaderWriteLineLength )
       
  1501 		{
       
  1502 		// copy this into the line-output buffer
       
  1503 		if ( !offset )
       
  1504 			{
       
  1505 			// this is the first line for this field since we're still pointing at the start of the buffer
       
  1506 			rOutputLine = *iOutputBuffer;
       
  1507 			}
       
  1508 		else
       
  1509 			{
       
  1510 			TPtrC8 data( ipOutputBuffer, dataRemaining );
       
  1511 			PackRemainingData( rOutputLine, data);
       
  1512 			}
       
  1513 
       
  1514 		delete iOutputBuffer;
       
  1515 		iOutputBuffer 		= NULL;
       
  1516 		ipOutputBuffer 		= NULL;
       
  1517 		iAddSpaceToNewLine 	= EFalse;
       
  1518 		// we can now advance to the next field
       
  1519 		return 1;
       
  1520 		}
       
  1521 	else // we need to send out the data in line-long segments
       
  1522 		{
       
  1523 		// only the first line gets the whole length, cos subsequent ones are prepended with a space.
       
  1524 		TInt lineLength = (offset ? KMaxIMailHeaderWriteLineLength : KMaxIMailHeaderWriteLineLength-1 );
       
  1525 
       
  1526 		TInt pos 	= 0;
       
  1527 		TInt left 	= 0;
       
  1528 		TInt right 	= 0;
       
  1529 		TBool splitAddress = EFalse;
       
  1530 		iAddSpaceToNewLine = EFalse;
       
  1531 
       
  1532 		// if currently handling subject field, then do not attempt to parse for email addresses.
       
  1533 		// This causes encoded words to be split accross line breaks, resulting in garbled text. 
       
  1534 		if (FieldIsEmailAddress())
       
  1535 			{
       
  1536 			TPtrC8 addrData(ipOutputBuffer, dataRemaining);
       
  1537 			while ( ValidEmailAddress( addrData, pos, left, right) )
       
  1538 				{
       
  1539 				if (left+pos < lineLength)
       
  1540 					{
       
  1541 					if (right+pos >= lineLength)
       
  1542 						{
       
  1543 						// Current Email address won't fit into line
       
  1544 						splitAddress = ETrue;
       
  1545 						iAddSpaceToNewLine = ETrue;
       
  1546 						
       
  1547 						if (right - left < lineLength)
       
  1548 							{
       
  1549 							// Break line just before Email address
       
  1550 							lineLength = left+pos;
       
  1551 							break;
       
  1552 							}	
       
  1553 						}
       
  1554 					}
       
  1555 				else
       
  1556 					{
       
  1557 					//length of alias is less than KMaxIMailHeaderWriteLineLength
       
  1558 					 if(left+pos < KMaxIMailHeaderLineLength)
       
  1559 						{
       
  1560 						splitAddress = ETrue;
       
  1561 						iAddSpaceToNewLine = ETrue;
       
  1562 						// Break line just before Email address
       
  1563 						lineLength = left+pos;
       
  1564 						}
       
  1565 					else
       
  1566 						{
       
  1567 						User::Leave(KErrSmtpBufferOverFlow);
       
  1568 						}
       
  1569 					break;
       
  1570 					 }		
       
  1571 			    if (right+pos > lineLength)
       
  1572 					{
       
  1573 					//length of email address is less than KMaxIMailHeaderWriteLineLength
       
  1574 					if(right+pos < KMaxIMailHeaderLineLength)
       
  1575 						{
       
  1576 						splitAddress = ETrue;
       
  1577 						iAddSpaceToNewLine = ETrue;
       
  1578 						// Break line just before Email address
       
  1579 						lineLength = right+pos;	
       
  1580 						}
       
  1581 					else
       
  1582 						{
       
  1583 						User::Leave(KErrSmtpBufferOverFlow);	
       
  1584 						}
       
  1585 					break;
       
  1586 					}	
       
  1587 				// Move pos to end of Email address
       
  1588 				pos += right;
       
  1589 				}
       
  1590 			}
       
  1591 					
       
  1592 		if ( !splitAddress )
       
  1593 			{
       
  1594 			TPtrC8 encData(ipOutputBuffer, dataRemaining);			
       
  1595 			while ( iHeaderConverter.FindEncodedWord(encData, pos, left, right) )
       
  1596 				{
       
  1597 				if (left+pos < lineLength)
       
  1598 					{
       
  1599 					// Second part of condition checks for too long encoded-words 
       
  1600 					if ((right+pos >= lineLength) && (right - left < lineLength))
       
  1601 						{
       
  1602 						// Break line just before encoded word
       
  1603 						lineLength = left+pos;
       
  1604 						iAddSpaceToNewLine = ETrue;
       
  1605 						break;
       
  1606 						}
       
  1607 					}
       
  1608 				else if (right+pos > lineLength)
       
  1609 					break;
       
  1610 				// Move pos to end of the encoded word
       
  1611 				pos += right;
       
  1612 				}
       
  1613 			}
       
  1614 
       
  1615 
       
  1616 		if ( !FieldIsEmailAddress() && !iAddSpaceToNewLine )
       
  1617 			{
       
  1618 				// We have a subject field and no wrapping set at an Encoded Word
       
  1619 				_LIT(KInvalidDataSize, "Data Remaining, not suitable for more than a line");
       
  1620 				__ASSERT_DEBUG( dataRemaining >= KMaxIMailHeaderWriteLineLength, User::Panic(KInvalidDataSize, 1 ));
       
  1621 				
       
  1622 				// Find space from a resonable length onwards in ascending order
       
  1623 				TInt minLineLength = KMaxIMailHeaderWriteLineLength/2;
       
  1624 				TPtrC8 buf(ipOutputBuffer+minLineLength, KMaxIMailHeaderWriteLineLength);
       
  1625 				lineLength = buf.Locate(' ');
       
  1626 				
       
  1627 				if ( lineLength != KErrNotFound )
       
  1628 					{
       
  1629 					// We have found a space
       
  1630 					lineLength += minLineLength;
       
  1631 					// only the first line gets the whole length, cos subsequent ones are prepended with a space.
       
  1632 					TInt maxLineLength = (offset ? KMaxIMailHeaderWriteLineLength : KMaxIMailHeaderWriteLineLength-1 );
       
  1633 					if (left+pos < maxLineLength)
       
  1634 					    {
       
  1635 					    // Second part of condition checks for too long encoded-words 
       
  1636 					    if ((right+pos >= maxLineLength) && pos>0)
       
  1637 					        {
       
  1638 					        rOutputLine = KImcvSpace;
       
  1639 					        }
       
  1640 					    }
       
  1641 					rOutputLine.Append( ipOutputBuffer, lineLength );
       
  1642 					ipOutputBuffer += lineLength;
       
  1643 					}
       
  1644 				else
       
  1645 					{
       
  1646 					// Line length limit is 1000 chars per line including CRLF (RFC2822, Section 2.1.1)
       
  1647                     // 1000 chars including "Field name: "+"Field body"+CRLF (here "Resent-Message-ID: " is largest field)
       
  1648 					if (dataRemaining > KSmtpMaxBufferExcludingCRLF)
       
  1649 						User::Leave(KErrSmtpBufferOverFlow);
       
  1650 	
       
  1651 					// No space found, so send the full remaining buffer as it is
       
  1652 					rOutputLine.Append( ipOutputBuffer, dataRemaining );
       
  1653 					delete iOutputBuffer;
       
  1654 					iOutputBuffer = NULL;
       
  1655 					ipOutputBuffer = NULL;
       
  1656 					return 1;
       
  1657 					}
       
  1658 				
       
  1659 				return 0;
       
  1660 			}
       
  1661 		// create a descriptor for the next line-length of characters
       
  1662 		TPtrC8 data( ipOutputBuffer, lineLength );
       
  1663 
       
  1664 		if ( !offset )
       
  1665 			{
       
  1666 			// this is the first line for this field
       
  1667 			rOutputLine = data;	
       
  1668 			}
       
  1669 		else
       
  1670 			{
       
  1671 			PackRemainingData( rOutputLine, data );
       
  1672 			}
       
  1673 		// advance the data pointer to the next line-length of data
       
  1674 		ipOutputBuffer += lineLength;
       
  1675 
       
  1676 		// prevent ourselves advancing to the next field
       
  1677 		return 0;
       
  1678 		}
       
  1679 	}
       
  1680 
       
  1681 // Assumption:
       
  1682 // data string coming in has already been formatted.
       
  1683 // address1@dd.com, address2@dd.com, addreass3@dd
       
  1684 // 
       
  1685 //---------------------------------------------------------------------------------
       
  1686 TBool CImSendRfc822Header::ValidEmailAddress(const TPtrC8& aData, const TInt aPos, 
       
  1687 															TInt& rStart, TInt& rEnd)
       
  1688 //---------------------------------------------------------------------------------
       
  1689 	{
       
  1690 	TBool found = EFalse;
       
  1691 
       
  1692 	TPtrC8 data = aData.Mid(aPos);
       
  1693 	TInt len = data.Length();
       
  1694 	if (len < 3)
       
  1695 		return found;
       
  1696 	//Assuming that alias does not contain '@'
       
  1697 	TInt at = data.Locate(KImcvAt);
       
  1698 	if ( at!=KErrNotFound )
       
  1699 		{
       
  1700 		found = ETrue;
       
  1701 
       
  1702 		TPtrC8 findEnd(data.Right(len-at));
       
  1703 		TPtrC8 findStart(data.Left(at));
       
  1704 
       
  1705 		rEnd = findEnd.Locate(KImcvComma);
       
  1706 		rStart = findStart.LocateReverse(KImcvSpaceChar);
       
  1707 		} 
       
  1708 
       
  1709 	rEnd = (rEnd==KErrNotFound) ? data.Length() : rEnd+at;
       
  1710 
       
  1711 	if (rStart==KErrNotFound)
       
  1712 		rStart = 0;
       
  1713 
       
  1714 	return found;
       
  1715 	}
       
  1716 
       
  1717 //---------------------------------------------------------------------------------
       
  1718 void CImSendRfc822Header::SetMessageIdL()
       
  1719 //---------------------------------------------------------------------------------
       
  1720 	{
       
  1721 	TInt domainNameLength= iDomainName && iDomainName->Length() ? iDomainName->Length():0;
       
  1722 
       
  1723 	// list of Valid Characters
       
  1724 	TBuf8<52> validCharacterBuffer(KValidCharacters);
       
  1725 	TBuf8<20> randomString;
       
  1726 	HBufC8* messageId = HBufC8::NewL(domainNameLength+24); 
       
  1727 	CleanupStack::PushL(messageId);
       
  1728 
       
  1729 	TPtr8 ptr(messageId->Des());
       
  1730 	TUint result = 0;
       
  1731 	TInt64 randSeed;
       
  1732 	TTime theTime;
       
  1733 
       
  1734 	theTime.UniversalTime(); 
       
  1735 	// Gets the current universal time to use as a random number seed
       
  1736 	randSeed = theTime.Int64();
       
  1737 
       
  1738 	while(randomString.Length()<20)
       
  1739 		{
       
  1740 		result= (Math::Rand(randSeed)%10)*10; 
       
  1741 		result+= Math::Rand(randSeed)%10;
       
  1742 		result%=52;
       
  1743 		randomString.AppendFormat(KImcvCharacterFormat, validCharacterBuffer[result]);
       
  1744 		result=0;
       
  1745 		}
       
  1746 
       
  1747 	ptr.Append(KImcvLeftChevron);
       
  1748 	ptr.Append(randomString.Left(12));
       
  1749 	ptr.Append(KImcvFullStop);
       
  1750 	ptr.Append(randomString.Right(8));
       
  1751 	if (domainNameLength)
       
  1752 		{
       
  1753 		ptr.Append(KImcvAt);
       
  1754 		ptr.Append(iDomainName->Des());
       
  1755 		}
       
  1756 	ptr.Append(KImcvRightChevron);
       
  1757 	iHeader->SetImMsgIdL(messageId->Des()); 
       
  1758 	
       
  1759 	CleanupStack::PopAndDestroy(messageId);
       
  1760 	}
       
  1761 
       
  1762 
       
  1763 //---------------------------------------------------------------------------------
       
  1764 TInt CImSendRfc822Header::PriorityL(TDes8& rOutputLine)
       
  1765 //---------------------------------------------------------------------------------
       
  1766 	{
       
  1767 	if (iPriority==EMsvMediumPriority)
       
  1768 		return 0;
       
  1769 	if (iPriority==EMsvHighPriority)
       
  1770 		PrepareBufferL((*iPriorityFields)[0], KImPrioritySendHigh);
       
  1771 	else if (iPriority==EMsvLowPriority)
       
  1772 		PrepareBufferL((*iPriorityFields)[0], KImPrioritySendLow);
       
  1773 	iPriorityFields->Delete(0);
       
  1774 	SendOutput( rOutputLine );
       
  1775 	
       
  1776 	return (iPriorityFields->Count()) ? 0:1; // Return 1 if array is empty
       
  1777 	}
       
  1778 
       
  1779 //---------------------------------------------------------------------------------
       
  1780 TInt CImSendRfc822Header::ImportanceL(TDes8& rOutputLine)
       
  1781 //---------------------------------------------------------------------------------
       
  1782 	{
       
  1783 	// Although importance means priority, it is a different field and 
       
  1784 	// had a different format. When we send the importance field we send
       
  1785 	// it based on the priority of the e-mail hense the usage of iPriority
       
  1786 
       
  1787 	if (iPriority==EMsvMediumPriority)
       
  1788 		return 0;
       
  1789 	if (iPriority==EMsvHighPriority)
       
  1790 		PrepareBufferL((*iImportanceFields)[0], KImImportanceSendHigh);
       
  1791 	else if (iPriority==EMsvLowPriority)
       
  1792 		PrepareBufferL((*iImportanceFields)[0], KImImportanceSendLow);
       
  1793 	iImportanceFields->Delete(0);
       
  1794 	SendOutput( rOutputLine );
       
  1795 	
       
  1796 	return (iImportanceFields->Count()) ? 0:1; // Return 1 if array is empty
       
  1797 	}
       
  1798 
       
  1799 // calculates & returns the total size of the header info, including the RFC822 tags, 
       
  1800 // comma & space separation, the CRLFs and the blank line after the header itself
       
  1801 
       
  1802 //---------------------------------------------------------------------------------
       
  1803 TInt CImSendRfc822Header::Size() const
       
  1804 //---------------------------------------------------------------------------------
       
  1805 	{
       
  1806 	__ASSERT_DEBUG( iHeader!=NULL, gPanic(KPanicNoRfc822Header) );
       
  1807 
       
  1808 	TInt size = iHeader->DataSize();
       
  1809 
       
  1810 	size+= KImcvFromPrompt().Length() + 3;
       
  1811 	if (iHeader->ReplyTo().
       
  1812 		Length()>0)	//test for existence of replyTo field 
       
  1813 		{
       
  1814 		size+= KImcvReplyToPrompt().Length() + 3;
       
  1815 		}
       
  1816 	size+= KImcvSubjectPrompt().Length() + 3;
       
  1817 	size+= KImcvDateStringLength + KImcvDatePrompt().Length() + 2;
       
  1818 	size+= KImcvXMailer().Length() + iProductName->Length() + 2;
       
  1819 
       
  1820 	
       
  1821 	if (iHeader->ToRecipients().Length())
       
  1822 		size+= KImcvToPrompt().Length()+3 
       
  1823 						+ iHeader->ToRecipients().Count()*2;
       
  1824 	
       
  1825 	if (iHeader->CcRecipients().Length())
       
  1826 		size+= KImcvCcPrompt().Length()+3 
       
  1827 							+ iHeader->CcRecipients().Count()*2;
       
  1828 
       
  1829 	if (iHeader->BccRecipients().Length())
       
  1830 		size+= KImcvBccPrompt().Length()+3 
       
  1831 							+ iHeader->BccRecipients().Count()*2;
       
  1832 
       
  1833 	if (iHeader->ReceiptAddress().Length())  
       
  1834 		// for now there will always be one return receipt field in send.  In future if we implement more than one 
       
  1835 		//field then the size should include other fields. 
       
  1836 		size+= KImcvMsgDispositionTo().Length()+3 
       
  1837 							+ iHeader->ReceiptAddress().Length()+2;
       
  1838 	return size;
       
  1839 	}
       
  1840 
       
  1841 
       
  1842 //---------------------------------------------------------------------------------
       
  1843 TUint CImSendRfc822Header::HeaderCharset() const
       
  1844 //---------------------------------------------------------------------------------
       
  1845 	{
       
  1846 	return iHeader->Charset();
       
  1847 	}
       
  1848 
       
  1849 //---------------------------------------------------------------------------------
       
  1850 void CImSendRfc822Header::EncodeHeaderFieldL(const TDesC& aBufIn, RBuf8& rBufOut, const TInt aArrayVal)
       
  1851 //---------------------------------------------------------------------------------
       
  1852 	{
       
  1853 	CArrayFix<TImHeaderEncodingInfo>* infoArray = &(iHeader->EncodingInfo());
       
  1854 	TImHeaderEncodingInfo::TEncodingType type;
       
  1855 	switch (iHeaderEncoding)
       
  1856 		{
       
  1857 		case EEncodingTypeQP: 
       
  1858 			type=TImHeaderEncodingInfo::EQP;
       
  1859 			break;
       
  1860 		case EEncodingTypeBASE64: 
       
  1861 			type=TImHeaderEncodingInfo::EBase64;
       
  1862 			break;
       
  1863 		case EEncodingTypeUU: 
       
  1864 			type=TImHeaderEncodingInfo::EUU;
       
  1865 			break;
       
  1866 		case EEncodingTypeNone: 
       
  1867 			type=TImHeaderEncodingInfo::ENoEncoding;
       
  1868 			break;
       
  1869 		default:
       
  1870 			__ASSERT_DEBUG( ETrue, gPanic(KPanicInvalidEncodingType) );
       
  1871 			type=TImHeaderEncodingInfo::ENoEncoding;
       
  1872 		}
       
  1873 
       
  1874 	if (iTransformingInfo.SendMethod() == ESendAsSimpleEmail)
       
  1875 		{
       
  1876 		// Don't encode, just convert 
       
  1877 		iHeaderConverter.ConvertHeaderFieldL(aBufIn, rBufOut, FieldIsEmailAddress());
       
  1878 		}
       
  1879 	else if (iHeaderCharset && iHeaderCharset!=KUidMsvCharsetNone)
       
  1880 		{
       
  1881 		iHeaderConverter.EncodeHeaderFieldL(aBufIn, rBufOut, iHeaderCharset, type, FieldIsEmailAddress());
       
  1882 		}
       
  1883 	else if (infoArray->Count())
       
  1884 		{
       
  1885 		// Use encoding information stored from incoming message.
       
  1886 		iHeaderConverter.EncodeHeaderFieldL(aBufIn, rBufOut, infoArray, iState, aArrayVal);
       
  1887 		}
       
  1888 	else
       
  1889 		{
       
  1890 		// Dont encode
       
  1891 		rBufOut.Copy(aBufIn);
       
  1892 		}
       
  1893 	}
       
  1894 
       
  1895 //*********************************************************************************
       
  1896 //              Class CImSendMimeHeader Functions
       
  1897 //*********************************************************************************
       
  1898 
       
  1899 //---------------------------------------------------------------------------------
       
  1900 CImSendMimeHeader* CImSendMimeHeader::NewLC(CImConvertHeader& aConverter, TMimeHeaderType aType)
       
  1901 //---------------------------------------------------------------------------------
       
  1902 	{
       
  1903 	CImSendMimeHeader* self = new (ELeave) CImSendMimeHeader(aConverter, aType);
       
  1904 	CleanupStack::PushL( self );
       
  1905 	return self;
       
  1906 	}
       
  1907 
       
  1908 //---------------------------------------------------------------------------------
       
  1909 CImSendMimeHeader* CImSendMimeHeader::NewL(CImConvertHeader& aConverter, TMimeHeaderType aType)
       
  1910 //---------------------------------------------------------------------------------
       
  1911 	{
       
  1912 	CImSendMimeHeader* self = CImSendMimeHeader::NewLC(aConverter, aType);
       
  1913 	CleanupStack::Pop();
       
  1914 	return self;
       
  1915 	}
       
  1916 
       
  1917 //---------------------------------------------------------------------------------
       
  1918 CImSendMimeHeader::CImSendMimeHeader(CImConvertHeader& aConverter, TMimeHeaderType aType) :
       
  1919 					iConverter(aConverter), iBoundaryString(TPtrC8()), iMimeHeaderType(aType)
       
  1920 //---------------------------------------------------------------------------------
       
  1921 	{
       
  1922 	}
       
  1923 
       
  1924 //---------------------------------------------------------------------------------
       
  1925 CImSendMimeHeader::~CImSendMimeHeader()
       
  1926 //---------------------------------------------------------------------------------
       
  1927 	{
       
  1928 	delete iCharsetString;
       
  1929 	}
       
  1930 				
       
  1931 //---------------------------------------------------------------------------------
       
  1932 void CImSendMimeHeader::InitialiseL( CImMimeHeader& aMimeHeader, const TPtrC aFilename, 
       
  1933 					const TPtrC8& aBoundary,  const TBool aEmbedded, 
       
  1934 					const TMsvEntry& aEntry,  const TImEmailTransformingInfo& aInfo,
       
  1935 					TBool aEmbeddedEmail)
       
  1936 //---------------------------------------------------------------------------------
       
  1937 	{
       
  1938 	iMimeHeader=&aMimeHeader;
       
  1939 	iBoundaryString.Set(aBoundary);
       
  1940 	iFilename = aFilename;
       
  1941 	iHeaderState=0;
       
  1942 	iDealingWithAnEmbeddedEmail = aEmbeddedEmail;
       
  1943 	iEntry=aEntry;
       
  1944 
       
  1945 	TPtrC8 contentType = iMimeHeader->ContentType(); 
       
  1946 	iIsMultipart = (contentType.Length() && contentType==KImcvMultipart) ? ETrue:EFalse;
       
  1947 
       
  1948 	// Set the EncodingType of whatever MIME part it is.
       
  1949 	if (aEmbedded)
       
  1950 		{
       
  1951 		// Deals with the case of a message/rfc22 which is 7 bit.
       
  1952 		iEncodingType=EEncodingTypeNone;
       
  1953 		}
       
  1954 	else if (aEntry.iType==KUidMsvMessageEntry && iMimeHeader->ContentType()!=KImcvMultipart)
       
  1955 		{
       
  1956 		// Special case: for non multipart HTML message.
       
  1957 		if ( ((TMsvEmailEntry)aEntry).MHTMLEmail() )
       
  1958 			{
       
  1959 			if ( aEntry.Attachment())
       
  1960 				{
       
  1961 				iEncodingType=aInfo.AttachmentEncoding();
       
  1962 				SetCharsetUidL(aInfo.HeaderCharset());
       
  1963 				}
       
  1964 			else
       
  1965 				{
       
  1966 				iEncodingType=aInfo.HTMLEncoding();
       
  1967 				SetCharsetUidL(aInfo.HTMLCharset());
       
  1968 				}
       
  1969 			}
       
  1970 		else if (contentType.CompareF(KImcvApplication)==0)
       
  1971 			{
       
  1972 			// So we know it is binary..
       
  1973 			iEncodingType=aInfo.AttachmentEncoding();
       
  1974 			SetCharsetUidL(aInfo.HeaderCharset());
       
  1975 			}
       
  1976 		else
       
  1977 			{
       
  1978 			iEncodingType=aInfo.BodyTextEncoding();
       
  1979 			SetCharsetUidL(aInfo.BodyTextCharset());
       
  1980 			}
       
  1981 		}
       
  1982 	else 
       
  1983 		{
       
  1984 		if  (aEntry.iType == KUidMsvAttachmentEntry)
       
  1985 			{
       
  1986 			iEncodingType=aInfo.AttachmentEncoding();
       
  1987 			SetCharsetUidL(aInfo.HeaderCharset());
       
  1988 			}
       
  1989 		else if (aEntry.iType == KUidMsvEmailHtmlEntry)
       
  1990 			{
       
  1991 			iEncodingType=aInfo.HTMLEncoding();
       
  1992 			SetCharsetUidL(aInfo.HTMLCharset());
       
  1993 			}
       
  1994 		else
       
  1995 			{
       
  1996 			iEncodingType=aInfo.BodyTextEncoding();
       
  1997 			SetCharsetUidL(aInfo.BodyTextCharset());
       
  1998 			}
       
  1999 		}
       
  2000 
       
  2001 	TUint mimeCharset = iMimeHeader->MimeCharset();
       
  2002 	if (mimeCharset)
       
  2003 		SetCharsetUidL(mimeCharset); // Ovverriding the info value passed in.
       
  2004 
       
  2005 	if (aEmbedded)
       
  2006 		{
       
  2007 		iMimeHeader->SetContentTypeL(KImcvMessage);
       
  2008 		iMimeHeader->SetContentSubTypeL(KImcvRfc822);
       
  2009 		}
       
  2010 
       
  2011 	if (iDealingWithAnEmbeddedEmail)
       
  2012 		{
       
  2013  		CImSendFile::EmbeddedEmailFilename(this->iEntry, this->iFilename);
       
  2014  		}
       
  2015 
       
  2016 	}
       
  2017 
       
  2018 //---------------------------------------------------------------------------------
       
  2019 TInt CImSendMimeHeader::NextLine( TDes8& rOutputLine, TInt& rPaddingCount )
       
  2020 //---------------------------------------------------------------------------------
       
  2021 	{
       
  2022 	TInt advance = 0;
       
  2023 	rOutputLine.Zero();
       
  2024 
       
  2025 	switch (iHeaderState)
       
  2026 		{
       
  2027 		case EMimeVersion: // Main only
       
  2028 			if (iMimeHeaderType==EMainMimeHeader)
       
  2029 				{
       
  2030 				advance = MimeVersion(rOutputLine);
       
  2031 				break;
       
  2032 				}
       
  2033 			advance++;  // else continue..
       
  2034 		case EContentLanguage: // Main only
       
  2035 			if (iMimeHeaderType==EMainMimeHeader)
       
  2036 				{
       
  2037 				advance = ContentLanguage( rOutputLine );
       
  2038 				break;
       
  2039 				}
       
  2040 			advance++;  // else continue..
       
  2041 		case EDescription: // Part only
       
  2042 			advance++;
       
  2043 			if ( Description(rOutputLine) )
       
  2044 				break;
       
  2045 			// else continue on to..
       
  2046 		case EContentType:
       
  2047 			advance++;
       
  2048 			if ( ContentType(rOutputLine) )
       
  2049 				break;
       
  2050 			// else continue..
       
  2051 		case EBoundaryString:
       
  2052 			if( iBoundaryString.Length() )
       
  2053 				{
       
  2054 				advance = Boundary(rOutputLine);
       
  2055 				break;
       
  2056 				}
       
  2057 			advance++;  // else continue..
       
  2058 		case EDisposition:
       
  2059 			if (iIsMultipart && !iDealingWithAnEmbeddedEmail)
       
  2060 				advance++;
       
  2061 			else if (Disposition(rOutputLine, advance))
       
  2062 				break;
       
  2063 			// else continue..
       
  2064  		case ETransferEncoding:
       
  2065 			advance++; 
       
  2066 			if ( !iIsMultipart && TransferEncoding(rOutputLine) )
       
  2067 				break;
       
  2068 			// else continue..
       
  2069 		case ECRLF:
       
  2070 			advance += AddCRLF(rOutputLine);
       
  2071 			break;
       
  2072 		default:
       
  2073 			__ASSERT_DEBUG( ETrue, gPanic(EPanicInvalidHeaderState) );
       
  2074 		}
       
  2075 
       
  2076 	iHeaderState += advance;
       
  2077 	rPaddingCount = rOutputLine.Length();
       
  2078 	return (iHeaderState >= EEndOfMimeHeader ? KImAttFinished : KErrNone);
       
  2079 	}
       
  2080 
       
  2081 
       
  2082 //---------------------------------------------------------------------------------
       
  2083 void CImSendMimeHeader::AppendFilenameL( TDes8& rOutputLine ) const
       
  2084 //---------------------------------------------------------------------------------
       
  2085 	{
       
  2086     HBufC8* buf = HBufC8::NewL( iFilename.Length() );
       
  2087 	RBuf8 bufPtr(buf);
       
  2088 	CleanupClosePushL(bufPtr);
       
  2089 	iConverter.EncodeHeaderFieldL( iFilename, bufPtr, iCharsetUid, KDefaultSendingHeaderEncoding, EFalse);
       
  2090 	rOutputLine.Append(KImcvEqualsQuote);
       
  2091 	rOutputLine.Append( bufPtr );	
       
  2092 	rOutputLine.Append(KImcvQuoteString);
       
  2093 	CleanupStack::PopAndDestroy(&bufPtr);
       
  2094 	}
       
  2095 
       
  2096 //---------------------------------------------------------------------------------
       
  2097 void CImSendMimeHeader::SetCharsetUidL(const TUint aId)
       
  2098 //---------------------------------------------------------------------------------
       
  2099 	{
       
  2100 	delete iCharsetString;
       
  2101 	iCharsetString=NULL;
       
  2102 
       
  2103 	iCharsetUid=aId;
       
  2104 
       
  2105 	if (iCharsetUid==KUidMsvCharsetNone)
       
  2106 		// Unknown charset, set string to original	
       
  2107 		iCharsetString = (iMimeHeader->GetContentTypeValue(KImcvCharset)).AllocL();
       
  2108 	else
       
  2109 		{
       
  2110 		if (!iCharsetUid)
       
  2111 			iCharsetUid=iConverter.CharConv().DefaultCharset();
       
  2112 
       
  2113 		iCharsetString = iConverter.CharConv().GetMimeCharsetTextStringL(iCharsetUid);
       
  2114 		}
       
  2115 	}
       
  2116 
       
  2117 //---------------------------------------------------------------------------------
       
  2118 TPtrC8	CImSendMimeHeader::GetCharsetString() const
       
  2119 //---------------------------------------------------------------------------------
       
  2120 	{
       
  2121 	return *iCharsetString;
       
  2122 	}
       
  2123 
       
  2124 
       
  2125 // Only calculates main header size
       
  2126 //---------------------------------------------------------------------------------
       
  2127 TInt CImSendMimeHeader::Size() const
       
  2128 //---------------------------------------------------------------------------------
       
  2129 	{
       
  2130 	TInt size=0;
       
  2131 
       
  2132 	// MIME VERSION
       
  2133 	size+=KImcvMimePrompt().Length() + 
       
  2134 					KImcvSpMimeVersion().Length() + 2;
       
  2135 
       
  2136 	// CONTENT LANGUAGE
       
  2137 	size+=KImcvContentLanguage().Length() + 
       
  2138 					KImcvDefaultLanguage().Length() + 2;
       
  2139 
       
  2140 	// CONTENT TYPE
       
  2141 	TPtrC8 contentType = iMimeHeader->ContentType();
       
  2142 	if (contentType.Length()!=0)
       
  2143 		{
       
  2144 		size += KImcvContentType().Length() +
       
  2145 					contentType.Length() + 2;
       
  2146 
       
  2147 		TPtrC8 contentSubType = iMimeHeader->ContentSubType();
       
  2148 		if ( contentSubType.Length() )
       
  2149 			{
       
  2150 			size += KImcvForwardSlash().Length() + contentSubType.Length() + 2;
       
  2151 			}
       
  2152 
       
  2153 		if ( contentType.CompareF(KImcvText)==0 )
       
  2154 			{
       
  2155 			size += 3 ; // space, =, semi colon
       
  2156 			size += KImcvCharset().Length() + (GetCharsetString()).Length() + 2;
       
  2157 			}
       
  2158 		}
       
  2159 
       
  2160 	// BOUNDARY
       
  2161 	size+= CImSendMimeEmail::KBoundaryStringLength + GetCharsetString().Length() + 2;
       
  2162 
       
  2163 	// TRANSFER ENCODING
       
  2164 	TPtrC8 encodingType = EncodingType();
       
  2165 	if (encodingType.Length())
       
  2166 		size+= KImcvContentTransferEncoding().Length() + encodingType.Length() + 2;
       
  2167 
       
  2168 	// CRLF
       
  2169 	size+= 2;
       
  2170 	
       
  2171 	return size;
       
  2172 	}
       
  2173 
       
  2174 
       
  2175 //*********************************************************************************
       
  2176 //              Class CImSendRichText Functions
       
  2177 //*********************************************************************************
       
  2178 
       
  2179 //---------------------------------------------------------------------------------
       
  2180 CImSendRichText* CImSendRichText::NewLC(CImConvertCharconv& aConv)
       
  2181 //---------------------------------------------------------------------------------
       
  2182 	{
       
  2183 	CImSendRichText* self = new (ELeave) CImSendRichText(aConv);
       
  2184 	CleanupStack::PushL( self );
       
  2185 	return self;
       
  2186 	}
       
  2187 
       
  2188 //---------------------------------------------------------------------------------
       
  2189 CImSendRichText* CImSendRichText::NewL(CImConvertCharconv& aConv)
       
  2190 //---------------------------------------------------------------------------------
       
  2191 	{
       
  2192 	CImSendRichText* self = CImSendRichText::NewLC(aConv);
       
  2193 	CleanupStack::Pop();
       
  2194 	return self;
       
  2195 	}
       
  2196 
       
  2197 //---------------------------------------------------------------------------------
       
  2198 CImSendRichText::CImSendRichText(CImConvertCharconv& aConv) : iConverter(aConv)
       
  2199 //---------------------------------------------------------------------------------
       
  2200 	{
       
  2201 	}
       
  2202 
       
  2203 
       
  2204 //---------------------------------------------------------------------------------
       
  2205 CImSendRichText::~CImSendRichText() 
       
  2206 //---------------------------------------------------------------------------------
       
  2207 	{
       
  2208 	delete iLeftOver;
       
  2209 	delete iPlainBodyText;	
       
  2210 	iCurrentChunk.Close();
       
  2211 	}
       
  2212 
       
  2213 //---------------------------------------------------------------------------------
       
  2214 TBool CImSendRichText::InitialiseL( CMsvServerEntry& aServerEntry,  TImCodec& anEncoder,
       
  2215 								    TImEncodingType aType, TUint aCharset)
       
  2216 //---------------------------------------------------------------------------------
       
  2217 	{
       
  2218 	TBool ret = 0;
       
  2219 	iPos = 0;
       
  2220 	delete iPlainBodyText;	
       
  2221 	iPlainBodyText = NULL;
       
  2222 	iIsNewChunk = ETrue;
       
  2223 
       
  2224 	iCurrentChunk.Close();
       
  2225 	iCurrentChunk.Create(KChunkSize);	
       
  2226 	
       
  2227 	if (aServerEntry.HasStoreL())
       
  2228 		{
       
  2229 		CMsvStore* store = aServerEntry.ReadStoreL();
       
  2230 		CleanupStack::PushL(store);
       
  2231 		
       
  2232 		ret = store->HasBodyTextL();
       
  2233 		if (ret)
       
  2234 			{
       
  2235 			// Initialize the plainbodytext message store for reading the bodytext.
       
  2236 			iPlainBodyText = store->InitialisePlainBodyTextForReadL(KChunkSize);					
       
  2237 			iBodySize = iPlainBodyText->Size(); // Size() returns in no of bytes and the data is 16 bit formatted.
       
  2238 			}	
       
  2239 		
       
  2240 		CleanupStack::PopAndDestroy(store); 
       
  2241 		}
       
  2242 
       
  2243 	if (aCharset ==KCharacterSetIdentifierIso88591 || aCharset== KCharacterSetIdentifierAscii)
       
  2244 		{
       
  2245 		aCharset=KCharacterSetIdentifierCodePage1252;
       
  2246 		}		
       
  2247 
       
  2248 	iPreparedToConvert= iConverter.PrepareToConvertToFromOurCharsetL(aCharset);
       
  2249 
       
  2250 	iBodyEncoding = aType;
       
  2251 	iEncoder=&anEncoder;
       
  2252 
       
  2253 	return ret;
       
  2254 	}
       
  2255 
       
  2256 
       
  2257 
       
  2258 //---------------------------------------------------------------------------------
       
  2259 TInt CImSendRichText::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
       
  2260 //---------------------------------------------------------------------------------
       
  2261 	{
       
  2262 	__ASSERT_DEBUG( iPlainBodyText != NULL, gPanic(KPanicNoRichText) );
       
  2263 
       
  2264 	TInt noMoreChars= 0;
       
  2265 	
       
  2266 	switch (iBodyEncoding)
       
  2267 		{
       
  2268 	case EEncodingTypeQP:
       
  2269 		noMoreChars = EncodeQPNextLineL(rOutputLine, rPaddingCount);
       
  2270 		break;
       
  2271 	case EEncodingTypeUU:
       
  2272 	case EEncodingTypeBASE64:
       
  2273 		noMoreChars = EncodeNextLineL(rOutputLine, rPaddingCount);
       
  2274 		break;
       
  2275 	case EEncodingTypeNone:
       
  2276 	default:
       
  2277 		NoEncodeNextLineL(rOutputLine, rPaddingCount);
       
  2278 		}
       
  2279 	
       
  2280 	return noMoreChars;
       
  2281 	}
       
  2282 
       
  2283 /**
       
  2284 Extract line from the chunk restored from Message Store
       
  2285 @param rOutputLine The output line to be sent.
       
  2286 @return void.
       
  2287 */
       
  2288 void CImSendRichText::ExtractLineFromChunkL(TDes16& aOutputLine)
       
  2289 	{
       
  2290 	// Check if there is enough data in the chunk to extract a line from it.
       
  2291 	if((iPos + iMaxLength) > iCurrentChunk.Length())
       
  2292 		{
       
  2293 		iIsNewChunk = ETrue;		
       
  2294 		}
       
  2295 	
       
  2296 	// Restore the newchunk from the messagestore.
       
  2297 	if(iIsNewChunk)
       
  2298 		{
       
  2299 		iIsNewChunk = EFalse;
       
  2300 		
       
  2301 		// Rearrange the remaining data from current chunk.
       
  2302 		iCurrentChunk.Delete(0, iPos);		
       
  2303 		TInt currentChunkLength = iCurrentChunk.Length();
       
  2304 		
       
  2305 		// Resize iCurrentChunk as per data left for send operation.
       
  2306 		iCurrentChunk.ReAlloc(KChunkSize + currentChunkLength);		
       
  2307 		iCurrentChunk.SetMax();
       
  2308 		
       
  2309 		TPtr16 restoredChunkPtr =  iCurrentChunk.MidTPtr(currentChunkLength);
       
  2310 		
       
  2311 		// Restore the chunk from Message Store.	
       
  2312 		iPlainBodyText->NextChunkL(restoredChunkPtr);
       
  2313 		// if NextChunkL did not return a full size chunk, then need to update the size of iCurrentChunk	
       
  2314 		if(restoredChunkPtr.Length() != KChunkSize)
       
  2315 			{
       
  2316 			iCurrentChunk.SetLength(currentChunkLength + restoredChunkPtr.Length());
       
  2317 			}
       
  2318 		iPos = 0;
       
  2319 		}
       
  2320 
       
  2321 	// Check whether chunk length is not greater than (iPos+iMaxlength).
       
  2322 	if( (iPos + iMaxLength) >= iCurrentChunk.Length() )	
       
  2323 		{
       
  2324 		aOutputLine.Copy(iCurrentChunk.MidTPtr(iPos));	
       
  2325 		}
       
  2326 	else
       
  2327 		{
       
  2328 		aOutputLine.Copy(iCurrentChunk.MidTPtr(iPos, iMaxLength));			
       
  2329 		}
       
  2330 	}
       
  2331 
       
  2332 
       
  2333 // Convert character set of line	
       
  2334 //---------------------------------------------------------------------------------
       
  2335 TInt CImSendRichText::ConvertNextLineL( const TDesC& aInput, TDes8& rOutput)
       
  2336 //---------------------------------------------------------------------------------
       
  2337 	{
       
  2338 	TInt unconvertedChars=0;
       
  2339 	TInt pos=0;
       
  2340 	if (iPreparedToConvert)
       
  2341 		iConverter.ConvertFromOurCharsetL(aInput, rOutput, unconvertedChars, pos);
       
  2342 	else
       
  2343 		rOutput.Copy(aInput);
       
  2344 
       
  2345 	return  pos;
       
  2346 	}
       
  2347 
       
  2348 //---------------------------------------------------------------------------------
       
  2349 TInt CImSendRichText::NoEncodeNextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
       
  2350 //---------------------------------------------------------------------------------
       
  2351 	{ 
       
  2352 	rOutputLine.Zero();
       
  2353 
       
  2354 	// grab a few characters from the buffer 
       
  2355 	// (making sure this is more than we will ever need for the current line).
       
  2356 
       
  2357 	TBuf<2*KMaxIMailBodyLineLength> source;
       
  2358 
       
  2359 	iMaxLength = iPos+2*KMaxIMailBodyLineLength > iBodySize ? 
       
  2360 								iBodySize-iPos : 2*KMaxIMailBodyLineLength;
       
  2361 	
       
  2362 	// Extract line from chunk restored from store.
       
  2363 	ExtractLineFromChunkL(source);
       
  2364 	HBufC* output = HBufC::NewLC(rOutputLine.MaxLength());
       
  2365 
       
  2366 	TPtr outPtr(output->Des());
       
  2367 	TInt ret = RemoveControlCharacters( source, outPtr, rPaddingCount );
       
  2368 
       
  2369 	ConvertNextLineL( outPtr, rOutputLine);
       
  2370 
       
  2371 	CleanupStack::PopAndDestroy(output); 
       
  2372 	return ret;
       
  2373 	}
       
  2374 
       
  2375 
       
  2376 //---------------------------------------------------------------------------------  
       
  2377 TInt CImSendRichText::RemoveControlCharacters( const TDesC& aInputLine, TDes& rOutputLine, TInt& rPaddingCount )
       
  2378 //---------------------------------------------------------------------------------  
       
  2379 	{ 
       
  2380 	TInt written=0;				// number of characters written to the current line
       
  2381 
       
  2382 	TLex lexSource(aInputLine);
       
  2383 	TDes& ptr = rOutputLine;
       
  2384 
       
  2385 	while ( (written<KMaxIMailBodyLineLength) && !lexSource.Eos() )
       
  2386 		{
       
  2387 		// first check whether we're at a line break
       
  2388 		if ( IsEOL(lexSource.Peek()) )
       
  2389 			{
       
  2390 			Append( ptr, (TDesC8&) KImcvCRLF);
       
  2391 			written+=2;
       
  2392 
       
  2393 			// we just added an extra character
       
  2394 			rPaddingCount+=1;
       
  2395 			lexSource.Inc();
       
  2396 			break;
       
  2397 			}
       
  2398 		else if ( SmartBreak(written, lexSource.Remainder()) )
       
  2399 			{
       
  2400 			ptr.Append( lexSource.Peek() );
       
  2401 			Append( ptr, (TDesC8&) KImcvCRLF);
       
  2402 			written+=3;
       
  2403 			rPaddingCount+=2;
       
  2404 			lexSource.Inc();
       
  2405 			break;
       
  2406 			}
       
  2407 		else if ( written >= KMaxIMailBodyLineLength-1 )
       
  2408 			// make sure we don't exceed 76 chars per line of encoded text (must allow for CRLF)
       
  2409 			{
       
  2410 			Append( ptr, (TDesC8&) KImcvCRLF);
       
  2411 			written+=2;
       
  2412 			rPaddingCount+=2;
       
  2413 			}
       
  2414 			// check whether we have a whacky control character from CEditableText
       
  2415 		else if ( lexSource.Peek()<KImcvSP )
       
  2416 			{
       
  2417 			TUint8 replacement = ReplacementChar( lexSource.Peek() );
       
  2418 			if (replacement)	// potentially ditch the character altogther
       
  2419 				{
       
  2420 				ptr.Append( replacement );
       
  2421 				written++;
       
  2422 				}
       
  2423 			else
       
  2424 				rPaddingCount-=1;
       
  2425 			}
       
  2426 		else
       
  2427 			{
       
  2428 			ptr.Append( lexSource.Peek() );
       
  2429 			written++;
       
  2430 			}
       
  2431 		
       
  2432 		// advance to next source character	
       
  2433 		lexSource.Inc();
       
  2434 
       
  2435 		} // while
       
  2436 
       
  2437 	iPos += written - rPaddingCount;
       
  2438 	rPaddingCount = rPaddingCount >=0 ? rPaddingCount : 0;
       
  2439 
       
  2440 	// set up the output parameter & return value
       
  2441 	return (iPos >= iBodySize ? 1 : 0);
       
  2442 	}
       
  2443 
       
  2444 //---------------------------------------------------------------------------------
       
  2445 TInt CImSendRichText::EncodeNextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
       
  2446 //---------------------------------------------------------------------------------
       
  2447 	{ 		
       
  2448 	rOutputLine.Zero();
       
  2449 	TInt sourceLength=0;
       
  2450 
       
  2451 	HBufC8* output = HBufC8::NewLC(rOutputLine.MaxLength());
       
  2452 	TPtr8 outPtr(output->Des());
       
  2453 
       
  2454 	TBuf<KMaxIMailBodyLineLength+1> source;
       
  2455 
       
  2456 	iMaxLength = iPos+KMaxIMailBodyLineLength > iBodySize ? 
       
  2457 								iBodySize-iPos : KMaxIMailBodyLineLength;
       
  2458 	
       
  2459 	TInt leftOverLength= (iLeftOver) ? (*iLeftOver).Length() : 0 ;
       
  2460 	if (leftOverLength < KDecodeLineLength && iPos<iBodySize )
       
  2461 		{
       
  2462 		// Extract line from chunk restored from store.
       
  2463 		ExtractLineFromChunkL(source);
       
  2464 		sourceLength=source.Length();	
       
  2465 
       
  2466 		// Character conversion
       
  2467 		ConvertNextLineL( source, outPtr );
       
  2468 
       
  2469 		ConvertLineBreaks(source, ETrue); 
       
  2470 		}
       
  2471 
       
  2472 	if (iLeftOver)
       
  2473 		{
       
  2474 		outPtr.Insert(0, *iLeftOver);
       
  2475 		delete iLeftOver;
       
  2476 		iLeftOver=NULL;
       
  2477 		}
       
  2478 	
       
  2479 	TInt rem = outPtr.Length() - KDecodeLineLength;
       
  2480 	if (rem>0)
       
  2481 		{
       
  2482 		iLeftOver=(outPtr.Right(rem)).AllocL();
       
  2483 		outPtr.SetLength(KDecodeLineLength);
       
  2484 		}
       
  2485 
       
  2486 	if (outPtr.Length())
       
  2487 		iEncoder->Encode(outPtr, rOutputLine); 
       
  2488 
       
  2489 	if (source.Length()) // some text has bee extracted from the rich text store
       
  2490 		iPos +=sourceLength;
       
  2491 	
       
  2492 	CleanupStack::PopAndDestroy(output); 
       
  2493 
       
  2494 	rPaddingCount=rOutputLine.Length();
       
  2495 
       
  2496 	// set up the output parameter & return value
       
  2497 	return iLeftOver ? 0 : (iPos >= iBodySize ? 1 : 0);
       
  2498 	}
       
  2499 
       
  2500 
       
  2501 //---------------------------------------------------------------------------------
       
  2502 TInt CImSendRichText::EncodeQPNextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
       
  2503 //---------------------------------------------------------------------------------
       
  2504 	{ 		
       
  2505 	rOutputLine.Zero();
       
  2506 	iUseRichText=ETrue;
       
  2507 	TInt sourceUsed=0;
       
  2508 	TInt crlfPadding=0;
       
  2509 	TBool unicodeChars=EFalse;
       
  2510 	TInt originalSource=0;
       
  2511 
       
  2512 	HBufC8* output = HBufC8::NewLC(rOutputLine.MaxLength());
       
  2513 	TPtr8 outPtr(output->Des());
       
  2514 
       
  2515 	TBuf<KMaxIMailBodyLineLength+1> source;
       
  2516 
       
  2517 	iMaxLength = iPos+KMaxIMailBodyLineLength > iBodySize ? 
       
  2518 								iBodySize-iPos : KMaxIMailBodyLineLength;
       
  2519 	
       
  2520 	TInt leftOverLength= (iLeftOver) ? (*iLeftOver).Length() : 0 ;
       
  2521 	if (leftOverLength < KMaxIMailBodyLineLength && iPos<iBodySize )
       
  2522 		{
       
  2523 		// Extract line from chunk restored from store.
       
  2524 		ExtractLineFromChunkL(source);
       
  2525 		crlfPadding=ConvertLineBreaks(source, ETrue); 
       
  2526 		originalSource=source.Length()-crlfPadding;
       
  2527 
       
  2528 		// Character conversion
       
  2529 		ConvertNextLineL( source, outPtr );
       
  2530 
       
  2531 		unicodeChars = (outPtr.Length() > source.Length()) ? ETrue:EFalse;
       
  2532 		}
       
  2533 
       
  2534 	if (iLeftOver)
       
  2535 		outPtr.Insert(0, *iLeftOver);
       
  2536 	
       
  2537 	// QP encode line 
       
  2538 	((TImCodecQP*) iEncoder)->AddPlainChar(KImcvPlainRichText);
       
  2539 
       
  2540 
       
  2541 	TInt written = iEncoder->Encode(outPtr, rOutputLine); 
       
  2542 	TInt leftover = outPtr.Length() - written;
       
  2543 
       
  2544 	if (iLeftOver)
       
  2545 		{
       
  2546 		TInt rem = leftOverLength - written;
       
  2547 		if (rem>0)
       
  2548 			{
       
  2549 			// Not all of the leftOver buffer was used.
       
  2550 			iLeftOver->Des().Copy((*iLeftOver).Right(rem));
       
  2551 			sourceUsed=0;
       
  2552 			}
       
  2553 		else
       
  2554 			{
       
  2555 			delete iLeftOver;
       
  2556 			iLeftOver=NULL;
       
  2557 			if(leftover)
       
  2558  				sourceUsed=rem*(-1);
       
  2559  			else
       
  2560  				sourceUsed=originalSource;
       
  2561 			}
       
  2562 		}
       
  2563 	else if (leftover)
       
  2564 			sourceUsed=written;
       
  2565 	else 
       
  2566 		sourceUsed=originalSource;
       
  2567 
       
  2568 	if (unicodeChars && !iLeftOver && leftover>0)
       
  2569 		{
       
  2570 		iLeftOver=(outPtr.Right(leftover)).AllocL();
       
  2571  		iPos += originalSource;
       
  2572 		}
       
  2573 	else if (source.Length()) // some text has bee extracted from the rich text store
       
  2574 		iPos +=sourceUsed;
       
  2575 	
       
  2576 	CleanupStack::PopAndDestroy(output);
       
  2577 
       
  2578 	rPaddingCount=rOutputLine.Length();
       
  2579 
       
  2580 	// set up the output parameter & return value
       
  2581 	return iLeftOver ? 0 : (iPos >= iBodySize ? 1 : 0);
       
  2582 	}
       
  2583 
       
  2584 
       
  2585 
       
  2586 //---------------------------------------------------------------------------------
       
  2587 TBool CImSendRichText::SmartBreak( TInt aWritten, const TUint8* aSource, TInt aMaxLength )
       
  2588 //---------------------------------------------------------------------------------
       
  2589 	{
       
  2590 	// Check whether the current char is breakable.
       
  2591 
       
  2592 	TBool ret = EFalse;
       
  2593 	TUint8 ch = *aSource;
       
  2594 
       
  2595 	if ( IsBreakable(ch) )
       
  2596 		{
       
  2597 		// Scan ahead looking for the next breakable char
       
  2598 
       
  2599 		const TUint8* lookAhead = aSource+1;
       
  2600 		TBool found = EFalse;
       
  2601 		while ( !found && lookAhead-aSource <= aMaxLength )
       
  2602 			{
       
  2603 			found = IsBreakable(*lookAhead);
       
  2604 			if (!found)
       
  2605 				lookAhead++;
       
  2606 			}
       
  2607 
       
  2608 		// There's another breakable char before the end of the text - we need to break now 
       
  2609 		// if it's too far away and only if the non-breakable text fits on an output line.
       
  2610 
       
  2611 		ret = (aWritten+(lookAhead-aSource) >= KMaxIMailBodyLineLength 
       
  2612 			             && (lookAhead-aSource) < KMaxIMailBodyLineLength);
       
  2613 		}
       
  2614 
       
  2615 	return ret;
       
  2616 	}
       
  2617 
       
  2618 
       
  2619 //---------------------------------------------------------------------------------  
       
  2620 TBool CImSendRichText::SmartBreak( TInt aWritten, const TDesC& aSource )
       
  2621 //---------------------------------------------------------------------------------  
       
  2622 	{
       
  2623 	TBool ret = EFalse;
       
  2624 	TLex source( aSource );
       
  2625 
       
  2626 	// only check for whether we should break if the current char is breakable
       
  2627 	if ( IsBreakable(source.Peek()) )
       
  2628 		{
       
  2629  		// scan ahead looking for the next breakable char
       
  2630 		source.Inc();
       
  2631 		TBool found = EFalse;
       
  2632 		TInt encodingOffset=(IsPlain(source.Peek()) ? 0 : 2);
       
  2633 		while ( !found && !source.Eos() )
       
  2634 			{
       
  2635 			found = IsBreakable(source.Peek());
       
  2636 			if (!found)
       
  2637 				{
       
  2638 				encodingOffset+=(IsPlain(source.Peek()) ? 0 : 2);
       
  2639 				source.Inc();
       
  2640 				}
       
  2641 			}
       
  2642 		// there's another breakable char before the end of the text 
       
  2643 		// - we need to break now if it's too far away
       
  2644 		// but only if the non-breakable text fits on a line itself.
       
  2645 
       
  2646 		ret = ((aWritten+source.Offset()+encodingOffset) > KMaxIMailBodyLineLength-4);
       
  2647 		}
       
  2648 
       
  2649 	return ret;
       
  2650 	}
       
  2651 
       
  2652 //*********************************************************************************
       
  2653 //              Class CImSendFile Functions
       
  2654 //*********************************************************************************
       
  2655 
       
  2656 //---------------------------------------------------------------------------------
       
  2657 CImSendFile* CImSendFile::NewLC(RFs& anFs, CImConvertCharconv& aCharConv)
       
  2658 //---------------------------------------------------------------------------------
       
  2659 	{
       
  2660 	CImSendFile* self = new (ELeave) CImSendFile(anFs, aCharConv);
       
  2661 	CleanupStack::PushL( self );
       
  2662 	self->ConstructL();
       
  2663 	return self;
       
  2664 	}
       
  2665 
       
  2666 //---------------------------------------------------------------------------------
       
  2667 CImSendFile* CImSendFile::NewL(RFs& anFs, CImConvertCharconv& aCharConv)
       
  2668 //---------------------------------------------------------------------------------
       
  2669 	{
       
  2670 	CImSendFile* self = CImSendFile::NewLC(anFs, aCharConv);
       
  2671 	CleanupStack::Pop();
       
  2672 	return self;
       
  2673 	}
       
  2674 
       
  2675 /**
       
  2676 	Intended Usage	:	Second phase of two-phase construction method. Does any 
       
  2677 						allocations required to fully construct the object.
       
  2678 	@since			7.0s
       
  2679 	@leave			KErrNoMemory.
       
  2680 	@pre 			First phase of construction is complete
       
  2681 	@post			The object is fully constructed and initialised.
       
  2682  */
       
  2683 //---------------------------------------------------------------------------------
       
  2684 void CImSendFile::ConstructL()
       
  2685 //---------------------------------------------------------------------------------
       
  2686 	{
       
  2687 	iAttachmentFile = new(ELeave) TImAttachmentFile(CONST_CAST(RFs&,iFs));
       
  2688 	}
       
  2689 
       
  2690 //---------------------------------------------------------------------------------
       
  2691 CImSendFile::CImSendFile(RFs& anFs, CImConvertCharconv& aCharConv) 
       
  2692 	:iFs(anFs), iConverter(aCharConv), iAttachmentFile(NULL)
       
  2693 //---------------------------------------------------------------------------------
       
  2694 	{
       
  2695 	}
       
  2696 
       
  2697 //---------------------------------------------------------------------------------
       
  2698 void CImSendFile::InitialiseL( CMsvServerEntry& aServerEntry, TImFileCodec& anEncoder)
       
  2699 //---------------------------------------------------------------------------------
       
  2700 	{
       
  2701 	iEncoder = &anEncoder;
       
  2702 	iAttachmentState=ENextFile;
       
  2703 	Filename(aServerEntry, iAttachmentInfo);
       
  2704 	}
       
  2705 
       
  2706 //---------------------------------------------------------------------------------
       
  2707 CImSendFile::~CImSendFile() 
       
  2708 //---------------------------------------------------------------------------------
       
  2709 	{
       
  2710 	delete iAttachmentFile;
       
  2711 	}
       
  2712 
       
  2713 //---------------------------------------------------------------------------------
       
  2714 TInt CImSendFile::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
       
  2715 //---------------------------------------------------------------------------------
       
  2716 	{
       
  2717 	rOutputLine.Zero();
       
  2718 				
       
  2719 	do
       
  2720 		{
       
  2721 		switch(iAttachmentState)
       
  2722 			{
       
  2723 		case ENextFile:
       
  2724 			iAttachmentState=EPrefixLines;
       
  2725 			break;
       
  2726 		case EPrefixLines:
       
  2727 			if (iEncoder->PrefixNextLineL(rOutputLine, iAttachmentInfo.iName, rPaddingCount)==KImAttFinished)
       
  2728 				iAttachmentState=EEncodeFile;
       
  2729 			break;		
       
  2730 		case EEncodeFile:
       
  2731 			if (iAttachmentFile->ReadFile( iSourceLine, KDecodeLineLength))
       
  2732 				{
       
  2733 				iAttachmentState=EPostfixLines;
       
  2734 				}
       
  2735 			else if (iSourceLine.Length()!=0)
       
  2736 				{
       
  2737 				iEncoder->Encode(iSourceLine, rOutputLine);	
       
  2738 				rPaddingCount=rOutputLine.Length()-(iSourceLine.Length());
       
  2739 				}
       
  2740 			else
       
  2741 				{
       
  2742 				iAttachmentState=EPostfixLines;
       
  2743 				}
       
  2744 			break;
       
  2745 		case EPostfixLines:
       
  2746 			if (iEncoder->PostfixNextLine(rOutputLine, rPaddingCount)==KImAttFinished)
       
  2747 				iAttachmentState=EEndOfAttachments;
       
  2748 			break;
       
  2749 		case EEndOfAttachments:
       
  2750 			iAttachmentFile->CloseFile();
       
  2751 			iAttachmentState=ECloseDelimiter;
       
  2752 			break;
       
  2753 		case ECloseDelimiter:
       
  2754 			// Dependent on encoding type
       
  2755 			iAttachmentState=ECRLFLine;
       
  2756 			break;				
       
  2757 		case ECRLFLine:
       
  2758 			AddCRLF(rOutputLine, rPaddingCount);
       
  2759 			rPaddingCount=rOutputLine.Length();
       
  2760 			iAttachmentState=EEnd;
       
  2761 			break;				
       
  2762 			}
       
  2763 	
       
  2764 		} while(!rOutputLine.Length());
       
  2765 	
       
  2766 		return (iAttachmentState==EEnd ? KImAttFinished : KErrNone);
       
  2767 	}
       
  2768 
       
  2769 //---------------------------------------------------------------------------------
       
  2770 const TFileName& CImSendFile::Filename() const
       
  2771 //---------------------------------------------------------------------------------
       
  2772 	{
       
  2773 	return iAttachmentInfo.iName;
       
  2774 	}
       
  2775 
       
  2776 TFileName& CImSendFile::Filename(CMsvServerEntry& aEntry, SAttachmentInfo& aInfo)
       
  2777 	{
       
  2778 	TMsvEntry entry = aEntry.Entry();
       
  2779 	aInfo.iSize=entry.iSize; 
       
  2780 
       
  2781 		CMsvStore* store = aEntry.ReadStoreL(); 
       
  2782 		CleanupStack::PushL(store);
       
  2783 		MMsvAttachmentManager& manager=store->AttachmentManagerL();
       
  2784 		if(manager.AttachmentCount())
       
  2785 			{
       
  2786 			CMsvAttachment* attachment = manager.GetAttachmentInfoL(0);
       
  2787 			CleanupStack::PushL(attachment);
       
  2788 			TParsePtrC parse(attachment->FilePath());
       
  2789 			aInfo.iPath=parse.DriveAndPath();
       
  2790 			aInfo.iName=parse.NameAndExt();
       
  2791 			iAttachmentFile->CloseFile();
       
  2792 			RFile file=manager.GetAttachmentFileL(0);
       
  2793 			iAttachmentFile->SetFileHandle(file,TImAttachmentFile::EImFileRead);
       
  2794 			CleanupStack::PopAndDestroy(attachment);	
       
  2795 			}
       
  2796 		CleanupStack::PopAndDestroy(store); 
       
  2797 	return aInfo.iName;
       
  2798 	}
       
  2799 
       
  2800 //---------------------------------------------------------------------------------
       
  2801 void CImSendFile::EmbeddedEmailFilename(TMsvEntry& aEntry, TFileName& aFileName)
       
  2802 //---------------------------------------------------------------------------------
       
  2803  	{
       
  2804  	if (aEntry.iDescription.Length())
       
  2805  		{
       
  2806  		aFileName = aEntry.iDescription;
       
  2807  		if ( (aFileName.MaxLength() - aFileName.Length()) >= KImcvEmbeddedEmailFilenameExtension().Length() )
       
  2808  			{
       
  2809  			aFileName.Insert(aFileName.Length(), KImcvEmbeddedEmailFilenameExtension);
       
  2810  			}
       
  2811  		else
       
  2812  			{
       
  2813  			aFileName = KImcvEmbeddedEmailDefaultFilename;
       
  2814  			aFileName.Insert(aFileName.Length(), KImcvEmbeddedEmailFilenameExtension);
       
  2815  			}
       
  2816  		}
       
  2817  	}
       
  2818  
       
  2819  
       
  2820 
       
  2821 
       
  2822 //*********************************************************************************
       
  2823 //              Class CImCalculateMsgSize Functions
       
  2824 //*********************************************************************************
       
  2825 
       
  2826 //---------------------------------------------------------------------------------
       
  2827 EXPORT_C CImCalculateMsgSize* CImCalculateMsgSize::NewL(RFs &anFs,CMsvServerEntry& aServerEntry)
       
  2828 //---------------------------------------------------------------------------------
       
  2829 	{
       
  2830 	CImCalculateMsgSize* self=new (ELeave) CImCalculateMsgSize(anFs, aServerEntry);
       
  2831 	CleanupStack::PushL(self);
       
  2832 	self->ConstructL();
       
  2833 	CleanupStack::Pop();
       
  2834 	return self;
       
  2835 	}
       
  2836 
       
  2837 
       
  2838 //---------------------------------------------------------------------------------
       
  2839 CImCalculateMsgSize::CImCalculateMsgSize(RFs &anFs,CMsvServerEntry& aServerEntry)
       
  2840 				: 	CMsgActive(EPriorityStandard), iFs(anFs),iServerEntry(aServerEntry)
       
  2841 //---------------------------------------------------------------------------------
       
  2842 	{
       
  2843 	}
       
  2844 
       
  2845 
       
  2846 //---------------------------------------------------------------------------------
       
  2847 void CImCalculateMsgSize::ConstructL()
       
  2848 //---------------------------------------------------------------------------------
       
  2849 	{	
       
  2850 	CActiveScheduler::Add(this);	
       
  2851 	}
       
  2852 
       
  2853 //---------------------------------------------------------------------------------
       
  2854 EXPORT_C CImCalculateMsgSize::~CImCalculateMsgSize()
       
  2855 //---------------------------------------------------------------------------------
       
  2856 	{
       
  2857 	Cancel();
       
  2858 	Reset();
       
  2859 	}
       
  2860 
       
  2861 
       
  2862 //---------------------------------------------------------------------------------
       
  2863 EXPORT_C void CImCalculateMsgSize::StartL(TRequestStatus& aStatus,TMsvId aMsvId,
       
  2864 			TImSendMethod aAlgorithm, TTime& aTimeDate, const TDesC& aDomainName,
       
  2865 			const TUint aCharset)
       
  2866 //---------------------------------------------------------------------------------
       
  2867 	{
       
  2868 	Reset();
       
  2869 	//initialise
       
  2870 	iMailString.Zero();
       
  2871 	iFinished=KErrNone;
       
  2872 	iSize=0;
       
  2873 	//
       
  2874 	iSendMsg=CImSendMessage::NewL(iServerEntry);
       
  2875 	iSendMsg->InitialiseL(aMsvId, aAlgorithm, aTimeDate, aDomainName, aCharset, ESendNoCopy);
       
  2876 	//
       
  2877 #if defined (_DEBUG)
       
  2878 	TBuf<25> KFileName=_L("c:\\mailtest\\imcv\\size.txt");
       
  2879 	TInt err=iFile.Open(iFs, KFileName, EFileStreamText|EFileWrite|EFileShareAny);
       
  2880 	if (err==KErrNotFound) // file does not exist - create it
       
  2881 		{
       
  2882 		err = iFile.Create(iFs, KFileName, EFileStreamText|EFileWrite|EFileShareAny);
       
  2883 		}
       
  2884 	if (err == KErrNone)
       
  2885 		{
       
  2886 		iFileOpen=ETrue;
       
  2887 		}
       
  2888 #endif
       
  2889 	Queue(aStatus);
       
  2890 	TRequestStatus* status=&iStatus;
       
  2891 	User::RequestComplete(status,0);
       
  2892 	SetActive();
       
  2893 	}
       
  2894 
       
  2895 
       
  2896 //---------------------------------------------------------------------------------
       
  2897 void CImCalculateMsgSize::Reset()
       
  2898 //---------------------------------------------------------------------------------
       
  2899 	{
       
  2900 	delete iSendMsg;
       
  2901 	iSendMsg=NULL;
       
  2902 #if defined (_DEBUG)
       
  2903 	if (iFileOpen)
       
  2904 		{
       
  2905 		iFile.Close();
       
  2906 		iFileOpen=EFalse;
       
  2907 		}
       
  2908 #endif
       
  2909 	}
       
  2910 
       
  2911 //---------------------------------------------------------------------------------
       
  2912 void CImCalculateMsgSize::DoRunL()
       
  2913 //---------------------------------------------------------------------------------
       
  2914 	{
       
  2915 	if (iStatus.Int()!=KErrNone || iFinished==KImCvFinished)
       
  2916 		return;
       
  2917 	TInt count=0;
       
  2918 	iFinished=iSendMsg->NextLineL(iMailString,count);
       
  2919 	iSize+=iMailString.Length();
       
  2920 #if defined (_DEBUG)
       
  2921 	if (iFileOpen)
       
  2922 		{
       
  2923 		iFile.Write(iMailString);
       
  2924 		}
       
  2925 #endif
       
  2926 	SetActive();
       
  2927 	TRequestStatus* status=&iStatus;
       
  2928 	User::RequestComplete(status,0);
       
  2929 	}
       
  2930 
       
  2931 
       
  2932 //---------------------------------------------------------------------------------
       
  2933 void CImCalculateMsgSize::DoCancel()
       
  2934 //---------------------------------------------------------------------------------
       
  2935 	{
       
  2936 	CMsgActive::DoCancel();
       
  2937 	}
       
  2938