email/imap4mtm/imapsession/src/cimapsessionmanager.cpp
changeset 0 72b543305e3a
child 55 5b3b2fa8c3ec
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "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 "cimapsettings.h"
       
    17 #include <miut_err.h>		// imap server error codes
       
    18 #include <utf.h>
       
    19 #include <imutcon.h>
       
    20 #include "cimapsessionmanager.h"
       
    21 #include "cimapsession.h"
       
    22 #include "ctransportmanager.h"
       
    23 #include "msocketfactory.h"
       
    24 #include "cimapcapabilityinfo.h"
       
    25 #include "cimaplistfolderinfo.h"
       
    26 #include "cimapservergreetinginfo.h"
       
    27 #include "moutputstream.h"
       
    28 #include "minputstream.h"
       
    29 #include "cimaplogger.h"
       
    30 #include "msocketconnector.h"
       
    31 #include "cimapsessionconsts.h"
       
    32 
       
    33 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
    34 	#include "cimapauthhelpers.h"
       
    35 #endif
       
    36 /**
       
    37 Static factory constructor. Part of two phased construction.
       
    38 
       
    39 @param aImapSettings Settings for the Imap service
       
    40 @param aImapMailStore Imap mail store
       
    41 @return The constructed CImapSessionManager object
       
    42 */
       
    43 EXPORT_C CImapSessionManager* CImapSessionManager::NewL(CImapSettings& aImapSettings, CImapMailStore& aImapMailStore)
       
    44 	{
       
    45 	CImapSessionManager* self = new (ELeave) CImapSessionManager(aImapSettings, aImapMailStore);
       
    46 	CleanupStack::PushL(self);
       
    47 	self->ConstructL();
       
    48 	CleanupStack::Pop(self);
       
    49 	return self;
       
    50 	}
       
    51 
       
    52 /**
       
    53 Class constructor
       
    54 
       
    55 @param aImapSettings Settings for IMAP service
       
    56 @param aImapMailStore Imap mail store
       
    57 */
       
    58 CImapSessionManager::CImapSessionManager(CImapSettings& aImapSettings, CImapMailStore& aImapMailStore)
       
    59 	: CMsgActive(EPriorityStandard)
       
    60 	, iProgressState(TImap4GenericProgress::EIdle)
       
    61 	, iImapSettings(aImapSettings)
       
    62 	, iImapMailStore(aImapMailStore)
       
    63 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
    64 	, iCurrentAuthProfile(CImapAuthMechanismHelper::EUndefined)
       
    65 #endif
       
    66 	{
       
    67 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::CImapSessionManager");
       
    68 	}
       
    69 
       
    70 /**
       
    71 Class destructor
       
    72 */
       
    73 CImapSessionManager::~CImapSessionManager()
       
    74 	{
       
    75 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::~CImapSessionManager");
       
    76 
       
    77 	Cancel();
       
    78 
       
    79 	delete iTransportManager;
       
    80 	delete iImConnect;
       
    81 	iSocketServ.Close();
       
    82 	delete iHostAddr8;
       
    83 	iDisconnectList.Reset();
       
    84 	iSeparatorFolderList.ResetAndDestroy();
       
    85 	delete iImapSession;
       
    86 	}
       
    87 
       
    88 /**
       
    89 Non-trival constructor. Part of two phased construction.
       
    90 */
       
    91 void CImapSessionManager::ConstructL()
       
    92 	{
       
    93 	// We're an active object...
       
    94 	CActiveScheduler::Add(this);
       
    95 	}
       
    96 
       
    97 /**
       
    98 Requests construction of a connected, logged in CImapSession object
       
    99 
       
   100 @param aStatus Signals completion of the request.
       
   101 @param aSession Place to store the session once it is fully created.
       
   102 */
       
   103 EXPORT_C void CImapSessionManager::GetSessionL(TRequestStatus& aStatus, CImapSession*& aSession)
       
   104 	{
       
   105 	__ASSERT_DEBUG(iState == EStateIdle,
       
   106 	               TImapServerPanic::ImapPanic(TImapServerPanic::EUnexpectedStateForGetSession));
       
   107 
       
   108 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::GetSessionL");
       
   109 
       
   110 	iStoreSession = &aSession;
       
   111 
       
   112 	if (!iCreatedNetworkConnection)
       
   113 		{
       
   114 		CreateNetworkConnectionL();
       
   115 		}
       
   116 	else
       
   117 		{
       
   118 		CreateSocketL();
       
   119 		}
       
   120 
       
   121 	Queue(aStatus);
       
   122 	}
       
   123 
       
   124 /**
       
   125 Requests logout and disconnect of a list of sessions.
       
   126 
       
   127 @param aStatus Signals completion of the request.
       
   128 @param aSessionList List of sessions to disconnect
       
   129 */
       
   130 EXPORT_C void CImapSessionManager::Disconnect(TRequestStatus& aStatus, const RPointerArray<CImapSession>& aSessionList)
       
   131 	{
       
   132 	__ASSERT_DEBUG(iState == EStateIdle,
       
   133 	               TImapServerPanic::ImapPanic(TImapServerPanic::EUnexpectedStateForDisConnect));
       
   134 
       
   135 	__ASSERT_DEBUG(iDisconnectList.Count() == 0,
       
   136 	               TImapServerPanic::ImapPanic(TImapServerPanic::EDisconnectWhenDisconnectListNotEmpty1));
       
   137 
       
   138 	// Take a copy of the list of sessions to disconnect
       
   139 	iDisconnectList.Reset();
       
   140 	for (TInt session(0); session < aSessionList.Count(); ++session)
       
   141 		{
       
   142 		__LOG_TEXT(aSessionList[session]->LogId(), "CImapSessionManager::Disconnect (async, list)");
       
   143 
       
   144 		iDisconnectList.Append(aSessionList[session]);
       
   145 		}
       
   146 
       
   147 	iProgressState = TImap4GenericProgress::EDisconnecting;
       
   148 	DisconnectFirstSessionInList();
       
   149 
       
   150 	Queue(aStatus);
       
   151 	}
       
   152 
       
   153 /**
       
   154 Requests immediate disconnect of a list of sessions. The logout command is not
       
   155 sent.
       
   156 
       
   157 @param aSessionList List of sessions to disconnect
       
   158 */
       
   159 EXPORT_C void CImapSessionManager::Disconnect(const RPointerArray<CImapSession>& aSessionList)
       
   160 	{
       
   161 	__ASSERT_DEBUG(iDisconnectList.Count() == 0,
       
   162 	               TImapServerPanic::ImapPanic(TImapServerPanic::EDisconnectWhenDisconnectListNotEmpty2));
       
   163 
       
   164 	// Take a copy of the list of sessions to disconnect
       
   165 	iDisconnectList.Reset();
       
   166 	for (TInt session(0); session < aSessionList.Count(); ++session)
       
   167 		{
       
   168 		__LOG_TEXT(aSessionList[session]->LogId(), "CImapSessionManager::Disconnect (sync, list)");
       
   169 
       
   170 		iDisconnectList.Append(aSessionList[session]);
       
   171 		}
       
   172 
       
   173 	ImmediateDisconnect();
       
   174 	}
       
   175 
       
   176 /**
       
   177 Requests immediate disconnect of a session. The logout command is not sent.
       
   178 
       
   179 @param aSession Session to disconnect
       
   180 */
       
   181 EXPORT_C void CImapSessionManager::Disconnect(const CImapSession& aSession)
       
   182 	{
       
   183 	__ASSERT_DEBUG(iDisconnectList.Count() == 0,
       
   184 	               TImapServerPanic::ImapPanic(TImapServerPanic::EDisconnectWhenDisconnectListNotEmpty3));
       
   185 
       
   186 	__LOG_TEXT(aSession.LogId(), "CImapSessionManager::Disconnect() - START - (sync, session)");
       
   187 
       
   188 	// Create a disconnect list with just this one session
       
   189 	iDisconnectList.Reset();
       
   190 	iDisconnectList.Append(&aSession);
       
   191 	ImmediateDisconnect();
       
   192 
       
   193     __LOG_TEXT(aSession.LogId(), "CImapSessionManager::Disconnect() - END - (sync, session)");
       
   194 	}
       
   195 
       
   196 /**
       
   197 Gets LastSocketActivityTimeout value for the connection
       
   198 
       
   199 @return LastSocketActivityTimeout value
       
   200 */
       
   201 EXPORT_C TUint32 CImapSessionManager::LastSocketActivityTimeout()
       
   202 	{
       
   203 	return iLastSocketActivityTimeout;
       
   204 	}
       
   205 
       
   206 /**
       
   207 Gets progress for an asynchronous operation
       
   208 
       
   209 @param aProgress Holds progress information
       
   210 */
       
   211 EXPORT_C void CImapSessionManager::Progress(TImap4GenericProgress& aProgress)
       
   212 	{
       
   213 	aProgress.iOperation = TImap4GenericProgress::EConnect;
       
   214 	switch(iState)
       
   215 		{
       
   216 	case EStateCreatingNetworkConnection:
       
   217 	case EStateConnectingSocket:
       
   218 	case EStateGettingLastSocketActivityTimeout:
       
   219 	case EStateUpgradingSSLWrappedSocket:
       
   220 	case EStateGreetingWait:
       
   221 	case EStateCapabilityWait:
       
   222 	case EStateStartTLSWait:
       
   223 	case EStateUpgradingTLSSocket:
       
   224 	case EStateSecureCapabilityWait:
       
   225 	case EStateLoginWait:
       
   226 	case EStateSeparatorWait:
       
   227 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   228 	case EStateAuthenticateWait:
       
   229 #endif
       
   230 		{
       
   231 		// We are connecting a session
       
   232 		aProgress.iState = TImap4GenericProgress::EConnecting;
       
   233 		aProgress.iImap4SubStateProgress = TImap4GenericProgress::EIdle;
       
   234 
       
   235 		// iMsgsDone must contain the connection stage information
       
   236 		aProgress.iMsgsDone = GetConnectionStage();
       
   237 		TUint32 iap = 0;
       
   238 		TInt err(KErrNotFound);
       
   239 		// Get the IAP value to store in iMsgsToDo
       
   240 		if (iImConnect != NULL)
       
   241 			{
       
   242 			err = iImConnect->GetIAPValue(iap);
       
   243 			}
       
   244 		if (err == KErrNone)
       
   245 			{
       
   246 			aProgress.iMsgsToDo = iap;
       
   247 			}
       
   248 		else
       
   249 			{
       
   250 			aProgress.iMsgsToDo = err;
       
   251 			}
       
   252 
       
   253 		break;
       
   254 		}
       
   255 
       
   256 	case EStateIdle:
       
   257 	default:
       
   258 		{
       
   259 		aProgress.iState = iProgressState;
       
   260 		aProgress.iImap4SubStateProgress = TImap4GenericProgress::EIdle;
       
   261 		break;
       
   262 		}
       
   263 		}				
       
   264 	}
       
   265 
       
   266 /**
       
   267 From MSocketConnectObserver - called when a connection to the remote server
       
   268 has been successfully made.
       
   269 
       
   270 @param aInputStream Created socket's input stream API
       
   271 @param aOutputStream Created socket's output stream API
       
   272 */
       
   273 void CImapSessionManager::ConnectionMadeL(MInputStream& aInputStream, MOutputStream& aOutputStream)
       
   274 	{
       
   275 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::ConnectionMadeL");
       
   276 
       
   277 	iInputStream = &aInputStream;
       
   278 	iOutputStream = &aOutputStream;
       
   279 
       
   280 	// Temporarily bind to the streams for close notifications.
       
   281 	// Once the session is created, it will take over the binding.
       
   282 	iInputStream->Bind(*this, KDefaultLog);
       
   283 	iOutputStream->Bind(*this, KDefaultLog);
       
   284 	
       
   285 	// Store the current bearer type in the imap settings class
       
   286 	TUint32 bearerType;
       
   287 	iImConnect->GetIAPBearer(bearerType);
       
   288 	iImapSettings.SetCurrentBearerType(bearerType);
       
   289 
       
   290 	CompleteSelf(KErrNone);
       
   291 	}
       
   292 
       
   293 /**
       
   294 From MSocketConnectObserver - Handle the Connection Error
       
   295 
       
   296 Notification that an error has occured in the connecting service. The error 
       
   297 code will have a value of KErrCancel if the observer has stopped the connect 
       
   298 service via the MSocketConnectObserver::StopConnect() API. If a problem
       
   299 does occur the socket connector will suicide after handling the error.
       
   300 
       
   301 @param aError The error code.
       
   302 @return A value of KErrNone if the error has been handled or any other 
       
   303         value if its has not been handled.
       
   304 */
       
   305 TInt CImapSessionManager::HandleConnectError(TInt aError)
       
   306 	{
       
   307 	__LOG_FORMAT((KDefaultLog, "CImapSessionManager::HandleConnectError - %d", aError));
       
   308 
       
   309 	// We should only get this while trying to connect the socket.
       
   310 	// At any other time we can ignore it.
       
   311 	// We can also get this after stopping a socket connect due to a
       
   312 	// cancel. However we will have already self completed and we don't
       
   313 	// want to complete again. If we have completed, then the iSocketConnector
       
   314 	// will have been set to NULL, so check this.
       
   315 	if ((iState == EStateConnectingSocket) && (iSocketConnector != NULL))
       
   316 		{
       
   317 		CompleteSelf(aError);
       
   318 		}
       
   319 
       
   320 	return KErrNone;
       
   321 	}
       
   322 
       
   323 /**
       
   324 From MOutputStreamObserver - Indicates data has been sent successfully.
       
   325 */
       
   326 void CImapSessionManager::SendDataCnf()
       
   327 	{
       
   328 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::SendDataCnf");
       
   329 
       
   330 	// No action required
       
   331 	}
       
   332 
       
   333 /**
       
   334 From MOutputStreamObserver - Indicates that output stream has closed.
       
   335 
       
   336 @param aError Error code that caused stream close.
       
   337 */
       
   338 void CImapSessionManager::OutputStreamCloseInd(TInt aError)
       
   339 	{
       
   340 	__LOG_FORMAT((KDefaultLog, "CImapSessionManager::OutputStreamCloseInd - Error %d, State %d", aError, iState));
       
   341 
       
   342 	// We can only get this when bound to the stream before the stream
       
   343 	// binding is taken over by the session.
       
   344 	__ASSERT_DEBUG(iState == EStateUpgradingSSLWrappedSocket,
       
   345 	               TImapServerPanic::ImapPanic(TImapServerPanic::EUnexpectedOutputStreamCloseInd));
       
   346 
       
   347 	if (iState == EStateUpgradingSSLWrappedSocket)
       
   348 		{
       
   349 		iOutputStream = NULL;
       
   350 
       
   351 		// The only reason the socket should have closed is if a genuine error
       
   352 		// has occured. However if for some reason we don't get an error
       
   353 		// returned we need to complete with KErrDisconnected because the
       
   354 		// socket has closed and we need to tell the caller that we are not
       
   355 		// going to be able to finish creating the requested session.
       
   356 		if (aError >= KErrNone)
       
   357 			{
       
   358 			aError = KErrDisconnected;
       
   359 			}
       
   360 
       
   361 		CompleteSelf(aError);
       
   362 		}
       
   363 	}
       
   364 
       
   365 /**
       
   366 From MOutputStreamSecureObserver - Indicates that a secure socket request
       
   367 has completed on the output stream.
       
   368 
       
   369 @param aError Error code from completed request.
       
   370 */
       
   371 void CImapSessionManager::SecureClientCnf(TInt aError)
       
   372 	{
       
   373 	__LOG_FORMAT((LogId(), "CImapSessionManager::SecureClientCnf - Error %d, State %d", aError, iState));
       
   374 
       
   375 	// Should only get this when we are upgrading to a secure socket
       
   376 	__ASSERT_DEBUG((iState == EStateUpgradingSSLWrappedSocket ||
       
   377 	                iState == EStateUpgradingTLSSocket),
       
   378 	                TImapServerPanic::ImapPanic(TImapServerPanic::EUnexpectedSecureClientCnf));
       
   379 
       
   380 	if ((iState == EStateUpgradingSSLWrappedSocket) ||
       
   381 	    (iState == EStateUpgradingTLSSocket))
       
   382 		{
       
   383 		CompleteSelf(aError);
       
   384 		}
       
   385 	}
       
   386 
       
   387 /**
       
   388 From MInputStreamObserver - Indicates that the stream has received some data.
       
   389 */
       
   390 void CImapSessionManager::ReceivedDataIndL(const TDesC8& /*aBuffer*/)
       
   391 	{
       
   392 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::ReceivedDataIndL");
       
   393 	// No action required
       
   394 	}
       
   395 
       
   396 /**
       
   397 From MInputStreamObserver - Indicates that a secure socket request
       
   398 has completed on the input stream.
       
   399 */
       
   400 void CImapSessionManager::SecureServerCnf()
       
   401 	{
       
   402 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::SecureServerCnf");
       
   403  
       
   404 	// No action required
       
   405 	}
       
   406 
       
   407 /**
       
   408 From MInputStreamObserver - Indicates that the input stream has been closed.
       
   409 
       
   410 @param aError Error code that caused stream close.
       
   411 */
       
   412 void CImapSessionManager::InputStreamCloseInd(TInt aError)
       
   413 	{
       
   414 	__LOG_FORMAT((KDefaultLog, "CImapSessionManager::InputStreamCloseInd - Error %d, State %d", aError, iState));
       
   415 
       
   416 	// We can only get this when bound to the stream before the stream
       
   417 	// binding is taken over by the session.
       
   418 	__ASSERT_DEBUG(iState == EStateUpgradingSSLWrappedSocket,
       
   419 	               TImapServerPanic::ImapPanic(TImapServerPanic::EUnexpectedInputStreamCloseInd));
       
   420 
       
   421 	if (iState == EStateUpgradingSSLWrappedSocket)
       
   422 		{
       
   423 		iInputStream = NULL;
       
   424 
       
   425 		// The only reason the socket should have closed is if a genuine error
       
   426 		// has occured. However if for some reason we don't get an error
       
   427 		// returned we need to complete with KErrDisconnected because the
       
   428 		// socket has closed and we need to tell the caller that we are not
       
   429 		// going to be able to finish creating the requested session.
       
   430 		if (aError >= KErrNone)
       
   431 			{
       
   432 			aError = KErrDisconnected;
       
   433 			}
       
   434 		
       
   435 		// Complete the request if there is no error while upgrading socket to SSL/TLS.
       
   436 		if(!iErrorUpgradingSSLSocket)
       
   437 		   {
       
   438 		   CompleteSelf(aError);	
       
   439 		   }
       
   440 		
       
   441 		}
       
   442 	}
       
   443 
       
   444 /**
       
   445 Called when asynchronous IMAP Session events occur.
       
   446 Manages the various steps necessary to log in to the IMAP Service, or to
       
   447 logout from it.
       
   448 */
       
   449 void CImapSessionManager::DoRunL()
       
   450 	{
       
   451 	iCompletedSelf = EFalse;
       
   452 
       
   453 	// If we get a positive error code such as KErrImapNO, leave now
       
   454 	// which will mean that DoComplete is called with that error code.
       
   455 	// This is derived from CMsgActive, so we should not get any negative
       
   456 	// error codes. They will go straight to DoComplete.
       
   457 	if (iStatus.Int() > KErrNone)
       
   458 		{
       
   459 		User::Leave(iStatus.Int());
       
   460 		}
       
   461 
       
   462 	switch(iState)
       
   463 		{
       
   464 		case EStateCreatingNetworkConnection:
       
   465 			{
       
   466 			ProcessNetworkConnectionCreatedL();
       
   467 			break;
       
   468 			}
       
   469 
       
   470 		case EStateConnectingSocket:
       
   471 			{
       
   472 			ProcessSocketConnectedL();
       
   473 			break;
       
   474 			}
       
   475 
       
   476 		case EStateUpgradingSSLWrappedSocket:
       
   477 			{
       
   478 			ProcessUpgradedSSLWrappedSocketL();
       
   479 			break;
       
   480 			}
       
   481 
       
   482 		case EStateGreetingWait:
       
   483 			{
       
   484 			ProcessGreetingResponseL();
       
   485 			break;
       
   486 			}
       
   487 
       
   488 		case EStateCapabilityWait:
       
   489 			{
       
   490 			ProcessCapabilityResponseL();
       
   491 			break;
       
   492 			}
       
   493 	
       
   494 		case EStateStartTLSWait:
       
   495 			{
       
   496 			ProcessStartTLSResponse();
       
   497 			break;
       
   498 			}
       
   499 
       
   500 		case EStateUpgradingTLSSocket:
       
   501 			{
       
   502 			ProcessUpgradedTLSSocketL();
       
   503 			break;
       
   504 			}
       
   505 
       
   506 		case EStateSecureCapabilityWait:
       
   507 			{
       
   508 			ProcessSecureCapabilityResponseL();
       
   509 			break;
       
   510 			}
       
   511 
       
   512 		case EStateLoginWait:
       
   513 			{
       
   514 			ProcessLoginResponseL();
       
   515 			break;
       
   516 			}
       
   517 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   518 		case EStateAuthenticateWait:
       
   519 			{
       
   520 			ProcessAuthenticateResponseL();
       
   521 			break;
       
   522 			}	
       
   523 #endif
       
   524 		case EStateSeparatorWait:
       
   525 			{
       
   526 			ProcessSeparatorResponseL();
       
   527 			break;
       
   528 			}
       
   529 
       
   530 		case EStateLogoutWait:
       
   531 			{
       
   532 			ProcessLogoutResponse();
       
   533 			break;
       
   534 			}
       
   535 
       
   536 		case EStateDisconnectingSocket:
       
   537 			{
       
   538 			ProcessSocketDisconnected();
       
   539 			break;
       
   540 			}
       
   541 
       
   542 		case EStateGettingLastSocketActivityTimeout:
       
   543 		default:
       
   544 			{
       
   545 			__ASSERT_DEBUG(ETrue, TImapServerPanic::ImapPanic(TImapServerPanic::EUnexpectedStateForDoRunL));
       
   546 			break;
       
   547 			}
       
   548 		}
       
   549 	}
       
   550 
       
   551 /**
       
   552 Cancels the current outstanding asynchronous operation.
       
   553 
       
   554 The operation will only be cancelled here. Any cleanup is deferred to the
       
   555 DoComplete method which will be called next as this is a CMsgActive.
       
   556 */
       
   557 void CImapSessionManager::DoCancel()
       
   558 	{
       
   559 	__LOG_TEXT(LogId(), "CImapSessionManager::DoCancel");
       
   560 
       
   561 	switch(iState)
       
   562 		{
       
   563 		case EStateCreatingNetworkConnection:
       
   564 			{
       
   565 			iImConnect->Cancel();
       
   566 			break;
       
   567 			}
       
   568 
       
   569 		case EStateConnectingSocket:
       
   570 			{
       
   571 			// We will call StopConnect() on the socket connector.
       
   572 			// This is supposed to call back to HandleConnectError with
       
   573 			// KErrCancel once it completes. However it appears that this
       
   574 			// does not always happen, so it is safer to self complete here
       
   575 			// with KErrCancel.
       
   576 			// Just in case the HandleConnectError() routine does get called
       
   577 			// we will set the iSocketConnector to NULL to indicate that the
       
   578 			// request has been cancelled
       
   579 			MSocketConnector* socketConnector(iSocketConnector);
       
   580 			iSocketConnector = NULL;
       
   581 			socketConnector->StopConnect();
       
   582 			CompleteSelf(KErrCancel);
       
   583 			break;
       
   584 			}
       
   585 
       
   586 		case EStateGreetingWait:
       
   587 		case EStateCapabilityWait:
       
   588 		case EStateStartTLSWait:
       
   589 		case EStateSecureCapabilityWait:
       
   590 		case EStateLoginWait:
       
   591 		case EStateSeparatorWait:
       
   592 		case EStateLogoutWait:
       
   593 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   594 		case EStateAuthenticateWait:
       
   595 #endif
       
   596 			{
       
   597 			iImapSession->Cancel();
       
   598 			break;
       
   599 			}
       
   600 
       
   601 		case EStateUpgradingSSLWrappedSocket:
       
   602 		case EStateUpgradingTLSSocket:
       
   603 		case EStateDisconnectingSocket:
       
   604 			{
       
   605 			// There is no specific cancel for any of these states.
       
   606 			// Just self complete with KErrCancel.
       
   607 			CompleteSelf(KErrCancel);
       
   608 			break;
       
   609 			}
       
   610 
       
   611 		case EStateGettingLastSocketActivityTimeout:
       
   612 		default:
       
   613 			{
       
   614 			__ASSERT_DEBUG(ETrue, TImapServerPanic::ImapPanic(TImapServerPanic::EUnexpectedStateForDoCancel));
       
   615 			CompleteSelf(KErrCancel);
       
   616 			break;
       
   617 			}
       
   618 		}
       
   619 
       
   620 	// Call base class version to notify parent class.
       
   621 	CMsgActive::DoCancel();
       
   622 	}
       
   623 
       
   624 /**
       
   625 The current outstanding asynchronous operation has completed.
       
   626 Perform any necessary cleanup.
       
   627 
       
   628 @param aStatus Status of completed operation.
       
   629 */
       
   630 void CImapSessionManager::DoComplete(TInt& aStatus)
       
   631 	{
       
   632 	__LOG_FORMAT((LogId(), "CImapSessionManager::DoComplete - Error %d, State %d", aStatus, iState));
       
   633 
       
   634 	iCompletedSelf = EFalse;
       
   635 	
       
   636 	// If we have completed with an error code, we may want to change it to a
       
   637 	// more specific one based on the state we are in.
       
   638 	if (aStatus != KErrNone)
       
   639 		{
       
   640 		ConvertError(aStatus);
       
   641 		}
       
   642 
       
   643 	// If we have completed with an error, handle any required cleanup
       
   644 	if (aStatus != KErrNone)
       
   645 		{
       
   646 		switch (iState)
       
   647 			{
       
   648 			case EStateCreatingNetworkConnection:
       
   649 				{
       
   650 				delete iImConnect;
       
   651 				iImConnect = NULL;
       
   652 				break;
       
   653 				}
       
   654 
       
   655 			case EStateConnectingSocket:
       
   656 				{
       
   657 				// Nothing required.
       
   658 				break;
       
   659 				}
       
   660 
       
   661 			case EStateGettingLastSocketActivityTimeout:
       
   662 			case EStateUpgradingSSLWrappedSocket:
       
   663 				{
       
   664 				// Need to close the streams as we have not yet passed them
       
   665 				// on to the session.
       
   666 				// Closing the output stream will close the input stream too.
       
   667 				if (iOutputStream != NULL)
       
   668 					{
       
   669 					// Since there was a error while upgrading socket to SSL/TLS.
       
   670 					iErrorUpgradingSSLSocket = ETrue;
       
   671 					iOutputStream->Close();
       
   672 					}
       
   673 				break;
       
   674 				}
       
   675 
       
   676 			case EStateUpgradingTLSSocket:
       
   677 			case EStateGreetingWait:
       
   678 			case EStateCapabilityWait:
       
   679 			case EStateStartTLSWait:
       
   680 			case EStateSecureCapabilityWait:
       
   681 			case EStateLoginWait:
       
   682 			case EStateSeparatorWait:
       
   683 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   684 			case EStateAuthenticateWait:
       
   685 #endif
       
   686 				{
       
   687 				// At this stage, the session has been created so we need
       
   688 				// to close the streams and then delete the session.
       
   689 				CloseSessionStreams(iImapSession);
       
   690 				delete iImapSession;
       
   691 				iImapSession = NULL;
       
   692 				break;
       
   693 				}
       
   694 
       
   695 			case EStateLogoutWait:
       
   696 			case EStateDisconnectingSocket:
       
   697 				{
       
   698 				// Immediately disconnect all the sessions remaining in the disconnect
       
   699 				// list. This is because the protocol controller has no way of knowing
       
   700 				// which ones are disconnected and which ones are not, so it is safer
       
   701 				// just to disconnect them all.
       
   702 				ImmediateDisconnect();
       
   703 				break;
       
   704 				}
       
   705 
       
   706 			default:
       
   707 				{
       
   708 				__ASSERT_DEBUG(ETrue, TImapServerPanic::ImapPanic(TImapServerPanic::EUnexpectedStateForDoCompleteWithError));
       
   709 				break;
       
   710 				}
       
   711 			}
       
   712 		iProgressState = TImap4GenericProgress::EDisconnected;
       
   713 		}
       
   714 	else
       
   715 		{
       
   716 		iProgressState = TImap4GenericProgress::EIdle;
       
   717 		}
       
   718 
       
   719 	// If we have completed successfully, and we are performing a connect,
       
   720 	// store the completed session information in the place requested by the
       
   721 	// caller.
       
   722 	// Note that iImapSession will only be non NULL for a successful connection
       
   723 	// attempt.
       
   724 	if (iImapSession != NULL)
       
   725 		{
       
   726 		*iStoreSession = iImapSession;
       
   727 		iImapSession = NULL;
       
   728 		}
       
   729 
       
   730 	delete iHostAddr8;
       
   731 	iHostAddr8 = NULL;
       
   732 
       
   733 	iInputStream = NULL;
       
   734 	iOutputStream = NULL;
       
   735 	iSocketConnector = NULL;
       
   736 
       
   737 	iState = EStateIdle;
       
   738 	}
       
   739 
       
   740 /**
       
   741 State handler called when network connection has been created.
       
   742 */
       
   743 void CImapSessionManager::ProcessNetworkConnectionCreatedL()
       
   744 	{
       
   745 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::ProcessNetworkConnectionCreatedL");
       
   746 
       
   747 	iCreatedNetworkConnection = ETrue;
       
   748 	CreateSocketL();
       
   749 	}
       
   750 
       
   751 /**
       
   752 State handler called when socket has been connected.
       
   753 */
       
   754 void CImapSessionManager::ProcessSocketConnectedL()
       
   755 	{
       
   756 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::ProcessSocketConnectedL");
       
   757 
       
   758 	// Change state just in case the call to GetLastSocketActivityTimeout
       
   759 	// returns an error and we leave. This allows the subsequent DoComplete
       
   760 	// to clean up the connection
       
   761 	iState = EStateGettingLastSocketActivityTimeout;
       
   762 	User::LeaveIfError(iImConnect->GetLastSocketActivityTimeout(iLastSocketActivityTimeout));
       
   763 
       
   764 	if (iImapSettings.SSLWrapper())
       
   765 		{
       
   766 		iState = EStateUpgradingSSLWrappedSocket;
       
   767 		iErrorUpgradingSSLSocket = EFalse;
       
   768 		CreateSecureSocket();
       
   769 		}
       
   770 	else
       
   771 		{
       
   772 		StartSessionL();
       
   773 		}
       
   774 	}
       
   775 
       
   776 /**
       
   777 State handler called when a socket has been upgraded to SSL.
       
   778 */
       
   779 void CImapSessionManager::ProcessUpgradedSSLWrappedSocketL()
       
   780 	{
       
   781 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::ProcessUpgradedSSLWrappedSocketL");
       
   782 
       
   783 	StartSessionL();
       
   784 	}
       
   785 
       
   786 /**
       
   787 State handler called when a greeting response has been received.
       
   788 */
       
   789 void CImapSessionManager::ProcessGreetingResponseL()
       
   790 	{
       
   791 	__LOG_TEXT(LogId(), "CImapSessionManager::ProcessGreetingResponseL");
       
   792 
       
   793 	const CImapServerGreetingInfo& greetingInfo = iImapSession->ServerGreetingInfo();
       
   794 
       
   795 	switch (greetingInfo.ResponseTag())
       
   796 		{
       
   797 		case CImapServerGreetingInfo::ETagOk:
       
   798 			{
       
   799 			__LOG_TEXT(LogId(), "CImapSessionManager::Greeting response OK");
       
   800 
       
   801 			// Request capability information from server
       
   802 			iImapSession->CapabilityL(iStatus);
       
   803 			iState=EStateCapabilityWait;
       
   804 			SetActive();
       
   805 			break;
       
   806 			}
       
   807 
       
   808 		case CImapServerGreetingInfo::ETagPreAuth:
       
   809 			{
       
   810 			__LOG_TEXT(LogId(), "CImapSessionManager::Greeting response PreAuth");
       
   811 
       
   812 			// Server has pre authenticated us. Just request hierarchy
       
   813 			// separator and complete.
       
   814 			GetHierarchySeparatorL();
       
   815 			break;
       
   816 			}
       
   817 
       
   818 		case CImapServerGreetingInfo::ETagBye:
       
   819 			{
       
   820 			__LOG_TEXT(LogId(), "CImapSessionManager::Greeting response Bye");
       
   821 
       
   822 			// Server is currently busy. Complete with an error
       
   823 			Complete(KErrImapServerBusy);
       
   824 			break;
       
   825 			}
       
   826  
       
   827 		default:
       
   828 			{
       
   829 			__ASSERT_DEBUG(ETrue, TImapServerPanic::ImapPanic(TImapServerPanic::EUnexpectedServerGreetingResponse));
       
   830 			Complete(KErrCorrupt);
       
   831 			break;
       
   832 			}
       
   833 		}
       
   834 	}
       
   835 
       
   836 /**
       
   837 State handler called when a capability response has been received.
       
   838 */
       
   839 void CImapSessionManager::ProcessCapabilityResponseL()
       
   840 	{
       
   841 	__LOG_TEXT(LogId(), "CImapSessionManager::ProcessCapabilityResponseL");
       
   842 
       
   843 	const CImapCapabilityInfo& capabilityInfo = iImapSession->CapabilityInfo();
       
   844 
       
   845 	// Check that a valid IMAP revision number has been received
       
   846 	if (!capabilityInfo.QueryFlag(CImapCapabilityInfo::EVersion4Rev1))
       
   847 		{
       
   848 		__LOG_TEXT(LogId(), "CImapSessionManager - Capability not IMAP4Rev1");
       
   849 
       
   850 		Complete(KErrImapServerVersion);
       
   851 		return;
       
   852 		}
       
   853 
       
   854 	// Check if we must use a secure socket connection
       
   855 	if (iImapSettings.SecureSockets())
       
   856 		{
       
   857 		__LOG_TEXT(LogId(), "CImapSessionManager - Use secure socket");
       
   858 
       
   859 		// We need a secure socket connection, so check that the server
       
   860 		// supports TLS
       
   861 		if (capabilityInfo.QueryFlag(CImapCapabilityInfo::EStartTls))
       
   862 			{
       
   863 			iImapSession->StartTlsL(iStatus);
       
   864 			iState=EStateStartTLSWait;
       
   865 			SetActive();
       
   866 			}
       
   867 		else
       
   868 			{
       
   869 			__LOG_TEXT(LogId(), "CImapSessionManager - Server does not support TLS");
       
   870 
       
   871 			// Server does not support TLS, so complete with an error
       
   872 			Complete(KErrImapServerNoSecurity);
       
   873 			}
       
   874 		}
       
   875 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   876 	else if (iImapSettings.IMAP4Auth())
       
   877 		{
       
   878 		SelectAuthExtensionProfileL(capabilityInfo);
       
   879 		}
       
   880 #endif	
       
   881 	else 
       
   882 		{
       
   883 		if (capabilityInfo.QueryFlag(CImapCapabilityInfo::ELoginDisabled))
       
   884 			{
       
   885 			__LOG_TEXT(LogId(), "CImapSessionManager - Login disabled");
       
   886 
       
   887 			// The server does not support insecure logins, so complete with an error
       
   888 			Complete(KErrImapServerLoginDisabled);
       
   889 			}	
       
   890 		else
       
   891 			{
       
   892 			// Just do plain login
       
   893 			SendLoginL();	
       
   894 			} 
       
   895 		}
       
   896 	}
       
   897 
       
   898 /**
       
   899 State handler called when the Start TLS response has been received.
       
   900 */
       
   901 void CImapSessionManager::ProcessStartTLSResponse()
       
   902 	{
       
   903 	__LOG_TEXT(LogId(), "CImapSessionManager::ProcessCapabilityResponseL");
       
   904 
       
   905 	iState = EStateUpgradingTLSSocket;
       
   906 	CreateSecureSocket();
       
   907 	}
       
   908 
       
   909 /**
       
   910 State handler called when a socket has been upgraded to TLS.
       
   911 */
       
   912 void CImapSessionManager::ProcessUpgradedTLSSocketL()
       
   913 	{
       
   914 	__LOG_TEXT(LogId(), "CImapSessionManager::ProcessUpgradedTLSSocketL");
       
   915 
       
   916 	iImapSession->CapabilityL(iStatus);
       
   917 	iState=EStateSecureCapabilityWait;
       
   918 	SetActive();
       
   919 	}
       
   920 
       
   921 /**
       
   922 State handler called when a capability response has been received after
       
   923 secure connection setup.
       
   924 */
       
   925 void CImapSessionManager::ProcessSecureCapabilityResponseL()
       
   926 	{
       
   927 	__LOG_TEXT(LogId(), "CImapSessionManager::ProcessSecureCapabilityResponseL");
       
   928 
       
   929 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   930 	const CImapCapabilityInfo& capabilityInfo = iImapSession->CapabilityInfo();
       
   931 	if (iImapSettings.IMAP4Auth())
       
   932 		{
       
   933 		SelectAuthExtensionProfileL(capabilityInfo);
       
   934 		}
       
   935 	else
       
   936 #endif 
       
   937 		{
       
   938 		SendLoginL();	
       
   939 		}
       
   940 	}
       
   941 
       
   942 /**
       
   943 State handler called when a login response has been received.
       
   944 */
       
   945 void CImapSessionManager::ProcessLoginResponseL()
       
   946 	{
       
   947 	__LOG_ON(LogId(), ETrue);
       
   948 	__LOG_TEXT(LogId(), "CImapSessionManager::ProcessLoginResponseL");
       
   949 
       
   950 	GetHierarchySeparatorL();
       
   951 	}
       
   952 
       
   953 /**
       
   954 State handler called when a separator response has been received.
       
   955 */
       
   956 void CImapSessionManager::ProcessSeparatorResponseL()
       
   957 	{
       
   958 	__LOG_TEXT(LogId(), "CImapSessionManager::ProcessSeparatorResponseL");
       
   959 
       
   960 	if ((iSeparatorFolderList.Count() > 0) &&
       
   961 	    (iSeparatorFolderList[0]->iHierarchySeperator != '\0'))
       
   962 		{
       
   963 		iImapSettings.SetPathSeparatorL(iSeparatorFolderList[0]->iHierarchySeperator);
       
   964 		}
       
   965 
       
   966 	iSeparatorFolderList.ResetAndDestroy();
       
   967 
       
   968 	Complete(KErrNone);
       
   969 	}
       
   970 
       
   971 /**
       
   972 State handler called when a logout response has been received.
       
   973 */
       
   974 void CImapSessionManager::ProcessLogoutResponse()
       
   975 	{
       
   976 	__LOG_TEXT(LogId(), "CImapSessionManager::ProcessLogoutResponse");
       
   977 
       
   978 	DisconnectSocket();
       
   979 	}
       
   980 
       
   981 /**
       
   982 State handler called when a socket has been disconnected.
       
   983 */
       
   984 void CImapSessionManager::ProcessSocketDisconnected()
       
   985 	{
       
   986 	__LOG_TEXT(LogId(), "CImapSessionManager::ProcessSocketDisconnected");
       
   987 
       
   988 	iDisconnectList.Remove(0);
       
   989 	DisconnectFirstSessionInList();
       
   990 	}
       
   991 
       
   992 /**
       
   993 Start creation of a network connection.
       
   994 */
       
   995 void CImapSessionManager::CreateNetworkConnectionL()
       
   996 	{
       
   997 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::CreateNetworkConnectionL");
       
   998 	
       
   999 	if (iSocketServ.Handle() == 0)
       
  1000 		{
       
  1001 		User::LeaveIfError(iSocketServ.Connect());
       
  1002 		}
       
  1003 
       
  1004 	if (iImConnect == NULL)
       
  1005 		{
       
  1006 		iImConnect = CImConnect::NewL(iImapSettings.IAPPreferences(), iSocketServ);
       
  1007 		}
       
  1008 
       
  1009 	iImConnect->StartL(iStatus);
       
  1010 	iState = EStateCreatingNetworkConnection;
       
  1011 	SetActive();
       
  1012 	}
       
  1013 
       
  1014 /**
       
  1015 Gets the server address and password from the CImapSettings class and
       
  1016 establishes a socket to the server.
       
  1017 */
       
  1018 void CImapSessionManager::CreateSocketL()
       
  1019 	{
       
  1020 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::CreateSocket");
       
  1021 
       
  1022 	if (iTransportManager == NULL)
       
  1023 		{
       
  1024 		iTransportManager = CTransportManager::NewL(iSocketServ.Handle(), iImConnect->GetConnection());
       
  1025 		}
       
  1026 
       
  1027 	TPtrC hostAddress = iImapSettings.ServerAddress();
       
  1028 	TInt hostPort     = iImapSettings.Port();
       
  1029 
       
  1030 	iHostAddr8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(hostAddress);	
       
  1031 	TPtr8 addr8ptr = iHostAddr8->Des();
       
  1032 
       
  1033 	iSocketConnector = &(iTransportManager->SocketFactory().ConnectL(*this, addr8ptr, hostPort));
       
  1034 
       
  1035 	iState = EStateConnectingSocket;
       
  1036 	iStatus = KRequestPending;
       
  1037 	SetActive();
       
  1038 	}
       
  1039 
       
  1040 /**
       
  1041 Start creation of a secure socket.
       
  1042 */
       
  1043 void CImapSessionManager::CreateSecureSocket()
       
  1044 	{
       
  1045 	__LOG_TEXT(LogId(), "CImapSessionManager::CreateSecureSocket");
       
  1046 
       
  1047 	iOutputStream->BindSecure(*this);
       
  1048 
       
  1049 	TPtrC8 domainName;
       
  1050 	if (iImapSettings.TlsSslDomain().Length() > 0)
       
  1051 		{
       
  1052 		domainName.Set(iImapSettings.TlsSslDomain());
       
  1053 		}
       
  1054 	else
       
  1055 		{
       
  1056 		domainName.Set(*iHostAddr8);
       
  1057 		}
       
  1058 
       
  1059 	iOutputStream->SecureClientReq(domainName);
       
  1060 
       
  1061 	iStatus = KRequestPending;
       
  1062 	SetActive();
       
  1063 	}
       
  1064 
       
  1065 /**
       
  1066 Create a new session, and wait for the greeting response from the IMAP server.
       
  1067 */
       
  1068 void CImapSessionManager::StartSessionL()
       
  1069 	{
       
  1070 	__LOG_TEXT(KDefaultLog, "CImapSessionManager::StartSessionL");
       
  1071 
       
  1072 	// Create the IMAP Session. 
       
  1073 	iImapSession = CImapSession::NewL(iImapSettings, iImapMailStore, *iInputStream, *iOutputStream);
       
  1074 
       
  1075 	// Connected, request consumption of Server Greeting
       
  1076 	iState = EStateGreetingWait;
       
  1077 	iImapSession->ReadServerGreetingL(iStatus);
       
  1078 	SetActive();
       
  1079 	}
       
  1080 
       
  1081 /**
       
  1082 Send a login command to the IMAP server.
       
  1083 */
       
  1084 void CImapSessionManager::SendLoginL()
       
  1085 	{
       
  1086 	__LOG_TEXT(LogId(), "CImapSessionManager::SendLoginL");
       
  1087 	
       
  1088 	// Turn off logging so that user name and password are hidden
       
  1089 	__LOG_ON(LogId(), EFalse);
       
  1090 
       
  1091 	iImapSession->LoginL(iStatus, iImapSettings.LoginName(), iImapSettings.Password());
       
  1092 	iState = EStateLoginWait;
       
  1093 	SetActive();
       
  1094 	}
       
  1095 
       
  1096 /**
       
  1097 Request the hierarchy separator from the IMAP server by sending a list command
       
  1098 with no folders specified.
       
  1099 */
       
  1100 void CImapSessionManager::GetHierarchySeparatorL()
       
  1101 	{
       
  1102 	__LOG_TEXT(LogId(), "CImapSessionManager::GetHierarchySeparatorL");
       
  1103 
       
  1104 	// Always update the path separator on connection.
       
  1105 	iSeparatorFolderList.ResetAndDestroy();
       
  1106 	iImapSession->ListL(iStatus, KNullDesC(), KNullDesC(), iSeparatorFolderList);
       
  1107 	iState = EStateSeparatorWait;
       
  1108 	SetActive();
       
  1109 	}
       
  1110 
       
  1111 /**
       
  1112 We are disconnecting a list of sessions. If there are any left in the list,
       
  1113 send a logout command for the first one.
       
  1114 */
       
  1115 void CImapSessionManager::DisconnectFirstSessionInList()
       
  1116 	{
       
  1117 	if (iDisconnectList.Count() == 0)
       
  1118 		{
       
  1119 		iDisconnectList.Reset();
       
  1120 		Complete(KErrNone);
       
  1121 		return;
       
  1122 		}
       
  1123 
       
  1124 	__LOG_TEXT(LogId(), "CImapSessionManager::Logout session");
       
  1125 
       
  1126 	iState = EStateLogoutWait;
       
  1127 	TRAPD(err, iDisconnectList[0]->LogoutL(iStatus));
       
  1128 
       
  1129 	if (err == KErrNone)
       
  1130 		{
       
  1131 		SetActive();
       
  1132 		}
       
  1133 	else
       
  1134 		{
       
  1135 		DisconnectSocket();
       
  1136 		}
       
  1137 	}
       
  1138 
       
  1139 /**
       
  1140 Disconnect a socket.
       
  1141 */
       
  1142 void CImapSessionManager::DisconnectSocket()
       
  1143 	{
       
  1144 	__LOG_TEXT(LogId(), "CImapSessionManager::DisconnectSocket");
       
  1145 
       
  1146 	// Just close the streams as this will delete the socket to.
       
  1147 	CloseSessionStreams(iDisconnectList[0]);
       
  1148 
       
  1149 	iState = EStateDisconnectingSocket;
       
  1150 
       
  1151 	// Complete ourselves to keep the state machine moving
       
  1152 	iStatus = KRequestPending;
       
  1153 	CompleteSelf(KErrNone);
       
  1154 	SetActive();
       
  1155 	}
       
  1156 
       
  1157 /**
       
  1158 Immediately disconnect all the sessions in the disconnect list.
       
  1159 No logout command is sent. We just disconnect the socket.
       
  1160 */
       
  1161 void CImapSessionManager::ImmediateDisconnect()
       
  1162 	{
       
  1163 	while (iDisconnectList.Count() > 0)
       
  1164 		{
       
  1165 		__LOG_TEXT(LogId(), "CImapSessionManager::ImmediateDisconnect");
       
  1166 
       
  1167 		// Just close the streams as this will delete the socket to.
       
  1168 		CloseSessionStreams(iDisconnectList[0]);
       
  1169 		iDisconnectList.Remove(0);
       
  1170 		}
       
  1171 
       
  1172 	iDisconnectList.Reset();
       
  1173 	}
       
  1174 
       
  1175 /**
       
  1176 Close the session streams. This will also delete the streams and their
       
  1177 associated socket.
       
  1178 */
       
  1179 void CImapSessionManager::CloseSessionStreams(CImapSession* aSession)
       
  1180 	{
       
  1181 	__LOG_TEXT(aSession->LogId(), "CImapSessionManager::CloseSessionStreams");
       
  1182 
       
  1183 	// Closing the output stream will close the input stream too.
       
  1184 	MOutputStream* outputStream = aSession->OutputStream();
       
  1185 
       
  1186 	if (outputStream != NULL)
       
  1187 		{
       
  1188 		outputStream->Close();
       
  1189 		}
       
  1190 	}
       
  1191 
       
  1192 /**
       
  1193 Gets the connection stage information from the connection.
       
  1194 
       
  1195 @return Connection stage or error code.
       
  1196 */
       
  1197 TInt CImapSessionManager::GetConnectionStage()
       
  1198 	{
       
  1199 	if (iImConnect)
       
  1200 		{
       
  1201 		TNifProgress progress;
       
  1202 		TInt err = iImConnect->Progress(progress);
       
  1203 		return (err == KErrNone) ? (progress.iStage) : (err);
       
  1204 		
       
  1205 		}
       
  1206 
       
  1207 	return KErrNotFound;
       
  1208 	}
       
  1209 
       
  1210 /**
       
  1211 Converts an error code to one that is more meaningful for the state we are in.
       
  1212 
       
  1213 @param aError Error code to convert.
       
  1214 */
       
  1215 void CImapSessionManager::ConvertError(TInt& aError)
       
  1216 	{
       
  1217 	if (aError <= KErrNone)
       
  1218 		{
       
  1219 		return;
       
  1220 		}
       
  1221 
       
  1222 	switch (iState)
       
  1223 		{
       
  1224 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)			
       
  1225 
       
  1226 		case EStateCapabilityWait:
       
  1227 			{
       
  1228 			__LOG_TEXT(LogId(), "CImapSessionManager - Convert error to bad  authenticate");
       
  1229 			aError = KErrImapAuthenticationFailed;
       
  1230 			break;
       
  1231 			}
       
  1232 #endif
       
  1233 		case EStateLoginWait:
       
  1234 			{
       
  1235 			__LOG_TEXT(LogId(), "CImapSessionManager - Convert error to bad logon");
       
  1236 			aError = KErrImapBadLogon;
       
  1237 			break;
       
  1238 			}
       
  1239 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)			
       
  1240 		case EStateAuthenticateWait:
       
  1241 			{
       
  1242 			__LOG_TEXT(LogId(), "CImapSessionManager - Convert error to bad logon");
       
  1243 			aError = KErrImapBadLogon;
       
  1244 			break;
       
  1245 			}
       
  1246 #endif
       
  1247 		case EStateStartTLSWait:
       
  1248 			{
       
  1249 			__LOG_TEXT(LogId(), "CImapSessionManager - Convert error to TLS negotiate failed");
       
  1250 			aError = KErrImapTLSNegotiateFailed;
       
  1251 			break;
       
  1252 			}
       
  1253 
       
  1254 		case EStateLogoutWait:
       
  1255 		case EStateDisconnectingSocket:
       
  1256 			{
       
  1257 			// Do nothing
       
  1258 			break;
       
  1259 			}
       
  1260 
       
  1261 		default:
       
  1262 			{
       
  1263 			__LOG_TEXT(LogId(), "CImapSessionManager - Convert error to Imap connect error");
       
  1264 			// This is a postive error code (defined in cimapsession, thus allowing further
       
  1265 			// handling in the protocol controller. Specifically, this is used in the case
       
  1266 			// of initial connection failure where brearer mobility is configured.
       
  1267 			aError = KErrImapConnectError;
       
  1268 			break;
       
  1269 			}
       
  1270 		}
       
  1271 	}
       
  1272 
       
  1273 /**
       
  1274 Self complete with specified error code.
       
  1275 
       
  1276 @param aError Error code to complete with.
       
  1277 */
       
  1278 void CImapSessionManager::CompleteSelf(TInt aError)
       
  1279 	{
       
  1280 	// We use callbacks from the transport handler to receive error
       
  1281 	// notifications and then self complete with those error codes. As it is
       
  1282 	// possible to receive more than one callback at a time, we have to make
       
  1283 	// sure we don't try to self complete more than once.
       
  1284 	if (!iCompletedSelf)
       
  1285 		{
       
  1286 		TRequestStatus* status = &iStatus;
       
  1287 		User::RequestComplete(status, aError);
       
  1288 		iCompletedSelf = ETrue;
       
  1289 		}
       
  1290 	}
       
  1291 
       
  1292 /**
       
  1293 Gets the log ID to use for debug logging.
       
  1294 
       
  1295 @return Log ID
       
  1296 */
       
  1297 TInt CImapSessionManager::LogId()
       
  1298 	{
       
  1299 #ifdef __IMAP_LOGGING
       
  1300 	if (iImapSession)
       
  1301 		{
       
  1302 		return iImapSession->LogId();
       
  1303 		}
       
  1304 	else if (iDisconnectList.Count() > 0)
       
  1305 		{
       
  1306 		return iDisconnectList[0]->LogId();
       
  1307 		}
       
  1308 #endif //__IMAP_LOGGING
       
  1309 	return KDefaultLog;
       
  1310 	}
       
  1311 
       
  1312 /**
       
  1313 Returns ETrue if the session manager has access to an RConnection
       
  1314 
       
  1315 @return TBool
       
  1316 */
       
  1317 EXPORT_C TBool CImapSessionManager::HasConnection()
       
  1318 	{
       
  1319 	if (iImConnect)
       
  1320 		{
       
  1321 		return ETrue;
       
  1322 		}
       
  1323 
       
  1324 	return EFalse;
       
  1325 	}
       
  1326 
       
  1327 /**
       
  1328 Gets the RConnection used for all the sessions
       
  1329 
       
  1330 @return RConnection reference
       
  1331 */
       
  1332 EXPORT_C RConnection& CImapSessionManager::GetConnectionL()
       
  1333 	{
       
  1334 	__ASSERT_DEBUG(iImConnect,
       
  1335 	               TImapServerPanic::ImapPanic(TImapServerPanic::ERConnectionNotDefined));
       
  1336 
       
  1337 	if (!iImConnect)
       
  1338 		{
       
  1339 		User::Leave(KErrNotFound);		
       
  1340 		}
       
  1341 
       
  1342 	return iImConnect->GetConnection();
       
  1343 	}
       
  1344 
       
  1345 /**
       
  1346 Gets the access point ID in use for the connection to the server
       
  1347 
       
  1348 @param aAccessPointId On return stores the access point ID value
       
  1349 
       
  1350 @return KErrNone if successful, or a system wide error code
       
  1351 */
       
  1352 EXPORT_C TInt CImapSessionManager::GetAccessPointIdForConnection(TUint32& aAccessPointId) const
       
  1353 	{
       
  1354 	if (iImConnect)
       
  1355 		{
       
  1356 		return iImConnect->GetIAPValue(aAccessPointId);
       
  1357 		}
       
  1358 
       
  1359 	return KErrNotFound;
       
  1360 	}
       
  1361 	
       
  1362 /**
       
  1363 Close the current network connection since all the sessions will be closed before this
       
  1364 */
       
  1365 EXPORT_C void CImapSessionManager::CloseNetworkConnection()
       
  1366  	{
       
  1367  	iCreatedNetworkConnection = EFalse;	
       
  1368 	delete iTransportManager;
       
  1369 	iTransportManager = NULL;
       
  1370  	delete iImConnect;
       
  1371 	iImConnect = NULL ;
       
  1372  	iSocketServ.Close();
       
  1373  	}
       
  1374 
       
  1375 /**
       
  1376 Send a Authenticate  command to the IMAP server.
       
  1377 @param aCurrentAuthProfile
       
  1378 */
       
  1379 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
  1380 
       
  1381 void CImapSessionManager::SendAuthenticateL(CImapAuthMechanismHelper::TImapAuthProfileFlag aCurrentAuthProfile) 
       
  1382 	{
       
  1383 	__LOG_TEXT(LogId(), "CImapSessionManager::SendAuthenticateL");
       
  1384 	
       
  1385 	iImapSession->AuthenticateL(iStatus,aCurrentAuthProfile);
       
  1386 
       
  1387 	iState =  EStateAuthenticateWait;
       
  1388 	SetActive();
       
  1389 	}
       
  1390 
       
  1391 /**
       
  1392 State handler called when a authenticate response has been received.
       
  1393 */
       
  1394 void CImapSessionManager::ProcessAuthenticateResponseL()
       
  1395 	{
       
  1396 	__LOG_ON(LogId(), ETrue);
       
  1397 	__LOG_TEXT(LogId(), "CImapSessionManager::ProcessLoginResponseL");
       
  1398 
       
  1399 	GetHierarchySeparatorL();
       
  1400 	}
       
  1401 
       
  1402 /**
       
  1403 Selects  Authentication extension profile depending on authentication and fallback flags
       
  1404 @param aCapabilityInfo
       
  1405 */	
       
  1406 void CImapSessionManager::SelectAuthExtensionProfileL(const CImapCapabilityInfo& aCapabilityInfo)
       
  1407 	{
       
  1408 	if (aCapabilityInfo.QueryFlag(CImapCapabilityInfo::EAuthCramMd5))	
       
  1409 		{
       
  1410 		__LOG_TEXT(LogId(), "CImapSessionManager - ECramMD5");
       
  1411 		iCurrentAuthProfile = CImapAuthMechanismHelper::ECramMD5;
       
  1412 		SendAuthenticateL(iCurrentAuthProfile);
       
  1413 		}
       
  1414 	else if(iImapSettings.FallBack())
       
  1415     	{
       
  1416       	if (aCapabilityInfo.QueryFlag(CImapCapabilityInfo::EAuthPlain))
       
  1417       		{
       
  1418       		__LOG_TEXT(LogId(), "CImapSessionManager - EAuthPlain");
       
  1419       		iCurrentAuthProfile=CImapAuthMechanismHelper::EPlain;
       
  1420 			SendAuthenticateL(iCurrentAuthProfile);
       
  1421       		}
       
  1422 		else if (aCapabilityInfo.QueryFlag(CImapCapabilityInfo::EAuthLogin))
       
  1423 			{
       
  1424 			__LOG_TEXT(LogId(), "CImapSessionManager - ELogin");
       
  1425 			iCurrentAuthProfile = CImapAuthMechanismHelper::ELogin;
       
  1426 			SendAuthenticateL(iCurrentAuthProfile);
       
  1427 			}
       
  1428     	else
       
  1429 			{
       
  1430 			__LOG_TEXT(LogId(), "CImapSessionManager - ELogin");
       
  1431 			SendLoginL();	
       
  1432 			}
       
  1433 		}
       
  1434 	else 
       
  1435 		{
       
  1436 		TInt status = 1;
       
  1437 		Complete(status);
       
  1438 		}
       
  1439 	}
       
  1440 #endif