applayerprotocols/httptransportfw/Test/testfilter/testhttpfilter.cpp
branchRCL_3
changeset 3 5ee1d9ce5878
child 6 fa2fd8b2d6cc
equal deleted inserted replaced
0:b16258d2340f 3:5ee1d9ce5878
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <http/rhttptransaction.h>
       
    17 #include <http/rhttpheaders.h>
       
    18 #include <http/rhttpresponse.h>
       
    19 #include <httperr.h>
       
    20 #include <httpstringconstants.h>
       
    21 #include <imcvcodc.h>      //for base64 en/decoding
       
    22 #include <bautils.h>
       
    23 #include <e32math.h>
       
    24 #include <hash.h>
       
    25 #include <e32const.h>
       
    26 #include <tconvbase64.h>
       
    27 #include "testhttpfilter.h"
       
    28 _LIT8( KTESTHTTPFilterName, "TestHttp");
       
    29 _LIT8( KAuthenticationInfoStr, "Authentication-Info" );
       
    30 _LIT8( KUserAgentProductToken,"3gpp-gba");
       
    31 _LIT8( KColon, ":" );
       
    32 const TInt KB64KeySize = 64;
       
    33 _LIT(KTestHttpFilter, "TEST HTTP FILTER ");
       
    34 
       
    35 void PanicTestHttpFilters(TInt aErr = 0)
       
    36 {
       
    37     User::Panic(KTestHttpFilter, aErr);
       
    38 }
       
    39 
       
    40 // ============================ MEMBER FUNCTIONS ===============================
       
    41 
       
    42 // -----------------------------------------------------------------------------
       
    43 // CTestFilter::CTestFilter
       
    44 // Constructor
       
    45 // -----------------------------------------------------------------------------
       
    46 //
       
    47 CTestFilter::CTestFilter()
       
    48 		: iBootstrapCount(0),iHaveCredentials(EFalse)
       
    49 {
       
    50 
       
    51 }
       
    52 
       
    53 // -----------------------------------------------------------------------------
       
    54 // CTestFilter::InstallFilterL
       
    55 // Initialize the filter and register it to sesssion's filter collection
       
    56 // -----------------------------------------------------------------------------
       
    57 //
       
    58 CTestFilterInterface* CTestFilter::InstallFilterL(TAny* aParams)
       
    59 {
       
    60 	__ASSERT_DEBUG(aParams != NULL, PanicTestHttpFilters());
       
    61 	RHTTPSession* session = REINTERPRET_CAST(RHTTPSession*, aParams);
       
    62 	CTestFilter* filter = new (ELeave) CTestFilter();
       
    63 	CleanupStack::PushL(filter);
       
    64 	filter->ConstructL(*session);
       
    65 	CleanupStack::Pop(filter);
       
    66 	return filter;
       
    67 }
       
    68 	
       
    69 // -----------------------------------------------------------------------------
       
    70 // CTestFilter::ConstructL
       
    71 // Memory and resource allocation, leaves
       
    72 // -----------------------------------------------------------------------------
       
    73 //
       
    74 void CTestFilter::ConstructL(RHTTPSession aSession)
       
    75 {
       
    76 	iStringPool = aSession.StringPool();
       
    77 	// register the filter
       
    78 	RStringF filterName = iStringPool.OpenFStringL( KTESTHTTPFilterName );
       
    79 	CleanupClosePushL( filterName );
       
    80 	iStringPool = aSession.StringPool();
       
    81 
       
    82 	iUsernameStr = iStringPool.StringF( HTTP::EUsername, RHTTPSession::GetTable() );
       
    83     iPasswordStr = iStringPool.StringF( HTTP::EPassword, RHTTPSession::GetTable() );
       
    84 	iUserAgent = iStringPool.OpenFStringL( KUserAgentProductToken );
       
    85     iAuthInfo = iStringPool.OpenFStringL( KAuthenticationInfoStr );
       
    86     
       
    87     //Regsiter for THTTPEvent::ESubmit http event
       
    88     aSession.FilterCollection().AddFilterL( *this,
       
    89                                             THTTPEvent::ESubmit,
       
    90                                             RStringF(),
       
    91                                             KAnyStatusCode,
       
    92                                             EStatusCodeHandler,
       
    93                                             filterName);
       
    94    
       
    95     //Regsiter for THTTPEvent::EGotResponseHeaders http event with "Authentication-Info" header 
       
    96     //and HTTPStatus::EOk http status code,just to know if the credentials established are valid.
       
    97     aSession.FilterCollection().AddFilterL( *this,
       
    98                                             THTTPEvent::EGotResponseHeaders,
       
    99                                             iAuthInfo,
       
   100                                             HTTPStatus::EOk,
       
   101                                             EStatusCodeHandler,
       
   102                                             filterName );
       
   103 
       
   104     //Regsiter for THTTPEvent::EGotResponseHeaders http event with "WWW-Authenticate" header 
       
   105     //and HTTPStatus::EUnauthorized http status code
       
   106     //The priority for this is set to MHTTPFilter::EStatusCodeHandler - 1,
       
   107     //so the filter intercepts the transaction before the default 
       
   108     //http digest authentication filter(which has priority MHTTPFilter::EStatusCodeHandler).
       
   109 
       
   110     aSession.FilterCollection().AddFilterL( *this, 
       
   111 											THTTPEvent::EGotResponseHeaders,	// Any transaction event
       
   112 											iStringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()),
       
   113 											HTTPStatus::EUnauthorized,
       
   114 											MHTTPFilter::EStatusCodeHandler - 1,	  // Priority of filter
       
   115 											filterName );						      // Name of filter
       
   116 
       
   117 	CleanupStack::PopAndDestroy( &filterName );
       
   118   
       
   119     iTimeOut =  CTimerOut::NewL(*this);
       
   120     
       
   121 	}
       
   122 
       
   123 
       
   124 //------------------------------------------------------------------------
       
   125 // CTestFilter::~CTestFilter
       
   126 // Destructor
       
   127 //------------------------------------------------------------------------
       
   128 //
       
   129 CTestFilter::~CTestFilter()
       
   130 {
       
   131 	CleanupAll();			
       
   132 	delete iTimeOut;
       
   133 }
       
   134 
       
   135 //------------------------------------------------------------------------
       
   136 // CTestFilter::MHFLoad
       
   137 //------------------------------------------------------------------------
       
   138 //
       
   139 void CTestFilter::MHFLoad(RHTTPSession, THTTPFilterHandle)
       
   140 {
       
   141 	++iLoadCount;
       
   142 }
       
   143 
       
   144 //------------------------------------------------------------------------
       
   145 // CTestFilter::MHFUnload
       
   146 //------------------------------------------------------------------------
       
   147 //
       
   148 void CTestFilter::MHFUnload(RHTTPSession , THTTPFilterHandle)
       
   149 {
       
   150 	 __ASSERT_DEBUG( iLoadCount >= 0, PanicTestHttpFilters() );
       
   151     
       
   152 	if (--iLoadCount)
       
   153 	{
       
   154 		return;
       
   155 	}
       
   156 	delete this;
       
   157 }
       
   158 
       
   159 //------------------------------------------------------------------------
       
   160 // CTestFilter::MHFRunL
       
   161 // See MHTTPFilterBase::MHFRunL 
       
   162 //------------------------------------------------------------------------
       
   163 //
       
   164 void CTestFilter::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent)
       
   165 {
       
   166 	if (aEvent.iUID != KHTTPUid) 
       
   167 		return;
       
   168 
       
   169 	switch(aEvent.iStatus)
       
   170 	{
       
   171 		case THTTPEvent::ESubmit:
       
   172 		{
       
   173 			DoSubmitL(aTransaction);
       
   174 		}
       
   175 		break;
       
   176 
       
   177 		case THTTPEvent::EGotResponseHeaders:
       
   178 		{
       
   179 			// Get HTTP status code from header (e.g. 200)
       
   180 			RHTTPResponse resp = aTransaction.Response();
       
   181 			CheckHeadersL( aTransaction );
       
   182 		}
       
   183 		break;
       
   184 		default: 
       
   185 		{
       
   186 		}
       
   187 		break;
       
   188 	}
       
   189 	
       
   190 }
       
   191 
       
   192 
       
   193 //------------------------------------------------------------------------
       
   194 // CTestFilter::MHFRunError
       
   195 // See MHTTPFilterBase::MHFRunError
       
   196 //------------------------------------------------------------------------
       
   197 //
       
   198 TInt CTestFilter::MHFRunError(TInt /*aError*/, RHTTPTransaction aTransaction, const THTTPEvent& )
       
   199 {
       
   200  	TInt error = 0;
       
   201 	// map aError to global error message
       
   202 	// pass the errorcode forward
       
   203 	THTTPEvent httpEvent(error);
       
   204 	TRAP_IGNORE(aTransaction.SendEventL(httpEvent, THTTPEvent::EIncoming, THTTPFilterHandle::ECurrentFilter ));
       
   205 	return KErrNone;
       
   206 }
       
   207 
       
   208 //------------------------------------------------------------------------
       
   209 // CTestFilter::MHFSessionRunL
       
   210 // See MHTTPFilterBase::MHFSessionRunL
       
   211 //------------------------------------------------------------------------
       
   212 //
       
   213 void CTestFilter::MHFSessionRunL(const THTTPSessionEvent& )
       
   214 {
       
   215 	// do nothing
       
   216 }
       
   217 
       
   218 //------------------------------------------------------------------------
       
   219 // CTestFilter::MHFSessionRunL
       
   220 // See MHTTPFilterBase::MHFSessionRunL
       
   221 //------------------------------------------------------------------------
       
   222 //
       
   223 TInt CTestFilter::MHFSessionRunError(TInt aError, const THTTPSessionEvent& )
       
   224 {
       
   225 	// session problem
       
   226 	return aError;
       
   227 }
       
   228 //------------------------------------------------------------------------
       
   229 // CTestFilter::CheckHeadersL
       
   230 // Check HTTP headers and extract MIME type
       
   231 //------------------------------------------------------------------------
       
   232 // 
       
   233 void CTestFilter::CheckHeadersL(  RHTTPTransaction& aTrans )
       
   234 {
       
   235 	// read the header data and check the MIME type here	
       
   236 	// check the status and body
       
   237 	RHTTPResponse response = aTrans.Response();
       
   238 	TInt status = response.StatusCode();
       
   239 	THTTPHdrVal fieldVal;
       
   240 	// check if status == 401 and realm is 3GPP then we need to bootstrap, if we are already bootstrappign this is the second call
       
   241 	if(  status == HTTPStatus::EUnauthorized )
       
   242 	{				
       
   243 	
       
   244 	   TInt headerPart=0;    	
       
   245 	   THTTPHdrVal headerVal;
       
   246        TInt cred = KErrNotFound;
       
   247        RStringF wwwAuthHeader = iStringPool.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable());
       
   248 	   RHTTPHeaders headers(aTrans.Response().GetHeaderCollection());
       
   249 
       
   250 	    RString realm;
       
   251 	    THTTPHdrVal hdrVal;
       
   252 	    if (!headers.GetParam(wwwAuthHeader, iStringPool.StringF(HTTP::ERealm,RHTTPSession::GetTable()), 
       
   253 				  hdrVal, headerPart))
       
   254 	    {
       
   255 			realm = hdrVal;
       
   256 			const TDesC8& val = realm.DesC();
       
   257 	   			if (headerPart == KErrNotFound)
       
   258 					return;
       
   259 	            THTTPHdrVal authTypeParam;
       
   260 
       
   261 
       
   262 	 				RHTTPTransactionPropertySet propSet = aTrans.PropertySet();
       
   263 	 				// if we are already bootstrapping results will be retrieved when request is resubmitted
       
   264 	                iBootstrapPending = ETrue;
       
   265 	                
       
   266              
       
   267 	                TTimeIntervalMicroSeconds32 aInterval(20000000);
       
   268 	                
       
   269 	                iTimeOut->Start(aInterval); //Start the http post request timer, aInterval - timeout in micro-seconds
       
   270 	                
       
   271 	                if(!iBootstrapWait.IsStarted())
       
   272 	                    {
       
   273                         iBootstrapWait.Start();
       
   274 	                    }
       
   275 	                  
       
   276 	                if( iHaveCredentials )
       
   277 	                    {
       
   278                         RHTTPTransactionPropertySet propSet = aTrans.PropertySet();
       
   279                        
       
   280                         //user name/pass word for accessing http://replab.nrln.net/digest/ 
       
   281                         //username: dummy, password: dummy
       
   282                         TBuf8<KB64KeySize> keyBase64(_L8("Aladdin")); 
       
   283                         TBuf8<KB64KeySize> keyBase64Username(_L8("open sesame"));;
       
   284                         RString username = iStringPool.OpenStringL( keyBase64 );
       
   285                         CleanupClosePushL<RString>( username );
       
   286                         RString password = iStringPool.OpenStringL( keyBase64Username );
       
   287                        CleanupClosePushL<RString>( password );
       
   288                         propSet.SetPropertyL( iUsernameStr, username );
       
   289                         propSet.SetPropertyL( iPasswordStr, password );
       
   290                         CleanupStack::PopAndDestroy(&password);
       
   291                         CleanupStack::PopAndDestroy(&username);
       
   292                         //Cancel the transaction
       
   293                         aTrans.Cancel();
       
   294                         // Re-submit the http request with much needed credentials
       
   295                         aTrans.SubmitL(); 
       
   296                         }
       
   297 	                else
       
   298 	                    {
       
   299                         //Since bootstrapping failed,Do not have to resubmit the http request ?
       
   300                         return;
       
   301                         }
       
   302 			
       
   303 		}
       
   304 	}
       
   305 }
       
   306 
       
   307 void CTestFilter::DoSubmitL( RHTTPTransaction aTransaction )
       
   308 {
       
   309 	RHTTPHeaders hdr = aTransaction.Request().GetHeaderCollection();
       
   310 	
       
   311 	RStringF fieldname = aTransaction.Session().StringPool().StringF(HTTP::EUserAgent,RHTTPSession::GetTable());
       
   312 	
       
   313 	TBool found = EFalse;
       
   314 	TPtrC8 rawFieldData;
       
   315 	
       
   316 	hdr.GetRawField(fieldname, rawFieldData);
       
   317 	
       
   318 	found = rawFieldData.Find(iUserAgent.DesC()) != KErrNotFound;
       
   319 	
       
   320 	if(!found)
       
   321 	    hdr.SetFieldL(fieldname, iUserAgent);
       
   322 	
       
   323     TInt cred = KErrNotFound;
       
   324     
       
   325     if( iHaveCredentials )
       
   326         {
       
   327         TBuf8<KB64KeySize> keyBase64(_L8("Aladdin")); 
       
   328         TBuf8<KB64KeySize> keyBase64Username(_L8("open sesame"));;
       
   329         RString username = iStringPool.OpenStringL( keyBase64 );
       
   330         CleanupClosePushL<RString>( username );
       
   331         RString password = iStringPool.OpenStringL( keyBase64Username );
       
   332         CleanupClosePushL<RString>( password );
       
   333 		EncodeBasicAuthL(username, password, aTransaction);
       
   334         CleanupStack::PopAndDestroy(&password);
       
   335         CleanupStack::PopAndDestroy(&username);
       
   336         	
       
   337         }
       
   338 }
       
   339 
       
   340 //-----------------------------------------------------------------------------
       
   341 // CTestFilter::CleanupAll
       
   342 // Cleanup all the transactions, in case a session error happens or a session
       
   343 // is closed.
       
   344 //-----------------------------------------------------------------------------
       
   345 //
       
   346 void CTestFilter::CleanupAll()
       
   347 {	
       
   348 	
       
   349 	iUserAgent.Close();
       
   350 	iAuthInfo.Close();
       
   351 }
       
   352 
       
   353 TBool CTestFilter::HandleTimerEventL(TTimerEventType /*aEventType*/)
       
   354 {
       
   355     iBootstrapPending = EFalse;
       
   356     
       
   357     iHaveCredentials = ETrue;
       
   358      
       
   359     if (iBootstrapWait.IsStarted())
       
   360     	iBootstrapWait.AsyncStop();
       
   361     
       
   362     return ETrue;
       
   363 }
       
   364 
       
   365 
       
   366 void CTestFilter::EncodeBasicAuthL(RString& aUsername, 
       
   367 										  RString& aPW, 
       
   368 										  RHTTPTransaction& aTransaction)
       
   369 	{
       
   370 	// Standard, plain-text HTTP - Base 64 the name and password
       
   371 	TBase64 codec;
       
   372 	HBufC8* nameAndPW = HBufC8::NewMaxLC(aUsername.DesC().Length() + aPW.DesC().Length() + 1);
       
   373 	_LIT8(KBasicAuthFormatString, "%S:%S");
       
   374 	nameAndPW->Des().Format(KBasicAuthFormatString, &aUsername.DesC(), &aPW.DesC());
       
   375  
       
   376 	// Conservatively allocate a buffer twice as big as the unencoded
       
   377 	// buffer for the encoded string.
       
   378 	HBufC8* encoded = HBufC8::NewMaxLC(nameAndPW->Des().Length() * 2);
       
   379 	TPtr8 encodedPtr(encoded->Des());
       
   380 	codec.Encode(*nameAndPW, encodedPtr);
       
   381 	
       
   382 	RString encodedString = iStringPool.OpenStringL(*encoded);
       
   383 	CleanupStack::PopAndDestroy(2, nameAndPW); 
       
   384 
       
   385 	CleanupClosePushL(encodedString);
       
   386 	
       
   387 	RHTTPHeaders requestHeaders(aTransaction.Request().GetHeaderCollection());
       
   388 	
       
   389 	requestHeaders.RemoveField(iStringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable())); 
       
   390 	requestHeaders.SetFieldL(iStringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
       
   391 									THTTPHdrVal(iStringPool.StringF(HTTP::EBasic,RHTTPSession::GetTable())));
       
   392 	
       
   393 	requestHeaders.SetFieldL(iStringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
       
   394 									THTTPHdrVal(encodedString));
       
   395 
       
   396 	aTransaction.PropertySet().SetPropertyL(iStringPool.StringF(HTTP::EAuthorization,RHTTPSession::GetTable()), 
       
   397 																THTTPHdrVal(encodedString));
       
   398 	
       
   399 	CleanupStack::PopAndDestroy(&encodedString);
       
   400 	
       
   401 	}