/*
* Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:           
*
*/











#include <uri8.h>
#include <es_sock.h>
#include <in_sock.h>
#include <http.h>

#include "sendebug.h" // filelogging and debugging MACROS
#include <SenServiceConnection.h> // KErrSenNoHttpResponseBody
#include <SenElement.h>
#include <SenXmlUtils.h>
#include <SenHttpTransportProperties.h>
#include "senhttpchannelimpl.h"
#include "senhttpeventhandler.h"
#include "sentxnstate.h"
#include "senatomtxnstate.h"
#include "senrfiletxnstate.h"
#include "senhttpchannel.h"
#include "senlayeredhttptransportproperties.h"
#include "msenidentitymanager.h"
#include "senlogger.h"

#include "senhttpchanneltransportplugin.h"
//For HTTPProxyFilter
#include <HttpFilterProxyInterface.h>
#include <HttpFilterAcceptHeaderInterface.h>
#include <HttpFilterCommonStringsExt.h>
#include <DeflateFilterInterface.h>

// CONSTANTS
namespace
    {
    _LIT(KTxnStateNullPanicText,            "TxnState is NULL");

    // Minimum granularity for array initialization
    const TInt KMinimumArrayGranularity =   1;

#ifdef _SENDEBUG
    // logging constants
    //_LIT(KLogFileDir, "SenHttpChannel");
   // _LIT(KLogFileName, "SenHttpChannel.log");
    _LIT(KDateFormat,"%D%M%Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S.%C%:3");
    // Size of buffer used when submitting request bodies
    const TInt KMaxHeaderNameLen = 16;
    const TInt KMaxHeaderValueLen = 128;
    const TInt KMaxFilterNameLen = 16;
#endif
    }

//
// Implementation of CSenHttpChannelImpl
//
CSenHttpChannelImpl::CSenHttpChannelImpl(MSenIdentityManager& aManager)
:
    iIapId(KErrNone),
    iManager(aManager),
    iSessionAuthentication(NULL),
    iPasswordFromUser(EFalse),
    iExplicitIapDefined(EFalse),
    iProxyHostPort(NULL),
    iXopResponse(EFalse),
    iHasHttpContentType(ETrue)
    {
    }

CSenHttpChannelImpl* CSenHttpChannelImpl::NewL(MSenIdentityManager& aManager)
    {
    CSenHttpChannelImpl* pNew = NewLC(aManager);
    CleanupStack::Pop(pNew);
    return pNew;
    }

CSenHttpChannelImpl* CSenHttpChannelImpl::NewLC(MSenIdentityManager& aManager)
    {
    CSenHttpChannelImpl* pNew = new (ELeave) CSenHttpChannelImpl(aManager);
    CleanupStack::PushL(pNew);
    pNew->ConstructL();
    return pNew;
    }

CSenHttpChannelImpl* CSenHttpChannelImpl::NewL(MSenIdentityManager& aManager,
                                               TUint32 aIapId)
    {
    CSenHttpChannelImpl* pNew = NewLC(aManager, aIapId);
    CleanupStack::Pop(pNew);
    return pNew;
    }

CSenHttpChannelImpl* CSenHttpChannelImpl::NewLC(MSenIdentityManager& aManager,
                                                TUint32 aIapId)
    {
    CSenHttpChannelImpl* pNew = new (ELeave) CSenHttpChannelImpl(aManager);
    CleanupStack::PushL(pNew);
    pNew->ConstructL(aIapId); 
    return pNew;
    }

// Ask IAP from user
void CSenHttpChannelImpl::ConstructL()
    {
    // Open connection to the file logger server
    TLSLOG_OPEN(KSenHttpChannelLogChannelBase, KSenHttpChannelLogLevel, KSenHttpChannelLogDir, KSenHttpChannelLogFile);
    TLSLOG(KSenHttpChannelLogChannelBase , KMinLogLevel,(_L("CSenHttpChannelImpl::ConstructL - Log file opened")));

    // Open the RHTTPSession
    TLSLOG(KSenHttpChannelLogChannelBase , KMinLogLevel,(_L("- Opening HTTP/TCP session.")));

    iSess.OpenL();

    // Store the string pool for this HTTP session
    iStringPool = iSess.StringPool();

    // Install this class as the callback for authentication requests
    InstallAuthenticationL( iSess );
    //Install Proxy Filter  
    iDeflateFilter = EFalse;

#ifdef EKA2
  //#ifndef _DEBUG 
    CHttpFilterProxyInterface::InstallFilterL( iSess );
    iSess.StringPool().OpenL(HttpFilterCommonStringsExt::GetLanguageTable());
    iSess.StringPool().OpenL(HttpFilterCommonStringsExt::GetTable());

    CHttpFilterAcceptHeaderInterface::InstallFilterL(iSess);
    TLSLOG_L(KSenHttpChannelLogChannelBase , KNormalLogLevel,"HTTPProxyFilter installed for EKA2 build.");
    TLSLOG_L(KSenHttpChannelLogChannelBase , KNormalLogLevel,"HTTPAcceptFilter installed for EKA2 build.");
  //#else
  //  LOG_WRITE_L("HTTPProxyFilter is NOT in use with EKA2 debug builds.");
  //#endif
#else // __INSTALL_HTTP_PROXY_FILTER__ is not defined by macro in .mmp
    TLSLOG_L(KSenHttpChannelLogChannelBase , KNormalLogLevel,"HTTPProxyFilter is NOT in use with EKA1.");
    TLSLOG_L(KSenHttpChannelLogChannelBase , KNormalLogLevel,"HTTPAcceptProxyFilter is NOT in use with EKA1.");
#endif // __INSTALL_HTTP_PROXY_FILTER__

    iTransObs = CSenHttpEventHandler::NewL(this);//, &iLog);
    iTxnStates =
        new (ELeave) CArrayPtrFlat<CSenTxnState>(KMinimumArrayGranularity);

    iBasicConnectionTries = 0;

#ifdef _SENDEBUG
    ListFilters();
#endif // _SENDEBUG
    }

// Forces preselected IAP to be used!
void CSenHttpChannelImpl::ConstructL( TUint32 aIapId )
    {
    // Initialize
//    SetupConnectionWithIapPrefsL( aIapId, iConnection, iSockServ );
        
    ConstructL();

//    AttachSocketServerAndConnectionWithHttpSession( aIapId, iConnection, iSockServ );
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"CSenHttpChannelImpl::ConstructL - Setting IAP id");


//    Use local variable (new RSocketServer each time; handle is given to RHTTPSession via RConnectionInfo..)
//    RSocketServ server; // with "anon" (local) socket servers, should we keep array of open ones in case of pending txns?
//    SetIapPrefsL(aIapId, iConnection, server);

    const TInt result = SetIapPrefsL(aIapId, ETrue, iConnection, iSockServ);
    User::LeaveIfError( result );
    
    }

CSenHttpChannelImpl::~CSenHttpChannelImpl()
    {
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"CSenHttpChannelImpl::~CSenHttpChannelImpl()");
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"Closing http session.");
    iSess.Close();
    if (iTransObs) //might be NULL if constructor failed ---
        {
        delete iTransObs;   
        iTransObs = NULL;
        }
    if (iTxnStates) //might be NULL if constructor failed--- 
        {
        iTxnStates->ResetAndDestroy();
        delete iTxnStates;
        iTxnStates = NULL;
        }

    if(iProxyHostPort)
        {
        delete iProxyHostPort;
        iProxyHostPort = NULL;
        }
    
    if(iMultiPartContentType.params.Count())
        {
        iMultiPartContentType.params.Close();
        }
    if(iDeflateFilter)
        {
        REComSession::DestroyedImplementation(KDeflateFilterUid); 	
        }
        
    iConnection.Close();
    iSockServ.Close();

    // Close the log file and the connection to the server.
    TLSLOG(KSenHttpChannelLogChannelBase , KMinLogLevel,(_L("Log file closed.")));
    TLSLOG_CLOSE(KSenHttpChannelLogChannelBase);
    }

