--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pushmtm/Plugins/PushContentHandler/PushMtmFetchOperation.cpp Wed Sep 01 12:31:04 2010 +0100
@@ -0,0 +1,1043 @@
+/*
+* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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: Implementation of CPushMtmFetchOperation.
+*
+*/
+
+
+
+// INCLUDE FILES
+
+#include "PushMtmFetchOperation.h"
+#include "PushContentHandlerPanic.h"
+#include "PushMtmLog.h"
+#include <push/cslpushmsgentry.h>
+#include <Uri8.h>
+#include <SysUtil.h>
+#include <cookiefilterinterface.h>
+#include <uaproffilter_interface.h>
+#include <CommDbConnPref.h>
+#include <cdbcols.h>
+#include <browseruisdkcrkeys.h>
+#include "PushMtmPrivateCRKeys.h"
+#include <centralrepository.h>
+#include <commdb.h>
+#include <ApDataHandler.h>
+#include <ApAccessPointItem.h>
+#include <ApUtils.h>
+#include <ApSelect.h>
+#include <httpfilteracceptheaderinterface.h>
+#include <httpfilteriopinterface.h>
+#include <httpfiltercommonstringsext.h>
+#include <deflatefilterinterface.h>
+#include <FeatMgr.h>
+
+// ================= MACROS =======================
+
+#ifdef _DEBUG
+ /// Guard "debug-only" argument name with this (expands to argument).
+ #define DEBUG_ONLY( argName ) argName
+#else /* not defined _DEBUG */
+ /// Guard "debug-only" argument name with this (expands to nothing).
+ #define DEBUG_ONLY( argName )
+#endif /* def _DEBUG */
+
+// ================= LOCAL CONSTANTS =======================
+
+_LIT8( KHttpProtString, "HTTP/TCP" );
+_LIT8( KUserAgent, "Push MTM" );
+
+/// Base HTTP error code. See Extended Error Handling UI Specification!
+LOCAL_C const TInt KPushMtmHttpErrorBase = -25000;
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::NewL
+// ---------------------------------------------------------
+//
+CPushMtmFetchOperation* CPushMtmFetchOperation::NewL
+ (
+ const TDesC& aRequestedUrl,
+ TRequestStatus& aObserverRequestStatus
+ )
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::NewL")
+
+ CPushMtmFetchOperation* op =
+ new (ELeave) CPushMtmFetchOperation( aObserverRequestStatus );
+ CleanupStack::PushL( op );
+ op->ConstructL( aRequestedUrl );
+ CleanupStack::Pop( op ); // op
+
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::NewL")
+ return op;
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::~CPushMtmFetchOperation
+// ---------------------------------------------------------
+//
+CPushMtmFetchOperation::~CPushMtmFetchOperation()
+ {
+ Cancel();
+ delete ( iCacheMgr );
+ delete iCacheSupply;
+ iHttpTrans.Close();
+ iHttpSess.Close();
+ iConn.Close();
+ iSockServ.Close();
+ delete iRequestedUrl;
+ delete iSourceUri;
+ delete iBody;
+ FeatureManager::UnInitializeLib();
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::StartL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::StartL()
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::StartL")
+
+ Cancel();
+
+ iResult = KErrNone;
+ iState = EInit;
+
+ SetActive();
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone );
+
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::StartL")
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::CPushMtmFetchOperation
+// ---------------------------------------------------------
+//
+CPushMtmFetchOperation::CPushMtmFetchOperation
+ ( TRequestStatus& aObserverRequestStatus )
+: CActive( EPriorityStandard ),
+ iObserver( aObserverRequestStatus ),
+ iState( EInit ),
+ iResult( KErrNone )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::ConstructL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::ConstructL( const TDesC& aRequestedUrl )
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::ConstructL")
+
+ iRequestedUrl = HBufC8::NewMaxL( aRequestedUrl.Length() );
+ iRequestedUrl->Des().Copy( aRequestedUrl );
+
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::ConstructL")
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::GetDefaultInetAccessPointL
+// ---------------------------------------------------------
+//
+TBool CPushMtmFetchOperation::GetDefaultInetAccessPointL
+ ( TUint32& aIapId ) const
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::GetDefaultInetAccessPointL")
+
+ // Try to find the default AP.
+ // The Browser may stores the default AP in the shared data.
+ CRepository* repository = CRepository::NewL( KCRUidBrowser );
+ CleanupStack::PushL( repository );
+
+ TInt wapApId;
+ User::LeaveIfError
+ ( repository->Get( KBrowserDefaultAccessPoint, wapApId ) );
+ TUint32 wapApId32( wapApId );
+ TUint32 iapId32( 0 );
+
+ CleanupStack::PopAndDestroy( repository );
+ repository = 0;
+
+ CCommsDatabase* commsDb = CCommsDatabase::NewL( EDatabaseTypeIAP );
+ CleanupStack::PushL( commsDb );
+ CApDataHandler* apDataHandler = CApDataHandler::NewLC( *commsDb );
+ CApAccessPointItem* apItem = CApAccessPointItem::NewLC();
+ TRAPD( err, apDataHandler->AccessPointDataL( wapApId32, *apItem ) );
+ CApUtils* apUtils = CApUtils::NewLC( *commsDb );
+
+ TBool wapApFound( EFalse );
+ TBool iapFound( EFalse );
+
+ PUSHLOG_WRITE_FORMAT(" err: <%d>",err)
+ if ( err == KErrNone )
+ {
+ wapApFound = ETrue;
+ }
+ else // err != KErrNone
+ {
+ // The first valid access point has to be selected if exists
+ CApSelect* apSelect = CApSelect::NewLC
+ (
+ *commsDb,
+ KEApIspTypeAll,
+ EApBearerTypeAll,
+ KEApSortNameAscending
+ );
+ if ( apSelect->MoveToFirst() )
+ {
+ wapApFound = ETrue;
+ wapApId32 = apSelect->Uid();
+ }
+ CleanupStack::PopAndDestroy( apSelect ); // apSelect
+ }
+
+ if ( wapApFound )
+ {
+ // Get the IAP ID from the WAP AP ID.
+#ifndef __SERIES60_WSP
+ iapId32 = 0;
+ TRAPD( errTransl, iapId32 = apUtils->IapIdFromWapIdL( wapApId32 ) );
+ PUSHLOG_WRITE_FORMAT(" IapIdFromWapIdL errTransl: <%d>",errTransl)
+ if ( errTransl == KErrNone )
+ {
+ iapFound = ETrue;
+ }
+#else
+ iapId32 = wapApId32;
+ iapFound = ETrue;
+#endif // __SERIES60_WSP
+ }
+
+ CleanupStack::PopAndDestroy( 4 ); // apUtils, apItem,
+ // apDataHandler, commsDb
+
+ if ( iapFound )
+ {
+ aIapId = iapId32;
+ }
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::GetDefaultInetAccessPointL")
+ return iapFound;
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::InitializeL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::InitializeL()
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::InitializeL")
+
+ User::LeaveIfError( iSockServ.Connect() );
+ PUSHLOG_WRITE("CPushMtmFetchOperation iSockServ.Connect() OK")
+ User::LeaveIfError( iConn.Open( iSockServ ) );
+ PUSHLOG_WRITE("CPushMtmFetchOperation iConn.Open() OK")
+
+ // Open the HTTP session.
+ iHttpSess.OpenL( KHttpProtString );
+ PUSHLOG_WRITE("CPushMtmFetchOperation iHttpSess.OpenL OK")
+
+ // Set our Socket Server handle and Connection as session properties.
+ iHttpSess.ConnectionInfo().SetPropertyL
+ (
+ StringF( HTTP::EHttpSocketServ ),
+ THTTPHdrVal( iSockServ.Handle() )
+ );
+ PUSHLOG_WRITE("CPushMtmFetchOperation EHttpSocketServ set")
+ iHttpSess.ConnectionInfo().SetPropertyL
+ (
+ StringF( HTTP::EHttpSocketConnection ),
+ THTTPHdrVal( REINTERPRET_CAST( TInt, &iConn ) )
+ );
+ PUSHLOG_WRITE("CPushMtmFetchOperation EHttpSocketConnection set")
+
+ // Open different string tables to the session. These are required
+ // by the Accept Header Filter.
+ iHttpSess.StringPool().OpenL( HttpFilterCommonStringsExt::GetTable() );
+ PUSHLOG_WRITE("CPushMtmFetchOperation table 1 opened");
+ iHttpSess.StringPool().OpenL( HttpFilterCommonStringsExt::GetLanguageTable() );
+ PUSHLOG_WRITE("CPushMtmFetchOperation table 2 opened");
+
+ // Install the very same set of filters that BrowserEngine installs.
+ // The following filters must not be installed:
+ // - Authentication Filter, because the fetch operation and the push mtm
+ // subsystem does not support credentials.
+ // - Conn Handler Filter, because the fetch operation let it to the HTTP
+ // core framework to create connection - it just sets the acces point.
+
+ // Install UAProf filter.
+ CHttpUAProfFilterInterface::InstallFilterL( iHttpSess );
+ PUSHLOG_WRITE(" UAProf installed")
+
+ // Install cookie filter.
+ CHttpCookieFilter::InstallFilterL( iHttpSess );
+ PUSHLOG_WRITE(" Cookie filter installed")
+
+ // Create cache manager
+ FeatureManager::InitializeLibL();
+ iCacheMgr = CHttpCacheManager::NewL();
+ PUSHLOG_WRITE(" Cache Manager installed")
+
+ // Install Accept Header Filter.
+ CHttpFilterAcceptHeaderInterface::InstallFilterL( iHttpSess );
+ PUSHLOG_WRITE(" Accept Header Filter installed")
+
+ // Install IOP Filter.
+ CHttpFilterIopInterface::InstallFilterL( iHttpSess, iopOptionHostHeader );
+ PUSHLOG_WRITE(" IOP Filter installed")
+
+ // Install Deflate Filter.
+ CHttpDeflateFilter::InstallFilterL( iHttpSess );
+ PUSHLOG_WRITE(" Deflate Filter installed");
+
+ TUint32 defIapId( 0 );
+ TBool defIapIdFound = EFalse;
+ TCommDbConnPref commPrefs;
+#ifndef __WINS__
+ // Use Browser default AP & comms db:
+ defIapIdFound = GetDefaultInetAccessPointL( defIapId );
+ PUSHLOG_WRITE_FORMAT(" defIapIdFound: <%d>",(TInt)defIapIdFound)
+ PUSHLOG_WRITE_FORMAT(" defIapId: <%d>",defIapId)
+ commPrefs.SetDialogPreference( ECommDbDialogPrefDoNotPrompt );
+ if ( defIapIdFound )
+ {
+ commPrefs.SetIapId( defIapId );
+ }
+#else // __WINS__
+ // Prompt the user to select access point
+ commPrefs.SetDialogPreference( ECommDbDialogPrefPrompt );
+#endif // __WINS__
+
+ iState = EStartRequest;
+
+ iStatus = KRequestPending;
+ SetActive();
+ iConn.Start( commPrefs, iStatus );
+
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::InitializeL")
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::StartRequestL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::StartRequestL()
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::StartRequestL")
+
+ // Create the transaction.
+ CreateTransactionL();
+
+ CheckCacheL();
+
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::StartRequestL")
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::CheckCacheL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::CheckCacheL()
+
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::CheckCacheL")
+ iCacheSupply = CPushMtmCacheSupply::NewL(iCacheMgr, this);
+ TInt ret = iCacheSupply->StartRequestL();
+ iStatus = KRequestPending;
+ SetActive();
+ if (ret != KErrNone) // Not in cache
+ {
+ iState = ERequest;
+ iCachedResponse = ETrue;
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone);
+ }
+ else
+ {
+ iState = EDone;
+ iCachedResponse = EFalse;
+ }
+
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::CheckCacheL")
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::RequestL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::RequestL()
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::RequestL")
+
+ iState = EDone;
+
+ iStatus = KRequestPending;
+ SetActive();
+ SubmitTransactionL();
+ // Do not call InvokeRun(). Let MHFRunL to handle the request.
+
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::RequestL")
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::Done
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::Done()
+ {
+ PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::Done iResult: <%d>",iResult);
+
+ delete iRequestedUrl;
+ iRequestedUrl = NULL;
+
+ // Notify parent.
+ TRequestStatus* status = &iObserver;
+ User::RequestComplete( status, iResult );
+// iState = EInit;
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::CreateTransactionL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::CreateTransactionL()
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::CreateTransactionL")
+
+ __ASSERT_DEBUG( iRequestedUrl,
+ ContHandPanic( EPushContHandPanNotInitUrl ) );
+
+ // Create the transaction.
+ TUriParser8 uri;
+ User::LeaveIfError( uri.Parse( *iRequestedUrl ) );
+ iHttpTrans =
+ iHttpSess.OpenTransactionL( uri, *this, StringF( HTTP::EGET ) );
+ PUSHLOG_WRITE("CPushMtmFetchOperation OpenTransactionL OK")
+
+ // Set request headers.
+ RHTTPHeaders hdr = iHttpTrans.Request().GetHeaderCollection();
+ SetHeaderL( hdr, HTTP::EUserAgent, KUserAgent );
+ SetHeaderL( hdr, HTTP::EAccept, HTTP::EAnyAny );
+
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::CreateTransactionL")
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::SubmitTransactionL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::SubmitTransactionL()
+ {
+ iHttpTrans.SubmitL();
+ PUSHLOG_WRITE("CPushMtmFetchOperation iHttpTrans.SubmitL OK")
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::HandleResponseHeadersL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::HandleResponseHeadersL( RHTTPResponse aResponse )
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::HandleResponseHeadersL")
+
+ TInt httpCode = aResponse.StatusCode();
+ PUSHLOG_WRITE_FORMAT(" HttpStatus: %d",httpCode)
+
+#ifdef __TEST_LOG__
+ LogHeadersL( aResponse.GetHeaderCollection() );
+#endif // __TEST_LOG__
+
+ if ( HTTPStatus::IsSuccessful( httpCode ) &&
+ ( httpCode != HTTPStatus::ENoContent ) )
+ {
+ // Successful GET.
+ PUSHLOG_WRITE(" Successful GET")
+ // Get content type.
+ iDataType = TDataType
+ ( GetContentTypeL( aResponse.GetHeaderCollection() ) );
+ // Get source URI.
+ HBufC8* buf = GetSourceUriL( iHttpTrans ).AllocL();
+ PUSHLOG_WRITE(" Source URI got")
+ delete iSourceUri;
+ iSourceUri = buf;
+ // No error:
+ iResult = KErrNone;
+ }
+ else
+ {
+ // See Extended Error Handling UI Specification!
+ iResult = KPushMtmHttpErrorBase - httpCode;
+ PUSHLOG_WRITE_FORMAT(" iResult: <%d>",iResult)
+ }
+
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::HandleResponseHeadersL")
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::VersionRetryL
+// ---------------------------------------------------------
+//
+TBool CPushMtmFetchOperation::VersionRetryL()
+ {
+ TBool retryDone( EFalse );
+
+ // Check what http version we are using.
+ THTTPHdrVal val;
+ TBool exists = iHttpSess.ConnectionInfo().Property
+ (
+ StringF( HTTP::EHTTPVersion ),
+ val
+ );
+ if ( exists && TInt( val ) == HTTP::EHttp11 )
+ {
+ // Currently using HTTP/1.1. Cancel transaction and resubmit it using
+ // HTTP/1.0.
+ iHttpTrans.Cancel();
+ iHttpSess.ConnectionInfo().SetPropertyL
+ (
+ StringF( HTTP::EHTTPVersion ),
+ THTTPHdrVal( StringF( HTTP::EHttp10 ) )
+ );
+ SubmitTransactionL();
+ retryDone = ETrue;
+ }
+
+ return retryDone;
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::AppendResponse
+// ---------------------------------------------------------
+//
+TInt CPushMtmFetchOperation::AppendResponse( const TDesC8& aDataChunk )
+ {
+ TInt err( KErrNone );
+ HBufC8* newBodyBuf = NULL;
+
+ if ( !iBody )
+ {
+ // iBody does not exist yet; allocate buffer for the first data chunk.
+ newBodyBuf = HBufC8::New( aDataChunk.Length() );
+ }
+ else
+ {
+ const TInt needed( iBody->Des().Length() + aDataChunk.Length() );
+ if ( iBody->Des().MaxLength() < needed )
+ {
+ // iBody exists, but small.
+ newBodyBuf = iBody->ReAlloc( needed );
+ iBody = NULL; // ReAlloc deleted it!
+ }
+ else
+ {
+ // iBody exists and the new chunk fits into it.
+ }
+ }
+
+ if ( newBodyBuf )
+ {
+ __ASSERT_DEBUG( iBody == NULL,
+ ContHandPanic( EPushContHandPanAlreadyInitialized ) );
+ delete iBody; // Not necessary, JIC.
+ iBody = newBodyBuf;
+ }
+ else
+ {
+ if (aDataChunk.Length() > 0)
+ {
+ err = KErrNoMemory;
+ }
+ }
+
+ if ( !err )
+ {
+ iBody->Des().Append( aDataChunk );
+ }
+
+ return err;
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::SetHeaderL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::SetHeaderL( RHTTPHeaders aHeaders,
+ HTTP::TStrings aHdrField,
+ const TDesC8& aHdrValue )
+ {
+ RStringF valStr = iHttpSess.StringPool().OpenFStringL( aHdrValue );
+ CleanupClosePushL<RStringF>( valStr );
+ SetHeaderL( aHeaders, aHdrField, valStr );
+ CleanupStack::PopAndDestroy(); // close valStr
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::SetHeaderL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::SetHeaderL( RHTTPHeaders aHeaders,
+ HTTP::TStrings aHdrField,
+ HTTP::TStrings aHdrValue )
+ {
+ SetHeaderL( aHeaders, aHdrField, StringF( aHdrValue ) );
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::SetHeaderL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::SetHeaderL( RHTTPHeaders aHeaders,
+ HTTP::TStrings aHdrField,
+ const RStringF aHdrValue )
+ {
+ THTTPHdrVal val( aHdrValue );
+ aHeaders.SetFieldL( StringF( aHdrField ), val );
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::GetContentTypeL
+// ---------------------------------------------------------
+//
+const TDesC8& CPushMtmFetchOperation::GetContentTypeL( RHTTPHeaders aHeaders )
+ {
+ THTTPHdrVal hdrVal;
+ User::LeaveIfError
+ ( aHeaders.GetField( StringF( HTTP::EContentType ), 0, hdrVal ) );
+ if ( hdrVal.Type() != THTTPHdrVal::KStrFVal )
+ {
+ User::Leave( KErrArgument );
+ }
+ return hdrVal.StrF().DesC();
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::GetSourceUriL
+// ---------------------------------------------------------
+//
+const TDesC8& CPushMtmFetchOperation::GetSourceUriL
+ ( RHTTPTransaction aTransaction )
+ {
+ // TODO if redirected URI exists, how do we get it?
+ // For the moment request URI is used.
+ return aTransaction.Request().URI().UriDes();
+ }
+
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::LogHeadersL
+// ---------------------------------------------------------
+//
+#ifndef __TEST_LOG__
+
+void CPushMtmFetchOperation::LogHeadersL( RHTTPHeaders /*aHeaders*/ )
+ {
+ }
+
+#else // #ifdef __TEST_LOG__
+
+void CPushMtmFetchOperation::LogHeadersL( RHTTPHeaders aHeaders )
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::LogHeadersL")
+
+ _LIT( KDateFormat, "%D%M%Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S.%C%:3" );
+
+ PUSHLOG_WRITE("Headers:");
+
+ RStringPool strP = iHttpTrans.Session().StringPool();
+ THTTPHdrFieldIter it = aHeaders.Fields();
+
+ while ( !it.AtEnd() )
+ {
+ RStringTokenF fieldName = it();
+ RStringF fieldNameStr = strP.StringF( fieldName );
+ THTTPHdrVal fieldVal;
+ if ( aHeaders.GetField( fieldNameStr, 0, fieldVal ) == KErrNone )
+ {
+ const TInt KMaxLogStrLen = 64;
+ TPtrC8 fieldName8 = fieldNameStr.DesC();
+ TInt fieldNameLen = fieldName8.Length();
+ fieldNameLen = ( KMaxLogStrLen < fieldNameLen ) ?
+ KMaxLogStrLen : fieldNameLen;
+ fieldName8.Set( fieldName8.Mid( 0, fieldNameLen ) );
+ HBufC* fieldNameHBufC = HBufC::NewMaxLC( fieldName8.Length() );
+ TPtr fieldName = fieldNameHBufC->Des();
+ fieldName.Copy( fieldName8 );
+
+ switch ( fieldVal.Type() )
+ {
+ case THTTPHdrVal::KTIntVal:
+ {
+ PUSHLOG_WRITE_FORMAT2
+ (" <%S> (%d)",&fieldName,fieldVal.Int())
+ break;
+ }
+
+ case THTTPHdrVal::KStrFVal:
+ {
+ RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
+ TPtrC8 fieldVal8 = fieldValStr.DesC();
+ // Truncate if too long.
+ TInt fieldValLen = fieldVal8.Length();
+ fieldNameLen = ( KMaxLogStrLen < fieldValLen ) ?
+ KMaxLogStrLen : fieldValLen;
+ fieldVal8.Set( fieldVal8.Mid( 0, fieldValLen ) );
+ // Truncate end.
+ HBufC* fieldValHBufC = HBufC::NewMaxLC( fieldVal8.Length() );
+ TPtr fieldVal = fieldValHBufC->Des();
+ fieldVal.Copy( fieldVal8 );
+ PUSHLOG_WRITE_FORMAT2
+ (" <%S> (%S)",&fieldName,&fieldVal)
+ CleanupStack::PopAndDestroy( fieldValHBufC );
+ // fieldValHBufC
+ break;
+ }
+
+ case THTTPHdrVal::KStrVal:
+ {
+ RString fieldValStr = strP.String( fieldVal.Str() );
+ TPtrC8 fieldVal8 = fieldValStr.DesC();
+ // Truncate if too long.
+ TInt fieldValLen = fieldVal8.Length();
+ fieldNameLen = ( KMaxLogStrLen < fieldValLen ) ?
+ KMaxLogStrLen : fieldValLen;
+ fieldVal8.Set( fieldVal8.Mid( 0, fieldValLen ) );
+ // Truncate end.
+ HBufC* fieldValHBufC = HBufC::NewMaxLC( fieldVal8.Length() );
+ TPtr fieldVal = fieldValHBufC->Des();
+ fieldVal.Copy( fieldVal8 );
+ PUSHLOG_WRITE_FORMAT2
+ (" <%S> (%S)",&fieldName,&fieldVal)
+ CleanupStack::PopAndDestroy( fieldValHBufC );
+ // fieldValHBufC
+ break;
+ }
+
+ case THTTPHdrVal::KDateVal:
+ {
+ TDateTime date = fieldVal.DateTime();
+ TBuf<40> dateTimeString;
+ TTime t( date );
+ TRAP_IGNORE( t.FormatL( dateTimeString, KDateFormat ) );
+ PUSHLOG_WRITE_FORMAT2
+ (" <%S> (%S)",&fieldName,&dateTimeString)
+ break;
+ }
+
+ default:
+ {
+ PUSHLOG_WRITE_FORMAT2
+ (" <%S> unrecognised value type (%d)",
+ &fieldName,fieldVal.Type())
+ break;
+ }
+ }
+
+ // Display realm for WWW-Authenticate header.
+ RStringF wwwAuth = strP.StringF
+ ( HTTP::EWWWAuthenticate, RHTTPSession::GetTable() );
+ if ( fieldNameStr == wwwAuth )
+ {
+ PUSHLOG_WRITE(" fieldNameStr == wwwAuth")
+ // check the auth scheme is 'basic'
+ RStringF basic = strP.StringF
+ ( HTTP::EBasic, RHTTPSession::GetTable() );
+ RStringF realm = strP.StringF
+ ( HTTP::ERealm, RHTTPSession::GetTable() );
+ THTTPHdrVal realmVal;
+ if ( ( fieldVal.StrF() == basic ) &&
+ ( !aHeaders.GetParam( wwwAuth, realm, realmVal ) ) )
+ {
+ RStringF realmValStr = strP.StringF( realmVal.StrF() );
+ PUSHLOG_WRITE_FORMAT(" Realm <%S>",&realmValStr);
+ }
+ }
+
+ CleanupStack::PopAndDestroy( fieldNameHBufC ); // fieldNameHBufC
+ }
+ ++it;
+ }
+
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::LogHeadersL")
+ }
+
+#endif // __TEST_LOG__
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::DoCancel
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::DoCancel()
+ {
+ switch ( iState )
+ {
+ /*case EStartConnect:
+ {
+ // Complete ourselves - nothing is outstanding.
+ TRequestStatus* ownStatus = &iStatus;
+ User::RequestComplete( ownStatus, KErrCancel );
+ break;
+ }*/
+
+ /*case EConnect:
+ {
+ //__ASSERT_DEBUG( iConn, ContHandPanic( ECodInternal ) );
+ //iConn->Cancel(); // This will complete our status.
+ break;
+ }*/
+
+ case EStartRequest:
+ case ECheckCache:
+ case ERequest:
+ {
+ delete iCacheSupply;
+ iCacheSupply = NULL;
+
+ iHttpTrans.Close();
+ // Now the transaction has been closed. Closing it does not
+ // complete our status, so we do it manually.
+ TRequestStatus* status = &iStatus;
+ SetActive();
+ User::RequestComplete( status, iResult );
+ break;
+ }
+
+ case EInit:
+ default:
+ {
+ // No requests should be outstanding in these states.
+ //ContHandPanic( ECodInternal );
+ break;
+ }
+ }
+
+ iResult = KErrCancel;
+ Done();
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::RunL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::RunL()
+ {
+ PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::RunL status = %d", iState);
+ // Handle errors in RunError().
+ User::LeaveIfError( iStatus.Int() );
+
+ switch ( iState )
+ {
+ case EInit:
+ {
+ InitializeL();
+ break;
+ }
+
+ case EStartRequest:
+ {
+ StartRequestL();
+ break;
+ }
+
+ case ERequest:
+ {
+ RequestL();
+ break;
+ }
+
+ case EDone:
+ {
+ Done();
+ break;
+ }
+
+ default:
+ {
+ // JIC.
+ Done();
+ break;
+ }
+ }
+ PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::RunL moving to status = %d", iState);
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::RunError
+// ---------------------------------------------------------
+//
+TInt CPushMtmFetchOperation::RunError( TInt aError )
+ {
+ PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::RunError <%d>",aError)
+
+ iResult = aError;
+ delete iCacheSupply;
+ iCacheSupply = NULL;
+ iHttpTrans.Close();
+ Done();
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::MHFRunL
+// ---------------------------------------------------------
+//
+void CPushMtmFetchOperation::MHFRunL
+ (
+ RHTTPTransaction DEBUG_ONLY( aTransaction ),
+ const THTTPEvent& aEvent
+ )
+ {
+ PUSHLOG_ENTERFN("CPushMtmFetchOperation::MHFRunL")
+ __ASSERT_DEBUG( aTransaction == iHttpTrans,
+ ContHandPanic( EPushContHandPanBadTransaction ) );
+ switch ( aEvent.iStatus )
+ {
+ case THTTPEvent::EGotResponseHeaders:
+ {
+ PUSHLOG_WRITE(" EGotResponseHeaders")
+ // pass headers to the cache first
+ TRAP_IGNORE( iCacheSupply->HeadersReceivedL() );
+ // Now we know that the request was processed by the server.
+ HandleResponseHeadersL( iHttpTrans.Response() );
+ break;
+ }
+
+ case THTTPEvent::EGotResponseBodyData:
+ {
+ PUSHLOG_WRITE(" EGotResponseBodyData")
+ // pass chunk to the cache first
+ TRAP_IGNORE( iCacheSupply->BodyReceivedL() );
+ // Get body data and save it.
+ TInt err( KErrNone );
+ MHTTPDataSupplier* body = iHttpTrans.Response().Body();
+ if ( !body )
+ {
+ PUSHLOG_WRITE(" NULL body")
+ }
+ else
+ {
+ TPtrC8 bodyPtr;
+ // Caution: no leaving between body->GetNextDataPart and
+ // body->ReleaseData calls! Data must always be released.
+#ifdef __TEST_LOG__
+ TBool isLast = body->GetNextDataPart( bodyPtr ); // No leave...
+ PUSHLOG_WRITE_FORMAT(" last? (%d)",(isLast?1:0))
+#else // ifndef __TEST_LOG__
+ (void)body->GetNextDataPart( bodyPtr ); // No leave...
+#endif // __TEST_LOG__
+ //if ( iHttpTrans.Request().Method() == StringF( HTTP::EGET ) )
+ err = AppendResponse( bodyPtr );
+ body->ReleaseData(); // ...until here.
+ PUSHLOG_WRITE_FORMAT(" err: (%d)",err)
+ User::LeaveIfError( err );
+ }
+ break;
+ }
+
+ case THTTPEvent::EResponseComplete:
+ {
+ // do not mix it up with the ESucceeded
+ // The transaction's response is complete. An incoming event.
+ TRAP_IGNORE( iCacheSupply->ResponseCompleteL() );
+ break;
+ }
+
+ case THTTPEvent::ERequestComplete:
+ {
+ // request is all set
+ iCacheSupply->CloseRequest();
+ break;
+ }
+
+ case THTTPEvent::EFailed:
+ {
+ PUSHLOG_WRITE(" EFailed")
+ // Safety code: we should already have an error code.
+ if ( iResult == KErrNone )
+ {
+ iResult = KErrGeneral;
+ }
+ // TODO. Fall through.
+ }
+
+ case THTTPEvent::ESucceeded:
+ {
+ PUSHLOG_WRITE(" ESucceeded")
+ delete iCacheSupply;
+ iCacheSupply = NULL;
+ iHttpTrans.Close();
+ // Transaction is finished, invoke RunL now.
+ TRequestStatus* status = &iStatus;
+ if (!IsActive())
+ {
+ SetActive();
+ }
+ User::RequestComplete( status, iResult );
+ break;
+ }
+
+ case THTTPEvent::ERedirectedPermanently:
+ {
+ PUSHLOG_WRITE(" ERedirectedPermanently")
+ // Do nothing just continue.
+ break;
+ }
+
+ default:
+ {
+ PUSHLOG_WRITE(" default case")
+ // Handle errors in MHFRunError.
+ User::LeaveIfError( aEvent.iStatus );
+ break;
+ }
+ }
+
+ PUSHLOG_LEAVEFN("CPushMtmFetchOperation::MHFRunL")
+ }
+
+// ---------------------------------------------------------
+// CPushMtmFetchOperation::MHFRunError
+// ---------------------------------------------------------
+//
+TInt CPushMtmFetchOperation::MHFRunError
+ (
+ TInt aError,
+ RHTTPTransaction DEBUG_ONLY( aTransaction ),
+ const THTTPEvent& /*aEvent*/
+ )
+ {
+ __ASSERT_DEBUG( aTransaction == iHttpTrans,
+ ContHandPanic( EPushContHandPanBadTransaction ) );
+ iResult = aError;
+ iCacheSupply->CloseRequest();
+ iHttpTrans.Close();
+
+ // Transaction is finished, invoke RunL now.
+ // iResult contains the (error) code.
+ if ( !IsActive() )
+ {
+ SetActive();
+ }
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone );
+
+ return KErrNone;
+ }
+
+// End of file.