email/pop3andsmtpmtm/popservermtm/src/POPSOP.CPP
changeset 0 72b543305e3a
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 // Copyright (c) 2008-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 <e32std.h>
       
    17 #include "POPS.H"		//CImPop3Session
       
    18 #include "POPSOP.H"		//CImPop3Operation
       
    19 #include "POPS.PAN"		//IMPP panic codes
       
    20 
       
    21 #include <imcvrecv.h>	//CImRecvConvert
       
    22 #include <imcvutil.h>   //ImCheckDiskSpace utility class
       
    23 #include <msvapi.h>     //MessageServer utility class
       
    24 
       
    25 const TInt KTOPRequestSize = 18; // i.e. 'TOP nnnn 1\r\n' where nnnn can be a 32 bit integer
       
    26 const TInt KTOPBatchLimit = 100; // Pipelining limit of 100 TOP requests at a time
       
    27 
       
    28 // string constants used whilst parsing response from POP3 email server
       
    29 _LIT8(KAuthMatchString,"*SASL *");
       
    30 _LIT8(KAuthPlainMatchString,"* PLAIN*");
       
    31 _LIT8(KAuthLoginMatchString,"* LOGIN*");
       
    32 _LIT8(KAuthCramMD5MatchString,"* CRAM-MD5*");
       
    33 
       
    34 // Special case for non-compliant Domino servers 
       
    35 _LIT8(KAuthDominoMatchString,"*AUTH=*"); 
       
    36 _LIT8(KAuthDominoPlainMatchString,"*=PLAIN*"); 
       
    37 _LIT8(KAuthDominoLoginMatchString,"*=LOGIN*"); 
       
    38 _LIT8(KAuthDominoCramMD5MatchString,"*=CRAM-MD5*"); 
       
    39 
       
    40 // Utility functions declared in IMPP.CPP
       
    41 GLREF_C TBool CommandAccepted(TDesC8& aResponse);
       
    42 
       
    43 // IMPP Panic function
       
    44 GLREF_C void Panic(TPopsPanic aPanic);
       
    45 //
       
    46 // CImPop3Operation - an Abstract base for all the specific POP3 operations
       
    47 //
       
    48 CImPop3Operation::CImPop3Operation()
       
    49 	: CMsgActive(KImPopSessionPriority),iFullStopTerminator(_S8(".\r\n"))
       
    50 	{
       
    51 	_LIT(KPop3Operation,"CImPop3Operation");
       
    52 	__DECLARE_NAME(KPop3Operation());
       
    53 	}
       
    54 
       
    55 CImPop3Operation::~CImPop3Operation()
       
    56 	{
       
    57 	Cancel();
       
    58 	delete iImId;
       
    59 	}
       
    60 
       
    61 //
       
    62 // 2nd stage of construction
       
    63 //
       
    64 void CImPop3Operation::Construct(CImPop3Session *aPopSession)
       
    65 	{
       
    66 	iPopSession=aPopSession;
       
    67 	iTextServer=aPopSession->TextServerSession();
       
    68 	CActiveScheduler::Add(this); 
       
    69 	}
       
    70 
       
    71 void CImPop3Operation::Construct(CImPop3Session *aPopSession, CImRecvConvert* aRecvConverter)
       
    72 	{
       
    73 	Construct(aPopSession);
       
    74 	iRecvConverter=aRecvConverter;
       
    75 	}
       
    76 
       
    77 void CImPop3Operation::DoRunL()
       
    78 	{
       
    79 	iPopSession->SetOpNotPending();
       
    80 
       
    81 	__ASSERT_ALWAYS(iTextServer->GetCurrentTextLine(iTextServerResponse)==ECRLFTerminated,User::Leave(EImppBufferNotTerminated));
       
    82 	if(CommandAccepted(iTextServerResponse)==EFalse)
       
    83 		{
       
    84 		// Message has disapeared already
       
    85 		}
       
    86 	}
       
    87 
       
    88 void CImPop3Operation::DoCancel()
       
    89 	{
       
    90 	iTextServer->Cancel();
       
    91 	if (iRecvConverter != NULL)
       
    92 		{
       
    93 		iRecvConverter->Cancel();
       
    94 		}
       
    95 	CMsgActive::DoCancel();
       
    96 	}
       
    97 //
       
    98 // Queue a read operation to get next line of text
       
    99 //
       
   100 void CImPop3Operation::QueueReadNext()
       
   101 	{
       
   102 	iTextServer->QueueReceiveNextTextLine(iStatus);
       
   103 	SetActive();
       
   104 	}
       
   105 
       
   106 //
       
   107 // Return the Pop3 mailbox index no of a message with give Babel msg id
       
   108 //
       
   109 TInt CImPop3Operation::MessageNo(TMsvId aMsgId)
       
   110 	{
       
   111 	TInt msgNo=iPopSession->MessageNo(aMsgId);
       
   112 	return msgNo;
       
   113 	}
       
   114 
       
   115 //
       
   116 // Check if there's a poperation outstainding if so panic
       
   117 //
       
   118 void CImPop3Operation::CheckIfPending()
       
   119 	{
       
   120 	iPopSession->IsPending() ? Panic(EImppOperationAlreadyPending) : iPopSession->SetPending();
       
   121 	}
       
   122 
       
   123 //
       
   124 // Retrieve a full message or just the specified no of lines
       
   125 //
       
   126 void CImPop3Operation::RetrieveMessageL()
       
   127 	{
       
   128 	iPopSession->SetOpNotPending();
       
   129 	
       
   130 	iTextServer->GetCurrentTextLine(iTextServerResponse);
       
   131 
       
   132 	if(iFirstLine)
       
   133 		{ 
       
   134 		iParsedHeader=EFalse;
       
   135 		iCommandAccepted=CommandAccepted(iTextServerResponse);
       
   136 		iFirstLine=EFalse;
       
   137 		if(!iCommandAccepted)
       
   138 			{
       
   139 			return;
       
   140 			}
       
   141 		}
       
   142 	else
       
   143 		{ 
       
   144 		TBool fakeDot=EFalse;
       
   145 		if(iTextServerResponse.Compare(iFullStopTerminator)!=0)  // header + first n lines last line is a full stop
       
   146 			{
       
   147 			RemoveFirstDot();
       
   148 			if (iRecvConverter->ParseNextField( iTextServerResponse ) == KErrNoMemory)
       
   149 				{
       
   150 				User::Leave(KErrNoMemory);
       
   151 				}
       
   152 			}
       
   153 		else if(iParsedHeader==EFalse)
       
   154 			{
       
   155 			RemoveFirstDot();
       
   156 			_LIT8(KCrLfStr,"\r\n");
       
   157 			if (iRecvConverter->ParseNextField( KCrLfStr ) == KErrNoMemory)
       
   158 				{
       
   159 				User::Leave(KErrNoMemory);
       
   160 				}    
       
   161 			fakeDot=ETrue;
       
   162 			}
       
   163 		else
       
   164 			return;
       
   165   
       
   166 		// test for comp header
       
   167 		if(iRecvConverter->ValidCompleteHeader())
       
   168 			{
       
   169 			iParsedHeader=ETrue;
       
   170 			// test for valid headers
       
   171 			const CImHeader& header = iRecvConverter->Header();
       
   172 			iEmptyHeaders=(   (header.From().Length()==0)
       
   173 							&&(header.ReplyTo().Length()==0)
       
   174 							&&(header.ToRecipients().Count()==0)
       
   175 							&&(header.CcRecipients().Count()==0)
       
   176 							&&(header.BccRecipients().Count()==0));
       
   177 		
       
   178 			// store id of new entry created by IMCV
       
   179 			iNewEntryId = iRecvConverter->EntryId();
       
   180 			// store internet msg id
       
   181 			HBufC8* imId = header.ImMsgId().AllocL();
       
   182 			delete iImId;
       
   183 			iImId = NULL;
       
   184 			iImId = imId;
       
   185 			}
       
   186  
       
   187 		if(fakeDot!=EFalse)
       
   188 			{
       
   189 			return;
       
   190 			}
       
   191 		}
       
   192  
       
   193 	QueueReadNext();
       
   194 	}
       
   195 
       
   196 //
       
   197 // What to do on completion
       
   198 //
       
   199 void CImPop3Operation::DoComplete(TInt& /*aCompleteRequest*/)
       
   200 	{
       
   201 	}
       
   202 
       
   203 TBool CImPop3Operation::PopCommandAccepted()
       
   204 	{
       
   205 	return iCommandAccepted;
       
   206 	}
       
   207 
       
   208 //
       
   209 // Remove first dot of a pair
       
   210 //
       
   211 void CImPop3Operation::RemoveFirstDot()
       
   212 	{
       
   213 	if(iTextServerResponse.Length()>2)
       
   214 		{
       
   215 		if( (iTextServerResponse[0]=='.') && (iTextServerResponse[1]=='.'))
       
   216 			{
       
   217 			iTextServerResponse.Delete(0,1);
       
   218 			}
       
   219 		}
       
   220 	}
       
   221 
       
   222 TPtrC8 CImPop3Operation::ImMsgId()
       
   223 	{ 
       
   224 	return (iImId ? TPtrC8(*iImId) : TPtrC8()); 
       
   225 	}
       
   226 
       
   227 TBool CImPop3Operation::SetMessage(TMsvId anId)
       
   228 	{
       
   229 	iMessageNo=MessageNo(anId);
       
   230 	return iMessageNo == KErrNotFound ? EFalse: ETrue;
       
   231 	}
       
   232 
       
   233 
       
   234 //
       
   235 // CImPop3Stat return no of messages and the mailbox size
       
   236 //
       
   237 CImPop3Stat* CImPop3Stat::NewL(CImPop3Session *aPopSession)
       
   238 	{
       
   239 	CImPop3Stat* self = new (ELeave) CImPop3Stat();
       
   240 	self->Construct(aPopSession);
       
   241 	return self;
       
   242 	}
       
   243 
       
   244 void CImPop3Stat::Start(TRequestStatus& aStatus, TUint &aNoMsg, TUint &aMboxSize)
       
   245 	{
       
   246 	CheckIfPending();
       
   247 
       
   248 	iNoMessages=&aNoMsg;
       
   249 	iMailboxSize=&aMboxSize;
       
   250 
       
   251 	_LIT8(KStatCrLfStr,"STAT\r\n");
       
   252 	iTextServer->SendQueueReceive(iStatus, KStatCrLfStr());
       
   253 	SetActive();
       
   254 	Queue(aStatus);
       
   255 	}
       
   256 
       
   257 // Got a response from the text server
       
   258 
       
   259 void CImPop3Stat::DoRunL()
       
   260 	{
       
   261 	iPopSession->SetOpNotPending();
       
   262 	__ASSERT_ALWAYS(iTextServer->GetCurrentTextLine(iTextServerResponse)==ECRLFTerminated,User::Leave(EImppBufferNotTerminated));
       
   263 		
       
   264 	if(CommandAccepted(iTextServerResponse))
       
   265 		{
       
   266 		TLex8 parseResponse(iTextServerResponse);
       
   267 		parseResponse.SkipCharacters();
       
   268 		parseResponse.SkipSpace();
       
   269 
       
   270 		if(parseResponse.Val(*iNoMessages)==KErrNone)
       
   271 			{
       
   272 			parseResponse.SkipSpace();
       
   273 			parseResponse.Val(*iMailboxSize);
       
   274 			}
       
   275 		else
       
   276 			*iNoMessages=0;
       
   277 		}
       
   278 	}
       
   279 
       
   280 //
       
   281 // CImPop3List list a specific message no  and size or all messages and sizes
       
   282 //
       
   283 CImPop3List* CImPop3List::NewL(CImPop3Session *aPopSession)
       
   284 	{
       
   285 	CImPop3List* self = new (ELeave) CImPop3List();
       
   286 	self->Construct(aPopSession);
       
   287 	return self;
       
   288 	}
       
   289 
       
   290 void CImPop3List::Start(TRequestStatus& aStatus, TUint* aSize)
       
   291 	{
       
   292 	CheckIfPending();
       
   293 	iSize=aSize;
       
   294 	iArrayPos=0;
       
   295 
       
   296 	if(iMessageNo!=0)
       
   297 		{
       
   298 		_LIT8(KListArgCrLfStr,"LIST %d\r\n");
       
   299 		iTextServer->SendQueueReceive(iStatus, KListArgCrLfStr, iMessageNo);
       
   300 		}
       
   301 	else
       
   302 		{
       
   303 		_LIT8(KListCrLfStr,"LIST\r\n");
       
   304 		iTextServer->SendQueueReceive(iStatus,KListCrLfStr());
       
   305 		iFirstLine=ETrue;
       
   306 		}
       
   307 
       
   308 	SetActive();
       
   309 	Queue(aStatus);
       
   310 	}
       
   311 
       
   312 void CImPop3List::DoRunL()
       
   313 	{
       
   314 	iPopSession->SetOpNotPending();
       
   315 	
       
   316 	__ASSERT_ALWAYS(iTextServer->GetCurrentTextLine(iTextServerResponse)==ECRLFTerminated,User::Leave(EImppBufferNotTerminated));
       
   317 	TLex8 parseResponse(iTextServerResponse);
       
   318 
       
   319 	if(iNoResponses > 0)
       
   320 		{
       
   321 		if(CommandAccepted(iTextServerResponse))
       
   322 		User::Leave(KErrNotFound);
       
   323 		}
       
   324 		
       
   325 	if(iMessageNo!=0)
       
   326 		{
       
   327 		if(CommandAccepted(iTextServerResponse))
       
   328 			{
       
   329 			parseResponse.SkipCharacters();
       
   330 			parseResponse.SkipSpace();
       
   331 			GetIndexAndSize(&parseResponse);
       
   332 			}
       
   333 		else
       
   334 			Panic(EImppBabelMsgDoesNotExist);
       
   335 		}
       
   336 	else
       
   337 		{
       
   338 		if(iFirstLine)
       
   339 			{
       
   340 			if(CommandAccepted(iTextServerResponse))
       
   341 				{
       
   342 				iFirstLine=EFalse;
       
   343 				}
       
   344 			else
       
   345 				{
       
   346 				return;
       
   347 				}
       
   348 			}
       
   349 		else
       
   350 			{
       
   351 			if(iTextServerResponse.Compare(iFullStopTerminator)==0)  // list of message info last line is a full stop
       
   352 				{
       
   353 				return;
       
   354 				}
       
   355 			else
       
   356 				{
       
   357 				if(GetIndexAndSize(&parseResponse)==KErrNone)
       
   358 					{
       
   359 					iArrayPos++;
       
   360 					iNoResponses++;
       
   361 					}
       
   362 				else
       
   363 					{
       
   364 					iSize[iArrayPos] = 0;
       
   365 					}
       
   366 				}
       
   367 			}
       
   368 		QueueReadNext();
       
   369 		}
       
   370 	}
       
   371 
       
   372 //
       
   373 // Get size of a specific message (folder view displays message sizes)
       
   374 //
       
   375 TInt CImPop3List::GetIndexAndSize(TLex8 *aLex)
       
   376 	{
       
   377 	aLex->SkipCharacters();
       
   378 	aLex->SkipSpace();
       
   379 	return(aLex->Val(iSize[iArrayPos]));
       
   380 	}
       
   381 
       
   382 //
       
   383 // CImPop3Retr Retrieve a specific message
       
   384 //
       
   385 CImPop3Retr* CImPop3Retr::NewL(CImPop3Session *aPopSession, CImRecvConvert* aRecvConverter, RFs& aFs)
       
   386 	{
       
   387 	CImPop3Retr* self = new (ELeave) CImPop3Retr(aFs);
       
   388 	CleanupStack::PushL(self);
       
   389 	self->ConstructL(aPopSession, aRecvConverter);
       
   390 	CleanupStack::Pop(self);
       
   391 	return self;
       
   392 	}
       
   393 void CImPop3Retr::ConstructL(CImPop3Session *aPopSession, CImRecvConvert* aRecvConverter)
       
   394 	{
       
   395 	Construct(aPopSession,aRecvConverter);
       
   396 	iCurrentDrive = MessageServer::CurrentDriveL(iFs);
       
   397 	}
       
   398 
       
   399 void CImPop3Retr::StartL(TRequestStatus& aStatus)
       
   400 	{
       
   401 	CheckIfPending();
       
   402 	iFirstLine=ETrue;
       
   403 	iNoBytesRetrieved=0;
       
   404 	iEmptyHeaders = EFalse;
       
   405 	ImCheckDiskSpace::LeaveIfLowDiskL(iFs, iCurrentDrive);
       
   406 
       
   407 	iRecvConverter->ResetL();
       
   408 	
       
   409 	_LIT8(KRetrArgCrLfStr,"RETR %d\r\n");
       
   410 	iTextServer->SendQueueReceive(iStatus, KRetrArgCrLfStr, iMessageNo);
       
   411 	SetActive();
       
   412 	Queue(aStatus);
       
   413 	}
       
   414 
       
   415 void CImPop3Retr::DoRunL()
       
   416 	{
       
   417 	RetrieveMessageL();
       
   418 	if(iFirstLine==EFalse)
       
   419 		{
       
   420 		iNoBytesRetrieved+=iTextServerResponse.Length();
       
   421 		}
       
   422 	}
       
   423 
       
   424 TUint CImPop3Retr::Progress()
       
   425 	{
       
   426 	return iNoBytesRetrieved;
       
   427 	}
       
   428 
       
   429 void CImPop3Retr::SetMessageIndex(TInt anIndex)
       
   430 	{
       
   431 	iMessageNo=anIndex;
       
   432 	}
       
   433 //
       
   434 // CImPop3Dele Delete a specified message
       
   435 //
       
   436 CImPop3Dele* CImPop3Dele::NewL(CImPop3Session *aPopSession)
       
   437 	{
       
   438 	CImPop3Dele* self = new (ELeave) CImPop3Dele();
       
   439 	self->Construct(aPopSession);
       
   440 	return self;
       
   441 	}
       
   442 
       
   443 void CImPop3Dele::Start(TRequestStatus& aStatus)
       
   444 	{
       
   445 	CheckIfPending();
       
   446 
       
   447 	_LIT8(KDeleArgCrLfStr,"DELE %d\r\n");
       
   448 	iTextServer->SendQueueReceive(iStatus, KDeleArgCrLfStr, iMessageNo);
       
   449 	SetActive();
       
   450 	Queue(aStatus);
       
   451 	}
       
   452 
       
   453 
       
   454 //
       
   455 // CImPop3Noop No operation (but I'm still here)
       
   456 //
       
   457 CImPop3Noop* CImPop3Noop::NewL(CImPop3Session *aPopSession)
       
   458 	{
       
   459 	CImPop3Noop* self = new (ELeave) CImPop3Noop();
       
   460 	self->Construct(aPopSession);
       
   461 	return self;
       
   462 	}
       
   463 
       
   464 void CImPop3Noop::Start(TRequestStatus& aStatus)
       
   465 	{
       
   466 	CheckIfPending();
       
   467 
       
   468 	_LIT8(KNoopCrLfStr,"NOOP\r\n");
       
   469 	iTextServer->SendQueueReceive(iStatus, KNoopCrLfStr());
       
   470 	SetActive();
       
   471 	Queue(aStatus);
       
   472 	}
       
   473 
       
   474 //
       
   475 // CImPop3Rset Reset
       
   476 //
       
   477 CImPop3Rset* CImPop3Rset::NewL(CImPop3Session *aPopSession)
       
   478 	{
       
   479 	CImPop3Rset* self = new (ELeave) CImPop3Rset();
       
   480 	self->Construct(aPopSession);
       
   481 	return self;
       
   482 	}
       
   483 
       
   484 void CImPop3Rset::Start(TRequestStatus& aStatus)
       
   485 	{
       
   486 	CheckIfPending();
       
   487 	_LIT8(KRsetCrLfStr,"RSET\r\n");
       
   488 	iTextServer->SendQueueReceive(iStatus, KRsetCrLfStr());
       
   489 	SetActive();
       
   490 	Queue(aStatus);
       
   491 	}
       
   492 
       
   493 //
       
   494 // Return specified header and top n lines of message.
       
   495 // If the POP server supports pipelining, TOP requests will be submitted in
       
   496 // batches. The batch size limit is 100 requests.
       
   497 //
       
   498 CImPop3Top* CImPop3Top::NewL(CImPop3Session *aPopSession, CImRecvConvert* aRecvConverter,TBool aHeaderOnly)
       
   499 	{
       
   500 	CImPop3Top* self = new (ELeave) CImPop3Top();
       
   501 	self->ConstructL(aPopSession,aRecvConverter,aHeaderOnly);
       
   502 	return self;
       
   503 	}
       
   504 
       
   505 void CImPop3Top::ConstructL(CImPop3Session *aPopSession, CImRecvConvert* aRecvConverter,TBool aHeaderOnly)
       
   506 	{
       
   507 	CImPop3Operation::Construct(aPopSession,aRecvConverter);
       
   508 	iHeadersOnly = aHeaderOnly;
       
   509 	}
       
   510 
       
   511 void CImPop3Top::StartL(TRequestStatus& aStatus)
       
   512 	{
       
   513 	CheckIfPending();
       
   514 	iFirstLine=ETrue;
       
   515 	iNoBytesRetrieved=0;
       
   516 	iEmptyHeaders = EFalse;
       
   517 
       
   518 	if (iHeadersOnly)
       
   519 		{
       
   520 		iRecvConverter->ResetForHeadersL();
       
   521 		}
       
   522 	else
       
   523 		{
       
   524 		iRecvConverter->ResetL();
       
   525 		}
       
   526 
       
   527 	if(iPipeliningSupported)
       
   528 		{
       
   529 		if(iMessageNo <= iLastMulti)
       
   530 			{
       
   531 			TInt numberToGet = iLastMulti - iStartMsg;
       
   532 			TInt tempStartPos(iStartMsg);
       
   533 			if (numberToGet > KTOPBatchLimit)
       
   534 				{
       
   535 				tempStartPos = iLastMulti - KTOPBatchLimit;
       
   536 				numberToGet = KTOPBatchLimit;
       
   537 				}
       
   538 			HBufC8* buffer = HBufC8::NewLC(numberToGet * KTOPRequestSize);
       
   539 			TPtr8 bufferPtr = buffer->Des();
       
   540 			for(; iLastMulti > tempStartPos; --iLastMulti)
       
   541 				{
       
   542  				if(iPopSession->MessageArray()[iLastMulti-1]==0)
       
   543 					{
       
   544 					_LIT8(KTopArgArgCrLfStr,"TOP %d %d\r\n");
       
   545  					bufferPtr.AppendFormat( KTopArgArgCrLfStr, iLastMulti, iNoLines );
       
   546  					}
       
   547 				}
       
   548 			iTextServer->SendQueueReceive(iStatus, bufferPtr);
       
   549 			CleanupStack::PopAndDestroy(buffer);
       
   550 			}
       
   551 		else
       
   552 			{
       
   553 			// These headers should be on their way already, queue another read
       
   554             QueueReadNext(); // This calls SetActive() for us
       
   555             Queue(aStatus);
       
   556             return;
       
   557 			}
       
   558 		}
       
   559 	else // pipelining not supported by server
       
   560 		{
       
   561 		_LIT8(KTopArgArgCrLfStr,"TOP %d %d\r\n");
       
   562 		iTextServer->SendQueueReceive(iStatus, KTopArgArgCrLfStr, iMessageNo, iNoLines);
       
   563 		}
       
   564 	SetActive();
       
   565 	Queue(aStatus);
       
   566 	}
       
   567 
       
   568 void CImPop3Top::DoRunL()
       
   569 	{
       
   570 	RetrieveMessageL();
       
   571 	if(iFirstLine==EFalse)
       
   572 		{
       
   573 		iNoBytesRetrieved+=iTextServerResponse.Length();
       
   574 		}
       
   575 	}
       
   576 
       
   577 TBool CImPop3Top::SetMessageAndLines(TMsvId aId, TInt aNoLines)
       
   578 	{
       
   579 	iNoLines=aNoLines;
       
   580 	return SetMessage(aId);
       
   581 	}
       
   582 
       
   583 void CImPop3Top::SetMessageIndexAndLines(TInt anIndex, TInt aNoLines)
       
   584 	{
       
   585 	iMessageNo=anIndex;
       
   586 	iNoLines=aNoLines;
       
   587 	}
       
   588 	
       
   589 void CImPop3Top::SetStartAndEndMessageIndex(TInt aStart, TInt aEnd)
       
   590 	{
       
   591 	iPipeliningSupported = ETrue;
       
   592 	iStartMsg = aStart;
       
   593 	iLastMulti = aEnd + 1; // off by one 
       
   594 	}
       
   595 
       
   596 TUint CImPop3Top::Progress()
       
   597 	{
       
   598 	return iNoBytesRetrieved;
       
   599 	}
       
   600 
       
   601 // CImPop3UidlMap
       
   602 //
       
   603 CImPop3UidlMap* CImPop3UidlMap::NewL(TInt aMsgCount)
       
   604 	{
       
   605 	return new(ELeave) CImPop3UidlMap(aMsgCount);
       
   606 	}
       
   607 
       
   608 CImPop3UidlMap::~CImPop3UidlMap()
       
   609 	{}
       
   610 
       
   611 void CImPop3UidlMap::BindL(TInt aMsgIx,const TDesC8& aUidl)
       
   612 	{
       
   613 	// Insert mail Uidls into Uidl array including duplicated uidls.
       
   614 	TInt pos = iUid.InsertIsqAllowDuplicatesL(aUidl,ECmpNormal); 
       
   615 	iMsgNo.InsertL(pos,aMsgIx);
       
   616 	}
       
   617 
       
   618 
       
   619 TInt CImPop3UidlMap::MsgNo(const TDesC8& aUidl) const
       
   620 	{
       
   621 	TInt pos;
       
   622 	if (iUid.FindIsq(aUidl,pos,ECmpNormal)==0)
       
   623 		{
       
   624 		return iMsgNo[pos];
       
   625 		}
       
   626 	return -1;
       
   627 	}
       
   628 
       
   629 TPtrC8 CImPop3UidlMap::At(TInt aMsgIx) const
       
   630 	{
       
   631 	if (iMsgNo.Count())
       
   632 		{
       
   633 		const TInt* p=&iMsgNo[0];
       
   634 		for (TInt ii=iMsgNo.Count();--ii>=0;)
       
   635 			{
       
   636 			if (p[ii]==aMsgIx)
       
   637 				{
       
   638 				return iUid[ii];
       
   639 				}
       
   640 			}
       
   641 		}
       
   642 	return TPtrC8();
       
   643 	}
       
   644 
       
   645 CImPop3UidlMap::CImPop3UidlMap(TInt aMsgCount)
       
   646 	:iUid(aMsgCount),iMsgNo(aMsgCount)
       
   647 	{
       
   648 	__DECLARE_NAME(_S("CImPop3UidlMap"));
       
   649 	}
       
   650 
       
   651 //
       
   652 // CImPop3 Uidl return unique id for a specified message or all the messages
       
   653 //
       
   654 CImPop3Uidl* CImPop3Uidl::NewL(CImPop3Session *aPopSession)
       
   655 	{
       
   656 	CImPop3Uidl* self = new (ELeave) CImPop3Uidl();
       
   657 	self->Construct(aPopSession);
       
   658 	return self;
       
   659 	}
       
   660 
       
   661 void CImPop3Uidl::Start(TRequestStatus& aStatus, CImPop3UidlMap& anArray)
       
   662 	{
       
   663 	CheckIfPending();
       
   664 	iMsgUid=&anArray;
       
   665 	if(iMessageNo!=0)
       
   666 		{
       
   667 		_LIT8(KUidlArgCrLfStr,"UIDL %d\r\n");
       
   668 		iTextServer->SendQueueReceive(iStatus, KUidlArgCrLfStr, iMessageNo);
       
   669 		}
       
   670 	else
       
   671 		{
       
   672 		_LIT8(KUidlCrLfStr,"UIDL\r\n");
       
   673 		iTextServer->SendQueueReceive(iStatus, KUidlCrLfStr());
       
   674 		iFirstLine=ETrue;
       
   675 		}
       
   676 	SetActive();
       
   677 	Queue(aStatus);
       
   678 	}
       
   679 
       
   680 void CImPop3Uidl::DoRunL()
       
   681 	{
       
   682 	iPopSession->SetOpNotPending();
       
   683 	__ASSERT_ALWAYS(iTextServer->GetCurrentTextLine(iTextServerResponse)==ECRLFTerminated,User::Leave(EImppBufferNotTerminated));
       
   684 	TLex8 parseResponse(iTextServerResponse);
       
   685 
       
   686 	if(iMessageNo!=0) // one specific Uid
       
   687 		{
       
   688 		iCommandAccepted=CommandAccepted(iTextServerResponse);
       
   689 		if(iCommandAccepted)
       
   690 			{
       
   691 			parseResponse.SkipCharacters();
       
   692 			parseResponse.SkipSpace();
       
   693 			GetIndexAndUidL(&parseResponse);
       
   694 			}
       
   695 		else
       
   696 			Panic(EImppBabelMsgDoesNotExist);
       
   697 		}
       
   698 	else // list all Uids
       
   699 		{
       
   700 		if(iFirstLine)
       
   701 			{
       
   702 			iCommandAccepted=CommandAccepted(iTextServerResponse);
       
   703 			if(iCommandAccepted)
       
   704 				{
       
   705 				iFirstLine=EFalse;
       
   706 				}
       
   707 			else
       
   708 				{
       
   709 				return;
       
   710 				}
       
   711 			}
       
   712 		else
       
   713 			{
       
   714 			if(iTextServerResponse.Compare(iFullStopTerminator)==0) // list of message info last line is a full stop
       
   715 				{
       
   716 				return;
       
   717 				}
       
   718 			else
       
   719 				{
       
   720 				GetIndexAndUidL(&parseResponse);
       
   721 				}
       
   722 			}
       
   723 		QueueReadNext();
       
   724 		}
       
   725 	}
       
   726 
       
   727 //
       
   728 // Get index no and Pop id of a message
       
   729 //
       
   730 void CImPop3Uidl::GetIndexAndUidL(TLex8* aLex)
       
   731 	{
       
   732 	TInt msgNo;
       
   733 	TInt lexErr=aLex->Val(msgNo);
       
   734 	TLexMark8 uidMarker;
       
   735 
       
   736 	if(lexErr==KErrNone)
       
   737 		{
       
   738 		aLex->SkipSpace();
       
   739 		aLex->Mark(uidMarker);
       
   740 		aLex->SkipCharacters();
       
   741 		iMsgUid->BindL(msgNo-1,aLex->MarkedToken( uidMarker ));
       
   742 		}
       
   743 	}
       
   744 
       
   745 //
       
   746 // CImPop3Capa returns the list of capabilities supported by the server
       
   747 //
       
   748 CImPop3Capa* CImPop3Capa::NewL(CImPop3Session *aPopSession)
       
   749 	{
       
   750 	CImPop3Capa* self = new (ELeave) CImPop3Capa();
       
   751 	self->Construct(aPopSession);
       
   752 	return self;
       
   753 	}
       
   754 
       
   755 void CImPop3Capa::Start(TRequestStatus& aStatus)
       
   756 	{
       
   757 	CheckIfPending();
       
   758 	_LIT8(KCapaCrLfStr,"CAPA\r\n");
       
   759 	iTextServer->SendQueueReceive(iStatus, KCapaCrLfStr());
       
   760 	iFirstLine = ETrue;
       
   761 	SetActive();
       
   762 	Queue(aStatus);
       
   763 	}
       
   764 
       
   765 // Got a response from the text server
       
   766 void CImPop3Capa::DoRunL()
       
   767 	{
       
   768 	iPopSession->SetOpNotPending();
       
   769 
       
   770 	iTextServer->GetCurrentTextLine(iTextServerResponse);
       
   771 	if(iFirstLine)
       
   772 		{ 
       
   773 		iCommandAccepted = CommandAccepted(iTextServerResponse);
       
   774 		iFirstLine = EFalse;
       
   775 		if(!iCommandAccepted)
       
   776 			{
       
   777 			return;
       
   778 			}
       
   779 		}
       
   780 	else
       
   781 		{
       
   782 		if(iTextServerResponse.Compare(iFullStopTerminator) != 0)
       
   783 			{
       
   784 			TInt crPos = iTextServerResponse.Find(KImcvCRLF);
       
   785 			if(crPos>0)
       
   786 				{
       
   787 				TPtrC8 ptr;
       
   788 				ptr.Set(iTextServerResponse.Left(crPos));
       
   789 				_LIT8(KPipelining, "PIPELINING");
       
   790 				
       
   791 				if(ptr.CompareF(KPipelining) == 0)
       
   792 					{
       
   793 					iPipeliningSupported = ETrue;
       
   794 					}
       
   795 					
       
   796 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)				
       
   797 				if (iTextServerResponse.Match(KAuthMatchString) != KErrNotFound || 
       
   798     					iTextServerResponse.Match(KAuthDominoMatchString) != KErrNotFound)
       
   799 					{
       
   800 					SetSaslAuthExtensionFlag();
       
   801 					}
       
   802 #endif					
       
   803 				}
       
   804 			else
       
   805 				return;
       
   806 			}
       
   807 		else
       
   808 			return;
       
   809 		}
       
   810 	QueueReadNext();
       
   811 	}
       
   812 
       
   813 TBool CImPop3Capa::PipeliningSupport()
       
   814 	{
       
   815 	return iPipeliningSupported;
       
   816 	}
       
   817 	
       
   818 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   819 
       
   820 /**
       
   821 To check the Server Response for CAPABILITY command and set iSupportedAuthProfiles accordingly.
       
   822 */
       
   823 void CImPop3Capa::SetSaslAuthExtensionFlag()
       
   824 	{
       
   825 	// check for each supported profile
       
   826 	if (iTextServerResponse.Match(KAuthMatchString) != KErrNotFound)
       
   827 		{
       
   828 		if (iTextServerResponse.Match(KAuthPlainMatchString) != KErrNotFound)
       
   829 			{
       
   830 			iSupportedAuthProfiles|=CPopAuthMechanismHelper::EPlain;
       
   831 			}
       
   832 			
       
   833 		if (iTextServerResponse.Match(KAuthLoginMatchString) != KErrNotFound)
       
   834 			{
       
   835 			iSupportedAuthProfiles|=CPopAuthMechanismHelper::ELogin;
       
   836 			}
       
   837 			
       
   838 		if (iTextServerResponse.Match(KAuthCramMD5MatchString) != KErrNotFound)
       
   839 			{
       
   840 			iSupportedAuthProfiles|=CPopAuthMechanismHelper::ECramMD5;
       
   841 			}
       
   842 		}
       
   843 		
       
   844 	// Special case for Domino servers tagging "=" after "AUTH" 
       
   845 	if (iTextServerResponse.Match(KAuthDominoMatchString) != KErrNotFound)	
       
   846 		{
       
   847 		if (iTextServerResponse.Match(KAuthDominoPlainMatchString) != KErrNotFound) 
       
   848 			{
       
   849 			iSupportedAuthProfiles|=CPopAuthMechanismHelper::EPlain; 
       
   850 			}
       
   851     		
       
   852    		if (iTextServerResponse.Match(KAuthDominoLoginMatchString) != KErrNotFound) 
       
   853    			{
       
   854    			iSupportedAuthProfiles|=CPopAuthMechanismHelper::ELogin; 
       
   855    			}
       
   856     		
       
   857    		if (iTextServerResponse.Match(KAuthDominoCramMD5MatchString) != KErrNotFound) 
       
   858    			{
       
   859    			iSupportedAuthProfiles|=CPopAuthMechanismHelper::ECramMD5;
       
   860    			}
       
   861    		}
       
   862    	}
       
   863 
       
   864 /**
       
   865 To get iSupportedAuthProfiles value.
       
   866 */	
       
   867 TUint CImPop3Capa::SaslAuthExtensionFlag()
       
   868 	{
       
   869 	return iSupportedAuthProfiles;
       
   870 	}
       
   871 #endif
       
   872 
       
   873 // Function will return Index of message(if unique UIDL) Or KErrAlreadyExists(if Duplicate UIdl)
       
   874 //Or KErrNotFound if UIdl not present..
       
   875 TInt CImPop3UidlMap::MsgUidlNo(const TDesC8& aUidl,TInt& aPos) const
       
   876 	{
       
   877 	if (iUid.FindIsq(aUidl,aPos,ECmpNormal) == 0)
       
   878 		{
       
   879 		if(aPos > 0 )
       
   880 			{
       
   881 			//To Check that the index does not exceed size of the iUid array.
       
   882 		 	if(aPos == (iMsgNo.Count() - 1))
       
   883 		 		{
       
   884 		  		if ((iUid[aPos-1]) == aUidl) 
       
   885 		 			{
       
   886 					return KErrAlreadyExists;
       
   887 					}
       
   888 				 }
       
   889 			 else
       
   890 			 	{
       
   891 			 	if ((iUid[aPos-1]) == aUidl || (iUid[aPos+1]) == aUidl) 
       
   892 			 		{
       
   893 			 		return KErrAlreadyExists;
       
   894 			 		}
       
   895 			 		
       
   896 			 	}	 
       
   897 			}
       
   898 			return iMsgNo[aPos];
       
   899 			
       
   900 		}
       
   901 	return KErrNotFound;
       
   902 	}
       
   903 
       
   904 
       
   905 // To return the Index of the UIDL corresponding to a UIDL position.
       
   906 TInt CImPop3UidlMap::MsgIndex(TInt aPos) const
       
   907 	{
       
   908 	return iMsgNo[aPos];
       
   909 	}
       
   910 
       
   911 // To get the no. of UIDLs in the server..
       
   912 TInt CImPop3UidlMap::MsgCount() const
       
   913 	{
       
   914 	return iMsgNo.Count();
       
   915 	}
       
   916 
       
   917 //Return the UIDL at aPos.
       
   918 TPtrC8  CImPop3UidlMap::MsgUidl(TInt aPos) const
       
   919 	{
       
   920 	return iUid[aPos];
       
   921 	}