// This function expects that RConnection has been connected
// and that RConnection has already been opened!
/*
void CSenHttpChannelImpl::SetIapPrefsL(TUint32 aIapId, 
                                       RConnection& aConnection, 
                                       RSocketServ& aSocketServer)
    {
    // Check whether IAP ID is not equal with the one that is currently in effect:
    if(iExplicitIapDefined && iIapId == aIapId )
        {
        return; // nothing to do
        }
        
    LOG_WRITEFORMAT((_L8("- SetIapPrefsL: Re-setting IAP ID (%d)"), aIapId));

    // Check if socket server (connection) is already open..
    if( iExplicitIapDefined )
        {
         // Socket server opened once before for some other IAP
        LOG_WRITE_L("- SetIapPrefsL: Re-using existing RConnection => calling RConnection::Stop");
        aConnection.Stop();
        }
    else
        {
        aConnection.Stop(); // prompted from user
        iSess.DisconnectL();
        iSess.ConnectL();

        // Connect to a socket server    
        LOG_WRITE_L("- SetIapPrefsL: Connecting to new socket server");    
        User::LeaveIfError(aSocketServer.Connect());       

        // Open new connection
        LOG_WRITE_L("- SetIapPrefsL: Opening new RConnection using the socket server.");       
        User::LeaveIfError(aConnection.Open(aSocketServer)); 
        }
        
    // Set the IAP selection preferences (IAP ID, do not prompt)
    TCommDbConnPref pref;
    pref.SetIapId( aIapId );    

    TCommDbDialogPref dialogPref;
    dialogPref = ECommDbDialogPrefDoNotPrompt;
    pref.SetDialogPreference(dialogPref);
    
    // Start the connection with the new preferences
    LOG_WRITE_L("- SetIapPrefsL: Calling RConnection::Start with new IAP prefs");
    aConnection.Start(pref);
    
    // Get the connection "handle" from the HTTP session    
    RHTTPConnectionInfo connInfo = iSess.ConnectionInfo();
     
    // Attach socket server
    connInfo.SetPropertyL(iStringPool.StringF(  HTTP::EHttpSocketServ,
                                                RHTTPSession::GetTable()),
                                                THTTPHdrVal(aSocketServer.Handle()));
    
    // Attach connection  
    TInt connPtr = REINTERPRET_CAST(TInt, &aConnection);
    connInfo.SetPropertyL(iStringPool.StringF(  HTTP::EHttpSocketConnection, 
                                                RHTTPSession::GetTable()), 
                                                THTTPHdrVal(connPtr));
                                                
    // Remember the IAP id that is being set; there is
    // no direct API to query effective IAP ID from CommsDB.
    iExplicitIapDefined = ETrue;
    iIapId = aIapId;
    }
*/


/*
void CSenHttpChannelImpl::SetupConnectionWithIapPrefsL( TUint32 aIapId, 
                                                        RConnection& aConnection, 
                                                        RSocketServ& aSocketServer )
    {
    // Check whether IAP ID is not equal with the one that is currently in effect:
    if(iExplicitIapDefined && iIapId == aIapId )
        {
        return; // nothing to do
        }
        
    LOG_WRITEFORMAT((_L8("- SetIapPrefsL, IAP ID (%d)"), aIapId));

    // Check if socket server (connection) is already open..
    if( iExplicitIapDefined )
        {
         // Socket server opened once before for some other IAP
        LOG_WRITE_L("- SetIapPrefsL: Re-using existing RConnection => calling RConnection::Stop");
        aConnection.Stop();
        }
    else
        {
        // Connect to a socket server    
        LOG_WRITE_L("- SetIapPrefsL: Connecting to new socket server");    
        User::LeaveIfError( aSocketServer.Connect() );       

        // Open new connection
        LOG_WRITE_L("- SetIapPrefsL: Opening new RConnection using the socket server.");       
        User::LeaveIfError( aConnection.Open(aSocketServer) ); 
        }
        
    // Set the IAP selection preferences (IAP ID, do not prompt)
    TCommDbConnPref pref;
    pref.SetIapId( aIapId );    

    TCommDbDialogPref dialogPref;
    dialogPref = ECommDbDialogPrefDoNotPrompt;
    pref.SetDialogPreference(dialogPref);
    
    // Start the connection with the new preferences
    LOG_WRITE_L("- SetIapPrefsL: Calling RConnection::Start with new IAP prefs");
    aConnection.Start(pref);
    }
    

void CSenHttpChannelImpl::AttachSocketServerAndConnectionWithHttpSession( TUint32 aIapId, 
                                                                          RConnection& aConnection, 
                                                                          RSocketServ& aSocketServer )
    {
    if(iExplicitIapDefined && iIapId == aIapId )
        {
        return; // nothing to do
        }

    // Get the connection "handle" from the HTTP session    
    RHTTPConnectionInfo connInfo = iSess.ConnectionInfo();
     
    // Attach socket server
    connInfo.SetPropertyL(iStringPool.StringF(  HTTP::EHttpSocketServ,
                                                RHTTPSession::GetTable()),
                                                THTTPHdrVal(aSocketServer.Handle()));
    
    // Attach connection  
    TInt connPtr = REINTERPRET_CAST(TInt, &aConnection);
    connInfo.SetPropertyL(iStringPool.StringF(  HTTP::EHttpSocketConnection, 
                                                RHTTPSession::GetTable()), 
                                                THTTPHdrVal(connPtr));
                                                
    // Remember the IAP id that is being set, because *at the moment*,
    // there is NO direct API to query effective IAP ID from CommsDB.
    iExplicitIapDefined = ETrue;
    iIapId = aIapId;
    }
    

void CSenHttpChannelImpl::SetIapPrefsL( TUint32 aIapId, RConnection& aConnection, RSocketServ& aSocketServer )
    {
    SetupConnectionWithIapPrefsL( aIapId, aConnection, aSocketServer );
    AttachSocketServerAndConnectionWithHttpSession( aIapId, aConnection, aSocketServer );
    }        
*/


TInt CSenHttpChannelImpl::SetIapPrefsL( TUint32 aIapId, TBool aDialogPref, RConnection& aConnection, RSocketServ& aSocketServer )
   	{
   	TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KNormalLogLevel, _L8("- SetIapPrefsL, IAP ID (%d)"), aIapId));
   	
    // Check whether IAP ID is not equal with the one that is currently in effect:
    if(iExplicitIapDefined && iIapId == aIapId )
        {
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetIapPrefsL: Iap Id is same as currently in effect");
        return KErrNone;
        }
		else
				{
				TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetIapPrefsL: Iap Id different with the currently in effect");
				}    
    

    // Check if socket server (connection) is already open..
    if( iExplicitIapDefined )
        {
         // Socket server opened once before for some other IAP
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetIapPrefsL: Re-using existing RConnection => calling RConnection::Stop");
        aConnection.Stop();
        }
    else
        {
        // Connect to a socket server    
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetIapPrefsL: Connecting to new socket server");    
        User::LeaveIfError( aSocketServer.Connect() );       

        // Open new connection
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetIapPrefsL: Opening new RConnection using the socket server.");       
        User::LeaveIfError( aConnection.Open(aSocketServer) ); 
        }
        
    // Set the IAP selection preferences (IAP ID, do not prompt)
    /*
    *Single click connectivity feature has been implemented by CSock (RConnection class).
    *According to this client no need to set the IAP ID. 
    *Automatically RConnection will use the suitable IAP
    */
    

	    TCommDbConnPref pref;
    #ifndef __SINGLE_CLICK_CONNECTIVITY_ENABLED__	    
	    pref.SetIapId( aIapId );
		#else
			pref.SetIapId( 0 );	 //By default IAP ID is "0". IAP selection will take care by RConnection
    #endif //__SINGLE_CLICK_CONNECTIVITY_ENABLED__	    
	    TCommDbDialogPref dialogPref;
	    
	    if (aDialogPref)
	        {
	        dialogPref = ECommDbDialogPrefDoNotPrompt;
	        }
	    else
	        {
	        dialogPref = ECommDbDialogPrefPrompt;
	        }     
	    pref.SetDialogPreference(dialogPref);
    
  	// Start the connection with the new preferences
	  TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetIapPrefsL: Calling RConnection::Start with new IAP prefs");

    TInt retVal =aConnection.Start(pref);
    
		TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("RConnection->Start retVal [%d]"), retVal));
		        
    // Get the connection "handle" from the HTTP session    
    RHTTPConnectionInfo connInfo = iSess.ConnectionInfo();
     
    // Attach socket server
    connInfo.SetPropertyL(iStringPool.StringF(  HTTP::EHttpSocketServ,
                                                RHTTPSession::GetTable()),
                                                THTTPHdrVal(aSocketServer.Handle()));
    
    // Attach connection  
    TInt connPtr = REINTERPRET_CAST(TInt, &aConnection);
    connInfo.SetPropertyL(iStringPool.StringF(  HTTP::EHttpSocketConnection, 
                                                RHTTPSession::GetTable()), 
                                                THTTPHdrVal(connPtr));
                                                
    // Remember the IAP id that is being set, because *at the moment*,
    // there is NO direct API to query effective IAP ID from CommsDB.
    if (!retVal)
        {
        #ifdef __SINGLE_CLICK_CONNECTIVITY_ENABLED__
        	//Since we are using by default setIapId "0".
        	//There won't be any explicitly defined Iap Id
        	iExplicitIapDefined = EFalse;
        	iIapId = 0;
				#else        	
        	iExplicitIapDefined = ETrue;
        	iIapId = aIapId;
        #endif //__SINGLE_CLICK_CONNECTIVITY_ENABLED__
        }
    return retVal;
    }
