pushmtm/Plugins/PushContentHandler/PushMtmFetchOperation.cpp
branchRCL_3
changeset 69 4455192101e4
parent 65 8e6fa1719340
equal deleted inserted replaced
65:8e6fa1719340 69:4455192101e4
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of CPushMtmFetchOperation.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 
       
    22 #include "PushMtmFetchOperation.h"
       
    23 #include "PushContentHandlerPanic.h"
       
    24 #include "PushMtmLog.h"
       
    25 #include <push/cslpushmsgentry.h>
       
    26 #include <Uri8.h>
       
    27 #include <SysUtil.h>
       
    28 #include <cookiefilterinterface.h>
       
    29 #include <uaproffilter_interface.h>
       
    30 #include <CommDbConnPref.h>
       
    31 #include <cdbcols.h>
       
    32 #include <browseruisdkcrkeys.h>
       
    33 #include "PushMtmPrivateCRKeys.h"
       
    34 #include <centralrepository.h> 
       
    35 #include <commdb.h>
       
    36 #include <ApDataHandler.h>
       
    37 #include <ApAccessPointItem.h>
       
    38 #include <ApUtils.h>
       
    39 #include <ApSelect.h>
       
    40 #include <httpfilteracceptheaderinterface.h>
       
    41 #include <httpfilteriopinterface.h>
       
    42 #include <httpfiltercommonstringsext.h>
       
    43 #include <deflatefilterinterface.h>
       
    44 #include <FeatMgr.h>
       
    45 
       
    46 // ================= MACROS =======================
       
    47 
       
    48 #ifdef _DEBUG
       
    49     /// Guard "debug-only" argument name with this (expands to argument).
       
    50     #define DEBUG_ONLY( argName ) argName
       
    51 #else /* not defined _DEBUG */
       
    52     /// Guard "debug-only" argument name with this (expands to nothing).
       
    53     #define DEBUG_ONLY( argName )
       
    54 #endif /* def _DEBUG */
       
    55 
       
    56 // ================= LOCAL CONSTANTS =======================
       
    57 
       
    58 _LIT8( KHttpProtString, "HTTP/TCP" );
       
    59 _LIT8( KUserAgent, "Push MTM" );
       
    60 
       
    61 /// Base HTTP error code. See Extended Error Handling UI Specification!
       
    62 LOCAL_C const TInt KPushMtmHttpErrorBase = -25000;
       
    63 
       
    64 // ================= MEMBER FUNCTIONS =======================
       
    65 
       
    66 // ---------------------------------------------------------
       
    67 // CPushMtmFetchOperation::NewL
       
    68 // ---------------------------------------------------------
       
    69 //
       
    70 CPushMtmFetchOperation* CPushMtmFetchOperation::NewL
       
    71                                     (
       
    72                                         const TDesC& aRequestedUrl, 
       
    73                                         TRequestStatus& aObserverRequestStatus 
       
    74                                     )
       
    75     {
       
    76     PUSHLOG_ENTERFN("CPushMtmFetchOperation::NewL")
       
    77 
       
    78     CPushMtmFetchOperation* op = 
       
    79         new (ELeave) CPushMtmFetchOperation( aObserverRequestStatus );
       
    80     CleanupStack::PushL( op );
       
    81     op->ConstructL( aRequestedUrl );
       
    82     CleanupStack::Pop( op ); // op
       
    83 
       
    84     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::NewL")
       
    85     return op;
       
    86     }
       
    87 
       
    88 // ---------------------------------------------------------
       
    89 // CPushMtmFetchOperation::~CPushMtmFetchOperation
       
    90 // ---------------------------------------------------------
       
    91 //
       
    92 CPushMtmFetchOperation::~CPushMtmFetchOperation()
       
    93     {
       
    94     Cancel();
       
    95     delete ( iCacheMgr );
       
    96     delete iCacheSupply;
       
    97     iHttpTrans.Close();
       
    98     iHttpSess.Close();
       
    99     iConn.Close();
       
   100     iSockServ.Close();
       
   101     delete iRequestedUrl;
       
   102     delete iSourceUri;
       
   103     delete iBody;
       
   104     FeatureManager::UnInitializeLib();
       
   105     }
       
   106 
       
   107 // ---------------------------------------------------------
       
   108 // CPushMtmFetchOperation::StartL
       
   109 // ---------------------------------------------------------
       
   110 //
       
   111 void CPushMtmFetchOperation::StartL()
       
   112     {
       
   113     PUSHLOG_ENTERFN("CPushMtmFetchOperation::StartL")
       
   114 
       
   115     Cancel();
       
   116 
       
   117     iResult = KErrNone;
       
   118     iState = EInit;
       
   119 
       
   120 	SetActive();
       
   121     TRequestStatus* status = &iStatus;
       
   122     User::RequestComplete( status, KErrNone );
       
   123 
       
   124     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::StartL")
       
   125     }
       
   126 
       
   127 // ---------------------------------------------------------
       
   128 // CPushMtmFetchOperation::CPushMtmFetchOperation
       
   129 // ---------------------------------------------------------
       
   130 //
       
   131 CPushMtmFetchOperation::CPushMtmFetchOperation
       
   132                         ( TRequestStatus& aObserverRequestStatus ) 
       
   133 :   CActive( EPriorityStandard ), 
       
   134     iObserver( aObserverRequestStatus ),
       
   135     iState( EInit ),
       
   136     iResult( KErrNone )
       
   137     {
       
   138     CActiveScheduler::Add( this );
       
   139     }
       
   140 
       
   141 // ---------------------------------------------------------
       
   142 // CPushMtmFetchOperation::ConstructL
       
   143 // ---------------------------------------------------------
       
   144 //
       
   145 void CPushMtmFetchOperation::ConstructL( const TDesC& aRequestedUrl )
       
   146     {
       
   147     PUSHLOG_ENTERFN("CPushMtmFetchOperation::ConstructL")
       
   148 
       
   149     iRequestedUrl = HBufC8::NewMaxL( aRequestedUrl.Length() );
       
   150     iRequestedUrl->Des().Copy( aRequestedUrl );
       
   151 
       
   152     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::ConstructL")
       
   153     }
       
   154 
       
   155 // ---------------------------------------------------------
       
   156 // CPushMtmFetchOperation::GetDefaultInetAccessPointL
       
   157 // ---------------------------------------------------------
       
   158 //
       
   159 TBool CPushMtmFetchOperation::GetDefaultInetAccessPointL
       
   160                               ( TUint32& aIapId ) const
       
   161     {
       
   162     PUSHLOG_ENTERFN("CPushMtmFetchOperation::GetDefaultInetAccessPointL")
       
   163 
       
   164     // Try to find the default AP.
       
   165     // The Browser may stores the default AP in the shared data.
       
   166     CRepository* repository = CRepository::NewL( KCRUidBrowser );
       
   167     CleanupStack::PushL( repository );
       
   168 
       
   169     TInt wapApId;
       
   170     User::LeaveIfError
       
   171         ( repository->Get( KBrowserDefaultAccessPoint, wapApId ) );
       
   172     TUint32 wapApId32( wapApId );
       
   173     TUint32 iapId32( 0 );
       
   174 
       
   175     CleanupStack::PopAndDestroy( repository );
       
   176     repository = 0;
       
   177 
       
   178     CCommsDatabase* commsDb = CCommsDatabase::NewL( EDatabaseTypeIAP );
       
   179     CleanupStack::PushL( commsDb );
       
   180     CApDataHandler* apDataHandler = CApDataHandler::NewLC( *commsDb );
       
   181     CApAccessPointItem* apItem = CApAccessPointItem::NewLC();
       
   182     TRAPD( err, apDataHandler->AccessPointDataL( wapApId32, *apItem ) );
       
   183     CApUtils* apUtils = CApUtils::NewLC( *commsDb );
       
   184 
       
   185     TBool wapApFound( EFalse );
       
   186     TBool iapFound( EFalse );
       
   187 
       
   188     PUSHLOG_WRITE_FORMAT("  err: <%d>",err)
       
   189     if ( err == KErrNone )
       
   190         {
       
   191         wapApFound = ETrue;
       
   192         }
       
   193     else // err != KErrNone
       
   194         {
       
   195         // The first valid access point has to be selected if exists
       
   196         CApSelect* apSelect = CApSelect::NewLC
       
   197                                             (
       
   198                                                 *commsDb, 
       
   199                                                 KEApIspTypeAll, 
       
   200                                                 EApBearerTypeAll, 
       
   201                                                 KEApSortNameAscending
       
   202                                             );
       
   203         if ( apSelect->MoveToFirst() )
       
   204             {
       
   205             wapApFound = ETrue;
       
   206             wapApId32 = apSelect->Uid();
       
   207             }
       
   208         CleanupStack::PopAndDestroy( apSelect ); // apSelect
       
   209         }
       
   210 
       
   211     if ( wapApFound )
       
   212         {
       
   213         // Get the IAP ID from the WAP AP ID.
       
   214 #ifndef __SERIES60_WSP
       
   215         iapId32 = 0;
       
   216         TRAPD( errTransl, iapId32 = apUtils->IapIdFromWapIdL( wapApId32 ) );
       
   217         PUSHLOG_WRITE_FORMAT("  IapIdFromWapIdL errTransl: <%d>",errTransl)
       
   218         if ( errTransl == KErrNone )
       
   219             {
       
   220             iapFound = ETrue;
       
   221             }
       
   222 #else
       
   223         iapId32 = wapApId32;
       
   224         iapFound = ETrue;
       
   225 #endif // __SERIES60_WSP
       
   226         }
       
   227 
       
   228     CleanupStack::PopAndDestroy( 4 ); // apUtils, apItem, 
       
   229                                             // apDataHandler, commsDb
       
   230 
       
   231     if ( iapFound )
       
   232         {
       
   233         aIapId = iapId32;
       
   234         }
       
   235     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::GetDefaultInetAccessPointL")
       
   236     return iapFound;
       
   237     }
       
   238 
       
   239 // ---------------------------------------------------------
       
   240 // CPushMtmFetchOperation::InitializeL
       
   241 // ---------------------------------------------------------
       
   242 //
       
   243 void CPushMtmFetchOperation::InitializeL()
       
   244     {
       
   245     PUSHLOG_ENTERFN("CPushMtmFetchOperation::InitializeL")
       
   246 
       
   247     User::LeaveIfError( iSockServ.Connect() );
       
   248     PUSHLOG_WRITE("CPushMtmFetchOperation iSockServ.Connect() OK")
       
   249     User::LeaveIfError( iConn.Open( iSockServ ) );
       
   250     PUSHLOG_WRITE("CPushMtmFetchOperation iConn.Open() OK")
       
   251 
       
   252     // Open the HTTP session.
       
   253     iHttpSess.OpenL( KHttpProtString );
       
   254     PUSHLOG_WRITE("CPushMtmFetchOperation iHttpSess.OpenL OK")
       
   255 
       
   256     // Set our Socket Server handle and Connection as session properties.
       
   257     iHttpSess.ConnectionInfo().SetPropertyL
       
   258         (
       
   259             StringF( HTTP::EHttpSocketServ ),
       
   260             THTTPHdrVal( iSockServ.Handle() )
       
   261         );
       
   262     PUSHLOG_WRITE("CPushMtmFetchOperation EHttpSocketServ set")
       
   263     iHttpSess.ConnectionInfo().SetPropertyL
       
   264         (
       
   265             StringF( HTTP::EHttpSocketConnection ),
       
   266             THTTPHdrVal( REINTERPRET_CAST( TInt, &iConn ) )
       
   267         );
       
   268     PUSHLOG_WRITE("CPushMtmFetchOperation EHttpSocketConnection set")
       
   269 
       
   270     // Open different string tables to the session. These are required 
       
   271     // by the Accept Header Filter.
       
   272     iHttpSess.StringPool().OpenL( HttpFilterCommonStringsExt::GetTable() );
       
   273     PUSHLOG_WRITE("CPushMtmFetchOperation table 1 opened");
       
   274     iHttpSess.StringPool().OpenL( HttpFilterCommonStringsExt::GetLanguageTable() );
       
   275     PUSHLOG_WRITE("CPushMtmFetchOperation table 2 opened");
       
   276 
       
   277     // Install the very same set of filters that BrowserEngine installs.
       
   278     // The following filters must not be installed:
       
   279     // - Authentication Filter, because the fetch operation and the push mtm 
       
   280     //   subsystem does not support credentials.
       
   281     // - Conn Handler Filter, because the fetch operation let it to the HTTP 
       
   282     //   core framework to create connection - it just sets the acces point.
       
   283 
       
   284     // Install UAProf filter.
       
   285     CHttpUAProfFilterInterface::InstallFilterL( iHttpSess );
       
   286     PUSHLOG_WRITE(" UAProf installed")
       
   287 
       
   288     // Install cookie filter.
       
   289     CHttpCookieFilter::InstallFilterL( iHttpSess );
       
   290     PUSHLOG_WRITE(" Cookie filter installed")
       
   291 
       
   292     // Create cache manager
       
   293     FeatureManager::InitializeLibL();
       
   294     iCacheMgr = CHttpCacheManager::NewL();
       
   295     PUSHLOG_WRITE(" Cache Manager installed")
       
   296 
       
   297     // Install Accept Header Filter.
       
   298     CHttpFilterAcceptHeaderInterface::InstallFilterL( iHttpSess );
       
   299     PUSHLOG_WRITE(" Accept Header Filter installed")
       
   300 
       
   301     // Install IOP Filter.
       
   302     CHttpFilterIopInterface::InstallFilterL( iHttpSess, iopOptionHostHeader );
       
   303     PUSHLOG_WRITE(" IOP Filter installed")
       
   304 
       
   305     // Install Deflate Filter.
       
   306     CHttpDeflateFilter::InstallFilterL( iHttpSess );
       
   307     PUSHLOG_WRITE(" Deflate Filter installed");
       
   308 
       
   309     TUint32 defIapId( 0 );
       
   310     TBool defIapIdFound = EFalse;
       
   311     TCommDbConnPref commPrefs;
       
   312 #ifndef __WINS__
       
   313     // Use Browser default AP & comms db:
       
   314     defIapIdFound = GetDefaultInetAccessPointL( defIapId );
       
   315     PUSHLOG_WRITE_FORMAT("  defIapIdFound: <%d>",(TInt)defIapIdFound)
       
   316     PUSHLOG_WRITE_FORMAT("  defIapId:      <%d>",defIapId)
       
   317     commPrefs.SetDialogPreference( ECommDbDialogPrefDoNotPrompt );
       
   318     if ( defIapIdFound )
       
   319         {
       
   320         commPrefs.SetIapId( defIapId );
       
   321         }
       
   322 #else // __WINS__
       
   323     // Prompt the user to select access point
       
   324     commPrefs.SetDialogPreference( ECommDbDialogPrefPrompt );
       
   325 #endif // __WINS__
       
   326 
       
   327     iState = EStartRequest;
       
   328 
       
   329     iStatus = KRequestPending;
       
   330     SetActive();
       
   331     iConn.Start( commPrefs, iStatus );
       
   332 
       
   333     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::InitializeL")
       
   334     }
       
   335 
       
   336 // ---------------------------------------------------------
       
   337 // CPushMtmFetchOperation::StartRequestL
       
   338 // ---------------------------------------------------------
       
   339 //
       
   340 void CPushMtmFetchOperation::StartRequestL()
       
   341     {
       
   342     PUSHLOG_ENTERFN("CPushMtmFetchOperation::StartRequestL")
       
   343 
       
   344     // Create the transaction.
       
   345     CreateTransactionL();
       
   346 
       
   347     CheckCacheL();
       
   348 
       
   349     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::StartRequestL")
       
   350     }
       
   351 
       
   352 // ---------------------------------------------------------
       
   353 // CPushMtmFetchOperation::CheckCacheL
       
   354 // ---------------------------------------------------------
       
   355 //
       
   356 void CPushMtmFetchOperation::CheckCacheL()
       
   357 
       
   358     {
       
   359     PUSHLOG_ENTERFN("CPushMtmFetchOperation::CheckCacheL")
       
   360     iCacheSupply = CPushMtmCacheSupply::NewL(iCacheMgr, this);
       
   361     TInt ret = iCacheSupply->StartRequestL();
       
   362     iStatus = KRequestPending;
       
   363 	SetActive();
       
   364     if (ret != KErrNone) // Not in cache
       
   365         {
       
   366         iState = ERequest;
       
   367         iCachedResponse = ETrue;
       
   368         TRequestStatus* status = &iStatus;
       
   369         User::RequestComplete( status, KErrNone);
       
   370         }
       
   371     else
       
   372         {
       
   373         iState = EDone;
       
   374         iCachedResponse = EFalse;
       
   375         }
       
   376 
       
   377     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::CheckCacheL")
       
   378     }
       
   379 
       
   380 // ---------------------------------------------------------
       
   381 // CPushMtmFetchOperation::RequestL
       
   382 // ---------------------------------------------------------
       
   383 //
       
   384 void CPushMtmFetchOperation::RequestL()
       
   385     {
       
   386     PUSHLOG_ENTERFN("CPushMtmFetchOperation::RequestL")
       
   387 
       
   388     iState = EDone;
       
   389 
       
   390     iStatus = KRequestPending;
       
   391 	SetActive();
       
   392     SubmitTransactionL();
       
   393     // Do not call InvokeRun(). Let MHFRunL to handle the request.
       
   394 
       
   395     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::RequestL")
       
   396     }
       
   397 
       
   398 // ---------------------------------------------------------
       
   399 // CPushMtmFetchOperation::Done
       
   400 // ---------------------------------------------------------
       
   401 //
       
   402 void CPushMtmFetchOperation::Done()
       
   403     {
       
   404     PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::Done iResult: <%d>",iResult);
       
   405 
       
   406     delete iRequestedUrl;
       
   407     iRequestedUrl = NULL;
       
   408 
       
   409     // Notify parent.
       
   410     TRequestStatus* status = &iObserver;
       
   411     User::RequestComplete( status, iResult );
       
   412 //  iState = EInit;
       
   413     }
       
   414 
       
   415 // ---------------------------------------------------------
       
   416 // CPushMtmFetchOperation::CreateTransactionL
       
   417 // ---------------------------------------------------------
       
   418 //
       
   419 void CPushMtmFetchOperation::CreateTransactionL()
       
   420     {
       
   421     PUSHLOG_ENTERFN("CPushMtmFetchOperation::CreateTransactionL")
       
   422 
       
   423     __ASSERT_DEBUG( iRequestedUrl, 
       
   424                     ContHandPanic( EPushContHandPanNotInitUrl ) );
       
   425 
       
   426     // Create the transaction.
       
   427     TUriParser8 uri;
       
   428     User::LeaveIfError( uri.Parse( *iRequestedUrl ) );
       
   429     iHttpTrans = 
       
   430         iHttpSess.OpenTransactionL( uri, *this, StringF( HTTP::EGET ) );
       
   431     PUSHLOG_WRITE("CPushMtmFetchOperation OpenTransactionL OK")
       
   432 
       
   433     // Set request headers.
       
   434     RHTTPHeaders hdr = iHttpTrans.Request().GetHeaderCollection();
       
   435     SetHeaderL( hdr, HTTP::EUserAgent, KUserAgent );
       
   436     SetHeaderL( hdr, HTTP::EAccept, HTTP::EAnyAny );
       
   437 
       
   438     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::CreateTransactionL")
       
   439     }
       
   440 
       
   441 // ---------------------------------------------------------
       
   442 // CPushMtmFetchOperation::SubmitTransactionL
       
   443 // ---------------------------------------------------------
       
   444 //
       
   445 void CPushMtmFetchOperation::SubmitTransactionL()
       
   446     {
       
   447     iHttpTrans.SubmitL();
       
   448     PUSHLOG_WRITE("CPushMtmFetchOperation iHttpTrans.SubmitL OK")
       
   449     }
       
   450 
       
   451 // ---------------------------------------------------------
       
   452 // CPushMtmFetchOperation::HandleResponseHeadersL
       
   453 // ---------------------------------------------------------
       
   454 //
       
   455 void CPushMtmFetchOperation::HandleResponseHeadersL( RHTTPResponse aResponse )
       
   456     {
       
   457     PUSHLOG_ENTERFN("CPushMtmFetchOperation::HandleResponseHeadersL")
       
   458 
       
   459     TInt httpCode = aResponse.StatusCode();
       
   460     PUSHLOG_WRITE_FORMAT(" HttpStatus: %d",httpCode)
       
   461 
       
   462 #ifdef __TEST_LOG__
       
   463     LogHeadersL( aResponse.GetHeaderCollection() );
       
   464 #endif // __TEST_LOG__
       
   465 
       
   466     if ( HTTPStatus::IsSuccessful( httpCode ) && 
       
   467          ( httpCode != HTTPStatus::ENoContent ) )
       
   468         {
       
   469         // Successful GET.
       
   470         PUSHLOG_WRITE(" Successful GET")
       
   471         // Get content type.
       
   472         iDataType = TDataType
       
   473             ( GetContentTypeL( aResponse.GetHeaderCollection() ) );
       
   474         // Get source URI.
       
   475         HBufC8* buf = GetSourceUriL( iHttpTrans ).AllocL();
       
   476         PUSHLOG_WRITE(" Source URI got")
       
   477         delete iSourceUri;
       
   478         iSourceUri = buf;
       
   479         // No error:
       
   480         iResult = KErrNone;
       
   481         }
       
   482     else
       
   483         {
       
   484         // See Extended Error Handling UI Specification!
       
   485         iResult = KPushMtmHttpErrorBase - httpCode;
       
   486         PUSHLOG_WRITE_FORMAT(" iResult: <%d>",iResult)
       
   487         }
       
   488 
       
   489     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::HandleResponseHeadersL")
       
   490     }
       
   491 
       
   492 // ---------------------------------------------------------
       
   493 // CPushMtmFetchOperation::VersionRetryL
       
   494 // ---------------------------------------------------------
       
   495 //
       
   496 TBool CPushMtmFetchOperation::VersionRetryL()
       
   497     {
       
   498     TBool retryDone( EFalse );
       
   499 
       
   500     // Check what http version we are using.
       
   501     THTTPHdrVal val;
       
   502     TBool exists = iHttpSess.ConnectionInfo().Property
       
   503         (
       
   504         StringF( HTTP::EHTTPVersion ), 
       
   505         val
       
   506         );
       
   507     if ( exists && TInt( val ) == HTTP::EHttp11 )
       
   508         {
       
   509         // Currently using HTTP/1.1. Cancel transaction and resubmit it using
       
   510         // HTTP/1.0.
       
   511         iHttpTrans.Cancel();
       
   512         iHttpSess.ConnectionInfo().SetPropertyL
       
   513             (
       
   514             StringF( HTTP::EHTTPVersion ),
       
   515             THTTPHdrVal( StringF( HTTP::EHttp10 ) )
       
   516             );
       
   517         SubmitTransactionL();
       
   518         retryDone = ETrue;
       
   519         }
       
   520 
       
   521     return retryDone;
       
   522     }
       
   523 
       
   524 // ---------------------------------------------------------
       
   525 // CPushMtmFetchOperation::AppendResponse
       
   526 // ---------------------------------------------------------
       
   527 //
       
   528 TInt CPushMtmFetchOperation::AppendResponse( const TDesC8& aDataChunk )
       
   529     {
       
   530     TInt err( KErrNone );
       
   531     HBufC8* newBodyBuf = NULL;
       
   532 
       
   533     if ( !iBody )
       
   534         {
       
   535         // iBody does not exist yet; allocate buffer for the first data chunk.
       
   536         newBodyBuf = HBufC8::New( aDataChunk.Length() );
       
   537         }
       
   538     else
       
   539         {
       
   540         const TInt needed( iBody->Des().Length() + aDataChunk.Length() );
       
   541         if ( iBody->Des().MaxLength() < needed )
       
   542             {
       
   543             // iBody exists, but small.
       
   544             newBodyBuf = iBody->ReAlloc( needed );
       
   545             iBody = NULL; // ReAlloc deleted it!
       
   546             }
       
   547         else
       
   548             {
       
   549             // iBody exists and the new chunk fits into it.
       
   550             }
       
   551         }
       
   552 
       
   553     if ( newBodyBuf )
       
   554         {
       
   555         __ASSERT_DEBUG( iBody == NULL, 
       
   556                         ContHandPanic( EPushContHandPanAlreadyInitialized ) );
       
   557         delete iBody; // Not necessary, JIC.
       
   558         iBody = newBodyBuf;
       
   559         }
       
   560     else
       
   561         {
       
   562         if (aDataChunk.Length() > 0)
       
   563             {
       
   564             err = KErrNoMemory;
       
   565             }
       
   566         }
       
   567 
       
   568     if ( !err )
       
   569         {
       
   570         iBody->Des().Append( aDataChunk );
       
   571         }
       
   572 
       
   573     return err;
       
   574     }
       
   575 
       
   576 // ---------------------------------------------------------
       
   577 // CPushMtmFetchOperation::SetHeaderL
       
   578 // ---------------------------------------------------------
       
   579 //
       
   580 void CPushMtmFetchOperation::SetHeaderL( RHTTPHeaders aHeaders, 
       
   581                                          HTTP::TStrings aHdrField, 
       
   582                                          const TDesC8& aHdrValue )
       
   583     {
       
   584     RStringF valStr = iHttpSess.StringPool().OpenFStringL( aHdrValue );
       
   585     CleanupClosePushL<RStringF>( valStr );
       
   586     SetHeaderL( aHeaders, aHdrField, valStr );
       
   587     CleanupStack::PopAndDestroy();  // close valStr
       
   588     }
       
   589 
       
   590 // ---------------------------------------------------------
       
   591 // CPushMtmFetchOperation::SetHeaderL
       
   592 // ---------------------------------------------------------
       
   593 //
       
   594 void CPushMtmFetchOperation::SetHeaderL( RHTTPHeaders aHeaders, 
       
   595                                          HTTP::TStrings aHdrField, 
       
   596                                          HTTP::TStrings aHdrValue )
       
   597     {
       
   598     SetHeaderL( aHeaders, aHdrField, StringF( aHdrValue ) );
       
   599     }
       
   600 
       
   601 // ---------------------------------------------------------
       
   602 // CPushMtmFetchOperation::SetHeaderL
       
   603 // ---------------------------------------------------------
       
   604 //
       
   605 void CPushMtmFetchOperation::SetHeaderL( RHTTPHeaders aHeaders, 
       
   606                                          HTTP::TStrings aHdrField, 
       
   607                                          const RStringF aHdrValue )
       
   608     {
       
   609     THTTPHdrVal val( aHdrValue );
       
   610     aHeaders.SetFieldL( StringF( aHdrField ), val );
       
   611     }
       
   612 
       
   613 // ---------------------------------------------------------
       
   614 // CPushMtmFetchOperation::GetContentTypeL
       
   615 // ---------------------------------------------------------
       
   616 //
       
   617 const TDesC8& CPushMtmFetchOperation::GetContentTypeL( RHTTPHeaders aHeaders )
       
   618     {
       
   619     THTTPHdrVal hdrVal;
       
   620     User::LeaveIfError
       
   621         ( aHeaders.GetField( StringF( HTTP::EContentType ), 0, hdrVal ) );
       
   622     if ( hdrVal.Type() != THTTPHdrVal::KStrFVal )
       
   623         {
       
   624         User::Leave( KErrArgument );
       
   625         }
       
   626     return hdrVal.StrF().DesC();
       
   627     }
       
   628 
       
   629 // ---------------------------------------------------------
       
   630 // CPushMtmFetchOperation::GetSourceUriL
       
   631 // ---------------------------------------------------------
       
   632 //
       
   633 const TDesC8& CPushMtmFetchOperation::GetSourceUriL
       
   634                                       ( RHTTPTransaction aTransaction )
       
   635     {
       
   636     // TODO if redirected URI exists, how do we get it?
       
   637     // For the moment request URI is used.
       
   638     return aTransaction.Request().URI().UriDes();
       
   639     }
       
   640 
       
   641 
       
   642 // ---------------------------------------------------------
       
   643 // CPushMtmFetchOperation::LogHeadersL
       
   644 // ---------------------------------------------------------
       
   645 //
       
   646 #ifndef __TEST_LOG__
       
   647 
       
   648 void CPushMtmFetchOperation::LogHeadersL( RHTTPHeaders /*aHeaders*/ )
       
   649     {
       
   650     }
       
   651 
       
   652 #else // #ifdef __TEST_LOG__
       
   653 
       
   654 void CPushMtmFetchOperation::LogHeadersL( RHTTPHeaders aHeaders )
       
   655     {
       
   656     PUSHLOG_ENTERFN("CPushMtmFetchOperation::LogHeadersL")
       
   657 
       
   658     _LIT( KDateFormat, "%D%M%Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S.%C%:3" );
       
   659 
       
   660     PUSHLOG_WRITE("Headers:");
       
   661 
       
   662     RStringPool strP = iHttpTrans.Session().StringPool();
       
   663     THTTPHdrFieldIter it = aHeaders.Fields();
       
   664 
       
   665     while ( !it.AtEnd() )
       
   666         {
       
   667         RStringTokenF fieldName = it();
       
   668         RStringF fieldNameStr = strP.StringF( fieldName );
       
   669         THTTPHdrVal fieldVal;
       
   670         if ( aHeaders.GetField( fieldNameStr, 0, fieldVal ) == KErrNone )
       
   671             {
       
   672             const TInt KMaxLogStrLen = 64;
       
   673             TPtrC8 fieldName8 = fieldNameStr.DesC();
       
   674             TInt fieldNameLen = fieldName8.Length();
       
   675             fieldNameLen = ( KMaxLogStrLen < fieldNameLen ) ? 
       
   676                              KMaxLogStrLen : fieldNameLen;
       
   677             fieldName8.Set( fieldName8.Mid( 0, fieldNameLen ) );
       
   678             HBufC* fieldNameHBufC = HBufC::NewMaxLC( fieldName8.Length() );
       
   679             TPtr fieldName = fieldNameHBufC->Des();
       
   680             fieldName.Copy( fieldName8 );
       
   681 
       
   682             switch ( fieldVal.Type() )
       
   683                 {
       
   684                 case THTTPHdrVal::KTIntVal:
       
   685                     {
       
   686                     PUSHLOG_WRITE_FORMAT2
       
   687                         (" <%S> (%d)",&fieldName,fieldVal.Int())
       
   688                     break;
       
   689                     }
       
   690 
       
   691                 case THTTPHdrVal::KStrFVal:
       
   692                     {
       
   693                     RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
       
   694                     TPtrC8 fieldVal8 = fieldValStr.DesC();
       
   695                     // Truncate if too long.
       
   696                     TInt fieldValLen = fieldVal8.Length();
       
   697                     fieldNameLen = ( KMaxLogStrLen < fieldValLen ) ? 
       
   698                                      KMaxLogStrLen : fieldValLen;
       
   699                     fieldVal8.Set( fieldVal8.Mid( 0, fieldValLen ) );
       
   700                     // Truncate end.
       
   701                     HBufC* fieldValHBufC = HBufC::NewMaxLC( fieldVal8.Length() );
       
   702                     TPtr fieldVal = fieldValHBufC->Des();
       
   703                     fieldVal.Copy( fieldVal8 );
       
   704                     PUSHLOG_WRITE_FORMAT2
       
   705                         (" <%S> (%S)",&fieldName,&fieldVal)
       
   706                     CleanupStack::PopAndDestroy( fieldValHBufC ); 
       
   707                                                 // fieldValHBufC
       
   708                     break;
       
   709                     }
       
   710 
       
   711                 case THTTPHdrVal::KStrVal:
       
   712                     {
       
   713                     RString fieldValStr = strP.String( fieldVal.Str() );
       
   714                     TPtrC8 fieldVal8 = fieldValStr.DesC();
       
   715                     // Truncate if too long.
       
   716                     TInt fieldValLen = fieldVal8.Length();
       
   717                     fieldNameLen = ( KMaxLogStrLen < fieldValLen ) ? 
       
   718                                      KMaxLogStrLen : fieldValLen;
       
   719                     fieldVal8.Set( fieldVal8.Mid( 0, fieldValLen ) );
       
   720                     // Truncate end.
       
   721                     HBufC* fieldValHBufC = HBufC::NewMaxLC( fieldVal8.Length() );
       
   722                     TPtr fieldVal = fieldValHBufC->Des();
       
   723                     fieldVal.Copy( fieldVal8 );
       
   724                     PUSHLOG_WRITE_FORMAT2
       
   725                         (" <%S> (%S)",&fieldName,&fieldVal)
       
   726                     CleanupStack::PopAndDestroy( fieldValHBufC ); 
       
   727                                                 // fieldValHBufC
       
   728                     break;
       
   729                     }
       
   730 
       
   731                 case THTTPHdrVal::KDateVal:
       
   732                     {
       
   733                     TDateTime date = fieldVal.DateTime();
       
   734                     TBuf<40> dateTimeString;
       
   735                     TTime t( date );
       
   736                     TRAP_IGNORE( t.FormatL( dateTimeString, KDateFormat ) );
       
   737                     PUSHLOG_WRITE_FORMAT2
       
   738                         (" <%S> (%S)",&fieldName,&dateTimeString)
       
   739                     break;
       
   740                     }
       
   741 
       
   742                 default:
       
   743                     {
       
   744                     PUSHLOG_WRITE_FORMAT2
       
   745                         (" <%S> unrecognised value type (%d)",
       
   746                            &fieldName,fieldVal.Type())
       
   747                     break;
       
   748                     }
       
   749                 }
       
   750 
       
   751             // Display realm for WWW-Authenticate header.
       
   752             RStringF wwwAuth = strP.StringF
       
   753                 ( HTTP::EWWWAuthenticate, RHTTPSession::GetTable() );
       
   754             if ( fieldNameStr == wwwAuth )
       
   755                 {
       
   756                 PUSHLOG_WRITE(" fieldNameStr == wwwAuth")
       
   757                 // check the auth scheme is 'basic'
       
   758                 RStringF basic = strP.StringF
       
   759                     ( HTTP::EBasic, RHTTPSession::GetTable() );
       
   760                 RStringF realm = strP.StringF
       
   761                     ( HTTP::ERealm, RHTTPSession::GetTable() );
       
   762                 THTTPHdrVal realmVal;
       
   763                 if ( ( fieldVal.StrF() == basic ) && 
       
   764                     ( !aHeaders.GetParam( wwwAuth, realm, realmVal ) ) )
       
   765                     {
       
   766                     RStringF realmValStr = strP.StringF( realmVal.StrF() );
       
   767                     PUSHLOG_WRITE_FORMAT(" Realm <%S>",&realmValStr);
       
   768                     }
       
   769                 }
       
   770 
       
   771             CleanupStack::PopAndDestroy( fieldNameHBufC ); // fieldNameHBufC
       
   772             }
       
   773         ++it;
       
   774         }
       
   775 
       
   776     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::LogHeadersL")
       
   777     }
       
   778 
       
   779 #endif // __TEST_LOG__
       
   780 
       
   781 // ---------------------------------------------------------
       
   782 // CPushMtmFetchOperation::DoCancel
       
   783 // ---------------------------------------------------------
       
   784 //
       
   785 void CPushMtmFetchOperation::DoCancel()
       
   786     {
       
   787     switch ( iState )
       
   788         {
       
   789         /*case EStartConnect:
       
   790             {
       
   791             // Complete ourselves - nothing is outstanding.
       
   792             TRequestStatus* ownStatus = &iStatus;
       
   793             User::RequestComplete( ownStatus, KErrCancel );
       
   794             break;
       
   795             }*/
       
   796 
       
   797         /*case EConnect:
       
   798             {
       
   799             //__ASSERT_DEBUG( iConn, ContHandPanic( ECodInternal ) );
       
   800             //iConn->Cancel(); // This will complete our status.
       
   801             break;
       
   802             }*/
       
   803 
       
   804         case EStartRequest:
       
   805         case ECheckCache:
       
   806         case ERequest:
       
   807             {
       
   808             delete iCacheSupply;
       
   809             iCacheSupply = NULL;
       
   810 
       
   811             iHttpTrans.Close();
       
   812             // Now the transaction has been closed. Closing it does not
       
   813             // complete our status, so we do it manually.
       
   814             TRequestStatus* status = &iStatus;
       
   815             SetActive();
       
   816             User::RequestComplete( status, iResult );
       
   817             break;
       
   818             }
       
   819 
       
   820         case EInit:
       
   821         default:
       
   822             {
       
   823             // No requests should be outstanding in these states.
       
   824             //ContHandPanic( ECodInternal );
       
   825             break;
       
   826             }
       
   827         }
       
   828 
       
   829     iResult = KErrCancel;
       
   830     Done();
       
   831     }
       
   832 
       
   833 // ---------------------------------------------------------
       
   834 // CPushMtmFetchOperation::RunL
       
   835 // ---------------------------------------------------------
       
   836 //
       
   837 void CPushMtmFetchOperation::RunL()
       
   838     {
       
   839     PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::RunL status = %d", iState);
       
   840     // Handle errors in RunError().
       
   841     User::LeaveIfError( iStatus.Int() );
       
   842 
       
   843     switch ( iState )
       
   844         {
       
   845         case EInit:
       
   846             {
       
   847             InitializeL();
       
   848             break;
       
   849             }
       
   850 
       
   851         case EStartRequest:
       
   852             {
       
   853             StartRequestL();
       
   854             break;
       
   855             }
       
   856 
       
   857         case ERequest:
       
   858             {
       
   859             RequestL();
       
   860             break;
       
   861             }
       
   862 
       
   863         case EDone:
       
   864             {
       
   865             Done();
       
   866             break;
       
   867             }
       
   868 
       
   869         default:
       
   870             {
       
   871             // JIC.
       
   872             Done();
       
   873             break;
       
   874             }
       
   875         }
       
   876     PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::RunL moving to status = %d", iState);
       
   877     }
       
   878 
       
   879 // ---------------------------------------------------------
       
   880 // CPushMtmFetchOperation::RunError
       
   881 // ---------------------------------------------------------
       
   882 //
       
   883 TInt CPushMtmFetchOperation::RunError( TInt aError )
       
   884     {
       
   885     PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::RunError <%d>",aError)
       
   886 
       
   887     iResult = aError;
       
   888     delete iCacheSupply;
       
   889     iCacheSupply = NULL;
       
   890     iHttpTrans.Close();
       
   891     Done();
       
   892 
       
   893     return KErrNone;
       
   894     }
       
   895 
       
   896 // ---------------------------------------------------------
       
   897 // CPushMtmFetchOperation::MHFRunL
       
   898 // ---------------------------------------------------------
       
   899 //
       
   900 void CPushMtmFetchOperation::MHFRunL
       
   901     ( 
       
   902         RHTTPTransaction DEBUG_ONLY( aTransaction ), 
       
   903         const THTTPEvent& aEvent 
       
   904     )
       
   905     {
       
   906     PUSHLOG_ENTERFN("CPushMtmFetchOperation::MHFRunL")
       
   907     __ASSERT_DEBUG( aTransaction == iHttpTrans, 
       
   908                     ContHandPanic( EPushContHandPanBadTransaction ) );
       
   909     switch ( aEvent.iStatus )
       
   910         {
       
   911         case THTTPEvent::EGotResponseHeaders:
       
   912             {
       
   913             PUSHLOG_WRITE(" EGotResponseHeaders")
       
   914             // pass headers to the cache first
       
   915             TRAP_IGNORE( iCacheSupply->HeadersReceivedL() );
       
   916             // Now we know that the request was processed by the server.
       
   917             HandleResponseHeadersL( iHttpTrans.Response() );
       
   918             break;
       
   919             }
       
   920 
       
   921         case THTTPEvent::EGotResponseBodyData:
       
   922             {
       
   923             PUSHLOG_WRITE(" EGotResponseBodyData")
       
   924             // pass chunk to the cache first
       
   925             TRAP_IGNORE( iCacheSupply->BodyReceivedL() );
       
   926             // Get body data and save it.
       
   927             TInt err( KErrNone );
       
   928             MHTTPDataSupplier* body = iHttpTrans.Response().Body();
       
   929             if ( !body )
       
   930                 {
       
   931                 PUSHLOG_WRITE(" NULL body")
       
   932                 }
       
   933             else
       
   934                 {
       
   935                 TPtrC8 bodyPtr;
       
   936                 // Caution: no leaving between body->GetNextDataPart and
       
   937                 // body->ReleaseData calls! Data must always be released.
       
   938 #ifdef __TEST_LOG__
       
   939                 TBool isLast = body->GetNextDataPart( bodyPtr ); // No leave...
       
   940                 PUSHLOG_WRITE_FORMAT(" last? (%d)",(isLast?1:0))
       
   941 #else // ifndef __TEST_LOG__
       
   942                 (void)body->GetNextDataPart( bodyPtr ); // No leave...
       
   943 #endif // __TEST_LOG__
       
   944                 //if ( iHttpTrans.Request().Method() == StringF( HTTP::EGET ) )
       
   945                 err = AppendResponse( bodyPtr );
       
   946                 body->ReleaseData();                          // ...until here.
       
   947                 PUSHLOG_WRITE_FORMAT(" err: (%d)",err)
       
   948                 User::LeaveIfError( err );
       
   949                 }
       
   950             break;
       
   951             }
       
   952 
       
   953         case THTTPEvent::EResponseComplete:
       
   954             {                  
       
   955             // do not mix it up with the ESucceeded
       
   956             // The transaction's response is complete. An incoming event. 
       
   957             TRAP_IGNORE( iCacheSupply->ResponseCompleteL() );
       
   958             break;
       
   959             }
       
   960 
       
   961         case THTTPEvent::ERequestComplete:
       
   962             {
       
   963             // request is all set
       
   964             iCacheSupply->CloseRequest();
       
   965             break;
       
   966             }
       
   967 
       
   968         case THTTPEvent::EFailed:
       
   969             {
       
   970             PUSHLOG_WRITE(" EFailed")
       
   971             // Safety code: we should already have an error code.
       
   972             if ( iResult == KErrNone )
       
   973                 {
       
   974                 iResult = KErrGeneral;
       
   975                 }
       
   976             // TODO. Fall through.
       
   977             }
       
   978 
       
   979         case THTTPEvent::ESucceeded:
       
   980             {
       
   981             PUSHLOG_WRITE(" ESucceeded")
       
   982             delete iCacheSupply;
       
   983             iCacheSupply = NULL;
       
   984             iHttpTrans.Close();
       
   985             // Transaction is finished, invoke RunL now.
       
   986             TRequestStatus* status = &iStatus;
       
   987             if (!IsActive())
       
   988                 {
       
   989                 SetActive();
       
   990                 }
       
   991             User::RequestComplete( status, iResult );
       
   992             break;
       
   993             }
       
   994 
       
   995         case THTTPEvent::ERedirectedPermanently:
       
   996             {
       
   997             PUSHLOG_WRITE(" ERedirectedPermanently")
       
   998             // Do nothing just continue.
       
   999             break;
       
  1000             }
       
  1001 
       
  1002         default:
       
  1003             {
       
  1004             PUSHLOG_WRITE(" default case")
       
  1005             // Handle errors in MHFRunError.
       
  1006             User::LeaveIfError( aEvent.iStatus );
       
  1007             break;
       
  1008             }
       
  1009         }
       
  1010 
       
  1011     PUSHLOG_LEAVEFN("CPushMtmFetchOperation::MHFRunL")
       
  1012     }
       
  1013 
       
  1014 // ---------------------------------------------------------
       
  1015 // CPushMtmFetchOperation::MHFRunError
       
  1016 // ---------------------------------------------------------
       
  1017 //
       
  1018 TInt CPushMtmFetchOperation::MHFRunError
       
  1019     ( 
       
  1020         TInt aError, 
       
  1021         RHTTPTransaction DEBUG_ONLY( aTransaction ), 
       
  1022         const THTTPEvent& /*aEvent*/ 
       
  1023     )
       
  1024     {
       
  1025     __ASSERT_DEBUG( aTransaction == iHttpTrans, 
       
  1026                     ContHandPanic( EPushContHandPanBadTransaction ) );
       
  1027     iResult = aError;
       
  1028     iCacheSupply->CloseRequest();
       
  1029     iHttpTrans.Close();
       
  1030 
       
  1031     // Transaction is finished, invoke RunL now. 
       
  1032     // iResult contains the (error) code.
       
  1033     if ( !IsActive() )
       
  1034         {
       
  1035 	    SetActive();
       
  1036         }
       
  1037     TRequestStatus* status = &iStatus;
       
  1038     User::RequestComplete( status, KErrNone );
       
  1039 
       
  1040     return KErrNone;
       
  1041     }
       
  1042 
       
  1043 // End of file.