omadrm/drmengine/legacy/src/DRMCommon.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:21:16 +0100
branchRCL_3
changeset 72 1481bf457703
parent 71 1221b68b8a5f
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2002, 2003 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 common DRM operations
*
*/


// INCLUDE FILES

#include <f32file.h>
#include <s32file.h>
#include <apmstd.h>
#include <featmgr.h>
#include <wspdecoder.h>
#include <wspencoder.h>

#include <barsc.h>
#include <barsread.h>

#include <DRMCommon.rsg>

#ifdef RD_MULTIPLE_DRIVE
#include <driveinfo.h>
#endif

#include "DRMCommon.h"
#include "DRMRightsClient.h"
#include "DcfCommon.h"
#include "Oma1Dcf.h"
#include "oma2dcf.h"
#include "DrmPermission.h"

// EXTERNAL DATA STRUCTURES

// EXTERNAL FUNCTION PROTOTYPES

// CONSTANTS

const TInt KBufferSize = 1024;
_LIT8(KRiUrl, "Rights-Issuer");

// MACROS

// LOCAL CONSTANTS AND MACROS

_LIT8(KFLPrefix, "flk:");
_LIT8(KLDPrefix, "ldf:");
_LIT8(KHeaderNameEnding, ":");
_LIT8(KHeaderEnding, "\r\n");

 #ifdef RD_MULTIPLE_DRIVE
_LIT(KDataTypesFile, "%c:\\system\\data\\DataType.dat");
_LIT(KResourceFile, "%c:\\resource\\drmcommon.rsc");
_LIT(KTempFile, "%c:\\system\\temp\\DataType.tmp");
#else
_LIT(KDataTypesFile, "c:\\system\\data\\DataType.dat");
_LIT(KResourceFile, "z:\\resource\\drmcommon.rsc");
_LIT(KTempFile, "c:\\system\\temp\\DataType.tmp");
#endif


// Version of the client

const TUint8 KClientVersionMajor = 1;
const TUint8 KClientVersionMinor = 1;
const TUint16 KClientVersionBuild = 2;

// Which lowest server version is supported

const TUint8 KServerVersionMajor = 1;
const TUint8 KServerVersionMinor = 2;
const TUint16 KServerVersionBuild = 1;

//_LIT(KNullDate,"00000000:000000.000000");


// MODULE DATA STRUCTURES

// LOCAL FUNCTION PROTOTYPES

/*
LOCAL_C TInt CheckContentRightsL(
    const TDesC8& aContentURI,
    TUint32 aRightsSpec);

LOCAL_C TInt IsProtectedContentL(
    const TDesC8& aContent,
    TBool& aProtection);

LOCAL_C TInt GetNewHeaderBuffer(
    HBufC8*& aOldHeaderBuf,
    const TDesC8& aHeaderName,
    const TDesC8& aHeaderValue,
    HBufC8*& aNewHeaderBuf
    );

LOCAL_C TInt WriteNewFile(
    TFileName aFileName,
    HBufC8*& aHeaderBuf,
    TUint32& aFirstPartLength,
    TUint32& aDataLength,
    TUint32& aDataPartPos
    );

LOCAL_C TInt GetContentURIListL(
    RPointerArray<HBufC8>*& aURIList);

LOCAL_C TInt DataTypesCountL(
    TInt& aCount);

LOCAL_C TInt SupportedDataTypeL(
    const TInt aIndex, TDataType& aDataType);

LOCAL_C TInt StaticDataTypesCountL(
    TInt& aCount);

LOCAL_C TInt RegisterDataTypeL(
    const TDataType& aDataType);

LOCAL_C TInt UnRegisterDataTypeL(
    const TInt aIndex);

*/

LOCAL_C void GetActiveRightsL(
    const TDesC8& aContentURI,
    TUint32 aRightsSpec,
    CDRMRights*& aRightsObject);

LOCAL_C TInt CheckFileRightsL(
    const TDesC& aFileName,
    TUint32 aRightsSpec);

LOCAL_C TInt CheckFileRightsL(
    RFile& aFileHandle,
    TUint32 aRightsSpec);

LOCAL_C TInt IsProtectedFileL(
    const TDesC& aFileName,
    TBool& aProtection);

LOCAL_C TInt IsProtectedFileL(
    RFile& aFileHandle,
    TBool& aProtection);

LOCAL_C TInt GetContentInfoL(
    const TDesC8& aContent,
    DRMCommon::TContentProtection& aProtection,
    HBufC8*& aMIMEType,
    HBufC8*& aContentURI,
    TUint& aDataLength);

LOCAL_C TInt GetFileInfoL(
    const TDesC& aFileName,
    DRMCommon::TContentProtection& aProtection,
    HBufC8*& aMIMEType,
    HBufC8*& aContentURI,
    TUint& aDataLength);

LOCAL_C TInt GetFileInfoL(
    RFile& aFileHandle,
    DRMCommon::TContentProtection& aProtection,
    HBufC8*& aMIMEType,
    HBufC8*& aContentURI,
    TUint& aDataLength);

LOCAL_C void GetContentHeaderL(
    const TDesC8& aContent,
    const TDesC8& aHeaderName,
    HBufC8*& aHeaderValue);

LOCAL_C void GetFileHeaderL(
    const TFileName& aFileName,
    const TDesC8& aHeaderName,
    HBufC8*& aHeaderValue);

LOCAL_C void GetFileHeaderL(
    RFile& aFileHandle,
    const TDesC8& aHeaderName,
    HBufC8*& aHeaderValue);

LOCAL_C void SetContentHeaderL(
    HBufC8*& aContent,
    const TDesC8& aHeaderName,
    const TDesC8& aHeaderValue);

LOCAL_C void SetFileHeaderL(
    const TDesC16& aFileName,
    const TDesC8& aHeaderName,
    const TDesC8& aHeaderValue);

LOCAL_C void SetFileHeaderL(
    RFile& aFileHandle,
    const TDesC8& aHeaderName,
    const TDesC8& aHeaderValue);

LOCAL_C void GetSingleRightsObjectL(
    const TDesC8& aContentURI,
    TUint32 aLocalID,
    CDRMRights*& aRightsObject);

LOCAL_C void GetDetailedContentRightsL(
    const TDesC8& aContentURI,
    RPointerArray<CDRMRights>*& aRightsList);

LOCAL_C void GetDetailedFileRightsL(
    const TDesC& aFileName,
    RPointerArray<CDRMRights>*& aRightsList);

LOCAL_C void GetDetailedFileRightsL(
    RFile& aFileHandle,
    RPointerArray<CDRMRights>*& aRightsList);

LOCAL_C TInt RegisterDynamicDataTypeL(
    const TDataType& aDataType);

LOCAL_C TInt UnRegisterDynamicDataTypeL(
    const TInt aIndex);

LOCAL_C TInt CalculatePaddingL(
    COma1Dcf* dcf);

LOCAL_C void DoResetAndDestroy( TAny* aPtr );


LOCAL_C TInt GetFileHandleRead(
    RFs& aFileServer,
    RFile& aFile,
    const TDesC& aFileName );

LOCAL_C void AddParents(
    DRMCommon* aDrmCommon,
    RPointerArray<CDRMRights>& aRights );

// FORWARD DECLARATIONS

using namespace ContentAccess;

// ============================= LOCAL FUNCTIONS ===============================

// ----------------------------------------------------------------------------
// DoResetAndDestroy
// Does RPointerArray< >->ResetAndDestroy() for the given array aPtr.
// ----------------------------------------------------------------------------
//
LOCAL_C void DoResetAndDestroy( TAny* aPtr )
    {
    ( reinterpret_cast< RPointerArray< CDRMPermission >* >( aPtr ) )->
        ResetAndDestroy();
    }


// -----------------------------------------------------------------------------
// GetPermission
// -----------------------------------------------------------------------------
LOCAL_C void GetPermission(
    RDRMRightsClient& aClient,
    const TDesC8& aUri,
    TIntent aIntent,
    CDRMPermission*& aPermission )
    {
    TInt r = KErrNone;
    CDRMPermission* permission = NULL;
    TUint32 reason = 0;

    TRAP( r, permission = aClient.GetActiveRightsL( aIntent, aUri, reason ) );
    if ( permission != NULL )
        {
        if ( aPermission == NULL )
            {
            TRAP_IGNORE( aPermission = CDRMPermission::NewL() );
            }
        aPermission->Merge( *permission );
        delete permission;
        }
    }

