--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmplugins/drmudtmodule/src/DrmUdtHandler.cpp Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,1228 @@
+/*
+* Copyright (c) 2005 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: Implementation of the User Data Transfer module
+*
+*/
+
+
+// INCLUDE FILES
+#include "DrmUdtHandler.h"
+#include "DrmUdtConn.h"
+#include "RoapStorageClient.h"
+#include "DrmRightsClient.h"
+#include "DrmUdtObserver.h"
+
+#include <hash.h>
+#include <stringpool.h>
+#include <http/thttphdrval.h>
+#include <etelmm.h>
+#include <mmtsy_names.h>
+
+#ifdef _DEBUG
+#define LOGGING
+#endif
+
+#define LOGGING
+
+#ifdef LOGGING
+_LIT(KLogDir, "DRM");
+_LIT(KLogName, "UDT.log");
+#include "flogger.h"
+#define LOG(string) \
+ RFileLogger::Write(KLogDir, KLogName, \
+ EFileLoggingModeAppend, string);
+#define LOGINT(string, val) \
+ RFileLogger::WriteFormat(KLogDir, KLogName, \
+ EFileLoggingModeAppend, string, val);
+#define LOGHEX(buffer) \
+ RFileLogger::HexDump(KLogDir, KLogName, \
+ EFileLoggingModeAppend, _S(""), _S(""), \
+ buffer.Ptr(), buffer.Length());
+#else
+#define LOG
+#define LOGHEX
+#endif
+
+using namespace Roap;
+
+// ================= CONSTANTS ======================
+
+// The time out value in HTTP, 30 sec
+LOCAL_D const TInt KUdtTimeoutValue = 30000000;
+
+LOCAL_D const TInt KMaxSerNumLength = 64;
+LOCAL_D const TInt KRdbKeyLength = 256;
+LOCAL_D const TInt KVersionSize = 1;
+LOCAL_D const TInt KMessageIdSize = 1;
+LOCAL_D const TInt KLengthSize = 4;
+LOCAL_D const TInt KSignatureLength = 128;
+
+LOCAL_D const TInt KVersion = 0;
+
+LOCAL_D const TInt KPadding255 = 1;
+
+_LIT8( KUdtContentType, "application/binary" );
+
+// UDT message identifiers
+LOCAL_D const TUint8 KUdtRequestId = 0;
+LOCAL_D const TUint8 KUdtResponseId = 1;
+LOCAL_D const TUint8 KStatusResponseId = 3;
+LOCAL_D const TUint8 KErrorResponseId = 4;
+LOCAL_D const TUint8 KServerErrorValue = 0;
+LOCAL_D const TUint8 KClientErrorValue = 1;
+
+
+LOCAL_D const TInt KUdtResponseSize = 129;
+
+NONSHARABLE_STRUCT( TUnloadModule )
+ {
+ RTelServer* iServer;
+ const TDesC* iName;
+ };
+
+// ================= LOCAL FUNCTIONS =========================
+
+LOCAL_C void WriteIntToBlock( TInt aValue, TDes8& aBlock, TInt aOffset )
+ {
+ aBlock.SetLength(4);
+ aBlock[aOffset] = (aValue & 0xff000000) >> 24;
+ aBlock[aOffset + 1] = (aValue & 0x00ff0000) >> 16;
+ aBlock[aOffset + 2] = (aValue & 0x0000ff00) >> 8;
+ aBlock[aOffset + 3] = (aValue & 0x000000ff);
+ }
+
+template<class S>
+void PointerArrayResetDestroyAndClose(TAny* aPtr)
+ {
+ (reinterpret_cast<RPointerArray<S>*>(aPtr))->ResetAndDestroy();
+ (reinterpret_cast<RPointerArray<S>*>(aPtr))->Close();
+ }
+
+LOCAL_C void DoUnloadPhoneModule( TAny* aAny )
+ {
+ __ASSERT_DEBUG( aAny, User::Invariant() );
+ TUnloadModule* module = ( TUnloadModule* ) aAny;
+ module->iServer->UnloadPhoneModule( *( module->iName ) );
+ }
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::NewL()
+// ---------------------------------------------------------
+//
+EXPORT_C CDrmUdtHandler* CDrmUdtHandler::NewL( )
+ {
+ LOG( _L("CDrmUdtHandler:NewL:") );
+ CDrmUdtHandler* handler = new( ELeave ) CDrmUdtHandler();
+ CleanupStack::PushL( handler );
+ handler->ConstructL();
+ CleanupStack::Pop( handler );
+ return handler;
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::~CDrmUdtModule()
+// ---------------------------------------------------------
+//
+CDrmUdtHandler::~CDrmUdtHandler()
+ {
+ LOG( _L("CDrmUdtHandler::~CDrmUdtHandler") );
+ Cancel();
+ iSession.Close();
+ delete iConnection;
+ delete iUri;
+ delete iTimeout;
+ delete iOneTimePassword;
+ delete iUdtRequest;
+ delete iUdtResponse;
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::ConstructL()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::ConstructL()
+ {
+ LOG( _L("CDrmUdtHandler::ConstructL") );
+ iConnection = CDrmUdtConn::NewL();
+ iTimeout = CPeriodic::NewL( CActive::EPriorityUserInput );
+ iRequestType = EUdtRequest;
+ iUdtError = EUdtOk;
+ iStateInfo.iState = TUdtStateInfo::EUdtNotStarted;
+ iStateInfo.iProgress = 0;
+ iStateInfo.iError = EUdtOk;
+ }
+
+// -----------------------------------------------------------------------------
+// CDrmUdtHandler::DoUserDataTransferL()
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CDrmUdtHandler::DoUserDataTransferL( const TDesC8& aOneTimePassword,
+ const TDesC8& aServiceUrl,
+ MDrmUdtObserver* aObserver,
+ TRequestStatus& aStatus )
+ {
+ LOG( _L("CDrmUdtHandler::DoUserDataTransferL") );
+ __ASSERT_ALWAYS( iState == EInit, User::Invariant() );
+
+ /*
+ 1. fetch original RDB data from the rights client (serial number and key)
+ 2. create UDT package with the original RDB data, the one time password,
+ our serial number and our certificate
+ 3. open a connection to the service URL
+ 4. do a POST to the service URL, sending our UDT package
+ 5. receive the anwser with the re-encrypted RDB key
+ 6. tell the rights client to do a restore, using the re-encrypted RDB key
+ 7. do a POST to the service URL, sendind a success or error notification
+ */
+
+ iOneTimePassword = aOneTimePassword.AllocLC();
+ iUri = aServiceUrl.AllocL();
+ iObserver = aObserver;
+
+ LOG( _L8("Password: ") );
+ LOG( aOneTimePassword );
+ LOG( _L8("URL: ") );
+ LOG( aServiceUrl );
+
+ iParentStatus = &aStatus;
+ *iParentStatus = KRequestPending;
+ iState = EStart;
+ TRequestStatus* ownStatus = &iStatus;
+ *ownStatus = KRequestPending;
+ iRequestType = EUdtRequest;
+
+ SetActive();
+ User::RequestComplete( ownStatus, KErrNone );
+ CleanupStack::Pop(); // iOneTimePassword
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::SetPreferredIap()
+// ---------------------------------------------------------
+EXPORT_C void CDrmUdtHandler::SetPreferredIap( TUint32 aPreferredIap )
+ {
+ LOG( _L("CDrmUdtHandler::SetPreferredIap") );
+ iPreferredIap = aPreferredIap;
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::DoCancel()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::DoCancel()
+ {
+ LOG( _L("CDrmUdtHandler::DoCancel") );
+ switch ( iState )
+ {
+ case EStart:
+ case EConnect:
+ {
+ iConnection->Cancel();
+ break;
+ }
+ case EResponseReceived:
+ {
+ iTransaction.Close();
+ SelfComplete( iError );
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ iError = KErrCancel;
+ Complete();
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::RunL()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::RunL()
+ {
+ LOG( _L("CDrmUdtHandler::RunL") );
+ User::LeaveIfError( iStatus.Int() );
+
+ switch ( iState )
+ {
+ case EStart:
+ {
+ ConnectL();
+ break;
+ }
+ case EConnect:
+ {
+ CreateSessionL();
+ break;
+ }
+ case ESendMessage:
+ {
+ SendUdtMessageL();
+ break;
+ }
+ case EResponseReceived:
+ {
+ ResponseReceivedL();
+ break;
+ }
+ case EComplete:
+ {
+ iState = EInit;
+ Complete();
+ break;
+ }
+ case EInit:
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::RunError()
+// ---------------------------------------------------------
+//
+TInt CDrmUdtHandler::RunError( TInt aError )
+ {
+ LOG( _L("CDrmUdtHandler::RunError") );
+ iError = aError;
+ iState = EInit;
+ Complete();
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::ConnectL()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::ConnectL()
+ {
+ LOG( _L("CDrmUdtHandler::ConnectL") );
+ __ASSERT_ALWAYS( iState == EStart, User::Invariant() );
+
+ iConnection->ConnectL( iPreferredIap, iObserver, &iStatus );
+ iState = EConnect;
+ iError = EUdtOk;
+ SetActive();
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::CreateSessionL()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::CreateSessionL()
+ {
+ LOG( _L("CDrmUdtHandler::CreateSessionL") );
+ __ASSERT_ALWAYS( iState == EConnect, User::Invariant() );
+
+ TUint32 ap;
+
+ if( !iConnection->IsConnected( ap ) )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ iSession.Close();
+ iSession.OpenL();
+
+ RStringPool strPool = iSession.StringPool();
+
+ // Remove first session properties just in case.
+ RHTTPConnectionInfo connInfo = iSession.ConnectionInfo();
+
+ // Clear RConnection and Socket Server instances
+ connInfo.RemoveProperty(strPool.StringF(HTTP::EHttpSocketServ,RHTTPSession::GetTable()));
+ connInfo.RemoveProperty(strPool.StringF(HTTP::EHttpSocketConnection,RHTTPSession::GetTable()));
+
+#ifdef __WINS__
+ // Clear the proxy settings
+ RStringF proxy;
+ proxy = strPool.OpenFStringL(_L8("172.22.168.15"));
+ connInfo.SetPropertyL
+ (
+ strPool.StringF( HTTP::EProxyAddress, RHTTPSession::GetTable() ),
+ THTTPHdrVal( proxy )
+ );
+ proxy.Close();
+ connInfo.SetPropertyL
+ (
+ strPool.StringF( HTTP::EProxyUsage, RHTTPSession::GetTable() ),
+ THTTPHdrVal( strPool.StringF(HTTP::EUseProxy, RHTTPSession::GetTable() ) )
+ );
+
+#else
+ THTTPHdrVal proxyUsage(strPool.StringF(HTTP::EUseProxy,RHTTPSession::GetTable()));
+ connInfo.RemoveProperty(strPool.StringF(HTTP::EProxyUsage,RHTTPSession::GetTable()));
+ connInfo.RemoveProperty(strPool.StringF(HTTP::EProxyAddress,RHTTPSession::GetTable()));
+#endif
+
+ connInfo.SetPropertyL
+ (
+ strPool.StringF( HTTP::EHttpSocketServ, RHTTPSession::GetTable() ),
+ THTTPHdrVal( iConnection->SocketServ().Handle() )
+ );
+
+ connInfo.SetPropertyL
+ (
+ strPool.StringF( HTTP::EHttpSocketConnection, RHTTPSession::GetTable() ),
+ THTTPHdrVal( REINTERPRET_CAST( TInt, &iConnection->Conn() ) )
+ );
+
+ InstallHttpFiltersL();
+
+ // Complete requests
+ TRequestStatus* ownStatus = &iStatus;
+ *ownStatus = KRequestPending;
+ iState = ESendMessage;
+ SetActive();
+ User::RequestComplete( ownStatus, KErrNone );
+ }
+
+
+// ---------------------------------------------------------
+// CDrmUdtModule::InstallHttpFilters()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::InstallHttpFiltersL()
+ {
+ LOG( _L("CDrmUdtHandler::InstallHttpFiltersL") );
+ // CHttpUAProfFilterInterface::InstallFilterL( iSession );
+ // CHttpCookieFilter::InstallFilterL( iSession );
+ // InstallAuthenticationL( iSession );
+ // CHttpFilterProxyInterface::InstallFilterL( iSession );
+ }
+
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::SendUdtMessageL()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::SendUdtMessageL()
+ {
+ LOG( _L("CDrmUdtHandler::SendUdtMessageL") );
+ __ASSERT_ALWAYS( iState == ESendMessage, User::Invariant() );
+
+ TUriParser8 uri;
+
+ if ( iRequestType == EUdtRequest )
+ {
+ CreateUdtRequestL();
+ }
+ else if( iRequestType == EStatusNotification )
+ {
+ CreateStatusNotificationL();
+ }
+
+ User::LeaveIfError( uri.Parse( *iUri ) );
+ RStringF POST;
+ POST = iSession.StringPool().StringF( HTTP::EPOST, RHTTPSession::GetTable() );
+ iTransaction = iSession.OpenTransactionL( uri, *this, POST );
+
+ // Set required headers
+ RHTTPHeaders hdrs = iTransaction.Request().GetHeaderCollection();
+
+ SetHeaderL(hdrs, HTTP::EAccept, KUdtContentType() );
+
+ SetHeaderL(hdrs, HTTP::EContentType, KUdtContentType() );
+
+ // Add request body
+ MHTTPDataSupplier* ds = this;
+ iTransaction.Request().SetBody(*ds);
+
+ iTransaction.SubmitL();
+
+ iState = EResponseReceived;
+ iStatus = KRequestPending;
+ SetActive();
+
+ iTimeout->Cancel();
+ iTimeout->Start( KUdtTimeoutValue,
+ KUdtTimeoutValue,
+ TCallBack( StaticTimeOut,this ) );
+ }
+
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::CreateUdtRequestL()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::CreateUdtRequestL()
+ {
+ RRoapStorageClient client;
+ RPointerArray< HBufC8 > certChain;
+ TCleanupItem listCleanup( PointerArrayResetDestroyAndClose< HBufC8 >,
+ &certChain );
+ HBufC8* certBlock;
+ TInt i;
+ TInt n;
+ TPtr8 ptr( NULL, 0 );
+ TBuf8< sizeof ( TUint32 ) > intBuf;
+ TBuf8< KMaxSerNumLength > targetSer;
+ TBuf8< KRdbKeyLength > rdb_data;
+ TBuf8< KSignatureLength > hash;
+ HBufC8* signature = NULL;
+ TInt udtVersion;
+ CSHA1* hasher = NULL;
+
+ LOG( _L("CDrmUdtHandler::CreateUdtRequestL") );
+ delete iUdtRequest;
+
+ if ( iObserver )
+ {
+ iStateInfo.iState = TUdtStateInfo::EUdtReguest;
+ iStateInfo.iProgress = 0;
+ iObserver->UdtProgressInfoL( iStateInfo );
+ }
+
+ hasher = CSHA1::NewL();
+ CleanupStack::PushL( hasher );
+ User::LeaveIfError( client.Connect() );
+ CleanupClosePushL( client );
+ client.SelectTrustedRootL( KNullDesC8 );
+
+ LOG( _L(" Getting cert chain") );
+ User::LeaveIfError( client.GetDeviceCertificateChainL( certChain ) );
+ CleanupStack::PushL( listCleanup );
+
+ LOG( _L(" Getting UDT data") );
+ ReadUdtDataL( targetSer, udtVersion, rdb_data );
+
+ LOG(_L8("RDB data:"));
+ LOGHEX(rdb_data)
+
+ n = 0;
+ for ( i = 0; i < certChain.Count(); i++ )
+ {
+ n = n + KLengthSize + certChain[i]->Size();
+ }
+ certBlock = HBufC8::NewL( n );
+ CleanupStack::PushL( certBlock );
+ ptr.Set( certBlock->Des() );
+ for ( i = 0; i < certChain.Count(); i++ )
+ {
+ WriteIntToBlock( certChain[i]->Size(), intBuf, 0 );
+ ptr.Append( intBuf );
+ ptr.Append( *certChain[i] );
+ }
+
+ n = KVersionSize +
+ KMessageIdSize +
+ KLengthSize +
+ iOneTimePassword->Size() +
+ KLengthSize +
+ certBlock->Size() +
+ KLengthSize +
+ targetSer.Size() +
+ rdb_data.Size() +
+ KLengthSize +
+ KSignatureLength;
+
+ iUdtRequest = HBufC8::NewL( n );
+ ptr.Set( iUdtRequest->Des() );
+ WriteIntToBlock( n - (KVersionSize + KMessageIdSize +
+ KLengthSize + KSignatureLength), intBuf, 0 );
+
+ ptr.Append( KVersion ); // 1. version
+ ptr.Append( KUdtRequestId ); // 2. request id
+ ptr.Append( intBuf ); // 3. request length
+ ptr.Append( *iOneTimePassword ); // 4. password
+ WriteIntToBlock( certBlock->Size(), intBuf, 0 );
+ ptr.Append( intBuf ); // 5. ceritificate block length
+ ptr.Append( *certBlock ); // 6. ceritificate block
+ WriteIntToBlock( targetSer.Size(), intBuf, 0 );
+ ptr.Append( intBuf ); // 7. serial number length
+ ptr.Append( targetSer ); // 8. original serial number
+ ptr.Append( rdb_data ); // 9. RDB data
+ WriteIntToBlock( udtVersion, intBuf, 0 );
+ ptr.Append( intBuf ); // 10. UDT key version
+
+ hasher->Update( ptr );
+ hash.Append( 0 );
+ hash.Append( KPadding255 );
+ for ( i = 2; i < KSignatureLength - SHA1_HASH - 1; i++ )
+ {
+ hash.Append( 255 );
+ }
+ hash.Append( 0 );
+ hash.Append( hasher->Final() );
+ LOG(_L8("Hash:"));
+ LOGHEX(hash);
+ client.RsaSignL( hash, signature );
+ CleanupStack::PushL(signature);
+ ptr.Append( *signature ); // 11. signature
+ LOG(_L8("Signature:"));
+ LOGHEX((*signature));
+
+ CleanupStack::PopAndDestroy( 5 ); // certBlock, listCleanup,
+ // client, hasher, signature
+ if ( iObserver )
+ {
+ iStateInfo.iState = TUdtStateInfo::EUdtReguest;
+ iStateInfo.iProgress += 20;
+ iObserver->UdtProgressInfoL( iStateInfo );
+ }
+
+ LOG(_L8("Request:"));
+ LOGHEX((*iUdtRequest));
+ }
+
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::CreateStatusNotificationL()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::CreateStatusNotificationL()
+ {
+ LOG( _L("CDrmUdtHandler::CreateStatusNotificationL") );
+
+ if ( iObserver )
+ {
+ iStateInfo.iState = TUdtStateInfo::EUdtStatusNotification;
+ iStateInfo.iProgress += 20;
+ iObserver->UdtProgressInfoL( iStateInfo );
+ }
+
+ delete iUdtRequest;
+ iUdtRequest = NULL;
+ iUdtRequest = HBufC8::NewL(64);
+ TPtr8 ptr = iUdtRequest->Des();
+ ptr.Append(0);
+ ptr.Append(2);
+ ptr.Append(*iOneTimePassword);
+ iUdtError == EUdtOk ? ptr.Append(1) : ptr.Append(0);
+ }
+
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::ResponseReceivedL()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::ResponseReceivedL()
+ {
+ LOG( _L("CDrmUdtHandler::ResponseReceivedL") );
+ __ASSERT_ALWAYS( iState == EResponseReceived, User::Invariant() );
+ __ASSERT_ALWAYS( iUdtResponse, User::Invariant() );
+
+ TPtrC8 udtRespPtr( *iUdtResponse );
+ HBufC8* origDBKey = NULL;
+ TPtrC8 origDBKeyPtr( KNullDesC8 );
+ RDRMRightsClient rightsClient;
+ TInt error = EUdtOk;
+
+ LOGHEX((*iUdtResponse));
+
+ // check response type
+ switch ( udtRespPtr[1] )
+ {
+ case KUdtResponseId:
+ {
+ if ( iObserver )
+ {
+ iStateInfo.iState = TUdtStateInfo::EUdtKeyRestore;
+ iStateInfo.iProgress += 20;
+ iObserver->UdtProgressInfoL( iStateInfo );
+ }
+
+ if ( udtRespPtr.Length() < KUdtResponseSize )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ origDBKeyPtr.Set( udtRespPtr.Mid( 2 ) );
+ origDBKey = origDBKeyPtr.AllocLC();
+
+ iUdtError = rightsClient.Connect();
+ CleanupClosePushL( rightsClient );
+
+ if ( !iUdtError )
+ {
+ iUdtError = rightsClient.InitiateUdt( origDBKeyPtr );
+ }
+
+ CleanupStack::PopAndDestroy( 2 ); // origDBKey, rightsClient
+
+ iRequestType = EStatusNotification;
+ iState = ESendMessage;
+ iStatus = KRequestPending;
+ SetActive();
+ SelfComplete( KErrNone );
+ break;
+ }
+ case KStatusResponseId:
+ {
+ if ( iObserver )
+ {
+ iStateInfo.iState = TUdtStateInfo::EUdtStatusNotification;
+ iStateInfo.iProgress += 20;
+ iObserver->UdtProgressInfoL( iStateInfo );
+ }
+
+ iState = EComplete;
+ iStatus = KRequestPending;
+ SetActive();
+
+ if ( iUdtError )
+ {
+ error = EUdtKeyRestoreFailed;
+ iUdtError = EUdtOk;
+ }
+ SelfComplete( error );
+ break;
+ }
+ case KErrorResponseId:
+ {
+ if ( udtRespPtr.Length() >= 3 && udtRespPtr[2] == KClientErrorValue )
+ {
+ error = EUdtClientError;
+ }
+ else
+ {
+ error = EUdtServerError;
+ }
+
+ iState = EComplete;
+ iStatus = KRequestPending;
+ SetActive();
+ SelfComplete( error );
+ break;
+ }
+ default:
+ {
+ User::Leave( KErrNotSupported );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::SetHeaderL()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue)
+ {
+ LOG( _L("CDrmUdtHandler::SetHeaderL") );
+ RStringF valStr = iSession.StringPool().OpenFStringL(aHdrValue);
+ THTTPHdrVal val(valStr);
+ aHeaders.SetFieldL(iSession.StringPool().StringF(aHdrField,RHTTPSession::GetTable()), val);
+ valStr.Close();
+ }
+
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::Complete()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::Complete()
+ {
+ LOG( _L("CDrmUdtHandler::Complete") );
+
+ delete iUri;
+ iUri = NULL;
+ delete iUdtResponse;
+ iUdtResponse = NULL;
+ delete iUdtRequest;
+ iUdtRequest = NULL;
+ delete iOneTimePassword;
+ iOneTimePassword = NULL;
+
+ if( iTimeout )
+ {
+ iTimeout->Cancel();
+ }
+
+ if ( iObserver )
+ {
+ iStateInfo.iState = TUdtStateInfo::EUdtComplete;
+ iStateInfo.iProgress = 100;
+ iStateInfo.iError = iError;
+ TRAPD(ignore, iObserver->UdtProgressInfoL( iStateInfo ));
+ }
+
+ User::RequestComplete( iParentStatus, iError );
+ iParentStatus = NULL;
+ }
+
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::CDrmUdtModule()
+// ---------------------------------------------------------
+//
+CDrmUdtHandler::CDrmUdtHandler(): CActive( CActive::EPriorityStandard )
+ {
+ LOG( _L("CDrmUdtHandler::CDrmUdtHandler") );
+ CActiveScheduler::Add( this );
+ }
+
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::SelfComplete()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::SelfComplete( TInt aResult )
+ {
+ LOG( _L("CDrmUdtHandler::SelfComplete") );
+ if ( iStatus == KRequestPending )
+ {
+ TRequestStatus* ownStatus = &iStatus;
+ User::RequestComplete( ownStatus, aResult );
+ }
+ else
+ {
+ if ( aResult != KErrNone )
+ {
+ iStatus = aResult;
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::MHFRunL()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::MHFRunL( RHTTPTransaction /*aTransaction */,
+ const THTTPEvent& aEvent )
+ {
+ LOGINT( _L("CDrmUdtHandler::MHFRunL: %d"), aEvent.iStatus );
+ iTimeout->Cancel();
+ iTimeout->Start( KUdtTimeoutValue,
+ KUdtTimeoutValue,
+ TCallBack( StaticTimeOut,this ) );
+
+ switch ( aEvent.iStatus )
+ {
+ case THTTPEvent::EGotResponseHeaders:
+ {
+ HandleResponseHeadersL( iTransaction.Response() );
+ break;
+ }
+
+ case THTTPEvent::EGotResponseBodyData:
+ {
+ TInt ret( KErrNone );
+ MHTTPDataSupplier* body = iTransaction.Response().Body();
+ TPtrC8 ptr;
+ body->GetNextDataPart( ptr );
+ ret = AppendResponseData( ptr );
+ body->ReleaseData();
+ User::LeaveIfError( ret );
+ break;
+ }
+
+ case THTTPEvent::EFailed:
+ {
+ if ( iError == KErrNone )
+ {
+ iError = EUdtServerError;
+ }
+ iTransaction.Close();
+ SelfComplete( iError );
+ break;
+ }
+
+ case THTTPEvent::ESucceeded:
+ {
+ iTransaction.Close();
+ SelfComplete( iError );
+ break;
+ }
+
+ case THTTPEvent::ERedirectRequiresConfirmation:
+ {
+ iTransaction.SubmitL();
+ }
+
+ default:
+ {
+ if( aEvent.iStatus == KErrHttpRedirectUseProxy )
+ {
+ }
+ else
+ {
+ User::LeaveIfError( aEvent.iStatus );
+ }
+ break;
+ }
+ }
+
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::MHFRunError()
+// ---------------------------------------------------------
+//
+TInt CDrmUdtHandler::MHFRunError (
+ TInt aError,
+ RHTTPTransaction /* aTransaction */,
+ const THTTPEvent& /* aEvent */
+ )
+ {
+ LOG( _L("CDrmUdtHandler::MHFRunError") );
+ iTransaction.Close();
+ iError = aError;
+ SelfComplete( iError );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::HandleResponseHeadersL()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::HandleResponseHeadersL( RHTTPResponse aHttpResponse )
+ {
+ LOG( _L("CDrmUdtHandler::HandleResponseHeadersL") );
+ RHTTPHeaders headers = aHttpResponse.GetHeaderCollection();
+
+ TInt httpCode = aHttpResponse.StatusCode();
+ TBool status;
+
+ status = CheckHttpCode( httpCode );
+
+ if ( status )
+ {
+ RStringF contentTypeStr;
+ THTTPHdrVal contentTypeVal;
+ TPtrC8 ptrContentType(KNullDesC8);
+ RStringPool srtPool;
+ srtPool = iSession.StringPool();
+
+ contentTypeStr = srtPool.StringF( HTTP::EContentType, RHTTPSession::GetTable() );
+ User::LeaveIfError( headers.GetField( contentTypeStr, 0, contentTypeVal ) );
+
+ if ( contentTypeVal.StrF().DesC().CompareF( KUdtContentType() ) != KErrNone )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ }
+ if ( aHttpResponse.HasBody() )
+ {
+ TInt dataSize = aHttpResponse.Body()->OverallDataSize();
+ if ( dataSize >= 0 )
+ {
+ HBufC8* buf = HBufC8::NewL( dataSize );
+ delete iUdtResponse;
+ iUdtResponse = buf;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::CheckHttpCode()
+// ---------------------------------------------------------
+//
+TBool CDrmUdtHandler::CheckHttpCode( TInt aHttpStatus )
+ {
+ LOGINT(_L("CDrmUdtHandler::CheckHttpCode: %d"), aHttpStatus);
+ if ( HTTPStatus::IsInformational( aHttpStatus ) )
+ {
+ // 1xx
+ // Informational messages.
+ iError = EUdtServerError;
+ return EFalse;
+ }
+ else if ( aHttpStatus == HTTPStatus::EOk ||
+ aHttpStatus == HTTPStatus::ENonAuthoritativeInfo )
+ {
+ // 200 OK
+ // 203 Non-Authoritative Information
+ iError = EUdtOk;
+ return ETrue;
+ }
+ else if ( HTTPStatus::IsSuccessful( aHttpStatus ) )
+ {
+ // 2xx
+ // Success codes without an usable body.
+ iError = EUdtServerError;
+ return EFalse;
+ }
+ else if ( aHttpStatus == HTTPStatus::EUnauthorized ||
+ aHttpStatus == HTTPStatus::EProxyAuthenticationRequired )
+ {
+ // 401 Unauthorized
+ // 407 Proxy authentication required
+ iError = EUdtInvalidServerAddress;
+ return EFalse;
+ }
+ else if ( aHttpStatus == HTTPStatus::ENotFound ||
+ aHttpStatus == HTTPStatus::EGone )
+ {
+ // 404 Not found
+ // 410 Gone
+ iError = EUdtInvalidServerAddress;
+ return EFalse;
+ }
+ else if ( HTTPStatus::IsClientError( aHttpStatus ) )
+ {
+ // 4xx
+ iError = EUdtInvalidServerAddress;
+ return EFalse;
+ }
+ else if ( aHttpStatus == HTTPStatus::EHTTPVersionNotSupported )
+ {
+ // 505 HTTP Version Not Supported
+ iError = EUdtServerError;
+ return EFalse;
+ }
+ else if ( HTTPStatus::IsServerError( aHttpStatus ) )
+ {
+ // 5xx
+ iError = EUdtServerError;
+ return EFalse;
+ }
+ else
+ {
+ // Everything else.
+ iError = EUdtServerError;
+ }
+ return EFalse;
+ }
+
+
+// ---------------------------------------------------------
+// CDrmUdtModule::AppendResponseData()
+// ---------------------------------------------------------
+//
+TInt CDrmUdtHandler::AppendResponseData( const TDesC8& aDataChunk )
+ {
+ LOG( _L("CDrmUdtHandler::AppendResponseData") );
+ TInt needed = iUdtResponse->Des().Length() + aDataChunk.Length();
+ if ( iUdtResponse->Des().MaxLength() < needed )
+ {
+ HBufC8* buf = iUdtResponse->ReAlloc( needed );
+ if ( buf )
+ {
+ iUdtResponse = buf;
+ }
+ else
+ {
+ return KErrNoMemory;
+ }
+ }
+ iUdtResponse->Des().Append( aDataChunk );
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CDrmUdtHandler::StaticTimeOut()
+// -----------------------------------------------------------------------------
+//
+TInt CDrmUdtHandler::StaticTimeOut( TAny* aPointer )
+ {
+ LOG( _L("CDrmUdtHandler::StaticTimeOut") );
+ CDrmUdtHandler* itself = STATIC_CAST(CDrmUdtHandler*, aPointer);
+ if(itself)
+ {
+ itself->TimeOut();
+ }
+ return KErrNone;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CDrmUdtHandler::TimeOut()
+// -----------------------------------------------------------------------------
+//
+void CDrmUdtHandler::TimeOut()
+ {
+ LOG( _L("CDrmUdtHandler::TimeOut") );
+ iTransaction.Close();
+ iError = KErrTimedOut;
+ SelfComplete( iError );
+ }
+
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::GetNextDataPart()
+// ---------------------------------------------------------
+//
+TBool CDrmUdtHandler::GetNextDataPart( TPtrC8& aDataPart )
+ {
+ LOG( _L("CDrmUdtHandler::GetNextDataPart") );
+ aDataPart.Set( iUdtRequest->Des() );
+ return ETrue;
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::ReleaseData()
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::ReleaseData()
+ {
+ LOG( _L("CDrmUdtHandler::ReleaseData") );
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::OverallDataSize()
+// ---------------------------------------------------------
+//
+TInt CDrmUdtHandler::OverallDataSize()
+ {
+ LOG( _L("CDrmUdtHandler::OverallDataSize") );
+ return iUdtRequest->Des().Size();
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::Reset()
+// ---------------------------------------------------------
+//
+TInt CDrmUdtHandler::Reset()
+ {
+ LOG( _L("CDrmUdtHandler::Reset") );
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::ReadUdtDataL
+//
+// ---------------------------------------------------------
+//
+void CDrmUdtHandler::ReadUdtDataL(
+ TDes8& aTargetSerialNumber,
+ TInt& aUdtKeyVersion,
+ TDes8& aEncryptedRdbData )
+ {
+ RDRMRightsClient rightsClient;
+ HBufC* serialNum = NULL;
+
+ LOG( _L("CDrmUdtHandler::ReadUdtDataL") );
+ User::LeaveIfError( rightsClient.Connect() );
+ CleanupClosePushL( rightsClient );
+ serialNum = SerialNumberL();
+
+ aTargetSerialNumber.Copy( *serialNum );
+
+ aUdtKeyVersion = 0;
+ User::LeaveIfError( rightsClient.GetUdtData( aEncryptedRdbData ) );
+ if( !aEncryptedRdbData.Length() )
+ {
+ User::Leave( KErrNotFound );
+ }
+ CleanupStack::PopAndDestroy(); // rightsClient
+ }
+
+// ---------------------------------------------------------
+// CDrmUdtHandler::ReadUdtDataL
+//
+// ---------------------------------------------------------
+//
+HBufC* CDrmUdtHandler::SerialNumberL()
+ {
+ TInt error( KErrNone );
+ TInt count( 0 );
+ TInt count2( 0 );
+ TUint32 caps( 0 );
+ HBufC* imei = NULL;
+
+#ifndef __WINS__
+ LOG( _L("CDrmUdtHandler::SerialNumberL") );
+
+ RTelServer etelServer;
+ RMobilePhone phone;
+
+ for ( TUint8 i = 0; i < 3; ++i )
+ {
+ error = etelServer.Connect();
+ if ( error )
+ {
+ User::After( TTimeIntervalMicroSeconds32( 100000 ) );
+ }
+ }
+
+ User::LeaveIfError( error );
+ CleanupClosePushL( etelServer );
+
+ LOG( _L(" Connected to ETEL") );
+
+ User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) );
+
+ LOG( _L(" Phone Module loaded") );
+
+ TUnloadModule unload;
+ unload.iServer = &etelServer;
+ unload.iName = &KMmTsyModuleName;
+
+ TCleanupItem item( DoUnloadPhoneModule, &unload );
+ CleanupStack::PushL( item );
+
+ User::LeaveIfError( etelServer.EnumeratePhones( count ) );
+
+ LOG( _L(" Phones enumerated") );
+
+ for ( count2 = 0; count2 < count; ++count2 )
+ {
+ RTelServer::TPhoneInfo phoneInfo;
+ User::LeaveIfError( etelServer.GetTsyName( count2, phoneInfo.iName ) );
+
+ LOG( _L(" Got TSY module") );
+ LOG( phoneInfo.iName );
+ if ( phoneInfo.iName.CompareF( KMmTsyModuleName ) == 0 )
+ {
+ User::LeaveIfError( etelServer.GetPhoneInfo( count2, phoneInfo ) );
+ LOG( _L(" Got phone info") );
+ User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) );
+ LOG( _L(" Opened phone") );
+ CleanupClosePushL( phone );
+ break;
+ }
+ }
+
+ if ( count2 == count )
+ {
+ // Not found.
+ LOG( _L(" No phone found") );
+ User::Leave( KErrNotFound );
+ }
+
+ LOG( _L(" Got phone") );
+
+ User::LeaveIfError( phone.GetIdentityCaps( caps ) );
+
+ LOG( _L(" Got Caps") );
+
+ if ( caps & RMobilePhone::KCapsGetSerialNumber )
+ {
+ RMobilePhone::TMobilePhoneIdentityV1 id;
+ TRequestStatus status;
+
+ phone.GetPhoneId( status, id );
+ User::WaitForRequest( status );
+
+ User::LeaveIfError( status.Int() );
+
+ imei = id.iSerialNumber.AllocL();
+
+ LOG( _L(" Got serial number") );
+
+ CleanupStack::PopAndDestroy( 3 ); // phone, item, etelServer
+
+ return imei;
+ }
+
+ User::Leave( KErrNotFound );
+
+ // Never happens...
+ return imei;
+
+#else
+ _LIT( KDefaultSerialNumber, "123456789123456789" );
+ imei = KDefaultSerialNumber().AllocL();
+
+ return imei;
+#endif
+ }
+
+