internetradio2.0/dataprovidersrc/irdataprovider.cpp
changeset 14 896e9dbc5f19
parent 12 608f67c22514
child 15 065198191975
equal deleted inserted replaced
12:608f67c22514 14:896e9dbc5f19
     1 /*
       
     2 * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  ?Description
       
    15 *
       
    16 */
       
    17 
       
    18 #include <ezgzip.h>
       
    19 #include <bautils.h>
       
    20 #include <f32file.h>
       
    21 
       
    22 #include "irdataprovider.h"
       
    23 #include "irdataproviderobserver.h"
       
    24 #include "irdebug.h"
       
    25 #include "irhttpdataprovider.h"
       
    26 #include "irhttprequestdata.h"
       
    27 #include "irsettings.h"
       
    28 
       
    29 _LIT( KGzXmlFile, "iSdsResponse.xml.gz" );
       
    30 _LIT( KXmlFile, "iSdsResponse.xml" );
       
    31 
       
    32 // ---------------------------------------------------------------------------
       
    33 //  CIRDataProvider::NewL(MIRDataProviderObserver& aObserver)
       
    34 //  Creates instance of CIRDataProvider.
       
    35 // ---------------------------------------------------------------------------
       
    36 //
       
    37 EXPORT_C CIRDataProvider *CIRDataProvider::NewL(
       
    38     MIRDataProviderObserver &aObserver )
       
    39     {
       
    40     IRLOG_DEBUG( "CIRDataProvider::NewL - Entering" );
       
    41     CIRDataProvider *self = NewLC( aObserver );
       
    42     CleanupStack::Pop(self);
       
    43     IRLOG_DEBUG( "CIRDataProvider::NewL - Exiting" );
       
    44     return self;
       
    45     }
       
    46 
       
    47 // ---------------------------------------------------------------------------
       
    48 //  CIRDataProvider::NewL(MIRDataProviderObserver& aObserver)
       
    49 //  Creates instance of CIRDataProvider.
       
    50 // ---------------------------------------------------------------------------
       
    51 //
       
    52 EXPORT_C CIRDataProvider *CIRDataProvider::NewL(
       
    53     MIRDataProviderObserver &aObserver, const TDesC &aFileName )
       
    54     {
       
    55     IRLOG_DEBUG( "CIRDataProvider::NewL(..., &aFileName) - Entering" );
       
    56     CIRDataProvider *self = NewLC( aObserver, aFileName );
       
    57     CleanupStack::Pop(self);
       
    58     IRLOG_DEBUG( "CIRDataProvider::NewL(..., &aFileName) - Exiting." );
       
    59     return self;
       
    60     }
       
    61 
       
    62 // ---------------------------------------------------------------------------
       
    63 //  CIRDataProvider::~CIRDataProvider()
       
    64 //  Destructs an instance of CIRDataProvider.
       
    65 // ---------------------------------------------------------------------------
       
    66 //
       
    67 CIRDataProvider::~CIRDataProvider() // destruct - virtual, so no export
       
    68     {
       
    69     IRLOG_DEBUG( "CIRDataProvider::~CIRDataProvider() - Entering" );
       
    70 
       
    71     if (iHttpDataProvider)
       
    72         {
       
    73         // Cancel any active transactions
       
    74         iHttpDataProvider->CancelTransaction();
       
    75         // Destroy the data provider object
       
    76         }
       
    77 
       
    78     delete iHttpDataProvider;
       
    79 
       
    80     if( iIRSettings )
       
    81     	{
       
    82     	iIRSettings->Close();
       
    83 		}
       
    84 
       
    85     if (iDataProviderTimer)
       
    86         {
       
    87      	iDataProviderTimer->Cancel(); // Cancel the timer
       
    88         }
       
    89 
       
    90     delete iDataProviderTimer; // Destroy the timer object
       
    91 	if( iResponseHeaders )
       
    92 		{
       
    93         delete iResponseHeaders;
       
    94 		}
       
    95     iFile.Close();
       
    96     iFsSession.Close(); // Close the file server session
       
    97     IRLOG_DEBUG( "CIRDataProvider::~CIRDataProvider() - Exiting" );
       
    98     }
       
    99 
       
   100 // General functions exported ( These are the API`s exposed )( HTTP )
       
   101 
       
   102 // ---------------------------------------------------------------------------
       
   103 //  CIRDataProvider::IRHttpIssueRequest(TDesC8& aUri)
       
   104 //  Used to issue an Http request
       
   105 // ---------------------------------------------------------------------------
       
   106 //
       
   107 EXPORT_C void CIRDataProvider::IRHttpIssueRequestL(
       
   108      CIRHttpRequestData &aRequestObject )
       
   109     {
       
   110     IRHttpCancelRequest();
       
   111     IRLOG_DEBUG( "CIRDataProvider::IRHttpIssueRequestL - Entering" );
       
   112 	IRRDEBUG2("CIRDATAPROVIDER::IRHTTPISSUEREQUESTL",KNullDesC);
       
   113     CIRHttpResponseData* newResponseHeaders = new ( ELeave ) CIRHttpResponseData;
       
   114     delete iResponseHeaders;
       
   115     iResponseHeaders = newResponseHeaders;
       
   116 
       
   117 
       
   118     // Create or replace the file used to store xml response from iSDS
       
   119     User::LeaveIfError(iFile.Replace( iFsSession, iXmlGzFilePath, EFileWrite ));
       
   120     iHttpDataProvider->CancelTransaction();
       
   121 
       
   122     TInt err = iHttpDataProvider->IssueHttpRequestL( aRequestObject );
       
   123     // Cancel the timer if active
       
   124     iDataProviderTimer->Cancel();
       
   125     // Start the timer for timeout
       
   126     iDataProviderTimer->After( iTimeOut );
       
   127     if ( err == KErrCouldNotConnect )
       
   128         {
       
   129         // If error in IssueHttpRequest then close the open file
       
   130 	    iFile.Close();
       
   131 	    iDataProviderTimer->Cancel();
       
   132 	    iDataProviderObserver.IRHttpGeneralError( err );
       
   133 	    // Cancel any possibly pending transactions
       
   134 	    iHttpDataProvider->CancelTransaction();
       
   135         }
       
   136 
       
   137     IRLOG_DEBUG( "CIRDataProvider::IRHttpIssueRequestL - Exiting." );
       
   138     }
       
   139 
       
   140 
       
   141 // ---------------------------------------------------------------------------
       
   142 //  CIRDataProvider::IRHttpCancelRequest()
       
   143 //  Used to cancel a request
       
   144 // ---------------------------------------------------------------------------
       
   145 //
       
   146 EXPORT_C void CIRDataProvider::IRHttpCancelRequest()
       
   147     {
       
   148     IRLOG_DEBUG( "CIRDataProvider::IRHttpCancelRequest - Entering" );
       
   149     // Cancel the timer if active
       
   150     iDataProviderTimer->Cancel();
       
   151     // Cancel any possibly pending transactions
       
   152     iHttpDataProvider->CancelTransaction();
       
   153     // Close the file handle used to store the xml response
       
   154     iFile.Close();
       
   155     IRLOG_DEBUG( "CIRDataProvider::IRHttpCancelRequest - Exiting." );
       
   156     }
       
   157 
       
   158 
       
   159 // ---------------------------------------------------------------------------
       
   160 //  CIRDataProvider::ReleaseResources()
       
   161 //  Used to release the resources held by the IRHttpDataProvider
       
   162 // ---------------------------------------------------------------------------
       
   163 //
       
   164 EXPORT_C void CIRDataProvider::ReleaseResources()
       
   165 	{
       
   166 	IRLOG_DEBUG( "CIRDataProvider::ReleaseResources - Entering" );
       
   167 	// Release the resources held by the IRHttpDataProvider
       
   168 	iHttpDataProvider->ReleaseResources();
       
   169 	IRLOG_DEBUG( "CIRDataProvider::ReleaseResources - Exiting" );
       
   170 	}
       
   171 
       
   172 
       
   173 //These are the callback functions used by CIRHttpDataProvider to
       
   174 //provide the CIRDataProvider with the data after processing the
       
   175 //HTTP request.
       
   176 
       
   177 // ---------------------------------------------------------------------------
       
   178 //  CIRDataProvider::HttpEventComplete()
       
   179 //  Used to Indicate to the observer that the request event has completed
       
   180 // ---------------------------------------------------------------------------
       
   181 //
       
   182 void CIRDataProvider::HttpEventComplete()
       
   183     {
       
   184     IRLOG_DEBUG( "CIRDataProvider::HttpEventComplete - Entering" );
       
   185     iFile.Close();
       
   186     iDataProviderTimer->Cancel();
       
   187 
       
   188     // unzip the gz file
       
   189     TRAP_IGNORE( UnzipFileL( iXmlFilePath ) );
       
   190     // delete the original gz file
       
   191     BaflUtils::DeleteFile( iFsSession, iXmlGzFilePath );
       
   192     // Need to take a member to a local variable, as the IRHttpDataReceived may initiate
       
   193     // an IRHttpIssueRequestL() call, causing the headers to be replaced with empty ones, and
       
   194     // causing crashes.
       
   195     CIRHttpResponseData* currentHeaders = iResponseHeaders;
       
   196     iResponseHeaders = NULL; // prevents the destructor to delete in case something streange happens.
       
   197     iDataProviderObserver.IRHttpDataReceived( iXmlFilePath,*currentHeaders );
       
   198 
       
   199     delete currentHeaders;
       
   200     IRLOG_DEBUG( "CIRDataProvider::HttpEventComplete - Exiting." );
       
   201     }
       
   202 
       
   203 
       
   204 void CIRDataProvider::ExtractHeaderValue(const TDesC8& aHeaderData,const
       
   205 	TDesC8& aHeaderName,const TDesC8& aDelimeter,TDes8& aHolder) const
       
   206 	{
       
   207 	IRLOG_DEBUG( "CIRDataProvider::ExtractHeaderValue - Entering" );
       
   208 	TInt position = aHeaderData.Find(aHeaderName);
       
   209 	if( position >= 0)
       
   210 		{
       
   211 		TPtrC8 headerValue = aHeaderData.Mid(position);
       
   212 		TInt delimeterPosition = headerValue.Find(aDelimeter);
       
   213 		if( delimeterPosition != KErrNotFound )
       
   214 			{
       
   215 			delimeterPosition++;
       
   216 			TPtrC8 value = headerValue.Mid(delimeterPosition);
       
   217 			aHolder.Copy(value);
       
   218 			aHolder.TrimAll();
       
   219 			}
       
   220 		}
       
   221 	IRLOG_DEBUG( "CIRDataProvider::ExtractHeaderValue - Exiting." );
       
   222 	}
       
   223 
       
   224 
       
   225 // ---------------------------------------------------------------------------
       
   226 //  CIRDataProvider::HttpHeaderReceived( const TDesC8& aHeaderData )
       
   227 //  Used by CIRHttpDataProvider to indicate that an HTTP header is received.
       
   228 // ---------------------------------------------------------------------------
       
   229 //
       
   230 void CIRDataProvider::HttpHeaderReceived( const TDesC8& aHeaderData )
       
   231     {
       
   232     IRLOG_DEBUG( "CIRDataProvider::HttpHeaderReceived - Entering." );
       
   233 	_LIT8(KDelim,":");
       
   234 	_LIT8(KContentType,"Content-Type");
       
   235 	ExtractHeaderValue(aHeaderData,KContentType,KDelim,iResponseHeaders->
       
   236 		iContentType);
       
   237 	_LIT8(KMaxAge,"max-age");
       
   238 	_LIT8(KDelimEqual,"=");
       
   239 	ExtractHeaderValue(aHeaderData,KMaxAge,KDelimEqual,iResponseHeaders->
       
   240 		iMaxAge);
       
   241 	_LIT8(KContentLength,"Content-Length");
       
   242 	ExtractHeaderValue(aHeaderData,KContentLength,KDelim,iResponseHeaders->
       
   243 		iContentLength);
       
   244 	_LIT8(KExpires,"Expires");
       
   245 	ExtractHeaderValue(aHeaderData,KExpires,KDelim,iResponseHeaders->iExpires);
       
   246 	IRLOG_DEBUG( "CIRDataProvider::HttpHeaderReceived - Exiting." );
       
   247     }
       
   248 
       
   249 
       
   250 void CIRDataProvider::HttpDateHeaderReceived(const TDesC8 &aHeader,
       
   251 	const TTime& aTime )
       
   252 	{
       
   253 	IRLOG_DEBUG( "CIRDataProvider::HttpDateHeaderReceived - Entering." );
       
   254 	_LIT8(KDate,"Date");
       
   255 	_LIT8(KLastModified,"Last-Modified");
       
   256 	TInt position = aHeader.Find(KDate);
       
   257 	if( position != KErrNotFound )
       
   258 		{
       
   259 		iResponseHeaders->iDate = aTime;
       
   260 		//find the difference between device time and response time
       
   261 		//and storing the offset
       
   262 		SetOffsetSeconds( aTime );
       
   263 		return ;
       
   264 		}
       
   265 	position = aHeader.Find(KLastModified);
       
   266 	if( position != KErrNotFound )
       
   267 		{
       
   268 		iResponseHeaders->iLastModified = aTime;
       
   269 		}
       
   270 	IRLOG_DEBUG( "CIRDataProvider::HttpDateHeaderReceived - Exiting." );
       
   271 	}
       
   272 
       
   273 
       
   274 
       
   275 // ---------------------------------------------------------------------------
       
   276 //  CIRDataProvider::HttpBodyReceived( const TDesC8& aBodyData )
       
   277 //  Used by CIRHttpDataProvider to indicate that an HTTP response body
       
   278 //  is received.
       
   279 // ---------------------------------------------------------------------------
       
   280 //
       
   281 void CIRDataProvider::HttpBodyReceived( const TDesC8 &aBodyData )
       
   282     {
       
   283     IRLOG_DEBUG( "CIRDataProvider::HttpBodyReceived - Entering" );
       
   284     TInt FileWritePos = 0;
       
   285     iFile.Seek( ESeekEnd, FileWritePos );
       
   286     iFile.Write( FileWritePos, aBodyData );
       
   287     IRLOG_DEBUG( "CIRDataProvider::HttpBodyReceived - Exiting." );
       
   288     }
       
   289 
       
   290 // ---------------------------------------------------------------------------
       
   291 //  CIRDataProvider::HttpTransactionError(TInt aErrCode)
       
   292 //  Used by CIRHttpDataProvider to indicate that a HTTP Transaction error
       
   293 //  has occured.
       
   294 // ---------------------------------------------------------------------------
       
   295 //
       
   296 void CIRDataProvider::HttpTransactionError( TInt aErrCode )
       
   297     {
       
   298     IRLOG_DEBUG( "CIRDataProvider::HttpTransactionError - Entering" );
       
   299     iFile.Close();
       
   300     iDataProviderTimer->Cancel();
       
   301     iDataProviderObserver.IRHttpGeneralError( aErrCode );
       
   302     // Cancel any possibly pending transactions
       
   303     iHttpDataProvider->CancelTransaction();
       
   304     IRLOG_DEBUG( "CIRDataProvider::HttpTransactionError - Exiting." );
       
   305     }
       
   306 
       
   307 // ---------------------------------------------------------------------------
       
   308 //  CIRDataProvider::HttpResponseCodeRecieved(TInt aResponseCode)
       
   309 //  Used by CIRHttpDataProvider to indicate to the iSDS Client that a
       
   310 //  304 Not Changed response received
       
   311 //  Note: Implemented in version 0.2
       
   312 // ---------------------------------------------------------------------------
       
   313 //
       
   314 void CIRDataProvider::HttpResponseCodeRecieved( TInt aResponseCode )
       
   315     {
       
   316     IRLOG_DEBUG( "CIRDataProvider::HttpResponseCodeRecieved - Entering" );
       
   317     iDataProviderObserver.IRHttpResponseCodeReceived( aResponseCode, *iResponseHeaders );
       
   318     IRLOG_DEBUG( "CIRDataProvider::HttpResponseCodeRecieved- Exiting" );
       
   319     }
       
   320 
       
   321 // constructor support
       
   322 // don't export these, because used only by functions in this DLL
       
   323 // ---------------------------------------------------------------------------
       
   324 //  CIRDataProvider::CIRDataProvider(MIRDataProviderObserver& aObserver):
       
   325 //  iDataProviderObserver(aObserver)
       
   326 //  Default Constructor
       
   327 // ---------------------------------------------------------------------------
       
   328 //
       
   329 void CIRDataProvider::TimerExpired()
       
   330     {
       
   331     IRLOG_INFO( "CIRDataProvider::TimerExpired - Entering" );
       
   332     IRHttpCancelRequest();
       
   333     HttpTransactionError( KDataProviderTimeout );
       
   334     IRLOG_INFO( "CIRDataProvider::TimerExpired - Exiting" );
       
   335     }
       
   336 
       
   337 
       
   338 
       
   339 CIRDataProvider::CIRDataProvider( MIRDataProviderObserver &aObserver ):
       
   340     iDataProviderObserver( aObserver ) // first-phase C++ constructor
       
   341     {
       
   342     IRLOG_INFO( "CIRDataProvider::CIRDataProvider" );
       
   343     // Definition not required
       
   344     }
       
   345 
       
   346 // ---------------------------------------------------------------------------
       
   347 //  void CIRDataProvider::ConstructL()
       
   348 //  2nd Phase construction
       
   349 // ---------------------------------------------------------------------------
       
   350 //
       
   351 void CIRDataProvider::ConstructL() // second-phase constructor
       
   352     {
       
   353     IRLOG_DEBUG( "CIRDataProvider::ConstructL - Entering" );
       
   354     ConstructL( KGzXmlFile );
       
   355     iHttpDataProvider->iSetNonUAProfUserAgent = EFalse;
       
   356     IRLOG_DEBUG( "CIRDataProvider::ConstructL - Exiting" );
       
   357     }
       
   358 
       
   359 // ---------------------------------------------------------------------------
       
   360 //  void CIRDataProvider::ConstructL(TDesC& aFilePath)
       
   361 //  2nd Phase construction
       
   362 // ---------------------------------------------------------------------------
       
   363 //
       
   364 void CIRDataProvider::ConstructL( const TDesC &aFileName )
       
   365     {
       
   366     IRLOG_DEBUG( "CIRDataProvider::ConstructL(const TDesC &aFileName) - Entering" );
       
   367     iHttpDataProvider = CIRHttpDataProvider::NewL( *this );
       
   368     iDataProviderTimer = CIRDataProviderTimer::NewL( EPriorityHigh,  *this );
       
   369     User::LeaveIfError(iFsSession.Connect());
       
   370     iIRSettings = CIRSettings::OpenL();
       
   371     iXmlGzFilePath = iIRSettings->PrivatePath();
       
   372     iXmlFilePath = iXmlGzFilePath;
       
   373     iXmlGzFilePath.Append( aFileName );
       
   374     iXmlFilePath.Append( KXmlFile );
       
   375     iTimeOut = iIRSettings->GetTimeOut();
       
   376     iHttpDataProvider->iSetNonUAProfUserAgent = ETrue;
       
   377     IRLOG_DEBUG( "CIRDataProvider::ConstructL(const TDesC &aFileName) - Exiting." );
       
   378     }
       
   379 
       
   380 
       
   381 
       
   382 // ---------------------------------------------------------------------------
       
   383 //  CIRDataProvider::NewLC(MIRDataProviderObserver& aObserver)
       
   384 //  Creates instance of CIRDataProvider.
       
   385 // ---------------------------------------------------------------------------
       
   386 //
       
   387 CIRDataProvider *CIRDataProvider::NewLC( MIRDataProviderObserver &aObserver )
       
   388     {
       
   389     IRLOG_DEBUG( "CIRDataProvider::NewLC - Entering." );
       
   390     CIRDataProvider *self = new( ELeave )CIRDataProvider( aObserver );
       
   391     CleanupStack::PushL( self );
       
   392     self->ConstructL();
       
   393     IRLOG_DEBUG( "CIRDataProvider::NewLC - Exiting." );
       
   394     return self;
       
   395     }
       
   396 
       
   397 // ---------------------------------------------------------------------------
       
   398 //  CIRDataProvider::NewLC(MIRDataProviderObserver& aObserver)
       
   399 //  Creates instance of CIRDataProvider.
       
   400 // ---------------------------------------------------------------------------
       
   401 //
       
   402 CIRDataProvider *CIRDataProvider::NewLC( MIRDataProviderObserver &aObserver,
       
   403     const TDesC &aFileName )
       
   404     {
       
   405     IRLOG_DEBUG( "CIRDataProvider::NewLC - Entering." );
       
   406     CIRDataProvider *self = new( ELeave )CIRDataProvider( aObserver );
       
   407     CleanupStack::PushL( self );
       
   408     self->ConstructL( aFileName );
       
   409     IRLOG_DEBUG( "CIRDataProvider::NewLC - Exiting." );
       
   410     return self;
       
   411     }
       
   412 
       
   413 EXPORT_C CIRHttpDataProvider* CIRDataProvider::GetHttpDataProvider()
       
   414 {
       
   415 IRLOG_DEBUG( "CIRDataProvider::GetHttpDataProvider" );
       
   416 	return iHttpDataProvider;
       
   417 }
       
   418 
       
   419 // ---------------------------------------------------------------------------
       
   420 //  CIRDataProvider::SetOffsetSeconds( const TTime& aTime )
       
   421 //  Stores the offset between device time and response header in settings
       
   422 // ---------------------------------------------------------------------------
       
   423 //
       
   424 void CIRDataProvider::SetOffsetSeconds( const TTime& aTime )
       
   425 	{
       
   426 	IRLOG_DEBUG( "CIRDataProvider::SetOffsetSeconds - Entering" );
       
   427 	TTime currenttime;
       
   428 	//calculates the current time
       
   429 	currenttime.UniversalTime();
       
   430 	//finds offset from isds response
       
   431 	TTimeIntervalSeconds offsetseconds;
       
   432 	//Find offset from isds response
       
   433 	TInt err = currenttime.SecondsFrom(aTime,offsetseconds);
       
   434 	if( err )
       
   435 		{
       
   436 		//if error offsetseconds is set to zero
       
   437 		offsetseconds = 0;
       
   438 		}
       
   439 	//storing the offset value in setting
       
   440 	TRAP_IGNORE( iIRSettings->SetTimeCorrectionL(offsetseconds.Int()) )
       
   441 	IRLOG_DEBUG( "CIRDataProvider::SetOffsetSeconds - Exiting." );
       
   442 	}
       
   443 
       
   444 // ---------------------------------------------------------------------------
       
   445 //  CIRDataProvider::UnzipFileL
       
   446 // ---------------------------------------------------------------------------
       
   447 //
       
   448 void CIRDataProvider::UnzipFileL( const TDesC& aOutputFile )
       
   449     {
       
   450     IRLOG_DEBUG( "CIRDataProvider::UnzipFileL - Enter." );
       
   451     RFile outputFile;
       
   452     CleanupClosePushL( outputFile );
       
   453     User::LeaveIfError( outputFile.Replace( iFsSession, aOutputFile, 
       
   454                         EFileStream | EFileWrite | EFileShareExclusive ) );
       
   455     CEZGZipToFile* gZip = 
       
   456         CEZGZipToFile::NewLC( iFsSession, iXmlGzFilePath, outputFile );
       
   457 
       
   458     while ( gZip->InflateL() )
       
   459         {
       
   460         // unzip the gz file, quit when finish
       
   461         }
       
   462     CleanupStack::PopAndDestroy( gZip );
       
   463     CleanupStack::PopAndDestroy( &outputFile );
       
   464     IRLOG_DEBUG( "CIRDataProvider::UnzipFileL - Exit." );
       
   465     }