diff -r 000000000000 -r b16258d2340f applayerpluginsandutils/httpprotocolplugins/WspProtocolHandler/CWspProxyInfoProvider.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/applayerpluginsandutils/httpprotocolplugins/WspProtocolHandler/CWspProxyInfoProvider.cpp Tue Feb 02 01:09:52 2010 +0200 @@ -0,0 +1,636 @@ +// Copyright (c) 2001-2009 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: +// + +// System includes +#include +#include +#include +#include +#include + +// User includes +#include "wsppanic.h" + +// Class signature +#include "cwspproxyinfoprovider.h" + +// Constants used in this file +const TInt KPortSecureCO = 9203; +const TInt KPortInsecureCO = 9201; +const TInt KPortSecureCL = 9202; +const TInt KPortInsecureCL = 9200; + +CWspProxyInfoProvider* CWspProxyInfoProvider::NewL(RHTTPSession aSession) + { + return new (ELeave) CWspProxyInfoProvider(aSession); + } + +CWspProxyInfoProvider::~CWspProxyInfoProvider() + { + // Cleanup the proxy info + iProxyInfo.Close(); + } + +CWspProxyInfoProvider::CWspProxyInfoProvider(RHTTPSession aSession) +: CBase(), iSession(aSession) + { + } + +void CWspProxyInfoProvider::UpdateProxyInfoL() + { + // Has a proxy redirection occured? + if( iProxyInfoLocked ) + { + // Yes the current proxy info is the redirected proxy info - don't + // change, but reset the redirection flag + iProxyInfoLocked = EFalse; + } + else + { + // Get the client specified proxy info + TProxyInfo proxyInfo = GetProxyInfoL(); + + // Cleanup the current proxy info + iProxyInfo.Close(); + + // Set the proxy info to its new value + iProxyInfo = proxyInfo; + } + } +void CWspProxyInfoProvider::SetTemporaryRedirectedProxyL(TWspRedirectedAddress& aRedirectAddress) + { + // Change current proxy info to the redirected one + ChangeToRedirectedProxyInfoL(aRedirectAddress); + } + +void CWspProxyInfoProvider::SetPermanentRedirectedProxyL(TWspRedirectedAddress& aRedirectAddress) + { + // Change current proxy info to the redirected one + ChangeToRedirectedProxyInfoL(aRedirectAddress); + + // Set HTTP session properties with the redirected proxy info + RHTTPConnectionInfo connInfo = iSession.ConnectionInfo(); + RStringPool stringPool = iSession.StringPool(); + + // Set the proxy address + THTTPHdrVal address = iProxyInfo.iProxyAddress; + connInfo.SetPropertyL(stringPool.StringF(HTTP::EWspProxyAddress, RHTTPSession::GetTable()), address); + + // Set the bearer + THTTPHdrVal bearer; + if( iProxyInfo.iBearer == EIP ) + { + bearer = THTTPHdrVal(stringPool.StringF(HTTP::EWspIp, RHTTPSession::GetTable())); + + // Need to set the port as this is an IP bearer + THTTPHdrVal port = iProxyInfo.iRemotePort; + connInfo.SetPropertyL(stringPool.StringF(HTTP::EWspRemotePort, RHTTPSession::GetTable()), port); + } + else + { + __ASSERT_DEBUG( iProxyInfo.iBearer == EWAPSMS, Panic(KWspPanicBadBearerType) ); + + // Must be an SMS bearer otherwise would have left before this + bearer = THTTPHdrVal(stringPool.StringF(HTTP::EWspSMS, RHTTPSession::GetTable())); + } + connInfo.SetPropertyL(stringPool.StringF(HTTP::EWspBearer, RHTTPSession::GetTable()), bearer); + } + +TBool CWspProxyInfoProvider::ProxyInfoChangedAndUpdateL() + { + // Get the client specified proxy info + TProxyInfo proxyInfo = GetProxyInfoL(); + + // Compare against current proxy info + TBool hasChanged = proxyInfo != iProxyInfo; + + // Cleanup the current proxy info + iProxyInfo.Close(); + + // Set the proxy info to its new value + iProxyInfo = proxyInfo; + + // Set the locked flag + iProxyInfoLocked = ETrue; + + return hasChanged; + } + +void CWspProxyInfoProvider::UnlockProxyInfo() + { + // Clear the locked flag + iProxyInfoLocked = EFalse; + } + +void CWspProxyInfoProvider::ResetProxyInfo() + { + // Reset to the state after construction. + UnlockProxyInfo(); + iProxyInfo.Close(); + } + +void CWspProxyInfoProvider::ChangeToRedirectedProxyInfoL(TWspRedirectedAddress& aRedirectAddress) + { + // Set the proxy info - first the proxy address, convert the descriptor to an RStringF + TProxyInfo proxyInfo; + proxyInfo.iProxyAddress = iSession.StringPool().OpenFStringL(aRedirectAddress.iProxyAddress); + CleanupStack::PushL(&proxyInfo.iProxyAddress); + + // Check for bearer type + if( aRedirectAddress.iHasBearer ) + { + // Use the given bearer + proxyInfo.iBearer = aRedirectAddress.iBearer; + + if( proxyInfo.iBearer == ESMS ) + { + // Get the Service centre number from the Comms DB + ReadServiceCentreNumberL(iSession.StringPool(), proxyInfo.iServiceCentreNumber); + } + } + else + { + // Use the current bearer + proxyInfo.iBearer = iProxyInfo.iBearer; + + if( proxyInfo.iBearer == ESMS ) + { + // Copy the service centre number + proxyInfo.iServiceCentreNumber = iProxyInfo.iServiceCentreNumber.Copy(); + } + } + + // Clean up - proxyInfo retains ownership of the RStringF + CleanupStack::Pop(&proxyInfo.iProxyAddress); + + // Check for port number + if( aRedirectAddress.iHasPort ) + { + // Use the given bearer + proxyInfo.iRemotePort = aRedirectAddress.iPort; + } + else + { + // Use the current bearer + proxyInfo.iRemotePort = iProxyInfo.iRemotePort; + } + // Copy over the other info + proxyInfo.iSecureConnection = iProxyInfo.iSecureConnection; + proxyInfo.iLocalPort = iProxyInfo.iLocalPort; + proxyInfo.iSessionType = iProxyInfo.iSessionType; + + // Set the current proxy info to the new info. + // Cleanup the current proxy info + iProxyInfo.Close(); + + // Set the proxy info to its new value + iProxyInfo = proxyInfo; + + // Set the locked flag + iProxyInfoLocked = ETrue; + } + +TProxyInfo CWspProxyInfoProvider::GetProxyInfoL() const + { + // Check the session properties first... + RHTTPConnectionInfo connInfo = iSession.ConnectionInfo(); + RStringPool stringPool = iSession.StringPool(); + TProxyInfo proxyInfo; + + // Need to check to see if the proxy address has been specified in the HTTP + // session properties, otherwise need to get proxy info from the Comms + // Database. + THTTPHdrVal namedProxyValue; + TBool useNamedProxy = connInfo.Property(stringPool.StringF(HTTP::EWspProxyAddress, RHTTPSession::GetTable()), namedProxyValue); + if( useNamedProxy ) + { + // First, get the session service type - make sure it is not CL + proxyInfo.iSessionType = ExtractSessionTypeFromSession(connInfo, stringPool); + if( proxyInfo.iSessionType == EWspConnectionLess ) + { + // Don't support CL at the moment, so leave + User::Leave(KErrNotSupported); + } + + // Now get the proxy address... + __ASSERT_DEBUG((namedProxyValue.Type() == THTTPHdrVal::KStrFVal), Panic(KWspPanicBadProxyAddressProperty)); + proxyInfo.iProxyAddress = namedProxyValue.StrF().Copy(); + + // ...the bearer... + proxyInfo.iBearer = ExtractBearerInfoFromSession(connInfo, stringPool); + + // ...security type... + proxyInfo.iSecureConnection = ExtractSecurityInfoFromSession(connInfo, stringPool); + + // Get bearer specific stuff + if( proxyInfo.iBearer == EIP ) + { + // For IP, need local and remote ports + proxyInfo.iLocalPort = ExtractPortInfoFromSession(HTTP::EWspLocalPort, connInfo, stringPool); + proxyInfo.iRemotePort = ExtractPortInfoFromSession(HTTP::EWspRemotePort, connInfo, stringPool); + + // Check for correct default value + if( proxyInfo.iRemotePort == 0 ) + proxyInfo.iRemotePort = DefaultRemotePort(proxyInfo.iSecureConnection, ETrue); + } + else + { + // For SMS stuff need the Service number - no default, leave if not set + THTTPHdrVal serviceNumberValue; + TBool hasServiceNumber = connInfo.Property(stringPool.StringF(HTTP::EWspServiceNumber, RHTTPSession::GetTable()), serviceNumberValue); + if( hasServiceNumber ) + { + __ASSERT_DEBUG((serviceNumberValue.Type() == THTTPHdrVal::KStrFVal), Panic(KWspPanicBadServiceNumberProperty)); + proxyInfo.iServiceCentreNumber = serviceNumberValue.StrF().Copy(); + } + else + User::Leave(KWspErrServiceNumberNotDefined); + } + } + else + { + // Read proxy info from CommDB + ReadWapAccessPointInfoL(stringPool, proxyInfo.iBearer, + proxyInfo.iProxyAddress, + proxyInfo.iSecureConnection, + proxyInfo.iServiceCentreNumber, + proxyInfo.iSessionType); + + // Check the bearer + if( proxyInfo.iBearer == EIP ) + { + // Initialise the local and remote port values for the IP bearer + proxyInfo.iLocalPort = 0; + proxyInfo.iRemotePort = DefaultRemotePort(proxyInfo.iSecureConnection, ETrue); + } + } + return proxyInfo; + } + +/* + * Methods from MWspProxyInfoProvider + */ + +const TDesC8& CWspProxyInfoProvider::ProxyAddress() const + { + return iProxyInfo.iProxyAddress.DesC(); + } + +TUint16 CWspProxyInfoProvider::RemotePort() const + { + return iProxyInfo.iRemotePort; + } + +TUint16 CWspProxyInfoProvider::LocalPort() const + { + return iProxyInfo.iLocalPort; + } + +TWspBearer CWspProxyInfoProvider::Bearer() const + { + return iProxyInfo.iBearer; + } + +const TDesC8& CWspProxyInfoProvider::ServiceCentreNumber() const + { + return iProxyInfo.iServiceCentreNumber.DesC(); + } + +TWspSession CWspProxyInfoProvider::WspSessionService() const + { + return iProxyInfo.iSessionType; + } + +TBool CWspProxyInfoProvider::SecureConnection() const + { + return iProxyInfo.iSecureConnection; + } + +TWspSession CWspProxyInfoProvider::ExtractSessionTypeFromSession(RHTTPConnectionInfo aConnInfo, RStringPool aStringPool) + { + // Check for the Wsp Session Service type, or use default value of + // EWspConnectionOriented. + TWspSession session = EWspConnectionOriented; + + THTTPHdrVal sessionType; + TBool hasSessionType = aConnInfo.Property(aStringPool.StringF(HTTP::EWspSessionType, RHTTPSession::GetTable()), sessionType); + if( hasSessionType ) + { + __ASSERT_DEBUG((sessionType.Type() == THTTPHdrVal::KStrFVal), Panic(KWspPanicBadWspSessionTypeProperty)); + switch (sessionType.StrF().Index(RHTTPSession::GetTable())) + { + case HTTP::EWspConnectionOriented: + { + // Nothing to do as session type already set to default + } break; + case HTTP::EWspConnectionLess: + { + session = EWspConnectionLess; + } break; + default: + __ASSERT_DEBUG(ETrue, Panic(KWspPanicBadWspSessionTypeProperty)); + } + } + return session; + } + +TWspBearer CWspProxyInfoProvider::ExtractBearerInfoFromSession(RHTTPConnectionInfo aConnInfo, RStringPool aStringPool) + { + // Check for bearer property, or use default value of EIP + TWspBearer bearer = EIP; + + THTTPHdrVal bearerValue; + TBool hasBearer = aConnInfo.Property(aStringPool.StringF(HTTP::EWspBearer, RHTTPSession::GetTable()), bearerValue); + if( hasBearer ) + { + __ASSERT_DEBUG((bearerValue.Type() == THTTPHdrVal::KStrFVal), Panic(KWspPanicBadBearerProperty)); + switch (bearerValue.StrF().Index(RHTTPSession::GetTable())) + { + case HTTP::EWspIp: + { + // Nothing to do as bearer already set to default + } break; + case HTTP::EWspSMS: + { + bearer = EWAPSMS; + } + default: + __ASSERT_DEBUG(ETrue, Panic(KWspPanicBadBearerProperty)); + } + } + return bearer; + } + +TBool CWspProxyInfoProvider::ExtractSecurityInfoFromSession(RHTTPConnectionInfo aConnInfo, RStringPool aStringPool) + { + // Check for security property, or use default value of unsecured + TBool useWtls = EFalse; + + THTTPHdrVal securityValue; + TBool hasSecurityValue = aConnInfo.Property(aStringPool.StringF(HTTP::EWspSecurity, RHTTPSession::GetTable()), securityValue); + if( hasSecurityValue ) + { + __ASSERT_DEBUG((securityValue.Type() == THTTPHdrVal::KStrFVal), Panic(KWspPanicBadSecurityProperty)); + switch (securityValue.StrF().Index(RHTTPSession::GetTable())) + { + case HTTP::EWspUseWtls: + { + useWtls = ETrue; + } break; + case HTTP::EWspDoNotUseWtls: + { + // Nothing to do as security level already set to default + } break; + default: + __ASSERT_DEBUG(ETrue, Panic(KWspPanicBadSecurityProperty)); + } + } + return useWtls; + } + +TUint16 CWspProxyInfoProvider::ExtractPortInfoFromSession(TInt aPortType, RHTTPConnectionInfo aConnInfo, RStringPool aStringPool) + { + // Check for the specified port property, or use the default value of 0 + TUint16 port = 0; + + THTTPHdrVal portValue; + TBool hasPort = aConnInfo.Property(aStringPool.StringF(aPortType, RHTTPSession::GetTable()), portValue); + if( hasPort ) + { + __ASSERT_DEBUG((portValue.Type() == THTTPHdrVal::KTIntVal), Panic(KWspPanicBadPortProperty)); + port = STATIC_CAST(TUint16, portValue.Int()); + } + return port; + } + +TUint16 CWspProxyInfoProvider::DefaultRemotePort(TBool aSecureConnection, TBool aCOConnection) + { + TUint16 port = 0; + if( aCOConnection ) + { + // Defaults for CO session + if( aSecureConnection ) + port = KPortSecureCO; + else + port = KPortInsecureCO; + } + else + { + // Defaults for CL session + if( aSecureConnection ) + port = KPortSecureCL; + else + port = KPortInsecureCL; + } + return port; + } + +void CWspProxyInfoProvider::ReadWapAccessPointInfoL( + RStringPool aStringPool, + TWspBearer& aBearer, + RStringF& aProxyAddress, + TBool& aSecureConnection, + RStringF& aServiceCentreNumber, + TWspSession& aSessionServiceType + ) + { + // Open the Comms DB - don't specify whether it should be a IAP or ISP + // style DB - this doesn't matter here. + CCommsDatabase* db=CCommsDatabase::NewL(EDatabaseTypeUnspecified); + CleanupStack::PushL(db); + + // Find the ID of the WAP Access Point marked in the global settings. This + // is the 'default' WAP AP, as marked by the user's most recent selection + // of a bookmark in the WAP browser. + TUint32 wapAPID; + db->GetGlobalSettingL(TPtrC(WAP_ACCESS_POINT), wapAPID); + + // Open a view on the WAP AP Table, selecting the WAP Access Point that + // matches wapAPID. We expect only one record to in the view as we're + // selecting against a unique ID! + CCommsDbTableView* apView= + db->OpenViewMatchingUintLC(TPtrC(WAP_ACCESS_POINT) + , TPtrC(COMMDB_ID), wapAPID); + if( apView->GotoFirstRecord() != KErrNone ) + User::Leave(KWspErrAccessPointNotSetUp); + + // Read the Bearer name specified in the selected WAP AP record. + HBufC* bearer16 = HBufC::NewL(KCommsDbSvrMaxFieldLength); + CleanupStack::PushL(bearer16); + TPtr bearerPtr16 = bearer16->Des(); + apView->ReadTextL(TPtrC(WAP_CURRENT_BEARER), bearerPtr16); + + // Open a view on the appropriate bearer table according to the bearer + // name. Use the WAP AP ID to select a record in the appropriate WAP + // bearer table (either WAP_IP_BEARER or WAP_SMS_BEARER). + CCommsDbTableView* bearerView = NULL; + if( bearerPtr16.Compare(TPtrC(WAP_SMS_BEARER)) == 0 ) // SMS (8-bit WAP SMS) + { + aBearer = EWAPSMS; + bearerView = db->OpenViewMatchingUintLC( + TPtrC(WAP_SMS_BEARER), // table name + TPtrC(WAP_ACCESS_POINT_ID), // column to match + wapAPID // value to match + ); + } + else if( bearerPtr16.Compare(TPtrC(WAP_IP_BEARER)) == 0 ) // IPv4 + { + aBearer = EIP; + bearerView = db->OpenViewMatchingUintLC( + TPtrC(WAP_IP_BEARER), // table name + TPtrC(WAP_ACCESS_POINT_ID), // column to match + wapAPID // value to match + ); + } + else + { + // Some unknown and unsupported bearer was specified - leave. + User::Leave(KWspErrAccessPointNotSetUp); + } + + // Navigate to the first record matching our selection in the view. We + // expect only one record to in the view as we don't want more than one IP + // or SMS bearer definition per WAP AP. + if( bearerView->GotoFirstRecord() != KErrNone ) + User::Leave(KWspErrAccessPointNotSetUp); + + // Read the Secure connection flag from the chosen bearer record. + bearerView->ReadBoolL(TPtrC(WAP_SECURITY), aSecureConnection); + + // Read the Gateway from the WAP AP settings. It is held as a UNICODE + // descriptor - convert this to 8-bit before returning + // NB the Gateway field in CommDB is actually used to hold the SMS Service + // Number when SMS is used as a bearer. However, the field type is + // specified separately as an addressing scheme, so read that first and + // use it for validation. + HBufC* gateway16 = HBufC::NewL(KCommsDbSvrMaxFieldLength); + CleanupStack::PushL(gateway16); + TPtr gatewayPtr16 = gateway16->Des(); + bearerView->ReadTextL(TPtrC(WAP_GATEWAY_ADDRESS), gatewayPtr16); + + // Copy to 8-bits... + HBufC8* gateway8 = HBufC8::NewL(gatewayPtr16.Length()); + CleanupStack::PushL(gateway8); + TPtr8 gatewayPtr8 = gateway8->Des(); + gatewayPtr8.Copy(gatewayPtr16); + + if( aBearer == EIP ) + { + // Set gateway as an IPv4 quadruplet; service number is not being used + // so clear it. + aProxyAddress = aStringPool.OpenFStringL(gatewayPtr8); + aServiceCentreNumber = RStringF(); + } + else // aBearer == EWapSMS + { + // Set gateway as a service number - this is the proxy address + aProxyAddress = aStringPool.OpenFStringL(gatewayPtr8); + + // Only the SMS bearer has a Service Centre Address + + // Read the Service Centre Address from the WAP AP settings. This is + // in the form of a phone number when SMS is being used as a bearer. + // Note: this isn't used by HTTP to configure the WAP stack - it is + // used by the WAP stack to configure the SMS stack. HTTP doesn't need + // to worry about it. However, store it anyway, just in case... + HBufC* svcCentreAddr16 = HBufC::NewL(KCommsDbSvrMaxFieldLength); + CleanupStack::PushL(svcCentreAddr16); + + TPtr svcCentreAddrPtr16 = svcCentreAddr16->Des(); + bearerView->ReadTextL(TPtrC(WAP_SERVICE_CENTRE_ADDRESS), + svcCentreAddrPtr16); + + // Copy to 8-bits... + HBufC8* svcCentreAddr8 = HBufC8::NewL(svcCentreAddrPtr16.Length()); + CleanupStack::PushL(svcCentreAddr8); + TPtr8 svcCentreAddrPtr8 = svcCentreAddr8->Des(); + svcCentreAddrPtr8.Copy(svcCentreAddrPtr16); + + aServiceCentreNumber = aStringPool.OpenFStringL(svcCentreAddrPtr8); + CleanupStack::PopAndDestroy(2, svcCentreAddr16); // svcCentreAddr16, svcCentreAddr8 + } + + // Read the WSP Option - CO (Connection Oriented) or CL (Connection-less). + // Note: this WAP browser isn't going to support a connectionless mode of + // operation. + TUint32 wspOptionID = 0; + bearerView->ReadUintL(TPtrC(WAP_WSP_OPTION), wspOptionID); + switch( wspOptionID ) + { + case EWapWspOptionConnectionless: // Connection-less + { + aSessionServiceType = EWspConnectionLess; + } break; + case EWapWspOptionConnectionOriented: // Connection-oriented + { + aSessionServiceType = EWspConnectionOriented; + } break; + default: // 'NULL' setting - don't know what this means... leave with + // a 'AP Not set up' failure + User::Leave(KWspErrAccessPointNotSetUp); + break; + } + // All done - clean up + CleanupStack::PopAndDestroy(6, db); // gateway8, gateway16, bearerView, bearer16, + // apView, db + } +void CWspProxyInfoProvider::ReadServiceCentreNumberL(RStringPool aStringPool, RStringF& aServiceCentreNumber) + { + // Open the Comms DB - don't specify whether it should be a IAP or ISP + // style DB - this doesn't matter here. + CCommsDatabase* db=CCommsDatabase::NewL(EDatabaseTypeUnspecified); + CleanupStack::PushL(db); + + // Find the ID of the WAP Access Point marked in the global settings. This + // is the 'default' WAP AP, as marked by the user's most recent selection + // of a bookmark in the WAP browser. + TUint32 wapAPID; + db->GetGlobalSettingL(TPtrC(WAP_ACCESS_POINT), wapAPID); + + // Open a view on the SMS Bearer table. Use the WAP AP ID to select a record + // in the appropriate WAP bearer table. + CCommsDbTableView* bearerView = db->OpenViewMatchingUintLC( + TPtrC(WAP_SMS_BEARER), // table name + TPtrC(WAP_ACCESS_POINT_ID), // column to match + wapAPID // value to match + ); + if( bearerView == NULL ) + { + // No SMS bearer table - leave + User::Leave(KWspErrSMSBearerNotInCommsDB); + } + + // Read the Service Centre Address from the WAP AP settings. This is + // in the form of a phone number when SMS is being used as a bearer. + // Note: this isn't used by HTTP to configure the WAP stack - it is + // used by the WAP stack to configure the SMS stack. HTTP doesn't need + // to worry about it. However, store it anyway, just in case... + HBufC* svcCentreAddr16 = HBufC::NewL(KCommsDbSvrMaxFieldLength); + CleanupStack::PushL(svcCentreAddr16); + + TPtr svcCentreAddrPtr16 = svcCentreAddr16->Des(); + bearerView->ReadTextL(TPtrC(WAP_SERVICE_CENTRE_ADDRESS), svcCentreAddrPtr16); + + // Copy to 8-bits... + HBufC8* svcCentreAddr8 = HBufC8::NewL(svcCentreAddrPtr16.Length()); + CleanupStack::PushL(svcCentreAddr8); + TPtr8 svcCentreAddrPtr8 = svcCentreAddr8->Des(); + svcCentreAddrPtr8.Copy(svcCentreAddrPtr16); + + aServiceCentreNumber = aStringPool.OpenFStringL(svcCentreAddrPtr8); + + // Cleanup... + CleanupStack::PopAndDestroy(4, db); + }