httpfilters/httpfilteriop/Src/HttpFilterIop.cpp
changeset 0 b16258d2340f
child 6 fa2fd8b2d6cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/httpfilters/httpfilteriop/Src/HttpFilterIop.cpp	Tue Feb 02 01:09:52 2010 +0200
@@ -0,0 +1,321 @@
+/*
+* Copyright (c) 2003 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:  Iop filter
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <http.h>
+#include <es_sock.h>
+
+// User Includes
+#include "httpfilterIop.h"
+#include "httpfiltercommonstringsext.h"
+
+#include "MIopRedirectCallback.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+void PanicHttpFiltersIop(TInt aErr = 0);
+
+// CONSTANTS
+const TInt KIopOrderOffset = 10;
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CHttpFilterIop::CHttpFilterIop
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CHttpFilterIop::CHttpFilterIop(RHTTPSession* aSession, MIopRedirectCallback* aIopRedirectCallback, TUint aIopCapabilities)
+{
+    __ASSERT_DEBUG(aSession != NULL, PanicHttpFiltersIop());
+    iSession = aSession;
+	iIopCapabilities = aIopCapabilities;
+	iIopRedirectCallback = aIopRedirectCallback; //can be null for backward compatibility or iopOptionRedirectAction not used
+	iLoadCount = 0;
+}
+
+
+// ------------------------------------------------------------------------------------------
+// CHttpFilterIop::ConstructL
+// Symbian 2nd phase constructor can leave.
+// ------------------------------------------------------------------------------------------
+//
+void CHttpFilterIop::ConstructL()
+{
+	if (iIopCapabilities & iopOptionHostHeader)
+		{
+		// Register the filter for submit events,
+		// Adds a filter to the session's filter queue.
+
+		iSession->FilterCollection().AddFilterL(*this,   // The filter to add
+												THTTPEvent::ESubmit,       // The event that triggers this filter
+												RStringF(),                // The header whose presence triggers this filter, or KNullDesC to trigger on any header
+												KAnyStatusCode,            // The status code that triggers this filter, or KAnyStatusCode to trigger on any status code
+												EStatusCodeHandler - KIopOrderOffset,    // The position of the filter in the queue
+												iSession->StringPool().StringF(HttpFilterCommonStringsExt::EIopFilter,
+												HttpFilterCommonStringsExt::GetTable())); //The name of the filter to add
+		}
+
+	if ( (iIopCapabilities & iopOptionRedirectAction) && iIopRedirectCallback)
+		{
+		// 301 Found
+		iSession->FilterCollection().AddFilterL(*this, // The filter to add
+									THTTPEvent::EGotResponseHeaders, // The event that triggers this filter
+									RStringF(),						 // The header whose presence triggers this filter, or KNullDesC to trigger on any header
+									301,							// The status code that triggers this filter, or KAnyStatusCode to trigger on any status code
+									EStatusCodeHandler-10,			// The position of the filter in the queue
+									iSession->StringPool().StringF(HttpFilterCommonStringsExt::EIopFilter,
+									HttpFilterCommonStringsExt::GetTable())); //The name of the filter to add
+		// 302 Found
+		iSession->FilterCollection().AddFilterL(*this, // The filter to add
+									THTTPEvent::EGotResponseHeaders, // The event that triggers this filter
+									RStringF(),						 // The header whose presence triggers this filter, or KNullDesC to trigger on any header
+									302,							// The status code that triggers this filter, or KAnyStatusCode to trigger on any status code
+									EStatusCodeHandler-10,			// The position of the filter in the queue
+									iSession->StringPool().StringF(HttpFilterCommonStringsExt::EIopFilter,
+									HttpFilterCommonStringsExt::GetTable())); //The name of the filter to add
+
+		// 303 See other
+		iSession->FilterCollection().AddFilterL(*this, // The filter to add
+									THTTPEvent::EGotResponseHeaders, // The event that triggers this filter
+									RStringF(),						 // The header whose presence triggers this filter, or KNullDesC to trigger on any header
+									303,							// The status code that triggers this filter, or KAnyStatusCode to trigger on any status code
+									EStatusCodeHandler-10,			// The position of the filter in the queue
+									iSession->StringPool().StringF(HttpFilterCommonStringsExt::EIopFilter,
+									HttpFilterCommonStringsExt::GetTable())); //The name of the filter to add
+		// 307 See other
+		iSession->FilterCollection().AddFilterL(*this, // The filter to add
+									THTTPEvent::EGotResponseHeaders, // The event that triggers this filter
+									RStringF(),						 // The header whose presence triggers this filter, or KNullDesC to trigger on any header
+									307,							// The status code that triggers this filter, or KAnyStatusCode to trigger on any status code
+									EStatusCodeHandler-10,			// The position of the filter in the queue
+									iSession->StringPool().StringF(HttpFilterCommonStringsExt::EIopFilter,
+									HttpFilterCommonStringsExt::GetTable())); //The name of the filter to add
+
+		}
+
+}
+
+//---------------------------------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------------------------------
+//
+CHttpFilterIop::~CHttpFilterIop()
+{
+    // If we've been destroyed from the cleanup stack during creation
+    // of the object, it might still be loaded. So check. (Normaly the
+    // delete is initiated by the 'delete this' in MHFUnload)
+    if (iLoadCount)
+        {
+        // As we're already in a destructor, MHFUnload must not delete us again
+        iLoadCount = -1;
+        if( NULL != iSession)  
+  			{  
+     		iSession->FilterCollection().RemoveFilter(iSession->StringPool().StringF( HttpFilterCommonStringsExt::EIopFilter, HttpFilterCommonStringsExt::GetTable()));  
+  			}  
+
+        }
+}
+
+// ---------------------------------------------------------------------------------------------
+// CHttpFilterIop::InstallFilterL
+// Two-phased constructor. This function replaces NewL.
+// ---------------------------------------------------------------------------------------------
+//
+CHttpFilterIop* CHttpFilterIop::InstallFilterL(TAny* aParams)
+{
+    __ASSERT_DEBUG(aParams != NULL, PanicHttpFiltersIop());
+    TIopParams* iopParams = REINTERPRET_CAST(TIopParams*, aParams);
+    __ASSERT_DEBUG(iopParams->iSession != NULL, PanicHttpFiltersIop());
+
+    CHttpFilterIop* filter = new (ELeave) CHttpFilterIop( iopParams->iSession, iopParams->iIopRedirectCallback, iopParams->iIopCapabilities );
+    CleanupStack::PushL(filter);
+    filter->ConstructL();
+    CleanupStack::Pop(filter);
+    return filter;
+}
+
+// ---------------------------------------------------------------------------------------------
+// CHttpFilterIop::MHFLoad
+// Called when the filter is being added to the session's filter queue.
+// ---------------------------------------------------------------------------------------------
+//
+void CHttpFilterIop::MHFLoad(RHTTPSession, THTTPFilterHandle)
+{
+    ++iLoadCount;
+}
+
+// ----------------------------------------------------------------------------------------------
+// CHttpFilterIop::MHFUnload
+// Called when the filter is being removed from a session's filter queue.
+// ----------------------------------------------------------------------------------------------
+//
+void CHttpFilterIop::MHFUnload(RHTTPSession /*aSession*/, THTTPFilterHandle /*aFilterHandler*/)
+{
+    __ASSERT_DEBUG(iLoadCount >= 0, PanicHttpFiltersIop());
+    if (--iLoadCount)
+    {
+        return;
+    }
+    delete this;
+}
+
+// ------------------------------------------------------------------------------------------------
+// CHttpFilterIop::MHFRunL
+// Process a transaction event.
+// ------------------------------------------------------------------------------------------------
+//
+void CHttpFilterIop::MHFRunL(RHTTPTransaction aTransaction,
+                             const THTTPEvent& aEvent)
+{
+	switch (aEvent.iStatus)
+		{
+		case THTTPEvent::ESubmit:
+			{
+			_LIT8(KPort80, "80");
+			TPtrC8 port80Ptr = KPort80();
+
+			RHTTPHeaders headers(aTransaction.Request().GetHeaderCollection());
+			if (iIopCapabilities & iopOptionHostHeader)
+				{
+				TUriC8 uri = aTransaction.Request().URI();
+				TPtrC8 hostPtr = uri.Extract(EUriHost);
+				TPtrC8 portPtr = uri.Extract(EUriPort);
+				if (portPtr.Length() > 0 && portPtr.Compare(port80Ptr))
+					{
+					hostPtr.Set(hostPtr.Ptr(), hostPtr.Length() + 1 + portPtr.Length());
+					}
+
+				headers.RemoveField(iSession->StringPool().StringF(HTTP::EHost, RHTTPSession::GetTable()));
+				if (hostPtr.Length() > 0)
+					{
+					RStringF hostString = iSession->StringPool().OpenFStringL(hostPtr);
+					CleanupClosePushL(hostString);
+					headers.SetFieldL(iSession->StringPool().StringF(HTTP::EHost, RHTTPSession::GetTable()),
+											 THTTPHdrVal(hostString));
+					CleanupStack::PopAndDestroy(); // hostString
+					}
+				}
+			break;
+			} // case THTTPEvent::ESubmit:
+		case THTTPEvent::EGotResponseHeaders:
+			{
+			switch (aTransaction.Response().StatusCode())
+				{
+				case 301:
+				case 302:
+				case 303:
+				case 307:
+					{
+					if (iIopRedirectCallback) // can not be null
+						HandleRedirectL(aTransaction);
+					break;
+					}
+				default:
+					break;
+				} //  switch (aTransaction.Response().StatusCode())
+			} // case THTTPEvent::EGotResponseHeaders:
+		default:
+			break;
+		} // switch (aEvent.iStatus)
+}
+
+// -----------------------------------------------------------------------------
+// CHttpFilterIop::MHFRunError
+// Process an error that occured while processing the transaction.
+// -----------------------------------------------------------------------------
+//
+TInt CHttpFilterIop::MHFRunError(TInt ,
+                                 RHTTPTransaction ,
+                                 const THTTPEvent& )
+{
+//    aTransaction.Fail();
+    return KErrNone;
+}
+
+// -----------------------------------------------------------------------------
+// CHttpFilterIop::MHFSessionRunL
+// Process a session event.
+// -----------------------------------------------------------------------------
+//
+void CHttpFilterIop::MHFSessionRunL(const THTTPSessionEvent& /*aEvent*/)
+{
+}
+
+// -----------------------------------------------------------------------------
+// CHttpFilterIop::MHFSessionRunError
+// Called when MHFRunL leaves from a session event.
+// -----------------------------------------------------------------------------
+//
+TInt CHttpFilterIop::MHFSessionRunError(TInt aError, const THTTPSessionEvent& /*aEvent*/)
+{
+    return aError;
+}
+
+// -----------------------------------------------------------------------------
+// CHttpFilterIop::HandleRedirectL
+// Called when received redirection status code 
+// -----------------------------------------------------------------------------
+//
+void CHttpFilterIop::HandleRedirectL(RHTTPTransaction aTransaction)
+    {
+
+	RStringPool strPool = iSession->StringPool();
+    RStringF location = strPool.StringF(HTTP::ELocation,RHTTPSession::GetTable());
+    RHTTPHeaders responseHeaders(aTransaction.Response().GetHeaderCollection());
+    THTTPHdrVal locationValue;
+
+    TInt err = responseHeaders.GetField(location, 0, locationValue);
+    if (err == KErrNotFound) // location not present when redirected
+        return; // Redirect filter will deal with it, we care only about non http, https and relative(assumes http(s) ) schemes
+    else
+        {
+		User::LeaveIfError(err);
+        TUriParser8 uri;
+        uri.Parse(locationValue.StrF().DesC());
+		if (uri.IsPresent(EUriHost) && uri.IsPresent(EUriScheme)) // looking only for absolue Url path and schemes other than http(s)
+			{
+				const TDesC8& scheme = uri.Extract(EUriScheme);
+				if (scheme.FindF(_L8("http")) == KErrNotFound) // everything but http(s)
+				{
+					TPtrC8 ptr(uri.UriDes());
+					iIopRedirectCallback->NonHttpRedirect(ptr, aTransaction);
+					aTransaction.Cancel();
+				}
+			}
+		}
+    }
+
+//  End of File
+