--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/applayerprotocols/httptransportfw/Test/testfilter/testhttpfilter.cpp Fri Feb 19 23:50:57 2010 +0200
@@ -0,0 +1,401 @@
+// Copyright (c) 2003-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:
+//
+
+#include <http/rhttptransaction.h>
+#include <http/rhttpheaders.h>
+#include <http/rhttpresponse.h>
+#include <httperr.h>
+#include <httpstringconstants.h>
+#include <imcvcodc.h> //for base64 en/decoding
+#include <bautils.h>
+#include <e32math.h>
+#include <hash.h>
+#include <e32const.h>
+#include <tconvbase64.h>
+#include "testhttpfilter.h"
+_LIT8( KTESTHTTPFilterName, "TestHttp");
+_LIT8( KAuthenticationInfoStr, "Authentication-Info" );
+_LIT8( KUserAgentProductToken,"3gpp-gba");
+_LIT8( KColon, ":" );
+const TInt KB64KeySize = 64;
+_LIT(KTestHttpFilter, "TEST HTTP FILTER ");
+
+void PanicTestHttpFilters(TInt aErr = 0)
+{
+ User::Panic(KTestHttpFilter, aErr);
+}
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CTestFilter::CTestFilter
+// Constructor
+// -----------------------------------------------------------------------------
+//
+CTestFilter::CTestFilter()
+ : iBootstrapCount(0),iHaveCredentials(EFalse)
+{
+
+}
+
+// -----------------------------------------------------------------------------
+// CTestFilter::InstallFilterL
+// Initialize the filter and register it to sesssion's filter collection
+// -----------------------------------------------------------------------------
+//
+CTestFilterInterface* CTestFilter::InstallFilterL(TAny* aParams)
+{
+ __ASSERT_DEBUG(aParams != NULL, PanicTestHttpFilters());
+ RHTTPSession* session = REINTERPRET_CAST(RHTTPSession*, aParams);
+ CTestFilter* filter = new (ELeave) CTestFilter();
+ CleanupStack::PushL(filter);
+ filter->ConstructL(*session);
+ CleanupStack::Pop(filter);
+ return filter;
+}
+
+// -----------------------------------------------------------------------------
+// CTestFilter::ConstructL
+// Memory and resource allocation, leaves
+// -----------------------------------------------------------------------------
+//
+void CTestFilter::ConstructL(RHTTPSession aSession)
+{
+ iStringPool = aSession.StringPool();
+ // register the filter
+ RStringF filterName = iStringPool.OpenFStringL( KTESTHTTPFilterName );
+ CleanupClosePushL( filterName );
+ iStringPool = aSession.StringPool();
+
+ iUsernameStr = iStringPool.StringF( HTTP::EUsername, RHTTPSession::GetTable() );
+ iPasswordStr = iStringPool.StringF( HTTP::EPassword, RHTTPSession::GetTable() );
+ iUserAgent = iStringPool.OpenFStringL( KUserAgentProductToken );
+ iAuthInfo = iStringPool.OpenFStringL( KAuthenticationInfoStr );
+
+ //Regsiter for THTTPEvent::ESubmit http event
+ aSession.FilterCollection().AddFilterL( *this,
+ THTTPEvent::ESubmit,
+ RStringF(),
+ KAnyStatusCode,
+ EStatusCodeHandler,
+ filterName);
+
+ //Regsiter for THTTPEvent::EGotResponseHeaders http event with "Authentication-Info" header
+ //and HTTPStatus::EOk http status code,just to know if the credentials established are valid.
+ aSession.FilterCollection().AddFilterL( *this,
+ THTTPEvent::EGotResponseHeaders,
+ iAuthInfo,
+ HTTPStatus::EOk,
+ EStatusCodeHandler,
+ filterName );
+
+ //Regsiter for THTTPEvent::EGotResponseHeaders http event with "WWW-Authenticate" header
+ //and HTTPStatus::EUnauthorized http status code
+ //The priority for this is set to MHTTPFilter::EStatusCodeHandler - 1,
+ //so the filter intercepts the transaction before the default
+ //http digest authentication filter(which has priority MHTTPFilter::EStatusCodeHandler).
+
+ aSession.FilterCollection().AddFilterL( *this,
+ THTTPEvent::EGotResponseHeaders, // Any transaction event
+ iStringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
+ HTTPStatus::EUnauthorized,
+ MHTTPFilter::EStatusCodeHandler - 1, // Priority of filter
+ filterName ); // Name of filter
+
+ CleanupStack::PopAndDestroy( &filterName );
+
+ iTimeOut = CTimerOut::NewL(*this);
+
+ }
+
+
+//------------------------------------------------------------------------
+// CTestFilter::~CTestFilter
+// Destructor
+//------------------------------------------------------------------------
+//
+CTestFilter::~CTestFilter()
+{
+ CleanupAll();
+ delete iTimeOut;
+}
+
+//------------------------------------------------------------------------
+// CTestFilter::MHFLoad
+//------------------------------------------------------------------------
+//
+void CTestFilter::MHFLoad(RHTTPSession, THTTPFilterHandle)
+{
+ ++iLoadCount;
+}
+
+//------------------------------------------------------------------------
+// CTestFilter::MHFUnload
+//------------------------------------------------------------------------
+//
+void CTestFilter::MHFUnload(RHTTPSession , THTTPFilterHandle)
+{
+ __ASSERT_DEBUG( iLoadCount >= 0, PanicTestHttpFilters() );
+
+ if (--iLoadCount)
+ {
+ return;
+ }
+ delete this;
+}
+
+//------------------------------------------------------------------------
+// CTestFilter::MHFRunL
+// See MHTTPFilterBase::MHFRunL
+//------------------------------------------------------------------------
+//
+void CTestFilter::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent)
+{
+ if (aEvent.iUID != KHTTPUid)
+ return;
+
+ switch(aEvent.iStatus)
+ {
+ case THTTPEvent::ESubmit:
+ {
+ DoSubmitL(aTransaction);
+ }
+ break;
+
+ case THTTPEvent::EGotResponseHeaders:
+ {
+ // Get HTTP status code from header (e.g. 200)
+ RHTTPResponse resp = aTransaction.Response();
+ CheckHeadersL( aTransaction );
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+
+}
+
+
+//------------------------------------------------------------------------
+// CTestFilter::MHFRunError
+// See MHTTPFilterBase::MHFRunError
+//------------------------------------------------------------------------
+//
+TInt CTestFilter::MHFRunError(TInt /*aError*/, RHTTPTransaction aTransaction, const THTTPEvent& )
+{
+ TInt error = 0;
+ // map aError to global error message
+ // pass the errorcode forward
+ THTTPEvent httpEvent(error);
+ TRAP_IGNORE(aTransaction.SendEventL(httpEvent, THTTPEvent::EIncoming, THTTPFilterHandle::ECurrentFilter ));
+ return KErrNone;
+}
+
+//------------------------------------------------------------------------
+// CTestFilter::MHFSessionRunL
+// See MHTTPFilterBase::MHFSessionRunL
+//------------------------------------------------------------------------
+//
+void CTestFilter::MHFSessionRunL(const THTTPSessionEvent& )
+{
+ // do nothing
+}
+
+//------------------------------------------------------------------------
+// CTestFilter::MHFSessionRunL
+// See MHTTPFilterBase::MHFSessionRunL
+//------------------------------------------------------------------------
+//
+TInt CTestFilter::MHFSessionRunError(TInt aError, const THTTPSessionEvent& )
+{
+ // session problem
+ return aError;
+}
+//------------------------------------------------------------------------
+// CTestFilter::CheckHeadersL
+// Check HTTP headers and extract MIME type
+//------------------------------------------------------------------------
+//
+void CTestFilter::CheckHeadersL( RHTTPTransaction& aTrans )
+{
+ // read the header data and check the MIME type here
+ // check the status and body
+ RHTTPResponse response = aTrans.Response();
+ TInt status = response.StatusCode();
+ THTTPHdrVal fieldVal;
+ // check if status == 401 and realm is 3GPP then we need to bootstrap, if we are already bootstrappign this is the second call
+ if( status == HTTPStatus::EUnauthorized )
+ {
+
+ TInt headerPart=0;
+ THTTPHdrVal headerVal;
+ TInt cred = KErrNotFound;
+ RStringF wwwAuthHeader = iStringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable());
+ RHTTPHeaders headers(aTrans.Response().GetHeaderCollection());
+
+ RString realm;
+ THTTPHdrVal hdrVal;
+ if (!headers.GetParam(wwwAuthHeader, iStringPool.StringF(HTTP::ERealm,RHTTPSession::GetTable()),
+ hdrVal, headerPart))
+ {
+ realm = hdrVal;
+ const TDesC8& val = realm.DesC();
+ if (headerPart == KErrNotFound)
+ return;
+ THTTPHdrVal authTypeParam;
+
+
+ RHTTPTransactionPropertySet propSet = aTrans.PropertySet();
+ // if we are already bootstrapping results will be retrieved when request is resubmitted
+ iBootstrapPending = ETrue;
+
+
+ TTimeIntervalMicroSeconds32 aInterval(20000000);
+
+ iTimeOut->Start(aInterval); //Start the http post request timer, aInterval - timeout in micro-seconds
+
+ if(!iBootstrapWait.IsStarted())
+ {
+ iBootstrapWait.Start();
+ }
+
+ if( iHaveCredentials )
+ {
+ RHTTPTransactionPropertySet propSet = aTrans.PropertySet();
+
+ //user name/pass word for accessing http://replab.nrln.net/digest/
+ //username: dummy, password: dummy
+ TBuf8<KB64KeySize> keyBase64(_L8("Aladdin"));
+ TBuf8<KB64KeySize> keyBase64Username(_L8("open sesame"));;
+ RString username = iStringPool.OpenStringL( keyBase64 );
+ CleanupClosePushL<RString>( username );
+ RString password = iStringPool.OpenStringL( keyBase64Username );
+ CleanupClosePushL<RString>( password );
+ propSet.SetPropertyL( iUsernameStr, username );
+ propSet.SetPropertyL( iPasswordStr, password );
+ CleanupStack::PopAndDestroy(&password);
+ CleanupStack::PopAndDestroy(&username);
+ //Cancel the transaction
+ aTrans.Cancel();
+ // Re-submit the http request with much needed credentials
+ aTrans.SubmitL();
+ }
+ else
+ {
+ //Since bootstrapping failed,Do not have to resubmit the http request ?
+ return;
+ }
+
+ }
+ }
+}
+
+void CTestFilter::DoSubmitL( RHTTPTransaction aTransaction )
+{
+ RHTTPHeaders hdr = aTransaction.Request().GetHeaderCollection();
+
+ RStringF fieldname = aTransaction.Session().StringPool().StringF(HTTP::EUserAgent,RHTTPSession::GetTable());
+
+ TBool found = EFalse;
+ TPtrC8 rawFieldData;
+
+ hdr.GetRawField(fieldname, rawFieldData);
+
+ found = rawFieldData.Find(iUserAgent.DesC()) != KErrNotFound;
+
+ if(!found)
+ hdr.SetFieldL(fieldname, iUserAgent);
+
+ TInt cred = KErrNotFound;
+
+ if( iHaveCredentials )
+ {
+ TBuf8<KB64KeySize> keyBase64(_L8("Aladdin"));
+ TBuf8<KB64KeySize> keyBase64Username(_L8("open sesame"));;
+ RString username = iStringPool.OpenStringL( keyBase64 );
+ CleanupClosePushL<RString>( username );
+ RString password = iStringPool.OpenStringL( keyBase64Username );
+ CleanupClosePushL<RString>( password );
+ EncodeBasicAuthL(username, password, aTransaction);
+ CleanupStack::PopAndDestroy(&password);
+ CleanupStack::PopAndDestroy(&username);
+
+ }
+}
+
+//-----------------------------------------------------------------------------
+// CTestFilter::CleanupAll
+// Cleanup all the transactions, in case a session error happens or a session
+// is closed.
+//-----------------------------------------------------------------------------
+//
+void CTestFilter::CleanupAll()
+{
+
+ iUserAgent.Close();
+ iAuthInfo.Close();
+}
+
+TBool CTestFilter::HandleTimerEventL(TTimerEventType /*aEventType*/)
+{
+ iBootstrapPending = EFalse;
+
+ iHaveCredentials = ETrue;
+
+ if (iBootstrapWait.IsStarted())
+ iBootstrapWait.AsyncStop();
+
+ return ETrue;
+}
+
+
+void CTestFilter::EncodeBasicAuthL(RString& aUsername,
+ RString& aPW,
+ RHTTPTransaction& aTransaction)
+ {
+ // Standard, plain-text HTTP - Base 64 the name and password
+ TBase64 codec;
+ HBufC8* nameAndPW = HBufC8::NewMaxLC(aUsername.DesC().Length() + aPW.DesC().Length() + 1);
+ _LIT8(KBasicAuthFormatString, "%S:%S");
+ nameAndPW->Des().Format(KBasicAuthFormatString, &aUsername.DesC(), &aPW.DesC());
+
+ // Conservatively allocate a buffer twice as big as the unencoded
+ // buffer for the encoded string.
+ HBufC8* encoded = HBufC8::NewMaxLC(nameAndPW->Des().Length() * 2);
+ TPtr8 encodedPtr(encoded->Des());
+ codec.Encode(*nameAndPW, encodedPtr);
+
+ RString encodedString = iStringPool.OpenStringL(*encoded);
+ CleanupStack::PopAndDestroy(2, nameAndPW);
+
+ CleanupClosePushL(encodedString);
+
+ RHTTPHeaders requestHeaders(aTransaction.Request().GetHeaderCollection());
+
+ requestHeaders.RemoveField(iStringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()));
+ requestHeaders.SetFieldL(iStringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(iStringPool.StringF(HTTP::EBasic,RHTTPSession::GetTable())));
+
+ requestHeaders.SetFieldL(iStringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(encodedString));
+
+ aTransaction.PropertySet().SetPropertyL(iStringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()),
+ THTTPHdrVal(encodedString));
+
+ CleanupStack::PopAndDestroy(&encodedString);
+
+ }