--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/browserutilities/downloadmgr/DownloadMgrServEng/Src/HttpDownload.cpp Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,7092 @@
+/*
+* Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: ?Description
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "HeaderField.h"
+#include "HttpDownloadManagerServerEngine.h"
+#include "HttpClientApp.h"
+#include "FileExt.h"
+#include "HttpDownload.h"
+#include "HttpStorage.h"
+#include "HttpDownloadMgrLogger.h"
+#include "bautils.h"
+
+#include <CommDbConnPref.h>
+#include <Uri16.h>
+#include <F32FILE.H>
+#include <EscapeUtils.h>
+#include <HttpFilterCommonStringsExt.h>
+#include <tinternetdate.h>
+#include <SysUtil.h>
+#include <MGXFileManagerFactory.h>
+#include <CMGXFileManager.h>
+#include <DcfEntry.h>
+#include <DcfRep.h>
+
+#include <pathinfo.h>
+
+// EXTERNAL DATA STRUCTURES
+//extern ?external_data;
+
+// EXTERNAL FUNCTION PROTOTYPES
+//extern ?external_function( ?arg_type,?arg_type );
+
+// CONSTANTS
+const TInt32 KDMgrInfoFileId = 0x2002; // id to check if it's really an info file
+const TInt32 KDmgrVersionNumber = 0x0301; // version number of the info file
+const TInt KUrlFixChar = '_';
+const TInt KMaxHeaderOfMultipart = 32000;
+const TInt KRespSizeForRecognition = 1024; //for THttpProgressState EHttpContTypeRecognitionAvail
+const TInt KMinDataSizeToSend = (32*1024); //for Browser Control to call NewDownloadL
+
+_LIT8( KHttpScheme, "http" );
+_LIT8( KHttpsScheme, "https" );
+_LIT8( KDefDestFilename, "content.bin" );
+_LIT8( KSchemeAddon, "://" );
+_LIT8( KBoundary, "boundary=" );
+_LIT8( KDoubleEOL, "\r\n\r\n" );
+_LIT8( KContentType, "Content-Type: " );
+
+#ifdef __SYNCML_DM_FOTA
+_LIT8( KFotaMimeType, "application/vnd.nokia.swupd.dp2");
+#endif
+_LIT8( KDefaultAcceptHeader, "multipart/mixed, application/java-archive, application/java, application/x-java-archive, text/vnd.sun.j2me.app-descriptor, application/vnd.oma.drm.message, application/vnd.oma.drm.content, application/vnd.wap.mms-message, text/x-co/desc, application/vnd.oma.dd+xml, text/javascript, text/javascript, application/x-javascript, text/ecmascript, */*" );
+_LIT8( KDRMOldContentType, "x-drm-old-content-type"); // old content type header to be added
+
+_LIT( KIndexString, "(%d)" );
+const TInt KMaxIndexStringLength = 16; // max size of index string "(4294967296)"
+
+_LIT8( KCookieUsage, "CookiesEnabled" );
+
+const TInt KStringAttribMaxLengths[][2] = {
+ {EDlAttrReqUrl, KMaxUrlLength},
+ {EDlAttrRedirUlr, KMaxUrlLength},
+ {EDlAttrCurrentUrl, KMaxUrlLength},
+ {EDlAttrName, KMaxPath},
+ {EDlAttrRealm,KMaxRealmLength},
+ {EDlAttrUsername, KMaxDefAttrLength},
+ {EDlAttrPassword, KMaxDefAttrLength},
+ {EDlAttrProxyRealm, KMaxRealmLength},
+ {EDlAttrProxyUsername, KMaxDefAttrLength},
+ {EDlAttrProxyPassword, KMaxDefAttrLength},
+ {EDlAttrDestFilename, KMaxPath},
+ {EDlAttrContentType, KMaxContentTypeLength},
+ {EDlAttrMediaType, KMaxContentTypeLength},
+ {0,0}
+ };
+
+const TInt KDownloadInfoIncrSize = 2*4096; // used for DownloadInfo
+
+_LIT( KDownloadPath, "download");
+
+// MACROS
+//#define ?macro ?macro_def
+
+#define _OMADLOTA2_MULTI_DOWNLOAD (iCodDlData && iCodDlData->Count()>1)
+
+// LOCAL CONSTANTS AND MACROS
+const TInt KDMHttpErrorBase = -25000;
+#define GLOBAL_HTTP_ERROR( err ) ( KDMHttpErrorBase - err )
+const TInt KErrMultipeObjectDownloadFailed = -20046;
+
+// MODULE DATA STRUCTURES
+//enum ?declaration
+//typedef ?declaration
+
+// LOCAL FUNCTION PROTOTYPES
+//?type ?function_name( ?arg_type, ?arg_type );
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::CHttpDownload
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CHttpDownload::CHttpDownload( CHttpClientApp *aClientApp,
+ TInt32 aId,
+ CHttpClientAppInstance* aClAppInstance )
+ : CActive( EPriorityStandard )
+ , iId( aId )
+ , iClientApp( aClientApp )
+ , iClAppInstance( aClAppInstance )
+ , iPort( KDefaultPort )
+ , iDisconnectOnPause( ETrue )
+ , iDisconnectOnReset( ETrue )
+ , iCodDownload( 0 )
+ , iFotaPckgId( KDefaultFotaPckgId )
+ , iDate( 0, EJanuary, 1, 0, 0, 0, 0 )
+ , iExpires( 0, EJanuary, 1, 0, 0, 0, 0 )
+ , iDlState( EHttpDlMultipleMOStarted )
+ , iAction( ELaunch )
+ , iRestartAction( ERestartIfExpired )
+ , iPausable( ETrue )
+ , iPausableDRM( ETrue )
+ , iDrmContentLengthValid( ETrue )
+ , iMultiPart( EFalse )
+ , iDlNameChanged(EFalse)
+ {
+ __ASSERT_DEBUG( iClientApp, DMPanic( KErrArgument ) );
+ CLOG_CREATE;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ConstructL( const TDesC8& aUrl )
+ {
+ CLOG_NAME_2( _L("cl%x_d%x"), iClientApp->AppUid(), iId );
+ LOGGER_ENTERFN( "ConstructL" );
+ CLOG_WRITE8_1( "URL: %S", &aUrl );
+
+ CActiveScheduler::Add( this );
+
+ iResponseHeaders = new (ELeave) CArrayPtrFlat<CHeaderField>(2);
+ iRequestHeaders = new (ELeave) CArrayPtrFlat<CHeaderField>(2);
+ iEntityHeaders = new (ELeave) CArrayPtrFlat<CHeaderField>(2);
+ iGeneralHeaders = new (ELeave) CArrayPtrFlat<CHeaderField>(2);
+ iStorage = CHttpStorage::NewL( this );
+ iActiveDownload = 1 ;
+ iMoLength = 0;
+ iMoDownloadCompleted = EFalse;
+ CLOG_ATTACH( iStorage, this );
+
+ iUrl = aUrl.AllocL();
+ if( iUrl->Length() )
+ // this is a new download
+ {
+ ParseRequestedUrlL(); // iCurrentUrl is initialized there
+ ParseDownloadNameL();
+ StoreDownloadInfoL();
+ SetDownloadStatus( EHttpProgNone, EHttpDlMultipleMOStarted );
+ }
+ else
+ {
+ LoadDownloadInfoL();
+
+ if( iDlState == EHttpDlInprogress )
+ // previous crash left this download here
+ // reseting download can solve the problem
+ {
+ ++iDontFireEvent;
+
+ TRAPD(err, PauseL() );
+
+ --iDontFireEvent;
+
+ User::LeaveIfError( err );
+ }
+ }
+
+ if( !iStorage->CheckContentFileIntegrityL() )
+ {
+ if (iStorage->ProgressiveDownload() &&
+ iStorage->Length() == iStorage->DownloadedSize() )
+ // If it was a progressive download
+ // and downloaded size = content length,
+ // it means that download was not properly closed
+ // in the previous session
+ {
+ ReInitializeDownload();
+ }
+ else
+ {
+ OnError( KErrUnknown, EContentFileIntegrity );
+ }
+ }
+
+ iMoveInProgress = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CHttpDownload* CHttpDownload::NewL( const TDesC8& aUrl,
+ CHttpClientApp *aClientApp,
+ TInt32 aId,
+ CHttpClientAppInstance* aClAppInstance )
+ {
+ __ASSERT_DEBUG( aId, DMPanic( KErrArgument ) );
+ CHttpDownload* self = new( ELeave ) CHttpDownload( aClientApp,
+ aId,
+ aClAppInstance );
+
+ CleanupStack::PushL( self );
+ self->ConstructL( aUrl );
+ CleanupStack::Pop();
+
+ return self;
+ }
+
+
+// Destructor
+CHttpDownload::~CHttpDownload()
+ {
+ ++iDontFireEvent;
+
+ Cancel();
+
+ delete iUrl;
+ delete iRedirUrl;
+ delete iCurrentUrl;
+ delete iHttpRealm;
+ delete iHttpNonce;
+ delete iHttpUsername;
+ delete iHttpPassword;
+ delete iHttpProxyRealm;
+ delete iHttpProxyUsername;
+ delete iHttpProxyPassword;
+ delete iContentType;
+ delete iDDType;
+ delete iMediaType;
+ delete iDlName;
+ delete iDispositionType;
+ delete iFileMan;
+
+
+ delete iHashedMsgBody;
+ delete iDownloadInfo;
+ delete iAttachmentFileName;
+
+ if( iTransValid )
+ {
+ iTrans.Close();
+ }
+
+ if( iResponseHeaders )
+ {
+ iResponseHeaders->ResetAndDestroy();
+ delete iResponseHeaders;
+ }
+
+ if( iRequestHeaders )
+ {
+ iRequestHeaders->ResetAndDestroy();
+ delete iRequestHeaders;
+ }
+
+ if( iEntityHeaders )
+ {
+ iEntityHeaders->ResetAndDestroy();
+ delete iEntityHeaders;
+ }
+
+ if( iGeneralHeaders )
+ {
+ iGeneralHeaders->ResetAndDestroy();
+ delete iGeneralHeaders;
+ }
+
+ delete iStorage;
+ iStorage = NULL;
+ delete iHeaderOfMultipart;
+
+ iMoveInProgress = EFalse;
+
+ CLOG_CLOSE;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::Attach
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::Attach( CHttpClientAppInstance* aClientAppInstance )
+ {
+ LOGGER_ENTERFN( "CHttpDownload::Attach" );
+
+ __ASSERT_DEBUG( !iPDClAppInstance, DMPanic( KErrInUse) );
+ iPDClAppInstance = aClientAppInstance;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::StartL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::StartL()
+ {
+ LOGGER_ENTERFN( "StartL" );
+
+ __ASSERT_DEBUG( !iNoMedia, DMPanic( KErrAbort ) );
+ if( iNoMedia )
+ // nomedia download cannot be started
+ {
+ SetDownloadStatus( EHttpProgNone, EHttpDlFailed, EInternal );
+
+ return;
+ }
+
+ if( iContinueDownload )
+ // Don't do anything until user accepts the given content
+ // to be downloaded.
+ {
+ CLOG_WRITE( "Continue download" );
+
+
+ if( !iConnHandler )
+ // assign download to the connhandler
+ // connection is surely up because it was created from client side
+ // iClAppInstance also must be valid because it's a continue download
+ {
+ iConnHandler = iClAppInstance->ConnHandler();
+ }
+
+ if( iDlState == EHttpDlMultipleMOStarted )
+ // do it only if EHttpDlCreated, anyway ignore Start request
+ {
+ iStorage->CreateDestinationFileL();
+
+ SetDownloadStatus( EHttpProgResponseHeaderReceived );
+ }
+ else if( iDlState == EHttpDlInprogress )
+ {
+ TriggerEvent( EHttpDlAlreadyRunning );
+ }
+
+ // This is the place where client already set every continue
+ // download attribute
+ StoreDownloadInfoL();
+
+ return;
+ }
+ if( iCodDownload )
+ {
+ if(iDlState == EHttpDlPaused)
+ {
+ if( !iConnHandler )
+ {
+ iConnHandler = iClAppInstance->ConnHandler();
+ }
+ SetDownloadStatus( EHttpStarted );
+ //TriggerEvent( EHttpDlInprogress, EHttpProgCodDownloadShouldResume );
+ }
+ else
+ {
+ TriggerEvent( EHttpDlInprogress, EHttpProgCodDownloadStarted );
+ }
+ return;
+ }
+ switch( iDlState )
+ {
+ case EHttpDlMultipleMOStarted:
+ // normal start from the beginning
+ break;
+
+ case EHttpDlInprogress:
+
+ if( iUpdatedDDUriSet )
+ {
+ ReInitializeDownload();
+
+ iStorage->UpdateDestinationFilenameL( KNullDesC, EFalse );
+
+ ParseRequestedUrlL(); // iCurrentUrl is initialized there
+ ParseDownloadNameL();
+ StoreDownloadInfoL();
+ SetDownloadStatus( EHttpStarted );
+
+ if( !iConnHandler )
+ // assign download to the connhandler
+ // connection is surely up because it was created from client side
+ // iClAppInstance also must be valid because it's a continue download
+ {
+ iConnHandler = iClAppInstance->ConnHandler();
+ }
+
+ }
+ else
+ {
+ TriggerEvent( EHttpDlAlreadyRunning );
+ }
+ return;
+
+ case EHttpDlPaused:
+ {
+ if( IsExpired() || !iPausable )
+ // cannot be resume:
+ // expired
+ // non-pauseable
+ {
+ ForcedRestartL();
+ }
+ }
+ break;
+
+ case EHttpDlMultipleMOCompleted:
+ {
+ if( iRestartAction == ERestartNoIfCompleted )
+ // nothing to do because content is downloaded
+ // and update check is not interested
+ {
+ TriggerEvent( EHttpDlMultipleMOCompleted );
+ return;
+ }
+ else if( iRestartAction == ERestartForced )
+ // doesn't matter what we have.
+ // Download must be restarted from the very beginning
+ {
+ ForcedRestartL();
+ }
+ else if( iRestartAction == ERestartIfExpired )
+ // First check that content is expired
+ // If so, check for update on the server
+ {
+ if( !IsExpired() )
+ // content is still valid -> no need to download again
+ // Client has to use ERestartForced or Reset() to
+ // be able to download it again
+ {
+ TriggerEvent( EHttpDlMultipleMOCompleted );
+ return;
+ }
+ }
+ }
+ break;
+
+ case EHttpDlFailed:
+ {
+ if( NoMedia() )
+ // we can't restart because original media is not present.
+ // need a reset.
+ {
+ TriggerEvent( EHttpDlMediaRemoved );
+ }
+ else if( iRestartAction == ERestartNoIfCompleted )
+ {
+ if( iLastError == EContentExpired )
+ // Can't download content because it's expired.
+ // Use ERestartIfExpired, ERestartForced or Reset()
+ {
+ OnError( KErrUnknown, EContentExpired );
+ return;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if( iRedirect )
+ // Requested url has to be restored, because of a previous redirection
+ {
+ ReallocateStringL( iCurrentUrl, *iRedirUrl, KMaxUrlLength );
+ iRedirect = EFalse;
+ }
+
+ __ASSERT_DEBUG( iClAppInstance || iPDClAppInstance, DMPanic( KErrCorrupt ) );
+ if (iPDClAppInstance && !iClAppInstance )
+ //this is the case when browser is the main client and we exit browser
+ //in this case the PD client has to be made the main client.
+ {
+ iClAppInstance = iPDClAppInstance;
+ iPDClAppInstance = NULL;
+ }
+ if( iClAppInstance )
+ {
+ if( !iConnHandler )
+ {
+ iConnHandler = iClAppInstance->ConnHandler();
+ }
+
+ iUseCookies = iClAppInstance->Cookies();
+ }
+
+ iDlStartedByClient = ETrue;
+
+ SetDownloadStatus( EHttpStarted );
+
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::PauseL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::PauseL( TBool aStore )
+ {
+ LOGGER_ENTERFN( "PauseL" );
+
+ if( iDlState == EHttpDlPaused )
+ // already paused
+ {
+ TriggerEvent( EHttpDlPaused );
+ return;
+ }
+
+ //If the download is failed or completed, pause doesnt has any effect.
+ if( iDlState == EHttpDlMultipleMOCompleted || iDlState == EHttpDlMultipleMOFailed )
+ {
+ return;
+ }
+
+ InternalPauseL( iDisconnectOnPause );
+
+ //Pause the download only if it is pausable
+ if( iDlState == EHttpDlInprogress )
+ {
+ if( Pausable() )
+ // Do not change state when it's
+ // created, pause, completed or failed.
+ {
+ SetDownloadStatus( EHttpProgNone, EHttpDlPaused );
+
+ if( iCodDownload )
+ {
+ TriggerEvent( EHttpDlPaused, EHttpProgCodDownloadPause );
+ }
+ }
+ else
+ {
+ //Else report error
+ OnError( iGlobalErrorId, (THttpDownloadMgrError) iLastError );
+ }
+ }
+
+ if( aStore && Pausable() )
+ {
+ StoreDownloadInfoL();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::Reset
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::Reset()
+ {
+ LOGGER_ENTERFN( "Reset" );
+
+ DoReset();
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::Delete
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::Delete( CHttpClientAppInstance* aClAppInstance )
+ {
+ CLOG_WRITE( "Delete()" );
+ if( !ClientApp()->Engine()->IsEngineClosing() )
+ {
+ if( aClAppInstance )
+ {
+ if( iPDClAppInstance == aClAppInstance )
+ {
+ iPDClAppInstance = NULL;
+ if( !iStorage->ProgressiveMode() )
+ {
+ return;//This Attribute tells if Delete is called from MP when Exiting from Browser
+ }
+ if( iClAppInstance )
+ {
+ SetDownloadStatus( EHttpProgNone, EHttpDlDeleting );
+ //Deref Attach Download instance
+ aClAppInstance->ClientApp()->UnregisterDownload( this );
+ return;
+ }
+ }
+ else if( iClAppInstance == aClAppInstance )
+ {
+ iClAppInstance = NULL;
+ if( iPDClAppInstance )
+ {
+ SetDownloadStatus( EHttpProgNone, EHttpDlDeleting );
+ //Deref Master Client Instance
+ aClAppInstance->ClientApp()->UnregisterDownload( this );
+ return;
+ }
+ }
+ }
+ }
+
+ // Do not inform user about that we are in deleteing state
+ // This won't be reenabled at the end of this function so
+ // don't call delete only from outside of this class.
+ ++iDontFireEvent;
+
+ TPath folder;
+ TFileName file;
+
+ // delete info file
+ iClientApp->Engine()->DownloadInfoFolder( iClientApp, folder );
+ file.Format( _L("%S%d"), &folder, iId );
+ TInt err = iClientApp->Engine()->Fs().Delete( file );
+ CLOG_WRITE_2( "Delete info file: %S, err : %d", &file, err );
+
+ // delete cod info file
+ iClientApp->Engine()->CODDownloadInfoFolder( iClientApp, folder );
+ file.Format( _L("%S%d"), &folder, iId );
+ //delete main info file
+ err = iClientApp->Engine()->Fs().Delete( file );
+ CLOG_WRITE_2( "Delete info file: %S, err : %d", &file, err );
+
+ //delete subinfo file
+ CFileMan* fileMan = CFileMan::NewL(iClientApp->Engine()->Fs() );
+ file.Format( _L("%S%d_*"), &folder, iId );
+ fileMan->Delete( file );
+ delete fileMan;
+
+
+ // to make sure the CHttpStorage releases the content file
+ // and deletes it.
+ CHttpStorage::TFileCloseOperation closeOp = CHttpStorage::EDeleteFile;
+
+ if( iStorage->DestFNameSet() && iDlState == EHttpDlMultipleMOCompleted )
+ // Do NOT delete the file: if the destination filename was
+ // set by the client and download completed.
+ {
+ CLOG_WRITE("Keep file");
+ closeOp = CHttpStorage::EKeepFile;
+ }
+
+ if( iStorage->RFileSetByClient())
+ {
+ TBool pausable;
+ GetBoolAttributeL( EDlAttrPausable, pausable );
+ if( iDlState == EHttpDlMultipleMOCompleted || ( iDlState == EHttpDlInprogress && pausable ) )
+ {
+ CLOG_WRITE("Keep file");
+ closeOp = CHttpStorage::EKeepFile;
+ }
+ }
+ if( iCodDlData )
+ {
+ // For User Delete when all the Downloads are moved to gallery
+ if( EHttpDlMultipleMOCompleted == iDlState && closeOp == CHttpStorage::EDeleteFile )
+ {
+ for(TInt i = 1; i <= iCodDlData->Count(); i++)
+ {
+ TPtrC fullName = ((*iCodDlData)[i])->DestFilename();
+ ClientApp()->Engine()->Fs().Delete( fullName );
+ }
+ }
+ // For User Cancel to Cancel Multiple download, Current and Queued DLs will be delete, completed ones will be kept
+ else if( EHttpDlInprogress == iDlState || EHttpDlPaused == iDlState || EHttpDlDeleting == iDlState)
+ {
+ for(TInt i = 1; i <= iCodDlData->Count(); i++)
+ {
+ if( EInProgress == ((*iCodDlData)[i])->State() || EFailed == ((*iCodDlData)[i])->State() ) // OnGoing and Queued will be deleted
+ {
+ TPtrC fullName = ((*iCodDlData)[i])->DestFilename();
+ if(fullName.Length())
+ {
+ ClientApp()->Engine()->Fs().Delete( fullName );
+ }
+ }
+ //else if( ESucceeded == ((*iCodDlData)[i])->State() )
+ // Completed ones will be kept and moved to Gallery
+ else if( ESucceeded == ((*iCodDlData)[i])->State() )
+ {
+ MoveInDelete(i);
+ }
+ }
+ }
+ }
+ else
+ {
+ iStorage->CloseDestinationFile( closeOp );
+ }
+ // when delete there's no store -> no leave
+ aClAppInstance->ClientApp()->UnregisterDownload( this );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::DeleteInfoFile
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::DeleteInfoFile( CHttpClientAppInstance* aClAppInstance )
+ {
+ CLOG_WRITE( "DeleteInfoFile()" );
+
+ // This should be called only after the completion of download
+ if( ! (EHttpDlMultipleMOCompleted == iDlState &&
+ (
+ EHttpProgContentFileMoved == iProgState ||
+ EHttpProgContentFileMovedAndDestFNChanged == iProgState
+ )
+ ))
+ {
+ return;
+ }
+
+ // Do not inform user about that we are in deleteing state
+ // This won't be reenabled at the end of this function so
+ // don't call delete only from outside of this class.
+ ++iDontFireEvent;
+
+ TPath folder;
+ TFileName file;
+
+ // delete info file
+ iClientApp->Engine()->DownloadInfoFolder( iClientApp, folder );
+ file.Format( _L("%S%d"), &folder, iId );
+ CLOG_WRITE_1( "Delete info file: %S", &file );
+ iClientApp->Engine()->Fs().Delete( file );
+
+ // delete cod info file
+ iClientApp->Engine()->CODDownloadInfoFolder( iClientApp, folder );
+ file.Format( _L("%S%d"), &folder, iId );
+ CLOG_WRITE_1( "Delete info file: %S", &file );
+ iClientApp->Engine()->Fs().Delete( file );
+
+ //delete subinfo file
+ CFileMan* fileMan = CFileMan::NewL(iClientApp->Engine()->Fs() );
+ file.Format( _L("%S%d_*"), &folder, iId );
+ fileMan->Delete( file );
+ delete fileMan;
+
+
+ // to make sure the CHttpStorage releases the content file
+ // and deletes it.
+ CHttpStorage::TFileCloseOperation closeOp = CHttpStorage::EDeleteFile;
+
+ if( iStorage->DestFNameSet() && iDlState == EHttpDlMultipleMOCompleted )
+ // Do NOT delete the file: if the destination filename was
+ // set by the client and download completed.
+ {
+ CLOG_WRITE("Keep file");
+ closeOp = CHttpStorage::EKeepFile;
+ }
+
+ iStorage->CloseDestinationFile( closeOp );
+
+ // when delete there's no store -> no leave
+ aClAppInstance->ClientApp()->UnregisterDownload( this );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::MoveL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::MoveL()
+ {
+ LOGGER_ENTERFN( "MoveL" );
+
+
+ if(iMoveInProgress)
+ {
+ CLOG_WRITE(" return MoveL ");
+ return;
+ }
+
+ iMoveInProgress = ETrue;
+
+ if( !iCodDownload && iDlState != EHttpDlMultipleMOCompleted )
+ {
+ User::Leave( KErrNotReady );
+ }
+ //Incase of COD downloads, Move should happen only after COD Load End
+ if( iCodDownload && iProgState != EHttpProgCodLoadEnd )
+ {
+ User::Leave( KErrNotReady );
+ }
+
+ if( iProgState == EHttpProgMovingContentFile )
+ {
+ User::Leave( KErrInUse );
+ }
+
+ //File is already moved. Ignore the move
+ if( iProgState == EHttpProgContentFileMovedAndDestFNChanged ||
+
+ iProgState == EHttpProgContentFileMoved )
+ {
+ return;
+ }
+
+ __ASSERT_DEBUG( !IsActive(), DMPanic( KErrInUse ) );
+ //__ASSERT_DEBUG( !iFileMan, DMPanic( KErrInUse ) );
+
+ if(_OMADLOTA2_MULTI_DOWNLOAD)
+ {
+ iMOMoved = 1;
+ SetDownloadStatus( EHttpProgMovingContentFile, iDlState );
+ MoveDownloadedMediaObjectL(iMOMoved);
+ return;
+ }
+
+
+ RFs &rFs = iClientApp->Engine()->Fs();
+ if(!iFileMan)
+ {
+ iFileMan = CFileMan::NewL(rFs);
+ }
+
+ CLOG_WRITE_1( "Src: %S", iStorage->LocalFilename() );
+ CLOG_WRITE_1( "Dest: %S", iStorage->DestFilename() );
+ UpdateDestFileNameL();
+
+ HBufC* fileName = HBufC::NewLC( KMaxPath );
+ TPtr fileNamePtr = fileName->Des();
+ fileNamePtr = *iStorage->DestFilename();
+ HBufC* uniqueName = NULL;
+ TInt index( 0 );
+ TBool bFound( EFalse );
+ do
+ {
+ CreateIndexedNameL(uniqueName , fileNamePtr , index);
+ if( !BaflUtils::FileExists( rFs , *uniqueName ) )
+ //Check if file name exist in Destination path
+ //Generate Unique name if exist
+ {
+ bFound =ETrue;
+ break;
+ }
+ iDlNameChanged = ETrue;
+
+ }while( !bFound );
+ CleanupStack::PopAndDestroy( fileName );
+
+ if( iDlNameChanged )
+ {
+ HBufC16* destFileName ;
+ destFileName = iStorage->DestFilename();
+ TPtr destFileNamePtr = destFileName->Des();
+ destFileNamePtr.Replace(0, destFileNamePtr.Length() , *uniqueName);
+ TInt lastSlashPos = destFileNamePtr.LocateReverse( '\\' );
+ TPtr dlName = destFileNamePtr.MidTPtr(lastSlashPos +1 );
+ TInt dotPos = iDlName->LocateReverse( '.' );
+ if( dotPos == KErrNotFound )
+ {
+ //Remove Extension from dlName as it was not present in old iDlName
+ dotPos = dlName.LocateReverse( '.' );
+ if(dotPos != KErrNotFound )
+ {
+ dlName.Copy( dlName.Left(dotPos));
+ }
+ }
+ //download name has changed
+ ReallocateStringL( iDlName, dlName, KDownloadNameMaxSize );
+ }
+
+ TInt err =iFileMan->Move( *iStorage->LocalFilename(),
+ *iStorage->DestFilename(),
+ CFileMan::EOverWrite,
+ iStatus );
+ if(err != KErrNone)
+ {
+ iMoveInProgress = EFalse;
+ CLOG_WRITE("setting iMoveInProgress false when move fails");
+ }
+
+ User::LeaveIfError( err );
+ // waiting for move to complete
+ SetActive();
+ SetDownloadStatus( EHttpProgMovingContentFile, iDlState );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::GetIntAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::GetIntAttributeL( THttpDownloadAttrib aAttribute,
+ TInt32& aValue )
+ {
+ LOGGER_ENTERFN( "GetIntAttributeL" );
+ CLOG_WRITE_1( "Attr(%d)", aAttribute );
+
+ iNoRealError = ETrue;
+
+ switch( aAttribute )
+ {
+ case EDlAttrState:
+ {
+ if(iDlState == EHttpDlMultipleMOCompleted )
+ {
+ aValue = EHttpDlCompleted;
+ }
+ else if(iDlState == EHttpDlMultipleMOFailed )
+ {
+ aValue = EHttpDlFailed;
+ }
+ else
+ {
+ aValue = iDlState;
+ }
+ }
+ break;
+
+ case EDlAttrProgressState:
+ {
+ aValue = iProgState;
+ }
+ break;
+
+ case EDlAttrUserData:
+ {
+ aValue = iUserData;
+ }
+ break;
+
+ case EDlAttrId:
+ {
+ aValue = iId;
+ }
+ break;
+
+ case EDlAttrMultipleMOLength:
+ {
+ if ( iCodDownload )
+ {
+ aValue = iMoLength;
+ }
+ else
+ {
+ aValue = iStorage->Length();
+ }
+ }
+ break;
+
+ case EDlAttrMultipleMODownloadedSize:
+ {
+ if( iCodDownload )
+ {
+ aValue = iStorage->MoDownloadedSize();
+ }
+ else
+ {
+ aValue = iStorage->DownloadedSize();
+ }
+ }
+ break;
+
+ case EDlAttrLength:
+ {
+ aValue = iStorage->Length();
+ }
+ break;
+
+ case EDlAttrDownloadedSize:
+ {
+ aValue = iStorage->DownloadedSize();
+ }
+ break;
+
+ case EDlAttrStatusCode:
+ {
+ aValue = iStatusCode;
+ }
+ break;
+
+ case EDlAttrAction:
+ {
+ aValue = iAction;
+ }
+ break;
+
+ case EDlAttrPort:
+ {
+ aValue = iPort;
+ }
+ break;
+
+ case EDlAttrRestartAction:
+ {
+ aValue = iRestartAction;
+ }
+ break;
+
+ case EDlAttrErrorId:
+ {
+ aValue = iLastError;
+ }
+ break;
+
+ case EDlAttrGlobalErrorId:
+ {
+ aValue = iGlobalErrorId;
+ }
+ break;
+
+ case EDlAttrTargetApp:
+ {
+ aValue = iTargetApp;
+ }
+ break;
+
+ case EDlAttrAuthScheme:
+ {
+ aValue = iAuthScheme;
+ }
+ break;
+
+ case EDlAttrRequestHeaderAddonLength:
+ {
+ aValue = 0;
+
+ for( TInt i = 0; i < iRequestHeaders->Count(); ++i )
+ {
+ aValue += (*iRequestHeaders)[i]->FieldName()->Length() +
+ (*iRequestHeaders)[i]->FieldRawData()->Length() +
+ 2; // +2 = KColon + KHttpFieldSeparator
+ }
+ }
+ break;
+
+ case EDlAttrMethod:
+ {
+ aValue = iMethod;
+ }
+ break;
+
+ case EDlAttrFotaPckgId:
+ {
+ aValue = iFotaPckgId;
+ }
+ break;
+
+ case EDlAttrNumMediaObjects:
+ {
+ aValue = 1;
+ if(iCodDlData)
+ {
+ aValue = iCodDlData->Count();
+ }
+ }
+ break;
+ case EDlAttrActiveDownload:
+ {
+ aValue = iActiveDownload;
+ }
+ break;
+ case EDlAttrActivePlayedDownload:
+ {
+ aValue = iActivePlayedDownload;
+ }
+ break;
+
+ default:
+ {
+ CLOG_WRITE_1( "Unknown int attrib: %d", aAttribute );
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ }
+ break;
+ }
+
+ iNoRealError = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::GetIntAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::GetIntAttributeL( THttpDownloadAttrib aAttribute,
+ TInt32& aMoIndex,
+ TInt32& aValue )
+ {
+ LOGGER_ENTERFN( "GetIntAttributeL" );
+ CLOG_WRITE_1( "Attr(%d)", aAttribute );
+
+ if (!iCodDlData)
+ {
+ aValue = 0;
+ return;
+ }
+ if ((aMoIndex <= KNonMoIndex) || (aMoIndex > iCodDlData->Count()))
+ {
+ User::Leave( KErrArgument );
+ }
+
+ CMediaDataBase* mediaData = (*iCodDlData)[aMoIndex];
+ iNoRealError = ETrue;
+
+ switch( aAttribute )
+ {
+ case EDlAttrMultipleMOLength:
+ {
+ aValue = iMoLength;
+ }
+ break;
+
+ case EDlAttrMultipleMODownloadedSize:
+ {
+ // Calculate downloaded size of current media object from
+ // album downloaded size.
+ TInt dlSize = iStorage->DownloadedSize();
+ for (TInt index = 0; index < iCodDlData->Count(); ++index)
+ {
+ CMediaDataBase* moData = (*iCodDlData)[index+1];
+ if ((moData->State() == ESucceeded) || (moData->State() == EInProgress))
+ dlSize -= moData->DownloadedSize();
+ }
+
+ aValue = dlSize;
+ }
+ break;
+
+ case EDlAttrLength:
+ {
+ aValue = iStorage->Length();
+ }
+ break;
+
+ case EDlAttrDownloadedSize:
+ {
+ aValue = iStorage->DownloadedSize();
+ }
+ break;
+
+ case EDlAttrErrorId:
+ {
+ aValue = mediaData->LastErrorId();
+ }
+ break;
+
+ case EDlAttrGlobalErrorId:
+ {
+ aValue = mediaData->GlobalErrorId();
+ }
+ break;
+
+ case EDlAttrMethod:
+ {
+ aValue = mediaData->Method();
+ }
+ break;
+
+ default:
+ {
+ CLOG_WRITE_1( "Unknown int attrib: %d", aAttribute );
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ }
+ break;
+ }
+
+ iNoRealError = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::GetBoolAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::GetBoolAttributeL( THttpDownloadAttrib aAttribute,
+ TBool& aValue )
+ {
+ LOGGER_ENTERFN( "GetBoolAttributeL" );
+ CLOG_WRITE_1( "Attr(%d): %d", aAttribute );
+
+ iNoRealError = ETrue;
+
+ switch( aAttribute )
+ {
+ case EDlAttrNoContentTypeCheck:
+ {
+ aValue = iNoContentTypeCheck;
+ }
+ break;
+
+ case EDlAttrDisconnectOnReset:
+ {
+ aValue = iDisconnectOnReset;
+ }
+ break;
+
+ case EDlAttrDisconnectOnPause:
+ {
+ aValue = iDisconnectOnPause;
+ }
+ break;
+
+ case EDlAttrNoMedia:
+ {
+ aValue = iNoMedia;
+ }
+ break;
+
+ case EDlAttrRedirected:
+ {
+ aValue = iRedirect;
+ }
+ break;
+
+ case EDlAttrPausable:
+ {
+ aValue = iPausable;
+ }
+ break;
+
+ case EDlAttrHidden:
+ {
+ aValue = iHidden;
+ }
+ break;
+
+ case EDlAttrSilent:
+ {
+ aValue = iSilentMode;
+ }
+ break;
+
+ case EDlAttrContinue:
+ {
+ aValue = iContinueDownload;
+ }
+ break;
+
+ case EDlAttrCodDownload:
+ {
+ aValue = iCodDownload;
+ }
+ break;
+
+ case EDlAttrProgressive:
+ {
+ aValue = iStorage->ProgressiveMode();
+ }
+ break;
+
+ case EDlAttrDestRemovable:
+ {
+ aValue = iStorage->RemovableDest();
+ }
+ break;
+
+ case EDlAttrCodPdAvailable:
+ {
+ aValue = iCodPdAvailable;
+ }
+ break;
+ default:
+ {
+ CLOG_WRITE_1( "Unknown bool attrib: %d", aAttribute );
+
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ }
+ break;
+ }
+
+ iNoRealError = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::GetBoolAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::GetBoolAttributeL( THttpDownloadAttrib aAttribute,
+ TInt32& aMoIndex,
+ TBool& aValue )
+ {
+ LOGGER_ENTERFN( "GetBoolAttributeL" );
+ CLOG_WRITE_1( "Attr(%d): %d", aAttribute );
+
+ if (!iCodDlData)
+ {
+ aValue = 0;
+ return;
+ }
+ if ((aMoIndex <= KNonMoIndex) || (aMoIndex > iCodDlData->Count()))
+ {
+ User::Leave( KErrArgument );
+ }
+
+ CMediaDataBase* mediaData = (*iCodDlData)[aMoIndex];
+ iNoRealError = ETrue;
+
+ switch( aAttribute )
+ {
+ case EDlAttrRedirected:
+ {
+ aValue = mediaData->Redirected();
+ }
+ break;
+
+ case EDlAttrPausable:
+ {
+ aValue = mediaData->Pausable();
+ }
+ break;
+
+ case EDlAttrProgressive:
+ {
+ aValue = mediaData->ProgressiveDownload();
+ }
+ break;
+
+ case EDlAttrDestRemovable:
+ {
+ aValue = mediaData->DesRemovable();
+ }
+ break;
+
+ default:
+ {
+ CLOG_WRITE_1( "Unknown bool attrib: %d", aAttribute );
+
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ }
+ break;
+ }
+
+ iNoRealError = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::GetStringAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* CHttpDownload::GetStringAttributeL( THttpDownloadAttrib aAttribute,
+ TBool& aDelete )
+ {
+ LOGGER_ENTERFN( "GetStringAttributeL" );
+ CLOG_WRITE_1( "Attr(%d): %d", aAttribute );
+
+ iNoRealError = ETrue;
+ HBufC* attr = NULL;
+ HBufC8* attr8 = NULL;
+
+ aDelete = EFalse;
+
+ switch( aAttribute )
+ {
+ case EDlAttrReqUrl:
+ {
+ attr8 = iUrl;
+ }
+ break;
+
+ case EDlAttrRedirUlr:
+ {
+ attr8 = iRedirUrl;
+ }
+ break;
+
+ case EDlAttrCurrentUrl:
+ {
+ attr8 = iCurrentUrl;
+ }
+ break;
+
+ case EDlAttrContentType:
+ {
+ attr8 = iContentType;
+ }
+ break;
+
+ case EDlAttrDDType:
+ {
+ attr8 = iDDType;
+ }
+ break;
+
+ case EDlAttrRealm:
+ {
+ attr8 = iHttpRealm;
+ }
+ break;
+
+ case EDlAttrUsername:
+ {
+ attr8 = iHttpUsername;
+ }
+ break;
+
+ case EDlAttrProxyUsername:
+ {
+ attr8 = iHttpProxyUsername;
+ }
+ break;
+
+ case EDlAttrRequestHeaderAddon:
+ {
+ TChar colon( KColon );
+ TInt32 length( 0 );
+
+ GetIntAttributeL( EDlAttrRequestHeaderAddonLength, length );
+ if( length )
+ {
+ attr8 = HBufC8::NewLC( length );
+
+ aDelete = ETrue;
+
+ for( TInt i = 0; i < iRequestHeaders->Count(); ++i )
+ {
+ TPtrC8 fieldName( *(*iRequestHeaders)[i]->FieldName() );
+ TPtrC8 fieldData( *(*iRequestHeaders)[i]->FieldRawData() );
+
+ attr8->Des().Append( fieldName );
+ attr8->Des().Append( colon );
+ attr8->Des().Append( fieldData );
+ attr8->Des().Append( KHttpFieldSeparator() );
+ }
+
+ CleanupStack::Pop();
+ }
+ }
+ break;
+
+ case EDlAttrDestFilename:
+ {
+ attr = iStorage->DestFilename();
+ }
+ break;
+
+ case EDlAttrLocalFileName:
+ {
+ attr = iStorage->LocalFilename();
+ }
+ break;
+
+ case EDlAttrDdFileName:
+ {
+ attr = iStorage->DdFileName();
+ }
+ break;
+
+ case EDlAttrName:
+ {
+ attr = iDlName;
+ }
+ break;
+
+ // Response headers
+// case EDlAttrCharSet:
+ case EDlAttrResponseCharSet:
+ case EDlAttrResponseAge:
+ case EDlAttrResponseETag:
+ case EDlAttrResponseLocation:
+ case EDlAttrResponseRetryAfter:
+ case EDlAttrResponseServer:
+ case EDlAttrResponseVary:
+ {
+ for( TInt i = 0; KResponseHeaderConvTable[i][0]; ++i )
+ {
+ if( KResponseHeaderConvTable[i][0] == aAttribute )
+ {
+ attr8 = HeaderFieldL( iResponseHeaders, KResponseHeaderConvTable[i][1] );
+ break;
+ }
+ }
+ }
+ break;
+
+ // Request headers
+ case EDlAttrRequestAccept:
+ case EDlAttrRequestAcceptCharSet:
+ case EDlAttrRequestAcceptLanguage:
+ case EDlAttrRequestExpect:
+ case EDlAttrRequestFrom:
+ case EDlAttrRequestHost:
+ case EDlAttrRequestMaxForwards:
+ case EDlAttrRequestPragma:
+ case EDlAttrRequestReferer:
+ case EDlAttrRequestUserAgent:
+ case EDlAttrRequestVary:
+ {
+ for( TInt i = 0; KRequestHeaderConvTable[i][0]; ++i )
+ {
+ if( KRequestHeaderConvTable[i][0] == aAttribute )
+ {
+ attr8 = HeaderFieldL( iRequestHeaders, KRequestHeaderConvTable[i][1] );
+ break;
+ }
+ }
+ }
+ break;
+
+ // Entity header fields
+ case EDlAttrEntityAllow:
+ case EDlAttrEntityContentEncoding:
+ case EDlAttrEntityContentLanguage:
+ case EDlAttrEntityContentLocation:
+ case EDlAttrEntityExpires:
+ case EDlAttrEntityLastModified:
+ {
+ for( TInt i = 0; KEntityHeaderConvTable[i][0]; ++i )
+ {
+ if( KEntityHeaderConvTable[i][0] == aAttribute )
+ {
+ attr8 = HeaderFieldL( iEntityHeaders, KEntityHeaderConvTable[i][1] );
+ break;
+ }
+ }
+ for( TInt i = 0; KResponseHeaderConvTable[i][0]; ++i )
+ {
+ if( KResponseHeaderConvTable[i][0] == aAttribute )
+ {
+ attr8 = HeaderFieldL( iResponseHeaders, KResponseHeaderConvTable[i][1] );
+ break;
+ }
+ }
+ }
+ break;
+
+ // General header fields
+ case EDlAttrGeneralCacheControl:
+ case EDlAttrGeneralDate:
+ case EDlAttrGeneralPragma:
+ case EDlAttrGeneralVia:
+ case EDlAttrGeneralWarning:
+ {
+ for( TInt i = 0; KGeneralHeaderConvTable[i][0]; ++i )
+ {
+ if( KGeneralHeaderConvTable[i][0] == aAttribute )
+ {
+ attr8 = HeaderFieldL( iGeneralHeaders, KGeneralHeaderConvTable[i][1] );
+ break;
+ }
+ }
+ for( TInt i = 0; KResponseHeaderConvTable[i][0]; ++i )
+ {
+ if( KResponseHeaderConvTable[i][0] == aAttribute )
+ {
+ attr8 = HeaderFieldL( iResponseHeaders, KResponseHeaderConvTable[i][1] );
+ break;
+ }
+ }
+ }
+ break;
+
+ case EDlAttrAlbumName:
+ {
+ if (iCodDlData && (iCodDlData->Name().Compare(KNullDesC)))
+ {
+ attr = iCodDlData->Name().AllocL();
+ aDelete = ETrue;
+ }
+ else
+ {
+ attr = iDlName;
+ }
+ }
+ break;
+
+ default:
+ {
+ {
+ CLOG_WRITE_1( "Unknown string8 attrib: %d", aAttribute );
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ }
+ }
+ break;
+ }
+
+ if( !attr && !attr8 )
+ {
+ CLOG_WRITE_1( "NULL attrib: %d", aAttribute );
+ User::Leave( KErrNotFound );
+ }
+
+ if( attr8 )
+ // it is an 8-bit attribute
+ // need to be converted to 16-bits
+ {
+ if( aDelete )
+ {
+ CleanupStack::PushL( attr8 );
+ }
+
+ ReallocateStringL( attr, *attr8 );
+ if( aDelete )
+ {
+ CleanupStack::PopAndDestroy( attr8 );
+ }
+
+ // it is always true because of the conversion.
+ aDelete = ETrue;
+ }
+
+ iNoRealError = EFalse;
+
+ return attr;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::GetStringAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C HBufC* CHttpDownload::GetStringAttributeL( THttpDownloadAttrib aAttribute,
+ TInt32& aMoIndex,
+ TBool& aDelete )
+ {
+ LOGGER_ENTERFN( "GetStringAttributeL" );
+ CLOG_WRITE_1( "Attr(%d): %d", aAttribute );
+
+ if (!iCodDlData)
+ {
+ return (KNullDesC().AllocL());
+ }
+ if ((aMoIndex <= KNonMoIndex) || (aMoIndex > iCodDlData->Count()))
+ {
+ User::Leave( KErrArgument );
+ }
+
+ CMediaDataBase* mediaData = (*iCodDlData)[aMoIndex];
+ iNoRealError = ETrue;
+ HBufC* attr = NULL;
+ HBufC8* attr8 = NULL;
+
+ aDelete = EFalse;
+
+ switch( aAttribute )
+ {
+ case EDlAttrReqUrl:
+ {
+ attr8 = mediaData->Url().AllocL();
+ aDelete = ETrue;
+ }
+ break;
+
+ case EDlAttrRedirUlr:
+ {
+ attr8 = mediaData->RedirUrl().AllocL();
+ aDelete = ETrue;
+ }
+ break;
+
+ case EDlAttrContentType:
+ {
+ attr8 = mediaData->Type().AllocL();
+ aDelete = ETrue;
+ }
+ break;
+
+ case EDlAttrDestFilename:
+ {
+ attr = mediaData->DestFilename().AllocL();
+ aDelete = ETrue;
+ }
+ break;
+
+ case EDlAttrName:
+ {
+ if (aMoIndex == iActiveDownload)
+ {
+ attr = iDlName;
+ }
+ else
+ {
+ attr = mediaData->Name().AllocL();
+ aDelete = ETrue;
+ }
+ }
+ break;
+
+ default:
+ {
+ {
+ CLOG_WRITE_1( "Unknown string8 attrib: %d", aAttribute );
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ }
+ }
+ break;
+ }
+
+ if( !attr && !attr8 )
+ {
+ CLOG_WRITE_1( "NULL attrib: %d", aAttribute );
+ User::Leave( KErrNotFound );
+ }
+
+ if( attr8 )
+ // it is an 8-bit attribute
+ // need to be converted to 16-bits
+ {
+ if( aDelete )
+ {
+ CleanupStack::PushL( attr8 );
+ }
+
+ ReallocateStringL( attr, *attr8 );
+ if( aDelete )
+ {
+ CleanupStack::PopAndDestroy( attr8 );
+ }
+
+ // it is always true because of the conversion.
+ aDelete = ETrue;
+ }
+
+ iNoRealError = EFalse;
+
+ return attr;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::GetString8AttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C HBufC8* CHttpDownload::GetString8AttributeL( THttpDownloadAttrib aAttribute,
+ TBool& aDelete )
+ {
+ LOGGER_ENTERFN( "GetString8AttributeL" );
+ CLOG_WRITE_1( "Attr(%d): %d", aAttribute );
+
+ iNoRealError = ETrue;
+ HBufC8* attr = NULL;
+ HBufC* attr16 = NULL;
+
+ aDelete = EFalse;
+
+ switch( aAttribute )
+ {
+ case EDlAttrReqUrl:
+ {
+ attr = iUrl;
+ }
+ break;
+
+ case EDlAttrRedirUlr:
+ {
+ attr = iRedirUrl;
+ }
+ break;
+
+ case EDlAttrCurrentUrl:
+ {
+ attr = iCurrentUrl;
+ }
+ break;
+
+ case EDlAttrRealm:
+ {
+ attr = iHttpRealm;
+ }
+ break;
+
+ case EDlAttrUsername:
+ {
+ attr = iHttpUsername;
+ }
+ break;
+
+ case EDlAttrProxyUsername:
+ {
+ attr = iHttpProxyUsername;
+ }
+ break;
+
+ case EDlAttrContentType:
+ {
+ attr = iContentType;
+ }
+ break;
+
+ case EDlAttrDDType:
+ {
+ attr = iDDType;
+ }
+ break;
+
+ case EDlAttrRequestHeaderAddon:
+ {
+ TChar colon( KColon );
+ TInt32 length( 0 );
+
+ GetIntAttributeL( EDlAttrRequestHeaderAddonLength, length );
+ if( length )
+ {
+ attr = HBufC8::NewLC( length );
+
+ for( TInt i = 0; i < iRequestHeaders->Count(); ++i )
+ {
+ TPtrC8 fieldName( *(*iRequestHeaders)[i]->FieldName() );
+ TPtrC8 fieldData( *(*iRequestHeaders)[i]->FieldRawData() );
+
+ attr->Des().Append( fieldName );
+ attr->Des().Append( colon );
+ attr->Des().Append( fieldData );
+ attr->Des().Append( KHttpFieldSeparator() );
+ }
+
+ CleanupStack::Pop();
+ aDelete = ETrue;
+ }
+ }
+ break;
+
+ case EDlAttrResponseCharSet:
+ // Response headers
+ case EDlAttrResponseAge:
+ case EDlAttrResponseETag:
+ case EDlAttrResponseLocation:
+ case EDlAttrResponseRetryAfter:
+ case EDlAttrResponseServer:
+ case EDlAttrResponseVary:
+ {
+ for( TInt i = 0; KResponseHeaderConvTable[i][0]; ++i )
+ {
+ if( KResponseHeaderConvTable[i][0] == aAttribute )
+ {
+ attr = HeaderFieldL( iResponseHeaders, KResponseHeaderConvTable[i][1] );
+ }
+ }
+ }
+ break;
+
+ // Request headers
+ case EDlAttrRequestAccept:
+ case EDlAttrRequestAcceptCharSet:
+ case EDlAttrRequestAcceptLanguage:
+ case EDlAttrRequestExpect:
+ case EDlAttrRequestFrom:
+ case EDlAttrRequestHost:
+ case EDlAttrRequestMaxForwards:
+ case EDlAttrRequestPragma:
+ case EDlAttrRequestReferer:
+ case EDlAttrRequestUserAgent:
+ case EDlAttrRequestVary:
+ {
+ for( TInt i = 0; KRequestHeaderConvTable[i][0]; ++i )
+ {
+ if( KRequestHeaderConvTable[i][0] == aAttribute )
+ {
+ attr = HeaderFieldL( iRequestHeaders, KRequestHeaderConvTable[i][1] );
+ break;
+ }
+ }
+ }
+ break;
+
+ // Entity header fields
+ case EDlAttrEntityAllow:
+ case EDlAttrEntityContentEncoding:
+ case EDlAttrEntityContentLanguage:
+ case EDlAttrEntityContentLocation:
+ case EDlAttrEntityExpires:
+ case EDlAttrEntityLastModified:
+ {
+ for( TInt i = 0; KEntityHeaderConvTable[i][0]; ++i )
+ {
+ if( KEntityHeaderConvTable[i][0] == aAttribute )
+ {
+ attr = HeaderFieldL( iEntityHeaders, KEntityHeaderConvTable[i][1] );
+ break;
+ }
+ }
+ for( TInt i = 0; KResponseHeaderConvTable[i][0]; ++i )
+ {
+ if( KResponseHeaderConvTable[i][0] == aAttribute )
+ {
+ attr = HeaderFieldL( iResponseHeaders, KResponseHeaderConvTable[i][1] );
+ }
+ }
+ }
+ break;
+
+ // General header fields
+ case EDlAttrGeneralCacheControl:
+ case EDlAttrGeneralDate:
+ case EDlAttrGeneralPragma:
+ case EDlAttrGeneralVia:
+ case EDlAttrGeneralWarning:
+ {
+ for( TInt i = 0; KGeneralHeaderConvTable[i][0]; ++i )
+ {
+ if( KGeneralHeaderConvTable[i][0] == aAttribute )
+ {
+ attr = HeaderFieldL( iGeneralHeaders, KGeneralHeaderConvTable[i][1] );
+ break;
+ }
+ }
+ for( TInt i = 0; KResponseHeaderConvTable[i][0]; ++i )
+ {
+ if( KResponseHeaderConvTable[i][0] == aAttribute )
+ {
+ attr = HeaderFieldL( iResponseHeaders, KResponseHeaderConvTable[i][1] );
+ }
+ }
+ }
+ break;
+
+ case EDlAttrHashedMsgBody:
+ {
+ attr = iHashedMsgBody;
+ }
+ break;
+
+ case EDlAttrMediaType:
+ {
+ attr = iMediaType;
+ }
+ break;
+
+ case EDlAttrMediaTypeBoundary:
+ {
+ attr = GetParamFromMediaTypeL( KBoundary() ).AllocL();
+ aDelete = ETrue;
+ }
+ break;
+
+ default:
+ {
+ {
+ CLOG_WRITE_1( "Unknown string8 attrib: %d", aAttribute );
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ }
+ }
+ break;
+ }
+
+ if( !attr && !attr16 )
+ {
+ CLOG_WRITE_1( "NULL attrib: %d", aAttribute );
+ User::Leave( KErrNotFound );
+ }
+
+ if( attr16 )
+ // it is an 8-bit attribute
+ // need to be converted to 16-bits
+ {
+ if( aDelete )
+ {
+ CleanupStack::PushL( attr16 );
+ }
+ ReallocateStringL( attr, *attr16 );
+ if( aDelete )
+ {
+ CleanupStack::PopAndDestroy( attr16 );
+ }
+
+ // it is always true because of the conversion.
+ aDelete = ETrue;
+ }
+
+ iNoRealError = EFalse;
+
+ return attr;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::GetString8AttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C HBufC8* CHttpDownload::GetString8AttributeL( THttpDownloadAttrib aAttribute,
+ TInt32& aMoIndex,
+ TBool& aDelete )
+ {
+ LOGGER_ENTERFN( "GetString8AttributeL" );
+ CLOG_WRITE_1( "Attr(%d): %d", aAttribute );
+
+ if (!iCodDlData)
+ {
+ return (KNullDesC8().AllocL());
+ }
+ if ((aMoIndex <= KNonMoIndex) || (aMoIndex > iCodDlData->Count()))
+ {
+ User::Leave( KErrArgument );
+ }
+
+ CMediaDataBase* mediaData = (*iCodDlData)[aMoIndex];
+ iNoRealError = ETrue;
+ HBufC8* attr = NULL;
+ HBufC* attr16 = NULL;
+
+ aDelete = EFalse;
+
+ switch( aAttribute )
+ {
+ case EDlAttrReqUrl:
+ {
+ attr = mediaData->Url().AllocL();
+ aDelete = ETrue;
+ }
+ break;
+
+ case EDlAttrRedirUlr:
+ {
+ attr = mediaData->RedirUrl().AllocL();
+ aDelete = ETrue;
+ }
+ break;
+
+ case EDlAttrContentType:
+ {
+ attr = mediaData->Type().AllocL();
+ aDelete = ETrue;
+ }
+ break;
+
+ default:
+ {
+ {
+ CLOG_WRITE_1( "Unknown string8 attrib: %d", aAttribute );
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ }
+ }
+ break;
+ }
+
+ if( !attr && !attr16 )
+ {
+ CLOG_WRITE_1( "NULL attrib: %d", aAttribute );
+ User::Leave( KErrNotFound );
+ }
+
+ if( attr16 )
+ // it is an 8-bit attribute
+ // need to be converted to 16-bits
+ {
+ if( aDelete )
+ {
+ CleanupStack::PushL( attr16 );
+ }
+ ReallocateStringL( attr, *attr16 );
+ if( aDelete )
+ {
+ CleanupStack::PopAndDestroy( attr16 );
+ }
+
+ // it is always true because of the conversion.
+ aDelete = ETrue;
+ }
+
+ iNoRealError = EFalse;
+
+ return attr;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::GetFileHandleAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C RFile* CHttpDownload::GetFileHandleAttributeL()
+ {
+ LOGGER_ENTERFN( "GetFileHandleAttributeL" );
+
+ if( !iStorage->File() )
+ // destination file is not opened
+ {
+ User::Leave( KErrArgument );
+ }
+
+ return iStorage->File();
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetIntAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::SetIntAttributeL( THttpDownloadAttrib aAttribute,
+ const TInt32 aValue )
+ {
+ LOGGER_ENTERFN( "SetIntAttributeL" );
+ CLOG_WRITE_2( "Attr(%d): %d", aAttribute, aValue );
+ TBool store( ETrue );
+
+ iNoRealError = ETrue;
+
+ switch( aAttribute )
+ {
+ case EDlAttrUserData:
+ {
+ iUserData = aValue;
+ }
+ break;
+
+ case EDlAttrAction:
+ {
+ TBool PdSupported(EFalse);
+
+ iAction = (THttpDownloadMgrAction)aValue;
+
+ if(iClAppInstance)
+ {
+ TRAP_IGNORE(iClAppInstance->GetBoolAttributeL(EDlMgrProgressiveDownload, PdSupported));
+ }
+
+ if(!PdSupported)
+ {
+ iAction = (THttpDownloadMgrAction)(iAction & ~(EPdLaunch));
+ }
+ }
+ break;
+
+ case EDlAttrPort:
+ iPort = aValue;
+ break;
+
+ case EDlAttrRestartAction:
+ iRestartAction = (THttpRestartActions)aValue;
+ break;
+
+ case EDlAttrAuthScheme:
+ {
+ if( iContinueDownload && iDlState == EHttpDlMultipleMOStarted )
+ {
+ iAuthScheme = aValue;
+ }
+ }
+ break;
+
+ case EDlAttrLength:
+ {
+ if( (iContinueDownload && iDlState == EHttpDlMultipleMOStarted) ||
+ ( iCodDownload && iDlState == EHttpDlInprogress ) )
+ {
+ iStorage->SetLength( aValue );
+ }
+ else
+ {
+ store = EFalse;
+ }
+ }
+ break;
+
+ case EDlAttrMultipleMOLength:
+ {
+ iMoLength = aValue;
+ }
+ break;
+
+ case EDlAttrDownloadedSize:
+ {
+ if( (iCodDownload || iContinueDownload) && iDlState == EHttpDlInprogress )
+ {
+ iStorage->SetDownloadedSize( aValue );
+ // Calculate downloaded size of current media object from
+ // album downloaded size.
+ TInt dlSize = iStorage->DownloadedSize();
+ if( iCodDlData )
+ {
+ for (TInt index = 0; index < iCodDlData->Count() ; ++index)
+ {
+ if( iActiveDownload - 1 == index )
+ {
+ //the size of active download has already been taken into account
+ continue;
+ }
+ CMediaDataBase* moData = (*iCodDlData)[index+1];
+ if ((moData->State() == ESucceeded) || (moData->State() == EInProgress))
+ dlSize += moData->DownloadedSize();
+ }
+ iStorage->SetMoDownloadedSize(dlSize);
+ }
+ if( iStorage->Length() != KDefaultContentLength &&
+ iStorage->DownloadedSize() > iStorage->Length() )
+ // we don't know actually how many bytes will come down.
+ {
+ CLOG_WRITE( "Length modified" );
+ iStorage->SetLength( KDefaultContentLength );
+ StoreDownloadInfoL();
+ }
+ TriggerEvent( EHttpDlInprogress, EHttpProgResponseBodyReceived );
+ }
+
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrSucceeded:
+ {
+ if(!aValue)
+ DownloadSucceededL();
+ else
+ iMoDownloadCompleted = ETrue;//Download of MO has been Completed so change State ,But PD is on
+ //So MOVE will be issued by PD Client
+
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrFailed:
+ {
+ // This is an exeption!
+ iNoRealError = EFalse;
+ OnError( aValue, ETransactionFailed );
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrDefaultEvent:
+ {
+ }
+ break;
+
+ case EDlAttrMethod:
+ {
+ if( iContinueDownload && iDlState == EHttpDlMultipleMOStarted &&
+ ( aValue == EMethodGET ||
+ aValue == EMethodPOST ||
+ aValue == EMethodHEAD ) )
+ {
+ iMethod = (THttpMethod)aValue;
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+ break;
+
+ case EDlAttrFotaPckgId:
+ {
+ iFotaPckgId = aValue;
+ store = EFalse;
+ }
+ break;
+ case EDlAttrActiveDownload:
+ {
+ iActiveDownload = aValue;
+
+ // Active MO changed. Notify clients.
+ TriggerEvent( EHttpDlCreated, EHttpProgNone );
+ }
+ break;
+
+ case EDlAttrActivePlayedDownload:
+ {
+ iActivePlayedDownload = aValue;
+ }
+
+ break;
+ default:
+ {
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ }
+ break;
+ }
+
+ UpdatePausable();
+
+ iNoRealError = EFalse;
+
+ if( store )
+ {
+ StoreDownloadInfoL();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetBoolAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::SetBoolAttributeL( THttpDownloadAttrib aAttribute,
+ const TBool aValue )
+ {
+ LOGGER_ENTERFN( "SetBoolAttributeL" );
+ CLOG_WRITE_2( "Attr(%d): %d", aAttribute, aValue );
+ TBool store( ETrue );
+
+ iNoRealError = ETrue;
+
+ switch( aAttribute )
+ {
+ case EDlAttrNoContentTypeCheck:
+ {
+ iNoContentTypeCheck = aValue;
+ }
+ break;
+
+ case EDlAttrDisconnectOnReset:
+ {
+ iDisconnectOnReset = aValue;
+ }
+ break;
+
+ case EDlAttrDisconnectOnPause:
+ {
+ iDisconnectOnPause = aValue;
+ }
+ break;
+
+ case EDlAttrContinue:
+ {
+ if( iDlState == EHttpDlMultipleMOStarted )
+ {
+ iContinueDownload = aValue;
+ }
+ else
+ {
+ User::Leave( KErrInUse );
+ }
+
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrHidden:
+ {
+ iHidden = aValue;
+ }
+ break;
+
+ case EDlAttrSilent:
+ {
+ iSilentMode = aValue;
+ }
+ break;
+
+ case EDlAttrCodDownload:
+ {
+ SetCodFlag( aValue );
+ }
+ break;
+
+ case EDlAttrProgressive:
+ {
+ TBool PdSupported(EFalse);
+
+ if(iClAppInstance)
+ {
+ TRAP_IGNORE(iClAppInstance->GetBoolAttributeL(EDlMgrProgressiveDownload, PdSupported));
+ }
+
+ if(PdSupported)
+ {
+ iStorage->SetProgressiveMode( aValue );
+
+ if(!aValue)
+ {
+ iActivePlayedDownload = 0;
+ }
+
+ if (iCodDlData)
+ {
+ // Update for Active media object.
+ TInt active = iActiveDownload;
+ CMediaDataBase* mediaData = (*iCodDlData)[active];
+ mediaData->SetProgressiveDownload( aValue );
+ }
+
+ if( iProgState != EHttpProgMovingContentFile )
+ {
+ TriggerEvent( iDlState, aValue ? EHttpDlProgProgressive : EHttpDlProgNonProgressive);
+ }
+ }
+ else
+ {
+ TriggerEvent( iDlState, EHttpDlProgNonProgressive);
+ }
+ }
+ break;
+
+ case EDlAttrCodDescriptorAccepted:
+ {
+ TriggerEvent( EHttpDlInprogress, EHttpProgCodDescriptorAccepted );
+ }
+ break;
+
+ case EDlAttrCodLoadEnd:
+ {
+ SetDownloadStatus(EHttpProgCodLoadEnd,EHttpDlInprogress);
+ }
+ break;
+
+ case EDlAttrCodPdAvailable:
+ {
+ iCodPdAvailable = aValue;
+ TriggerEvent( EHttpDlInprogress, EHttpProgCodPdAvailable );
+ }
+ break;
+
+ case EDlAttrDestRemovable:
+ {
+ if( iCodDownload )
+ {
+ iStorage->SetRemovableDest( aValue );
+
+ if (iCodDlData)
+ {
+ // Update for Active media object.
+ TInt active = iActiveDownload;
+ CMediaDataBase* mediaData = (*iCodDlData)[active];
+ mediaData->SetDesRemovable( aValue );
+ }
+ }
+ }
+ break;
+
+ case EDlAttrDownloadUpdatedDDUri:
+ {
+ iUpdatedDDUriSet = aValue;
+ }
+ break;
+
+
+ case EDlAttrCodPausable:
+ {
+ iPausable = aValue;
+
+ // Update for Active media object.
+ TInt active = iActiveDownload;
+ CMediaDataBase* mediaData = (*iCodDlData)[active];
+ mediaData->SetPausable( aValue );
+
+ // inform client about change
+ TriggerEvent( iPausable ? EHttpDlPausable : EHttpDlNonPausable );
+ }
+ break;
+
+
+ default:
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ break;
+ }
+
+ UpdatePausable();
+
+ iNoRealError = EFalse;
+
+ if( store )
+ {
+ StoreDownloadInfoL();
+ }
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetStringAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::SetStringAttributeL( THttpDownloadAttrib aAttribute, const TInt32 aMOIndex,
+ const TDesC16& aValue )
+ {
+ LOGGER_ENTERFN( "SetStringAttributeL" );
+ CLOG_WRITE_2( "Attr(%d - %d)", aAttribute, aValue.Length () );
+
+ iNoRealError = ETrue;
+
+ CheckAttribMaxLengthL( aAttribute, aValue );
+
+ switch( aAttribute )
+ {
+ case EDlAttrDestFilename:
+ {
+ TBool updateFName = EFalse;
+
+ if( iDlState == EHttpDlMultipleMOStarted ||
+ iDlState == EHttpDlMultipleMOCompleted ||
+ iCodDownload )
+ // cannot set this attribute while
+ // download is in progress
+ {
+ if( !aValue.Length() )
+ {
+ updateFName = ETrue;
+ }
+ else if( iClientApp->Engine()->Fs().IsValidName( aValue ) )
+ {
+ TUint attrib;
+ TInt attErr = iClientApp->Engine()->Fs().Att( aValue, attrib );
+
+ if( (attErr == KErrNone && !(attrib & KEntryAttDir)) ||
+ attErr == KErrNotFound )
+ // File exists and not directory or not exists
+ {
+ updateFName = ETrue;
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+ else
+ // Invalid filename passed
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+ else
+ {
+ User::Leave( KErrInUse );
+ }
+
+ if (updateFName)
+ {
+ iStorage->UpdateDestinationFilenameL( aValue, ETrue );
+ if (iCodDlData)
+ {
+ CMediaDataBase* mediaData = (*iCodDlData)[aMOIndex];
+ mediaData->SetDestFilenameL( aValue );
+ }
+ }
+ }
+ break;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetStringAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::SetStringAttributeL( THttpDownloadAttrib aAttribute,
+ const TDesC16& aValue )
+ {
+ LOGGER_ENTERFN( "SetStringAttributeL" );
+ CLOG_WRITE_2( "Attr(%d - %d)", aAttribute, aValue.Length () );
+ TBool store( ETrue );
+
+ iNoRealError = ETrue;
+
+ CheckAttribMaxLengthL( aAttribute, aValue );
+
+ switch( aAttribute )
+ {
+ case EDlAttrReqUrl:
+ // this is only for internal testing usage!!!
+ {
+ if( iDlState == EHttpDlMultipleMOStarted )
+ {
+ ReallocateStringL( iUrl, aValue, KMaxUrlLength );
+ ParseRequestedUrlL(); // iCurrentUrl is initialized there
+ ParseDownloadNameL();
+ }
+ }
+ break;
+
+ case EDlAttrContentType:
+ {
+ if( iDlState == EHttpDlInprogress )
+ {
+ CLOG_WRITE( "EDlAttrContentType updated" );
+ ReallocateStringL( iContentType, aValue, KMaxContentTypeLength );
+ TriggerEvent( EHttpDlInprogress, EHttpProgContentTypeChanged );
+
+ // Update for Active media object.
+ HBufC8* type8 = HBufC8::NewLC( aValue.Length() );
+ type8->Des().Copy( aValue );
+
+ if (iCodDlData)
+ {
+ TInt active = iActiveDownload;
+ CMediaDataBase* mediaData = (*iCodDlData)[active];
+ mediaData->SetTypeL( type8->Des() );
+ CleanupStack::PopAndDestroy( type8 );
+ }
+ }
+ }
+ break;
+
+ case EDlAttrRealm:
+ {
+ if( iContinueDownload && iDlState == EHttpDlMultipleMOStarted )
+ {
+ ReallocateStringL( iHttpRealm, aValue, KMaxRealmLength );
+ }
+
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrUsername:
+ {
+ ReallocateStringL( iHttpUsername, aValue, KMaxDefAttrLength );
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrPassword:
+ {
+ ReallocateStringL( iHttpPassword, aValue, KMaxDefAttrLength );
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrProxyRealm:
+ {
+ if( iContinueDownload && iDlState == EHttpDlMultipleMOStarted )
+ {
+ ReallocateStringL( iHttpProxyRealm, aValue, KMaxRealmLength );
+ }
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrProxyUsername:
+ {
+ ReallocateStringL( iHttpProxyUsername, aValue, KMaxDefAttrLength );
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrProxyPassword:
+ {
+ ReallocateStringL( iHttpProxyPassword, aValue, KMaxDefAttrLength );
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrDestFilename:
+ {
+ TBool updateFName = EFalse;
+
+ if( iDlState == EHttpDlMultipleMOStarted ||
+ iDlState == EHttpDlMultipleMOCompleted ||
+ iCodDownload )
+ // cannot set this attribute while
+ // download is in progress
+ {
+ if( !aValue.Length() )
+ {
+ updateFName = ETrue;
+ }
+ else if( iClientApp->Engine()->Fs().IsValidName( aValue ) )
+ {
+ TUint attrib;
+ TInt attErr = iClientApp->Engine()->Fs().Att( aValue, attrib );
+
+ if( (attErr == KErrNone && !(attrib & KEntryAttDir)) ||
+ attErr == KErrNotFound )
+ // File exists and not directory or not exists
+ {
+ updateFName = ETrue;
+ }
+ else
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+ else
+ // Invalid filename passed
+ {
+ User::Leave( KErrArgument );
+ }
+ }
+ else
+ {
+ User::Leave( KErrInUse );
+ }
+
+ if (updateFName)
+ {
+ iStorage->UpdateDestinationFilenameL( aValue, ETrue );
+
+ if (iCodDlData)
+ {
+ TInt moIndex(0);
+ if( iActiveDownload != iActivePlayedDownload && iStorage->ProgressiveDownload() )
+ {
+ //MP has set the Destination File Name
+ moIndex = iActivePlayedDownload;
+ }
+ else
+ {
+ // Update for Active media object.
+ moIndex = iActiveDownload;
+ }
+ CMediaDataBase* mediaData = (*iCodDlData)[moIndex];
+ mediaData->SetDestFilenameL( aValue );
+ }
+ }
+ }
+ break;
+
+ case EDlAttrLocalFileName:
+ {
+ iStorage->SetLocalFilenameL(aValue);
+ }
+ break;
+
+ case EDlAttrRequestHeaderAddon:
+ {
+ if( aValue.Length() )
+ {
+ HBufC8* value = HBufC8::NewLC( aValue.Length() );
+
+ value->Des().Copy( aValue );
+ ParseRequestHeaderAddOnL( *value );
+
+ CleanupStack::PopAndDestroy( value );
+ }
+ }
+ break;
+
+ case EDlAttrResponseHeader:
+ {
+ if( iContinueDownload && iDlState == EHttpDlMultipleMOStarted )
+ {
+ HBufC8* temp = HBufC8::NewLC( aValue.Length() );
+ temp->Des().Copy( aValue );
+
+ ContinueDownloadStoreResponseHeaderL( *temp );
+
+ CleanupStack::PopAndDestroy( temp );
+ }
+ }
+ break;
+
+ case EDlAttrName:
+ {
+ if( iCodDownload )
+ {
+ SetDownloadNameL( aValue );
+
+ if (iCodDlData)
+ {
+ // Update for Active media object.
+ TInt active = iActiveDownload;
+ CMediaDataBase* mediaData = (*iCodDlData)[active];
+ mediaData->SetNameL( aValue );
+ }
+ }
+ }
+ break;
+
+ // Request headers
+ case EDlAttrRequestAccept:
+ case EDlAttrRequestAcceptCharSet:
+ case EDlAttrRequestAcceptLanguage:
+ case EDlAttrRequestExpect:
+ case EDlAttrRequestFrom:
+ case EDlAttrRequestHost:
+ case EDlAttrRequestMaxForwards:
+ case EDlAttrRequestPragma:
+ case EDlAttrRequestReferer:
+ case EDlAttrRequestUserAgent:
+ case EDlAttrRequestVary:
+ {
+ HBufC8* value = HBufC8::NewLC( aValue.Length() );
+
+ AddHeaderL( aAttribute, *value, KRequestHeaderConvTable, iRequestHeaders );
+
+ CleanupStack::PopAndDestroy( value );
+ }
+ break;
+
+ // General header fields
+ case EDlAttrGeneralCacheControl:
+ case EDlAttrGeneralPragma:
+ {
+ HBufC8* value = HBufC8::NewLC( aValue.Length() );
+
+ AddHeaderL( aAttribute, *value, KGeneralHeaderConvTable, iGeneralHeaders );
+
+ CleanupStack::PopAndDestroy( value );
+ }
+ break;
+
+ default:
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ break;
+ }
+
+ UpdatePausable();
+
+ iNoRealError = EFalse;
+
+ if( store )
+ {
+ StoreDownloadInfoL();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetStringAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::SetStringAttributeL( THttpDownloadAttrib aAttribute,
+ const TDesC8& aValue )
+ {
+ LOGGER_ENTERFN( "SetStringAttributeL(8)" );
+ CLOG_WRITE_2( "Attr(%d - %d)", aAttribute, aValue.Length () );
+ TBool store( ETrue );
+
+ iNoRealError = ETrue;
+
+ CheckAttribMaxLengthL( aAttribute, aValue );
+
+ switch( aAttribute )
+ {
+ case EDlAttrReqUrl:
+ // this is only for internal testing usage!!!
+ {
+ if( iDlState == EHttpDlMultipleMOStarted )
+ {
+ ReallocateStringL( iUrl, aValue, KMaxUrlLength );
+ ParseRequestedUrlL(); // iCurrentUrl is initialized there
+ ParseDownloadNameL();
+ }
+ }
+ break;
+
+ case EDlAttrContentType:
+ {
+ if( iDlState == EHttpDlInprogress )
+ {
+ ReallocateStringL( iContentType, aValue, KMaxContentTypeLength );
+ TriggerEvent( EHttpDlInprogress, EHttpProgContentTypeChanged );
+ }
+ else if (iDlState == EHttpDlMultipleMOCompleted )//Allow to change content type even if state is completed
+ {
+ ReallocateStringL( iContentType, aValue, KMaxContentTypeLength );
+ //No need to trigger any event
+ }
+ }
+ break;
+
+ case EDlAttrRealm:
+ {
+ if( iContinueDownload && iDlState == EHttpDlMultipleMOStarted )
+ {
+ ReallocateStringL( iHttpRealm, aValue, KMaxRealmLength );
+ }
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrUsername:
+ {
+ ReallocateStringL( iHttpUsername, aValue, KMaxDefAttrLength );
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrPassword:
+ {
+ ReallocateStringL( iHttpPassword, aValue, KMaxDefAttrLength );
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrProxyRealm:
+ {
+ if( iContinueDownload && iDlState == EHttpDlMultipleMOStarted )
+ {
+ ReallocateStringL( iHttpProxyRealm, aValue, KMaxRealmLength );
+ }
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrProxyUsername:
+ {
+ ReallocateStringL( iHttpProxyUsername, aValue, KMaxDefAttrLength );
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrProxyPassword:
+ {
+ ReallocateStringL( iHttpProxyPassword, aValue, KMaxDefAttrLength );
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrRequestHeaderAddon:
+ {
+ if( aValue.Length() )
+ {
+ ParseRequestHeaderAddOnL( aValue );
+ }
+ }
+ break;
+
+ case EDlAttrResponseHeader:
+ {
+ if( iContinueDownload && iDlState == EHttpDlMultipleMOStarted )
+ {
+ ContinueDownloadStoreResponseHeaderL( aValue );
+ }
+ }
+ break;
+
+ // Request headers
+ case EDlAttrRequestAccept:
+ case EDlAttrRequestAcceptCharSet:
+ case EDlAttrRequestAcceptLanguage:
+ case EDlAttrRequestExpect:
+ case EDlAttrRequestFrom:
+ case EDlAttrRequestHost:
+ case EDlAttrRequestMaxForwards:
+ case EDlAttrRequestPragma:
+ case EDlAttrRequestReferer:
+ case EDlAttrRequestUserAgent:
+ case EDlAttrRequestVary:
+ {
+ AddHeaderL( aAttribute, aValue, KRequestHeaderConvTable, iRequestHeaders );
+ }
+ break;
+
+ // General header fields
+ case EDlAttrGeneralCacheControl:
+ case EDlAttrGeneralPragma:
+ {
+ AddHeaderL( aAttribute, aValue, KGeneralHeaderConvTable, iGeneralHeaders );
+ }
+ break;
+
+ case EDlAttrHashedMsgBody:
+ {
+ ReallocateStringL( iHashedMsgBody, aValue, KHashLength );
+ }
+ break;
+
+ case EDlAttrRedirectedPermanently:
+ {
+ RedirectedPermanentlyL( aValue );
+
+ if (iCodDlData)
+ {
+ // Update for Active media object.
+ TInt active = iActiveDownload;
+ CMediaDataBase* mediaData = (*iCodDlData)[active];
+ if (!mediaData->Redirected())
+ mediaData->SetRedirUrlL( aValue );
+ }
+ }
+ break;
+
+ case EDlAttrRedirectedTemporary:
+ {
+ RedirectedTemporaryL( aValue );
+
+ if (iCodDlData)
+ {
+ // Update for Active media object.
+ TInt active = iActiveDownload;
+ CMediaDataBase* mediaData = (*iCodDlData)[active];
+ mediaData->SetRedirected( ETrue );
+ }
+ }
+ break;
+
+ case EDlAttrContinueBody:
+ {
+ iNoRealError = EFalse;
+ ResponseBodyReceivedL( aValue );
+ store = EFalse;
+ }
+ break;
+
+ case EDlAttrUpdatedDDUri:
+ {
+ ReallocateStringL( iUrl, aValue, KMaxUrlLength );
+ }
+ break;
+
+ default:
+#ifdef __WINS__
+ DMPanic( KErrArgument );
+#else
+ User::Leave( KErrArgument );
+#endif
+ break;
+ }
+
+ UpdatePausable();
+
+ iNoRealError = EFalse;
+
+ if( store )
+ {
+ StoreDownloadInfoL();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetStringAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::SetFileHandleAttributeL( RFile* aFile )
+ {
+ LOGGER_ENTERFN( "SetFileHandleAttributeL" );
+
+ iStorage->AdoptFileHandleL( aFile );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetDownloadDataAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::SetDownloadDataAttributeL( HBufC8* dlData )
+ {
+ LOGGER_ENTERFN( "SetDownloadDataAttributeL" );
+
+ if (iCodDlData)
+ {
+ delete iCodDlData;
+ iCodDlData = NULL;
+ }
+
+ iCodDlData = CDownloadDataServ::NewL(*dlData);
+ TInt downloadedSize = 0 ;
+ TBool activeDownloadChanged = EFalse;
+
+ iMoLength = 0 ;
+ for ( TInt i = 1; i <= iCodDlData->Count() ; ++i )
+ {
+ downloadedSize = downloadedSize + (*iCodDlData)[i]->DownloadedSize();
+ iMoLength += (*iCodDlData)[i]->Size();
+
+ // Below code is executed only when download is paused.
+ // Set the ActiveDownload, DownloadedSize and Length.
+ if (((*iCodDlData)[i]->State() == EInProgress) && !activeDownloadChanged)
+ {
+ iActiveDownload = i;
+ iStorage->SetDownloadedSize( (*iCodDlData)[i]->DownloadedSize() );
+ iStorage->SetLength( (*iCodDlData)[i]->Size() );
+ activeDownloadChanged = ETrue;
+ }
+ }
+ iStorage->SetMoDownloadedSize( downloadedSize );
+ }
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetTrackDataAttributeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::SetTrackDataAttributeL( TInt aIndex, HBufC8* dlData )
+ {
+ LOGGER_ENTERFN( "SetTrackDataAttributeL" );
+
+ if (iCodDlData)
+ {
+ CMediaDataServ* updatedMediaData = CMediaDataServ::NewL(*dlData);
+ CMediaDataBase* mediaData = (*iCodDlData)[aIndex];
+ mediaData->SetNameL(updatedMediaData->Name());
+ mediaData->SetUrlL(updatedMediaData->Url());
+ mediaData->SetSize(updatedMediaData->Size());
+ mediaData->SetIconL( updatedMediaData->Icon() );
+ mediaData->SetSourceUriL( updatedMediaData->SourceUri() );
+ mediaData->SetProgressiveDownload( updatedMediaData->ProgressiveDownload() );
+ mediaData->SetState( updatedMediaData->State() );
+ mediaData->SetResult( updatedMediaData->Result() );
+ mediaData->SetDownloadedSize( updatedMediaData->DownloadedSize() );
+ mediaData->SetDestFilenameL( updatedMediaData->DestFilename() );
+ mediaData->SetTempFilenameL( updatedMediaData->DestFilename() );
+
+ mediaData->ResetTypes();
+ for (TInt type = 0; type < updatedMediaData->TypesCount(); ++type)
+ mediaData->AddTypeL( updatedMediaData->Types().MdcaPoint(type) );
+
+ TInt result = updatedMediaData->Result();
+
+ //New track download Begins.Hence make track size as 0
+ //iStorage->SetDownloadedSize ( 0 );
+ // Active MO completed OR failed. Notify clients.
+ if (mediaData->Result() == 0)
+ {
+ iGlobalErrorId = 0;
+ iLastError = 0;
+ TriggerEvent( EHttpDlCompleted, EHttpProgNone );
+ }
+ else
+ {
+ // Set the error codes for single track albums
+ if(iCodDlData->Count() == 1)
+ {
+ if ( result <= -1000 )
+ {
+ iGlobalErrorId = KErrGeneral;
+ iLastError = (THttpDownloadMgrError)result;
+ }
+ else
+ {
+ iGlobalErrorId = result;
+ iLastError = EGeneral;
+ }
+ }
+ TriggerEvent( EHttpDlFailed, EHttpProgNone );
+ }
+ }
+ }
+// -----------------------------------------------------------------------------
+// CHttpDownload::ClientAppInstance
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CHttpClientAppInstance* CHttpDownload::ClientAppInstance() const
+ {
+ return iClAppInstance;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::OnError
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpDownload::OnError( TInt aError,
+ THttpDownloadMgrError aDlError )
+ {
+ LOGGER_ENTERFN( "OnError" );
+ CLOG_WRITE_2( "OnError1: %d - %d", aError, aDlError );
+
+ if( iNoRealError )
+ // Leave occured in Get/Set function. This leave must NOT stop
+ // download process.
+ {
+ CLOG_WRITE( "No real error" );
+ iNoRealError = EFalse;
+
+ return;
+ }
+
+ if( iCodDlData && iCodDlData->Count() > 1 )
+ {
+ if( aDlError == KErrMultipeObjectDownloadFailed )
+ {
+ //Permanently failed error in CodHandler
+ //Delete the download
+ SetDownloadStatus( EHttpProgNone,
+ EHttpDlMultipleMOFailed,
+ aDlError,
+ aError );
+ return;
+ }
+ else
+ {
+ SetDownloadStatus( EHttpProgNone,
+ EHttpDlPaused,
+ aDlError,
+ aError );
+ return;
+
+ }
+ }
+
+ if( iDlState < EHttpDlCreated )
+ // error occured during download object construction -> nothing to do here
+ {
+ return;
+ }
+
+
+ //For COD Downloads, the error code may be set from COD handler
+ //In that case if the download is paused just set the global and download error
+
+ if( iCodDownload && iDlState == EHttpDlPaused )
+ {
+ iLastError = aDlError;
+ iGlobalErrorId = aError;
+ TRAP_IGNORE( StoreDownloadInfoL() );
+ return;
+ }
+
+
+ CancelTransaction();
+ Cancel();
+ Disconnect();
+ // forget downloaded but not persisted content in case of OOM
+ CHttpStorage::TFileCloseOperation closeOp = CHttpStorage::EKeepFile;
+ if ( !Pausable() && ( iCodDlData && iCodDlData->Count() == 1 ) )
+ {
+ closeOp = CHttpStorage::EReplaceFile;
+ }
+
+ iStorage->CloseDestinationFile( closeOp );
+ CLOG_WRITE_1( "OnError1 : iDlState : %d ", iDlState );
+
+ if( iDlState != EHttpDlMultipleMOFailed )
+ {
+
+ // HTTP error code range (-7200 to -7399)
+ if((aError <= KHttpErrorBase && aError >= KHttpErrorBase - 199)||
+ aError == KErrConnectionTerminated ||
+ aError == KErrCannotFindProtocol )
+ {
+ if(!iPausable)
+ {
+ TriggerEvent( EHttpDlNonPausableNetworkLoss );
+ }
+ }
+
+ if( aError == KErrHttpPartialResponseReceived )
+ {
+ //Partial response has been received and connection has been disconnected. This error will be
+ //propagated to the client only, if the HTTP:ENotifyOnDisconnect property is set with a value
+ //HTTP::EEnableDisconnectNotification
+
+ //This error code was cancelling the pausable download. This error shud be ignored to keep the
+ //paused download.
+ //TSW Err ID : SXUU-77SRWL
+
+ SetDownloadStatus( EHttpProgNone,
+ EHttpDlPaused,
+ aDlError,
+ aError );
+
+ }
+ else if( aDlError == EConnectionFailed && iPausable)
+ {
+ //Whenever connection error occurs and download can be paused.
+ //Keep the download in paused state.
+ SetDownloadStatus( EHttpProgNone,
+ EHttpDlPaused,
+ aDlError,
+ aError );
+ }
+ else if ( aDlError == EMMCRemoved )
+ {
+ // MMC removed. Pause the download.
+ SetDownloadStatus( EHttpProgNone,
+ EHttpDlPaused,
+ aDlError,
+ aError );
+ }
+ else
+ {
+
+ SetDownloadStatus( EHttpProgNone,
+ EHttpDlMultipleMOFailed,
+ aDlError,
+ aError );
+ if(!iCodDlData)
+ {
+ TriggerEvent( EHttpDlFailed, EHttpProgNone );
+ }
+ }
+ }
+ else if( ( EHttpDlMultipleMOFailed == iDlState ) && iCodDownload )
+ {
+ TriggerEvent( EHttpDlMultipleMOFailed );
+ }
+
+ TRAP_IGNORE( StoreDownloadInfoL() );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::DetachClientInstance
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CHttpDownload::DetachClientInstance( CHttpClientAppInstance* aInstance )
+ {
+ if( iClAppInstance == aInstance )
+ {
+ iClAppInstance = NULL;
+ }
+ else if( iPDClAppInstance == aInstance )
+ {
+ iPDClAppInstance = NULL;
+ }
+
+ return (iPDClAppInstance || iClAppInstance);
+ }
+
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ClientApp
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CHttpClientApp* CHttpDownload::ClientApp() const
+ {
+ return iClientApp;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::PDClientAppInstance
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CHttpClientAppInstance* CHttpDownload::PDClientAppInstance() const
+ {
+ return iPDClAppInstance;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::Id
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CHttpDownload::Id() const
+ {
+ return iId;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::State
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+THttpDownloadState CHttpDownload::State() const
+ {
+ return iDlState;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ProgState
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+THttpProgressState CHttpDownload::ProgState() const
+ {
+ return iProgState;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ConnHandler
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CHttpConnHandler* CHttpDownload::ConnHandler() const
+ {
+ return iConnHandler;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::NoMedia
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CHttpDownload::NoMedia() const
+ {
+ return iNoMedia;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::MediaRemoved
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::MediaRemoved( TUint aUid, TBool aDontCheckMediaUid )
+ {
+ LOGGER_ENTERFN( "MediaRemoved" );
+ CLOG_WRITE_3( "Uid: %d, dontCheck: %d, iNoMedia: %d",
+ aUid,
+ aDontCheckMediaUid,
+ iNoMedia );
+
+ if( iNoMedia )
+ // it is already known for us.
+ {
+ CLOG_WRITE("already know it");
+ return;
+ }
+
+ if( !aDontCheckMediaUid && iStorage->GetDestinationDriveId() != aUid )
+ // destination drive is not media card
+ {
+ CLOG_WRITE("who cares");
+ return;
+ }
+
+ iNoMedia = ETrue;
+
+ TRAP_IGNORE( InternalPauseL() );
+
+ TriggerEvent( EHttpDlMediaRemoved );
+
+ if( iDlState == EHttpDlInprogress )
+ // it's happened during the download process
+ // in case of e.g completed download it's not error
+ {
+ OnError( KErrGeneral, EMMCRemoved );
+ }
+
+ TRAP_IGNORE( StoreDownloadInfoL() );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::MediaInserted
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::MediaInserted( TUint aUid )
+ {
+ LOGGER_ENTERFN( "MediaInserted" );
+
+ if( iStorage->GetDestinationDriveId() != aUid )
+ // this is not our media card
+ {
+ return;
+ }
+
+ iNoMedia = EFalse;
+ TriggerEvent( EHttpDlMediaInserted );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::GetDestinationDriveID
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CHttpDownload::GetDestinationDriveID() const
+ {
+ return (TInt)iStorage->GetDestinationDriveId();
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetClientInstance
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetClientInstance( CHttpClientAppInstance* aInstance,
+ TBool aNoMoveEvent )
+ {
+ iClAppInstance = aInstance;
+
+ if( iClAppInstance )
+ {
+ __ASSERT_DEBUG( iClAppInstance->Observer(), DMPanic( KErrCorrupt ) );
+ if( iClAppInstance->Observer() && !aNoMoveEvent )
+ // for this short moment download state becomes EHttpDlMoved
+ // to inform client app about that it grabbed this download
+ {
+ TriggerEvent( EHttpDlMoved, iProgState );
+ }
+ }
+
+ else
+ // No reason to keep it PD.
+ {
+ if (iStorage)
+ {
+ iStorage->SetProgressiveMode( EFalse );
+ }
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetConnHandler
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetConnHandler( CHttpConnHandler* aConnHandler )
+ {
+ iConnHandler = aConnHandler;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::Pausable
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CHttpDownload::Pausable() const
+ {
+ return iPausable;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetDownloadNameL
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetDownloadNameL( const TDesC& aNewName )
+ {
+ CLOG_WRITE_1( "New download name: [%S]", &aNewName );
+
+ ReallocateStringL( iDlName, aNewName, KDownloadNameMaxSize );
+
+ FixDownloadNameL();
+
+ TriggerEvent( EHttpDlInprogress, EHttpProgDlNameChanged );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::MHFRunL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::MHFRunL( RHTTPTransaction /*aTransaction*/,
+ const THTTPEvent& aEvent )
+ {
+ switch ( aEvent.iStatus )
+ {
+ case THTTPEvent::EGotResponseHeaders:
+ {
+ CLOG_WRITE( "Response header received" );
+ ResponseHeaderReceivedL();
+ }
+ break;
+
+ case THTTPEvent::EGotResponseBodyData:
+ {
+ MHTTPDataSupplier* respBody = iTrans.Response().Body();
+ TPtrC8 buf;
+
+ respBody->GetNextDataPart( buf );
+
+ ResponseBodyReceivedL( buf );
+
+ respBody->ReleaseData();
+ }
+ break;
+
+ case THTTPEvent::EResponseComplete:
+ {
+ CLOG_WRITE( "Response complete" );
+ }
+ break;
+
+ case THTTPEvent::ESucceeded:
+ {
+ CLOG_WRITE( "Transaction succeeded" );
+
+ DownloadSucceededL();
+ }
+ break;
+
+ case THTTPEvent::EFailed:
+ case THTTPEvent::EMoreDataReceivedThanExpected:
+ case THTTPEvent::EUnrecoverableError:
+ case THTTPEvent::ETooMuchRequestData:
+ {
+ CLOG_WRITE_1( "Failed event: %d", aEvent.iStatus );
+ if( iTransValid )
+ {
+ iTrans.Close();
+ iTransValid = EFalse;
+ }
+ iDlStartedByClient = EFalse;
+ }
+ break;
+
+ case THTTPEvent::ERedirectedPermanently:
+ {
+ RedirectedPermanentlyL( iTrans.Request().URI().UriDes() );
+ }
+ break;
+
+ case THTTPEvent::ERedirectedTemporarily:
+ {
+ RedirectedTemporaryL( iTrans.Request().URI().UriDes() );
+ }
+ break;
+
+ default:
+ {
+ CLOG_WRITE_1( "Event: %d", aEvent.iStatus );
+ if( aEvent.iStatus < 0 )
+ // error occured -> leave will be handled in OnError()
+ {
+ User::Leave( aEvent.iStatus );
+ }
+ }
+ break;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::MHFRunError
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CHttpDownload::MHFRunError( TInt aError,
+ RHTTPTransaction /*aTransaction*/,
+ const THTTPEvent& /*aEvent*/ )
+ {
+ CLOG_WRITE_1( "MHFRunError: %d", aError );
+
+ OnError( aError, ETransactionFailed );
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::DoCancel
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::DoCancel()
+ {
+ LOGGER_ENTERFN( "DoCancel" );
+
+ if( iProgState == EHttpProgMovingContentFile )
+ {
+ delete iFileMan;
+ iFileMan = NULL;
+
+ if( iStatus == KRequestPending )
+ // No cancel function in CFileMan
+ {
+ SelfComplete( KErrCancel );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::RunL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::RunL()
+ {
+ LOGGER_ENTERFN( "RunL" );
+
+ switch( iProgState )
+ // Keep progress states consistent with SetDownloadStatus()
+ {
+ case EHttpStarted:
+ {
+ iUpdatedDDUriSet = EFalse;
+ Connect();
+ }
+ break;
+
+ case EHttpProgConnected:
+ {
+ if( iStatus == KErrNone )
+ {
+ if( iCodDownload )
+ {
+ TriggerEvent( EHttpDlInprogress, EHttpProgCodDownloadShouldResume );
+ }
+ else
+ {
+ RequestContentL();
+ }
+ }
+
+ }
+ break;
+
+ case EHttpProgMovingContentFile:
+ // Move completed
+ // State remains in completed
+ // and move result stored in error attribs
+ {
+ CLOG_WRITE_1( "Move result: %d", iStatus.Int() );
+ // In case of PDL for OMA2 the MP/VP moves the file after the playback is done.
+ // So, the download status should be changed after that
+ //but we again send the progress state as EHttpProgContentFileMoved because we need to display
+ //where file is saved(saved to gallery)
+ //Change Dl State to Download Completed if not already
+
+ if(_OMADLOTA2_MULTI_DOWNLOAD)
+ {
+ TPtrC fileNamePtr = ((*iCodDlData)[iMOMoved])->DestFilename();
+ NotifyMediaGalleryL(fileNamePtr);
+
+ // Initiate async move for the next media object
+ iMOMoved++;
+ if(iMOMoved <= iCodDlData->Count())
+ {
+ MoveDownloadedMediaObjectL(iMOMoved);
+ break;
+ }
+ }
+
+ SetDownloadStatus( iDlNameChanged ? EHttpProgContentFileMovedAndDestFNChanged : EHttpProgContentFileMoved,
+ iDlState = EHttpDlMultipleMOCompleted,
+ iStatus == KErrNone ? ENoError : EMoveFailed,
+ iStatus.Int() );
+
+ if(iStatus == KErrNone)
+ {
+ iMoveInProgress = EFalse;
+ CLOG_WRITE("setting iMoveInProgress false when move is completed");
+ }
+
+
+ delete iFileMan; iFileMan = NULL;
+
+ if( !_OMADLOTA2_MULTI_DOWNLOAD)
+ {
+ TPtr fileNamePtr(iStorage->DestFilename()->Des());
+ NotifyMediaGalleryL(fileNamePtr);
+ }
+ }
+ break;
+
+ default:
+ {
+ DMPanic( KErrUnknown );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::RunError
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CHttpDownload::RunError(TInt aError)
+ {
+ // Untrapped leave occured in RunL() -> status must be update and
+ // client app has to be informed.
+ OnError( aError );
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::Connected
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::Connected()
+ {
+ LOGGER_ENTERFN( "Connected" );
+
+ if( iProgState == EHttpProgCreatingConnection )
+ // In any other progress state we're not interested in this event
+ {
+ SetDownloadStatus( EHttpProgConnected, EHttpDlInprogress );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::Suspended
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::Suspended()
+ {
+ LOGGER_ENTERFN( "Suspended" );
+
+ if( iDlState != EHttpDlInprogress )
+ // we are not interested in this event,
+ // only if the download is in progress.
+ {
+ return;
+ }
+
+ SetDownloadStatus( EHttpProgConnectionSuspended );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::Disconnected
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::Disconnected()
+ {
+ LOGGER_ENTERFN( "Disconnected" );
+
+ if( iDlState != EHttpDlInprogress )
+ // we are not interested in this event,
+ // only if the download is in progress.
+ {
+ return;
+ }
+
+ //Set the errors
+ TRAP_IGNORE( PauseL( ETrue ) );
+
+ iLastError = EConnectionFailed;
+ iGlobalErrorId = KErrCommsLineFail;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ConnectionFailed
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ConnectionFailed( TInt aError )
+ {
+ OnError( aError, EConnectionFailed );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::DoReset
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::DoReset( TBool aOnDelete )
+ {
+ LOGGER_ENTERFN( "DoReset" );
+
+ // Do not inform user about what we do while reseting
+ ++iDontFireEvent;
+
+ Cancel();
+
+ CancelTransaction();
+
+ if( iDisconnectOnReset )
+ {
+ Disconnect();
+ }
+
+ delete iFileMan; iFileMan = NULL;
+
+ ReInitializeDownload();
+
+ // these values are not initialized in ReInitializeDownload()
+ delete iContentType; iContentType = NULL;
+ delete iDDType; iDDType = NULL;
+ delete iHttpRealm; iHttpRealm = NULL;
+ delete iHttpNonce; iHttpNonce = NULL;
+ TRAP_IGNORE( ReallocateStringL( iRedirUrl, *iUrl, KMaxUrlLength ) );
+ TRAP_IGNORE( ReallocateStringL( iCurrentUrl, *iUrl, KMaxUrlLength ) );
+ iRedirect = EFalse;
+ iDlStartedByClient = EFalse;
+ iPausableDRM = ETrue;
+ iDrmContentLengthValid = ETrue;
+
+ // content type is unknown -> download might be pausable again
+ UpdatePausable();
+
+ if( !aOnDelete )
+ {
+ TRAP_IGNORE( StoreDownloadInfoL() );
+ }
+
+ --iDontFireEvent;
+
+ SetDownloadStatus( EHttpProgNone, EHttpDlMultipleMOStarted );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::StoreDownloadInfoL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::StoreDownloadInfoL()
+ {
+ LOGGER_ENTERFN( "StoreDownloadInfoL" );
+ TInt bufSz = KDownloadInfoIncrSize +
+ (iDownloadInfo ? iDownloadInfo->Length(): 0);
+ HBufC8* newInfo = HBufC8::NewLC( bufSz );
+ TPtr8 newInfoPtr = newInfo->Des();
+
+ APPEND_BUF_INT( newInfoPtr, KDMgrInfoFileId );
+ APPEND_BUF_INT( newInfoPtr, KDmgrVersionNumber );
+ APPEND_BUF_INT( newInfoPtr, iDlState );
+ APPEND_BUF_INT( newInfoPtr, iProgState );
+ APPEND_BUF_INT( newInfoPtr, iLastError );
+ APPEND_BUF_INT( newInfoPtr, iGlobalErrorId );
+ APPEND_BUF_INT( newInfoPtr, iAction );
+ APPEND_BUF_INT( newInfoPtr, iRestartAction );
+ APPEND_BUF_INT( newInfoPtr, iNoContentTypeCheck );
+
+ CLOG_WRITE("2");
+ AppendBufL( newInfoPtr, iUrl );
+ AppendBufL( newInfoPtr, iRedirUrl );
+ APPEND_BUF_INT( newInfoPtr, iPort );
+ AppendBufL( newInfoPtr, iCurrentUrl );
+ APPEND_BUF_INT( newInfoPtr, iRedirect );
+ APPEND_BUF_INT( newInfoPtr, iTargetApp );
+ iStorage->AppendStorageInfoL( newInfoPtr );
+ AppendBufL( newInfoPtr, iDlName );
+ AppendBufL( newInfoPtr, iHashedMsgBody );
+ APPEND_BUF_INT( newInfoPtr, iCodDownload );
+ APPEND_BUF_INT( newInfoPtr, iNoMedia );
+
+ CLOG_WRITE("3");
+ APPEND_BUF_INT( newInfoPtr, iPreferencies );
+ APPEND_BUF_INT( newInfoPtr, iDisconnectOnPause );
+ APPEND_BUF_INT( newInfoPtr, iDisconnectOnReset );
+
+ CLOG_WRITE("4");
+ AppendBufL( newInfoPtr, iContentType );
+ AppendBufL( newInfoPtr, iDDType );
+ APPEND_BUF_INT( newInfoPtr, iDate );
+ APPEND_BUF_INT( newInfoPtr, iExpires );
+ APPEND_BUF_INT( newInfoPtr, iMaxAge );
+
+ CLOG_WRITE("5");
+
+ AppendHeadersL( newInfoPtr, iResponseHeaders );
+ AppendHeadersL( newInfoPtr, iRequestHeaders );
+ AppendHeadersL( newInfoPtr, iEntityHeaders );
+ AppendHeadersL( newInfoPtr, iGeneralHeaders );
+
+ CLOG_WRITE("6");
+
+ APPEND_BUF_INT( newInfoPtr, iFotaPckgId );
+
+ CLOG_WRITE("7");
+
+ // check if download info is unchanged from previous update
+ if( iDownloadInfo && ( iDownloadInfo->Compare(*newInfo) == 0 ))
+ {
+ // no change
+ CLOG_WRITE("DownloadInfo unchanged - no need to update");
+ CleanupStack::PopAndDestroy( newInfo );
+ }
+ else
+ {
+ CLOG_WRITE("DownloadInfo changed - replace info file");
+ delete iDownloadInfo;
+ iDownloadInfo = newInfo;
+ CleanupStack::Pop( newInfo );
+
+ HBufC* folderBuf = HBufC::NewLC( KMaxPath );
+ TPtr folder = folderBuf->Des();
+ HBufC* fileNameBuf = HBufC::NewLC( KMaxPath );
+ TPtr fileName = fileNameBuf->Des();
+ iClientApp->Engine()->DownloadInfoFolder( iClientApp, folder );
+ fileName.Format( _L("%S%d"), &folder, iId );
+ CLOG_WRITE_1( "info: %S", &fileName );
+
+ RFile outFile;
+ CleanupClosePushL<RFile>( outFile );
+ User::LeaveIfError( outFile.Replace( iClientApp->Engine()->Fs(),
+ fileName,
+ EFileShareExclusive |
+ EFileStream |
+ EFileWrite ) );
+
+ outFile.Write( newInfoPtr );
+ User::LeaveIfError( outFile.Flush() );
+ CleanupStack::PopAndDestroy( 2, fileNameBuf );
+ CleanupStack::PopAndDestroy(); // outFile
+ }
+ CLOG_WRITE("CHttpDownload::StoreDownloadInfoL() - exit");
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::LoadDownloadInfoL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::LoadDownloadInfoL()
+ {
+ LOGGER_ENTERFN( "LoadDownloadInfoL" );
+
+ HBufC* folderBuf = HBufC::NewLC( KMaxPath );
+ TPtr folder = folderBuf->Des();
+ HBufC* fileNameBuf = HBufC::NewLC( KMaxPath );
+ TPtr fileName = fileNameBuf->Des();
+
+ iClientApp->Engine()->DownloadInfoFolder( iClientApp, folder );
+
+ fileName.Format( _L("%S%d"), &folder, iId );
+ CLOG_WRITE_1( "info: %S", &fileName );
+
+ RFile inFile;
+ User::LeaveIfError( inFile.Open( iClientApp->Engine()->Fs(),
+ fileName,
+ EFileShareReadersOnly |
+ EFileRead ) );
+
+ CLOG_WRITE("1");
+ CleanupClosePushL<RFile>( inFile );
+
+ TInt32 id;
+ READ_INT_L( inFile, id );
+
+ if( id == KDMgrInfoFileId )
+ {
+ TInt version;
+ READ_INT_L( inFile, version );
+
+ if( version != KDmgrVersionNumber )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ READ_INT_L( inFile, iDlState );
+ }
+ else
+ {
+ iDlState = (THttpDownloadState)id;
+ }
+
+ READ_INT_L( inFile, iProgState );
+ READ_INT_L( inFile, iLastError );
+ READ_INT_L( inFile, iGlobalErrorId );
+ READ_INT_L( inFile, iAction );
+ READ_INT_L( inFile, iRestartAction );
+ READ_INT_L( inFile, iNoContentTypeCheck );
+
+ CLOG_WRITE("2");
+ ReadHBufCL( inFile, iUrl );
+ ReadHBufCL( inFile, iRedirUrl );
+ READ_INT_L( inFile, iPort );
+ ReadHBufCL( inFile, iCurrentUrl );
+ READ_INT_L( inFile, iRedirect );
+ READ_INT_L( inFile, iTargetApp );
+ iStorage->LoadStorageInfoL( inFile );
+ ReadHBufCL( inFile, iDlName );
+ ReadHBufCL( inFile, iHashedMsgBody );
+ READ_INT_L( inFile, iCodDownload );
+ READ_INT_L( inFile, iNoMedia );
+
+
+ CLOG_WRITE("3");
+ READ_INT_L( inFile, iPreferencies );
+ READ_INT_L( inFile, iDisconnectOnPause );
+ READ_INT_L( inFile, iDisconnectOnReset );
+
+ CLOG_WRITE("4");
+ ReadHBufCL( inFile, iContentType );
+ ReadHBufCL( inFile, iDDType );
+ READ_CUST_L( inFile, iDate );
+ READ_CUST_L( inFile, iExpires );
+ READ_CUST_L( inFile, iMaxAge );
+
+ CLOG_WRITE("5");
+
+ LoadHeadersL( inFile, iResponseHeaders );
+ LoadHeadersL( inFile, iRequestHeaders );
+ LoadHeadersL( inFile, iEntityHeaders );
+ LoadHeadersL( inFile, iGeneralHeaders );
+
+ CLOG_WRITE("6");
+
+ READ_INT_L( inFile, iFotaPckgId );
+
+ CleanupStack::PopAndDestroy(); // inFile
+ CleanupStack::PopAndDestroy( 2, folderBuf ); // also fileNameBuf
+
+ CLOG_WRITE("9");
+
+ UpdatePausable();
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::IsExpired
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CHttpDownload::IsExpired()
+ {
+ TBool expired = EFalse;
+ TTime now;
+
+ // Set UTC
+ now.UniversalTime();
+
+ if( iMaxAge.Int() )
+ {
+ TTime date( iDate );
+
+ if( date + iMaxAge < now )
+ {
+ expired = ETrue;
+ }
+ }
+ else if( iExpires.Year() )
+ {
+ TTime expires( iExpires );
+
+ if( expires < now )
+ {
+ expired = ETrue;
+ }
+ }
+
+ return expired;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::IsContentFileStorageType
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+TBool CHttpDownload::IsContentFileStorageType()
+ {
+
+
+ if( iCodDownload
+ && iContentType->Compare( KRoapMimeType )
+ && iContentType->Compare( KRoapPduMimeType )
+ && iContentType->Compare( KFotaPackageDataType) )
+ {
+ return ETrue;
+ }
+
+ return EFalse;
+
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::OnCompletedL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::OnCompletedL()
+ {
+ LOGGER_ENTERFN( "OnCompletedL" );
+
+ if( 1 == iCodDownload )
+ {
+ iCodDownload++;
+ TriggerEvent( EHttpDlInprogress, EHttpProgCodDescriptorDownloaded );
+ TriggerEvent( EHttpDlInprogress, EHttpProgCodDownloadStarted );
+ }
+ else
+ {
+ if( !iContTypeRecognitionAvailSent )
+ {
+ CLOG_WRITE( "CHttpDownload::OnCompletedL(): triggering event EHttpResponseForContentType" );
+ TriggerEvent( EHttpDlInprogress, EHttpContTypeRecognitionAvail );
+ iContTypeRecognitionAvailSent = ETrue;
+ }
+ //for correct display of string in download list for COD download we set progress state to moved
+ if(IsContentFileStorageType())
+ {
+ // Retrieve the file name from the whole paths
+ HBufC* fileName = iStorage->DestFilename();
+ TInt lastSlashPos = fileName->LocateReverse( '\\' );
+ if( lastSlashPos == KErrNotFound )
+ lastSlashPos = 0;
+
+ HBufC* name = HBufC::NewLC(KMaxFileName);
+ TPtr namePtr( name->Des() );
+ namePtr.Copy( fileName->Right(fileName->Length()-lastSlashPos-1) );
+
+ TInt findDot = iDlName->LocateReverse( '.' );
+ if( findDot == KErrNotFound )
+ {
+ //if Name displayed does not have Extension then
+ // Remove extention from retrieved name
+ TInt dotInd = namePtr.LocateReverse( '.' );
+ if( dotInd == KErrNotFound )
+ dotInd = namePtr.Length();
+ namePtr.Copy( namePtr.Left( dotInd ) );
+
+ }
+
+ //we never get file moved and Download complete for Cod download becuase move is inherent
+ //to Install() state i.e Download is in progress so display in download list is incorrect.
+ //related to bug HCHA-753D6G
+
+ if(namePtr.Compare(*iDlName))
+ {
+ ReallocateStringL( iDlName, namePtr, KDownloadNameMaxSize );
+ SetDownloadStatus( EHttpProgContentFileMovedAndDestFNChanged, EHttpDlMultipleMOCompleted );
+ }
+ else
+ {
+ SetDownloadStatus( EHttpProgContentFileMoved, EHttpDlMultipleMOCompleted );
+ }
+ CleanupStack::PopAndDestroy( name );
+
+ }
+ else
+ {
+ TriggerEvent( EHttpDlCompleted, EHttpProgNone );
+ SetDownloadStatus( EHttpProgNone, EHttpDlMultipleMOCompleted );
+ }
+ }
+
+ ++iDontFireEvent;
+
+ Cancel();
+ Disconnect();
+
+ iStorage->OnComplete();
+
+ // this is a special case because transaction don't need to be
+ // canceled, only deleted
+ iContinueDownload = EFalse;
+ if( iTransValid )
+ {
+ iTrans.Close();
+ iTransValid = EFalse;
+ }
+
+ --iDontFireEvent;
+
+ TRAP_IGNORE( StoreDownloadInfoL() );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::GetParamFromMediaTypeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TPtrC8 CHttpDownload::GetParamFromMediaTypeL( const TDesC8& aAttribute )
+ {
+ if( !iMediaType )
+ {
+ User::Leave( KErrNotFound );
+ }
+ TInt length = iMediaType->Length();
+ TInt start = iMediaType->Des().FindF( aAttribute );
+ start = ( ( start + aAttribute.Length() ) >= length ) ? KErrNotFound : start;
+ User::LeaveIfError( start );
+ start += aAttribute.Length();
+ TInt end = iMediaType->Des().Mid( start, length-start ).Locate( KSemiColon );
+ TInt boundaryLength = ( KErrNotFound == end ) ? length - start : end;
+ TPtrC8 ptr = iMediaType->Des().Mid( start, boundaryLength );
+ return ptr;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ReInitializeDownload
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ReInitializeDownload()
+ {
+ LOGGER_ENTERFN( "ReInitializeDownload" );
+
+ iResponseHeaders->ResetAndDestroy();
+ iEntityHeaders->ResetAndDestroy();
+
+ iStorage->ResetAndDestroy();
+
+ iLastError = ENoError;
+ iMaxAge = 0;
+ iExpires.Set( 0, EJanuary, 1, 0, 0, 0, 0 );
+ iDate.Set( 0, EJanuary, 1, 0, 0, 0, 0 );
+
+ iNoMedia = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::CancelTransaction
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::CancelTransaction()
+ {
+ LOGGER_ENTERFN( "CancelTransaction" );
+ if( iTransValid )
+ {
+ iTrans.Close();
+ iTransValid = EFalse;
+ }
+
+ if( iContinueDownload )
+ {
+ TriggerEvent( EHttpDlCancelTransaction );
+ }
+
+ iContinueDownload = EFalse;
+
+ iDlStartedByClient = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::InternalPauseL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::InternalPauseL( TBool aDisconnect )
+ {
+ LOGGER_ENTERFN( "InternalPauseL" );
+
+ CHttpStorage::TFileCloseOperation closeOp = CHttpStorage::EKeepFile;
+ if ( !Pausable() && ( iCodDlData && iCodDlData->Count() == 1 ) )
+ {
+ closeOp = CHttpStorage::EReplaceFile;
+ }
+ iStorage->CloseDestinationFile( closeOp );
+ CancelTransaction();
+
+ if( aDisconnect )
+ {
+ // Indicate all clients about network loss if the downlolad is not pausable
+ if(!iPausable)
+ {
+ TriggerEvent(EHttpDlNonPausableNetworkLoss);
+ }
+ Disconnect();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetDownloadStatus
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetDownloadStatus( THttpProgressState aProgState,
+ THttpDownloadState aStatus,
+ THttpDownloadMgrError aErrorId,
+ TInt aGlobalErrorId )
+ {
+#ifdef __DOWNLOADMGR_LOG__ // to filter out EHttpProgResponseBodyReceived
+ if( aProgState != EHttpProgResponseBodyReceived )
+ {
+ CLOG_WRITE_2( "SetDownloadStatus: %d - %d", aStatus, aProgState );
+ }
+#endif
+
+ TBool eventTriggered( EFalse );
+
+ switch( aStatus )
+ {
+ case EHttpDlMultipleMOStarted:
+ case EHttpDlDeleting:
+ {
+ iDlState = aStatus;
+ iProgState = aProgState;
+ }
+ break;
+
+ case EHttpDlFailed:
+ case EHttpDlMultipleMOCompleted:
+ case EHttpDlMultipleMOFailed:
+ {
+ iDlState = aStatus;
+ iProgState = aProgState;
+ iLastError = aErrorId;
+ iGlobalErrorId = aGlobalErrorId;
+ }
+ break;
+
+ case EHttpDlInprogress:
+ {
+ iDlState = aStatus;
+ iProgState = aProgState;
+
+ if( aProgState == EHttpStarted ||
+ aProgState == EHttpProgConnected )
+ // in the other progress state there's no need
+ // to go into RunL()
+ // Keep it consistente with Runl()
+ {
+ SelfComplete();
+ }
+ }
+ break;
+
+ case EHttpDlPaused:
+ {
+ iDlState = aStatus;
+ iProgState = aProgState;
+ iLastError = aErrorId;
+ iGlobalErrorId = aGlobalErrorId;
+ Cancel();
+ }
+ break;
+
+ case EHttpDlMoved:
+ case EHttpDlMediaRemoved:
+ case EHttpDlMediaInserted:
+ {
+ TriggerEvent( EHttpDlMoved, EHttpProgNone );
+ eventTriggered = ETrue;
+ }
+ break;
+
+ default:
+ {
+ DMPanic( KErrArgument );
+ }
+ }
+
+ TRAP_IGNORE( StoreDownloadInfoL() ); //saving the state
+
+ if( !eventTriggered )
+ {
+ TriggerEvent( iDlState, iProgState );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ResponseHeaderReceivedL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ResponseHeaderReceivedL()
+ {
+ LOGGER_ENTERFN( "ResponseHeaderReceivedL" );
+
+ RHTTPResponse resp = iTrans.Response();
+ iStatusCode = resp.StatusCode();
+
+ CLOG_WRITE_1( "iStatusCode: %d", iStatusCode );
+
+ if( iProgState == EHttpContentTypeRequested )
+ {
+ // HEAD method
+ switch( iStatusCode )
+ {
+ case 200: // OK
+ case 201: // Created
+ case 202: // Accepted
+ case 203: // Non-Authoritative Information
+ case 204: // No Content
+ case 205: // Reset Content
+ {
+ if( iStorage->ProgressiveDownload() && iStorage->DownloadedSize() )
+ // progressive download cannot be resumed this way.
+ // it's always an error case.
+ {
+ OnError( KErrUnknown, EHttpRestartFailed );
+ }
+ else
+ {
+ // store response header only after first request
+ StoreResponseHeaderL();
+ ContentTypeReceivedL();
+ StoreDownloadInfoL();
+ }
+ }
+ break;
+
+ case 401: // Unauthorized
+ {
+ HttpResponse401L();
+ }
+ break;
+
+ case 407: // Proxy Authentication Required
+ {
+ HttpResponse407L();
+ }
+ break;
+
+ case 404: // Not Found
+ {
+ OnError( KErrUnknown, EObjectNotFound );
+ }
+ break;
+
+ default:
+ {
+ SetDownloadStatus( EHttpProgNone,
+ EHttpDlFailed,
+ EHttpUnhandled,
+ GLOBAL_HTTP_ERROR( iStatusCode ) );
+ }
+ }
+ }
+ else
+ // GET method
+ {
+ TBool respOk = EFalse;
+
+ switch( iStatusCode )
+ {
+ case 200: // OK
+ case 201: // Created
+ case 202: // Accepted
+ case 203: // Non-Authoritative Information
+ case 204: // No Content
+ case 205: // Reset Content
+ // full content download
+ // If ERestartNoIfCompleted comes with 200 and
+ // iDownloadedSize != 0 it means http server
+ // doesn't support conditional range download
+ {
+ ReInitializeDownload();
+ // store response header only after first request
+ StoreResponseHeaderL();
+ iStorage->CreateDestinationFileL();
+ StoreDownloadInfoL();
+ respOk = ETrue;
+ }
+ break;
+
+ case 206: // Partial Content
+ // partial content download
+ {
+ StoreResponseHeaderL();
+ iStorage->CreateDestinationFileL();
+
+ respOk = ETrue;
+ }
+ break;
+
+ case 304: // Not Modified
+ // content is not modified since download paused
+ {
+ iStorage->CreateDestinationFileL();
+ OnCompletedL();
+ }
+ break;
+
+ case 412: // Precondition Failed
+ case 416: // content range is wrong. Most probably expired, or modified.
+ {
+ if( iRestartAction == ERestartIfExpired ||
+ iRestartAction == ERestartForced )
+ {
+ // Forget a previous redirect
+ ReallocateStringL( iRedirUrl, *iUrl, KMaxUrlLength );
+ ReallocateStringL( iCurrentUrl, *iRedirUrl, KMaxUrlLength );
+ iRedirect = EFalse;
+
+ CancelTransaction();
+
+ ReInitializeDownload();
+
+ SetDownloadStatus( EHttpStarted );
+ }
+ else
+ // ERestartNoIfCompleted => content modified since last partial download
+ {
+ OnError( KErrUnknown, EPartialContentModified );
+ }
+ }
+ break;
+
+ case 401: // Unauthorized
+ // HTTP authentication failed
+ {
+ HttpResponse401L();
+ }
+ break;
+
+ case 407: // Proxy Authentication Required
+ // Proxy authentication failed
+ {
+ HttpResponse407L();
+ }
+ break;
+
+ case 404: // Not Found
+ // Object not found
+ {
+ OnError( KErrUnknown, EObjectNotFound );
+ }
+
+ default:
+ {
+ OnError( GLOBAL_HTTP_ERROR( iStatusCode ), EHttpUnhandled );
+ }
+ }
+
+ if( respOk )
+ {
+ SetDownloadStatus( EHttpProgResponseHeaderReceived );
+ }
+ else
+ {
+ CancelTransaction();
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ResponseBodyReceivedL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ResponseBodyReceivedL( const TDesC8& aBuf )
+ {
+ if( iMultiPart && !iCodDownload )
+ {
+ TBool isSupportedMultiPart( EFalse );
+ // If it leaves isSupportedMultiPart remains false -> does not supported!
+ TRAP_IGNORE( isSupportedMultiPart = IsMultipartSupportedL( aBuf ) );
+ if( isSupportedMultiPart )
+ {
+ SetCodFlag( ETrue );
+ TriggerEvent( EHttpDlInprogress, EHttpProgSupportedMultiPart );
+ }
+ }
+
+ TBool ret(ETrue);
+
+ if( iStorage->BufferingEnabled() )
+ {
+ // Buffering is enabled, just pass on the data
+ ret = iStorage->WriteOutNextBodyDataL(aBuf);
+ }
+ else
+ {
+ // Buffering not yet enabled, see how much data we still have to write without buffering
+ TInt bytesToWrite = aBuf.Length();
+ TInt downloadedSize = iStorage->DownloadedSize();
+
+ if(bytesToWrite + downloadedSize < KMinDataSizeToSend)
+ {
+ // Just dump non-buffered write
+ ret = iStorage->WriteOutNextBodyDataL( aBuf );
+ }
+ else
+ {
+ // Necessary to switch to buffered writing
+
+ TInt leftPartSize = KMinDataSizeToSend - downloadedSize;
+ TInt rightPartSize = bytesToWrite - leftPartSize;
+
+ TBool ret1 = ETrue;
+ TBool ret2 = ETrue;
+
+ if(leftPartSize > 0)
+ {
+ // Write left side of the block to get alignment matched
+ ret1 = iStorage->WriteOutNextBodyDataL( aBuf.Left(leftPartSize) );
+ }
+
+ // Enable buffering
+ iStorage->EnableBufferingL();
+
+ // And push the rest of this data block
+ if(rightPartSize > 0)
+ {
+ ret2 = iStorage->WriteOutNextBodyDataL( aBuf.Right(rightPartSize) );
+ }
+
+ if(!ret1 || !ret2)
+ {
+ ret = EFalse;
+ }
+ }
+ }
+
+ if( !ret )
+ {
+ StoreDownloadInfoL();
+ }
+
+ if( !iContTypeRecognitionAvailSent && (iStorage->DownloadedSize() >= KRespSizeForRecognition) )
+ {
+ TriggerEvent( EHttpDlInprogress, EHttpContTypeRecognitionAvail );
+ iContTypeRecognitionAvailSent = ETrue;
+ }
+
+ TriggerEvent( EHttpDlInprogress, EHttpProgResponseBodyReceived );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::IsMultipartSupportedL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CHttpDownload::IsMultipartSupportedL( const TDesC8& aBuf )
+ {
+ TBool ret( EFalse );
+
+ if( !iHeaderOfMultipart )
+ {
+ iHeaderOfMultipart = HBufC8::NewL( KMaxHeaderOfMultipart );
+ }
+ TInt full_length = iHeaderOfMultipart->Length() + aBuf.Length();
+ if( KMaxHeaderOfMultipart >= full_length )
+ {
+ iHeaderOfMultipart->Des().Append( aBuf );
+ }
+ else
+ {
+ ret = EFalse;
+ return ret;
+ }
+
+ TInt pos = iHeaderOfMultipart->Des().Find( KContentType() );
+
+ User::LeaveIfError( pos );
+
+ pos = pos + KContentType().Length();
+
+ TPtrC8 p = iHeaderOfMultipart->Des().Mid( pos );
+ TInt temp = p.Find( KDoubleEOL() );
+
+ TInt posEol = pos + temp;
+
+ TPtrC8 ptr = iHeaderOfMultipart->Des().Mid( pos, ( posEol - pos ) );
+ if( 0 == ptr.Find( KDdMimeType() ) ||
+ 0 == ptr.Find( KDd2MimeType() ) ||
+ 0 == ptr.Find( KCodMimeType() ))
+ {
+ ret = ETrue;
+ delete iHeaderOfMultipart;
+ iHeaderOfMultipart = NULL;
+ return ret;
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::Connect
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::Connect()
+ {
+ LOGGER_ENTERFN( "ConnectL" );
+
+ SetDownloadStatus( EHttpProgCreatingConnection );
+
+ if( iConnHandler->IsConnected() )
+ // we already have connection. Just use it.
+ {
+ Connected();
+ }
+ else
+ // No connection
+ {
+ if( iClAppInstance && iClAppInstance->AutoConnect() )
+ // Connection w/o question
+ {
+ TRAPD( err, iConnHandler->ConnectL() );
+
+ if( err )
+ {
+ OnError( err, EConnectionFailed );
+ }
+ }
+ else
+ // ask before connect
+ {
+ TriggerEvent( EHttpDlInprogress, EHttpProgConnectionNeeded );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::Disconnect
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::Disconnect()
+ {
+ LOGGER_ENTERFN( "Disconnect" );
+
+ if( iConnHandler )
+ {
+ TriggerEvent( iDlState, EHttpProgDisconnected );
+ // iConnHandler is set NULL from Disconnect()
+ iConnHandler->Disconnect( EFalse, this );
+
+ iConnHandler = NULL;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetRequestHeaderL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetRequestHeaderL( RStringPool& aStringPool,
+ RHTTPHeaders& aHeaders,
+ TBool aHeadMethod )
+ {
+ LOGGER_ENTERFN( "SetRequestHeaderL" );
+
+ // Set default Accept header
+ aHeaders.SetRawFieldL( aStringPool.StringF(HTTP::EAccept, RHTTPSession::GetTable()),
+ KDefaultAcceptHeader(),
+ KHttpFieldSeparator );
+
+ SetRequestHeaderAddOnL( aStringPool, aHeaders );
+ SetCredentialsInfoL( aStringPool );
+
+ // Find ETag in response header
+ RStringF etag = aStringPool.StringF(HTTP::EETag,
+ RHTTPSession::GetTable());
+ TInt fieldInd = FindHeaderField( iResponseHeaders, etag.DesC() );
+ if( fieldInd != KErrNotFound )
+ // ETag is known. ETag identifies the content. Set If-Match to see
+ // that if it's changed, or a redirection goes to another url.
+ // Server will respond with 412 on error.
+ {
+ RStringF ifMatch = aStringPool.StringF(HTTP::EIfMatch,
+ RHTTPSession::GetTable());
+ aHeaders.RemoveField( ifMatch );
+ aHeaders.SetRawFieldL( ifMatch,
+ *(*iResponseHeaders)[fieldInd]->FieldRawData(),
+ KHttpFieldSeparator );
+ CLOG_WRITE8_1( "ETag: %S", (*iResponseHeaders)[fieldInd]->FieldRawData() );
+ }
+
+ if( aHeadMethod )
+ // HEAD method doesn't require any other field to be set
+ {
+ return;
+ }
+
+ CLOG_WRITE_1( "Down: %d", iStorage->DownloadedSize() );
+ CLOG_WRITE_1( "Length: %d", iStorage->Length() );
+
+ if( iRestartAction == ERestartNoIfCompleted )
+ {
+ CLOG_WRITE( "ERestartNoIfCompleted" );
+
+ SetRangeFieldL( aStringPool, aHeaders );
+
+ RStringF field;
+
+ if( iStorage->DownloadedSize() != iStorage->Length() )
+ // download from previous point only if the content is unmodified
+ {
+ field = aStringPool.StringF(HTTP::EIfUnmodifiedSince,
+ RHTTPSession::GetTable());
+
+ SetExpireToFieldL( field, aStringPool, aHeaders );
+ }
+ }
+ else if( iRestartAction == ERestartIfExpired )
+ // Expire and max-age is already checked in StartL
+ // nothing to do if response is 304
+ {
+ CLOG_WRITE( "ERestartIfExpired" );
+
+ RStringF field;
+
+ if( iStorage->DownloadedSize() != iStorage->Length() )
+ // we don't have the entire content
+ // start from where we stopped before
+ {
+ SetRangeFieldL( aStringPool, aHeaders );
+ // download entire content if expired
+ field = aStringPool.StringF(HTTP::EIfRange, RHTTPSession::GetTable());
+ }
+ else
+ // we have the entire content. Check that content is modified
+ // since it's downloaded, or wait for response 304.
+ {
+ field = aStringPool.StringF(HTTP::EIfModifiedSince, RHTTPSession::GetTable());
+ }
+
+ SetExpireToFieldL( field, aStringPool, aHeaders );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::DisablePipeliningL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::DisablePipeliningL( RStringPool& aStringPool )
+ {
+ LOGGER_ENTERFN( "DisablePipeliningL" );
+
+ RStringF pipeline = aStringPool.StringF(HTTP::EHttpPipelining, RHTTPSession::GetTable());
+ RStringF disable = aStringPool.StringF(HTTP::EDisablePipelining, RHTTPSession::GetTable());
+
+ iTrans.PropertySet().SetPropertyL(pipeline, disable);
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpFilterAuthentication::SetPropertyL
+// Set property of the transaction
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetPropertyL( RStringPool& aStringPool,
+ RStringF aPropertyName,
+ const TDesC8& aToken )
+ {
+ RString tokenStr = aStringPool.OpenStringL( aToken );
+ THTTPHdrVal tokenVal = tokenStr;
+ CleanupClosePushL( tokenStr );
+ iTrans.PropertySet().RemoveProperty( aPropertyName );
+ iTrans.PropertySet().SetPropertyL( aPropertyName, tokenVal );
+
+ CLOG_WRITE8_2( "SetPropertyL: %S - %S", &aPropertyName.DesC(), &aToken );
+
+ CleanupStack::PopAndDestroy(); // tokenStr
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpFilterAuthentication::SetPropertyL
+// Set property of the transaction
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetPropertyL( RStringF aPropertyName,
+ const TInt aValue )
+ {
+ THTTPHdrVal tokenVal = aValue;
+
+ iTrans.PropertySet().RemoveProperty( aPropertyName );
+ iTrans.PropertySet().SetPropertyL( aPropertyName, tokenVal );
+
+ CLOG_WRITE8_2( "SetPropertyL: %S - %d", &aPropertyName.DesC(), aValue );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpFilterAuthentication::SetRequestHeaderAddOnL
+// Set property of the transaction
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetRequestHeaderAddOnL( RStringPool& aStringPool,
+ RHTTPHeaders& aHeaders )
+ {
+ if( !iRequestHeaders->Count() )
+ {
+ return;
+ }
+
+ TPtrC8 fieldName;
+ TPtrC8 fieldValue;
+ RStringF fieldNameStr;
+ THTTPHdrVal value;
+
+ for( TInt i = 0; i < iRequestHeaders->Count(); ++i )
+ {
+ CLOG_WRITE8_3( "Req(%d): %S: %S", i, (*iRequestHeaders)[i]->FieldName(), (*iRequestHeaders)[i]->FieldRawData() );
+
+ fieldNameStr = aStringPool.OpenFStringL( *(*iRequestHeaders)[i]->FieldName() );
+ CleanupClosePushL( fieldNameStr );
+
+// aHeaders.RemoveField( fieldNameStr );
+ if (fieldNameStr == aStringPool.StringF(HTTP::EIfModifiedSince, RHTTPSession::GetTable()) ||
+ fieldNameStr == aStringPool.StringF(HTTP::EIfUnmodifiedSince, RHTTPSession::GetTable()))
+ {
+ TInternetDate date;
+ date.SetDateL(*(*iRequestHeaders)[i]->FieldRawData());
+ TDateTime modifyTime(date.DateTime());
+ aHeaders.SetFieldL(fieldNameStr, modifyTime);
+ CleanupStack::PopAndDestroy(); // fieldNameStr
+ }
+ else
+ {
+ RStringF valueStr = aStringPool.OpenFStringL( *(*iRequestHeaders)[i]->FieldRawData() );
+ value.SetStrF( valueStr );
+ CleanupClosePushL( valueStr );
+
+ aHeaders.SetFieldL( fieldNameStr, valueStr );
+
+ CleanupStack::PopAndDestroy( 2 ); // valueStr, fieldNameStr
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetCredentialsInfoL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetCredentialsInfoL( RStringPool& aStringPool )
+ {
+ LOGGER_ENTERFN( "SetCredentialsInfoL" );
+
+ if( iHttpUsername )
+ {
+ RStringF username = aStringPool.StringF( HTTP::EUsername,
+ RHTTPSession::GetTable() );
+
+ SetPropertyL( aStringPool, username, *iHttpUsername );
+ }
+
+ if( iHttpPassword )
+ {
+ RStringF password = aStringPool.StringF( HTTP::EPassword,
+ RHTTPSession::GetTable() );
+
+ SetPropertyL( aStringPool, password, *iHttpPassword );
+ }
+
+ if( iHttpRealm )
+ {
+ RStringF realm = aStringPool.StringF( HTTP::ERealm,
+ RHTTPSession::GetTable() );
+ SetPropertyL( aStringPool, realm, *iHttpRealm );
+ }
+
+ if( iHttpProxyRealm )
+ {
+ RStringF proxyRealmStr = aStringPool.StringF(
+ HttpFilterCommonStringsExt::EProxyRealm,
+ HttpFilterCommonStringsExt::GetTable() );
+ SetPropertyL( aStringPool, proxyRealmStr, *iHttpProxyRealm );
+ }
+
+ if( iHttpProxyUsername )
+ {
+ RStringF proxyUsernameStr = aStringPool.StringF(
+ HttpFilterCommonStringsExt::EProxyUsername,
+ HttpFilterCommonStringsExt::GetTable() );
+ SetPropertyL( aStringPool, proxyUsernameStr, *iHttpProxyUsername );
+ }
+
+ if( iHttpProxyPassword )
+ {
+ RStringF proxyPasswordStr = aStringPool.StringF(
+ HttpFilterCommonStringsExt::EProxyPassword,
+ HttpFilterCommonStringsExt::GetTable() );
+ SetPropertyL( aStringPool, proxyPasswordStr, *iHttpProxyPassword );
+ }
+
+ if( iHttpNonce )
+ {
+ RStringF nonce = aStringPool.StringF( HTTP::ENonce,
+ RHTTPSession::GetTable() );
+
+ SetPropertyL( aStringPool, nonce, *iHttpNonce );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetRangeFieldL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetRangeFieldL( RStringPool& aStringPool,
+ RHTTPHeaders& aHeaders )
+ {
+ LOGGER_ENTERFN( "SetRangeFieldL" );
+
+ if( iStorage->DownloadedSize() == 0 )
+ // no bytes have been downloaded yet
+ {
+ return;
+ }
+
+ RStringF range = aStringPool.StringF(HTTP::ERange, RHTTPSession::GetTable());
+
+ aHeaders.RemoveField( range );
+
+ TBuf8<48> rawData;
+
+ rawData.Format( _L8("bytes=%d-"), iStorage->DownloadedSize() );
+
+ CLOG_WRITE8_1( "Range: %S", &rawData );
+ aHeaders.SetRawFieldL( range, rawData, KHttpFieldSeparator );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetExpireToFieldL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetExpireToFieldL( RStringF& aField,
+ RStringPool& aStringPool,
+ RHTTPHeaders& aHeaders )
+ {
+ LOGGER_ENTERFN( "SetExpireToFieldL" );
+
+ RStringF expires = aStringPool.StringF(HTTP::EExpires, RHTTPSession::GetTable());
+ RStringF lastModified = aStringPool.StringF(HTTP::ELastModified, RHTTPSession::GetTable());
+
+ TInt expInd( KErrNotFound );
+ TInt modInd( KErrNotFound );
+
+ for( TInt i = 0; i < iResponseHeaders->Count(); ++i )
+ // FindHeaderField, because this is double search for fieldnames
+ {
+ if( *(*iResponseHeaders)[i]->FieldName() == expires.DesC() )
+ {
+ expInd = i;
+ continue;
+ }
+ if( *(*iResponseHeaders)[i]->FieldName() == lastModified.DesC() )
+ {
+ modInd = i;
+ continue;
+ }
+ }
+
+ if( expInd != KErrNotFound )
+ {
+ CLOG_WRITE8_1( "Expire: %S", (*iResponseHeaders)[expInd]->FieldRawData() );
+
+ aHeaders.RemoveField( aField );
+ aHeaders.SetRawFieldL( aField,
+ *(*iResponseHeaders)[expInd]->FieldRawData(),
+ KHttpFieldSeparator );
+ }
+ else if( modInd != KErrNotFound )
+ {
+ CLOG_WRITE8_1( "LastMod: %S", (*iResponseHeaders)[modInd]->FieldRawData() );
+
+ aHeaders.RemoveField( aField );
+ aHeaders.SetRawFieldL( aField,
+ *(*iResponseHeaders)[modInd]->FieldRawData(),
+ KHttpFieldSeparator );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ParseRequestedUrlL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ParseRequestedUrlL()
+ {
+ LOGGER_ENTERFN( "ParseRequestedUrlL" );
+
+ __ASSERT_DEBUG( iUrl->Length(), DMPanic( KErrArgument ) );
+
+ TUriParser8 uri;
+ uri.Parse( *iUrl );
+
+ TPtrC8 scheme( uri.Extract( EUriScheme ) );
+
+ if( scheme != KHttpScheme &&
+ scheme != KHttpsScheme )
+ // unsupported or no scheme in url.
+ // Insert 'http://' to the beginning of it.
+ {
+ HBufC8* tempBuf = HBufC8::NewL( KHttpScheme().Length() +
+ KSchemeAddon().Length() +
+ iUrl->Length() );
+
+ tempBuf->Des().Append( KHttpScheme );
+ tempBuf->Des().Append( KSchemeAddon );
+ tempBuf->Des().Append( *iUrl );
+
+ delete iUrl; iUrl = NULL;
+
+ iUrl = tempBuf;
+
+ uri.Parse( *iUrl );
+ }
+
+ CUri8* url = CUri8::NewLC();
+
+ url->SetComponentL( uri.Extract( EUriScheme ), EUriScheme );
+ url->SetComponentL( uri.Extract( EUriHost ), EUriHost );
+ url->SetComponentL( uri.Extract( EUriPath ), EUriPath );
+ url->SetComponentL( uri.Extract( EUriUserinfo ), EUriUserinfo );
+ url->SetComponentL( uri.Extract( EUriQuery ), EUriQuery );
+ url->SetComponentL( uri.Extract( EUriFragment ), EUriFragment );
+
+ if( uri.IsPresent( EUriPort ) )
+ {
+ url->SetComponentL( uri.Extract( EUriPort ), EUriPort );
+ }
+ else
+ {
+ if( iPort != KDefaultPort )
+ {
+ TBuf8<10> port;
+
+ port.Format( _L8("%d"), iPort );
+
+ url->SetComponentL( port, EUriPort );
+ }
+ }
+
+ CLOG_WRITE8_1( "Parsed URL: %S", &url->Uri().UriDes() );
+
+ // Initially they are the same
+ ReallocateStringL( iRedirUrl, url->Uri().UriDes(), KMaxUrlLength );
+ ReallocateStringL( iCurrentUrl, url->Uri().UriDes() , KMaxUrlLength);
+
+ CleanupStack::PopAndDestroy( url );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ParseDownloadNameL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ParseDownloadNameL()
+ {
+ LOGGER_ENTERFN( "ParseDownloadNameL" );
+
+ // Calculate the download name from the requested URL
+ HBufC8* parsedUrl = EscapeUtils::EscapeDecodeL( *iCurrentUrl );
+ CleanupStack::PushL( parsedUrl );
+
+ TUriParser8 uri;
+ uri.Parse( *parsedUrl );
+
+ TPtrC8 path;
+
+ path.Set( uri.Extract( EUriPath ) );
+
+ HBufC* newDlName = HBufC::NewLC( KDownloadNameMaxSize );
+ TPtr newDlNamePtr = newDlName->Des();
+
+ // Here we don't have to deal with that iDlName is longer than KMaxPath
+ // ConvertDownloadNameUniqueL() will make the correction
+ if( path.Length() )
+ // there's path in the url
+ {
+ TInt slash = path.LocateReverse( '/' );
+
+ if( slash == KErrNotFound )
+ {
+ slash = path.LocateReverse( '\\' );
+ }
+
+ if( slash != KErrNotFound && slash != path.Length() )
+ // from the last slash this is the filename
+ {
+ TPtrC8 temp( path.Right( path.Length() - slash - 1 ) );
+
+ if( temp.Length() )
+ {
+ HBufC *tempstr = EscapeUtils::ConvertToUnicodeFromUtf8L(temp.Left( KDownloadNameMaxSize ));
+ newDlNamePtr.Copy(*tempstr);
+ delete tempstr;
+ }
+ else
+ // empty path -> default filename is the host
+ // filename is KDefDestFilename
+ {
+ newDlNamePtr.Copy( KDefDestFilename );
+ }
+ }
+ else
+ // no slash -> entire path is the filename
+ {
+ HBufC *tempstr = EscapeUtils::ConvertToUnicodeFromUtf8L(path.Left( KDownloadNameMaxSize ));
+ newDlNamePtr.Copy(*tempstr);
+ delete tempstr;
+ }
+ }
+ else
+ // no path -> default filename is the host
+ // filename is KDefDestFilename
+ {
+ newDlNamePtr.Copy( KDefDestFilename );
+ }
+
+ SetDownloadNameL( newDlNamePtr );
+ CleanupStack::PopAndDestroy( newDlName );
+ CleanupStack::PopAndDestroy( parsedUrl );
+
+ CLOG_WRITE_1( "Name: %S", iDlName );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::StoreResponseHeaderL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::StoreResponseHeaderL()
+ {
+ LOGGER_ENTERFN( "StoreResponseHeaderL" );
+
+ TPtrC8 rawData;
+ RStringPool strPool = iConnHandler->Session().StringPool();
+ RHTTPHeaders headers( iTrans.Response().GetHeaderCollection() );
+ THTTPHdrFieldIter it = headers.Fields();
+
+ // forget the previous headers
+ iResponseHeaders->ResetAndDestroy();
+ iEntityHeaders->ResetAndDestroy();
+
+ CLOG_WRITE( "Received response header:" );
+ while ( !it.AtEnd() )
+ {
+ RStringTokenF fieldName = it();
+ RStringF fieldNameStr = strPool.StringF (fieldName );
+
+ headers.GetRawField( fieldNameStr, rawData );
+
+ CHeaderField* field = CHeaderField::NewL( &fieldNameStr.DesC(), &rawData );
+ CleanupStack::PushL( field );
+
+ CLOG_WRITE8_2("%S:%S", &fieldNameStr.DesC(), &rawData);
+ iResponseHeaders->AppendL( field );
+
+ CleanupStack::Pop( field );
+
+ CHeaderField* entityField = CHeaderField::NewL( &fieldNameStr.DesC(), &rawData );
+ CleanupStack::PushL( entityField );
+
+ CLOG_WRITE8_2("%S:%S", &fieldNameStr.DesC(), &rawData);
+ iEntityHeaders->AppendL( entityField );
+
+ CleanupStack::Pop( entityField );
+
+ ++it;
+ }
+
+ ParseContentTypeL( strPool );
+
+ ParseContentDispositionL( strPool);
+ if (!iCodDownload)
+ {
+ if (iUseAttachmentFileName || iUseInlineFileName)
+ {
+ SetDownloadNameL( *iAttachmentFileName );
+ }
+ }
+
+ RStringF length = strPool.StringF(HTTP::EContentLength,RHTTPSession::GetTable());
+ RStringF date = strPool.StringF(HTTP::EDate,RHTTPSession::GetTable());
+ RStringF expires = strPool.StringF(HTTP::EExpires,RHTTPSession::GetTable());
+ RStringF maxAge = strPool.StringF(HTTP::EMaxAge,RHTTPSession::GetTable());
+ RStringF cacheControl = strPool.StringF(HTTP::ECacheControl,RHTTPSession::GetTable());
+ THTTPHdrVal value;
+
+ if( !headers.GetField( length, 0, value ) )
+ {
+ if( iStorage->Length() == KDefaultContentLength )
+ // content size is
+ {
+ iStorage->SetLength( value );
+ }
+ else
+ //This is a partial response as Length is already set so save this new length as partial Length that needs to be Downloaded.
+ {
+ iStorage->SetPartialContentLength( value );
+ }
+ }
+
+ CheckRealDRMContentType();
+ if( !iDrmContentLengthValid )
+ // Content was original encoded -> we don't know the actual content size.
+ {
+ iStorage->SetLength( KDefaultContentLength );
+ }
+
+
+ iMaxAge = 0;
+ TInt parts( 0 );
+ // this leave is trapped because we can still go on
+ TRAPD( err, parts = headers.FieldPartsL( cacheControl ) );
+
+ if( !err )
+ // try to find max-age in Cache-control field
+ {
+ for( TInt i = 0; i < parts; ++i )
+ {
+ RStringF directive;
+ THTTPHdrVal hdrVal;
+ TInt err;
+
+ // Get the cache-control from the headers
+ // initialise the fieldname
+ headers.GetField( cacheControl, i, hdrVal );
+
+ if((hdrVal.Type() == THTTPHdrVal::KStrVal) || (hdrVal.Type() == THTTPHdrVal::KStrFVal))
+ {
+ RStringF cacheDir = hdrVal.StrF();
+
+ TInt endPos;
+ _LIT8(KFind, "=");
+
+ endPos = cacheDir.DesC().Find( KFind );
+ if( endPos != -1 )
+ {
+ TRAP(err, directive = strPool.OpenFStringL(cacheDir.DesC().Left(endPos)));
+ if( !err )
+ {
+ if( directive == maxAge )
+ {
+ TInt valueInt( 0 );
+ TLex8 value( cacheDir.DesC().Right(cacheDir.DesC().Length() - endPos - 1) );
+
+ value.Val( valueInt );
+ iMaxAge = valueInt;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if( !headers.GetField( expires, 0, value ) )
+ {
+ iExpires = value;
+ }
+ else
+ {
+ iExpires.SetYear( 0 );
+ }
+
+ if( !headers.GetField( date, 0, value ) )
+ {
+ iDate = value;
+ }
+ else
+ {
+ iDate.SetYear( 0 );
+ }
+
+ UpdatePausable();
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::CheckRealDRMContentType
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::CheckRealDRMContentType()
+ {
+ LOGGER_ENTERFN( "CheckRealDRMContentType" );
+
+ iPausableDRM = ETrue;
+ iDrmContentLengthValid = ETrue;
+
+ TInt index = FindHeaderField( iResponseHeaders, KDRMOldContentType );
+ if( index != KErrNotFound )
+ // this is an old DRM protected content
+ // This transaction cannot be paused.
+ {
+ if( !(*iResponseHeaders)[index]->FieldRawData()->Compare( KDrmMessageMimeType() ) )
+ {
+ iPausableDRM = EFalse;
+// iDrmContentLengthValid = EFalse;
+ }
+ }
+
+ UpdatePausable();
+
+ CLOG_WRITE_2( "Pausable: [%d], Length: [%d]", iPausableDRM, iDrmContentLengthValid );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SaveCredentialsL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SaveCredentialsL( RStringPool aStringPool )
+ {
+ LOGGER_ENTERFN( "SaveCredentialsL" );
+
+ RStringF username = aStringPool.StringF( HTTP::EUsername,
+ RHTTPSession::GetTable() );
+ RStringF password = aStringPool.StringF( HTTP::EPassword,
+ RHTTPSession::GetTable() );
+ RStringF realm = aStringPool.StringF( HTTP::ERealm,
+ RHTTPSession::GetTable() );
+ RStringF nonce = aStringPool.StringF( HTTP::ENonce,
+ RHTTPSession::GetTable() );
+
+ THTTPHdrVal hdrValue;
+
+ // Realm
+ if( iTrans.PropertySet().Property( realm, hdrValue ) )
+ {
+ if( hdrValue.Str().DesC().Length() )
+ // W/o realm authentication is meaningless
+ {
+ ReallocateStringL( iHttpRealm, hdrValue.Str().DesC(), KMaxDefAttrLength );
+ CLOG_WRITE8_1( "Realm: [%S]", iHttpRealm );
+
+ // Username
+ if( iTrans.PropertySet().Property( username, hdrValue ) )
+ {
+ ReallocateStringL( iHttpUsername, hdrValue.Str().DesC(), KMaxDefAttrLength );
+ CLOG_WRITE8_1( "uname: [%S]", iHttpUsername );
+ }
+
+ // Password
+ if( iTrans.PropertySet().Property( password, hdrValue ) )
+ {
+ ReallocateStringL( iHttpPassword, hdrValue.Str().DesC(), KMaxDefAttrLength );
+ CLOG_WRITE8_1( "pwd: [%S]", iHttpPassword );
+ }
+
+ if( !iTrans.PropertySet().Property(
+ aStringPool.StringF( HTTP::EBasic,
+ RHTTPSession::GetTable() ),
+ hdrValue ) )
+ // this is a digest authentication response
+ // store nonce value
+ {
+ if( iTrans.PropertySet().Property( nonce, hdrValue ) )
+ {
+ ReallocateStringL( iHttpNonce, hdrValue.Str().DesC() );
+ CLOG_WRITE8_1( "nonce: [%S]", iHttpNonce );
+ }
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::RequestContentL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::RequestContentL()
+ {
+ LOGGER_ENTERFN( "RequestContentL" );
+
+ RStringPool strPool = iConnHandler->Session().StringPool();
+ RStringF method;
+ TBool aHead = ETrue;
+
+ if( (iContentType && iContentType->Length()) ||
+ iNoContentTypeCheck ||
+ iSilentMode )
+ // we know the content type -> head is already requested or
+ // every content type is welcome
+ {
+ method = strPool.StringF( HTTP::EGET,RHTTPSession::GetTable() );
+ aHead = EFalse;
+ }
+ else
+ // content type check needed -> first request HEAD
+ {
+ method = strPool.StringF( HTTP::EHEAD,RHTTPSession::GetTable() );
+ }
+
+ TUriParser8 uri;
+ uri.Parse( *iCurrentUrl );
+
+ CLOG_WRITE8_1( "Req URL: %S", iCurrentUrl );
+ CLOG_WRITE8_1( "Method: %S", &method.DesC() );
+
+ __ASSERT_DEBUG( !iTransValid, DMPanic( KErrCorrupt ) );
+ if( iTransValid )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ iTrans = iConnHandler->Session().OpenTransactionL( uri, *this, method );
+ iTransValid = ETrue;
+
+ RHTTPHeaders headers( iTrans.Request().GetHeaderCollection() );
+
+ SetRequestHeaderL( strPool, headers, aHead );
+
+ DisablePipeliningL( strPool );
+ SetCookiesL( strPool );
+
+ iTrans.SubmitL();
+
+ if( aHead )
+ {
+ SetDownloadStatus( EHttpContentTypeRequested );
+ }
+ else
+ {
+ SetDownloadStatus( EHttpProgSubmitIssued );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ContentTypeReceivedL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ContentTypeReceivedL()
+ {
+ LOGGER_ENTERFN( "ContentTypeReceivedL" );
+
+ InternalPauseL( EFalse );
+ SetDownloadStatus( EHttpContentTypeReceived, EHttpDlPaused );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::HttpResponse401L
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::HttpResponse401L()
+ {
+ LOGGER_ENTERFN( "HttpResponse401L" );
+
+ THTTPHdrVal hdrValue;
+ RStringPool strPool = iConnHandler->Session().StringPool();
+
+ // Check authentication scheme
+ TBool basic = iTrans.PropertySet().Property( strPool.StringF( HTTP::EBasic,
+ RHTTPSession::GetTable() ),
+ hdrValue );
+
+ if( basic )
+ // property is set -> Basic
+ {
+ iAuthScheme = EAuthBasic;
+ }
+ else
+ // property not set -> Digest
+ {
+ iAuthScheme = EAuthDigest;
+ }
+
+ RStringF staleStr = strPool.StringF( HTTP::EStale, RHTTPSession::GetTable() );
+
+ SaveCredentialsL( strPool );
+ if( iTrans.PropertySet().Property( staleStr, hdrValue ) || // 1.
+ (iDlStartedByClient && iHttpUsername) ) // 2.
+ // 1. - In case of stale we only have to resubmit the request
+ // with the same credentials info
+ // 2. - download was started by the client app that has specified
+ // the http username -> try to do the authentication
+ {
+ CancelTransaction();
+ SetDownloadStatus( EHttpStarted );
+ }
+ else
+ {
+ OnError( KErrUnknown, EHttpAuthenticationFailed );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::HttpResponse407L
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::HttpResponse407L()
+ {
+ LOGGER_ENTERFN( "HttpResponse407L" );
+
+ // Check authentication scheme
+ THTTPHdrVal hdrValue;
+
+ RStringPool strPool = iConnHandler->Session().StringPool();
+ TInt err = iTrans.PropertySet().Property( strPool.StringF( HTTP::EBasic,
+ RHTTPSession::GetTable() ),
+ hdrValue );
+
+ if( !err )
+ // property is set -> Basic
+ {
+ iAuthScheme = EAuthBasic;
+ }
+ else
+ // property not set -> Digest
+ {
+ iAuthScheme = EAuthDigest;
+ }
+
+ RStringF staleStr = strPool.StringF( HTTP::EStale, RHTTPSession::GetTable() );
+
+ SaveCredentialsL( strPool );
+ if( iTrans.PropertySet().Property( staleStr, hdrValue ) || // 1.
+ (iDlStartedByClient && iHttpUsername) ) // 2.
+ // 1. - In case of stale we only have to resubmit the request
+ // with the same credentials info
+ // 2. - download was started by the client app that has specified
+ // the http username -> try to do the authentication
+ {
+ CancelTransaction();
+ SetDownloadStatus( EHttpStarted );
+ }
+ else
+ {
+ OnError( KErrUnknown, EProxyAuthenticationFailed );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::FindHeaderField
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CHttpDownload::FindHeaderField( CArrayPtrFlat<CHeaderField>* aHeaders,
+ const TDesC8& aFieldName ) const
+ {
+ for( TInt index = 0; index < aHeaders->Count(); ++index )
+ {
+ if( *(*aHeaders)[index]->FieldName() == aFieldName )
+ {
+ return index;
+ }
+ }
+
+ return KErrNotFound;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ConvertDownloadNameUniqueL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ConvertDownloadNameUniqueL()
+ {
+ LOGGER_ENTERFN( "ConvertDownloadNameUniqueL" );
+
+ CArrayPtrFlat<CHttpDownload>* downloads = iClientApp->Downloads();
+ TBool bFound( EFalse );
+ TInt index( 0 );
+ HBufC* uniqueName = NULL;
+
+ do
+ {
+ bFound = EFalse;
+
+ CreateIndexedNameL( uniqueName, *iDlName, index );
+
+ for( TInt i = 0; i < downloads->Count(); ++i )
+ {
+ if( (*downloads)[i] != this )
+ {
+ CLOG_WRITE_1( "Compare: %S", (*downloads)[i]->iDlName );
+ if( !uniqueName->Des().Compare( *(*downloads)[i]->iDlName ) )
+ {
+ bFound = ETrue;
+ break;
+ }
+ }
+ }
+ }while( bFound );
+
+ delete iDlName;
+ iDlName = uniqueName;
+ CLOG_WRITE_1( "Unique name: [%S]", iDlName );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::CreateIndexedNameL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::CreateIndexedNameL( HBufC* &aUniqueName,
+ TDesC& aOrgName,
+ TInt& aIndex )
+ {
+ LOGGER_ENTERFN( "CreateIndexedNameL" );
+
+ TPtrC left;
+ TPtrC extension;
+ TBuf<KMaxIndexStringLength> indexStr;
+
+ if( aIndex )
+ {
+ indexStr.Format( KIndexString, aIndex );
+ }
+
+ TInt fullLength = aOrgName.Length() + indexStr.Length();
+ if( fullLength > KMaxPath )
+ // name is longer than KMaxPath.
+ {
+ OnError( KErrGeneral, EBadUrl );
+ User::Leave( KErrGeneral );
+ }
+
+ delete aUniqueName; aUniqueName = NULL;
+
+ TInt dotInd = aOrgName.LocateReverse( '.' );
+ if( dotInd != KErrNotFound )
+ // filename extension found.
+ // insert index string between name and extension
+ {
+ extension.Set( aOrgName.Right( aOrgName.Length() - dotInd ) );
+ left.Set( aOrgName.Left( MIN( dotInd, ( KDownloadNameMaxSize -
+ indexStr.Length() - extension.Length() ))));
+ }
+ else
+ {
+ left.Set( aOrgName.Left( KDownloadNameMaxSize - indexStr.Length() ));
+ }
+
+ aUniqueName = HBufC::NewL( fullLength );
+ aUniqueName->Des().Format( _L("%S%S%S"), &left,
+ &indexStr,
+ &extension );
+
+ ++aIndex;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ContinueDownloadStoreResponseHeaderL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ContinueDownloadStoreResponseHeaderL(
+ const TDesC8& aResponseHeader )
+ {
+ LOGGER_ENTERFN( "ContinueDownloadStoreResponseHeaderL" );
+
+ TInt colon( KErrNotFound );
+ TInt separator( KErrNotFound );
+ TPtrC8 field( aResponseHeader );
+ TPtrC8 fieldName;
+ TPtrC8 fieldValue;
+ RStringPool strPool;
+
+ // forget the previous headers
+ iResponseHeaders->ResetAndDestroy();
+ iEntityHeaders->ResetAndDestroy();
+
+ strPool.OpenL( RHTTPSession::GetTable() );
+ strPool.OpenL( HttpFilterCommonStringsExt::GetTable() );
+
+ do
+ {
+ separator = KErrNotFound;
+
+ colon = field.Locate( KColon );
+
+ if( colon > 0 )
+ // name found and is at least one byte long
+ {
+ fieldName.Set( field.Left( colon ) );
+ field.Set( field.Right( field.Length() - colon - 1 ) );
+
+ separator = field.Locate( KHttpFieldSeparator()[0] );
+
+ if( separator != KErrNotFound )
+ // there is more add-on
+ {
+ fieldValue.Set( field.Left( separator ) );
+ field.Set( field.Right( field.Length() - separator - 1 ) );
+ }
+ else
+ // this is the last add-on
+ {
+ fieldValue.Set( field );
+ }
+
+ CHeaderField* newField = CHeaderField::NewL( &fieldName, &fieldValue );
+ CleanupStack::PushL( newField );
+
+ CLOG_WRITE8_2("%S:%S", &fieldName, &fieldValue);
+ iResponseHeaders->AppendL( newField );
+
+ CleanupStack::Pop( newField );
+
+ CHeaderField* newentField = CHeaderField::NewL( &fieldName, &fieldValue );
+ CleanupStack::PushL( newentField );
+
+ CLOG_WRITE8_2("%S:%S", &fieldName, &fieldValue);
+ iEntityHeaders->AppendL( newentField );
+
+ CleanupStack::Pop( newentField );
+ }
+
+ }while( separator != KErrNotFound );
+
+ ParseContentTypeL( strPool );
+
+ ParseContentDispositionL( strPool);
+ if (!iCodDownload)
+ {
+ if (iUseAttachmentFileName || iUseInlineFileName)
+ {
+ SetDownloadNameL( *iAttachmentFileName );
+ }
+ }
+
+ CheckRealDRMContentType();
+
+ RStringF length = strPool.StringF(HTTP::EContentLength,RHTTPSession::GetTable());
+ RStringF contentEncoding = strPool.StringF( HTTP::EContentEncoding, RHTTPSession::GetTable() );
+
+ TInt index = FindHeaderField( iResponseHeaders, length.DesC() );
+ TInt contentEncodingInd = FindHeaderField( iResponseHeaders, contentEncoding.DesC() );
+ if( ( index != KErrNotFound && contentEncodingInd == KErrNotFound ) &&
+ iDrmContentLengthValid )
+ {
+ iStorage->SetLength( (*iResponseHeaders)[index]->Int() );
+ }
+ else
+ // in case of content-encoding the content length is size of the compressed content
+ // not the decompressed one.
+ {
+ CLOG_WRITE( "Content is encoded, or DRM" );
+ iStorage->SetLength( KDefaultContentLength );
+ }
+
+ strPool.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ParseContentTypeL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ParseContentTypeL( RStringPool& aStrPool )
+ {
+ LOGGER_ENTERFN( "ParseContentTypeL" );
+
+ RStringF contentType = aStrPool.StringF(HTTP::EContentType,RHTTPSession::GetTable());
+
+ TInt index = FindHeaderField( iResponseHeaders, contentType.DesC() );
+ if( index != KErrNotFound )
+ // store content-type
+ {
+ TPtrC8 rawData( *(*iResponseHeaders)[index]->FieldRawData() );
+ TPtrC8 mediaType;
+
+ // ';' separates content-type from media type
+ TInt semicolon = rawData.Locate( KSemiColon );
+
+ if( semicolon != KErrNotFound )
+ {
+ mediaType.Set( rawData.Right( rawData.Length() - semicolon - 1 ) );
+ Trim( mediaType );
+ rawData.Set( rawData.Left( semicolon ) );
+ Trim( rawData );
+ }
+
+ ReallocateStringL( iContentType, rawData, KMaxContentTypeLength );
+ ReallocateStringL( iDDType, rawData, KMaxContentTypeLength );
+ ReallocateStringL( iMediaType, mediaType, KMaxContentTypeLength );
+ }
+
+#ifdef __SYNCML_DM_FOTA
+ if( !iContentType->Des().CompareF( KFotaMimeType ) )
+ {
+ iStorage->SetStorageMethod( CHttpStorage::EStoreFota );
+ }
+#endif
+
+ if( ( 0 == iContentType->Des().Compare( KCodMimeType() ) ) ||
+ ( 0 == iContentType->Des().Compare( KDdMimeType() ) ) ||
+ ( 0 == iContentType->Des().Compare( KDd2MimeType() ) ) )
+ {
+ SetCodFlag( ETrue );
+ }
+
+ if( 0 == iContentType->Des().Compare( KMultiPartMimeType() ) )
+ {
+ iMultiPart = ETrue;
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ParseContentDispositionL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ParseContentDispositionL( RStringPool& aStrPool )
+ {
+ LOGGER_ENTERFN( "ParseContentDispositionL" );
+
+ RStringF contentDisposition = aStrPool.StringF(HTTP::EContentDisposition,RHTTPSession::GetTable());
+
+ TInt index = FindHeaderField( iResponseHeaders, contentDisposition.DesC() );
+ if( index != KErrNotFound )
+ // store content-disposition
+ {
+ TPtrC8 rawData( *(*iResponseHeaders)[index]->FieldRawData() );
+ TPtrC8 fileNameParm;
+ TBool isFileNameParam = EFalse;
+
+ // ';' separates disposition-type from disposition parm
+ TInt semicolon = rawData.Locate( KSemiColon );
+
+ if( semicolon != KErrNotFound )
+ {
+ fileNameParm.Set( rawData.Right( rawData.Length() - semicolon - 1 ) );
+ Trim( fileNameParm );
+ // filename=<AttachmentFileName>
+ TInt offset = fileNameParm.FindC( KHttpFileNameParm );
+ if (offset != KErrNotFound)
+ {
+ // '=' separates value of fileName from the <AttachmentFileName>
+ TInt equal = fileNameParm.Locate( KEqual );
+ if( equal != KErrNotFound )
+ {
+ fileNameParm.Set( fileNameParm.Right( fileNameParm.Length() - equal - 1 ) );
+ Trim( fileNameParm );
+ TInt semicolon1 = fileNameParm.Locate( KSemiColon );
+
+ // find '"' around the <AttachmentFileName>
+ TInt quote = fileNameParm.Locate( KQuote );
+ if (quote != KErrNotFound)
+ {
+ fileNameParm.Set( fileNameParm.Right( fileNameParm.Length() - quote - 1 ) );
+ Trim( fileNameParm );
+ }
+
+ TInt quote1 = fileNameParm.Locate( KQuote );
+ if (quote1 != KErrNotFound)
+ {
+ fileNameParm.Set( fileNameParm. Left(quote1) );
+ Trim( fileNameParm );
+ }
+
+ if( semicolon1 != KErrNotFound )
+ {
+ fileNameParm.Set( fileNameParm.Left( semicolon1 ) );
+ }
+ isFileNameParam = ETrue;
+ // we must strip off any directory names from the filename
+ // first check for and remove any trailing '\' or '/' characters
+ if( ( fileNameParm.Right( 1 ).Locate( '\\' ) != KErrNotFound ) ||
+ ( fileNameParm.Right( 1 ).Locate( '/' ) != KErrNotFound ))
+ {
+ fileNameParm.Set( fileNameParm.Left( fileNameParm.Length() - 1 ));
+ }
+ // next find location of last '/' or '\' to remove any directory names
+ TInt lastSlash = fileNameParm.LocateReverse( '/' );
+ if( lastSlash == KErrNotFound )
+ {
+ lastSlash = fileNameParm.LocateReverse( '\\' );
+ }
+ if( lastSlash != KErrNotFound )
+ {
+ fileNameParm.Set( fileNameParm.Mid( lastSlash + 1 ));
+ }
+ }
+ rawData.Set( rawData.Left( semicolon ) ); // DispositionType
+ Trim( rawData );
+ }
+ }
+
+ ReallocateStringL( iDispositionType, rawData, KMaxDispositionTypeLength );
+
+ if( isFileNameParam && (0 == iDispositionType->Des().CompareC( KHttpDispositionTypeAttachment()) ) )
+ {
+ ReallocateStringL( iAttachmentFileName, fileNameParm );
+ iUseAttachmentFileName = ETrue;
+ }
+ if( isFileNameParam && (0 == iDispositionType->Des().CompareC( KHttpDispositionTypeInline()) ) )
+ {
+ ReallocateStringL( iAttachmentFileName, fileNameParm );
+ iUseInlineFileName = ETrue;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::TriggerEvent
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::TriggerEvent( THttpDownloadState aDlState,
+ THttpProgressState aProgState )
+ {
+#ifdef __DOWNLOADMGR_LOG__ // to filter out EHttpProgResponseBodyReceived
+ if( aProgState != EHttpProgResponseBodyReceived )
+ {
+ CLOG_WRITE_3( "Trigger: %d - %d - %d", aDlState, aProgState, iActiveDownload );
+ }
+#endif
+
+ if( iSilentMode )
+ {
+ if( !((aDlState == EHttpDlInprogress && aProgState == EHttpStarted)
+ || aDlState == EHttpDlMultipleMOCompleted || aDlState == EHttpDlFailed ))
+ // See EDlAttrSilent
+ {
+ return;
+ }
+ }
+
+ if( !iDontFireEvent )
+ {
+ if( iClAppInstance && iClAppInstance->Observer() )
+ {
+ // informs client app about status change
+ iClAppInstance->Observer()->Event( this, aDlState, aProgState, iActiveDownload );
+ }
+
+ if( iPDClAppInstance && iPDClAppInstance->Observer() )
+ {
+ if( iActiveDownload == iActivePlayedDownload || aDlState == EHttpDlDeleting )
+ iPDClAppInstance->Observer()->Event( this, aDlState, aProgState, iActiveDownload );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::UpdatePausable
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::UpdatePausable()
+ {
+ LOGGER_ENTERFN( "UpdatePausable" );
+
+ TBool pausable( ETrue );
+
+ if( !iPausableDRM )
+ {
+ pausable = EFalse;
+ }
+
+ if( iMethod == EMethodPOST )
+ {
+ pausable = EFalse;
+ }
+
+ if( pausable != iPausable )
+ {
+ if( !iCodDownload )
+ {
+ iPausable = pausable;
+
+ // inform client about change
+ TriggerEvent( iPausable ? EHttpDlPausable : EHttpDlNonPausable );
+
+ TRAP_IGNORE( StoreDownloadInfoL() );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ForcedRestartL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ForcedRestartL()
+ {
+ // Forget a previous redirect
+ ReallocateStringL( iRedirUrl, *iUrl );
+ ReallocateStringL( iCurrentUrl, *iRedirUrl );
+ iRedirect = EFalse;
+
+ ReInitializeDownload();
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::HeaderFieldL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+HBufC8* CHttpDownload::HeaderFieldL( CArrayPtrFlat<CHeaderField>* aHeaders,
+ TInt aFieldIndex )
+ {
+ HBufC8* retVal = NULL;
+ RStringPool strPool;
+
+ strPool.OpenL( RHTTPSession::GetTable() );
+ // Find field in response header
+ RStringF charset = strPool.StringF( aFieldIndex, RHTTPSession::GetTable() );
+
+ TInt index = FindHeaderField( aHeaders, charset.DesC() );
+ if( KErrNotFound != index )
+ {
+ retVal = (*aHeaders)[index]->FieldRawData();
+ }
+
+ strPool.Close();
+
+ return retVal;
+ }
+
+#ifdef DEAD_CODE
+// -----------------------------------------------------------------------------
+// CHttpDownload::CheckIfContentUnModified
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CHttpDownload::CheckIfContentUnModified()
+ {
+ CLOG_WRITE( "CheckIfContentUnModified" );
+
+ RStringPool strPool = iConnHandler->Session().StringPool();
+ RHTTPHeaders headers( iTrans.Response().GetHeaderCollection() );
+
+ RStringF lastMod = strPool.StringF(HTTP::ELastModified,RHTTPSession::GetTable());
+ THTTPHdrVal value;
+
+ if( !headers.GetField( lastMod, 0, value ) )
+ {
+ TDateTime date( value );
+
+ if( iDate.Year() != date.Year() ||
+ iDate.Month() != date.Month() ||
+ iDate.Day() != date.Day() ||
+ iDate.Hour() != date.Hour() ||
+ iDate.Minute() != date.Minute() ||
+ iDate.Second() != date.Second() ||
+ iDate.MicroSecond() != date.MicroSecond() )
+ {
+ CLOG_WRITE( "Date changed" );
+
+ return EFalse;
+ }
+ }
+
+ return ETrue;
+ }
+#endif
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::CheckAttribMaxLengthL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::CheckAttribMaxLengthL( THttpDownloadAttrib aAttribute,
+ const TDesC16& aValue )
+ {
+ for( TInt i = 0; KStringAttribMaxLengths[i][0]; ++i )
+ {
+ if( aAttribute == KStringAttribMaxLengths[i][0] )
+ {
+ if( aValue.Length() > KStringAttribMaxLengths[i][1] )
+ {
+ CLOG_WRITE_2( "Overflow length: %d, max-length: %d", aValue.Length(),
+ KStringAttribMaxLengths[i][1] );
+ User::Leave( KErrOverflow );
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::CheckAttribMaxLengthL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::CheckAttribMaxLengthL( THttpDownloadAttrib aAttribute,
+ const TDesC8& aValue )
+ {
+ for( TInt i = 0; KStringAttribMaxLengths[i][0]; ++i )
+ {
+ if( aAttribute == KStringAttribMaxLengths[i][0] )
+ {
+ if( aValue.Length() > KStringAttribMaxLengths[i][1] )
+ {
+ CLOG_WRITE_2( "Overflow length: %d, max-length: %d", aValue.Length(),
+ KStringAttribMaxLengths[i][1] );
+ User::Leave( KErrOverflow );
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetCookiesL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetCookiesL( RStringPool& aStringPool )
+ {
+ RStringF propName = aStringPool.OpenFStringL( KCookieUsage );
+
+ CleanupClosePushL( propName );
+
+ SetPropertyL( propName, iUseCookies );
+
+ CleanupStack::PopAndDestroy( &propName );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::DownloadSucceededL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::DownloadSucceededL()
+ {
+ CLOG_WRITE( "Transaction succeeded" );
+
+ // inform storage class that it doesn't have to expect any more chunk
+ // completed event fired only when the last chunk is persisted
+ OnCompletedL();
+ iDlStartedByClient = EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::ParseRequestHeaderAddOnL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ParseRequestHeaderAddOnL( const TDesC8& aValue )
+ {
+ if( !aValue.Length() )
+ {
+ return;
+ }
+
+ TPtrC8 fieldName;
+ TPtrC8 fieldData;
+ TPtrC8 value( aValue );
+
+ TInt ind( 0 );
+ TBool found( EFalse );
+
+ RStringPool strPool = iClAppInstance->ConnHandler()->Session().StringPool();
+ TInt fieldInd;
+
+ do
+ {
+ fieldInd = KErrNotFound;
+ // find KColon in the argument string
+ for( ind = 0; ind < value.Length() && value[ind] != KColon; ++ind ){};
+
+ if( value[ind] != KColon )
+ // no KColon -> Invalid request header
+ {
+ User::Leave( KErrArgument );
+ }
+
+ // store field name
+ fieldName.Set( value.Left( ind ) );
+ // and remove it from the argument string
+ value.Set( value.Right( value.Length() - ind - 1 ) );
+
+ // find field separator
+ ind = value.Find( KHttpFieldSeparator );
+
+ if( ind == KErrNotFound )
+ // not found -> no more field
+ {
+ fieldData.Set( value );
+ found = EFalse;
+ }
+ else
+ // found -> store raw data
+ // and go to next field
+ {
+ fieldData.Set( value.Left( ind ) );
+ value.Set( value.Right( value.Length() - ind - 1 ) );
+ found = ETrue;
+ }
+
+ // Find out if this is a native request header field, or not.
+ // If not, fieldInd is KErrNotFound
+ for( TInt i = 0; KRequestHeaderConvTable[i][0]; ++i )
+ {
+ RStringF fieldNameStr = strPool.StringF( KRequestHeaderConvTable[i][1],
+ RHTTPSession::GetTable() );
+
+ if( !fieldName.CompareF( fieldNameStr.DesC() ) )
+ // this is a native header field name
+ {
+ fieldInd = i;
+ break;
+ }
+ }
+
+ CHeaderField* field = CHeaderField::NewL( &fieldName, &fieldData, fieldInd );
+ CleanupStack::PushL( field );
+
+ iRequestHeaders->AppendL( field );
+ CLOG_WRITE8_3("Req(%d): %S:%S", iRequestHeaders->Count(), &fieldName, &fieldData );
+
+ CleanupStack::Pop( field );
+ }while( found );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::LoadHeadersL
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::LoadHeadersL( RFile& aFile,
+ CArrayPtrFlat<CHeaderField>* aHeaders )
+ {
+ TInt headers;
+ READ_INT_L( aFile, headers );
+
+ CLOG_WRITE_1("Headers: %d", headers);
+ aHeaders->ResetAndDestroy();
+
+ for( TInt i = 0; i < headers; ++i )
+ {
+ CHeaderField* field = CHeaderField::NewL();
+ CleanupStack::PushL( field );
+
+ field->LoadHeaderInfoL( aFile );
+ aHeaders->AppendL( field );
+
+/* if( field->FieldName() && field->FieldRawData() )
+ {
+ CLOG_WRITE8_1( "%S", field->FieldName() );
+ CLOG_WRITE8_1( "%S", field->FieldRawData() );
+ }
+ else
+ {
+ CLOG_WRITE8( "Empty field" );
+ }
+*/
+ CleanupStack::Pop( field );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::AppendHeadersL
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::AppendHeadersL( TPtr8& aBuf,
+ CArrayPtrFlat<CHeaderField>* aHeaders )
+ {
+ TInt headers = aHeaders->Count();
+ CLOG_WRITE_1("Headers: %d", headers);
+
+ APPEND_BUF_INT( aBuf, headers );
+
+ HBufC8* fieldName = NULL;
+ HBufC8* fieldRawData = NULL;
+ for( TInt i = 0; i < headers; ++i )
+ {
+ fieldName = (*aHeaders)[i]->FieldName();
+ fieldRawData = (*aHeaders)[i]->FieldRawData();
+ AppendBufL( aBuf, fieldName );
+ AppendBufL( aBuf, fieldRawData );
+ CLOG_WRITE8_2( "%S:%S", fieldName, fieldRawData );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::AddHeaderL
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::AddHeaderL( THttpDownloadAttrib aAttribute,
+ const TDesC8& aValue,
+ const TInt aConversionTable[][2],
+ CArrayPtrFlat<CHeaderField>* aHeaders )
+ {
+ TInt index( KErrNotFound );
+
+ // search for if this field is already in the
+ for( index = 0; aConversionTable[index][0]; ++index )
+ {
+ if( aConversionTable[index][0] == aAttribute )
+ {
+ break;
+ }
+ }
+
+ __ASSERT_DEBUG( index != KErrNotFound, DMPanic( KErrCorrupt ) );
+
+ RStringPool strPool = iClAppInstance->ConnHandler()->Session().StringPool();
+ RStringF fieldName = strPool.StringF( aConversionTable[index][1],
+ RHTTPSession::GetTable() );
+ CleanupClosePushL( fieldName );
+
+ // make a copy of the raw data
+ HBufC8* value = HBufC8::NewLC( aValue.Length() );
+ value->Des().Copy( aValue );
+
+ CHeaderField* newField = CHeaderField::NewL( &fieldName.DesC(), value, index );
+
+ CleanupStack::Pop( value );
+ CleanupStack::PushL( newField );
+
+ aHeaders->AppendL( newField );
+
+ CleanupStack::Pop( 2 ); // newField, fieldName
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::RedirectedPermanentlyL
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::RedirectedPermanentlyL( const TDesC8& aNewUrl )
+ {
+ CLOG_WRITE8_1( "ERedirectedPermanently: %S", &aNewUrl );
+ // from now on this new redirected url has to be used
+ if( !iRedirect )
+ {
+ ReallocateStringL( iRedirUrl, aNewUrl, KMaxUrlLength );
+ ReallocateStringL( iCurrentUrl, *iRedirUrl, KMaxUrlLength );
+ }
+ else
+ // there has already been a temporary redirection
+ // this permanent is not used on next submitted request
+ {
+ ReallocateStringL( iCurrentUrl, aNewUrl, KMaxUrlLength );
+ }
+ ParseDownloadNameL();
+ StoreDownloadInfoL(); // to store new url
+
+ TriggerEvent( EHttpDlInprogress, EHttpProgRedirectedPermanently );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::RedirectedPermanentlyL
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::RedirectedTemporaryL( const TDesC8& aNewUrl )
+ {
+ CLOG_WRITE8_1( "ERedirectedTemporarily: %S", &aNewUrl );
+ iRedirect = ETrue;
+ ReallocateStringL( iCurrentUrl, aNewUrl, KMaxUrlLength );
+ ParseDownloadNameL();
+ StoreDownloadInfoL(); // to store iRedirect
+
+ TriggerEvent( EHttpDlInprogress, EHttpProgRedirectedTemporarily );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::FixDownloadNameL
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::FixDownloadNameL()
+ {
+ if( !iCodDownload )
+ {
+ TPtr name( iDlName->Des() );
+
+ for( TInt i = 0; i < name.Length(); ++i )
+ {
+ TChar currChar = (*iDlName)[i];
+
+ if( currChar.IsAlphaDigit() ||
+ currChar.IsGraph() ||
+ currChar == 0x20 ) // space
+ {
+ continue;
+ }
+ else
+ {
+ name[i] = KUrlFixChar;
+ }
+ }
+
+ ConvertDownloadNameUniqueL();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SetCodFlag
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SetCodFlag( TBool aValue )
+ {
+ if( aValue && iCodDownload )
+ {
+ // this case we will not overwrite
+ // the value of iCodDownload. iCodDownload might be > 1
+ return;
+ }
+ iCodDownload = aValue;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::SelfComplete
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::SelfComplete( TInt aReason )
+ {
+ __ASSERT_DEBUG( !IsActive(), DMPanic( KErrGeneral ) );
+ SetActive();
+
+ TRequestStatus* dummy = &iStatus;
+
+ User::RequestComplete( dummy, aReason );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::UpdateDestFileNameL
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::UpdateDestFileNameL()
+ {
+ LOGGER_ENTERFN( "UpdateDestFileNameL" );
+ RFs fs;
+ User::LeaveIfError( fs.Connect() );
+ CleanupClosePushL(fs);
+ TInt32 downloadedSize(0);
+ downloadedSize = iStorage->DownloadedSize();
+ HBufC16* fileName ;
+ fileName = iStorage->DestFilename();
+ TPtr fileNamePtr = fileName->Des();
+ TDriveUnit currentDrive(fileNamePtr);
+ TBuf<KMaxDrives> driveList;
+ TInt err( KErrNone );
+ TInt drive( EDriveC );
+ TBool criticalSpace( EFalse );
+ TBool needToUpdatePath( ETrue );
+
+ CLOG_WRITE_1( " entering fileName: %S", fileName );
+#ifdef RD_MULTIPLE_DRIVE
+ HBufC8* drivesDynList = iClientApp->Engine()->QueryDynDriveListLC();
+ TPtrC8 drives( *drivesDynList );
+#else
+ TPtrC drives( iClientApp->Engine()->iDriveLettersCenRep );
+#endif
+ // drive letters are separated by semicolons
+ for( TInt i = 0; i < drives.Length() && (err || !criticalSpace); i = i + 2 )
+ {
+ if( ( err = fs.CharToDrive( drives[i], drive )) != KErrNone )
+ {
+ continue;
+ }
+ if( drive == currentDrive )//if the current path is same as the path in cenrep then no need to update.The diff is because we must have not known size before hand
+ {
+ needToUpdatePath = EFalse;
+ break;
+ }
+ else
+ {
+ TInt bytesToWrite = downloadedSize;
+ if (bytesToWrite < 0)
+ bytesToWrite = 0;
+
+ TRAP( err, criticalSpace = !SysUtil::DiskSpaceBelowCriticalLevelL(
+ &fs, bytesToWrite, drive ));
+ }
+ }
+ if( needToUpdatePath )
+ {
+ iDlNameChanged = ETrue;
+#ifdef RD_MULTIPLE_DRIVE
+ // using PathInfo::RootPath to set correct destination folder
+ // depending on memory used
+
+ // Getting RootPath for selected Drive
+ TFileName rootPath;
+ User::LeaveIfError( PathInfo::GetRootPath( rootPath, drive ) );
+
+ // remove path from EDlAttrDestFilename
+ if( fileNamePtr.Length() > 0 )
+ {
+ TInt lastSlashPos = fileNamePtr.LocateReverse( '\\' );
+ if( lastSlashPos != KErrNotFound )
+ {
+ fileNamePtr.Delete( 0, lastSlashPos );
+ }
+ }
+
+ // Setting RootPath for new Destination file
+ fileNamePtr.Insert( 0, rootPath );
+ // Setting KDownloadPath
+ fileNamePtr.Insert( rootPath.Length(), KDownloadPath );
+#else
+ TChar driveChar;
+ fs.DriveToChar(drive, driveChar);
+ TBuf<2> buf;
+ buf.Append(driveChar);
+ fileNamePtr.Replace(0,1,buf);
+#endif
+ err = fs.MkDirAll( fileNamePtr );//in case the size unknown the dir needs to be formed again as Drive can change
+ if ( err != KErrNone && err != KErrAlreadyExists )
+ {
+ User::Leave( err );
+ }
+ }
+ CLOG_WRITE_1( " exiting fileName: %S", fileName );
+#ifdef RD_MULTIPLE_DRIVE
+ CleanupStack::PopAndDestroy( drivesDynList );
+#endif
+ CleanupStack::PopAndDestroy( &fs );
+ }
+
+// ---------------------------------------------------------
+// CHttpDownload::UpdateDCFRepositoryL()
+// Update saved file to DCFRepository
+// ---------------------------------------------------------
+//
+void CHttpDownload::UpdateDCFRepositoryL(
+ const TDesC& aFileName )
+ {
+ LOGGER_ENTERFN( "UpdateDCFRepositoryL" );
+ CLOG_WRITE_1( " :UpdateDCFRepositoryL() for: %S", &aFileName );
+ CDcfEntry* dcfEntry = NULL;
+ dcfEntry = CDcfEntry::NewL();
+ CleanupStack::PushL( dcfEntry );
+
+ CDcfRep* dcfRep = NULL;
+ dcfRep = CDcfRep::NewL();
+ CleanupStack::PushL( dcfRep );
+
+ dcfEntry->SetLocationL( aFileName, 0 );
+ CLOG_WRITE(" : SetLocationL OK");
+ dcfRep->UpdateL( dcfEntry );
+ CLOG_WRITE(" :UpdateL OK");
+ CleanupStack::PopAndDestroy(2); // dcfEntry, dcfRep
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::MoveInDeleteL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CHttpDownload::MoveInDelete(TInt mediaObjectIndex)
+ {
+ TInt err(KErrNone);
+ if(!iCodDlData)
+ return err;
+
+ if( mediaObjectIndex <= iCodDlData->Count())
+ {
+ TRAP_IGNORE(MoveDownloadedMediaObjectSyncL(mediaObjectIndex));
+ TPtrC filenamePtr = ((*iCodDlData)[mediaObjectIndex])->DestFilename();
+ if(filenamePtr.Length())
+ {
+ TRAP_IGNORE(NotifyMediaGalleryL( filenamePtr ));
+ }
+ }
+ return err;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::MoveDownloadedMediaObjectL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::MoveDownloadedMediaObjectL(TInt mediaObjectIndex)
+ {
+ LOGGER_ENTERFN( "MoveDownloadedMediaObjectsL" );
+
+ if( iDlState != EHttpDlMultipleMOCompleted && !iMoDownloadCompleted )
+ {
+ iStorage->SetProgressiveMode( EFalse );
+ TriggerEvent( iDlState, EHttpDlProgNonProgressive);
+ return;//Move will be Done by COD as MO Completed has not happened
+ }
+
+ //__ASSERT_DEBUG( !IsActive(), DMPanic( KErrInUse ) );
+ //__ASSERT_DEBUG( !iFileMan, DMPanic( KErrInUse ) );
+
+#if 0
+
+#else
+
+ HBufC* filename = HBufC::NewLC(KMaxFileName);
+ TPtr filenamePtr1 = filename->Des();
+
+ RFs &fs = iClientApp->Engine()->Fs();
+ if(!iFileMan)
+ {
+ iFileMan = CFileMan::NewL(fs);
+ }
+
+ TPtrC filenamePtr2 = ((*iCodDlData)[mediaObjectIndex])->DestFilename();
+ if(!filenamePtr2.Length())
+ {
+ CleanupStack::PopAndDestroy(filename);
+ return;
+ }
+
+ TInt firstSlashPos = filenamePtr2.Locate( '\\' );
+
+ if(firstSlashPos < 0)
+ {
+ CleanupStack::PopAndDestroy(filename);
+ return;
+ }
+ TPtrC dlName = filenamePtr2.Left(firstSlashPos);
+
+ TInt drive;
+
+ User::LeaveIfError( fs.CharToDrive( dlName[0], drive ));
+
+
+ // Getting RootPath for selected Drive
+ TFileName rootPath;
+ User::LeaveIfError( PathInfo::GetRootPath( rootPath, drive ) );
+
+ // Setting KDownloadPath
+ rootPath.Append( KDownloadPath );
+
+ filenamePtr1.Copy(rootPath);
+ filenamePtr1.Append(_L("\\"));
+
+ TInt error = fs.MkDirAll(filenamePtr1);
+ if (error!=KErrNone && error!=KErrAlreadyExists)
+ {
+ User::Leave(error);
+ }
+ if( mediaObjectIndex == iActivePlayedDownload )
+ {
+
+ iFname = ((*iCodDlData)[mediaObjectIndex])->TempFilename();
+ }
+
+ else
+ {
+
+ iFname = ((*iCodDlData)[mediaObjectIndex])->DestFilename();
+ }
+ // Find a unique name to avoid any conflict.
+ // Here iFname has full path of current location of file
+ // and filename has destination path.
+ FindUniqueDestinationFileNameL( iFname, filename );
+
+ filenamePtr1 = filename->Des();
+
+ User::LeaveIfError( iFileMan->Move( iFname, filenamePtr1, CFileMan::EOverWrite, iStatus ) );
+ // waiting for move to complete
+ SetActive();
+ iFname = filenamePtr1;
+ ((*iCodDlData)[mediaObjectIndex])->SetDestFilenameL(filenamePtr1);
+
+ CleanupStack::PopAndDestroy(filename);
+
+#endif
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::MoveDownloadedMediaObjectSyncL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::MoveDownloadedMediaObjectSyncL(TInt mediaObjectIndex)
+ {
+ LOGGER_ENTERFN( "MoveDownloadedMediaObjectSyncL" );
+
+ if( !iCodDownload && iDlState != EHttpDlMultipleMOCompleted )
+ {
+ User::Leave( KErrNotReady );
+ }
+
+ //__ASSERT_DEBUG( !IsActive(), DMPanic( KErrInUse ) );
+ //__ASSERT_DEBUG( !iFileMan, DMPanic( KErrInUse ) );
+
+
+
+ RFs &fs = iClientApp->Engine()->Fs();
+ if(!iFileMan)
+ {
+ iFileMan = CFileMan::NewL(fs);
+ }
+
+ HBufC* filename = HBufC::NewLC(KMaxFileName);
+ TPtr filenamePtr = filename->Des();
+
+ TPtrC fileNamePtr = ((*iCodDlData)[mediaObjectIndex])->DestFilename();
+ TInt firstSlashPos = fileNamePtr.Locate( '\\' );
+ if(firstSlashPos < 0)
+ {
+ CleanupStack::PopAndDestroy(filename);
+ return;
+ }
+ TPtrC dlName = fileNamePtr.Left(firstSlashPos);
+ TInt drive;
+
+ User::LeaveIfError( fs.CharToDrive( dlName[0], drive ));
+
+
+ // Getting RootPath for selected Drive
+ TFileName rootPath;
+ User::LeaveIfError( PathInfo::GetRootPath( rootPath, drive ) );
+
+ // Setting KDownloadPath
+ rootPath.Append( KDownloadPath );
+
+ filenamePtr.Copy(rootPath);
+ filenamePtr.Append(_L("\\"));
+
+ TInt error = fs.MkDirAll(filenamePtr);
+ if (error!=KErrNone && error!=KErrAlreadyExists)
+ {
+ User::Leave(error);
+ }
+ iFname = ((*iCodDlData)[mediaObjectIndex])->DestFilename();
+
+ // Find a unique name to avoid any conflict.
+ // Here iFname has full path of current location of file
+ // and filename has destination path.
+ FindUniqueDestinationFileNameL( iFname, filename );
+
+ filenamePtr = filename->Des();
+
+ TInt err = iFileMan->Move(iFname, filenamePtr, CFileMan::EOverWrite);
+ if(err != KErrNone)
+ {
+ User::LeaveIfError(err);
+ }
+ iFname = filenamePtr;
+ ((*iCodDlData)[mediaObjectIndex])->SetDestFilenameL(filenamePtr);
+
+ CleanupStack::PopAndDestroy(filename);
+
+
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpDownload::FindUniqueDestinationFileNameL
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::FindUniqueDestinationFileNameL( TDesC& srcFile, HBufC*& destPath )
+ {
+ HBufC* fileExtention = HBufC::NewLC(KMaxFileName);
+ HBufC* fileName = HBufC::NewLC(KMaxFileName);
+ TPtr fileNamePtr( fileName->Des() );
+
+ fileNamePtr = srcFile;
+ // Retrieve the file extention.
+ TInt dotInd = srcFile.LocateReverse( '.' );
+ if( dotInd != KErrNotFound )
+ // Filename extension found.
+ {
+ fileExtention->Des().Copy( srcFile.Right( srcFile.Length() - dotInd ) );
+ fileNamePtr.Copy( srcFile.Left( dotInd ) );
+ }
+
+ // Retrieve the file name (excluding file extention).
+ TInt lastSlashPos = fileNamePtr.LocateReverse( '\\' );
+ if( lastSlashPos != KErrNotFound )
+ // Filename found.
+ {
+ fileNamePtr.Copy( fileNamePtr.Right( fileNamePtr.Length() - lastSlashPos - 1 ) );
+ }
+
+ // Find a unique file name.
+ ConvertDownloadNameUniqueL( destPath, fileName, fileExtention );
+
+ // Found. Append file name and extention to destination path.
+ destPath->Des().Append( *fileName );
+ destPath->Des().Append( *fileExtention );
+
+ CleanupStack::PopAndDestroy( fileName );
+ CleanupStack::PopAndDestroy( fileExtention );
+ }
+
+
+// ---------------------------------------------------------
+// CHttpDownload::NotifyMediaGalleryL()
+// Notify media gallery about the new file.
+// ---------------------------------------------------------
+//
+void CHttpDownload::NotifyMediaGalleryL( const TDesC& aFileName )
+ {
+
+ LOGGER_ENTERFN( "CHttpDownload::NotifyMediaGalleryL" );
+ CLOG_WRITE_1(" notifying Gallery and DcfReposory about move for: %S",&aFileName);
+ //
+ // Notify Media Gallery about new media file
+ CMGXFileManager* mgFileManager = MGXFileManagerFactory::NewFileManagerL(
+ iClientApp->Engine()->Fs() );
+ CleanupStack::PushL( mgFileManager );
+ if( aFileName.Length() > 0 )
+ {
+ TRAP_IGNORE( mgFileManager->UpdateL( aFileName ) );
+ }
+ else
+ {
+ TRAP_IGNORE( mgFileManager->UpdateL() );
+ }
+ CleanupStack::PopAndDestroy( mgFileManager );
+ //
+ // Notify DCF repository
+ TRAP_IGNORE( UpdateDCFRepositoryL( aFileName ) );
+ }
+// -----------------------------------------------------------------------------
+// CCodSaver::ConvertDownloadNameUniqueL
+// -----------------------------------------------------------------------------
+//
+void CHttpDownload::ConvertDownloadNameUniqueL( HBufC*& filePath,
+ HBufC*& fileName,
+ HBufC*& fileExtn)
+ {
+ TBool bFound( EFalse );
+ TInt index( 0 );
+ HBufC* uniqueName = NULL;
+ HBufC* fullNameTemp = HBufC::NewLC(KMaxFileName);
+ TPtr fullNameTempPtr( fullNameTemp->Des() );
+
+ RFs rFs;
+ User::LeaveIfError( rFs.Connect() );
+ CleanupClosePushL(rFs);
+
+ do
+ {
+ bFound = EFalse;
+ //Generate Unique name.
+ CreateIndexedNameL( uniqueName, *fileName, index );
+
+ //Name in \\system\\temp.
+ fullNameTempPtr.Copy( *filePath );
+ fullNameTempPtr.Append( *uniqueName );
+ fullNameTempPtr.Append( *fileExtn );
+
+ if( BaflUtils::FileExists( rFs , fullNameTempPtr ) )
+ //Check if file name exist in Destination path.
+ {
+ bFound =ETrue;
+ }
+
+ }while( bFound );
+
+ CleanupStack::PopAndDestroy(&rFs);
+ CleanupStack::PopAndDestroy(fullNameTemp);
+
+ // This is the unique name that we were looking for.
+ CleanupStack::PopAndDestroy(fileName);
+ fileName = uniqueName;
+ CleanupStack::PushL(fileName);
+ }
+
+// End of File