codhandler/codeng/src/HttpLoader.cpp
changeset 0 dd21522fd290
child 10 a359256acfc6
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     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: 
       
    15 *      Loading functions for COD Handler.   
       
    16 *      
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 
       
    23 #include "HttpLoader.h"
       
    24 #include "CodSaver.h"
       
    25 #include "HttpTcpSession.h"
       
    26 #include "HttpWapSession.h"
       
    27 #include "CodLogger.h"
       
    28 #include "CodPanic.h"
       
    29 #include "CodError.h"
       
    30 #include "CodUtil.h"
       
    31 #include "Connection.h"
       
    32 #include "Timeout.h"
       
    33 #include "CodProgress.h"
       
    34 #include "CodEngbase.h"
       
    35 
       
    36 #include <CookieFilterInterface.h>
       
    37 #include <uaproffilter_interface.h>
       
    38 #include <DeflateFilterInterface.h>
       
    39 #include <httperr.h>
       
    40 #include <bldvariant.hrh>
       
    41 #include <ECom.h>
       
    42 #include <es_sock.h>
       
    43 #include <EscapeUtils.h>
       
    44 #include <http/rhttpheaders.h>
       
    45 #include <Oma2Agent.h>
       
    46 #include <HttpDownloadMgrCommon.h>
       
    47 #include    "HeaderField.h"
       
    48 #include    "FileExt.h"
       
    49 #include    "CodData.h"
       
    50 
       
    51 
       
    52 
       
    53 _LIT8( KDRMOldContentType, "x-drm-old-content-type");           // old content type header to be added
       
    54 _LIT8( KAcceptRangeHeader, "bytes");           
       
    55 
       
    56 // ================= CONSTANTS =======================
       
    57 
       
    58 /// Maximum user name length we support.
       
    59 LOCAL_D const TInt KCodMaxAuthUserName = 50;
       
    60 /// Maximum password length we support.
       
    61 LOCAL_D const TInt KCodMaxAuthPassword = 50;
       
    62 /// WSP protocol name.
       
    63 _LIT8( KCodWspProtocol, "WSP/WSP" );
       
    64 /// Accept-header value (application/vnd.wap.mms-message).
       
    65 _LIT8( KCodAcceptMmsHeaderValue, "application/vnd.wap.mms-message" );
       
    66 /// Accept-header value (application/vnd.wap.sic).
       
    67 _LIT8( KCodAcceptSiHeaderValue, "application/vnd.wap.sic" );
       
    68 /// "No activity" timeout for GET request (in microseconds), 60 sec - Updated to 60 secs as part of error fix JSIN-7JSE6H
       
    69 /// Let's try to keep the same timeout for WCDMA & GPRS (???)
       
    70 LOCAL_D const TInt KCodGetTimeout = 60000000;
       
    71 /// "No activity" timeout for POST request (in microseconds), 10 sec.
       
    72 LOCAL_D const TInt KCodPostTimeout = 10000000;
       
    73 /// Install-notify timeout (in microseconds), 50 msec.
       
    74 LOCAL_D const TInt KCodINTimeout = 50000;
       
    75 /// Retry count for GET request timeout (1 attempt == no retry).
       
    76 LOCAL_D const TInt KCodGetRetry = 1;
       
    77 /// Retry count for POST request timeout (2 attempt == 1 retry).
       
    78 LOCAL_D const TInt KCodPostRetry = 2;
       
    79 /// Estimated data transfer for reponse headers. Needed for progress.
       
    80 LOCAL_D const TInt KCodRespHdrsTraffic = 512;
       
    81 /// characters which should be escaped from requested URL's
       
    82 _LIT8( KUriEscChars, " ");
       
    83 
       
    84 // ================= MEMBER FUNCTIONS =======================
       
    85 
       
    86 // ---------------------------------------------------------
       
    87 // CHttpLoader::NewL()
       
    88 // ---------------------------------------------------------
       
    89 //
       
    90 CHttpLoader* CHttpLoader::NewL
       
    91         (
       
    92         CConnection& aConnection,
       
    93         MCodLoadObserver* aCodLoadObserver,
       
    94         TCodProgress* aProgress ,
       
    95         CCodEngBase* aCodEng 
       
    96         )
       
    97     {
       
    98     CHttpLoader* loader =
       
    99         new( ELeave ) CHttpLoader( aConnection, aCodLoadObserver, aProgress, aCodEng );
       
   100     CleanupStack::PushL( loader );
       
   101     loader->ConstructL();
       
   102     CleanupStack::Pop( loader );
       
   103     return loader;
       
   104     }
       
   105 // ---------------------------------------------------------
       
   106 // CHttpLoader::~CHttpLoader()
       
   107 // ---------------------------------------------------------
       
   108 //
       
   109 CHttpLoader::~CHttpLoader()
       
   110     {
       
   111     Cancel();
       
   112     iFeatMgr.Close();
       
   113     delete iTimeout;
       
   114     delete iSess;
       
   115     delete iNotifyBody;
       
   116     delete iUri;
       
   117     delete iINTimeout;
       
   118     
       
   119      if(iResponseHeaders != NULL)
       
   120     {
       
   121     iResponseHeaders->ResetAndDestroy();
       
   122     delete iResponseHeaders;
       
   123     }
       
   124     
       
   125     delete iDownloadInfo;
       
   126 
       
   127     REComSession::FinalClose();
       
   128     __ASSERT_DEBUG( !iParentStatus, CodPanic( ECodRequestPending ) );
       
   129     CLOG(( EHttpLoad, 2, _L("*** CHttpLoader::~CHttpLoader") ));
       
   130     }
       
   131 
       
   132 // ---------------------------------------------------------
       
   133 // CHttpLoader::LoadL()
       
   134 // ---------------------------------------------------------
       
   135 //
       
   136 void CHttpLoader::LoadL
       
   137         (
       
   138         const TDesC8& aUrl,
       
   139         MCodSaverFactory& aSaverFactory,
       
   140         TRequestStatus* aStatus
       
   141         )
       
   142     {
       
   143     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::LoadL") ));
       
   144     // Misuse asserts.
       
   145     __ASSERT_ALWAYS( aStatus, CodPanic( ECodInvalidArguments ) );
       
   146     __ASSERT_ALWAYS( iState == EInit, CodPanic( ECodOffState ) );
       
   147     // Internal asserts.
       
   148     __ASSERT_DEBUG( !iParentStatus, CodPanic( ECodInternal ) );
       
   149     __ASSERT_DEBUG( !iSaverFactory, CodPanic( ECodInternal ) );
       
   150     __ASSERT_DEBUG( !iSaver, CodPanic( ECodInternal ) );
       
   151     __ASSERT_DEBUG( !iUri, CodPanic( ECodInternal ) );
       
   152 
       
   153     iUri = aUrl.AllocL();
       
   154     iMethod = HTTP::EGET;
       
   155     iRetry = KCodGetRetry;
       
   156     iSaverFactory = &aSaverFactory;
       
   157     iResult = KErrNone;
       
   158     iRedirect = EFalse;
       
   159     
       
   160     
       
   161     iCodEng->LoadSubInfoFileL(iCodEng->Data().ActiveDownload() , iResponseHeaders );
       
   162     
       
   163     TBuf8<128> contentType;
       
   164     TRAPD( err, contentType = GetContentTypeL() );
       
   165     if(err == KErrNone)
       
   166         {
       
   167         iSaver = iSaverFactory->CreateSaverL( contentType );
       
   168         }
       
   169         
       
   170     iParentStatus = aStatus;
       
   171     *iParentStatus = KRequestPending;
       
   172 
       
   173     if( iProgress && iSaver )
       
   174         {
       
   175         iSaver->SetSourceUriL(iUri->Des() );
       
   176         TInt dlSize( 0 );
       
   177         //Current Track Downloaded Size
       
   178         dlSize += iCodEng->Data()[iCodEng->Data().ActiveDownload()]->DownloadedSize();
       
   179                 
       
   180         if(dlSize >= 0)
       
   181             {
       
   182             iProgress->SetAmountL(dlSize);                
       
   183             }
       
   184         }
       
   185 
       
   186     if( iProgress )
       
   187     	{
       
   188     	iProgress->StartPhaseL(TCodProgress::ELoad);
       
   189     	}
       
   190 
       
   191     Continue( EStart );
       
   192 
       
   193     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::LoadL") ));
       
   194     }
       
   195 
       
   196 // ---------------------------------------------------------
       
   197 // CHttpLoader::NotifyL()
       
   198 // ---------------------------------------------------------
       
   199 //
       
   200 void CHttpLoader::NotifyL
       
   201 ( const TDesC8& aUrl, const TDesC8& aNotifyBody, TRequestStatus* aStatus )
       
   202     {
       
   203     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::NotifyL") ));
       
   204     // Misuse asserts.
       
   205     __ASSERT_ALWAYS( aStatus, CodPanic( ECodInvalidArguments ) );
       
   206     __ASSERT_ALWAYS( iState == EInit, CodPanic( ECodOffState ) );
       
   207     // Internal asserts.
       
   208     __ASSERT_DEBUG( !iParentStatus, CodPanic( ECodInternal ) );
       
   209     __ASSERT_DEBUG( !iNotifyBody, CodPanic( ECodInternal ) );
       
   210     __ASSERT_DEBUG( !iUri, CodPanic( ECodInternal ) );
       
   211 
       
   212     // Allocation of two members iUri+iNotifyBody is atomic.
       
   213     HBufC8* notifyBody = aNotifyBody.AllocLC();
       
   214     iUri = aUrl.AllocL();
       
   215     iNotifyBody = notifyBody;
       
   216     CleanupStack::Pop( notifyBody );    // now member.
       
   217     iMethod = HTTP::EPOST;
       
   218     iRetry = KCodPostRetry;
       
   219     iParentStatus = aStatus;
       
   220     *iParentStatus = KRequestPending;
       
   221     iResult = KErrNone;
       
   222 
       
   223     Continue( EStart );
       
   224 
       
   225     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::NotifyL") ));
       
   226     }
       
   227 
       
   228 // ---------------------------------------------------------
       
   229 // CHttpLoader::DoCancel()
       
   230 // ---------------------------------------------------------
       
   231 //
       
   232 void CHttpLoader::DoCancel()
       
   233     {
       
   234     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::DoCancel iState(%d)"), iState ));
       
   235     switch ( iState )
       
   236         {
       
   237         case EStart:
       
   238             {
       
   239             // Already completed (by self-completion).
       
   240             __ASSERT_DEBUG( iStatus != KRequestPending, \
       
   241                 CodPanic( ECodInternal ) );
       
   242             SelfComplete( KErrCancel );
       
   243             break;
       
   244             }
       
   245 
       
   246         case EOpen:
       
   247             {
       
   248             __ASSERT_DEBUG( iSess, CodPanic( ECodInternal ) );
       
   249             // This will complete our status.
       
   250             iSess->Disconnect();
       
   251             break;
       
   252             }
       
   253 
       
   254         case ERequest:
       
   255             {
       
   256             CompleteTransaction( KErrCancel );
       
   257             break;
       
   258             }
       
   259 
       
   260         case EInit:
       
   261         default:
       
   262             {
       
   263             // No requests should be outstanding in these states.
       
   264             CLOG(( EHttpLoad, 0, _L("CHttpLoader::DoCancel: unexpected state") ));
       
   265             CodPanic( ECodInternal );
       
   266             break;
       
   267             }
       
   268         }
       
   269 
       
   270     iResult = KErrCancel;
       
   271     Done();
       
   272 
       
   273     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::DoCancel") ));
       
   274     }
       
   275 
       
   276 
       
   277 
       
   278 void CHttpLoader::Pause()
       
   279     {
       
   280     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::Pause iState(%d)"), iState ));
       
   281     switch ( iState )
       
   282         {
       
   283         case ERequest:
       
   284             {
       
   285             CompleteTransaction( KErrCodHttpDownloadPaused );
       
   286             break;
       
   287             }
       
   288         }
       
   289     //Done();
       
   290 
       
   291     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::Pause") ));
       
   292     }
       
   293 
       
   294 // ---------------------------------------------------------
       
   295 // CHttpLoader::RunL()
       
   296 // ---------------------------------------------------------
       
   297 //
       
   298 void CHttpLoader::RunL()
       
   299     {
       
   300     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::RunL iState(%d) iStatus(%d)"), \
       
   301         iState, iStatus.Int() ));
       
   302 
       
   303     User::LeaveIfError( iStatus.Int() );    // Handle errors in RunError.
       
   304     switch ( iState )
       
   305         {
       
   306         case EStart:
       
   307             {
       
   308             // Operation initiated - Open a session.
       
   309             OpenSessionL();
       
   310             break;
       
   311             }
       
   312 
       
   313         case EOpen:
       
   314             {
       
   315             // Session opened. Make the HTTP request.
       
   316             RequestL();
       
   317             break;
       
   318             }
       
   319 
       
   320         case ERequest:
       
   321             {
       
   322             // Request completed, we are done.
       
   323             Done();
       
   324             break;
       
   325             }
       
   326 
       
   327         case EInit:
       
   328         default:
       
   329             {
       
   330             // No requests should be outstanding in these states.
       
   331             CLOG(( ECodEng, 0, _L("CHttpLoader::RunL: unexpected state") ));
       
   332             CodPanic( ECodInternal );
       
   333             break;
       
   334             }
       
   335         }
       
   336     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::RunL") ));
       
   337     }
       
   338 
       
   339 // ---------------------------------------------------------
       
   340 // CHttpLoader::RunError()
       
   341 // ---------------------------------------------------------
       
   342 //
       
   343 TInt CHttpLoader::RunError( TInt aError )
       
   344     {
       
   345     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::RunError aError(%d)"), aError ));
       
   346     iResult = aError;
       
   347     Done();
       
   348     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::RunError") ));
       
   349     return KErrNone;
       
   350     }
       
   351 
       
   352 // ---------------------------------------------------------
       
   353 // CHttpLoader::MHFRunL()
       
   354 // ---------------------------------------------------------
       
   355 //
       
   356 void CHttpLoader::MHFRunL
       
   357 ( RHTTPTransaction DEBUG_ONLY( aTransaction ), const THTTPEvent& aEvent )
       
   358     {
       
   359     CLOG(( EHttpLoad, 0, _L("-> CHttpLoader::MHFRunL event(%d)"), \
       
   360                                                             aEvent.iStatus ));
       
   361     __ASSERT_DEBUG( aTransaction == iTrans, CodPanic( ECodInternal ) );
       
   362     __ASSERT_DEBUG( iState == ERequest, CodPanic( ECodOffState ) );
       
   363 
       
   364     StartTimeout();    // There was activity -> restart timeout.
       
   365 
       
   366     switch ( aEvent.iStatus )
       
   367         {
       
   368         case THTTPEvent::EGotResponseHeaders:
       
   369             {
       
   370             // Now we know that the request was processed by the server.
       
   371             iSuppressErrors = EFalse;
       
   372             if (iMethod == HTTP::EGET)
       
   373             {
       
   374                 StoreResponseHeaderL();
       
   375                 
       
   376                 //If DD contain TYPE defined more than once, 
       
   377             	//TYPE defined in the ClntServ should match the Content-Type that we obtain in the header while content downloading 
       
   378             
       
   379            	    const TDesC8& ContentType = GetContentTypeL( iTrans.Response().GetHeaderCollection() );
       
   380                 const CCodData& CodData = iCodEng->Data();
       
   381           
       
   382                 for ( TInt i = 1; i < CodData[CodData.ActiveDownload()]->Types().MdcaCount(); i++ )
       
   383             		{
       
   384           			const TDataType& type( CodData[CodData.ActiveDownload()]->Types().MdcaPoint( i ) );
       
   385             		if(ContentType.Find (type.Des8()) != KErrNotFound )             
       
   386                 		{
       
   387                 		CodData[CodData.ActiveDownload()]->ReArrangeTypesL(i);
       
   388                 		iCodEng->ContentTypeChanged();
       
   389                 		break;
       
   390                			}                
       
   391             		}
       
   392 
       
   393                 iCodEng->StoreSubInfoFileL(iResponseHeaders, iCodEng->Data().ActiveDownload() );
       
   394             }
       
   395             HandleResponseHeadersL( iTrans.Response() );
       
   396             
       
   397             if (iResult == KErrCodHttpBadUrl ) 
       
   398             {
       
   399             	User::Leave( KErrCodHttpBadUrl );
       
   400             } 
       
   401             else if ( iResult == KErrCodHttpBadResponse ) 
       
   402             {
       
   403             	User::Leave( KErrCodHttpBadResponse );
       
   404             }
       
   405             else 
       
   406             {
       
   407                 // Increment progress a bit to make update frequent.
       
   408                 IncProgressL( KCodRespHdrsTraffic );	
       
   409             }
       
   410             break;
       
   411             }
       
   412 
       
   413         case THTTPEvent::EGotResponseBodyData:
       
   414             {
       
   415             // Get body data and save (GET) or ignore (POST)
       
   416             TInt err( KErrNone );
       
   417             TInt size;
       
   418             MHTTPDataSupplier* body = iTrans.Response().Body();
       
   419             TPtrC8 bodyP;
       
   420             // Caution: no leaving between body->GetNextDataPart and
       
   421             // body->ReleaseData calls! Data must always be released.
       
   422 #ifdef __TEST_COD_LOG
       
   423             TBool lastChunk = // ('Log-only' variable.)
       
   424 #endif /* def __TEST_COD_LOG */
       
   425             body->GetNextDataPart( bodyP );     // No leave...
       
   426             size = bodyP.Size();
       
   427 #ifdef __TEST_COD_LOG
       
   428             CDUMP(( EHttpLoad, 5, _S("Data: "), _S("      "), \
       
   429                 bodyP.Ptr(), bodyP.Size() ));
       
   430             if ( lastChunk )
       
   431                 {
       
   432                 CLOG(( EHttpLoad, 5, _L("      (EOF)") ));
       
   433                 }
       
   434             else
       
   435                 {
       
   436                 CLOG(( EHttpLoad, 5, _L("      (more data)") ));
       
   437                 }
       
   438 #endif /* def __TEST_COD_LOG */
       
   439             if ( iMethod == HTTP::EGET )
       
   440                 {
       
   441 //TODO check  if iSaver == NULL occures                __ASSERT_DEBUG( iSaver, CodPanic( ECodInternal ) );
       
   442                 if (iSaver)
       
   443 				{
       
   444                   err = iSaver->AppendData( bodyP );
       
   445                   iCodEng->UpdateDownloadedSize( bodyP.Size());  
       
   446 				}
       
   447 			}
       
   448             body->ReleaseData();                // ...until here.
       
   449             User::LeaveIfError( err );
       
   450             IncProgressL( size );
       
   451             break;
       
   452             }
       
   453             
       
   454         case THTTPEvent::EResponseComplete:
       
   455             {
       
   456              if(iSaver)
       
   457                  {
       
   458                  iSaver->OnComplete();
       
   459                  }
       
   460              
       
   461         	 break;
       
   462             }    
       
   463 
       
   464         case THTTPEvent::EFailed:
       
   465             {
       
   466             // Safety code: we should already have an error code.
       
   467             if ( iResult == KErrNone )
       
   468                 {
       
   469                 iResult = KErrCodWapConnectionDropped;
       
   470                 }
       
   471             // Fall through.
       
   472             }
       
   473 
       
   474         case THTTPEvent::ESucceeded:
       
   475             {
       
   476             CompleteTransaction( iResult );
       
   477             break;
       
   478             }
       
   479 
       
   480         case THTTPEvent::ERedirectRequiresConfirmation:
       
   481             {
       
   482             // 3xx redirect response received for POST. Redirect filter is
       
   483             // cautious to redirect POST request and asks for confirmation.
       
   484             // Confirmation means that we must resubmit the transaction.
       
   485             iTrans.SubmitL();
       
   486             break;
       
   487             }
       
   488             
       
   489         case THTTPEvent::ERedirectedPermanently:
       
   490         	{
       
   491         	RedirectedPermanentlyL(iTrans.Request().URI().UriDes());
       
   492         	break;
       
   493         	}
       
   494         	
       
   495         case THTTPEvent::ERedirectedTemporarily:
       
   496         	{
       
   497         	RedirectedTemporaryL(iTrans.Request().URI().UriDes());
       
   498         	break;
       
   499         	}
       
   500 
       
   501         default:
       
   502             {
       
   503             if( aEvent.iStatus == KErrHttpRedirectUseProxy && UseProxyL() )
       
   504                 {
       
   505                 // KErrHttpRedirectUseProxy is sent by redirect filter if the
       
   506                 // response is 305 Use Proxy. This is not really an error;
       
   507                 // error code is returned only to indicate that the redirect
       
   508                 // filter cannot handle this kind of redirect automatically;
       
   509                 // client action is required.
       
   510                 //
       
   511                 // If UseProxyL can successfully set the new proxy address,
       
   512                 // this is not an error. Otherwise it is.
       
   513                 ;
       
   514                 }
       
   515             else if( aEvent.iStatus == KErrConnectionTerminated )
       
   516                 {
       
   517                 // if we get KErrConnectionTerminated during period of time
       
   518                 // when install-notify timeout is active, that means that
       
   519                 // connection has closed prior to timer firing and we should
       
   520                 // not make content available to user, then handle the error
       
   521                 // normally after that
       
   522                 CLOG(( EHttpLoad, 2, _L("CHttpLoader::MHFRunL: aEvent.iStatus = KErrConnectionTerminated") ));
       
   523                 if( iINTimeout && iINTimeout->IsActive() )
       
   524                     {
       
   525                     CLOG(( EHttpLoad, 2, _L(" :install-notify timeout active: set iSuppressError=EFalse") ));
       
   526                     iINTimeout->Cancel();
       
   527                     iSuppressErrors = EFalse;
       
   528                     }
       
   529                 // finish handling error in MHFRunError
       
   530                 User::Leave( KErrConnectionTerminated ); 
       
   531                 }
       
   532             else if( aEvent.iStatus ==  KErrHttpPartialResponseReceived )
       
   533                 {
       
   534                 //Partial response has been received and connection has been disconnected. This error will be 
       
   535                 //propagated to the client only, if the HTTP:ENotifyOnDisconnect property is set with a value
       
   536                 //HTTP::EEnableDisconnectNotification
       
   537                 
       
   538                 //This error code was cancelling the pausable download. This error shud be ignored to keep the
       
   539                 //paused download.
       
   540                 //TSW Err ID : SXUU-77SRWL
       
   541                 
       
   542                 CLOG(( EHttpLoad, 2, _L("CHttpLoader::MHFRunL: aEvent.iStatus = KErrHttpPartialResponseReceived") ));
       
   543                 }                
       
   544             else
       
   545                 {
       
   546                 // Handle errors in MHFRunError.
       
   547                 User::LeaveIfError( aEvent.iStatus );
       
   548                 }
       
   549             break;
       
   550             }
       
   551         }
       
   552     CLOG(( EHttpLoad, 0, _L("<- CHttpLoader::MHFRunL") ));
       
   553     }
       
   554 
       
   555 // ---------------------------------------------------------
       
   556 // CHttpLoader::MHFRunError()
       
   557 // ---------------------------------------------------------
       
   558 //
       
   559 TInt CHttpLoader::MHFRunError
       
   560         (
       
   561         TInt aError,
       
   562         RHTTPTransaction DEBUG_ONLY( aTransaction ),
       
   563         const THTTPEvent& /*aEvent*/
       
   564         )
       
   565     {
       
   566     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::MHFRunError (%d)"), aError ));
       
   567     __ASSERT_DEBUG( aTransaction == iTrans, CodPanic( ECodInternal ) );
       
   568     __ASSERT_DEBUG( iState == ERequest, CodPanic( ECodOffState ) );
       
   569     CompleteTransaction( aError );
       
   570     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::MHFRunError") ));
       
   571     return KErrNone;
       
   572     }
       
   573 
       
   574 // ---------------------------------------------------------
       
   575 // CHttpLoader::GetNextDataPart()
       
   576 // ---------------------------------------------------------
       
   577 //
       
   578 TBool CHttpLoader::GetNextDataPart( TPtrC8& aDataPart )
       
   579     {
       
   580     __ASSERT_DEBUG( iNotifyBody, CodPanic( ECodInternal ) );
       
   581     aDataPart.Set( iNotifyBody->Des() );
       
   582     return ETrue;
       
   583     }
       
   584 
       
   585 // ---------------------------------------------------------
       
   586 // CHttpLoader::ReleaseData()
       
   587 // ---------------------------------------------------------
       
   588 //
       
   589 void CHttpLoader::ReleaseData()
       
   590     {
       
   591     // Do not delete iNotifyBody here. Reset() may be called and since we
       
   592     // do support it, we may need to provide the data again.
       
   593     // iNotifyBody will be deleted in Done(); that's a safe place.
       
   594     }
       
   595 
       
   596 // ---------------------------------------------------------
       
   597 // CHttpLoader::OverallDataSize()
       
   598 // ---------------------------------------------------------
       
   599 //
       
   600 TInt CHttpLoader::OverallDataSize()
       
   601     {
       
   602     __ASSERT_DEBUG( iNotifyBody, CodPanic( ECodInternal ) );
       
   603     return iNotifyBody->Des().Size();
       
   604     }
       
   605 
       
   606 // ---------------------------------------------------------
       
   607 // CHttpLoader::Reset()
       
   608 // ---------------------------------------------------------
       
   609 //
       
   610 TInt CHttpLoader::Reset()
       
   611     {
       
   612     return KErrNone;
       
   613     }
       
   614 
       
   615 // ---------------------------------------------------------
       
   616 // CHttpLoader::GetCredentialsL()
       
   617 // ---------------------------------------------------------
       
   618 //
       
   619 TBool CHttpLoader::GetCredentialsL
       
   620         (
       
   621         const TUriC8& aURI,
       
   622         RString aRealm, 
       
   623         RStringF /*aAuthenticationType*/,
       
   624         RString& aUsername, 
       
   625         RString& aPassword
       
   626         )
       
   627     {
       
   628     TBool ret( EFalse );
       
   629     if ( iCodLoadObserver )
       
   630         {
       
   631         // Unfortunately, everything has to be converted from 8 to 16 bit
       
   632         // and vice versa.
       
   633         HBufC* host = CodUtil::ConvertLC( aURI.UriDes() );
       
   634         HBufC* realm = CodUtil::ConvertLC( aRealm.DesC() );
       
   635         TBuf<KCodMaxAuthUserName> userName;
       
   636         TBuf<KCodMaxAuthPassword> password;
       
   637         ret = iCodLoadObserver->UserAuthL
       
   638             ( *host, *realm, EFalse, userName, password );
       
   639         CleanupStack::PopAndDestroy( 2 );   // realm, host
       
   640         HBufC8* userName8 = CodUtil::ConvertLC( userName );
       
   641         aUsername = iSess->Sess().StringPool().OpenStringL( *userName8 );
       
   642         CleanupStack::PopAndDestroy( userName8 );
       
   643         CleanupClosePushL<RString>( aUsername );
       
   644         HBufC8* password8 = CodUtil::ConvertLC( password );
       
   645         aPassword = iSess->Sess().StringPool().OpenStringL( *password8 );
       
   646         CleanupStack::PopAndDestroy( password8 );
       
   647         CleanupStack::Pop();    // closing aUsername
       
   648         }
       
   649     return ret;
       
   650     }
       
   651 
       
   652 // ---------------------------------------------------------
       
   653 // CHttpLoader::CHttpLoader()
       
   654 // ---------------------------------------------------------
       
   655 //
       
   656 CHttpLoader::CHttpLoader
       
   657         (
       
   658         CConnection& aConnection,
       
   659         MCodLoadObserver* aCodLoadObserver,
       
   660         TCodProgress* aProgress,
       
   661         CCodEngBase* aCodEng
       
   662         )
       
   663 : CActive( CActive::EPriorityStandard ),
       
   664   iMethod( HTTP::EGET ),
       
   665   iHttpVersion( HTTP::EHttp11 ),
       
   666   iConn( aConnection ),
       
   667   iCodLoadObserver( aCodLoadObserver ),
       
   668   iState( EInit ),
       
   669   iResult( KErrNone ),
       
   670   iSuppressErrors( EFalse ),
       
   671   iProxySet( EFalse ),
       
   672   iProgress( aProgress ),
       
   673   iRetry( KCodGetRetry ),
       
   674   iCodEng(aCodEng),
       
   675   iPausableDRM( ETrue )
       
   676     {
       
   677     CActiveScheduler::Add( this );
       
   678 	if (iCodLoadObserver)
       
   679 	{
       
   680 	iCodLoadObserver->SetConnError( KErrNone);
       
   681 	}
       
   682     CLOG(( EHttpLoad, 2, _L("*** CHttpLoader::CHttpLoader") ));
       
   683     }
       
   684 // ---------------------------------------------------------
       
   685 // CHttpLoader::ConstructL()
       
   686 // ---------------------------------------------------------
       
   687 //
       
   688 void CHttpLoader::ConstructL() 
       
   689     {
       
   690     iFeatMgr.OpenL();
       
   691     
       
   692 	iResponseHeaders = new (ELeave) CArrayPtrFlat<CHeaderField>(2);	
       
   693 	
       
   694     }
       
   695 
       
   696 // ---------------------------------------------------------
       
   697 // CHttpLoader::OpenSessionL
       
   698 // ---------------------------------------------------------
       
   699 //
       
   700 void CHttpLoader::OpenSessionL()
       
   701     {
       
   702     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::OpenSessionL") ));
       
   703 
       
   704     if( iSess )
       
   705         {
       
   706         // Already opened.
       
   707         // Synchronous state change - we are already under RunL.
       
   708         CLOG(( EHttpLoad, 3, _L("  already open") ));
       
   709         iState = EOpen;
       
   710         RequestL();
       
   711         }
       
   712     else
       
   713         {
       
   714         if ( iFeatMgr.FeatureSupported( KFeatureIdWsp ) )
       
   715             {
       
   716             CLOG(( EHttpLoad, 4, _L("  KFeatureIdWsp supported") ));
       
   717             TUint32 iap;
       
   718             if ( !iConn.IsConnected( iap ) )
       
   719                 {
       
   720                 CLOG(( EHttpLoad, 3, _L("  not connected, leaving") ));
       
   721                 User::Leave( KErrCodCannotConnect );
       
   722                 }
       
   723             HBufC8* gateway = CodUtil::WapGatewayL( iap );  // NULL if not WAP.
       
   724             CleanupStack::PushL( gateway );                 // Push NULL is OK.
       
   725             if ( gateway )
       
   726                 {
       
   727                 CLOG(( EHttpLoad, 4, _L("  AP has WAP gateway") ));
       
   728                 // We have a valid WAP gateway. Check WSP protocol
       
   729                 // availability.
       
   730                 CLOG(( EHttpLoad, 3, _L("  Protocols available:") ));
       
   731                 TInt i;
       
   732                 TPtrC8 protocol;
       
   733                 RPointerArray<HBufC8> protocols;
       
   734                 RHTTPSession::ListAvailableProtocolsL( protocols );
       
   735                 for( i = 0; i < protocols.Count(); i++ )
       
   736                     {
       
   737                     protocol.Set( protocols[i]->Des() );
       
   738                     CLOG(( EWapConn | ETcpConn, 3, _L8("  <%S>"), &protocol ));
       
   739                     if( !protocol.Compare( KCodWspProtocol ) )
       
   740                         {
       
   741                         // WSP available. Use a WAP session.
       
   742                         iSess = CHttpWapSession::NewL( *gateway );
       
   743                         break;
       
   744                         }
       
   745                     }
       
   746                 }
       
   747             CleanupStack::PopAndDestroy( gateway ); // NULL is OK.
       
   748             }
       
   749         if( !iSess )
       
   750             {
       
   751             // No valid WAP gateway or WSP not available - use TCP session.
       
   752             iSess = CHttpTcpSession::NewL();
       
   753             }
       
   754 
       
   755         SetupSessionL();
       
   756 
       
   757         iSess->ConnectL( &iStatus );
       
   758         iState = EOpen;
       
   759         SetActive();
       
   760         }
       
   761 
       
   762     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::OpenSessionL") ));
       
   763     }
       
   764 
       
   765 // ---------------------------------------------------------
       
   766 // CHttpLoader::RequestL()
       
   767 // ---------------------------------------------------------
       
   768 //
       
   769 void CHttpLoader::RequestL()
       
   770     {
       
   771     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::RequestL") ));
       
   772     __ASSERT_DEBUG( iState == EOpen, CodPanic( ECodOffState ) );
       
   773     __ASSERT_DEBUG( iSess, CodPanic( ECodInternal ) );
       
   774     if( !iTimeout )
       
   775         {
       
   776         iTimeout = CTimeout::NewL
       
   777             ( CActive::EPriorityStandard, TCallBack( StaticTimeout, this ) );
       
   778         }
       
   779     iHttpVersion = HTTP::EHttp11;
       
   780     CreateTransactionL();
       
   781     SubmitTransactionL();
       
   782     // Wait it out.
       
   783     // In ERequest state there is no other object that takes a request status
       
   784     // to complete. Instead, events come via MHF... callbacks, and there is
       
   785     // always a final event, when we complete our status manually.
       
   786     iState = ERequest;
       
   787     iStatus = KRequestPending;
       
   788     SetActive();
       
   789     StartTimeout(); // After state change! Timeout unexpected in other states.
       
   790     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::RequestL") ));
       
   791     }
       
   792 
       
   793 // ---------------------------------------------------------
       
   794 // CHttpLoader::Done()
       
   795 // ---------------------------------------------------------
       
   796 //
       
   797 void CHttpLoader::Done()
       
   798     {
       
   799     CLOG(( EHttpLoad, 2, \
       
   800         _L("-> CHttpLoader::Done iResult(%d) iSuppressErrors(%d)"), \
       
   801         iResult, iSuppressErrors ));
       
   802     if( iTimeout )
       
   803         {
       
   804         iTimeout->Cancel();
       
   805         }
       
   806     iTrans.Close();
       
   807     if( iProxySet && iSess )
       
   808         {
       
   809         // Remove proxy address property from session.
       
   810         RHTTPConnectionInfo connInfo = iSess->Sess().ConnectionInfo();
       
   811         connInfo.RemoveProperty( StringF( HTTP::EUseProxy ) );
       
   812         connInfo.RemoveProperty( StringF( HTTP::EProxyAddress ) );
       
   813         iProxySet = EFalse;
       
   814         }
       
   815     if ( iSaver )
       
   816         {
       
   817         iSaver->CloseStore();
       
   818         }
       
   819     if( iINTimeout )
       
   820         {
       
   821         iINTimeout->Cancel();
       
   822         }
       
   823     iSaverFactory = NULL;
       
   824     iSaver = NULL;
       
   825     delete iNotifyBody;
       
   826     iNotifyBody = NULL;
       
   827     delete iUri;
       
   828     iUri = NULL;
       
   829     iMethod = HTTP::EGET;
       
   830     if ( iSuppressErrors )
       
   831         {
       
   832         iResult = KErrNone;
       
   833         iSuppressErrors = EFalse;
       
   834         }
       
   835     // Notify parent.
       
   836     __ASSERT_DEBUG( iParentStatus, CodPanic( ECodInternal ) );
       
   837     User::RequestComplete( iParentStatus, iResult );
       
   838     iParentStatus = NULL;
       
   839     iState = EInit;
       
   840     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::Done") ));
       
   841     }
       
   842 
       
   843 // ---------------------------------------------------------
       
   844 // CHttpLoader::Continue
       
   845 // ---------------------------------------------------------
       
   846 //
       
   847 void CHttpLoader::Continue( TState aNextState )
       
   848     {
       
   849     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::Continue nextState(%d)"), \
       
   850         aNextState ));
       
   851     __ASSERT_DEBUG( !IsActive(), CodPanic( ECodInternal ) );
       
   852 
       
   853     iState = aNextState;
       
   854     TRequestStatus* ownStatus = &iStatus;
       
   855     *ownStatus = KRequestPending;
       
   856     SetActive();
       
   857     User::RequestComplete( ownStatus, KErrNone );
       
   858     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::Continue") ));
       
   859     }
       
   860 
       
   861 // ---------------------------------------------------------
       
   862 // CHttpLoader::SelfComplete
       
   863 // ---------------------------------------------------------
       
   864 //
       
   865 void CHttpLoader::SelfComplete( TInt aError )
       
   866     {
       
   867     // This method safely handles the case when a request may be completed
       
   868     // from more then one place.
       
   869     // The main use is for loading (ERequest state), where
       
   870     // there is no real external request made and the request can complete
       
   871     // the following ways:
       
   872     // - Transaction finished
       
   873     // - Error (MHFRunError())
       
   874     // - Cancel
       
   875     // - Timeout
       
   876     CLOG(( EHttpLoad, 2, _L("CHttpLoader::SelfComplete(%d)"), aError ));
       
   877     if ( iStatus == KRequestPending )
       
   878         {
       
   879         // Request is pending, complete now.
       
   880         CLOG(( EHttpLoad, 4, _L("  completing now") ));
       
   881         TRequestStatus* ownStatus = &iStatus;
       
   882         User::RequestComplete( ownStatus, aError );
       
   883         }
       
   884     else
       
   885         {
       
   886         // Request already completed.
       
   887         // - If this second completion is error, override status.
       
   888         // - If this second completion is success, don't override - existing
       
   889         //   result may be error and we can't undo that.
       
   890         CLOG(( EHttpLoad, 4, _L("  already completed") ));
       
   891         if ( aError != KErrNone )
       
   892             {
       
   893             iStatus = aError;
       
   894             }
       
   895         }
       
   896     }
       
   897 // -----------------------------------------------------------------------------
       
   898 // CHttpLoader::SetRequestHeaderL
       
   899 // ?implementation_description
       
   900 // (other items were commented in a header).
       
   901 // -----------------------------------------------------------------------------
       
   902 //
       
   903 void CHttpLoader::SetRequestHeaderL( RStringPool& aStringPool,
       
   904                                        RHTTPHeaders& aHeaders)
       
   905     {
       
   906     // Set default Accept header
       
   907     SetHeaderL( aHeaders, HTTP::EAccept, HTTP::EAnyAny );
       
   908 
       
   909     // Some wap gateways update their database of MMS capable devices
       
   910     // *each time* the phone accesses the gateway. If these accept header is
       
   911     // only */* in content download, then the database will be updated so that
       
   912     // the terminal cannot receive MMS messages. As a result, MMS notifications
       
   913     // will not be sent to the phone and the user never receives MMS messages.
       
   914     // Overcome: add MMS and SI content types explicitly.
       
   915     SetHeaderL( aHeaders, HTTP::EAccept, KCodAcceptMmsHeaderValue );
       
   916     SetHeaderL( aHeaders, HTTP::EAccept, KCodAcceptSiHeaderValue );
       
   917     
       
   918     if ( iMethod == HTTP::EPOST )
       
   919         {
       
   920         // Content type header and body for POST.
       
   921         SetHeaderL( aHeaders, HTTP::EContentType, HTTP::ETextPlain );
       
   922         iTrans.Request().SetBody( *this );
       
   923         }
       
   924 
       
   925     // Find ETag in response header
       
   926     RStringF etag = aStringPool.StringF(HTTP::EETag, RHTTPSession::GetTable());
       
   927     TInt fieldInd = FindHeaderField( iResponseHeaders, etag.DesC() );
       
   928     
       
   929     if( fieldInd != KErrNotFound )
       
   930         // ETag is known. ETag identifies the content. Set If-Match to see
       
   931         // that if it's changed, or a redirection goes to another url.
       
   932         // Server will respond with 412 on error.
       
   933         {
       
   934         RStringF ifMatch = aStringPool.StringF(HTTP::EIfMatch, RHTTPSession::GetTable());
       
   935         aHeaders.RemoveField( ifMatch );
       
   936         aHeaders.SetRawFieldL( ifMatch, 
       
   937                                *(*iResponseHeaders)[fieldInd]->FieldRawData(), 
       
   938                                KHttpFieldSeparator );
       
   939         }
       
   940 
       
   941     SetRangeFieldL( aStringPool, aHeaders );
       
   942     }
       
   943 // ---------------------------------------------------------
       
   944 // CHttpLoader::CreateTransactionL()
       
   945 // ---------------------------------------------------------
       
   946 //
       
   947 void CHttpLoader::CreateTransactionL()
       
   948     {
       
   949     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::CreateTransactionL") ));
       
   950     __ASSERT_DEBUG( iUri, CodPanic( ECodInternal ) );
       
   951     __ASSERT_DEBUG( iMethod == HTTP::EGET || iMethod == HTTP::EPOST, \
       
   952         CodPanic( ECodInternal ) );
       
   953 
       
   954 #ifdef __TEST_COD_LOG
       
   955     TPtrC8 uriDes( iUri->Des() );
       
   956     CLOG(( EHttpLoad, 4, _L8("  method<%S> URI<%S>"), \
       
   957         &StringF( iMethod ).DesC(), &uriDes ));
       
   958 #endif /* def __TEST_COD_LOG */
       
   959 
       
   960     // Create the transaction.
       
   961     TUriParser8 uri; 
       
   962     User::LeaveIfError( uri.Parse( *iUri ) );
       
   963 
       
   964     // escape the uri for characters defined in KUriEscChars
       
   965     HBufC8* escUri = NULL;
       
   966     TRAPD( err, escUri = EscapeUtils::SpecificEscapeEncodeL(*iUri, KUriEscChars) );
       
   967     if( err == KErrNone )
       
   968         {
       
   969         // switch buffers to use the the escape-encoded version
       
   970         delete iUri;
       
   971         iUri = escUri;
       
   972         User::LeaveIfError( uri.Parse( *iUri ) );
       
   973         }
       
   974     else
       
   975         {
       
   976         // if encoding function leaves, perform cleanup for safety
       
   977         // and attempt to continue with request
       
   978         delete escUri;  
       
   979         }
       
   980     iTrans = iSess->Sess().OpenTransactionL( uri, *this, StringF( iMethod ) );
       
   981 
       
   982     // Set request headers.
       
   983     RHTTPHeaders hdr = iTrans.Request().GetHeaderCollection();
       
   984     
       
   985     RStringPool strPool = iSess->Sess().StringPool();
       
   986     SetRequestHeaderL(strPool, hdr);
       
   987         
       
   988     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::CreateTransactionL") ));
       
   989     }
       
   990 
       
   991 // ---------------------------------------------------------
       
   992 // CHttpLoader::SubmitTransactionL()
       
   993 // ---------------------------------------------------------
       
   994 //
       
   995 void CHttpLoader::SubmitTransactionL()
       
   996     {
       
   997 #ifdef __TEST_COD_LOG
       
   998     CLOG(( EHttpLoad, 0, _L("-> CHttpLoader::SubmitTransactionL") ));
       
   999     RHTTPRequest req = iTrans.Request();
       
  1000     TPtrC8 method( req.Method().DesC() );
       
  1001     TPtrC8 uri( req.URI().UriDes() );
       
  1002     CLOG(( EHttpLoad, 0, _L8("  method<%S> URI<%S>"), &method, &uri ));
       
  1003     LogHeaders( req.GetHeaderCollection() );
       
  1004 #endif /* def __TEST_COD_LOG */
       
  1005 #ifdef _DEBUG
       
  1006     HBufC* method16 = CodUtil::ConvertLC( iTrans.Request().Method().DesC() );
       
  1007     User::InfoPrint( *method16 );
       
  1008     CleanupStack::PopAndDestroy( method16 );
       
  1009 #endif
       
  1010 
       
  1011     if( !IsConnectionActive() )
       
  1012         {
       
  1013         User::Leave( KErrCodHttpCommsFailed );
       
  1014         }
       
  1015     CLOG(( EHttpLoad, 0, _L(" :calling RHttpTransaction.SubmitL()") ));
       
  1016     iTrans.SubmitL();
       
  1017     if( iMethod == HTTP::EPOST ) // ie, install-notify
       
  1018         {
       
  1019         if( !iINTimeout )
       
  1020             {
       
  1021             iINTimeout = CTimeout::NewL
       
  1022                          ( CActive::EPriorityStandard, TCallBack( INStaticTimeout, this ) );
       
  1023             }
       
  1024         CLOG(( EHttpLoad, 1, _L(" :starting iINTimeout with timeout of %d microsecs"), KCodINTimeout ));
       
  1025         TTimeIntervalMicroSeconds32 inTimeout = KCodINTimeout;
       
  1026         iINTimeout->After( inTimeout );
       
  1027         }
       
  1028     CLOG(( EHttpLoad, 0, _L("<- CHttpLoader::SubmitTransactionL") ));
       
  1029     }
       
  1030 
       
  1031 // ---------------------------------------------------------
       
  1032 // CHttpLoader::CompleteTransaction()
       
  1033 // ---------------------------------------------------------
       
  1034 //
       
  1035 void CHttpLoader::CompleteTransaction( TInt aError )
       
  1036     {
       
  1037     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::CompleteTransaction(%d)"), \
       
  1038         aError ));
       
  1039     __ASSERT_DEBUG( iState == ERequest, CodPanic( ECodOffState ) );
       
  1040     iTrans.Close();
       
  1041     iResult = aError;
       
  1042     SelfComplete( iResult );
       
  1043     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::CompleteTransaction") ));
       
  1044     }
       
  1045 
       
  1046 // ---------------------------------------------------------
       
  1047 // CHttpLoader::RestartTransaction()
       
  1048 // ---------------------------------------------------------
       
  1049 //
       
  1050 void CHttpLoader::RestartTransaction()
       
  1051     {
       
  1052     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::RestartTransaction")));
       
  1053     __ASSERT_DEBUG( iState == ERequest, CodPanic( ECodOffState ) );
       
  1054     
       
  1055     iState = EStart;
       
  1056     CompleteTransaction(KErrNone);
       
  1057     
       
  1058     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::CompleteTransaction") ));
       
  1059     }
       
  1060 
       
  1061 
       
  1062 // ---------------------------------------------------------
       
  1063 // CHttpLoader::AcceptRangesSupported()
       
  1064 // ---------------------------------------------------------
       
  1065 //
       
  1066 TBool CHttpLoader::AcceptRangesSupported()
       
  1067 	{
       
  1068     RStringF range = iSess->Sess().StringPool().StringF(HTTP::EAcceptRanges, RHTTPSession::GetTable());
       
  1069     THTTPHdrVal value;
       
  1070     
       
  1071     TInt index = FindHeaderField(iResponseHeaders, range.DesC());
       
  1072     
       
  1073     if( index  != KErrNotFound ) 
       
  1074         {
       
  1075         if( !(*iResponseHeaders)[index]->FieldRawData()->Compare( KAcceptRangeHeader() ) )
       
  1076             {
       
  1077             return ETrue;
       
  1078             }
       
  1079         }
       
  1080         
       
  1081     return EFalse;    
       
  1082 	}
       
  1083 
       
  1084 // ---------------------------------------------------------
       
  1085 // CHttpLoader::HandleResponseHeadersL()
       
  1086 // ---------------------------------------------------------
       
  1087 //
       
  1088 void CHttpLoader::HandleResponseHeadersL( RHTTPResponse aResponse )
       
  1089     {
       
  1090     CLOG(( EHttpLoad, 0, _L("-> CHttpLoader::HandleResponseHeadersL") ));
       
  1091     TInt httpCode = aResponse.StatusCode();
       
  1092 #ifdef __TEST_COD_LOG
       
  1093     CLOG(( EHttpLoad, 0, _L8("  HttpStatus(%d) <%S>"), \
       
  1094         httpCode, &(aResponse.StatusText().DesC()) ));
       
  1095     LogHeaders( aResponse.GetHeaderCollection() );
       
  1096 #endif /* def __TEST_COD_LOG */
       
  1097 
       
  1098     if ( HTTPStatus::IsInformational( httpCode ) )
       
  1099         {
       
  1100         // 1xx
       
  1101         // Informational messages. Do nothing.
       
  1102         }
       
  1103     else if ( httpCode == HTTPStatus::EOk ||
       
  1104               httpCode == HTTPStatus::ENonAuthoritativeInfo ||
       
  1105               httpCode == HTTPStatus::EPartialContent
       
  1106             )
       
  1107         {
       
  1108         // 200 OK
       
  1109         // 203 Non-Authoritative Information
       
  1110         iResult = KErrNone;
       
  1111         if ( iMethod == HTTP::EGET )
       
  1112             {
       
  1113             // Successful GET. Get a saver.
       
  1114             __ASSERT_DEBUG( iSaverFactory, CodPanic( ECodInternal ) );
       
  1115 
       
  1116             if(!iSaver)
       
  1117                 {
       
  1118                 iSaver = iSaverFactory->CreateSaverL( GetContentTypeL( aResponse.GetHeaderCollection() ) );
       
  1119                 iSaver->SetSourceUriL( GetSourceUriL( iTrans ) );
       
  1120                 }
       
  1121             if(httpCode != HTTPStatus::EPartialContent)
       
  1122                 {
       
  1123                 if( !iProgress->CurrentValue() )
       
  1124                     {
       
  1125                     iSaver->ResetL();
       
  1126                     iProgress->SetAmountL(1024);    
       
  1127                     }                
       
  1128                 }
       
  1129             CheckRealDRMContentTypeL();
       
  1130            	iCodEng->SetPausable(AcceptRangesSupported() && iCodEng->Pausable());
       
  1131 
       
  1132             // If we know the size, check it is valid and preallocate buffer
       
  1133             // for content.
       
  1134             if ( aResponse.HasBody() )
       
  1135                 {
       
  1136                 TInt dataSize = aResponse.Body()->OverallDataSize();
       
  1137                 if ( dataSize >= 0 )
       
  1138                     {
       
  1139                     // Content size is known. Check if fits.
       
  1140                     User::LeaveIfError( iSaver->CheckMaxSize( dataSize ) );
       
  1141                     }
       
  1142                 }
       
  1143                 iCodEng->SetResumePDAvailable();
       
  1144             }
       
  1145         else
       
  1146             {
       
  1147             // Successful POST.
       
  1148             // Do nothing.
       
  1149             }
       
  1150         }
       
  1151     else if ( HTTPStatus::IsSuccessful( httpCode ) )
       
  1152         {
       
  1153         // 2xx
       
  1154         // Success codes without an usable body.
       
  1155         // For GET, it is a failure; for POST it's OK
       
  1156         iResult = (iMethod == HTTP::EGET) ? KErrCodHttpNoResponse : KErrNone;
       
  1157         }
       
  1158     // 3xx codes handled by redirect filter.
       
  1159     else if ( httpCode == HTTPStatus::EUnauthorized ||
       
  1160               httpCode == HTTPStatus::EProxyAuthenticationRequired )
       
  1161         {
       
  1162         // 401 Unauthorized
       
  1163         // 407 Proxy authentication required
       
  1164         iResult = KErrCodHttpAuthFailed;
       
  1165         }
       
  1166     else if ( httpCode == HTTPStatus::ENotFound ||
       
  1167               httpCode == HTTPStatus::EGone )
       
  1168         {
       
  1169         // 404 Not found
       
  1170         // 410 Gone
       
  1171         iResult = KErrCodHttpBadUrl;
       
  1172         
       
  1173         // Cancel the download if bad url.
       
  1174         // Set pausable status to false.
       
  1175         iCodEng->SetPausable( EFalse );
       
  1176         }
       
  1177         
       
  1178     else if ( httpCode == HTTPStatus::ERequestedRangeNotSatisfiable )
       
  1179         {
       
  1180         //416 Requested Range Not Satisfiable. Download has to be cancelled.
       
  1181         iResult = KErrCodHttpRequestedRangeNotSatisfiable;
       
  1182         }
       
  1183     else if( httpCode == HTTPStatus::EPreconditionFailed )        
       
  1184         {
       
  1185         // Re init the download
       
  1186         if(iSaver)
       
  1187             {
       
  1188             iSaver->ResetL();
       
  1189             iProgress->SetAmountL(0);
       
  1190             }
       
  1191         CompleteTransaction( KErrCodHttpPreconditionFailed );
       
  1192         }
       
  1193     else if ( HTTPStatus::IsClientError( httpCode ) )
       
  1194         {
       
  1195         // 4xx
       
  1196         iResult = KErrCodHttpUnavailable;
       
  1197         }
       
  1198     else if ( httpCode == HTTPStatus::EHTTPVersionNotSupported )
       
  1199         {
       
  1200         // 505 HTTP Version Not Supported
       
  1201         // Retry with lower HTTP version if we can.
       
  1202         iResult = VersionRetryL() ? KErrNone : KErrCodHttpUnavailable;
       
  1203         }
       
  1204     else if ( HTTPStatus::IsServerError( httpCode ) )
       
  1205         {
       
  1206         // 5xx
       
  1207         // HTTP/1.0 servers may return other 5xx error codes for HTTP/1.1
       
  1208         // requests. So the same treatment  is given for all 5xx errors
       
  1209         // (version retry) - it's worth a try.
       
  1210         iResult = VersionRetryL() ? KErrNone : KErrCodHttpServerError;
       
  1211         }
       
  1212     else
       
  1213         {
       
  1214         // Everything else.
       
  1215         iResult = KErrCodHttpBadResponse;
       
  1216         }
       
  1217     CLOG(( EHttpLoad, 0, _L("<- CHttpLoader::HandleResponseHeadersL") ));
       
  1218     }
       
  1219 
       
  1220 // ---------------------------------------------------------
       
  1221 // CHttpLoader::VersionRetryL()
       
  1222 // ---------------------------------------------------------
       
  1223 //
       
  1224 TBool CHttpLoader::VersionRetryL()
       
  1225     {
       
  1226     CLOG(( EHttpLoad, 2, \
       
  1227         _L8("-> CHttpLoader::VersionRetryL iHttpVersion <%S>"), \
       
  1228         &(StringF( iHttpVersion ).DesC() ) ));
       
  1229 
       
  1230     // We should be in ERequest state, with the request outstanding.
       
  1231     __ASSERT_DEBUG( iState == ERequest, CodPanic( ECodInternal ) );
       
  1232     __ASSERT_DEBUG( iStatus == KRequestPending, CodPanic( ECodInternal ) );
       
  1233     __ASSERT_DEBUG( IsActive(), CodPanic( ECodInternal ) );
       
  1234 
       
  1235     TBool retryDone( EFalse );
       
  1236     if ( iHttpVersion == HTTP::EHttp11 )
       
  1237         {
       
  1238         // Currently using HTTP/1.1. Cancel transaction and resubmit it using
       
  1239         // HTTP/1.0.
       
  1240         iTrans.Cancel();
       
  1241         iSess->Sess().ConnectionInfo().SetPropertyL
       
  1242             (
       
  1243             StringF( HTTP::EHTTPVersion ),
       
  1244             THTTPHdrVal( StringF( HTTP::EHttp10 ) )
       
  1245             );
       
  1246         iHttpVersion = HTTP::EHttp10;
       
  1247         SubmitTransactionL();
       
  1248         retryDone = ETrue;
       
  1249         }
       
  1250     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::VersionRetryL return(0x%x)"), \
       
  1251         retryDone ));
       
  1252     return retryDone;
       
  1253     }
       
  1254 
       
  1255 // ---------------------------------------------------------
       
  1256 // CHttpLoader::UseProxyL()
       
  1257 // ---------------------------------------------------------
       
  1258 //
       
  1259 TBool CHttpLoader::UseProxyL()
       
  1260     {
       
  1261     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::UseProxyL iProxySet(0x%x)"), \
       
  1262         iProxySet ));
       
  1263 
       
  1264     // We should be in ERequest state, with the request outstanding.
       
  1265     __ASSERT_DEBUG( iState == ERequest, CodPanic( ECodInternal ) );
       
  1266     __ASSERT_DEBUG( iStatus == KRequestPending, CodPanic( ECodInternal ) );
       
  1267     __ASSERT_DEBUG( IsActive(), CodPanic( ECodInternal ) );
       
  1268     __ASSERT_DEBUG( iTrans.Response().StatusCode() == HTTPStatus::EUseProxy, \
       
  1269         CodPanic( ECodInvalidArguments ) );
       
  1270 
       
  1271     // First check if we already have a proxy address set. If yes, do not set
       
  1272     // another.
       
  1273     if( !iProxySet )
       
  1274         {
       
  1275         TBool proxySet( EFalse );   // Set by somebody else (?).
       
  1276         RStringF proxyUsage = StringF( HTTP::EProxyUsage );
       
  1277         RStringF useProxy = StringF( HTTP::EUseProxy );
       
  1278         RHTTPConnectionInfo connInfo = iSess->Sess().ConnectionInfo();
       
  1279         THTTPHdrVal val;
       
  1280         if( connInfo.Property( proxyUsage, val ) )
       
  1281             {
       
  1282             if( val.Type() != THTTPHdrVal::KStrFVal )
       
  1283                 {
       
  1284                 User::Leave( KErrCodHttpBadResponse );
       
  1285                 }
       
  1286             if( val.StrF() == useProxy )
       
  1287                 {
       
  1288                 proxySet = ETrue;
       
  1289                 CLOG(( EHttpLoad, 2, _L("  proxy already set") ));
       
  1290                 }
       
  1291             }
       
  1292         if( !proxySet )
       
  1293             {
       
  1294             // No proxy is currently set. Get the proxy address to set, from
       
  1295             // the Location header field.
       
  1296             RHTTPHeaders headers = iTrans.Response().GetHeaderCollection();
       
  1297             if( !headers.GetField( StringF( HTTP::ELocation ), 0, val ) )
       
  1298                 {
       
  1299                 if( val.Type() != THTTPHdrVal::KStrFVal )
       
  1300                     {
       
  1301                     User::Leave( KErrCodHttpBadResponse );
       
  1302                     }
       
  1303                 // Cancel the transaction and resubmit after the proxy was set.
       
  1304                 CLOG(( EHttpLoad, 2, _L8("  setting proxy <%S>"), \
       
  1305                     &(val.StrF().DesC()) ));
       
  1306                 iTrans.Cancel();
       
  1307                 connInfo.SetPropertyL( StringF( HTTP::EProxyAddress ), val );
       
  1308                 connInfo.SetPropertyL( proxyUsage, THTTPHdrVal( useProxy ) );
       
  1309                 SubmitTransactionL();
       
  1310                 iProxySet = ETrue;
       
  1311                 }
       
  1312             }
       
  1313         }
       
  1314     CLOG(( EHttpLoad, 2, \
       
  1315         _L("<- CHttpLoader::UseProxyL return iProxySet(0x%x)"), iProxySet ));
       
  1316     return iProxySet;
       
  1317     }
       
  1318 
       
  1319 // ---------------------------------------------------------
       
  1320 // CHttpLoader::SetupSessionL()
       
  1321 // ---------------------------------------------------------
       
  1322 //
       
  1323 void CHttpLoader::SetupSessionL()
       
  1324     {
       
  1325     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::SetupSessionL") ));
       
  1326     // Set our Socket Server handle and Connection as session properties.
       
  1327     iSess->Sess().ConnectionInfo().SetPropertyL
       
  1328         (
       
  1329         StringF( HTTP::EHttpSocketServ ),
       
  1330         THTTPHdrVal( iConn.SockServ().Handle() )
       
  1331         );
       
  1332     iSess->Sess().ConnectionInfo().SetPropertyL
       
  1333         (
       
  1334         StringF( HTTP::EHttpSocketConnection ),
       
  1335         THTTPHdrVal( REINTERPRET_CAST( TInt, &iConn.Conn() ) )
       
  1336         );
       
  1337 
       
  1338     // Set the disconnect notification 
       
  1339     iSess->Sess().ConnectionInfo().SetPropertyL
       
  1340         (
       
  1341         iSess->Sess().StringPool().StringF( HTTP::ENotifyOnDisconnect, RHTTPSession::GetTable() ), 
       
  1342         iSess->Sess().StringPool().StringF( HTTP::EEnableDisconnectNotification, RHTTPSession::GetTable() )
       
  1343         ); 
       
  1344 
       
  1345     CLOG(( EHttpLoad, 4, _L("  Install UAProf filter...") ));
       
  1346     // Install UAProf filter.
       
  1347     CHttpUAProfFilterInterface::InstallFilterL( iSess->Sess() );
       
  1348 
       
  1349     CLOG(( EHttpLoad, 4, _L("  Install Cookie filter...") ));
       
  1350     // Install cookie filter.
       
  1351     CHttpCookieFilter::InstallFilterL( iSess->Sess() );
       
  1352 
       
  1353     CLOG(( EHttpLoad, 4, _L("  Install Auth filter...") ));
       
  1354     // Install authentication filter.
       
  1355     InstallAuthenticationL( iSess->Sess() );
       
  1356 
       
  1357     CLOG(( EHttpLoad, 4, _L("  Install Deflate filter...") ));
       
  1358     // Install deflate Filter.
       
  1359     CHttpDeflateFilter::InstallFilterL( iSess->Sess() );
       
  1360 
       
  1361     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::SetupSessionL") ));
       
  1362     }
       
  1363 
       
  1364 // ---------------------------------------------------------
       
  1365 // CHttpLoader::StartTimeout()
       
  1366 // ---------------------------------------------------------
       
  1367 //
       
  1368 void CHttpLoader::StartTimeout()
       
  1369     {
       
  1370     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::StartTimeout") ));
       
  1371     __ASSERT_DEBUG( iState == ERequest, CodPanic( ECodOffState ) );
       
  1372     __ASSERT_DEBUG( iTimeout, CodPanic( ECodInternal ) );
       
  1373     TTimeIntervalMicroSeconds32 timeout = 
       
  1374         iMethod == HTTP::EGET ? KCodGetTimeout : KCodPostTimeout;
       
  1375     iTimeout->Cancel();         // Cancel pending (if any).
       
  1376     iTimeout->After( timeout ); // Start over.
       
  1377     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::StartTimeout (%d microsecs)"), \
       
  1378         timeout.Int() ));
       
  1379     }
       
  1380 
       
  1381 // ---------------------------------------------------------
       
  1382 // CHttpLoader::Timeout()
       
  1383 // ---------------------------------------------------------
       
  1384 //
       
  1385 void CHttpLoader::Timeout()
       
  1386     {
       
  1387     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::Timeout iRetry(%d)"), iRetry ));
       
  1388     __ASSERT_DEBUG( iState == ERequest, CodPanic( ECodOffState ) );
       
  1389     if ( --iRetry > 0 )
       
  1390         {
       
  1391         CompleteTransaction( KErrNone );    // Close (abandon) transaction.
       
  1392         iState = EOpen;                     // To RequestL() by self-complete.
       
  1393         }
       
  1394     else
       
  1395         {
       
  1396 		if (iCodLoadObserver)
       
  1397 			{
       
  1398 			iCodLoadObserver->SetConnError( KErrTimedOut);
       
  1399 			}
       
  1400         CompleteTransaction( KErrTimedOut );
       
  1401         }
       
  1402     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::Timeout") ));
       
  1403     }
       
  1404 
       
  1405 // ---------------------------------------------------------
       
  1406 // CHttpLoader::INTimeout()
       
  1407 // ---------------------------------------------------------
       
  1408 //
       
  1409 void CHttpLoader::INTimeout()
       
  1410     {
       
  1411     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::INTimeout") ));
       
  1412     __ASSERT_DEBUG( iState == ERequest, CodPanic( ECodOffState ) );
       
  1413     iSuppressErrors = ETrue;    // release content to user 
       
  1414     if( !IsConnectionActive() )
       
  1415         {
       
  1416         iSuppressErrors = EFalse;         // do not release content
       
  1417         iResult = KErrCodHttpCommsFailed; // set error code
       
  1418         }
       
  1419     CLOG(( EHttpLoad, 2, _L(" :iSuppressErrors = %d"), iSuppressErrors ));
       
  1420     CLOG(( EHttpLoad, 2, _L(" :iResult = %d"), iResult ));
       
  1421     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::INTimeout") ));
       
  1422     }
       
  1423 
       
  1424 // ---------------------------------------------------------
       
  1425 // CHttpLoader::IncProgressL()
       
  1426 // ---------------------------------------------------------
       
  1427 //
       
  1428 void CHttpLoader::IncProgressL( TInt aSize )
       
  1429     {
       
  1430     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::IncProgressL(%d)"), aSize ));
       
  1431     if ( iProgress )
       
  1432         {
       
  1433         iProgress->IncrementL( aSize );
       
  1434         }
       
  1435     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::IncProgressL") ));
       
  1436     }
       
  1437 
       
  1438 // ---------------------------------------------------------
       
  1439 // CHttpLoader::SetHeaderL()
       
  1440 // ---------------------------------------------------------
       
  1441 //
       
  1442 void CHttpLoader::SetHeaderL
       
  1443 ( RHTTPHeaders aHeaders, HTTP::TStrings aHdrField, const TDesC8& aHdrValue )
       
  1444     {
       
  1445     RStringF valStr = iSess->Sess().StringPool().OpenFStringL( aHdrValue );
       
  1446     CleanupClosePushL<RStringF>( valStr );
       
  1447     SetHeaderL( aHeaders, aHdrField, valStr );
       
  1448     CleanupStack::PopAndDestroy();  // close valStr
       
  1449     }
       
  1450 
       
  1451 // ---------------------------------------------------------
       
  1452 // CHttpLoader::SetHeaderL()
       
  1453 // ---------------------------------------------------------
       
  1454 //
       
  1455 void CHttpLoader::SetHeaderL
       
  1456 ( RHTTPHeaders aHeaders, HTTP::TStrings aHdrField, HTTP::TStrings aHdrValue )
       
  1457     {
       
  1458     SetHeaderL( aHeaders, aHdrField, StringF( aHdrValue ) );
       
  1459     }
       
  1460 
       
  1461 // ---------------------------------------------------------
       
  1462 // CHttpLoader::SetHeaderL()
       
  1463 // ---------------------------------------------------------
       
  1464 //
       
  1465 void CHttpLoader::SetHeaderL
       
  1466 ( RHTTPHeaders aHeaders, HTTP::TStrings aHdrField, const RStringF aHdrValue )
       
  1467     {
       
  1468     CLOG(( EHttpLoad, 2, _L8("CHttpLoader::SetHeaderL <%S> <%S>"), \
       
  1469         &StringF( aHdrField ).DesC(), &aHdrValue.DesC() ));
       
  1470     THTTPHdrVal val( aHdrValue );
       
  1471     aHeaders.SetFieldL( StringF( aHdrField ), val );
       
  1472     }
       
  1473 
       
  1474 // ---------------------------------------------------------
       
  1475 // CHttpLoader::GetContentTypeL()
       
  1476 // ---------------------------------------------------------
       
  1477 //
       
  1478 const TDesC8& CHttpLoader::GetContentTypeL( RHTTPHeaders aHeaders )
       
  1479     {
       
  1480     THTTPHdrVal hdrVal;
       
  1481     User::LeaveIfError
       
  1482         ( aHeaders.GetField( StringF( HTTP::EContentType ), 0, hdrVal ) );
       
  1483     if( hdrVal.Type() != THTTPHdrVal::KStrFVal )
       
  1484         {
       
  1485         User::Leave( KErrCodHttpBadResponse );
       
  1486         }
       
  1487     return hdrVal.StrF().DesC();
       
  1488     }
       
  1489 
       
  1490 // ---------------------------------------------------------
       
  1491 // CHttpLoader::GetContentTypeL()
       
  1492 // ---------------------------------------------------------
       
  1493 //
       
  1494 const TDesC8& CHttpLoader::GetContentTypeL()
       
  1495     {
       
  1496     _LIT8(KContentType, "Content-Type");
       
  1497 
       
  1498     THTTPHdrVal value;
       
  1499     
       
  1500     TInt index = FindHeaderField(iResponseHeaders, KContentType);
       
  1501     
       
  1502     if( index  != KErrNotFound ) 
       
  1503         {
       
  1504         HBufC8 *ptr = (*iResponseHeaders)[index]->FieldRawData();
       
  1505         return *ptr;
       
  1506         }
       
  1507 
       
  1508     return KNullDesC8;
       
  1509     }
       
  1510 
       
  1511 // ---------------------------------------------------------
       
  1512 // CHttpLoader::GetSourceUriL()
       
  1513 // ---------------------------------------------------------
       
  1514 //
       
  1515 const TDesC8& CHttpLoader::GetSourceUriL( RHTTPTransaction aTransaction )
       
  1516     {
       
  1517     // TODO if redirected URI exists, how do we get it?
       
  1518     // For the moment request URI is used.
       
  1519     return aTransaction.Request().URI().UriDes();
       
  1520     }
       
  1521 
       
  1522 // ---------------------------------------------------------
       
  1523 // CHttpLoader::StaticTimeout()
       
  1524 // ---------------------------------------------------------
       
  1525 //
       
  1526 TInt CHttpLoader::StaticTimeout( TAny* aPtr )
       
  1527     {
       
  1528     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::StaticTimeout") ));
       
  1529     STATIC_CAST( CHttpLoader*, aPtr )->Timeout();
       
  1530     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::StaticTimeout") ));
       
  1531     return EFalse;
       
  1532     }
       
  1533 
       
  1534 // ---------------------------------------------------------
       
  1535 // CHttpLoader::INStaticTimeout()
       
  1536 // ---------------------------------------------------------
       
  1537 //
       
  1538 TInt CHttpLoader::INStaticTimeout( TAny* aPtr )
       
  1539     {
       
  1540     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::INStaticTimeout") ));
       
  1541     STATIC_CAST( CHttpLoader*, aPtr )->INTimeout();
       
  1542     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::INStaticTimeout") ));
       
  1543     return EFalse;
       
  1544     }
       
  1545 
       
  1546 
       
  1547 // ---------------------------------------------------------
       
  1548 // CHttpLoader::IsConnectionActive()
       
  1549 // ---------------------------------------------------------
       
  1550 //
       
  1551 TBool CHttpLoader::IsConnectionActive()
       
  1552     {
       
  1553     CLOG(( EHttpLoad, 2, _L("-> CHttpLoader::IsConnectionActive") ));
       
  1554 
       
  1555     THTTPHdrVal val;
       
  1556     TBool active( ETrue );
       
  1557     TBool hasProp = iSess->Sess().ConnectionInfo().Property
       
  1558         ( StringF( HTTP::EHttpSocketConnection ), val );
       
  1559     if( hasProp && val.Type() == THTTPHdrVal::KTIntVal)
       
  1560         {
       
  1561         active = ( val.Int() != NULL );
       
  1562         CLOG(( EHttpLoad, 0, _L(" :RConnection found = %d"), active ));
       
  1563         }    
       
  1564 
       
  1565     if( active ) // confirm with second level check
       
  1566         {
       
  1567         TUint32 iap;
       
  1568         active = iConn.IsConnected( iap );
       
  1569         CLOG(( EHttpLoad, 3, _L(" :CConnection.IsConnection() = %d"), active ));
       
  1570         }
       
  1571     CLOG(( EHttpLoad, 2, _L("<- CHttpLoader::IsConnectionActive") ));
       
  1572     return active;
       
  1573     }
       
  1574     
       
  1575 // -----------------------------------------------------------------------------
       
  1576 // CHttpDownload::StoreResponseHeaderL
       
  1577 // ?implementation_description
       
  1578 // (other items were commented in a header).
       
  1579 // -----------------------------------------------------------------------------
       
  1580 //
       
  1581 void CHttpLoader::StoreResponseHeaderL()
       
  1582 	{
       
  1583 
       
  1584     TPtrC8 rawData;
       
  1585     RStringPool strPool = iSess->Sess().StringPool();
       
  1586 
       
  1587     RHTTPHeaders headers( iTrans.Response().GetHeaderCollection() );
       
  1588     THTTPHdrFieldIter it = headers.Fields();
       
  1589 
       
  1590     // forget the previous headers
       
  1591     iResponseHeaders->ResetAndDestroy();
       
  1592     
       
  1593     while ( !it.AtEnd() )
       
  1594         {
       
  1595         RStringTokenF fieldName = it();
       
  1596         RStringF fieldNameStr = strPool.StringF (fieldName );
       
  1597 
       
  1598         headers.GetRawField( fieldNameStr, rawData );
       
  1599 
       
  1600         CHeaderField* field = CHeaderField::NewL( &fieldNameStr.DesC(), &rawData );
       
  1601         CleanupStack::PushL( field );
       
  1602 
       
  1603         iResponseHeaders->AppendL( field );
       
  1604 
       
  1605         CleanupStack::Pop( field );
       
  1606 
       
  1607         ++it;
       
  1608         }    
       
  1609 
       
  1610     //ParseContentTypeL( strPool );
       
  1611 
       
  1612     RStringF length = strPool.StringF(HTTP::EContentLength,RHTTPSession::GetTable());
       
  1613     RStringF date = strPool.StringF(HTTP::EDate,RHTTPSession::GetTable());
       
  1614     RStringF expires = strPool.StringF(HTTP::EExpires,RHTTPSession::GetTable());
       
  1615     RStringF maxAge = strPool.StringF(HTTP::EMaxAge,RHTTPSession::GetTable());
       
  1616     RStringF cacheControl = strPool.StringF(HTTP::ECacheControl,RHTTPSession::GetTable());
       
  1617     RStringF acceptRanges = strPool.StringF(HTTP::EAcceptRanges,RHTTPSession::GetTable());
       
  1618     
       
  1619     THTTPHdrVal value;
       
  1620     /*
       
  1621     if( !headers.GetField( length, 0, value ) )
       
  1622         {
       
  1623         if( iStorage->Length() == KDefaultContentLength )
       
  1624             // content size is
       
  1625             {
       
  1626             iStorage->SetLength( value );
       
  1627             }
       
  1628         }
       
  1629              
       
  1630     CheckRealDRMContentTypeL();
       
  1631     if( !iDrmContentLengthValid )
       
  1632         // Content was original encoded -> we don't know the actual content size.
       
  1633         {
       
  1634         iStorage->SetLength( KDefaultContentLength );
       
  1635         }*/ 
       
  1636         
       
  1637 		CheckRealDRMContentTypeL();
       
  1638 		
       
  1639     iMaxAge = 0;
       
  1640     TInt parts( 0 );
       
  1641     // this leave is trapped because we can still go on
       
  1642     TRAPD( err, parts = headers.FieldPartsL( cacheControl ) );
       
  1643 
       
  1644     if( !err )
       
  1645         // try to find max-age in Cache-control field
       
  1646         {
       
  1647         for( TInt i = 0; i < parts; ++i )
       
  1648             {
       
  1649             RStringF directive;
       
  1650             THTTPHdrVal hdrVal;
       
  1651             TInt err;
       
  1652 
       
  1653             // Get the cache-control from the headers
       
  1654             // initialise the fieldname
       
  1655             headers.GetField( cacheControl, i, hdrVal );
       
  1656 
       
  1657             if((hdrVal.Type() == THTTPHdrVal::KStrVal) || (hdrVal.Type() == THTTPHdrVal::KStrFVal))
       
  1658                 {
       
  1659                 RStringF cacheDir = hdrVal.StrF();
       
  1660 
       
  1661                 TInt endPos;
       
  1662                 _LIT8(KFind, "=");
       
  1663 
       
  1664                 endPos = cacheDir.DesC().Find( KFind );
       
  1665                 if( endPos != -1 )
       
  1666                     {
       
  1667                     TRAP(err, directive = strPool.OpenFStringL(cacheDir.DesC().Left(endPos)));
       
  1668                     if( !err )
       
  1669                         {
       
  1670                         if( directive == maxAge )
       
  1671                             {
       
  1672                             TInt valueInt( 0 );
       
  1673                             TLex8 value( cacheDir.DesC().Right(cacheDir.DesC().Length() - endPos - 1) );
       
  1674 
       
  1675                             value.Val( valueInt );
       
  1676                             iMaxAge = valueInt;
       
  1677                             }
       
  1678                         }
       
  1679                     }
       
  1680                 }
       
  1681             }
       
  1682         }
       
  1683 
       
  1684     if( !headers.GetField( expires, 0, value ) )
       
  1685         {
       
  1686         iExpires = value;
       
  1687         }
       
  1688     else
       
  1689         {
       
  1690         iExpires.SetYear( 0 );
       
  1691         }
       
  1692 
       
  1693     if( !headers.GetField( date, 0, value ) )
       
  1694         {
       
  1695         iDate = value;
       
  1696         }
       
  1697     else
       
  1698         {
       
  1699         iDate.SetYear( 0 );
       
  1700         }
       
  1701 	}
       
  1702 
       
  1703 
       
  1704 	
       
  1705 void CHttpLoader::LoadHeadersL( RFile& aFile)
       
  1706 	{
       
  1707     TInt headers;
       
  1708     READ_INT_L( aFile, headers );
       
  1709 
       
  1710     iResponseHeaders->ResetAndDestroy();
       
  1711 
       
  1712     for( TInt i = 0; i < headers; ++i )
       
  1713         {
       
  1714         CHeaderField* field = CHeaderField::NewL();
       
  1715         CleanupStack::PushL( field );
       
  1716 
       
  1717         field->LoadHeaderInfoL( aFile );
       
  1718         iResponseHeaders->AppendL( field );
       
  1719 
       
  1720         CleanupStack::Pop( field );
       
  1721         }	
       
  1722 	}
       
  1723 	
       
  1724 void CHttpLoader::SetRangeFieldL( RStringPool& aStringPool,
       
  1725                                     RHTTPHeaders& aHeaders )
       
  1726     {
       
  1727     
       
  1728     if(!iSaver)
       
  1729     {
       
  1730         return;
       
  1731     }
       
  1732     
       
  1733     TInt size (iSaver->DownloadedFileSize());
       
  1734 
       
  1735     if( size <= 0 )
       
  1736         {
       
  1737 		// no bytes have been downloaded yet
       
  1738         return;
       
  1739         }
       
  1740 
       
  1741     RStringF range = aStringPool.StringF(HTTP::ERange, RHTTPSession::GetTable());
       
  1742 
       
  1743     aHeaders.RemoveField( range );
       
  1744 
       
  1745     TBuf8<48> rawData;
       
  1746 
       
  1747     rawData.Format( _L8("bytes=%d-"), size);
       
  1748 
       
  1749     aHeaders.SetRawFieldL( range, rawData, KHttpFieldSeparator );
       
  1750     }
       
  1751     
       
  1752 // -----------------------------------------------------------------------------
       
  1753 // CHttpLoader::FindHeaderField
       
  1754 // ?implementation_description
       
  1755 // (other items were commented in a header).
       
  1756 // -----------------------------------------------------------------------------
       
  1757 //
       
  1758 TInt CHttpLoader::FindHeaderField( CArrayPtrFlat<CHeaderField>* aHeaders,
       
  1759                                      const TDesC8& aFieldName ) const
       
  1760     {
       
  1761     for( TInt index = 0; index < aHeaders->Count(); ++index )
       
  1762         {
       
  1763         if( *(*aHeaders)[index]->FieldName() == aFieldName )
       
  1764             {
       
  1765             return index;
       
  1766             }
       
  1767         }
       
  1768 
       
  1769     return KErrNotFound;
       
  1770     }
       
  1771 	
       
  1772 void CHttpLoader::CheckRealDRMContentTypeL()
       
  1773     {
       
  1774     iPausableDRM = ETrue;
       
  1775     iDrmContentLengthValid = ETrue;
       
  1776     
       
  1777     TInt index = FindHeaderField( iResponseHeaders, KDRMOldContentType );
       
  1778     if( index != KErrNotFound )
       
  1779         // this is an old DRM protected content
       
  1780         // This transaction cannot be paused.
       
  1781         {
       
  1782         if( !(*iResponseHeaders)[index]->FieldRawData()->Compare( KDrmMessageMimeType() ) )
       
  1783             {
       
  1784             iPausableDRM = EFalse;
       
  1785             }
       
  1786         }
       
  1787         
       
  1788     UpdatePausableL();
       
  1789     }	
       
  1790 
       
  1791 // -----------------------------------------------------------------------------
       
  1792 // CHttpLoader::UpdatePausableL
       
  1793 // ?implementation_description
       
  1794 // (other items were commented in a header).
       
  1795 // -----------------------------------------------------------------------------
       
  1796 //
       
  1797 void CHttpLoader::UpdatePausableL()
       
  1798     {
       
  1799     TBool pausable( ETrue );
       
  1800 
       
  1801     if( !iPausableDRM )
       
  1802         {
       
  1803         pausable = EFalse;
       
  1804         }
       
  1805         
       
  1806     if( iMethod == EMethodPOST )
       
  1807         {
       
  1808         pausable = EFalse;
       
  1809         }
       
  1810 
       
  1811     if( pausable != iCodEng->Pausable() )
       
  1812         {
       
  1813         iCodEng->SetPausable( pausable );
       
  1814         
       
  1815         //TODO : Shud the change in pause behavior shud be notified. ??
       
  1816         // inform client about change
       
  1817         //TriggerEvent( iPausable ? EHttpDlPausable : EHttpDlNonPausable );
       
  1818 
       
  1819         //TRAP_IGNORE(StoreDownloadInfoL() );
       
  1820         iCodEng->StoreSubInfoFileL(iResponseHeaders, iCodEng->Data().ActiveDownload() );
       
  1821         }
       
  1822     }    
       
  1823 
       
  1824 // ---------------------------------------------------------
       
  1825 // CHttpLoader::LogHeaders()
       
  1826 // ---------------------------------------------------------
       
  1827 //
       
  1828 void CHttpLoader::LogHeaders( RHTTPHeaders LOG_ONLY( aHeaders ) )
       
  1829     {
       
  1830 #ifdef __TEST_COD_LOG
       
  1831     _LIT(KDateFormat,"%D%M%Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S.%C%:3");
       
  1832 
       
  1833     CLOG(( EHttpLoad, 1, _L("Headers:") ));
       
  1834 
       
  1835     TInt i;
       
  1836     TInt fieldParts;
       
  1837     RStringPool strP = iTrans.Session().StringPool();
       
  1838     THTTPHdrFieldIter it = aHeaders.Fields();
       
  1839 
       
  1840     while ( !it.AtEnd() )
       
  1841         {
       
  1842         RStringTokenF fieldName = it();
       
  1843         RStringF fieldNameStr = strP.StringF (fieldName );
       
  1844         THTTPHdrVal fieldVal;
       
  1845         fieldParts = 0; // For the case if next the call fails.
       
  1846         TRAP_IGNORE( fieldParts =  aHeaders.FieldPartsL( fieldNameStr ) );
       
  1847         for ( i = 0; i < fieldParts; i++ )
       
  1848             {
       
  1849             if ( aHeaders.GetField( fieldNameStr, i, fieldVal ) == KErrNone )
       
  1850                 {
       
  1851                 const TDesC8& fieldNameDesC = fieldNameStr.DesC();
       
  1852                 switch ( fieldVal.Type() )
       
  1853                     {
       
  1854                     case THTTPHdrVal::KTIntVal:
       
  1855                         {
       
  1856                         CLOG(( EHttpLoad, 1, _L8("  <%S> (%d)"), \
       
  1857                             &fieldNameDesC, fieldVal.Int() ));
       
  1858                         break;
       
  1859                         }
       
  1860 
       
  1861                     case THTTPHdrVal::KStrFVal:
       
  1862                         {
       
  1863                         RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
       
  1864                         const TDesC8& fieldValDesC = fieldValStr.DesC();
       
  1865                         CLOG(( EHttpLoad, 1, _L8("  <%S> <%S>"), \
       
  1866                             &fieldNameDesC, &fieldValDesC ));
       
  1867                         }
       
  1868                         break;
       
  1869 
       
  1870                     case THTTPHdrVal::KStrVal:
       
  1871                         {
       
  1872                         RString fieldValStr = strP.String( fieldVal.Str() );
       
  1873                         const TDesC8& fieldValDesC = fieldValStr.DesC();
       
  1874                         CLOG(( EHttpLoad, 1, _L8("  <%S> <%S>"), \
       
  1875                             &fieldNameDesC, &fieldValDesC ));
       
  1876                         }
       
  1877                         break;
       
  1878 
       
  1879                     case THTTPHdrVal::KDateVal:
       
  1880                         {
       
  1881                         TDateTime date = fieldVal.DateTime();
       
  1882                         TBuf<40> dateTimeString;
       
  1883                         TTime t( date );
       
  1884                         TRAP_IGNORE\
       
  1885                             ( t.FormatL( dateTimeString, KDateFormat ) );
       
  1886                         TBuf8<40> dateTimeString8;
       
  1887                         dateTimeString8.Copy( dateTimeString );
       
  1888                         CLOG(( EHttpLoad, 1, _L8("  <%S> <%S>"), \
       
  1889                             &fieldNameDesC, &dateTimeString8 ));
       
  1890                         } 
       
  1891                         break;
       
  1892 
       
  1893                     default:
       
  1894                         CLOG(( EHttpLoad, 1, \
       
  1895                             _L8("  <%S> unrecognised value type(%d)"), \
       
  1896                             &fieldNameDesC, fieldVal.Type() ));
       
  1897                         break;
       
  1898                     }
       
  1899 
       
  1900                 // Display realm for WWW-Authenticate header.
       
  1901                 RStringF wwwAuth = strP.StringF
       
  1902                     ( HTTP::EWWWAuthenticate, RHTTPSession::GetTable() );
       
  1903                 if ( fieldNameStr == wwwAuth )
       
  1904                     {
       
  1905                     // check the auth scheme is 'basic'
       
  1906                     RStringF basic = strP.StringF
       
  1907                         ( HTTP::EBasic, RHTTPSession::GetTable() );
       
  1908                     RStringF realm = strP.StringF
       
  1909                         ( HTTP::ERealm, RHTTPSession::GetTable() );
       
  1910                     THTTPHdrVal realmVal;
       
  1911                     if ( ( fieldVal.StrF() == basic ) && 
       
  1912                         ( !aHeaders.GetParam( wwwAuth, realm, realmVal ) ) )
       
  1913                         {
       
  1914                         RString realmValStr = strP.String( realmVal.Str() );
       
  1915                         const TDesC8& realmValDesC = realmValStr.DesC();
       
  1916                         CLOG(( EHttpLoad, 1, _L8("    Realm<%S>"), \
       
  1917                             &realmValDesC ));
       
  1918                         }
       
  1919                     }
       
  1920                 }
       
  1921             }
       
  1922         ++it;
       
  1923         }
       
  1924 #endif /* def __TEST_COD_LOG */
       
  1925     }
       
  1926 
       
  1927 
       
  1928 // -----------------------------------------------------------------------------
       
  1929 // CHttpLoader::RedirectedPermanentlyL
       
  1930 // -----------------------------------------------------------------------------
       
  1931 //
       
  1932 void CHttpLoader::RedirectedPermanentlyL( const TDesC8& aNewUrl )
       
  1933     {
       
  1934     CLOG(( EHttpLoad, 0, _L("CHttpLoader::RedirectedPermanentlyL => NewUrl(%S)"), \
       
  1935                                                             &aNewUrl ));
       
  1936 
       
  1937 	// Use the redirected Url
       
  1938 	ReallocateStringL( iUri, aNewUrl, KMaxUrlLength );
       
  1939 	
       
  1940 	// There has already been a temporary redirection
       
  1941     // This permanent is not used on next submitted request 
       
  1942 	if (!iRedirect)
       
  1943 		{
       
  1944 		HBufC* newUrl = CodUtil::ConvertLC( aNewUrl );
       
  1945 		iCodEng->SetUrlL( *newUrl );
       
  1946 		
       
  1947 		CleanupStack::PopAndDestroy( newUrl );
       
  1948 		}
       
  1949     }
       
  1950 
       
  1951 // -----------------------------------------------------------------------------
       
  1952 // CHttpLoader::RedirectedTemporaryL
       
  1953 // -----------------------------------------------------------------------------
       
  1954 //
       
  1955 void CHttpLoader::RedirectedTemporaryL( const TDesC8& aNewUrl )
       
  1956     {
       
  1957     CLOG(( EHttpLoad, 0, _L("CHttpLoader::RedirectedTemporaryL => NewUrl(%S)"), \
       
  1958                                                             &aNewUrl ));
       
  1959 
       
  1960 	// Make it TRUE so that any permanent redirections after
       
  1961 	// this are not saved
       
  1962 	iRedirect = ETrue;
       
  1963 	ReallocateStringL( iUri, aNewUrl, KMaxUrlLength );
       
  1964     }
       
  1965 
       
  1966 // -----------------------------------------------------------------------------
       
  1967 // CHttpLoader::ResponseHeaders
       
  1968 // -----------------------------------------------------------------------------
       
  1969 //
       
  1970 CArrayPtrFlat<CHeaderField>* CHttpLoader::ResponseHeaders()
       
  1971 	{
       
  1972 	return iResponseHeaders;
       
  1973 	}