TInt CSenHttpChannelImpl::SetSnapPrefsL( TUint32 aSnapId, TBool aDialogPref, RConnection& aConnection, RSocketServ& aSocketServer )
    {
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("- CSenHttpChannelImpl::SetSnapPrefsL, SNAP ID (%d)"), aSnapId));
		// Check whether SNAP ID is not equal with the one that is currently in effect:
    if(iExplicitIapDefined && iSnapId == aSnapId )
        {
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetSnapPrefsL: Sanp is same as currently in effect");
        return KErrNone;
        }
		else
			{
			TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetSnapPrefsL: Sanp is different with currently in effect");
			}        

    // Check if socket server (connection) is already open..
    if( iExplicitIapDefined )
        {
         // Socket server opened once before for some other IAP
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetSnapPrefsL: Re-using existing RConnection => calling RConnection::Stop");
        aConnection.Stop();
        }
    else
        {
        // Connect to a socket server    
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetSnapPrefsL: Connecting to new socket server");    
        User::LeaveIfError( aSocketServer.Connect() );       

        // Open new connection
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetSnapPrefsL: Opening new RConnection using the socket server.");       
        User::LeaveIfError( aConnection.Open(aSocketServer) ); 
        }
        
    // Set the SNAP selection preferences (SNAP ID)
    TConnSnapPref pref;
    pref.SetSnap(aSnapId);     
    
    // Start the connection with the new preferences
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- SetSnapPrefsL: Calling RConnection::Start with new SNAP prefs");
    TInt retVal = aConnection.Start(pref);
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("- SetSnapPrefsL, RConnection::Start returned: (%d)"), retVal));
    
    // Get the connection "handle" from the HTTP session    
    RHTTPConnectionInfo connInfo = iSess.ConnectionInfo();
     
    // Attach socket server
    connInfo.SetPropertyL(iStringPool.StringF(  HTTP::EHttpSocketServ,
                                                RHTTPSession::GetTable()),
                                                THTTPHdrVal(aSocketServer.Handle()));
    
    // Attach connection  
    TInt connPtr = REINTERPRET_CAST(TInt, &aConnection);
    connInfo.SetPropertyL(iStringPool.StringF(  HTTP::EHttpSocketConnection, 
                                                RHTTPSession::GetTable()), 
                                                THTTPHdrVal(connPtr));
                                                
    // Remember the SNAP id that is being set, because *at the moment*,
    // there is NO direct API to query effective SNAP ID from CommsDB.
    if (!retVal)
        {
        iExplicitIapDefined = ETrue;
        iSnapId = aSnapId;
        }
    return retVal;
    }

TInt CSenHttpChannelImpl::SendL( MSenResponseObserver& aObserver,
                                 const TDesC8& aUri,
                                 const TDesC8& aContent,
                                 CSenLayeredHttpTransportProperties& aProps )
    {
#ifdef _SENDEBUG
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"CSenHttpChannelImpl::SendL:");
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("- Endpoint URI: %S"), &aUri));
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMaxLogLevel,"- Content(msg):");
    TLSLOG_ALL(KSenHttpChannelLogChannelBase , KMaxLogLevel,(aContent));
#endif

    TPtrC8 contentType;
    TInt retVal = aProps.ContentTypeL(contentType);
    if(retVal!=KErrNone)
        {
        // Use the default
        contentType.Set(KDefaultContentType);
        }

    CSenTxnState* pTxnState = CSenTxnState::NewL(aObserver,
                                                 //Log(),
                                                 &aUri,
                                                 contentType,
                                                 &aContent);

    CleanupStack::PushL(pTxnState);
    AppendNewTxnStateL(pTxnState);
    CleanupStack::Pop(); // pTxnState

    return InvokeHttpMethodL(pTxnState, aProps);
    }
    
TInt CSenHttpChannelImpl::SendL( MSenResponseObserver& aObserver,
                                 const TDesC8& aUri,
                                 const RFile& aFile,
                                 CSenLayeredHttpTransportProperties& aProps )
    {
#ifdef _SENDEBUG
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"CSenHttpChannelImpl::SendL:");
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("- Endpoint URI: %S"), &aUri));
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMaxLogLevel,"- Content(msg):");
#endif

    TPtrC8 contentType;
    TInt retVal = aProps.ContentTypeL(contentType);
    if(retVal != KErrNone)
        {
        // Use the default
        contentType.Set(KDefaultContentType);
        }

    CSenRfileTxnState* pTxnState = CSenRfileTxnState::NewL(aObserver,
                                                 //Log(),
                                                 &aUri,
                                                 this,
                                                 contentType,
                                                 aFile);

    CleanupStack::PushL(pTxnState);
    AppendNewTxnStateL(pTxnState);
    CleanupStack::Pop(); // pTxnState

    return InvokeHttpMethodL(pTxnState, aProps);
    }
    
    
TInt CSenHttpChannelImpl::SendL(MSenResponseObserver& aObserver,
                           	    const TDesC8& aUri,
                               	CSenSoapEnvelope2& aContent, 
                               	CSenLayeredHttpTransportProperties& aProps)
    {
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"CSenHttpChannelImpl::SendL:");
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("- Endpoint URI: %S"), &aUri));
    
    TPtrC8 soapAction;
    TInt retVal = aProps.SoapActionL(soapAction);
    
    CSenMtomTxnState* pMtomTxnState = CSenMtomTxnState::NewL(aObserver,
                                             				 //Log(),
                                             				 &aUri,
                                             				 soapAction,
                                             				 aContent);
                                             				 
    if (aContent.SoapVersion() == ESOAP12)
      {
    aProps.RemovePropertyL(KSoapActionLocalName, MSenLayeredProperties::ESenMessageLayer);
      }

	CleanupStack::PushL(pMtomTxnState);
	AppendNewTxnStateL(pMtomTxnState);
    CleanupStack::Pop(); // pMtomTxnState

	return InvokeHttpMethodL(pMtomTxnState, aProps);
    }
TInt CSenHttpChannelImpl::SendL(MSenResponseObserver& aObserver,
                           	    const TDesC8& aUri,
                               	CSenAtomEntry& aContent, 
                               	CSenLayeredHttpTransportProperties& aProps)
    {
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"CSenHttpChannelImpl::SendL:");
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("- Endpoint URI: %S"), &aUri));
    CSenAtomTxnState* pAtomTxnState = CSenAtomTxnState::NewL(aObserver,
                                             				 &aUri,
                                             				 aContent);
                                             				 
    CleanupStack::PushL(pAtomTxnState);
	AppendNewTxnStateL(pAtomTxnState);
    CleanupStack::Pop(); // pAtomTxnState

	return InvokeHttpMethodL(pAtomTxnState, aProps);
    }    
