--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/internetradio2.0/irdataprovider/src/irdataprovider.cpp Wed Aug 18 09:40:26 2010 +0300
@@ -0,0 +1,495 @@
+/*
+* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+#ifdef REQUEST_ZIP_RESPONSE
+#include <ezgzip.h>
+#include <bautils.h>
+#include <f32file.h>
+#endif
+
+#include "irdataprovider.h"
+#include "irdataproviderobserver.h"
+#include "irdebug.h"
+#include "irhttpdataprovider.h"
+#include "irhttprequestdata.h"
+#include "irsettings.h"
+
+#ifdef REQUEST_ZIP_RESPONSE
+_LIT( KGzXmlFile, "iSdsResponse.xml.gz" );
+#endif
+_LIT( KXmlFile, "iSdsResponse.xml" );
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::NewL()
+// Creates instance of CIRDataProvider.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CIRDataProvider *CIRDataProvider::NewL(
+ MIRDataProviderObserver &aObserver )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::NewL - Entering" );
+ CIRDataProvider *self = NewLC( aObserver );
+ CleanupStack::Pop(self);
+ IRLOG_DEBUG( "CIRDataProvider::NewL - Exiting" );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::NewL()
+// Creates instance of CIRDataProvider.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CIRDataProvider *CIRDataProvider::NewL(
+ MIRDataProviderObserver &aObserver, const TDesC &aFileName )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::NewL(..., &aFileName) - Entering" );
+ CIRDataProvider *self = NewLC( aObserver, aFileName );
+ CleanupStack::Pop(self);
+ IRLOG_DEBUG( "CIRDataProvider::NewL(..., &aFileName) - Exiting." );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::~CIRDataProvider()
+// Destructs an instance of CIRDataProvider.
+// ---------------------------------------------------------------------------
+//
+CIRDataProvider::~CIRDataProvider()
+ {
+ IRLOG_DEBUG( "CIRDataProvider::~CIRDataProvider() - Entering" );
+
+ if ( iHttpDataProvider )
+ {
+ iHttpDataProvider->CancelTransaction();
+ delete iHttpDataProvider;
+ }
+
+ if ( iIRSettings )
+ {
+ iIRSettings->Close();
+ }
+
+ if ( iDataProviderTimer )
+ {
+ iDataProviderTimer->Cancel();
+ delete iDataProviderTimer;
+ }
+
+ if ( iResponseHeaders )
+ {
+ delete iResponseHeaders;
+ }
+
+ iFile.Close();
+ iFsSession.Close(); // Close the file server session
+ IRLOG_DEBUG( "CIRDataProvider::~CIRDataProvider() - Exiting" );
+ }
+
+// General functions exported ( These are the API`s exposed )( HTTP )
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::IRHttpIssueRequest(TDesC8& aUri)
+// Used to issue an Http request
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIRDataProvider::IRHttpIssueRequestL(
+ CIRHttpRequestData &aRequestObject )
+ {
+ IRHttpCancelRequest();
+ IRLOG_DEBUG( "CIRDataProvider::IRHttpIssueRequestL - Entering" );
+ IRRDEBUG2("CIRDATAPROVIDER::IRHTTPISSUEREQUESTL",KNullDesC);
+ CIRHttpResponseData* newResponseHeaders = new ( ELeave ) CIRHttpResponseData;
+ delete iResponseHeaders;
+ iResponseHeaders = newResponseHeaders;
+
+ // Create or replace the file used to store xml response from iSDS
+#ifdef REQUEST_ZIP_RESPONSE
+ User::LeaveIfError( iFile.Replace( iFsSession, iXmlGzFilePath, EFileWrite ) );
+#else
+ User::LeaveIfError( iFile.Replace( iFsSession, iXmlFilePath, EFileWrite ) );
+#endif
+
+ iHttpDataProvider->CancelTransaction();
+
+ TInt err = iHttpDataProvider->IssueHttpRequestL( aRequestObject );
+ // Cancel the timer if active
+ iDataProviderTimer->Cancel();
+ // Start the timer for timeout
+ iDataProviderTimer->After( iTimeOut );
+ if ( err == KErrCouldNotConnect )
+ {
+ // If error in IssueHttpRequest then close the open file
+ iFile.Close();
+ iDataProviderTimer->Cancel();
+ iDataProviderObserver.IRHttpGeneralError( err );
+ // Cancel any possibly pending transactions
+ iHttpDataProvider->CancelTransaction();
+ }
+
+ IRLOG_DEBUG( "CIRDataProvider::IRHttpIssueRequestL - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::IRHttpCancelRequest()
+// Used to cancel a request
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIRDataProvider::IRHttpCancelRequest()
+ {
+ IRLOG_DEBUG( "CIRDataProvider::IRHttpCancelRequest - Entering" );
+ // Cancel the timer if active
+ iDataProviderTimer->Cancel();
+ // Cancel any possibly pending transactions
+ iHttpDataProvider->CancelTransaction();
+ // Close the file handle used to store the xml response
+ iFile.Close();
+ IRLOG_DEBUG( "CIRDataProvider::IRHttpCancelRequest - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::ReleaseResources()
+// Used to release the resources held by the IRHttpDataProvider
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIRDataProvider::ReleaseResources()
+ {
+ IRLOG_DEBUG( "CIRDataProvider::ReleaseResources - Entering" );
+ // Release the resources held by the IRHttpDataProvider
+ iHttpDataProvider->ReleaseResources();
+ IRLOG_DEBUG( "CIRDataProvider::ReleaseResources - Exiting" );
+ }
+
+
+//These are the callback functions used by CIRHttpDataProvider to
+//provide the CIRDataProvider with the data after processing the
+//HTTP request.
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::HttpEventComplete()
+// Used to Indicate to the observer that the request event has completed
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::HttpEventComplete()
+ {
+ IRLOG_DEBUG( "CIRDataProvider::HttpEventComplete - Entering" );
+ iFile.Close();
+ iDataProviderTimer->Cancel();
+
+#ifdef REQUEST_ZIP_RESPONSE
+ // unzip the gz file
+ TRAP_IGNORE( UnzipFileL( iXmlFilePath ) );
+ // delete the original gz file
+ BaflUtils::DeleteFile( iFsSession, iXmlGzFilePath );
+#endif
+
+ // Need to take a member to a local variable, as the IRHttpDataReceived
+ // may initiate an IRHttpIssueRequestL() call, causing the headers
+ // to be replaced with empty ones, and causing crashes.
+ CIRHttpResponseData* currentHeaders = iResponseHeaders;
+ // prevents the destructor to delete in case something streange happens.
+ iResponseHeaders = NULL;
+ iDataProviderObserver.IRHttpDataReceived( iXmlFilePath, *currentHeaders );
+
+ delete currentHeaders;
+ IRLOG_DEBUG( "CIRDataProvider::HttpEventComplete - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::ExtractHeaderValue()
+//
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::ExtractHeaderValue( const TDesC8& aHeaderData,
+ const TDesC8& aHeaderName,
+ const TDesC8& aDelimeter,
+ TDes8& aHolder ) const
+ {
+ IRLOG_DEBUG( "CIRDataProvider::ExtractHeaderValue - Entering" );
+ TInt position = aHeaderData.Find( aHeaderName );
+ if ( position >= 0 )
+ {
+ TPtrC8 headerValue = aHeaderData.Mid( position );
+ TInt delimeterPosition = headerValue.Find( aDelimeter );
+ if ( delimeterPosition != KErrNotFound )
+ {
+ delimeterPosition++;
+ TPtrC8 value = headerValue.Mid( delimeterPosition );
+ aHolder.Copy( value );
+ aHolder.TrimAll();
+ }
+ }
+ IRLOG_DEBUG( "CIRDataProvider::ExtractHeaderValue - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::HttpHeaderReceived()
+// Used by CIRHttpDataProvider to indicate that an HTTP header is received.
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::HttpHeaderReceived( const TDesC8& aHeaderData )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::HttpHeaderReceived - Entering." );
+ _LIT8(KDelim,":");
+ _LIT8(KContentType,"Content-Type");
+ ExtractHeaderValue( aHeaderData, KContentType, KDelim,
+ iResponseHeaders-> iContentType );
+ _LIT8(KMaxAge,"max-age");
+ _LIT8(KDelimEqual,"=");
+ ExtractHeaderValue( aHeaderData, KMaxAge, KDelimEqual,
+ iResponseHeaders-> iMaxAge );
+ _LIT8(KContentLength,"Content-Length");
+ ExtractHeaderValue( aHeaderData, KContentLength, KDelim,
+ iResponseHeaders-> iContentLength );
+ _LIT8(KExpires,"Expires");
+ ExtractHeaderValue( aHeaderData, KExpires, KDelim,
+ iResponseHeaders->iExpires );
+ IRLOG_DEBUG( "CIRDataProvider::HttpHeaderReceived - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::HttpDateHeaderReceived()
+// Used by CIRHttpDataProvider to indicate that an HTTP header is received.
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::HttpDateHeaderReceived( const TDesC8 &aHeader,
+ const TTime& aTime )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::HttpDateHeaderReceived - Entering." );
+ _LIT8(KDate,"Date");
+ _LIT8(KLastModified,"Last-Modified");
+ TInt position = aHeader.Find( KDate );
+ if ( position != KErrNotFound )
+ {
+ iResponseHeaders->iDate = aTime;
+ //find the difference between device time and response time
+ //and storing the offset
+ SetOffsetSeconds( aTime );
+ return;
+ }
+ position = aHeader.Find( KLastModified );
+ if ( position != KErrNotFound )
+ {
+ iResponseHeaders->iLastModified = aTime;
+ }
+ IRLOG_DEBUG( "CIRDataProvider::HttpDateHeaderReceived - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::HttpBodyReceived()
+// Used by CIRHttpDataProvider to indicate that an HTTP response body
+// is received.
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::HttpBodyReceived( const TDesC8 &aBodyData )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::HttpBodyReceived - Entering" );
+ TInt FileWritePos = 0;
+ iFile.Seek( ESeekEnd, FileWritePos );
+ iFile.Write( FileWritePos, aBodyData );
+ IRLOG_DEBUG( "CIRDataProvider::HttpBodyReceived - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::HttpTransactionError()
+// Used by CIRHttpDataProvider to indicate that a HTTP Transaction error
+// has occured.
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::HttpTransactionError( TInt aErrCode )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::HttpTransactionError - Entering" );
+ iFile.Close();
+ iDataProviderTimer->Cancel();
+ iDataProviderObserver.IRHttpGeneralError( aErrCode );
+ // Cancel any possibly pending transactions
+ iHttpDataProvider->CancelTransaction();
+ IRLOG_DEBUG( "CIRDataProvider::HttpTransactionError - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::HttpResponseCodeRecieved()
+// Used by CIRHttpDataProvider to indicate to the iSDS Client that a
+// 304 Not Changed response received
+// Note: Implemented in version 0.2
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::HttpResponseCodeRecieved( TInt aResponseCode )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::HttpResponseCodeRecieved - Entering" );
+ iDataProviderObserver.IRHttpResponseCodeReceived( aResponseCode, *iResponseHeaders );
+ IRLOG_DEBUG( "CIRDataProvider::HttpResponseCodeRecieved- Exiting" );
+ }
+
+// constructor support
+// don't export these, because used only by functions in this DLL
+// ---------------------------------------------------------------------------
+// CIRDataProvider::TimerExpired()
+// Called to indicate expiry of timer
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::TimerExpired()
+ {
+ IRLOG_INFO( "CIRDataProvider::TimerExpired - Entering" );
+ IRHttpCancelRequest();
+ HttpTransactionError( KDataProviderTimeout );
+ IRLOG_INFO( "CIRDataProvider::TimerExpired - Exiting" );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::CIRDataProvider()
+// Default Constructor
+// ---------------------------------------------------------------------------
+//
+CIRDataProvider::CIRDataProvider( MIRDataProviderObserver &aObserver ):
+ iDataProviderObserver( aObserver ) // first-phase C++ constructor
+ {
+ IRLOG_INFO( "CIRDataProvider::CIRDataProvider" );
+ // Definition not required
+ }
+
+// ---------------------------------------------------------------------------
+// void CIRDataProvider::ConstructL()
+// 2nd Phase construction
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::ConstructL()
+ {
+ IRLOG_DEBUG( "CIRDataProvider::ConstructL - Entering" );
+#ifdef REQUEST_ZIP_RESPONSE
+ ConstructL( KGzXmlFile );
+#else
+ ConstructL(KXmlFile);
+#endif
+
+ iHttpDataProvider->iSetNonUAProfUserAgent = EFalse;
+ IRLOG_DEBUG( "CIRDataProvider::ConstructL - Exiting" );
+ }
+
+// ---------------------------------------------------------------------------
+// void CIRDataProvider::ConstructL(TDesC& aFilePath)
+// 2nd Phase construction
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::ConstructL( const TDesC &aFileName )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::ConstructL(const TDesC &aFileName) - Entering" );
+ iHttpDataProvider = CIRHttpDataProvider::NewL( *this );
+ iDataProviderTimer = CIRDataProviderTimer::NewL( EPriorityHigh, *this );
+ User::LeaveIfError( iFsSession.Connect() );
+ iIRSettings = CIRSettings::OpenL();
+#ifdef REQUEST_ZIP_RESPONSE
+ iXmlGzFilePath = iIRSettings->PrivatePath();
+ iXmlFilePath = iXmlGzFilePath;
+ iXmlGzFilePath.Append( aFileName );
+ iXmlFilePath.Append( KXmlFile );
+#else
+ iXmlFilePath = iIRSettings->PrivatePath();
+ iXmlFilePath.Append( aFileName );
+#endif
+
+ iTimeOut = iIRSettings->GetTimeOut();
+ iHttpDataProvider->iSetNonUAProfUserAgent = ETrue;
+ IRLOG_DEBUG( "CIRDataProvider::ConstructL(const TDesC &aFileName) - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::NewLC(MIRDataProviderObserver& aObserver)
+// Creates instance of CIRDataProvider.
+// ---------------------------------------------------------------------------
+//
+CIRDataProvider *CIRDataProvider::NewLC( MIRDataProviderObserver &aObserver )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::NewLC - Entering." );
+ CIRDataProvider *self = new( ELeave )CIRDataProvider( aObserver );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ IRLOG_DEBUG( "CIRDataProvider::NewLC - Exiting." );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::NewLC(MIRDataProviderObserver& aObserver)
+// Creates instance of CIRDataProvider.
+// ---------------------------------------------------------------------------
+//
+CIRDataProvider *CIRDataProvider::NewLC( MIRDataProviderObserver &aObserver,
+ const TDesC &aFileName )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::NewLC - Entering." );
+ CIRDataProvider *self = new( ELeave )CIRDataProvider( aObserver );
+ CleanupStack::PushL( self );
+ self->ConstructL( aFileName );
+ IRLOG_DEBUG( "CIRDataProvider::NewLC - Exiting." );
+ return self;
+ }
+
+EXPORT_C CIRHttpDataProvider* CIRDataProvider::GetHttpDataProvider()
+{
+IRLOG_DEBUG( "CIRDataProvider::GetHttpDataProvider" );
+ return iHttpDataProvider;
+}
+
+// ---------------------------------------------------------------------------
+// CIRDataProvider::SetOffsetSeconds()
+// Stores the offset between device time and response header in settings
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::SetOffsetSeconds( const TTime& aTime )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::SetOffsetSeconds - Entering" );
+ TTime currenttime;
+ //calculates the current time
+ currenttime.UniversalTime();
+ //finds offset from isds response
+ TTimeIntervalSeconds offsetseconds;
+ //Find offset from isds response
+ TInt err = currenttime.SecondsFrom( aTime, offsetseconds );
+ if ( err )
+ {
+ //if error offsetseconds is set to zero
+ offsetseconds = 0;
+ }
+ //storing the offset value in setting
+ TRAP_IGNORE( iIRSettings->SetTimeCorrectionL(offsetseconds.Int()) )
+ IRLOG_DEBUG( "CIRDataProvider::SetOffsetSeconds - Exiting." );
+ }
+
+#ifdef REQUEST_ZIP_RESPONSE
+// ---------------------------------------------------------------------------
+// CIRDataProvider::UnzipFileL
+// ---------------------------------------------------------------------------
+//
+void CIRDataProvider::UnzipFileL( const TDesC& aOutputFile )
+ {
+ IRLOG_DEBUG( "CIRDataProvider::UnzipFileL - Enter." );
+ RFile outputFile;
+ CleanupClosePushL( outputFile );
+ User::LeaveIfError( outputFile.Replace( iFsSession, aOutputFile,
+ EFileStream | EFileWrite | EFileShareExclusive ) );
+ CEZGZipToFile* gZip =
+ CEZGZipToFile::NewLC( iFsSession, iXmlGzFilePath, outputFile );
+
+ while ( gZip->InflateL() )
+ {
+ // unzip the gz file, quit when finish
+ }
+ CleanupStack::PopAndDestroy( gZip );
+ CleanupStack::PopAndDestroy( &outputFile );
+ IRLOG_DEBUG( "CIRDataProvider::UnzipFileL - Exit." );
+ }
+#endif
+
+// End of file