diff -r 608f67c22514 -r 896e9dbc5f19 internetradio2.0/irdataprovider/src/irdataprovider.cpp --- /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 +#include +#include +#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