/** Invoke the http method
This actually creates the transaction,
sets the headers and body and then starts the transaction
*/
TInt CSenHttpChannelImpl::InvokeHttpMethodL(CSenTxnState* aTxnState,
                                            CSenLayeredHttpTransportProperties& aProps)
    {
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"CSenHttpChannelImpl::InvokeHttpMethodL");
    TUriParser8 uri;
    RStringF method;
    TPtrC8 deflate;
    // Set IAP preferences, if such exist in properties (and not already in effect):
    TUint32 iapId(KErrNone);
    TBool doNotPrompt(ETrue); 
    
    TInt retVal = aProps.IAPDialogL( doNotPrompt );
    if ( retVal != KErrNone )
        {
        // by default, do not prompt (even if property does not exist!) 
        // => only if property is set, and has value "FALSE", show PROMPT            
        doNotPrompt = ETrue;
        }

    // Independent of dialog preference (property's existance), if IAP was predefined, it must be set        
    if(((aProps.IapIdL(iapId)) == KErrNone))
        {
        retVal = SetIapPrefsL(iapId, doNotPrompt, iConnection, iSockServ);
        }
    else if(((aProps.SnapIdL(iapId)) == KErrNone))
        {
        retVal = SetSnapPrefsL(iapId, doNotPrompt, iConnection, iSockServ);
        }
    else//to better control RConnection, we have to call Start by ourselve
        {
        retVal = SetSnapPrefsL(0, EFalse, iConnection, iSockServ);
        if(retVal == KErrNotFound)
            {
            retVal = SetIapPrefsL(0, EFalse, iConnection, iSockServ);
            }
        }
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Set Snap/IAP prefs retVal [%d]"), retVal));    
    User::LeaveIfError(retVal);
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"CSenHttpChannelImpl::InvokeHttpMethodL After User::Leave");
    TInt ret=iConnection.GetIntSetting(_L("IAP\\Id"), iUsedIapId);
    // Check transport properties
    CSenLayeredHttpTransportProperties::TSenHttpMethod httpMethod;
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("IAP %d"), iapId));
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("DONT PROMPT %d"), doNotPrompt));
    TInt retValHttpMethod = aProps.HttpMethodL(httpMethod);
    
    
    /*Installing the deflate filter based on the property values */
    /*Once installed, the filter will be alive for on session lifetime */   
    if(KErrNone == aProps.PropertyL(KWsPropertyValueHttpFilterDeflate,deflate))
       {
        if(!iDeflateFilter)
          {
           TRAPD(err, CHttpDeflateFilter::InstallFilterL(iSess));
           if(err == KErrNone) 
           	{
		     		iDeflateFilter = ETrue;  
	          TLSLOG_L(KSenHttpChannelLogChannelBase , KNormalLogLevel,"HTTPDeflateFilter installed for EKA2 build.");	
						}
					else
		     		{
		      	TLSLOG_L(KSenHttpChannelLogChannelBase , KNormalLogLevel,"ERROR:HTTPDeflateFilter Not installed for EKA2 build.");
		     		}
          }
       }


    if(!aTxnState->HasRequestBody())
        {
        if (retValHttpMethod) httpMethod = CSenLayeredHttpTransportProperties::ESenHttpGet;
        User::LeaveIfError( uri.Parse(aTxnState->RequestUri()) );
        switch(httpMethod)
            {
            case CSenLayeredHttpTransportProperties::ESenHttpPost:
                {
                method = iStringPool.StringF(HTTP::EPOST, RHTTPSession::GetTable());
                TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- HTTP::EPOST");
                }
                break;
            case CSenLayeredHttpTransportProperties::ESenHttpPut:
                {
                method = iStringPool.StringF(HTTP::EPUT, RHTTPSession::GetTable());
                TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- HTTP::EPUT");
                }
                break;
            case CSenLayeredHttpTransportProperties::ESenHttpDelete:
                {
                method = iStringPool.StringF(HTTP::EDELETE, RHTTPSession::GetTable());
                TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- HTTP::EDELETE");
                }
                break;
            case CSenLayeredHttpTransportProperties::ESenHttpGet:
            default:
                {
                // Default to HTTP GET, if no body has been provided
                method = iStringPool.StringF(HTTP::EGET, RHTTPSession::GetTable());
                TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- HTTP::EGET");
                }
            }
        }
    else 
        {   
        // Some request "body"; or a query string for GET or DELETE was provided
        if (retValHttpMethod) httpMethod = CSenLayeredHttpTransportProperties::ESenHttpPost;
        switch(httpMethod)
            {
            case CSenLayeredHttpTransportProperties::ESenHttpGet:
                {
                method = iStringPool.StringF(HTTP::EGET, RHTTPSession::GetTable());
                TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- HTTP::EGET");
                // The responsibility of correct query string for GET URI 
                // is on the shoulders of the original invoker (public API
                // caller):
                aTxnState->TransformBodyToUriL();

                // NOTE: warning from Uri16.h:
                // @warning The descriptor that is parsed by an object of this class will be referenced 
                // by that object. If the original descriptor is no longer in scope there will be undefined 
                // behaviour.
                User::LeaveIfError( uri.Parse(aTxnState->RequestUri()) );
                }
                break;
            case CSenLayeredHttpTransportProperties::ESenHttpPut:
                {
                method = iStringPool.StringF(HTTP::EPUT, RHTTPSession::GetTable());
                TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- HTTP::EPUT");
                User::LeaveIfError( uri.Parse(aTxnState->RequestUri()) );
                }
                break;
            case CSenLayeredHttpTransportProperties::ESenHttpDelete:
                {
                method = iStringPool.StringF(HTTP::EDELETE, RHTTPSession::GetTable());
                TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- HTTP::EDELETE");
                // The responsibility of correct query string for DELETE URI 
                // argument is on the shoulders of the original invoker 
                // (public API caller):
                aTxnState->TransformBodyToUriL();
                User::LeaveIfError( uri.Parse(aTxnState->RequestUri()) );
                }
                break;
            case CSenLayeredHttpTransportProperties::ESenHttpPost:
            default:
                {
                // default to HttpPost
                method = iStringPool.StringF(HTTP::EPOST, RHTTPSession::GetTable());
                TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- HTTP::EPOST");
                User::LeaveIfError( uri.Parse(aTxnState->RequestUri()) );
                }
            }
        }


    RHTTPTransaction transaction = iSess.OpenTransactionL(uri, *iTransObs, method);
    iHttpTransaction = transaction ;
    aTxnState->SetId(transaction.Id());
    aTxnState->SetTransaction(transaction);
    aTxnState->SetSession(iSess); 
    RHTTPHeaders hdr = transaction.Request().GetHeaderCollection();

    // Add request headers: Accept, User-Agent, any other user defined ones
    AddRequestHeadersL(hdr, aProps);

    // Add Content type header and request body if available
    if(aTxnState->HasRequestBody())
        {
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- Adding content type header and request body");

        // Set the "Content-Type" HTTP header here, and *only* here(!)
        aTxnState->SetContentTypeHeaderL(iSess, hdr);

        MHTTPDataSupplier* pDataSupplier = aTxnState;
        transaction.Request().SetBody(*pDataSupplier);
        }
#ifdef _SENDEBUG
    else
        {
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- This transaction does not carry a request body.");
        }
#endif

    // Submit the transaction
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- Submitting the transaction.");
    transaction.SubmitL();
    return aTxnState->Id();
    }

void CSenHttpChannelImpl::NotifyMoreBodyL()    
{
	iHttpTransaction.NotifyNewRequestBodyPartL();
}

void CSenHttpChannelImpl::SetProxyL(const TDesC8& aProxyHostBaseAddr, 
                                    TInt aProxyPort)
    {
    TBuf8<64> port;
    port.AppendNum(aProxyPort);
    HBufC8* pProxyHostPort = HBufC8::NewLC(aProxyHostBaseAddr.Length()
                                           +KColon().Length()
                                           +port.Length());

    pProxyHostPort->Des().Append( aProxyHostBaseAddr );
    pProxyHostPort->Des().Append( KColon );
    pProxyHostPort->Des().AppendNum( aProxyPort );

    TPtrC8 proxy = pProxyHostPort->Des();
    SetProxyL( proxy );
    CleanupStack::PopAndDestroy(pProxyHostPort);
    }

void CSenHttpChannelImpl::SetProxyL(const TDesC8& aProxyAddrStr)
    {
    if(iProxyHostPort && iProxyHostPort->Compare(aProxyAddrStr)==0)
        {
        // nothing to do, proxy address is already in use
        return;
        }

    delete iProxyHostPort;
    iProxyHostPort = NULL;

    iProxyHostPort = aProxyAddrStr.AllocL();

    RStringF proxyAddr = iSess.StringPool().OpenFStringL(*iProxyHostPort);

    CleanupClosePushL(proxyAddr);

    // Set the proxy here...
    RHTTPConnectionInfo connInfo = iSess.ConnectionInfo();
    THTTPHdrVal proxyUsage(
        iSess.StringPool().StringF(HTTP::EUseProxy, RHTTPSession::GetTable()));
    connInfo.SetPropertyL(
        iSess.StringPool().StringF(HTTP::EProxyUsage, RHTTPSession::GetTable()),
                                    proxyUsage);
    connInfo.SetPropertyL(
        iSess.StringPool().StringF(
                    HTTP::EProxyAddress, RHTTPSession::GetTable()), proxyAddr);

    CleanupStack::PopAndDestroy(); // proxyAddr
    }

void CSenHttpChannelImpl::SetHttpVersionL(TInt aVersion)
    {
    HTTP::TStrings httpVersion = HTTP::EHttp11;
    if(0 == aVersion)
        {
        httpVersion = HTTP::EHttp10;
        }

    RHTTPConnectionInfo connInfo = iSess.ConnectionInfo();
    RStringPool p=iSess.StringPool();
    connInfo.SetPropertyL(p.StringF(
                            HTTP::EHTTPVersion,RHTTPSession::GetTable()),
                          THTTPHdrVal(
                          p.StringF(httpVersion,RHTTPSession::GetTable())));
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KNormalLogLevel, _L8("Http version is set to HTTP 1.%d"), aVersion));
    }

void CSenHttpChannelImpl::SetProxyUsageL(TBool aProxyUsage)
    {
    RHTTPConnectionInfo connInfo = iSess.ConnectionInfo();
    RStringPool strPool=iSess.StringPool();
    if ( aProxyUsage )
        {
        connInfo.SetPropertyL
            ( 
            strPool.StringF( HTTP::EProxyUsage, RHTTPSession::GetTable() ), 
            THTTPHdrVal( strPool.StringF(HTTP::EUseProxy, RHTTPSession::GetTable() ) )
            );    
        TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Http Proxy usage is set to TRUE")));
        }
    else
        {
        connInfo.SetPropertyL
            ( 
            strPool.StringF( HTTP::EProxyUsage, RHTTPSession::GetTable() ), 
            THTTPHdrVal( strPool.StringF(HTTP::EDoNotUseProxy, RHTTPSession::GetTable() ) )
            );    
        TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Http Proxy usage is set to FALSE")));
        
        }
    }

void CSenHttpChannelImpl::SetSecureDialogL(TBool aSecureDialog)
    {
    RHTTPConnectionInfo connInfo = iSess.ConnectionInfo();
    RStringPool strPool=iSess.StringPool();
    if ( aSecureDialog )
        {
        connInfo.SetPropertyL
            ( 
            strPool.StringF( HTTP::ESecureDialog, RHTTPSession::GetTable() ), 
            THTTPHdrVal( strPool.StringF(HTTP::EDialogPrompt, RHTTPSession::GetTable() ) )
            );    
        TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Http Secure dialog prompt is set to TRUE")));
        }
    else
        {
        connInfo.SetPropertyL
            ( 
            strPool.StringF( HTTP::ESecureDialog, RHTTPSession::GetTable() ), 
            THTTPHdrVal( strPool.StringF(HTTP::EDialogNoPrompt, RHTTPSession::GetTable() ) )
            );    
        TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Http Secure dialog prompt is set to FALSE")));
        
        }
    }
    
