/*
* 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: ?Description
*
*/
#include "irdataprovider.h"
#include "irdataproviderobserver.h"
#include "irdebug.h"
#include "irhttpdataprovider.h"
#include "irhttprequestdata.h"
#include "irsettings.h"
// ---------------------------------------------------------------------------
// CIRDataProvider::NewL(MIRDataProviderObserver& aObserver)
// 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(MIRDataProviderObserver& aObserver)
// 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() // destruct - virtual, so no export
{
IRLOG_DEBUG( "CIRDataProvider::~CIRDataProvider() - Entering" );
if (iHttpDataProvider)
{
// Cancel any active transactions
iHttpDataProvider->CancelTransaction();
// Destroy the data provider object
}
delete iHttpDataProvider;
if( iIRSettings )
{
iIRSettings->Close();
}
if (iDataProviderTimer)
{
iDataProviderTimer->Cancel(); // Cancel the timer
}
delete iDataProviderTimer; // Destroy the timer object
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
User::LeaveIfError(iFile.Replace( iFsSession, iXmlFilePath, EFileWrite ));
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();
// 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;
iResponseHeaders = NULL; // prevents the destructor to delete in case something streange happens.
iDataProviderObserver.IRHttpDataReceived( iXmlFilePath,*currentHeaders );
delete currentHeaders;
IRLOG_DEBUG( "CIRDataProvider::HttpEventComplete - Exiting." );
}
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( const TDesC8& aHeaderData )
// 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." );
}
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( const TDesC8& aBodyData )
// 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(TInt aErrCode)
// 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(TInt aResponseCode)
// 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::CIRDataProvider(MIRDataProviderObserver& aObserver):
// iDataProviderObserver(aObserver)
// Default Constructor
// ---------------------------------------------------------------------------
//
void CIRDataProvider::TimerExpired()
{
IRLOG_INFO( "CIRDataProvider::TimerExpired - Entering" );
IRHttpCancelRequest();
HttpTransactionError( KDataProviderTimeout );
IRLOG_INFO( "CIRDataProvider::TimerExpired - Exiting" );
}
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() // second-phase constructor
{
IRLOG_DEBUG( "CIRDataProvider::ConstructL - Entering" );
_LIT( KXmlFile, "iSdsResponse.xml" );
ConstructL(KXmlFile);
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();
iXmlFilePath = iIRSettings->PrivatePath();
iXmlFilePath.Append( aFileName );
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( const TTime& aTime )
// 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." );
}