omadrm/drmplugins/drmrohandler/src/CRoHandler.cpp
changeset 0 95b198f216e5
child 2 76350b5be3d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmplugins/drmrohandler/src/CRoHandler.cpp	Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,1773 @@
+/*
+* Copyright (c) 2004-2009 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:  ECOM plugin for receiving OMA Rights Objects
+*
+*/
+
+
+// INCLUDE FILES
+#include <txtrich.h>                    // for CRichText
+#include <drmmessageparser.h>           // for CDrmMessageParser
+#include <drmrights.h>                  // for CDRMRights
+#include <ecom/implementationproxy.h>   // for TImplementationProxy
+#include <push/cpushhandlerbase.h>      // for CPushHandlerBase
+#include <push/pluginkiller.h>          // for CPluginKiller
+#include <push/pushmessage.h>           // for CPushMessage
+#include <roapeng.h>                    // for CRoapEng
+#include <roapengbase.h>
+#include <roapobserver.h>
+#include <centralrepository.h>          // link against centralrepository.lib
+#include <msvuids.h>
+#include <msvids.h>
+#include <downloadmgrclient.h>
+
+#ifdef RD_MULTIPLE_DRIVE
+#include <driveinfo.h>
+#endif
+
+#include <uri16.h>                          // TUriParser16
+#include <data_caging_path_literals.hrh>    // KDC_MTM_RESOURCE_DIR
+#include <uriutils.h>                       // UriUtils and so on
+#include <pushmtmui.rsg>                    // for R_PUSHMISC_UNK_SENDER
+#include <rohandler.rsg>                    // for R_QTN_DRM_MGR_INB_TITLE
+#include <sysutil.h>                        // Disk space checking
+
+#include "crohandler.h"
+#include "romtmcli.h"                       // for CRightsObjectMtmClient
+#include "roapsyncwrapper.h"
+
+#include "stringresourcereader.h"
+#include "rohandlerdmgrwrapper.h"
+#include "rohandlerinternalcrkeys.h"
+
+#ifdef _DEBUG
+#define DRMDEBUGLIT( a, b ) _LIT( a, b )
+#define DRMDEBUG( a ) RDebug::Print( a )
+#define DRMDEBUG2( a, b ) RDebug::Print( a, b )
+_LIT( KRoLogDir, "DRM" );
+_LIT( KRoLogFile, "RoHandler.log" );
+#define LOG( a ) RFileLogger::Write( KRoLogDir(), KRoLogFile(), EFileLoggingModeAppend, a );
+#define LOGHEX( ptr, len ) RFileLogger::HexDump( \
+    KRoLogDir(), KRoLogFile(), EFileLoggingModeAppend, _S(""), _S(""), ptr, len );
+#define LOG2( a, b ) RFileLogger::WriteFormat( \
+    KRoLogDir(), KRoLogFile(), EFileLoggingModeAppend, a, b );
+#else
+#define DRMDEBUGLIT( a, b )
+#define DRMDEBUG( a )
+#define DRMDEBUG2( a, b )
+#define LOG( a )
+#define LOGHEX( ptr, len )
+#define LOG2( a, b )
+#endif
+
+using namespace Roap;
+
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+const TImplementationProxy ImplementationTable[] =
+    {
+    IMPLEMENTATION_PROXY_ENTRY(0x101F7B93, CRoHandler::NewL)
+    //{{0x101F7B93}, CRoHandler::NewL}
+    };
+
+// For reading the string value of cenrep key Inbox entry visible (for
+// received RO). The size of string "false" is 5.
+const TInt KBooleanStringMaxSize = 5;
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+#ifdef RD_MULTIPLE_DRIVE
+_LIT( KRoHandlerTriggerFilePath, "%c:\\system\\data\\" );
+#else
+_LIT( KDriveZ, "z:" );
+_LIT( KRoHandlerTriggerFilePath, "c:\\system\\data\\" );
+#endif
+
+_LIT( KPushMtmRes, "PushMtmUi.rsc" );
+_LIT( KRoHandlerResourceFile, "RoHandler.rsc" );
+
+_LIT8( KRoapTriggerElement, "roapTrigger" );
+_LIT8( KWbxmlRoapTriggerElement, "\x03\x13j" );
+_LIT8( KRoapTriggerRoAcquisition, "roAcquisition" );
+_LIT8( KRoapTriggerMeteringReport, "meteringReport" );
+_LIT8( KRoapRoPduElement, "roResponse" );
+
+_LIT( KFalse, "false" );
+_LIT( KZero, "0" );
+
+_LIT( KRoAcquisitionPrefix, "ROA:" );
+_LIT( KTriggerPrefix, "TRI:" );
+
+// MODULE DATA STRUCTURES
+
+// Helper class for deleting file with given filename on cleanupstack
+// Note does not own its members
+// Used for cleaning up saved trigger if creating trigger related message
+// inbox entry fails.
+NONSHARABLE_CLASS( CFileDeleter ) : public CBase
+    {
+public:
+    static CFileDeleter* NewLC( RFs& aFs, TFileName& aFileName )
+        {
+        CFileDeleter* self( new ( ELeave ) CFileDeleter( aFs, aFileName ) );
+        CleanupStack::PushL( self );
+        return self;
+        }
+
+    inline void SetDelete()
+        {
+        iDeleteFileOnDestroy = ETrue;
+        }
+
+    inline void SetNoDelete()
+        {
+        iDeleteFileOnDestroy = EFalse;
+        }
+
+    virtual ~CFileDeleter()
+        {
+        if ( iDeleteFileOnDestroy )
+            {
+            iFs.Delete( iFileName );
+            }
+        }
+
+private:
+    CFileDeleter()
+        {
+        }
+    CFileDeleter( const CFileDeleter& )
+        {
+        }
+    CFileDeleter( RFs& aFs, TFileName& aFileName )
+        : iFs( aFs ), iFileName( aFileName )
+        {
+        }
+
+    CFileDeleter& operator=( const CFileDeleter& );
+
+    TBool iDeleteFileOnDestroy;
+    RFs iFs;
+    TFileName iFileName;
+    };
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// ============================= LOCAL FUNCTIONS ===============================
+#ifdef _DRM_TESTING
+LOCAL_C void WriteLogL( const TDesC8& text, RFs &aFs );
+LOCAL_C void WriteFileL( const TDesC8& text, RFs &aFs, const TDesC& aName );
+LOCAL_C void CreateLogL();
+LOCAL_C void WriteL( const TDesC8& aText );
+LOCAL_C void WriteL( const TDesC& aText );
+LOCAL_C void WriteL( const TDesC8& aText, TInt aErr );
+LOCAL_C void WriteL( const TDesC& aText, TInt aErr );
+LOCAL_C void WriteCurrentTimeL();
+#endif
+
+// -----------------------------------------------------------------------------
+// Testing stuff
+// -----------------------------------------------------------------------------
+//
+
+#ifdef _DRM_TESTING
+LOCAL_C void WriteLogL( const TDesC8& text, RFs &aFs )
+    {
+    _LIT( KLogFile, "c:\\CROHandler.txt" );
+    WriteFileL( text, aFs, KLogFile );
+    }
+
+LOCAL_C void WriteFileL( const TDesC8& text, RFs &aFs, const TDesC& aName )
+    {
+    RFile file;
+    TInt size;
+    User::LeaveIfError( file.Open( aFs, aName, EFileWrite ) );
+    CleanupClosePushL( file );
+    User::LeaveIfError( file.Size( size ) );
+    User::LeaveIfError( file.Write( size, text ) );
+    CleanupStack::PopAndDestroy( &file );
+    }
+
+LOCAL_C void CreateLogL()
+    {
+    RFs fs;
+    User::LeaveIfError( fs.Connect() );
+    CleanupClosePushL( fs );
+    RFile file;
+    User::LeaveIfError( file.Replace( fs, _L( "c:\\CROHandler.txt" ), EFileWrite ) );
+    file.Close();
+    CleanupStack::PopAndDestroy( &fs );
+    }
+
+LOCAL_C void WriteL( const TDesC& aText )
+    {
+    RFs fs;
+    User::LeaveIfError( fs.Connect() );
+    CleanupClosePushL( fs );
+    HBufC8* text = HBufC8::NewLC( 1000 );
+    TPtr8 textptr( text->Des() );
+    textptr.Append( aText );
+    textptr.Append( _L8( "\r\n" ) );
+    WriteLogL( textptr, fs );
+    CleanupStack::PopAndDestroy( text );
+    CleanupStack::PopAndDestroy( &fs );
+    WriteCurrentTimeL();
+    }
+
+LOCAL_C void WriteL( const TDesC8& aText )
+    {
+    RFs fs;
+    User::LeaveIfError( fs.Connect() );
+    CleanupClosePushL( fs );
+    HBufC8* text = HBufC8::NewLC( 1000 );
+    TPtr8 textptr( text->Des() );
+    textptr.Append( aText );
+    textptr.Append( _L8( "\r\n" ) );
+    WriteLogL( textptr, fs );
+    CleanupStack::PopAndDestroy( text );
+    CleanupStack::PopAndDestroy( &fs );
+    WriteCurrentTimeL();
+    }
+
+LOCAL_C void WriteL( const TDesC8& aText, TInt aErr )
+    {
+    _LIT8( KErr, ": %d" );
+    HBufC8* text = HBufC8::NewLC( 1000 + 20 );
+    TBuf8<20> num;
+    TPtr8 textptr( text->Des() );
+    textptr.Append( aText );
+    num.Format( KErr(), aErr );
+    textptr.Append( num );
+    WriteL( textptr );
+    CleanupStack::PopAndDestroy( text );
+    }
+
+LOCAL_C void WriteL( const TDesC& aText, TInt aErr )
+    {
+    _LIT8( KErr, ": %d" );
+    HBufC8* text = HBufC8::NewLC( 1000+20 );
+    TBuf8<20> num;
+    TPtr8 textptr( text->Des() );
+    textptr.Append( aText );
+    num.Format( KErr(), aErr );
+    textptr.Append( num );
+    WriteL( textptr );
+    CleanupStack::PopAndDestroy( text );
+    }
+
+LOCAL_C void WriteCurrentTimeL()
+    {
+    RFs fs;
+    User::LeaveIfError( fs.Connect() );
+    CleanupClosePushL( fs );
+    HBufC8* text = HBufC8::NewLC( 100 );
+    TPtr8 textptr( text->Des() );
+    // Date and Time display
+    TTime time;
+    time.HomeTime();
+    TBuf<256> dateString;
+    _LIT( KDate, "%*E%*D%X%*N%*Y %1 %2 '%3" );
+    time.FormatL( dateString, KDate );
+    textptr.Append( _L( "\r\n\t\tData:\t" ) );
+    textptr.Append( dateString );
+    _LIT( KTime, "%-B%:0%J%:1%T%:2%S%:3%+B" );
+    time.FormatL( dateString, KTime );
+    textptr.Append( _L( "\r\n\t\tTime:\t" ) );
+    textptr.Append( dateString );
+    textptr.Append( _L( "\r\n" ) );
+    textptr.Append( _L( "\r\n" ) );
+    WriteLogL( textptr, fs );
+    CleanupStack::PopAndDestroy( text );
+    CleanupStack::PopAndDestroy( &fs );
+    }
+#endif
+
+
+// ----------------------------------------------------------------------------
+// DoResetAndDestroy
+// Does RPointerArray< >->ResetAndDestroy() for the given array aPtr.
+// ----------------------------------------------------------------------------
+//
+LOCAL_C void DoResetAndDestroy( TAny* aPtr )
+    {
+    ( reinterpret_cast< RPointerArray< CDRMRights >* >( aPtr ) )->ResetAndDestroy();
+    delete aPtr;
+    aPtr = NULL;
+    }
+
+// ----------------------------------------------------------------------------
+// LeaveIfNullL
+// Leaves with given error or with KErrArgument if aBuf is null
+// ----------------------------------------------------------------------------
+//
+LOCAL_C inline void LeaveIfNullL( const TInt aRet, const HBufC8* aBuf )
+    {
+    if ( !aBuf )
+        {
+        User::LeaveIfError( aRet );
+        User::Leave( KErrArgument );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// IsMeteringSupported
+// ----------------------------------------------------------------------------
+//
+LOCAL_C TBool IsMeteringSupported()
+    {
+#ifdef RD_DRM_METERING
+    return ETrue;
+#else
+    return EFalse;
+#endif
+    }
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: NewL
+
+    Description: 1st phase constructor
+
+    Return Value: new CRoHandler
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+CRoHandler* CRoHandler::NewL
+        (
+        //None.
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, CreateLogL() );
+    TRAP( r, WriteL( _L8( "NewL" ) ) );
+#endif
+    CRoHandler* self( new( ELeave ) CRoHandler() );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "NewL-End" ) ) );
+#endif
+    return self;
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: CRoHandler
+
+    Description: C++ default constructor. Initialises the object
+                 with zero/NULL values.
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+CRoHandler::CRoHandler
+        (
+        //None.
+        )
+    : CPushHandlerBase(),
+    iFirstTime( ETrue ), iPushMsg( NULL ), iMsvId( NULL ),
+    iPutRightsToInbox( ETrue )
+    {
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: ConstructL
+
+    Description: Adds the AO to the Active Scheduler. Constructs iDrm object
+                 then connects to drm server
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+void CRoHandler::ConstructL
+        (
+        //None.
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "ConstructL" ) ) );
+#endif
+
+    CRepository* repository( NULL );
+    TInt err( KErrNone );
+
+    User::LeaveIfError( iFs.Connect() );
+
+    // create drm
+    iMessageParser = CDRMMessageParser::NewL();
+
+    // Create wbxml trigger parser instance
+    iWbxmlTriggerParser = DRM::CWbxmlRoapTriggerParser::NewL();
+
+    // Create CMsvSession
+    // new session is opened Synchronously
+    iSession = CMsvSession::OpenSyncL( *this );
+
+    iMtmReg = CClientMtmRegistry::NewL( *iSession );
+
+    // Check if metering feature is active
+    iMeteringSupported = IsMeteringSupported();
+
+    // Check cenrep key in order to find out whether received RO
+    // should be stored to inbox or not.
+    TRAP( err, repository = CRepository::NewL( KCRUidRoHandler ) );
+    if ( !err )
+        {
+        CleanupStack::PushL( repository );
+        TBuf<KBooleanStringMaxSize> string;
+        TInt error = repository->Get( KDRMRoHandlerInboxEntryVisible,
+        string );
+
+        // If the value of the repository key is found either "false" or
+        // "0", do not store rights to an Inbox entry.
+        if ( ( string.CompareF( KFalse ) == 0 ) ||
+            ( string.CompareF( KZero ) == 0 ) )
+        {
+        iPutRightsToInbox = EFalse;
+        }
+
+    CleanupStack::PopAndDestroy( repository );
+        }
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "Repository->Get done" ), iPutRightsToInbox ) );
+    TRAP( r, WriteL( _L8( "ConstructL-End" ) ) );
+#endif
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: ~CRoHandler
+
+    Description: Calls also baseclass destructor which calls
+                 REcomSession::DestroyedImplementation( iDtor_ID_Key).
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+CRoHandler::~CRoHandler
+        (
+        //None.
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "~CRoHandler" ) ) );
+#endif
+
+    iFs.Close();
+    // Delete the necessary instance attributes
+    delete iPushMsg;
+    delete iMessageParser;
+    delete iWbxmlTriggerParser;
+    delete iParsedXmlTrigger;
+    delete iMtm;
+    delete iMtmReg;
+
+    iMsvId = NULL;
+
+    // session must be deleted last (and constructed first)
+    delete iSession;
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "~CRoHandler-End" ) ) );
+#endif
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: AddRoContentL
+
+    Description: Adds Message content and number
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+void CRoHandler::AddRoContentL
+        (
+        TDesC& aMessageContent             //message content descriptor
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "AddRoContentL" ) ) );
+#endif
+    TMsvEntry msvEntry( ( iMtm->Entry() ).Entry() );
+
+    // We get the message body from Mtm and insert a bodytext
+    CRichText& mtmBody( iMtm->Body() );
+    mtmBody.Reset();
+    mtmBody.InsertL( 0, aMessageContent ); // insert our msg tag as the body text
+
+    // set iRecipient into the Details of the entry
+    msvEntry.SetNew( ETrue );              // set New
+    msvEntry.SetUnread( ETrue );
+    msvEntry.SetVisible( ETrue );
+    msvEntry.SetInPreparation( EFalse );   // set inPreparation to false
+    msvEntry.iDate.UniversalTime();        // set time to Universal Time
+
+    // To handle the sms specifics we start using SmsMtm
+    CRightsObjectMtmClient* roMtm( NULL );
+    roMtm = static_cast< CRightsObjectMtmClient* >( iMtm );
+
+    // save message
+    CMsvEntry& entry( iMtm->Entry() );
+    entry.ChangeL( msvEntry );             // make sure that we are handling the right entry
+    roMtm->SaveMessageL();                 // closes the message
+
+    // This moves the message entry to Inbox
+    MoveMessageEntryL( KMsvGlobalInBoxIndexEntryId );
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "AddRoContentL-End" ) ) );
+#endif
+    }
+
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: HandleSessionEventL
+
+    Description: Starts the message handling procedure asynchronously.
+                 Basically all the work is done in RunL method.
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+void CRoHandler::HandleSessionEventL
+        (
+        TMsvSessionEvent /* aEvent*/ ,
+        TAny* /* aArg1*/ ,
+        TAny* /* aArg2 */,
+        TAny* /* aArg3 */
+        )
+    {
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: HandleMessageL
+
+    Description: Asynchronous version of the HandleMessageL().
+                 NOT SUPPORTED
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+void CRoHandler::HandleMessageL
+        (
+        CPushMessage* aPushMsg,  // push message
+        TRequestStatus& aStatus  // status of the request
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "HandleMessageL(2)" ) ) );
+#endif
+    iPushMsg = aPushMsg;
+    SetConfirmationStatus( aStatus );
+    SignalConfirmationStatus( KErrNotSupported );
+    iPluginKiller->KillPushPlugin();
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "HandleMessageL(2)-End" ) ) );
+#endif
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: HandleMessageL
+
+    Description: Synchronous version of the HandleMessageL().
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+void CRoHandler::HandleMessageL
+        (
+        CPushMessage* aPushMsg // push message
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "HandleMessageL(1)" ) ) );
+#endif
+    iPushMsg = aPushMsg;
+    //
+    // Do sanity checks for the message.
+    //
+    User::LeaveIfError( PerformChecks() );
+    iMsgType = CheckMessageTypeL();
+    switch( iMsgType )
+        {
+        case EOma1Ro:
+            {
+            HandleRightsMessageL();
+            break;
+            }
+#ifdef __DRM_OMA2
+        case EOma2RoapTrigger:
+        case EOma2RoapTriggerRoAcquisition:
+            {
+            HandleRoapTriggerL();
+            break;
+            }
+        case EOma2RoapTriggerMetering:
+            {
+            HandleMeteringTriggerSilentlyL();
+            break;
+            }
+        case EOma2RoapPdu:
+            {
+            HandleRoapPduL();
+            break;
+            }
+#endif
+        default:
+            {
+            User::Leave( KErrNotSupported );
+            }
+        }
+
+    iPluginKiller->KillPushPlugin();
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "HandleMessageL(1)-End" ) ) );
+#endif
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: HandleRightsMessageL
+
+    Description: Process rights object and
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+
+void CRoHandler::HandleRightsMessageL()
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "HandleRightsMessageL" ) ) );
+#endif
+
+    HBufC16 *number( NULL );
+    HBufC16 *messageContent( NULL );
+    HBufC16* buffer( NULL );
+
+    TInt ret( 0 );
+    if ( iMessageBodyPtr.Size() == 0 )
+        {
+        User::Leave( KErrCorrupt );
+        }
+
+    // Heap desc contains Content URI
+    HBufC8* contentURI( NULL );
+    TUint32 localId( 0 );
+    RPointerArray< CDRMRights >*
+        rights( new ( ELeave ) RPointerArray< CDRMRights > );
+
+    if ( rights )
+        {
+        // process rights
+        ret = iMessageParser->ProcessRightsObject( iMessageBodyPtr, *rights );
+        }
+    else
+        {
+        User::Leave( KErrNoMemory );
+        }
+
+    if ( !ret && rights->Count() )
+        {
+        TCleanupItem cleanup( DoResetAndDestroy, rights );
+        CleanupStack::PushL( cleanup );
+        ret = ( *rights )[ 0 ]->GetContentURI( contentURI );
+        // null contentURI means invalid RO
+        LeaveIfNullL( ret, contentURI );
+        localId = ( *rights )[ 0 ]->GetLocalID();
+        CleanupStack::PopAndDestroy( rights );
+        rights = NULL;
+        CleanupStack::PushL( contentURI );
+        }
+    else
+        {
+        rights->ResetAndDestroy();
+        delete rights;
+        rights = NULL;
+        User::LeaveIfError( ret );
+        }
+
+    if ( iPutRightsToInbox )
+        {
+        buffer = HBufC16::NewL( contentURI->Length() );
+        TPtr uri16( buffer->Des() );
+        uri16.Copy( *contentURI );
+        CleanupStack::PopAndDestroy( contentURI );
+        contentURI = NULL;
+        CleanupStack::PushL( buffer );
+
+        number = HBufC16::NewLC( 11 ); //longer than max of tuint32
+        TPtr ptr( number->Des() );
+        ptr.AppendNum( localId, EDecimal );
+
+        messageContent = HBufC16::NewL( ptr.Length() + uri16.Length() + 4 );
+        TPtr ptrToMz( messageContent->Des() );
+        ptrToMz.Append( _L( "1 " ) );
+        ptrToMz.Append( ptr ); // add localID
+        ptrToMz.Append( _L( " " ) ); // add space
+        ptrToMz.Append( uri16 ); //add uri16
+
+        CleanupStack::PopAndDestroy( number );
+        CleanupStack::PopAndDestroy( buffer );
+        CleanupStack::PushL( messageContent );
+
+        // create empty sms
+        iMsvId = CreateNewMessageL();
+        SetEntryL( iMsvId );
+        // adds content in sms and moves it inbox
+        AddRoContentL( ptrToMz );
+
+        CleanupStack::PopAndDestroy( messageContent );
+        }
+    else
+        {
+        CleanupStack::PopAndDestroy( contentURI );
+        }
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "HandleRightsMessageL-End" ) ) );
+#endif
+    }
+
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: HandleRoapPduL
+
+    Description: Handles OMA 2.0 ROAP RO Response message
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+void CRoHandler::HandleRoapPduL()
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "HandleRoapPduL" ) ) );
+#endif
+    Roap::CRoapEngBase* roapHandler( NULL );
+    RPointerArray< CDRMRights > rights;
+
+    roapHandler = CRoapEng::NewL();
+    CleanupStack::PushL( roapHandler );
+
+    TCleanupItem cleanup( DoResetAndDestroy, &rights );
+    CleanupStack::PushL( cleanup );
+
+
+    //Parse received rights.
+#ifdef  _DRM_TESTING
+    TRAPD( err, roapHandler->HandleRoReponseL( iMessageBodyPtr, rights ) );
+    TRAP( r, WriteL( _L8( "HandleRoapPduL->HandleRoReponseL done" ), err ) );
+    User::LeaveIfError( err );
+#else
+    roapHandler->HandleRoReponseL( iMessageBodyPtr, rights );
+#endif
+
+
+    //handle parsed rights and save uri into mtm
+    if ( rights.Count() )
+        {
+        HBufC8* contentURI( NULL );
+        HBufC16* buffer( NULL );
+        HBufC16* number( NULL );
+        HBufC16* messageContent( NULL );
+        TUint32 localId( 0 );
+        TInt ret( KErrNone );
+
+#ifdef  _DRM_TESTING
+        TRAP( r, WriteL( _L8( "HandleRoapPduL->CID" ) ) );
+#endif
+        ret = rights[0]->GetContentURI( contentURI );
+        // null contentURI means invalid RO
+        LeaveIfNullL( ret,  contentURI );
+#ifdef  _DRM_TESTING
+        TRAP( r, WriteL( *contentURI ) );
+#endif
+        localId = rights[0]->GetLocalID();
+        CleanupStack::PushL( contentURI );
+        buffer = HBufC16::NewL( contentURI->Length() );
+        TPtr uri16( buffer->Des() );
+        uri16.Copy( *contentURI );
+        CleanupStack::PopAndDestroy( contentURI );
+        contentURI = NULL;
+        CleanupStack::PushL( buffer );
+        number = HBufC16::NewLC( 11 ); //longer than max of tuint32
+        TPtr ptr( number->Des() );
+        ptr.AppendNum( localId, EDecimal );
+        messageContent = HBufC16::NewL( ptr.Length() + uri16.Length() + 4 );
+        TPtr ptrToMz( messageContent->Des() );
+        ptrToMz.Append( _L( "1 " ) );
+        ptrToMz.Append( ptr ); // add localID
+        ptrToMz.Append( _L( " " ) ); // add space
+        ptrToMz.Append( uri16 ); //add uri16
+        CleanupStack::PopAndDestroy( number );
+        CleanupStack::PopAndDestroy( buffer );
+        CleanupStack::PushL( messageContent );
+        // create empty sms
+        iMsvId = CreateNewMessageL();
+        SetEntryL( iMsvId );
+        // adds content in sms and moves it inbox
+        AddRoContentL( ptrToMz );
+        CleanupStack::PopAndDestroy( messageContent );
+        }
+
+    // Finish up
+    CleanupStack::PopAndDestroy( &rights );
+    CleanupStack::PopAndDestroy( roapHandler );
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "HandleRoapPduL-End" ) ) );
+#endif
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: HandleRoapTriggerL
+
+    Description: Handles OMA 2.0 ROAP Trigger message
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+void CRoHandler::HandleRoapTriggerL()
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "HandleRoapTriggerL" ) ) );
+#endif
+
+    _LIT( KFile, "%S%u.tri" );
+    RFile f;
+    TFileName fileName;
+    TPtr ptr( NULL, 0 );
+    HBufC* content( NULL );
+    TInt ret( KErrNone );
+    TInt driveNumber( -1 );
+
+
+    // create empty sms
+    iMsvId = CreateNewMessageL();
+    SetEntryL( iMsvId );
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    driveNumber = EDriveC;
+    ret = iFs.MkDirAll( KRoHandlerTriggerFilePath );
+    fileName.Format( KFile, &KRoHandlerTriggerFilePath, iMsvId );
+
+#else //RD_MULTIPLE_DRIVE
+
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    TFileName roHandlerTriggerFilePath;
+    roHandlerTriggerFilePath.Format(
+                    KRoHandlerTriggerFilePath, ( TUint )driveLetter );
+
+    ret = iFs.MkDirAll( roHandlerTriggerFilePath );
+    fileName.Format( KFile, &roHandlerTriggerFilePath, iMsvId );
+
+#endif
+    if ( ret && ret != KErrAlreadyExists )
+        {
+        User::LeaveIfError( ret );
+        }
+
+    // Create cleanup item for file to be deleted on leave.
+    CFileDeleter* fileDeleter( CFileDeleter::NewLC( iFs, fileName ) );
+
+    // Leave if there is not enough space for file to be created.
+    if ( SysUtil::DiskSpaceBelowCriticalLevelL(
+            &iFs, iMessageBodyPtr.Size(), driveNumber ) )
+        {
+        User::Leave( KErrDiskFull );
+        }
+
+    User::LeaveIfError( f.Replace( iFs, fileName, EFileWrite ) );
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( fileName, iMsvId ) );
+#endif
+    CleanupClosePushL( f );
+    User::LeaveIfError( f.Write( iMessageBodyPtr ) );
+    CleanupStack::PopAndDestroy( &f );
+
+    // Delete created file on leave.
+    fileDeleter->SetDelete();
+
+
+    //format content
+    if ( iMsgType == EOma2RoapTriggerRoAcquisition )
+        {
+#ifdef _DRM_TESTING
+        TRAP( r, WriteL( _L8( "HandleRoapTriggerL->EOma2RoapTriggerRoAcquisition" ) ) );
+#endif
+        content = HBufC::NewLC(
+            fileName.Length() + KRoAcquisitionPrefix().Length() );
+        ptr.Set( content->Des() );
+        ptr.Append( KRoAcquisitionPrefix() );
+        ptr.Append( fileName );
+#ifdef RD_DRM_SILENT_RIGHTS_ACQUISITION
+        // do the ROAP silently, but if it fails, create the inbox entry
+        if ( !DoRoapL( iMessageBodyPtr ) )
+            {
+            AddRoContentL( ptr );
+            }
+#else
+        // adds content in sms and moves it inbox
+        AddRoContentL( ptr );
+#endif
+        CleanupStack::PopAndDestroy( content );
+        }
+    else
+        {
+        content = HBufC::NewLC(
+            fileName.Length() + KTriggerPrefix().Length() );
+        ptr.Set( content->Des() );
+        ptr.Append( KTriggerPrefix() );
+        ptr.Append( fileName );
+        AddRoContentL( ptr );
+        CleanupStack::PopAndDestroy( content );
+        }
+    // No leaves. So keep created file.
+    fileDeleter->SetNoDelete();
+    CleanupStack::PopAndDestroy( fileDeleter );
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( ptr ) );
+#endif
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "HandleRoapTriggerL-End" ) ) );
+#endif
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: CancelHandleMessage
+
+    Description: Cancels the pending asynchronous HandleMessageL.
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+void CRoHandler::CancelHandleMessage
+        (
+        //None.
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "CancelHandleMessage" ) ) );
+#endif
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "CancelHandleMessage-End" ) ) );
+#endif
+    }
+
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: CreateNewMessageL
+
+    Description: Creates a new message server entry and set up default values.
+
+    Return values:      TMsvId (the id of created entry)
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+TMsvId CRoHandler::CreateNewMessageL
+        (
+        //None.
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "CreateNewMessageL" ) ) );
+#endif
+    TMsvEntry newEntry;// This represents an entry in the Message Server index
+    newEntry.iMtm = KUidMsgTypeRO;// message type is RO
+    newEntry.iType = KUidMsvMessageEntry;                   // this defines the type of the entry: message
+    newEntry.iServiceId = KMsvLocalServiceIndexEntryId;     // ID of local service (containing the standard folders)
+    newEntry.iDate.UniversalTime();                         // set the date of the entry to Universal time
+    newEntry.SetVisible( EFalse );
+    newEntry.SetUnread( ETrue );                            // a soft notification would come
+
+    HBufC* detail( GetDetailLC() );
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L( "detail" ) ) );
+    TRAP( r, WriteL( *detail, detail->Des().Length() ) );
+#endif
+
+    HBufC* description( GetDescriptionLC() );
+
+    newEntry.iDetails.Set( detail->Des() );
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L( "newEntry.iDetails:" ) ) );
+    TRAP( r, WriteL( newEntry.iDetails, newEntry.iDetails.Length() ) );
+#endif
+
+    newEntry.iDescription.Set( description->Des() );
+
+    newEntry.SetInPreparation( ETrue );                       // a flag that this message is in preparation
+    //----
+    //newEntry.iBioType = 0x1000ffff;                         // define a bio UID if sending a bio message over SMS bearer
+    //----
+
+    // - CMsvEntry accesses and acts upon a particular Message Server entry.
+    // - NewL() does not create a new entry, but simply a new object to access an existing entry.
+    // - It takes in as parameters the client's message server session,
+    //   ID of the entry to access and initial sorting order of the children of the entry.
+    //
+    CMsvEntry* entry( NULL );
+    entry = CMsvEntry::NewL(
+        *iSession, KMsvDraftEntryIdValue, TMsvSelectionOrdering() );
+    CleanupStack::PushL( entry );
+
+    CMsvOperationActiveSchedulerWait* wait( NULL );
+    wait = CMsvOperationActiveSchedulerWait::NewLC();
+    CMsvOperation* oper( entry->CreateL( newEntry, wait->iStatus ) );
+    CleanupStack::PushL( oper );
+    wait->Start();
+
+    // ...and keep track of the progress of the create operation.
+    TMsvLocalOperationProgress progress(
+        McliUtils::GetLocalProgressL( *oper ) );
+    User::LeaveIfError( progress.iError );
+
+    // Set our entry context to the created one
+    entry->SetEntryL( progress.iId ); // operation progress contains the ID of the ceated entry
+    CleanupStack::PopAndDestroy( oper );
+    CleanupStack::PopAndDestroy( wait );
+    CleanupStack::PopAndDestroy( entry );
+    CleanupStack::PopAndDestroy( description );
+    CleanupStack::PopAndDestroy( detail );
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "CreateNewMessageL-End" ) ) );
+#endif
+    return progress.iId;
+    }
+
+
+
+HBufC* CRoHandler::ConvertDetailsL( const TDesC8& aFrom )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "ConvertDetailsL" ) ) );
+#endif
+    HBufC* from( HBufC::NewMaxLC( aFrom.Length() ) );
+    from->Des().Copy( aFrom );
+
+    TUriParser16 pars;
+    User::LeaveIfError( pars.Parse( *from ) );
+
+    HBufC* res( NULL );
+    if ( pars.IsPresent( EUriHost ) )
+        {
+        res = pars.Extract( EUriHost ).AllocL();
+        }
+    else
+        {
+        res = from->AllocL();
+        }
+
+    CleanupStack::PopAndDestroy( from );
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "ConvertDetailsL-End" ) ) );
+#endif
+    return res;
+    }
+
+void CRoHandler::ReadFromResourceLC(
+            const TDesC& aFile,
+            const TInt& aIndex,
+            HBufC*& aBuf )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "ReadFromResourceLC" ) ) );
+#endif
+    RFs fs;
+    if ( aBuf )
+        {
+        delete aBuf;
+        aBuf = NULL;
+        }
+    User::LeaveIfError( fs.Connect() );
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "ReadFromResourceLC-fs.Connect" ) ) );
+#endif
+    CleanupClosePushL( fs );
+    CStringResourceReader* reader(
+        new ( ELeave ) CStringResourceReader( fs, aFile ) );
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "ReadFromResourceLC-CStringResourceReader" ) ) );
+#endif
+    CleanupStack::PushL( reader );
+    aBuf = reader->AllocReadResourceL( aIndex );
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "ReadFromResourceLC-AllocReadResourceL" ) ) );
+#endif
+    CleanupStack::PopAndDestroy( reader );
+    CleanupStack::PopAndDestroy( &fs );
+    CleanupStack::PushL( aBuf );
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "ReadFromResourceLC-End" ) ) );
+#endif
+    }
+
+HBufC* CRoHandler::GetDetailLC()
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "GetDetailLC" ) ) );
+#endif
+    // Get server address.
+    TPtrC8 srvAddress;
+    TBool flag( iPushMsg->GetServerAddress( srvAddress ) );
+    HBufC* buf( NULL );
+    HBufC* result( NULL );
+
+    // First line in Inbox: TMsvEntry::iDetails.
+    if ( !flag || srvAddress.Length() == 0 )
+        {
+        // Read from resource.
+
+#ifndef RD_MULTIPLE_DRIVE
+
+        TFileName resourceFile( KDriveZ );
+
+#else //RD_MULTIPLE_DRIVE
+
+        _LIT( KDriveRoot, "%c:" );
+        TInt driveNumber( -1 );
+        TChar driveLetter;
+        DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+        iFs.DriveToChar( driveNumber, driveLetter );
+
+        TFileName resourceFile;
+        resourceFile.Format( KDriveRoot, (TUint )driveLetter );
+
+#endif
+
+        resourceFile.Append( KDC_MTM_RESOURCE_DIR );
+        resourceFile.Append( KPushMtmRes );
+        ReadFromResourceLC( resourceFile, R_PUSHMISC_UNK_SENDER, result );
+        }
+    else
+        {
+        // Convert the "From" information to the format required by the UI
+        // spec and then decode it.
+#ifdef _DRM_TESTING
+        TRAP( r, WriteL( _L( "From form: " ) ) );
+        TRAP( r, WriteL( srvAddress, srvAddress.Length() ) );
+#endif
+        buf = ConvertDetailsL( srvAddress );
+#ifdef _DRM_TESTING
+        TRAP( r, WriteL( _L( "Uri form: " ) ) );
+        TRAP( r, WriteL( *buf, buf->Length() ) );
+#endif
+        CleanupStack::PushL( buf );
+        result = ConvertUriToDisplayFormL( *buf );
+#ifdef _DRM_TESTING
+        TRAP( r, WriteL( _L( "Final form: " ) ) );
+        TRAP( r, WriteL( *result, result->Length() ) );
+#endif
+        CleanupStack::PopAndDestroy( buf ); // buf
+        buf = NULL;
+        CleanupStack::PushL( result );
+        }
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "GetDetailLC-End" ) ) );
+#endif
+    return result;
+    }
+
+HBufC* CRoHandler::ConvertUriToDisplayFormL( const TDesC& aUri )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "ConvertUriToDisplayFormL" ) ) );
+#endif
+    HBufC8* uri8( HBufC8::NewMaxLC( aUri.Length() ) );
+    uri8->Des().Copy( aUri );
+    TUriParser8 uriParser8;
+    User::LeaveIfError( uriParser8.Parse( *uri8 ) );
+    CUri16* convertedCUri( UriUtils::ConvertToDisplayFormL( uriParser8 ) );
+    CleanupStack::PopAndDestroy( uri8 );
+    CleanupStack::PushL( convertedCUri );
+    HBufC* convertedUri( convertedCUri->Uri().UriDes().AllocL() );
+    CleanupStack::PopAndDestroy( convertedCUri );
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "ConvertUriToDisplayFormL-End" ) ) );
+#endif
+    return convertedUri;
+    }
+
+HBufC* CRoHandler::GetDescriptionLC()
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "GetDescriptionLC" ) ) );
+#endif
+    HBufC* buf( NULL );
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    TFileName resourceFile( KDriveZ );
+
+#else //RD_MULTIPLE_DRIVE
+
+    _LIT( KDriveRoot, "%c:" );
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    TFileName resourceFile;
+    resourceFile.Format( KDriveRoot, ( TUint )driveLetter );
+
+#endif
+
+    resourceFile.Append( KDC_RESOURCE_FILES_DIR );
+    resourceFile.Append( KRoHandlerResourceFile );
+
+    if ( iMsgType == EOma2RoapTrigger )
+        {
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( resourceFile ) );
+#endif
+        ReadFromResourceLC(
+            resourceFile, R_ROHL_INBOX_DESCRIPTION_ROA, buf );
+        }
+    else
+        {
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( resourceFile ) );
+#endif
+        ReadFromResourceLC( resourceFile, R_ROHL_INBOX_DESCRIPTION, buf );
+        }
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "GetDescriptionLC-End" ) ) );
+#endif
+    return buf;
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: DoCancel
+
+    Description:Cancels the operation.
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+void CRoHandler::DoCancel
+        (
+        //None.
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "DoCancel" ) ) );
+#endif
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "DoCancel-End" ) ) );
+#endif
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: RunL
+
+    Description: Basically all the work is done from/through this method
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+void CRoHandler::RunL
+        (
+        //None.
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "RunL" ) ) );
+#endif
+    // First checking whether cancel has been called
+    if ( iStatus == KErrCancel )
+        {
+        iPluginKiller->KillPushPlugin();
+        return;
+        }
+
+    switch( iMsgType )
+        {
+        case EOma1Ro:
+            {
+            HandleRightsMessageL();
+            break;
+            }
+#ifdef __DRM_OMA2
+        case EOma2RoapTrigger:
+        case EOma2RoapTriggerRoAcquisition:
+            {
+            HandleRoapTriggerL();
+            break;
+            }
+        case EOma2RoapPdu:
+            {
+            HandleRoapPduL();
+            break;
+            }
+#endif
+        default:
+            {
+            User::Leave( KErrNotSupported );
+            }
+        }
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "RunL-End" ) ) );
+#endif
+    }
+/*
+-----------------------------------------------------------------------------
+
+    Method: RunError
+
+    Description: Called by ActiveScheduler in case RunL leaves.
+                 Currently does nothing.
+
+    Return Value: <errorcode>: Currently same as was given as a parameter
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+TInt CRoHandler::RunError
+        (
+        TInt
+#ifdef _DRM_TESTING
+        aError // errorcode
+#endif
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "RunError" ) ) );
+#endif
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "RunError-End" ), aError ) );
+#endif
+    return KErrNone;
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: CPushHandlerBase_Reserved1
+
+    Description: Reserved for future expansion.
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+void CRoHandler::CPushHandlerBase_Reserved1
+        (
+        //None.
+        )
+    {
+    _LIT( KNotSupported, "This method is not supported!" );
+    User::Panic( KNotSupported, KErrNotSupported );
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: CPushHandlerBase_Reserved2
+
+    Description: Reserved for future expansion.
+
+    Return Value: None.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+void CRoHandler::CPushHandlerBase_Reserved2
+        (
+        //None.
+        )
+    {
+    _LIT( KNotSupported, "This method is not supported!" );
+    User::Panic( KNotSupported, KErrNotSupported );
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: PerformChecks
+
+    Description: Checks that message is current type
+
+    Return Value:  TInt: KErrNone if ok else KErrCorrupt.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+TInt CRoHandler::PerformChecks
+        (
+        //None.
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "PerformChecks" ) ) );
+#endif
+    if ( !iPushMsg )
+        {
+        return KErrCorrupt;
+        }
+    // Check that body != NULL
+    TBool bodyPresent( EFalse );
+    // fetch message body
+    bodyPresent = iPushMsg->GetMessageBody( iMessageBodyPtr );
+
+    // 6 == minimum number of message fields. This is a very "mild" check but
+    // at least it guarantees that there is no empty body in the message
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "PerformChecks-End" ) ) );
+#endif
+    if ( ( !bodyPresent ) || ( iMessageBodyPtr.Size() < 6 ) )
+        {
+        return KErrCorrupt;
+        }
+    return KErrNone;
+    }
+
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: CheckMessageTypeL
+
+    Description: Checks the message type
+
+    Return Value:  EOma1Ro, EOma2RoapPdu or EOma2RoapTrigger
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+TMessageType CRoHandler::CheckMessageTypeL
+        (
+        //None.
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "CheckMessageType" ) ) );
+#endif
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "CheckMessageType-End" ) ) );
+#endif
+    TPtrC8 messageBodyPtr( iMessageBodyPtr );
+    TMessageType recognizedMessageType( EOma1Ro );
+    if ( iMessageBodyPtr.FindF( KWbxmlRoapTriggerElement() ) != KErrNotFound  )
+        {
+        iParsedXmlTrigger = iWbxmlTriggerParser->ParseL( iMessageBodyPtr );
+        messageBodyPtr.Set( *iParsedXmlTrigger );
+        }
+    if ( messageBodyPtr.FindF( KRoapTriggerElement() ) != KErrNotFound )
+        {
+        if ( messageBodyPtr.FindF( KRoapTriggerRoAcquisition() ) != KErrNotFound )
+            {
+            recognizedMessageType = EOma2RoapTriggerRoAcquisition;
+            }
+        else if ( messageBodyPtr.FindF( KRoapTriggerMeteringReport() ) != KErrNotFound )
+            {
+            recognizedMessageType = EOma2RoapTriggerMetering;
+            }
+        else
+            {
+            recognizedMessageType = EOma2RoapTrigger;
+            }
+
+        }
+    if ( iMessageBodyPtr.FindF( KRoapRoPduElement() ) != KErrNotFound )
+        {
+        recognizedMessageType = EOma2RoapPdu;
+        }
+    delete iParsedXmlTrigger;
+    iParsedXmlTrigger = NULL;
+    return recognizedMessageType;
+    }
+
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: SetEntryL
+
+    Description: Set up current message entry.
+
+    Note: It can be useful to remember the original entry id for
+          error handling.
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+void  CRoHandler::SetEntryL
+        (
+        TMsvId aEntryId //an entry in the Message Server index
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "SetEntryL" ) ) );
+#endif
+
+    // Get the server entry from our session
+    CMsvEntry* entry( iSession->GetEntryL( aEntryId ) );
+    CleanupStack::PushL( entry );
+
+    // Check if our mtm is different from the mtm set to our entry
+    if ( !iMtm || entry->Entry().iMtm != ( iMtm->Entry() ).Entry().iMtm )
+        {
+        // If so, we delete the old...
+        delete iMtm;
+        iMtm = NULL;
+        // ...and get a new one from the MtmRegistry
+        iMtm = iMtmReg->NewMtmL( entry->Entry().iMtm );
+        }
+    // Set our entry as current.
+    iMtm->SetCurrentEntryL( entry );
+
+    CleanupStack::Pop( entry );
+    entry = NULL;
+
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "SetEntryL-End" ) ) );
+#endif
+    }
+
+/*
+-----------------------------------------------------------------------------
+
+    Method: MoveMessageEntryL
+
+    Description: Moves an entry to another parent.
+
+    Return values: TMsvId of the moved message
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+TMsvId CRoHandler::MoveMessageEntryL
+        (
+        TMsvId aTarget //an entry in the Message Server index
+        )
+    {
+#ifdef _DRM_TESTING
+    TRAPD( r, WriteL( _L8( "MoveMessageEntryL" ) ) );
+#endif
+    TMsvEntry msvEntry( ( iMtm->Entry() ).Entry() );
+    TMsvId id = msvEntry.Id();
+
+    if ( msvEntry.Parent() != aTarget )
+        {
+        TMsvSelectionOrdering sort;
+        sort.SetShowInvisibleEntries( ETrue );    // we want to handle also the invisible entries
+        // Take a handle to the parent entry
+        CMsvEntry* parentEntry(
+            CMsvEntry::NewL( iMtm->Session(), msvEntry.Parent(), sort ) );
+        CleanupStack::PushL( parentEntry );
+
+        // Move original from the parent to the new location
+        CMsvOperationActiveSchedulerWait* wait(
+            CMsvOperationActiveSchedulerWait::NewLC() );
+        CMsvOperation* op(
+            parentEntry->MoveL( msvEntry.Id(), aTarget, wait->iStatus ) );
+        CleanupStack::PushL( op );
+        wait->Start();
+
+        TMsvLocalOperationProgress prog = McliUtils::GetLocalProgressL( *op );
+        User::LeaveIfError( prog.iError );
+        id = prog.iId; // id of the moved entry
+        CleanupStack::PopAndDestroy( op );
+        CleanupStack::PopAndDestroy( wait );
+        CleanupStack::PopAndDestroy( parentEntry );
+        }
+#ifdef _DRM_TESTING
+    TRAP( r, WriteL( _L8( "MoveMessageEntryL-End" ) ) );
+#endif
+    return id;
+    }
+
+TBool CRoHandler::DoRoapL( const TDesC8& aTrigger )
+    {
+    TBool r( EFalse );
+    LOG( _L8( "CRoHandler::DoRoapL ->" ) );
+    LOGHEX( aTrigger.Ptr(), aTrigger.Length() );
+    CRoapSyncWrapper *roap( CRoapSyncWrapper::NewL() );
+    CleanupStack::PushL( roap );
+    r = roap->HandleTriggerSilentlyL( aTrigger );
+    CleanupStack::PopAndDestroy( roap );
+    LOG( _L8( "CRoHandler::DoRoapL <-" ) );
+    return r;
+    }
+
+
+void CRoHandler::HandleMeteringTriggerSilentlyL()
+    {
+    LOG( _L8( "CRoHandler::HandleMeteringTriggerSilentlyL ->" ) );
+    LOGHEX( iMessageBodyPtr.Ptr(), iMessageBodyPtr.Length() );
+
+    if ( iMeteringSupported )
+        {
+        LOG( _L8( "Handling" ) );
+        CRoHandlerDMgrWrapper* dMgrWrapper( CRoHandlerDMgrWrapper::NewL() );
+        CleanupStack::PushL( dMgrWrapper );
+        dMgrWrapper->HandleRoapTriggerL( iMessageBodyPtr );
+        CleanupStack::PopAndDestroy( dMgrWrapper );
+        LOG( _L8( "Handled" ) );
+        }
+    else
+        {
+        LOG( _L8( "Metering trigger not supported --> dropping it" ) );
+        }
+    LOG( _L8( "CRoHandler::HandleMeteringTriggerSilentlyL <-" ) );
+    }
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+/*
+   -----------------------------------------------------------------------------
+
+Method: ImplementationGroupProxy
+
+    Description:
+
+    Return Value: TImplementationProxy*: Implementation table to the
+                  ECOM framework
+
+    Status: Proposal
+
+-----------------------------------------------------------------------------
+*/
+
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy
+        (
+        TInt& aTableCount
+        )
+    {
+    aTableCount =
+        sizeof( ImplementationTable ) / sizeof( TImplementationProxy );
+    return ImplementationTable;
+    }
+
+
+//  End of File