// ----------------------------------------------------------------------------
// CSenHttpChannelImpl::AddRequestHeadersL
// Adds headers to the request.
// ----------------------------------------------------------------------------
void CSenHttpChannelImpl::AddRequestHeadersL(RHTTPHeaders& aHeaders,
                                             CSenLayeredHttpTransportProperties& aProps)
    {
    TLSLOG(KSenHttpChannelLogChannelBase , KMinLogLevel,(_L("CSenHttpChannelImpl::AddRequestHeadersL")));


    //TPtrC8 useragent;
    TInt retVal;// = aProps.UserAgentL(useragent);

    // It is MANDATORY, that User-Agent header exists:
 //   if ( useragent.Length()== 0 )
 //       {
 //       //iProperties->SetPropertyL(KUserAgentLocalName, KSenHttpChannelUserAgentHeaderDefault, KHttpHeaderType);            
 //       useragent.Set( KSenHttpChannelUserAgentHeaderDefault );
 //       }

    // Fetch the accepted content types:
    MSenProperty* acceptHeaders = NULL;
    retVal = aProps.AcceptL(acceptHeaders);
    RPointerArray<TPtrC8> tokens;
    CleanupClosePushL(tokens);

    if(retVal == KErrNone)
        {
        if(acceptHeaders)
            {
            TInt retVal = acceptHeaders->ValueTokensL(KSenHttpAcceptHeaderDelimiter, tokens);
            // Sanity check
            if(retVal == KErrNone && tokens.Count()==0)
                {
                retVal = KErrNotFound; // should not happen
                }
            }
        else
            {
            retVal = KErrNotFound; // should not happen
            }
        }

    // It is MANDATORY, that at least one Accept header TOKEN exists:
  if ( tokens.Count()==0 )
        {
        TPtrC8* pDefaultToken = new (ELeave) TPtrC8( KSenHttpChannelAcceptHeaderDefault );
        TInt error = tokens.Append( pDefaultToken );
        if ( error )
            {
            delete pDefaultToken;
            }
        }
    // Http headers
    TInt headerCount(0);
    RPointerArray<MSenProperty> headersArray;
    retVal = aProps.HttpHeadersL(headersArray);
    if ( retVal == KErrNone )
        {
        CleanupClosePushL(headersArray);
        headerCount = headersArray.Count();
        for(TInt i=0; i<headerCount; i++)
            {
            MSenProperty* property = headersArray[i];
            if(property)
                {
                TPtrC8 name = property->Name();

                // Check if header name is "Content-Type"
                if(!name.Compare(KContentTypeLocalName) ||
                   !name.Compare(KAcceptLocalName))
                    {
                    // Skip Content-Type header(s) in here:
                    // - otherwise HTTP GET might get confused

                    // NOTE(!): Content-Type header is added separately
                    // through CSenTxnState -object:
                    // @InvokeHttpMethodL()
                    continue;
                    }

                TPtrC8 value = property->Value();
                TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("- Adding HTTP HEADER, name: (%S), value: (%S)"),
                    &name, &value));

                // Open stringpool strings
                RStringF headerName = iStringPool.OpenFStringL(name);
                CleanupClosePushL(headerName);
                RStringF headerValue = iStringPool.OpenFStringL(value);
                CleanupClosePushL(headerValue);
                // Create header name field
                THTTPHdrVal headerFieldVal;
                headerFieldVal.SetStrF(headerValue);
                // Check if the header field value already exists
                TBool fieldValueExists = EFalse;
                TInt fieldCount = aHeaders.FieldPartsL(headerName);
                TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Header < %S > field count: %d"), &name,
                                        fieldCount));

                for(TInt j=0; j<fieldCount; j++)
                    {
                    THTTPHdrVal hVal;
                    TInt retCode = aHeaders.GetField(headerName, j, hVal);
                    if(KErrNotFound != retCode)
                        {
                        if(hVal == headerFieldVal)
                            {
                            TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Header < %S: %S > already exists"),
                                               &name, &value));

                            fieldValueExists = ETrue;
                            }
                        }
                    }

                // Add header field
                if(!fieldValueExists)
                    {
                    aHeaders.SetFieldL(headerName, headerFieldVal);
                    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Header < %S: %S > added"),
                                       &name, &value));
                    }

                // Close stringpool strings
                CleanupStack::PopAndDestroy(2); // headerValue, headerName
                }
            }
        headersArray.Reset();
        CleanupStack::Pop(); // headersArray
        }
    else
        {
        // No HTTP headers were found(!)
        User::Leave( retVal );
        }

    for (TInt k = 0; k < tokens.Count(); k++)
        {
        TPtrC8 token = *tokens[k]; // accept header value
        TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("- Adding token to Accept header (%S)"), tokens[k]));

        //const TDesC8& acceptHeaderValueStr
        //        = iAcceptedContentTypes->MdcaPoint(k);

        // Open stringpool string
        RStringF acceptHeaderValue 
            = iStringPool.OpenFStringL(token);

        CleanupClosePushL(acceptHeaderValue);

        // Create header name field
        THTTPHdrVal headerFieldVal;
        headerFieldVal.SetStrF(acceptHeaderValue);

        // Check if the header field value already exists
        TBool fieldValueExists = EFalse;

        TInt fieldCount = aHeaders.FieldPartsL(
            iStringPool.StringF(HTTP::EAccept, RHTTPSession::GetTable()));
        TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KNormalLogLevel, _L8("Accept header field count: %d"), fieldCount));


        for(TInt j = 0; j < fieldCount; j++)
            {
            THTTPHdrVal hVal;
            TInt retCode = aHeaders.GetField(
                iStringPool.StringF(HTTP::EAccept, 
                                    RHTTPSession::GetTable()),
                                    j, 
                                    hVal);

            if(KErrNotFound != retCode)
                {
#ifdef _SENDEBUG
                const TDesC8& hValStr = hVal.StrF().DesC();
                TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Accept: %S"),
                                   &hValStr));
#endif // _SENDEBUG
                if(hVal == headerFieldVal)
                    {
                    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Header < Accept: %S > already exists"), &token));
                    fieldValueExists = ETrue;
                    }
                }
            }

        // Add header field
        if(!fieldValueExists)
            {
            aHeaders.SetFieldL(
                iStringPool.StringF(HTTP::EAccept, 
                                    RHTTPSession::GetTable()),
                                    headerFieldVal);
            TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Header < Accept: %S > added"), &token));

            }

        // Close stringpool string
        CleanupStack::PopAndDestroy(); // acceptHeaderValue
        }
    tokens.ResetAndDestroy(); // TPtrC8 is allocated with "new" keyword and thus owned by this array, eventhough
                              // the actual descriptors inside TPtrC8 tokens are NOT owned, of course (NORMAL).
    CleanupStack::PopAndDestroy(); // token array
    }

/** Called when a authenticated page is requested
Asks the user for a username and password that would be appropriate for the
url that was supplied.
*/
TBool CSenHttpChannelImpl::GetCredentialsL(const TUriC8& aURI,
                                           RString aRealm,
                                           RStringF /*aAuthenticationType*/,
                                           RString& aUsername,
                                           RString& aPassword)

    {
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("GetCredentialsL(),  for URL (%S), realm (%S)"),
                            &aURI.UriDes(), &aRealm.DesC()));

    if (iBasicConnectionTries > 2)
        {
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"GetCredentialsL() max number of tries with auth-dialog reached (3)");
        // In the next attempt start with a fresh identityprovider
        iSessionAuthentication = NULL;
        iPasswordFromUser = EFalse;
        iBasicConnectionTries = 0;
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"GetCredentialsL() returning EFalse");
        return EFalse;  // Invalid login attempts have reached the defined 
                        // maximum, abort this request
        }

    if (!iSessionAuthentication)
        {
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"GetCredentialsL() reading auth-pair from database (senidentites.xml)");
        iSessionAuthentication = iManager.IdentityProviderL(aURI.UriDes());
        if(!iSessionAuthentication)
            {
            // create and register new IDP
            iSessionAuthentication = CSenIdentityProvider::NewL(aURI.UriDes(),
                                                                KNullDesC8);
            iSessionAuthentication->SetFrameworkIdL(KNullDesC8); 
            TInt retVal = iManager.RegisterIdentityProviderL(iSessionAuthentication);
            if(retVal!=KErrNone)
                {
                TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("GetCredentials: Register IDP failed! Error code: (%d)"),
                    retVal));
                iSessionAuthentication = NULL;
                TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"GetCredentialsL() returning EFalse");
                return EFalse; // decision: we could not save info into database, abort
                }
            TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"New IDP registeration OK. Proceeding.");
            }
        // we have credentials
        TRAPD(err, aUsername = 
            aRealm.Pool().OpenStringL(iSessionAuthentication->AuthzID()));
        TRAP(err, aPassword = 
            aRealm.Pool().OpenStringL(iSessionAuthentication->Password()));
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"GetCredentialsL() returning ETrue");
        return ETrue;
        }
    else
        {
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"GetCredentialsL() prompting auth-info from user via dialog.");
        // Remove the old password before asking the new one.
        CSenElement& element = iSessionAuthentication->AsElement();
        delete element.RemoveElement(KSenIdpPasswordLocalname);
        
        TPckgBuf<TSenAuthentication> authInfo;
        iManager.AuthenticationForL(*iSessionAuthentication, authInfo);
        iPasswordFromUser = ETrue;

        TRAPD(err, aUsername = 
                aRealm.Pool().OpenStringL(authInfo().iUsername));
        TRAP(err, aPassword = 
                aRealm.Pool().OpenStringL(authInfo().iPassword));
        iBasicConnectionTries++;
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"GetCredentialsL() returning ETrue");
        return ETrue;
        }
    }