// -----------------------------------------------------------------------------
// GetActiveRightsL
// Returns a possible active rights object. Adopts to broken callers who still
// use a bitmask for intent.
// -----------------------------------------------------------------------------
void GetActiveRightsL(
    const TDesC8& aContentURI,
    TUint32 aConstraints,
    CDRMRights*& aRightsObject)
    {
    CDRMPermission* permission = NULL;
    RDRMRightsClient client;
    HBufC8* uri = NULL;

    User::LeaveIfError( client.Connect() );
    CleanupClosePushL( client );

    if ( aConstraints == 0 )
        {
        GetPermission( client, aContentURI, EView, permission );
        GetPermission( client, aContentURI, EPlay, permission );
        GetPermission( client, aContentURI, EExecute, permission );
        GetPermission( client, aContentURI, EPrint, permission );
        }
    else
        {
        GetPermission( client, aContentURI, static_cast<TIntent>( aConstraints ), permission );
        }

    if ( permission != NULL )
        {
        CleanupStack::PushL( permission );
        aRightsObject = CDRMRights::NewL();
        CleanupStack::PushL( aRightsObject );
        uri = aContentURI.AllocL();
        CleanupStack::PushL( uri );
        aRightsObject->SetPermissionL( *permission );
        aRightsObject->SetContentURI( uri );
        CleanupStack::Pop( uri );
        CleanupStack::Pop( aRightsObject );
        CleanupStack::PopAndDestroy( permission );
        }
    else
        {
        aRightsObject = NULL;
        User::Leave( KErrCANoRights );
        }
    CleanupStack::PopAndDestroy(); // client
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
LOCAL_C TInt IsProtectedFileL(
    const TDesC& aFileName,
    TBool& aProtection)
    {
    RFs fs;
    RFile file;
    TInt r = KErrNone;
    CDcfCommon* dcf = NULL;

    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);


    r = GetFileHandleRead( fs, file, aFileName );
    User::LeaveIfError(r);

    CleanupClosePushL(file);
    dcf = CDcfCommon::NewL(file);
    if (dcf != NULL)
        {
        aProtection = ETrue;
        delete dcf;
        }
    else
        {
        aProtection = EFalse;
        }
    CleanupStack::PopAndDestroy(2); // file, fs
    return r;
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
LOCAL_C TInt IsProtectedFileL(
    RFile& aFileHandle,
    TBool& aProtection)
    {
    TInt r = KErrNone;
    CDcfCommon* dcf = NULL;

    dcf = CDcfCommon::NewL(aFileHandle);
    if (dcf != NULL)
        {
        aProtection = ETrue;
        delete dcf;
        }
    else
        {
        aProtection = EFalse;
        }
    return r;
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
TInt GetContentInfoL(
    const TDesC8& aContent,
    DRMCommon::TContentProtection& aProtection,
    HBufC8*& aMIMEType,
    HBufC8*& aContentURI,
    TUint& aDataLength)
    {
    TInt r = KErrNone;
    COma1Dcf* dcf = NULL;
    TRAP(r, dcf = COma1Dcf::NewL(aContent));
    if (dcf != NULL)
        {
        CleanupStack::PushL( dcf );

        if (dcf->iContentID->Left(4).Compare(KLDPrefix) == 0 ||
            dcf->iContentID->Left(4).Compare(KFLPrefix) == 0 ||
            dcf->iRightsIssuerURL == NULL)
            {
            aProtection = DRMCommon::EForwardLocked;
            }
        else
            {
            aProtection = DRMCommon::ESuperDistributable;
            }
        if (dcf->iContentID != NULL)
            {
            aContentURI = dcf->iContentID->AllocL();
            }
        else
            {
            aContentURI = NULL;
            }
        if (dcf->iMimeType != NULL)
            {
            aMIMEType = dcf->iMimeType->AllocL();
            }
        else
            {
            aMIMEType = NULL;
            }

        CalculatePaddingL(dcf);
        aDataLength = dcf->iPlainTextLength;
        CleanupStack::PopAndDestroy();
        }
    else
        {
        aProtection = DRMCommon::ENoDCFFile;
        if (r == KErrArgument)
            {
            r = KErrNone;
            }
        User::LeaveIfError(r);
        }

    return r;
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
TInt GetFileInfoL(
    const TDesC& aFileName,
    DRMCommon::TContentProtection& aProtection,
    HBufC8*& aMIMEType,
    HBufC8*& aContentURI,
    TUint& aDataLength)
    {
    RFs fs;
    RFile file;
    TInt r = KErrNone;
    CDcfCommon* dcf = NULL;
    COma2Dcf* dcf2 = NULL;
    CData* data = NULL;

    aProtection = DRMCommon::ENoDCFFile;
    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);

    r = GetFileHandleRead( fs, file, aFileName );
    User::LeaveIfError(r);
    CleanupClosePushL(file);

    dcf = CDcfCommon::NewL(file);
    if (dcf != NULL)
        {
        CleanupStack::PushL(dcf);
        if (dcf->iVersion == EOma2Dcf)
            {
            dcf2 = static_cast<COma2Dcf*>(dcf);
            }

        if (dcf->iContentID->Left(4).Compare(KLDPrefix) == 0 ||
            dcf->iContentID->Left(4).Compare(KFLPrefix) == 0 ||
            dcf->iRightsIssuerURL == NULL)
            {
            aProtection = DRMCommon::EForwardLocked;
            }
        else
            {
            aProtection = DRMCommon::ESuperDistributable;
            }
        if (dcf->iContentID != NULL)
            {
            aContentURI = dcf->iContentID->AllocL();
            }
        else
            {
            aContentURI = NULL;
            }
        if (dcf->iMimeType != NULL)
            {
            aMIMEType = dcf->iMimeType->AllocL();
            }
        else
            {
            aMIMEType = NULL;
            }

        // Insert domain RO if it exists
        if (dcf2 != NULL && dcf2->iRightsObjects.Count() > 0)
            {
            // Creating a CData object will insert the domain RO into the RDB
            data = CData::NewL(file, KDefaultContentObject);
            delete data;
            }

        if (dcf->iVersion == EOma1Dcf && !dcf->iPlainTextLengthValid)
            {
            CalculatePaddingL(static_cast<COma1Dcf*>(dcf));
            }

        aDataLength = dcf->iPlainTextLength;
        CleanupStack::PopAndDestroy(); // dcf
        }
    CleanupStack::PopAndDestroy(2); // file, fs
    return r;
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
TInt GetFileInfoL(
    RFile& aFileHandle,
    DRMCommon::TContentProtection& aProtection,
    HBufC8*& aMIMEType,
    HBufC8*& aContentURI,
    TUint& aDataLength)
    {
    TInt r = KErrNone;
    CDcfCommon* dcf = NULL;
    COma2Dcf* dcf2 = NULL;
    CData* data = NULL;
    TInt initialPos = 0;

    // Store the initial filePos
    User::LeaveIfError(aFileHandle.Seek(ESeekCurrent, initialPos));

    aProtection = DRMCommon::ENoDCFFile;

    dcf = CDcfCommon::NewL(aFileHandle);
    if (dcf != NULL)
        {
        CleanupStack::PushL(dcf);
        if (dcf->iVersion == EOma2Dcf)
            {
            dcf2 = static_cast<COma2Dcf*>(dcf);
            }

        if (dcf->iContentID->Left(4).Compare(KLDPrefix) == 0 ||
            dcf->iContentID->Left(4).Compare(KFLPrefix) == 0 ||
            dcf->iRightsIssuerURL == NULL)
            {
            aProtection = DRMCommon::EForwardLocked;
            }
        else
            {
            aProtection = DRMCommon::ESuperDistributable;
            }
        if (dcf->iContentID != NULL)
            {
            aContentURI = dcf->iContentID->AllocL();
            }
        else
            {
            aContentURI = NULL;
            }
        if (dcf->iMimeType != NULL)
            {
            aMIMEType = dcf->iMimeType->AllocL();
            }
        else
            {
            aMIMEType = NULL;
            }

        // Insert domain RO if it exists
        if (dcf2 != NULL && dcf2->iRightsObjects.Count() > 0)
            {
            // Creating a CData object will insert the domain RO into the RDB
            data = CData::NewL(aFileHandle, KDefaultContentObject);
            delete data;
            }

        if (dcf->iVersion == EOma1Dcf && !dcf->iPlainTextLengthValid)
            {
            CalculatePaddingL(static_cast<COma1Dcf*>(dcf));
            }

        aDataLength = dcf->iPlainTextLength;
        CleanupStack::PopAndDestroy(); // dcf
        }
    // Restore filePos
    User::LeaveIfError(aFileHandle.Seek(ESeekStart, initialPos));
    return r;
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
TInt CheckFileRightsL(
    const TDesC& aFileName,
    TUint32 aRightsSpec)
    {
    RFs fs;
    RFile file;
    CDcfCommon* dcf = NULL;
    TInt r = DRMCommon::ENoRights;
    RDRMRightsClient client;
    TUint32 reason = 0;

    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);

    r = GetFileHandleRead(fs, file, aFileName);
    User::LeaveIfError(r);
    CleanupClosePushL(file);

    dcf = CDcfCommon::NewL(file);
    if ( dcf == NULL )
        {
        User::Leave(KErrArgument);
        }
    CleanupStack::PushL(dcf);
    User::LeaveIfError(client.Connect());
    CleanupClosePushL(client);
    r = client.CheckRights(aRightsSpec, *dcf->iContentID, reason);
    CleanupStack::PopAndDestroy(4); // dcf, file, client, fs
    return r;
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
TInt CheckFileRightsL(
    RFile& aFileHandle,
    TUint32 aRightsSpec)
    {
    CDcfCommon* dcf = NULL;
    TInt r = DRMCommon::ENoRights;
    RDRMRightsClient client;
    TUint32 reason = 0;

    dcf = CDcfCommon::NewL(aFileHandle);
    if ( dcf == NULL )
        {
        User::Leave(KErrArgument);
        }
    CleanupStack::PushL(dcf);
    User::LeaveIfError(client.Connect());
    CleanupClosePushL(client);
    r = client.CheckRights(aRightsSpec, *dcf->iContentID, reason);
    CleanupStack::PopAndDestroy(2); // dcf, file
    return r;
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
void GetSingleRightsObjectL(
    const TDesC8& aContentURI,
    TUint32 aLocalID,
    CDRMRights*& aRightsObject)
    {
    RDRMRightsClient client;
    CDRMPermission* p = NULL;
    CDRMAsset* a = NULL;

    aRightsObject = NULL;
    User::LeaveIfError(client.Connect());
    CleanupClosePushL(client);

    aRightsObject = CDRMRights::NewL();
    CleanupStack::PushL(aRightsObject);

    p = client.GetDbEntryL(aContentURI, aLocalID);
    CleanupStack::PushL(p);
    aRightsObject->SetPermissionL(*p);
    CleanupStack::PopAndDestroy(); // p

    a = CDRMAsset::NewLC();
    aRightsObject->SetAssetL(*a);
    CleanupStack::PopAndDestroy();

    aRightsObject->SetContentURIAndLocalID(aContentURI.AllocL(), aLocalID);
    CleanupStack::Pop(); // aRightsObject
    CleanupStack::PopAndDestroy(); // client
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
void GetDetailedContentRightsL(
    const TDesC8& aContentURI,
    RPointerArray<CDRMRights>*& aRightsList)
    {
    RDRMRightsClient client;
    RPointerArray<CDRMPermission> rights;
    CDRMRights* ro = NULL;
    CDRMAsset* a  = NULL;
    TInt i;
    // Need a temporary pointer
    HBufC8* contentId = NULL;

    aRightsList = NULL;
    User::LeaveIfError(client.Connect());
    CleanupClosePushL(client);

    client.GetDBEntriesL(aContentURI, rights);

    TCleanupItem cleanup( DoResetAndDestroy, &rights );
    CleanupStack::PushL( cleanup );

    aRightsList = new(ELeave) RPointerArray<CDRMRights>(rights.Count());

    // Push the actual pointer reserved with NewL in
    CleanupStack::PushL( aRightsList );

    // Push the cleanup of the items as well into the cleanup stack
    TCleanupItem cleanup2( DoResetAndDestroy, aRightsList );
    CleanupStack::PushL( cleanup2 );

    for (i = 0; i < rights.Count(); i++)
        {
        // Needs to be pushed to the cleanup stack
        ro = CDRMRights::NewL();
        CleanupStack::PushL(ro);

        // Push to cleanp stack
        a = CDRMAsset::NewLC();

        // Set asset
        ro->SetAssetL(*a);

        // Destroy asset
        CleanupStack::PopAndDestroy(); // Asset

        // Set the permission, copies the object
        ro->SetPermissionL(*rights[i]);

        // take a copy of the content id
        contentId = aContentURI.AllocL();

        // set content uri and local id
        ro->SetContentURIAndLocalID(contentId, rights[i]->iUniqueID);

        // Append the ro to the rights list
        aRightsList->AppendL(ro);

        // Take the ro out of the cleanup stack
        CleanupStack::Pop(ro);
        }

    CleanupStack::Pop(2); // aRightsList ( two items )
    CleanupStack::PopAndDestroy(2); // rights, client
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
void GetDetailedFileRightsL(
    const TDesC& aFileName,
    RPointerArray<CDRMRights>*& aRightsList)
    {

    CDcfCommon* dcf = NULL;
    RFile file;
    RFs fs;
    TInt r = KErrNone;

    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);

    r = GetFileHandleRead( fs, file, aFileName );
    User::LeaveIfError(r);
    CleanupClosePushL(file);


    dcf = CDcfCommon::NewL(file);
    if (dcf == NULL)
        {
        User::Leave(KErrArgument);
        }
    CleanupStack::PushL(dcf);
    GetDetailedContentRightsL(*dcf->iContentID, aRightsList);
    CleanupStack::PopAndDestroy(3); // dcf, file, client

    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
void GetDetailedFileRightsL(
    RFile& aFileHandle,
    RPointerArray<CDRMRights>*& aRightsList)
    {
    CDcfCommon* dcf = NULL;

    dcf = CDcfCommon::NewL(aFileHandle);
    if (dcf == NULL)
        {
        User::Leave(KErrArgument);
        }
    CleanupStack::PushL(dcf);
    GetDetailedContentRightsL(*dcf->iContentID, aRightsList);
    CleanupStack::PopAndDestroy(); // dcf
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
LOCAL_C void  GetNewHeaderBufferL(
    HBufC8*& aOldHeaderBuf,
    const TDesC8& aHeaderName,
    const TDesC8& aHeaderValue,
    HBufC8*& aNewHeaderBuf
    )
    {
    TInt oldHeaderValueLength = 0;
    TInt offset = 0;
    TPtr8 headerPtr(aOldHeaderBuf->Des());
    TPtr8 headerNamePtr(NULL, 0, 0);
    TPtr8 newHeaderPtr(NULL, 0, 0);

    HBufC8* headerName = HBufC8::NewL(aHeaderName.Length() + 1);
    // Find the position of the text in the header
    headerNamePtr.Set(headerName->Des());
    headerNamePtr.Copy(aHeaderName);
    headerNamePtr.Append(KHeaderNameEnding);
    offset = headerPtr.FindF(headerNamePtr);
    delete headerName;
    headerName = NULL;
    if (offset != KErrNotFound)
        {
        // All fields end with CRLF, search for the end of the field and if it is not found
        // return KErrArgument
        oldHeaderValueLength = headerPtr.Right(headerPtr.Length() -
            (offset + aHeaderName.Length() + 1)).Find(KHeaderEnding);
        User::LeaveIfError(oldHeaderValueLength);
        // reserve new buffer for the header, might be useless if the lengths are the same
        aNewHeaderBuf = HBufC8::NewL(headerPtr.Length() - oldHeaderValueLength +
            aHeaderValue.Length());
        newHeaderPtr.Set(aNewHeaderBuf->Des());
        newHeaderPtr.Copy(headerPtr.Left(offset + aHeaderName.Length() + 1));
        newHeaderPtr.Append(aHeaderValue);
        newHeaderPtr.Append(headerPtr.Right(headerPtr.Length() -
            (offset + aHeaderName.Length() + 1 + oldHeaderValueLength)));
        }
    else
        {
        aNewHeaderBuf = HBufC8::NewL(headerPtr.Length() + aHeaderName.Length() +
            aHeaderValue.Length() + 3);
        newHeaderPtr.Set(aNewHeaderBuf->Des());
        newHeaderPtr.Copy(headerPtr);
        newHeaderPtr.Append(aHeaderName);
        newHeaderPtr.Append(KHeaderNameEnding);
        newHeaderPtr.Append(aHeaderValue);
        newHeaderPtr.Append(KHeaderEnding);
        }
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
LOCAL_C void WriteNewFileL(
    RFs& aFs,
    RFile& aOriginalFile,
    const TDesC& aOriginalFileName,
    COma1Dcf& aDcf,
    TFileName& aTempFileName )
    {
    TPtrC tempFilePath;
    HBufC8* buffer = NULL;
    RFileWriteStream temp;
    TPtr8 ptr(NULL, 0, 0);
    TInt offset = 0;

    // Find the path of the file to be modified and put the tempfile
    // into that directory
    tempFilePath.Set(aOriginalFileName.Left(
        aOriginalFileName.LocateReverse('\\') + 1));
    User::LeaveIfError(temp.Temp(aFs, tempFilePath, aTempFileName, EFileWrite));
    CleanupClosePushL( temp );

    temp.WriteUint8L(1);
    temp.WriteUint8L(aDcf.iMimeType->Length());
    temp.WriteUint8L(aDcf.iContentID->Length());
    temp.WriteL(*aDcf.iMimeType);
    temp.WriteL(*aDcf.iContentID);
    buffer = TWspPrimitiveEncoder::UintVarL(aDcf.iHeaders->Length());
    CleanupStack::PushL(buffer);
    temp.WriteL(*buffer);
    CleanupStack::PopAndDestroy(buffer);
    buffer = TWspPrimitiveEncoder::UintVarL(aDcf.iDataLength);
    CleanupStack::PushL(buffer);
    temp.WriteL(*buffer);
    CleanupStack::PopAndDestroy(buffer);
    temp.WriteL(*aDcf.iHeaders);

    offset = aDcf.iOffset;
    User::LeaveIfError(aOriginalFile.Seek(ESeekStart, offset));
    buffer = HBufC8::NewLC(KBufferSize);
    do
        {
        ptr.Set(buffer->Des());
        ptr.SetLength(0);
        aOriginalFile.Read(ptr);
        if (ptr.Length() > 0)
            {
            temp.WriteL(ptr);
            }
        }
    while (ptr.Length() > 0);
    temp.CommitL();
    CleanupStack::PopAndDestroy(); // temp
    CleanupStack::PopAndDestroy(); //buffer
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
LOCAL_C void WriteNewFileL(
    RFs& aFs,
    RFile& aOriginalFile,
    COma1Dcf& aDcf)
    {
    TPtrC tempFilePath;
    HBufC8* buffer = NULL;
    RFile tempFileHandle;
    RFileWriteStream temp;
    RFileWriteStream orig;
    TFileName tempFile;
    TPtr8 ptr(NULL, 0, 0);
    TInt offset = 0;
    TInt fileSize = 0;

    // Find the path of the file to be modified and put the tempfile
    // into that directory
    tempFilePath.Set(_L("C:\\"));
    User::LeaveIfError( temp.Temp( aFs, tempFilePath, tempFile,
                        EFileWrite));
    CleanupClosePushL( temp );

    temp.WriteUint8L(1);
    temp.WriteUint8L(aDcf.iMimeType->Length());
    temp.WriteUint8L(aDcf.iContentID->Length());
    temp.WriteL(*aDcf.iMimeType);
    temp.WriteL(*aDcf.iContentID);
    buffer = TWspPrimitiveEncoder::UintVarL(aDcf.iHeaders->Length());
    CleanupStack::PushL(buffer);
    temp.WriteL(*buffer);
    CleanupStack::PopAndDestroy(buffer);
    buffer = TWspPrimitiveEncoder::UintVarL(aDcf.iDataLength);
    CleanupStack::PushL(buffer);
    temp.WriteL(*buffer);
    CleanupStack::PopAndDestroy(buffer);
    temp.WriteL(*aDcf.iHeaders);

    offset = aDcf.iOffset;
    User::LeaveIfError(aOriginalFile.Seek(ESeekStart, offset));
    buffer = HBufC8::NewLC(KBufferSize);
    do
        {
        ptr.Set(buffer->Des());
        ptr.SetLength(0);
        aOriginalFile.Read(ptr);
        if (ptr.Length() > 0)
            {
            temp.WriteL(ptr);
            }
        }
    while (ptr.Length() > 0);
    temp.CommitL();

    CleanupStack::PopAndDestroy(2); //buffer, temp
    // Get the size of the temp file


    User::LeaveIfError( tempFileHandle.Open( aFs, tempFile, EFileRead ));
    CleanupClosePushL( tempFileHandle );
    tempFileHandle.Size( fileSize );


    // Set the fileSize of the original file
    User::LeaveIfError( aOriginalFile.SetSize( fileSize ) );
    offset = 0;
    User::LeaveIfError( tempFileHandle.Seek( ESeekStart, offset ) );
    orig.Attach( aOriginalFile );
    CleanupClosePushL( orig );

    buffer = HBufC8::NewLC(KBufferSize);
    // Copy the file over because we can't use other copy things:
    do
        {
        ptr.Set(buffer->Des());
        ptr.SetLength(0);
        tempFileHandle.Read(ptr);
        if (ptr.Length() > 0)
            {
            orig.WriteL(ptr);
            }
        }
    while (ptr.Length() > 0);

    // Write the changes
    orig.CommitL();

    // close the tempfile
    CleanupStack::PopAndDestroy(3); // buffer, tempFileHandle, orig

    // Delete the temp file
    User::LeaveIfError( aFs.Delete( tempFile ) );
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
LOCAL_C void SetFileHeaderL(
    const TDesC16& aFileName,
    const TDesC8& aHeaderName,
    const TDesC8& aHeaderValue)
    {
    __UHEAP_MARK;
    TFileName tempFileName;
    HBufC8* newHeaderBuf = NULL;
    COma1Dcf* dcf = NULL;
    RFs fs;
    RFile file;

    User::LeaveIfError( fs.Connect() );
    CleanupClosePushL(fs);
    User::LeaveIfError( GetFileHandleRead( fs, file, aFileName ) );

    CleanupClosePushL(file);
    dcf = COma1Dcf::NewL(file);

    CleanupStack::PushL(dcf);
    GetNewHeaderBufferL(dcf->iHeaders, aHeaderName, aHeaderValue, newHeaderBuf);
    delete dcf->iHeaders;
    dcf->iHeaders = newHeaderBuf;
    dcf->iHeaderLength = newHeaderBuf->Length();
    WriteNewFileL( fs, file, aFileName, *dcf, tempFileName );
    CleanupStack::PopAndDestroy(2); // file, dcf
    User::LeaveIfError( fs.Replace( tempFileName, aFileName ) );
    CleanupStack::PopAndDestroy(); // fs

    __UHEAP_MARKEND;
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
LOCAL_C void SetFileHeaderL(
    RFile& aFileHandle,
    const TDesC8& aHeaderName,
    const TDesC8& aHeaderValue)
    {
    HBufC8* newHeaderBuf = NULL;
    COma1Dcf* dcf = NULL;
    RFs fs;

    User::LeaveIfError(fs.Connect());
    CleanupClosePushL( fs );

    dcf = COma1Dcf::NewL(aFileHandle);
    if (dcf == NULL)
        {
        User::Leave(KErrArgument);
        }
    CleanupStack::PushL(dcf);
    GetNewHeaderBufferL(dcf->iHeaders, aHeaderName, aHeaderValue, newHeaderBuf);
    delete dcf->iHeaders;
    dcf->iHeaders = newHeaderBuf;
    dcf->iHeaderLength = newHeaderBuf->Length();
    WriteNewFileL(fs, aFileHandle, *dcf);
    CleanupStack::PopAndDestroy(2); // dcf, fs
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
void SetContentHeaderL(
    HBufC8*& aContent,
    const TDesC8& aHeaderName,
    const TDesC8& aHeaderValue)
    {
    HBufC8* newHeaderBuf = NULL;
    HBufC8* newContent = NULL;
    HBufC8* buffer;
    COma1Dcf* dcf = NULL;
    TPtr8 ptr(0, 0);

    dcf = COma1Dcf::NewL(*aContent);
    if (dcf == NULL)
        {
        User::Leave(KErrArgument);
        }
    CleanupStack::PushL(dcf);
    GetNewHeaderBufferL(dcf->iHeaders, aHeaderName, aHeaderValue, newHeaderBuf);
    delete dcf->iHeaders;
    dcf->iHeaders = newHeaderBuf;
    dcf->iHeaderLength = newHeaderBuf->Length();
    newContent = HBufC8::NewLC(3 +
        dcf->iContentID->Length() + dcf->iMimeType->Length() + 2 * 5 +
        dcf->iHeaderLength + dcf->iDataLength);
    ptr.Set(newContent->Des());
    ptr.Append(1);
    ptr.Append(dcf->iMimeType->Length());
    ptr.Append(dcf->iContentID->Length());
    ptr.Append(*dcf->iMimeType);
    ptr.Append(*dcf->iContentID);
    buffer = TWspPrimitiveEncoder::UintVarL(dcf->iHeaders->Length());
    CleanupStack::PushL(buffer);
    ptr.Append(*buffer);
    CleanupStack::PopAndDestroy(buffer);
    buffer = TWspPrimitiveEncoder::UintVarL(dcf->iDataLength);
    CleanupStack::PushL(buffer);
    ptr.Append(*buffer);
    CleanupStack::PopAndDestroy(buffer);
    ptr.Append(*dcf->iHeaders);
    ptr.Append(aContent->Right(dcf->iDataLength));
    CleanupStack::Pop(newContent);
    CleanupStack::PopAndDestroy(dcf);
    delete aContent;
    aContent = newContent;
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
void GetHeaderL(
    const TDesC8& aContent,
    const TDesC8& aHeaderName,
    HBufC8*& aHeaderValue)
    {

    TInt i;
    TInt j;
    TPtrC8 ptr( aContent );

    // Add Room for CRLF and Semicolon:
    HBufC8* buffer = HBufC8::NewMaxLC( aHeaderName.Length() + 3 );
    TPtr8 searchBuf( const_cast<TUint8*>(buffer->Ptr()), 0, buffer->Des().MaxSize() );

    searchBuf.Copy(aHeaderName);
    searchBuf.Append(KHeaderNameEnding);

    // First see if the
    i = ptr.Find(searchBuf);
    User::LeaveIfError( i );

    if( i > 0 )
        {
        // if it's not the first one, use the search buffer:
        // Create the search buffer
        searchBuf.Copy(KHeaderEnding);
        searchBuf.Append(aHeaderName);
        searchBuf.Append(KHeaderNameEnding);

        // First see if the
        i = ptr.Find(searchBuf);
        User::LeaveIfError( i );
        }
    // Move search buffer
    i += searchBuf.Length();

    j = ptr.Mid(i).Find(KHeaderEnding);
    User::LeaveIfError( j );

    aHeaderValue = ptr.Mid(i, j).AllocL();
    CleanupStack::PopAndDestroy(); // buffer
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
void GetContentHeaderL(
    const TDesC8& aContent,
    const TDesC8& aHeaderName,
    HBufC8*& aHeaderValue)
    {
    COma1Dcf* dcf = NULL;

    dcf = COma1Dcf::NewL(aContent);
    CleanupStack::PushL(dcf);
    GetHeaderL(*dcf->iHeaders, aHeaderName, aHeaderValue);
    CleanupStack::PopAndDestroy(); // dcf
    }
// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
void GetFileHeaderL(
    const TFileName& aFileName,
    const TDesC8& aHeaderName,
    HBufC8*& aHeaderValue)
    {
    RFs fs;
    RFile file;

    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);
    User::LeaveIfError( GetFileHandleRead( fs, file, aFileName ) );

    CleanupClosePushL(file);
    GetFileHeaderL(file, aHeaderName, aHeaderValue);
    CleanupStack::PopAndDestroy(2); // fs, file
    }

// -----------------------------------------------------------------------------
//
//
// Parameters:
//
// Returns:
// -----------------------------------------------------------------------------
void GetFileHeaderL(
    RFile& aFileHandle,
    const TDesC8& aHeaderName,
    HBufC8*& aHeaderValue)
    {
    CDcfCommon* dcf = NULL;

    aHeaderValue = NULL;
    dcf = CDcfCommon::NewL(aFileHandle);
    if (dcf == NULL)
        {
        User::Leave(KErrArgument);
        }
    CleanupStack::PushL(dcf);
    if (dcf->iVersion == EOma1Dcf)
        {
        GetHeaderL(*static_cast<COma1Dcf*>(dcf)->iHeaders, aHeaderName,
            aHeaderValue);
        }
    else
        {
        if (aHeaderName.Compare(KRiUrl) == 0 && dcf->iRightsIssuerURL != NULL)
            {
            aHeaderValue = dcf->iRightsIssuerURL->AllocL();
            }
        }
    CleanupStack::PopAndDestroy(); // dcf
    }

// -----------------------------------------------------------------------------
// DynamicDataTypesCount: Returns the number of supported dynamic datatypes
//
// Parameters:
//      aCount: out parameter for the number of dynamically registered data
//          types
//
// Returns:
//      DRMCommon::EOk: Count returned successfully
// -----------------------------------------------------------------------------
LOCAL_C TInt DynamicDataTypesCount(
    TInt& aCount)
    {
    TInt err = 0;
    TDataType type;
    RFs fs;
    RFileReadStream reader;

    aCount = 0;
    err = fs.Connect();
    if (!err)
        {

#ifndef RD_MULTIPLE_DRIVE

    err = reader.Open(fs, KDataTypesFile, EFileRead);

#else //RD_MULTIPLE_DRIVE

    TInt driveNumber( -1 );
    TChar driveLetter;
    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
    fs.DriveToChar( driveNumber, driveLetter );

    TFileName dataTypesFile;
    dataTypesFile.Format( KDataTypesFile, (TUint)driveLetter );

    err = reader.Open(fs, dataTypesFile, EFileRead);

#endif

        if (err == KErrNotFound)
            {
            err = DRMCommon::EOk;
            }
        else
            {
            while (err == KErrNone)
                {
                TRAP(err, (reader >> type));
                if (err == KErrNone) aCount++;
                }

            if (err == KErrEof)
                {
                err = DRMCommon::EOk;
                }

            reader.Release();
            reader.Close();
            }
        }

    fs.Close();

    return err;
    }

// -----------------------------------------------------------------------------
// SupportedDynamicDataType: Returns a registered dynamic datatype
//
// Parameters:
//      aIndex: index of the dynamic data type
//      aDataType: out parameter for the data type
//
// Returns:
//      DRMCommon::EOk: Data type returned successfully
//      KErrEof: Data type not found
// -----------------------------------------------------------------------------
LOCAL_C TInt SupportedDynamicDataType(
    const TInt aIndex,
    TDataType& aDataType)
    {
    TInt err = KErrNone;
    TInt i;
    RFs fs;
    TDataType type;
    RFileReadStream reader;

    err = fs.Connect();
    if (!err)
        {

#ifndef RD_MULTIPLE_DRIVE

        err = reader.Open(fs, KDataTypesFile, EFileRead);

#else //RD_MULTIPLE_DRIVE

        TInt driveNumber( -1 );
        TChar driveLetter;
        DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
        fs.DriveToChar( driveNumber, driveLetter );

        TFileName dataTypesFile;
        dataTypesFile.Format( KDataTypesFile, (TUint)driveLetter );

        err = reader.Open(fs, dataTypesFile, EFileRead);

#endif

        if (!err)
            {
            i = -1;
            while (err == 0 && i != aIndex)
                {
                TRAP(err, (reader >> type));
                i++;
                }

            if (!err)
                {
                aDataType = type;
                }

            reader.Release();
            reader.Close();
            }
        }

    fs.Close();

    return err;
    }

// -----------------------------------------------------------------------------
// SupportedStaticDataType: Returns a static DRM datatype
//
// Parameters:
//      aIndex: index of the dynamic data type
//      aDataType: out parameter for the data type
//
// Returns:
//      DRMCommon::EOk: Data type returned successfully
//      KErrEof: Data type not found
// -----------------------------------------------------------------------------
LOCAL_C TInt SupportedStaticDataType(
    const TInt aIndex,
    TDataType& aDataType)
    {
    TInt err = 0;
    TInt index = 0;
    TInt length = 0;
    TInt i = 0;
    RFs fs;
    RResourceFile resourceFile;
    HBufC8* res = NULL;
    TResourceReader theReader;

    err = fs.Connect();
    if (err)
        {
        fs.Close();
        return err;
        }

#ifndef RD_MULTIPLE_DRIVE

    TRAP(err, resourceFile.OpenL(fs, KResourceFile));

#else //RD_MULTIPLE_DRIVE

    TInt driveNumber( -1 );
    TChar driveLetter;
    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
    fs.DriveToChar( driveNumber, driveLetter );

    TFileName resFile;
    resFile.Format( KResourceFile, (TUint)driveLetter );

    TRAP(err, resourceFile.OpenL(fs, resFile));

#endif
    if (err)
        {
        fs.Close();
        return err;
        }

    TRAP(err, (res = resourceFile.AllocReadL(DATATYPE)));
    if (err)
        {
        resourceFile.Close();
        fs.Close();
        return err;
        }

    theReader.SetBuffer(res);
    index = aIndex + 1;
    TPtrC temp16(theReader.ReadTPtrC(index, res));
    length = temp16.Length();
    HBufC8* temp = NULL;
    temp = HBufC8::NewMax(length);
    if (temp)
        {
        TPtr8 ptr(temp->Des());
        ptr.SetLength(length);
        for (i = 0; i < length; i++)
            {
            ptr[i] = (unsigned char) temp16[i];
            }
        aDataType = TDataType(ptr);
        }
    else
        {
        err = KErrNoMemory;
        }

    if (temp)
        {
        delete temp;
        }

    temp = NULL;
    resourceFile.Close();
    if (res)
        {
        delete res;
        }

    res = NULL;
    fs.Close();
    return err;
    }

// -----------------------------------------------------------------------------
// UnRegisterDynamicDataTypeL: Unregister one of the dynamically addable data
//      types
//
// Parameters:
//      aIndex: index of the data type in the list of dynamic types
//
// Returns:
//      DRMCommon::EOK: Data type removed successfully
// -----------------------------------------------------------------------------
LOCAL_C TInt UnRegisterDynamicDataTypeL(
    const TInt aIndex)
    {
    TInt r;
    TInt i;
    TDataType type;
    RFileWriteStream writer;
    RFileReadStream reader;
    RFs fs;

    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);

    // Open the data types file

#ifndef RD_MULTIPLE_DRIVE

    User::LeaveIfError(reader.Open(fs, KDataTypesFile, EFileRead));

#else //RD_MULTIPLE_DRIVE

    TInt driveNumber( -1 );
    TChar driveLetter;
    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
    fs.DriveToChar( driveNumber, driveLetter );

    TFileName dataTypesFile;
    dataTypesFile.Format( KDataTypesFile, (TUint)driveLetter );

    User::LeaveIfError(reader.Open(fs, dataTypesFile, EFileRead));

#endif

    CleanupReleasePushL(reader);

    // Create and open a replacement file

#ifndef RD_MULTIPLE_DRIVE

    User::LeaveIfError(writer.Replace(fs, KTempFile, EFileWrite));

#else //RD_MULTIPLE_DRIVE

    TFileName tempFile;
    tempFile.Format( KTempFile, (TUint)driveLetter );

    User::LeaveIfError(writer.Replace(fs, tempFile, EFileWrite));

#endif

    CleanupReleasePushL(writer);

    // Write all dynamic types into the replacement file, excluding the
    // data type to be removed

    r = KErrNone;
    for (i = 0; r == KErrNone; i++)
        {
        TRAP(r, reader >> type);
        if (r == KErrNone && i != aIndex)
            {
            writer << type;
            writer.CommitL();
            }
        }
    CleanupStack::PopAndDestroy();
    CleanupStack::PopAndDestroy();

    // Replace the data type file with the replacement file

#ifndef RD_MULTIPLE_DRIVE

    fs.Replace(KTempFile, KDataTypesFile);

#else //RD_MULTIPLE_DRIVE

    fs.Replace(tempFile, dataTypesFile);

#endif


    CleanupStack::PopAndDestroy();

    return DRMCommon::EOk;
    }

// -----------------------------------------------------------------------------
// RegisterDynamicDataTypeL: Register a new dynamically addable data type
//
// Parameters:
//      aDataType: new type to be added
//
// Returns:
//      DRMCommon::EOK: Data type removed successfully
// -----------------------------------------------------------------------------
LOCAL_C TInt RegisterDynamicDataTypeL(const TDataType& aDataType)
    {
    TInt err = KErrNone;
    TDataType type;
    RFileWriteStream writer;
    RFileReadStream reader;
    RFs fs;

    User::LeaveIfError(fs.Connect());
    CleanupClosePushL(fs);

    // Create and open a replacement file

#ifndef RD_MULTIPLE_DRIVE

    User::LeaveIfError(writer.Replace(fs, KTempFile, EFileWrite));

#else //RD_MULTIPLE_DRIVE

    TInt driveNumber( -1 );
    TChar driveLetter;
    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
    fs.DriveToChar( driveNumber, driveLetter );

    TFileName tempFile;
    tempFile.Format( KTempFile, (TUint)driveLetter );

    User::LeaveIfError(writer.Replace(fs, tempFile, EFileWrite));

#endif

    CleanupReleasePushL(writer);

    // Write the new data type into the replacement file

    writer << aDataType;
    writer.CommitL();

    // Write all other dynamic types into the replacement file

#ifndef RD_MULTIPLE_DRIVE

    err = reader.Open(fs, KDataTypesFile, EFileRead);

#else //RD_MULTIPLE_DRIVE

    TFileName dataTypesFile;
    dataTypesFile.Format( KDataTypesFile, (TUint)driveLetter );

    err = reader.Open(fs, dataTypesFile, EFileRead);

#endif

    if (err == KErrNone)
        {
        CleanupReleasePushL(reader);
        while (err == KErrNone)
            {
            TRAP(err, (reader >> type, writer << type, writer.CommitL()));
            }
        CleanupStack::PopAndDestroy();
        }

    CleanupStack::PopAndDestroy();

    // Replace the data type file with the replacement file

#ifndef RD_MULTIPLE_DRIVE

    fs.Replace(KTempFile, KDataTypesFile);

#else //RD_MULTIPLE_DRIVE

    fs.Replace(tempFile, dataTypesFile);

#endif

    CleanupStack::PopAndDestroy();

    return DRMCommon::EOk;
    }

TInt CalculatePaddingL(COma1Dcf* dcf)
    {
    RDRMRightsClient rdb;
    TBuf8<KDCFKeySize * 2> blocks;
    TInt pos;
    TBool blocksValid = ETrue;

    if (!dcf->iPlainTextLengthValid)
        {
        User::LeaveIfError(rdb.Connect());
        CleanupClosePushL(rdb);
        if (dcf->iFile.SubSessionHandle() != KNullHandle)
            {
            pos = dcf->iOffset + dcf->iDataLength - 2 * KDCFKeySize;
            dcf->iFile.Seek(ESeekStart, pos);
            dcf->iFile.Read(blocks);
            }
        else if (dcf->iData->Length() >= dcf->iOffset + dcf->iDataLength)
            {
            blocks.Copy(&(dcf->iData->Des())[dcf->iOffset +
                dcf->iDataLength - 2 * KDCFKeySize],
                KDCFKeySize * 2);
            }
        else
            {
            blocksValid = EFalse;
            }

        if (blocksValid && rdb.InitializeKey(*dcf->iContentID) == KErrNone)
            {
            dcf->iPadding = rdb.CalculatePadding(blocks);
            if (dcf->iPadding >= 0)
                {
                dcf->iPlainTextLength -= dcf->iPadding;
                dcf->iPlainTextLengthValid = ETrue;
                }
            }
        CleanupStack::PopAndDestroy(); // rdb
        }

    return dcf->iPadding;
    }

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// DRMCommon::DRMCommon
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
EXPORT_C DRMCommon::DRMCommon(void)
    {
    }

// -----------------------------------------------------------------------------
// DRMCommon::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
EXPORT_C void DRMCommon::ConstructL()
    {
    FeatureManager::InitializeLibL();
    } 

// -----------------------------------------------------------------------------
// DRMCommon::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
EXPORT_C DRMCommon* DRMCommon::NewL()
    {
    DRMCommon* self = new(ELeave) DRMCommon();
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(); // self
    return self;
    }


// Destructor
EXPORT_C DRMCommon::~DRMCommon()
    {
    FeatureManager::UnInitializeLib();
    }

// -----------------------------------------------------------------------------
// DRMCommon::CheckContentRights
// Checks if the give rights for a specific content URI are available.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::CheckContentRights(
    const TDesC8& aContentID,
    TUint32 aRightsSpec)
    {
    TInt r = ENoRights;
    RDRMRightsClient client;
    TUint32 reason = 0;

    if (client.Connect() == KErrNone)
        {
        r = client.CheckRights(aRightsSpec, aContentID, reason);
        client.Close();
        }
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::CheckFileRights
// Checks if the give rights for a specific content URI are available by
// opening a given file and reading the content URI from there.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::CheckFileRights(
    const TDesC& aFileName,
    TUint32 aRightsSpec)
    {
    TInt r = KErrNone;
    TInt retValue = KErrNone;
    TRAP(r, retValue = CheckFileRightsL(aFileName, aRightsSpec));
    if (r != KErrNone)
        {
        return r;
        }
    return retValue;
    }

// -----------------------------------------------------------------------------
// DRMCommon::CheckFileRights
// Checks if the give rights for a specific content URI are available by
// opening a given file and reading the content URI from there.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::CheckFileRights(
    RFile& aFileHandle,
    TUint32 aRightsSpec)
    {
    TInt r = KErrNone;
    TInt retValue = KErrNone;
    TRAP(r, retValue = CheckFileRightsL(aFileHandle, aRightsSpec));
    if (r != KErrNone)
        {
        return r;
        }
    return retValue;
    }

// -----------------------------------------------------------------------------
// DRMCommon::IsProtectedContent
// Check if a memory buffer contains DRM proteced content by looking for a
// predefined header string.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::IsProtectedContent(
    const TDesC8& aContent,
    TBool& aProtection)
    {
    if (COma1Dcf::IsValidDcf(aContent) || COma2Dcf::IsValidDcf(aContent))
        {
        aProtection = ETrue;
        }
    else
        {
        aProtection = EFalse;
        }
    return EOk;
    }

// -----------------------------------------------------------------------------
// DRMCommon::IsProtectedFile
// Check if a file contains DRM proteced content by looking for a
// predefined header string.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::IsProtectedFile(
    const TDesC& aFileName,
    TBool& aProtection)
    {
    TInt r = KErrNone;
    TRAP(r, IsProtectedFileL(aFileName, aProtection));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::IsProtectedFile
// Check if a file contains DRM proteced content by looking for a
// predefined header string.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::IsProtectedFile(
    RFile& aFileHandle,
    TBool& aProtection)
    {
    TInt r = KErrNone;
    TRAP(r, IsProtectedFileL(aFileHandle, aProtection));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetContentInfo
// Returns DRM information about a memory buffer.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetContentInfo(
    const TDesC8& aContent,
    TContentProtection& aProtection,
    HBufC8*& aMIMEType,
    HBufC8*& aContentURI,
    TUint& aDataLength)
    {
    TInt r = KErrNone;
    TRAP(r, GetContentInfoL(aContent, aProtection, aMIMEType, aContentURI,
        aDataLength));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetFileInfo
// Returns DRM information about a file.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetFileInfo(
    const TDesC& aFileName,
    TContentProtection& aProtection,
    HBufC8*& aMIMEType,
    HBufC8*& aContentURI,
    TUint& aDataLength)
    {
    TInt r = KErrNone;
    TRAP(r, GetFileInfoL(aFileName, aProtection, aMIMEType, aContentURI,
        aDataLength));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetFileInfo
// Returns DRM information about a file.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetFileInfo(
    RFile& aFileHandle,
    TContentProtection& aProtection,
    HBufC8*& aMIMEType,
    HBufC8*& aContentURI,
    TUint& aDataLength)
    {
    TInt r = KErrNone;
    TRAP(r, GetFileInfoL(aFileHandle, aProtection, aMIMEType, aContentURI,
        aDataLength));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetContentHeader
// Returns an optional header from a memory buffer containing encrypted content.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetContentHeader(
    const TDesC8& aContent,
    const TDesC8& aHeaderName,
    HBufC8*& aHeaderValue)
    {
    TInt r = KErrNone;

    TRAP(r, GetContentHeaderL(aContent, aHeaderName, aHeaderValue));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetFileHeader
// Returns an optional header from a file containing encrypted content.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetFileHeader(
    const TFileName& aFileName,
    const TDesC8& aHeaderName,
    HBufC8*& aHeaderValue)
    {
    TInt r = KErrNone;

    TRAP(r, GetFileHeaderL(aFileName, aHeaderName, aHeaderValue));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetFileHeader
// Returns an optional header from a file containing encrypted content.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetFileHeader(
    RFile& aFileHandle,
    const TDesC8& aHeaderName,
    HBufC8*& aHeaderValue)
    {
    TInt r = KErrNone;

    TRAP(r, GetFileHeaderL(aFileHandle, aHeaderName, aHeaderValue));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMAuthenticated::SetContentHeader
// Sets the specified optional header field of a DCF buffer.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::SetContentHeader(
    HBufC8*& aContent,
    const TDesC8& aHeaderName,
    const TDesC8& aHeaderValue)
    {
    TInt r = KErrNone;

    TRAP(r, SetContentHeaderL(aContent, aHeaderName, aHeaderValue));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::SetContentHeader
// Sets the specified optional header field of a DCF buffer.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::SetFileHeader(
    const TDesC16& aFileName,
    const TDesC8& aHeaderName,
    const TDesC8& aHeaderValue)
    {
    TInt r = KErrNone;

    TRAP(r, SetFileHeaderL(aFileName, aHeaderName, aHeaderValue));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::SetContentHeader
// Sets the specified optional header field of a DCF buffer.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::SetFileHeader(
    RFile& aFileHandle,
    const TDesC8& aHeaderName,
    const TDesC8& aHeaderValue)
    {
    TInt r = KErrNone;

    TRAP(r, SetFileHeaderL(aFileHandle, aHeaderName, aHeaderValue));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetSingleRightsObject
// Looks up the rights object using the content URI and the local ID.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetSingleRightsObject(
    const TDesC8& aContentURI,
    TUint32 aLocalID,
    CDRMRights*& aRightsObject)
    {
    TInt r = KErrNone;
    TRAP(r, GetSingleRightsObjectL(aContentURI, aLocalID, aRightsObject));
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetDetailedContentRights
// Returns all rights objects for a content URI
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetDetailedContentRights(
    const TDesC8& aContentURI,
    RPointerArray<CDRMRights>*& aRightsList)
    {
    TInt r = KErrNone;

    TRAP(r, GetDetailedContentRightsL(aContentURI, aRightsList));
    if (r == KErrNone)
        {
        AddParents( const_cast<DRMCommon*>(this), *aRightsList );
        }
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetDetailedFileRights
// Returns all rights objects for a content URI from a given file
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetDetailedFileRights(
    const TDesC& aFileName,
    RPointerArray<CDRMRights>*& aRightsList)
    {
    TInt r = KErrNone;

    TRAP(r, GetDetailedFileRightsL(aFileName, aRightsList));
    if (r == KErrNone)
        {
        AddParents( const_cast<DRMCommon*>(this), *aRightsList );
        }
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetDetailedFileRights
// Returns all rights objects for a content URI from a given file
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetDetailedFileRights(
    RFile& aFileHandle,
    RPointerArray<CDRMRights>*& aRightsList)
    {
    TInt r = KErrNone;

    TRAP(r, GetDetailedFileRightsL(aFileHandle, aRightsList));
    if (r == KErrNone)
        {
        AddParents( const_cast<DRMCommon*>(this), *aRightsList );
        }
    return r;
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetActiveRights
// Returns a possible active rights object
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetActiveRights(
    const TDesC8& aContentURI,
    TUint32 aConstraints,
    CDRMRights*& aRightsObject)
    {
    TInt r = KErrNone;

    TRAP( r, GetActiveRightsL( aContentURI, aConstraints, aRightsObject ) );
    if(r != KErrNone)
        {
        return DRMCommon::ENoRights;
        }
    else
        {
        CDRMRights::TRestriction restriction;
        CDRMRights::TExpiration expiration;
        TUint32 constType(0);
        aRightsObject->GetRightsInfo(aConstraints, restriction, expiration, constType);
        return restriction;
        }
    }

// -----------------------------------------------------------------------------
// DRMCommon::GetContentURIList
// Returns a list of all content URIs that have rights in the rights database.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::GetContentURIList(
    RPointerArray<HBufC8>*& aURIList)
    {
    RDRMRightsClient client;
    TInt error = client.Connect();

    aURIList = NULL;
    if (!error)
        {
        aURIList = new RPointerArray<HBufC8>(10);
        if (aURIList)
            {
            error = client.ExportContentIDList(*aURIList);
            if (error)
                {
                aURIList->ResetAndDestroy();
                aURIList->Close();
                delete aURIList;
                aURIList = NULL;
                }
            }
        else
            {
            error = KErrNoMemory;
            }
        client.Close();
        }

    return error;
    }

// -----------------------------------------------------------------------------
// DRMCommon::Connect
// Does nothing
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::Connect()
    {
    RDRMRightsClient client; // Used to start RightsServer in bootup
    TInt ignore = 0;                 // error will be ignored, if it fails to start the
                             // rights server there is nothing we can really
                             // do about it, and normally this would work and
                             // return AOk, just used because of the SkinSrv
                             // Bootup thing
    ignore = client.Connect();        // Called by SkinSrv during bootup
        if( ignore )
            {
            // The error shouldn't matter since it will be retried
            }
    client.Close();
    return EOk;
    }

// -----------------------------------------------------------------------------
// DRMCommon::Disconnect
// Does nothing
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::Disconnect()
    {
    return EOk;
    }

// -----------------------------------------------------------------------------
// DRMCommon::SupportedDRMMethods
// Returns the implementation level of the DRM system.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::SupportedDRMMethods(
    TInt& aDRMMethod, TOMALevel& aOMALevel)
    {
    aDRMMethod =
        DRMCommon::EForwardLock |
        DRMCommon::ECombinedDelivery |
        DRMCommon::ESeparateDelivery |
        DRMCommon::ESuperDistribution;
#ifdef __DRM_OMA2
    if ( FeatureManager::FeatureSupported( KFeatureIdFfOmadrm2Support ) )
        {
        aOMALevel = EOMA_2_0;
        }
    else
        {
        aOMALevel = EOMA_1_0;
        }
    
#else
    aOMALevel = EOMA_1_0;
#endif
    return EOk;
    }

// -----------------------------------------------------------------------------
// DRMCommon::Version
// Returns the client side API version.
// -----------------------------------------------------------------------------
EXPORT_C TVersion DRMCommon::Version()
    {
    return TVersion(KClientVersionMajor,
        KClientVersionMinor,
        KClientVersionBuild);
    }

// -----------------------------------------------------------------------------
// DRMCommon::ServerVersion
// Returns the version of the DRM engine.
// -----------------------------------------------------------------------------
EXPORT_C TVersion DRMCommon::ServerVersion()
    {
    return TVersion(KServerVersionMajor,
        KServerVersionMinor,
        KServerVersionBuild);
    }

// -----------------------------------------------------------------------------
// DRMCommon::DataTypesCount
// Returns the number of MIME types the DRM system understands.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::DataTypesCount(
    TInt& aCount)
    {
    TInt err = 0;
    TInt staticTotal = 0;
    TInt dynamicTotal = 0;

    err = StaticDataTypesCount(staticTotal);
    if (err)
        {
        return err;
        }

    err = DynamicDataTypesCount(dynamicTotal);
    if (err)
        {
        return err;
        }

    aCount = staticTotal + dynamicTotal;
    return err;
    }

// -----------------------------------------------------------------------------
// DRMCommon::SupportedDataType
// Returns a specific DRM enabled MIME type.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::SupportedDataType(
    const TInt aIndex,
    TDataType& aDataType)
    {
    TInt err = KErrNone;
    TInt total = 0;
    TInt stat = 0;

    err = DataTypesCount(total);
    if (!err) err = StaticDataTypesCount(stat);
    if (!err)
        {
        if (0 <= aIndex && aIndex < stat)
            {
            err = SupportedStaticDataType(aIndex, aDataType);
            }
        else if (stat <= aIndex && aIndex < total)
            {
            err = SupportedDynamicDataType(aIndex - stat, aDataType);
            }
        else
            {
            err = KErrArgument;
            }
        }

    return err;
    }

// -----------------------------------------------------------------------------
// DRMCommon::StaticDataTypesCount
// Returns the number of supported built-in datatypes.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::StaticDataTypesCount(
    TInt& aCount)
    {
    TInt err = 0;
    RFs fs;
    RResourceFile resourceFile;
    TResourceReader theReader;

    err = fs.Connect();

    if (err)
        {
        fs.Close();
        return err;
        }

#ifndef RD_MULTIPLE_DRIVE

    TRAP(err, resourceFile.OpenL(fs, KResourceFile));

#else //RD_MULTIPLE_DRIVE

    TInt driveNumber( -1 );
    TChar driveLetter;
    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
    fs.DriveToChar( driveNumber, driveLetter );

    TFileName resFile;
    resFile.Format( KResourceFile, (TUint)driveLetter );

    TRAP(err, resourceFile.OpenL(fs, resFile));

#endif
    if (err)
        {
        fs.Close();
        return err;
        }

    HBufC8* res = NULL;
    TRAP(err, (res = resourceFile.AllocReadL(DATATYPE)));
    if (err)
        {
        resourceFile.Close();
        fs.Close();
        return err;
        }


    theReader.SetBuffer(res);
    aCount = theReader.ReadInt8();

    delete res;
    res = NULL;
    resourceFile.Close();
    fs.Close();
    return err;
    }

// -----------------------------------------------------------------------------
// DRMCommon::RegisterDataType
// Register a MIME type as being handled by the DRM system.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::RegisterDataType(
    const TDataType& aDataType)
    {
    TInt total = 0;
    TInt err = KErrNone;
    TInt i;
    TDataType type;

    if (aDataType.Des().Length() > 0)
        {
        err = DataTypesCount(total);
        for (i = 0 ; err == KErrNone && i < total ; i++)
            {
            err = SupportedDataType(i, type);
            if (type == aDataType)
                {
                err = KErrAlreadyExists;
                }
            }

        if (!err)
            {
            TRAP(err, RegisterDynamicDataTypeL(aDataType));
            }
        }
    else
        {
        err = KErrArgument;
        }
    return err;
    }

// -----------------------------------------------------------------------------
// DRMCommon::UnRegisterDataType
// Unregister a MIME type as being handled by the DRM system.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::UnRegisterDataType(
    const TInt aIndex)
    {
    TInt r;
    TInt count;
    TInt total;

    StaticDataTypesCount(count);
    r = DataTypesCount(total);
    if (r == KErrNone && aIndex >= count && aIndex < total)
        {
        TRAP(r, UnRegisterDynamicDataTypeL(aIndex - count));
        }
    else
        {
        r = KErrArgument;
        }
    return r;
    }


// -----------------------------------------------------------------------------
// DRMCommon::MergeParentAndChild
// Merge rights with their parent rights
// -----------------------------------------------------------------------------
EXPORT_C void DRMCommon::MergeParentAndChild(CDRMRights* /*aRights*/)
    {
    return;
    /*
    HBufC8* parent = aRights->GetPermission().iParentUID;
    if (parent != NULL)
        {
        RPointerArray<CDRMRights>* parents;
        if (GetDetailedContentRights(*parent, parents) == KErrNone &&
            parents->Count() > 0)
            {
            TBool merged = EFalse;
            for (TInt i = 0; !merged && i < parents->Count(); i++)
                {
                CDRMRights::TRestriction restriction;
                CDRMRights::TExpiration expiration;
                TUint32 constraints;
                aRights->GetRightsInfo(EUnknown, restriction, expiration,
                    constraints);
                if ( expiration == CDRMRights::EValidRights)
                    {
                    aRights->Merge(*(*parents)[i]);
                    merged = ETrue;
                    }
                }
            parents->ResetAndDestroy();
            delete parents;
            }
        }
    */
    }




// -----------------------------------------------------------------------------
// GetFileHandle
// Get a file name trying to open it in the order required, which is:
// 1)  EFileShareReadersOrWriters
// 2)  EFileShareAny
// 3)  EFileShareReadersOnly
// -----------------------------------------------------------------------------
LOCAL_C TInt GetFileHandleRead(
    RFs& aFileServer,
    RFile& aFile,
    const TDesC& aFileName )
    {
    TInt error = KErrNone;

    // 1) Try to open in EFileShareReadersOrWriters
    error = aFile.Open( aFileServer, aFileName, EFileRead | EFileShareReadersOrWriters );
    if( error != KErrNone )
        {
        // 2) Try to open in EFileShareAny
        error = aFile.Open( aFileServer, aFileName, EFileRead | EFileShareAny );
        if( error != KErrNone )
            {
            // 3) Try to open in EFileShareReadersOnly
            error = aFile.Open( aFileServer, aFileName, EFileRead | EFileShareReadersOnly );
            }
        }
    return error;
    };

// -----------------------------------------------------------------------------
// GetFileHandle
// Get a file name trying to open it in the order required, which is:
// 1)  EFileShareReadersOrWriters
// 2)  EFileShareAny
// 3)  EFileShareReadersOnly
// -----------------------------------------------------------------------------
LOCAL_C void AddParents( DRMCommon* aDrmCommon,
                         RPointerArray<CDRMRights>& aRights )
    {
    HBufC8* parent = NULL;
    RPointerArray<CDRMRights>* parents = NULL;
    TInt error = KErrNone;
    RPointerArray<HBufC8> usedParents;


    for( TInt i = 0; i < aRights.Count(); i++ )
        {
        parent = aRights[i]->GetPermission().iParentUID;

        for(TInt counter = 0; counter < usedParents.Count(); counter++ )
            {
            if( parent && !usedParents[counter]->Compare( *parent ) )
                {
                parent = NULL;
                }
            }

        if( parent != NULL )
            {
            TRAP( error, usedParents.AppendL( parent ) );

            if( aDrmCommon->GetDetailedContentRights(parent->Des(), parents) == KErrNone )
                {
                for( TInt j = parents->Count()-1; j >= 0;j-- )
                    {
                    TRAP( error, aRights.AppendL( (*parents)[j] ) );
                    (*parents)[j] = NULL;
                    parents->Remove(j);
                    }
                parents->ResetAndDestroy();
                delete parents;
                parents = NULL;
                }

            }
        }
    usedParents.Reset();
    usedParents.Close();
    }

// -----------------------------------------------------------------------------
// DRMCommon::MapErrorCode
// Remaps DRM core specific error codes to DRM API error codes.
// -----------------------------------------------------------------------------
EXPORT_C TInt DRMCommon::MapErrorCode(
    const TInt /* aCode */)
    {
    return EUnsupported;
    }

// ========================== OTHER EXPORTED FUNCTIONS =========================

//  End of File