// This is a debug logging method:
void CSenHttpChannelImpl::ListFilters()
    {
#ifdef _SENDEBUG
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMaxLogLevel,"List HTTP filters started.");
    TLSLOG(KSenHttpChannelLogChannelBase , KMaxLogLevel,(_L(
    "      Name       | Pos'n | Event  |      Header      | Status | Handle ")
    ));
    TLSLOG(KSenHttpChannelLogChannelBase , KMaxLogLevel,(_L(
    "-----------------+-------+--------+------------------+--------+--------")
    ));

    RHTTPFilterCollection filtColl = iSess.FilterCollection();
    THTTPFilterIterator iter = filtColl.Query();

    THTTPFilterRegistration regInfo;
    iter.First();
    TBuf<KMaxFilterNameLen> earlierName;
    while (!iter.AtEnd())
        {
        // Get next filter registration info
        regInfo = iter();

        TBuf<KMaxFilterNameLen> name;
        name.Copy(iSess.StringPool().StringF(regInfo.iName).DesC().Left(
                                                        KMaxFilterNameLen));
        TBuf<KMaxHeaderNameLen> header;
        header.Copy(iSess.StringPool().StringF(regInfo.iHeader).DesC().Left(
                                                        KMaxHeaderNameLen));
        TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMaxLogLevel, _L8("%16S | %4d  | %4d   | %16S |   %3d  | %2d"),
               &name, regInfo.iPosition, regInfo.iEvent.iStatus, &header,
                regInfo.iStatus, regInfo.iHandle));

        earlierName.Format(name);
        ++iter;
        }
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMaxLogLevel,"List HTTP filters done.");
#endif    
    }

void CSenHttpChannelImpl::HandleResponseHeadersL(RHTTPTransaction aTransaction)
    {
    TInt txnId = aTransaction.Id();
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("CSenHttpChannelImpl::HandleResponseHeadersL( %d )"),
                        txnId));

    RHTTPResponse resp = aTransaction.Response();
    TInt status = resp.StatusCode();
#ifdef _SENDEBUG
    RStringF statusStr = resp.StatusText();
    const TDesC8& statusStrDesC = statusStr.DesC();
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Response status: %d ( %S )"), status, &statusStrDesC));
#endif // _SENDEBUG
    CSenTxnState* pTxnState = FindTxnState(txnId);

    __ASSERT_ALWAYS(pTxnState != NULL, User::Panic(KTxnStateNullPanicText, CSenHttpChannel::ETxnStateNull));

    if (status == 401)  // basic authentication needed
        {
        CSenHttpTransportProperties* tp = CSenHttpTransportProperties::NewLC();
        RHTTPHeaders responseHeaders = aTransaction.Response().GetHeaderCollection();
        THTTPHdrFieldIter fields = responseHeaders.Fields();
        while (!fields.AtEnd())
             {
             RStringTokenF fieldName = fields();
             RStringF fieldNameStr = iStringPool.StringF(fieldName);
             THTTPHdrVal fieldVal;
             if (responseHeaders.GetField(fieldNameStr,0,fieldVal) == KErrNone)
                 {
                  TPtrC8 ptr(KNullDesC8);
                  responseHeaders.GetRawField(fieldNameStr, ptr);
                  TPtrC8 ptr2(fieldNameStr.DesC());
                  if (fieldVal.Type() == THTTPHdrVal::KDateVal)
                      {
                      TDateTime date = fieldVal.DateTime();
                      RStringF dateS = iStringPool.StringF(HTTP::EDate, RHTTPSession::GetTable());
                      TTimeIntervalMinutes interval;
                      TTime begin(0);
                      TTime time(date);
                      time.MinutesFrom(begin, interval);
                      tp->SetIntPropertyL(dateS.DesC(), interval.Int());
                      pTxnState->SetTP(tp);//ownership transfered
                      pTxnState->HttpChannelPropertiesL().SetIntPropertyL(dateS.DesC(), interval.Int());
                      }
                  }
              ++fields;
             }
        CleanupStack::Pop(tp);
        return;
        }
        
    else if (status == 200)
        {
        RHTTPHeaders responseHeaders = aTransaction.Response().GetHeaderCollection();

        THTTPHdrVal fieldVal;
        TPtrC8 fieldValPtr;
        THTTPHdrVal paramVal;
            
        // get the Content-Type string
        RStringF content = iStringPool.StringF(HTTP::EContentType,
                                               RHTTPSession::GetTable());

        if (responseHeaders.GetField(content,0,fieldVal) == KErrNone)
            {
            // get the field value
            switch (fieldVal.Type())
                {
                case THTTPHdrVal::KStrFVal:
                    {
                    fieldValPtr.Set(iStringPool.StringF(fieldVal.StrF()).DesC());
                    }
                break;
                case THTTPHdrVal::KStrVal:
                    {
                    fieldValPtr.Set(iStringPool.String(fieldVal.Str()).DesC());
                    }
                break;
                default:
                    {
                    User::Panic(KUnrecognisedValueTypeOfContentTypePanicText,
                                EContentTypeUnrecognisedValueType);
                    }
                }
            _LIT8(KMultipartRelated,"Multipart/Related");	//CodeScannerWarning
            _LIT8(KBoundry,"boundary");
            _LIT8(KType,"type");
            _LIT8(KStart,"start");
            _LIT8(KStartInfo,"start-info");
            _LIT8(KAction,"action");
            _LIT8(KApplication,"application/xop+xml");
            if (fieldValPtr == KMultipartRelated)
                {
                //SenMultiPartUtils::TMultiPartContentType MultiPartContentType;
                iMultiPartContentType.fieldValue.Set(fieldValPtr);

                // get the param values
                TPtrC8 paramName(KBoundry);
                if(KErrNone == ContentTypeParamValueL(responseHeaders, content, paramName,  iMultiPartContentType))     
                    {
                    paramName.Set(KType);
                    if (KErrNone == ContentTypeParamValueL(responseHeaders, content, paramName,  iMultiPartContentType))     
                        {
                        paramName.Set(KStart);
                        if (KErrNone == ContentTypeParamValueL(responseHeaders, content, paramName,  iMultiPartContentType))     
                            {
                            paramName.Set(KStartInfo);
                            if (KErrNone == ContentTypeParamValueL(responseHeaders, content, paramName,  iMultiPartContentType))     
                                {
                                paramName.Set(KAction);
                                if (KErrSenNoHttpContentType == ContentTypeParamValueL(responseHeaders, content, paramName,  iMultiPartContentType))     
                                    {
                                    SenMultiPartUtils::TMultiPartContentTypeParam contentTypeParam = {_L8("action"), _L8("")};
                                    iMultiPartContentType.params.Append(contentTypeParam);
                                    }
                                TUint i(0);
                                while (iMultiPartContentType.params[i].paramName != KType)
                                    {
                                     ++i;
                                    }
                                if (iMultiPartContentType.params[i].paramValue == KApplication)   
                                    {
                                    iXopResponse = ETrue;
                                    content.Close();
                                    return;
                                    }
                                }
                            }
                        }
                    }
                }
           else 
                {
                iContentType.Set(fieldValPtr);
                content.Close();
                return;
                }
            }
        iHasHttpContentType = EFalse;
        content.Close();
        }
    }

TInt CSenHttpChannelImpl::ContentTypeParamValueL(const RHTTPHeaders& aResponseHeaders,
                                const RStringF& aContent, 
                                const TPtrC8& aParamName,
                                SenMultiPartUtils::TMultiPartContentType& aMultiPartContentType)
    {
    RStringF paramNameStr = iStringPool.OpenFStringL(aParamName);            
    
    THTTPHdrVal paramVal;
    TPtrC8 paramValPtr;
    if (aResponseHeaders.GetParam(aContent,paramNameStr,paramVal) == KErrNone)
        {
        switch (paramVal.Type())
            {
            case THTTPHdrVal::KStrFVal:
                {
                paramValPtr.Set(iStringPool.StringF(paramVal.StrF()).DesC());
                }
            break;
            case THTTPHdrVal::KStrVal:
                {
                paramValPtr.Set(iStringPool.String(paramVal.Str()).DesC());
                }
            break;
            default:
                User::Panic(KUnrecognisedValueTypeOfContentTypePanicText,
                            EContentTypeUnrecognisedValueType);
            break;
            }

        SenMultiPartUtils::TMultiPartContentTypeParam contentTypeParam = {_L8(""), _L8("")};
        contentTypeParam.paramName.Set(aParamName);
        contentTypeParam.paramValue.Set(paramValPtr);
        aMultiPartContentType.params.Append(contentTypeParam);
        paramNameStr.Close();
        return KErrNone;
        }
    else
        {
        paramNameStr.Close();
        return KErrSenNoHttpContentType;
        }
    }

void CSenHttpChannelImpl::HandleResponseBodyDataL(RHTTPTransaction aTransaction)
    {
    TInt txnId = aTransaction.Id();
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("CSenHttpChannelImpl::HandleResponseBodyDataL( %d )"), txnId));

    CSenTxnState* pTxnState = FindTxnState(txnId);
    __ASSERT_ALWAYS(pTxnState != NULL,
                    User::Panic(KTxnStateNullPanicText,
                    CSenHttpChannel::ETxnStateNull));

    // Get the body data supplier
    MHTTPDataSupplier* pRespBody = aTransaction.Response().Body();

    if(pRespBody)
        {
        TPtrC8 dataChunk;
#ifdef _SENDEBUG
        TBool isLast = pRespBody->GetNextDataPart(dataChunk);
        if (isLast)
            TLSLOG(KSenHttpChannelLogChannelBase , KMinLogLevel,(_L("Got last data chunk.")));
#else
        pRespBody->GetNextDataPart(dataChunk);
#endif // _SENDEBUG
        
        if (!iXopResponse)
            {
            pTxnState->CollectResponseBodyL(dataChunk);
            }
        else
            {
            ((CSenMtomTxnState*)pTxnState)->ParseMultiPartResponseL(dataChunk);
            }


        // Done with that bit of body data
        pRespBody->ReleaseData();
        }
    else
        {
        //pTxnState->ResponseError(-20000);
        pTxnState->ResponseErrorL(KErrSenNoHttpResponseBody); //SenServiceConnection.h // was -20000
        DeleteTxnState(txnId);
        aTransaction.Close();
        }
    }

void CSenHttpChannelImpl::HandleResponseL(RHTTPTransaction aTransaction)
    {
    TInt txnId = aTransaction.Id();
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("CSenHttpChannelImpl::HandleResponseL( %d )"), txnId));
    CSenTxnState* pTxnState = FindTxnState(txnId);
    __ASSERT_ALWAYS(pTxnState != NULL,
                    User::Panic(KTxnStateNullPanicText,
                    CSenHttpChannel::ETxnStateNull));

    // Propagate http status codes                                    
    RHTTPResponse resp = aTransaction.Response();
    TInt status = resp.StatusCode();
    pTxnState->StateChanged(status);    
                                           
    if (iHasHttpContentType)
        {
         if (!iXopResponse)
            {
            pTxnState->ResponseReceivedL(iContentType);
            }
        else
            {
            ((CSenMtomTxnState*)pTxnState)->ResponseReceivedL(iMultiPartContentType);
            }
        }
    else
        {
        pTxnState->ResponseErrorL(KErrSenNoHttpContentType); // was: -20001
        }

    DeleteTxnState(txnId);
    aTransaction.Close();
    }

void CSenHttpChannelImpl::HandleRunErrorL(RHTTPTransaction aTransaction,
                                          TInt aError)
    {
    TInt txnId = aTransaction.Id();
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("CSenHttpChannelImpl::HandleRunErrorL( %d ): %d"),txnId, aError));
    CSenTxnState* pTxnState = FindTxnState(txnId);
    __ASSERT_ALWAYS(pTxnState != NULL,
                    User::Panic(KTxnStateNullPanicText,
                    CSenHttpChannel::ETxnStateNull));

    pTxnState->ResponseErrorL(aError);
    DeleteTxnState(txnId);
    aTransaction.Close();
    }

void CSenHttpChannelImpl::HandleRedirectRequiresConfirmationL(
                                                RHTTPTransaction aTransaction)
    {
    TInt txnId = aTransaction.Id();
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("CSenHttpChannelImpl::HandleRedirectRequiresConfirmationL( %d )"),
                txnId));
    CSenTxnState* pTxnState = FindTxnState(txnId);
    __ASSERT_ALWAYS(pTxnState != NULL,
                    User::Panic(KTxnStateNullPanicText,
                    CSenHttpChannel::ETxnStateNull));
    pTxnState->ResponseErrorL(KErrSenHttpRedirectRequiresConfirmation); // was: -20002
    DeleteTxnState(txnId);
    aTransaction.Close();
    }
/*
RFileLogger* CSenHttpChannelImpl::Log() const
    {
    return (RFileLogger*) &iLog;
    }
*/
// This is a debug logging method
#ifdef _SENDEBUG
void CSenHttpChannelImpl::DumpRespHeadersL(RHTTPTransaction& aTrans)
    {
    TLSLOG(KSenHttpChannelLogChannelBase , KMinLogLevel,(_L("CSenHttpChannelImpl::DumpRespHeadersL")));
    RHTTPResponse resp = aTrans.Response();
    RHTTPHeaders hdr = resp.GetHeaderCollection();
    THTTPHdrFieldIter it = hdr.Fields();

    TBuf<KMaxHeaderNameLen>  fieldName16;
    TBuf<KMaxHeaderValueLen> fieldVal16;
    TBuf<KMaxHeaderNameLen>  paramName16;
    TBuf<KMaxHeaderValueLen> paramVal16;

    while (!it.AtEnd())
        {
        RStringTokenF fieldName = it();
        RStringF fieldNameStr = iStringPool.StringF(fieldName);
        THTTPHdrVal fieldVal;
        THTTPHdrVal paramVal;
        if (hdr.GetField(fieldNameStr,0,fieldVal) == KErrNone)
            {
            const TDesC8& fieldNameDesC = fieldNameStr.DesC();
            fieldName16.Copy(fieldNameDesC.Left(KMaxHeaderNameLen));
            switch (fieldVal.Type())
                {
            case THTTPHdrVal::KTIntVal:
                TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("%S: %d"), &fieldName16, fieldVal.Int()));
                break;
            case THTTPHdrVal::KStrFVal:
                {
                RStringF fieldValStr = iStringPool.StringF(fieldVal.StrF());
                const TDesC8& fieldValDesC = fieldValStr.DesC();
                fieldVal16.Copy(fieldValDesC.Left(KMaxHeaderValueLen));
                TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("%S: %S"), &fieldName16, &fieldVal16));
                }
                break;
            case THTTPHdrVal::KStrVal:
                {
                RString fieldValStr = iStringPool.String(fieldVal.Str());
                const TDesC8& fieldValDesC = fieldValStr.DesC();
                fieldVal16.Copy(fieldValDesC.Left(KMaxHeaderValueLen));
                TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("%S: %S"), &fieldName16, &fieldVal16));
                }
                break;
            case THTTPHdrVal::KDateVal:
                {
                TDateTime date = fieldVal.DateTime();
                TBuf<40> dateTimeString;
                TTime t(date);
                t.FormatL(dateTimeString,KDateFormat);
                TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("%S: %S"), &fieldName16, &dateTimeString));

                }
                break;
            default:
                TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("%S: <unrecognised value type>"), &fieldName16));
            break;
            }
            
        RStringF paramNameStr = iStringPool.OpenFStringL(_L8("type"));            
        const TDesC8& paramNameDesC = paramNameStr.DesC();
        paramName16.Copy(paramNameDesC.Left(KMaxHeaderNameLen));
        if (hdr.GetParam(fieldNameStr,paramNameStr,paramVal) == KErrNone)
            {
            switch (paramVal.Type())
                {
                case THTTPHdrVal::KStrFVal:
                    {
                    RStringF paramValStr = iStringPool.StringF(paramVal.StrF());
                    const TDesC8& paramValDesC = paramValStr.DesC();
                    paramVal16.Copy(paramValDesC.Left(KMaxHeaderValueLen));
                    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("%S: %S"), &paramName16, &paramVal16));
                    }
                break;
                case THTTPHdrVal::KStrVal:
                    {
                    RString paramValStr = iStringPool.String(paramVal.Str());
                    const TDesC8& paramValDesC = paramValStr.DesC();
                    paramVal16.Copy(paramValDesC.Left(KMaxHeaderValueLen));
                    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("%S: %S"), &paramName16, &paramVal16));
                    }
                break;
                default:
                    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("%S: <unrecognised value type>"), &paramName16));
                break;
                }
            }
		_LIT(KMultipartRelated,"Multipart/Related");
		_LIT(KApplication,"application/xop+xml");
        if ((fieldVal16 == KMultipartRelated) && (paramVal16 == KApplication))
            {
            iXopResponse = ETrue;    
            }
            
            // Display realm for WWW-Authenticate header
            RStringF wwwAuth =
                iStringPool.StringF(
                    HTTP::EWWWAuthenticate,RHTTPSession::GetTable());
            if (fieldNameStr == wwwAuth)
                {
                // check the auth scheme is 'basic'
                RStringF basic =
                    iStringPool.StringF(HTTP::EBasic,RHTTPSession::GetTable());
                RStringF realm =
                    iStringPool.StringF(HTTP::ERealm,RHTTPSession::GetTable());
                THTTPHdrVal realmVal;
                if ((fieldVal.StrF() == basic) &&
                    (!hdr.GetParam(wwwAuth, realm, realmVal)))
                    {
                    RStringF realmValStr =
                        iStringPool.StringF(realmVal.StrF());
                    const TDesC8& realmValDesC = realmValStr.DesC();
                    fieldVal16.Copy(realmValDesC.Left(KMaxHeaderValueLen));
                    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("Realm is: %S"), &fieldVal16));
                    }
                }
            paramNameStr.Close();
            }
        ++it;
        }
    }
#else
// do nothing
void CSenHttpChannelImpl::DumpRespHeadersL(RHTTPTransaction& /* aTrans */) {  } 
#endif


// This is second debug logging method
//Do a formatted dump of binary data
#ifdef _SENDEBUG
void CSenHttpChannelImpl::DumpBodyData(const TDesC8& aData)
    {
    // Iterate the supplied block of data in blocks of cols=80 bytes
    const TInt cols=16;
    TInt pos = 0;
    TBuf<KMaxFileName - 2> logLine;
    TBuf<KMaxFileName - 2> anEntry;
    const TInt dataLength = aData.Length();
    while (pos < dataLength)
        {
        //start-line hexadecimal( a 4 digit number)
        anEntry.Format(TRefByValue<const TDesC>_L("%04x : "), pos);
        logLine.Append(anEntry);

        // Hex output
        TInt offset;
        for (offset = 0; offset < cols; ++offset)
            {
            if (pos + offset < aData.Length())
                {
                TInt nextByte = aData[pos + offset];
                anEntry.Format(TRefByValue<const TDesC>_L("%02x "), nextByte);
                logLine.Append(anEntry);
                }
            else
                {
                // fill the remaining spaces with
                // blanks untill the cols-th Hex number
                anEntry.Format(TRefByValue<const TDesC>_L("   "));
                logLine.Append(anEntry);
                }
            }
        anEntry.Format(TRefByValue<const TDesC>_L(": "));
        logLine.Append(anEntry);

        // Char output
        for (offset = 0; offset < cols; ++offset)
            {
            if (pos + offset < aData.Length())
                {
                TInt nextByte = aData[pos + offset];
                if ((nextByte >= ' ') && (nextByte <= '~'))
                    {
                    anEntry.Format(TRefByValue<const TDesC>_L("%c"), nextByte);
                    logLine.Append(anEntry);
                    }
                else
                    {
                    anEntry.Format(TRefByValue<const TDesC>_L("."));
                    logLine.Append(anEntry);
                    }
                }
            else
                {
                anEntry.Format(TRefByValue<const TDesC>_L(" "));
                logLine.Append(anEntry);
                }
            }
        TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, TRefByValue<const TDesC>_L("%S"), &logLine));
            logLine.Zero();

        // Advance to next  byte segment (1 seg= cols)
        pos += cols;
        }
    }
#else
// do nothing
void CSenHttpChannelImpl::DumpBodyData(const TDesC8& /* aData */) { } 
#endif

// ----------------------------------------------------------------------------
// CSenHttpChannelImpl::AppendNewTxnStateL
// ----------------------------------------------------------------------------
//
void CSenHttpChannelImpl::AppendNewTxnStateL(CSenTxnState* aTxnState)
    {
    TLSLOG(KSenHttpChannelLogChannelBase , KMinLogLevel,(_L("CSenHttpChannelImpl::AppendNewTxnStateL")));
    iTxnStates->AppendL(aTxnState);
    }

// ----------------------------------------------------------------------------
// CSenHttpChannelImpl::DeleteTxnState
// ----------------------------------------------------------------------------
void CSenHttpChannelImpl::DeleteTxnState(TInt aTxnId)
    {
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("CSenHttpChannelImpl::DeleteTxnState( %d )"), aTxnId));
    TInt index;
    CSenTxnState* pTxnState = FindTxnState(aTxnId, &index);
    if(pTxnState)
        {
        iTxnStates->Delete(index);
        delete pTxnState;
        pTxnState = NULL;
        TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("TxnState ( %d ) deleted"), aTxnId));
        }
    }

// ----------------------------------------------------------------------------
// CSenHttpChannelImpl::FindTxnState
// ----------------------------------------------------------------------------
CSenTxnState* CSenHttpChannelImpl::FindTxnState(TInt aTxnId, TInt* aIndex)
    {
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("CSenHttpChannelImpl::FindTxnState( %d )"), aTxnId));
    for(TInt i = 0; i < iTxnStates->Count(); ++i)
        {
        if((*iTxnStates)[i]->Id() == aTxnId)
            {
            if(aIndex)
                {
                *aIndex = i;
                }
            return (*iTxnStates)[i];
            }
        }
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("TxnState ( %d ) not found"), aTxnId));
    return NULL;
    }


// @return KErrNone, if cancel was performed
//        KErrNotFound if transaction was not found 
TInt CSenHttpChannelImpl::CancelTransaction(const TInt aTxnId)
    {
    TLSLOG_L(KSenHttpChannelLogChannelBase , KSenHttpChannelLogLevel,"");
    TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("CSenHttpChannelImpl::CancelTransaction - TxnId: %d"),
        aTxnId));

    CSenTxnState* pTxnState = FindTxnState(aTxnId);
    if(pTxnState)
        {
        TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"- Txn found, calling Cancel():");
        return pTxnState->Cancel();
        }
    return KErrNotFound;
    }

void CSenHttpChannelImpl::CancelAllTransactions()
    {
    TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"CSenHttpChannelImpl::CancelAllTransaction");
    
    for(TInt i = 0; i < iTxnStates->Count(); ++i)
        {
        (*iTxnStates)[i]->Cancel();
        }
    }

void CSenHttpChannelImpl::SetExplicitIapDefined(TBool aExplicitIapDefined)
    {
    iExplicitIapDefined = aExplicitIapDefined;
    }


TBool CSenHttpChannelImpl::EffectiveIapId( TUint32 &aIapId )
    {
	TInt handle = iConnection.SubSessionHandle();
		if (handle>0)
	    {
        TUint connEnum(0);
        TInt err = iConnection.EnumerateConnections(connEnum);
        if (!err && !connEnum)
            {
            return EFalse;
            }
	    }

	TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("CSenHttpChannelImpl::EffectiveIapId(): Current RConnection's subsession handle(%d)"), iIapId ));
#ifdef _SENDEBUG
	if( iExplicitIapDefined )
		{
		TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8(" - IAP ID is known: %d"), iIapId ));
		}
	else
		{
		TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel," - IAP ID is not known.");
		}
		
	if( handle < KErrNone )
		{
		TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel," -> RConnection has not been initialized.");
		}
#endif // _SENDEBUG    
    
    if( handle && !iExplicitIapDefined )
    	{
		// Eventhough IAP was not explicitely set (through Serene API), this
		// code can check what IAP end-user provided via IAP selection dialog:
		TLSLOG_L(KSenHttpChannelLogChannelBase , KMinLogLevel,"CSenHttpChannelImpl::EffectiveIapId: about to call RConnection::GetIntSetting()");
		_LIT( KIapIdKey, "IAP\\Id" );
	    iConnection.GetIntSetting( KIapIdKey, iIapId);
	    if ( iIapId > 0 )
	    	{
			TLSLOG_FORMAT((KSenHttpChannelLogChannelBase , KMinLogLevel, _L8("CSenHttpChannelImpl::EffectiveIapId(): end-user provided IAP(%d)"), iIapId ));
	    	// Treat the end-user selection as "explicit" definition as well(!):
	    	iExplicitIapDefined = ETrue; 
	    	}
	    }
    if( iExplicitIapDefined )
        {
        aIapId = iIapId;
        }
    return iExplicitIapDefined;
    }

void CSenHttpChannelImpl::EnableTimeOutL(TInt aTxnId, TInt aTimeOutSec)
    {
    CSenTxnState* txn = FindTxnState(aTxnId);
    if (txn)
        txn->EnableTimeOutL(aTimeOutSec);
    }
void CSenHttpChannelImpl::DisableTimeOutL(TInt aTxnId)
    {
    CSenTxnState* txn = FindTxnState(aTxnId);
    if (txn)
        txn->DisableTimeOutL();
    }

TInt32 CSenHttpChannelImpl::UsedIap()
    {
    return iUsedIapId;
    }
// END OF FILE


